From e0ba6a587671c4e7d484152f35076c0fb1eb2996 Mon Sep 17 00:00:00 2001
From: Syldexia <syldexia@ofthewi.red>
Date: Mon, 21 May 2018 23:01:09 +0100
Subject: [PATCH] Added change password to user settings

---
 src/components/user_settings/user_settings.js | 22 ++++++++++++++++++-
 .../user_settings/user_settings.vue           | 21 +++++++++++++++++-
 src/i18n/messages.js                          | 10 +++++++--
 src/services/api/api.service.js               | 19 +++++++++++++++-
 .../backend_interactor_service.js             |  4 +++-
 5 files changed, 70 insertions(+), 6 deletions(-)

diff --git a/src/components/user_settings/user_settings.js b/src/components/user_settings/user_settings.js
index 1e7b9b12..b6026e18 100644
--- a/src/components/user_settings/user_settings.js
+++ b/src/components/user_settings/user_settings.js
@@ -13,7 +13,10 @@ const UserSettings = {
       previews: [ null, null, null ],
       deletingAccount: false,
       deleteAccountConfirmPasswordInput: '',
-      deleteAccountError: false
+      deleteAccountError: false,
+      changePasswordInputs: [ '', '', '' ],
+      changedPassword: false,
+      changePasswordError: false
     }
   },
   components: {
@@ -195,6 +198,23 @@ const UserSettings = {
             this.deleteAccountError = res.error
           }
         })
+    },
+    changePassword () {
+      const params = {
+        password: this.changePasswordInputs[0],
+        newPassword: this.changePasswordInputs[1],
+        newPasswordConfirmation: this.changePasswordInputs[2]
+      }
+      this.$store.state.api.backendInteractor.changePassword(params)
+        .then((res) => {
+          if (res.status === 'success') {
+            this.changedPassword = true
+            this.changePasswordError = false
+          } else {
+            this.changedPassword = false
+            this.changePasswordError = res.error
+          }
+        })
     }
   }
 }
diff --git a/src/components/user_settings/user_settings.vue b/src/components/user_settings/user_settings.vue
index ea9763f3..fbf3f651 100644
--- a/src/components/user_settings/user_settings.vue
+++ b/src/components/user_settings/user_settings.vue
@@ -49,6 +49,25 @@
         <i class=" icon-spin4 animate-spin uploading" v-if="uploading[2]"></i>
         <button class="btn btn-default" v-else-if="previews[2]" @click="submitBg">{{$t('general.submit')}}</button>
       </div>
+      <div class="setting-item">
+        <h3>{{$t('settings.change_password')}}</h3>
+        <div>
+          <p>{{$t('settings.current_password')}}</p>
+          <input type="password" v-model="changePasswordInputs[0]">
+        </div>
+        <div>
+          <p>{{$t('settings.new_password')}}</p>
+          <input type="password" v-model="changePasswordInputs[1]">
+        </div>
+        <div>
+          <p>{{$t('settings.confirm_new_password')}}</p>
+          <input type="password" v-model="changePasswordInputs[2]">
+        </div>
+        <button class="btn btn-default" @click="changePassword">{{$t('general.submit')}}</button>
+        <p v-if="changedPassword">{{$t('settings.changed_password')}}</p>
+        <p v-else-if="changePasswordError !== false">{{$t('settings.change_password_error')}}</p>
+        <p v-if="changePasswordError">{{changePasswordError}}</p>
+      </div>
       <div class="setting-item" v-if="pleromaBackend">
         <h3>{{$t('settings.follow_import')}}</h3>
         <p>{{$t('settings.import_followers_from_a_csv_file')}}</p>
@@ -62,7 +81,7 @@
           <p>{{$t('settings.follows_imported')}}</p>
         </div>
         <div v-else-if="followImportError">
-          <i class="icon-cross" @click="dismissImported"</i>
+          <i class="icon-cross" @click="dismissImported"></i>
           <p>{{$t('settings.follow_import_error')}}</p>
         </div>
       </div>
diff --git a/src/i18n/messages.js b/src/i18n/messages.js
index 19b50272..54a99b5a 100644
--- a/src/i18n/messages.js
+++ b/src/i18n/messages.js
@@ -291,12 +291,18 @@ const en = {
     follows_imported: 'Follows imported! Processing them will take a while.',
     follow_import_error: 'Error importing followers',
     delete_account: 'Delete Account',
-    delete_account_description: 'Permanantly delete your account and all your messages.',
+    delete_account_description: 'Permanently delete your account and all your messages.',
     delete_account_instructions: 'Type your password in the input below to confirm account deletion.',
     delete_account_error: 'There was an issue deleting your account. If this persists please contact your instance administrator.',
     follow_export: 'Follow export',
     follow_export_processing: 'Processing, you\'ll soon be asked to download your file',
-    follow_export_button: 'Export your follows to a csv file'
+    follow_export_button: 'Export your follows to a csv file',
+    change_password: 'Change Password',
+    current_password: 'Current password',
+    new_password: 'New password',
+    confirm_new_password: 'Confirm new password',
+    changed_password: 'Password changed successfully!',
+    change_password_error: 'There was an issue changing your password.'
   },
   notifications: {
     notifications: 'Notifications',
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index fd401068..65761aee 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -31,6 +31,7 @@ const UNBLOCKING_URL = '/api/blocks/destroy.json'
 const USER_URL = '/api/users/show.json'
 const FOLLOW_IMPORT_URL = '/api/pleroma/follow_import'
 const DELETE_ACCOUNT_URL = '/api/pleroma/delete_account'
+const CHANGE_PASSWORD_URL = '/api/pleroma/change_password'
 
 import { each, map } from 'lodash'
 import 'whatwg-fetch'
@@ -387,6 +388,21 @@ const deleteAccount = ({credentials, password}) => {
     .then((response) => response.json())
 }
 
+const changePassword = ({credentials, password, newPassword, newPasswordConfirmation}) => {
+  const form = new FormData()
+
+  form.append('password', password)
+  form.append('new_password', newPassword)
+  form.append('new_password_confirmation', newPasswordConfirmation)
+
+  return fetch(CHANGE_PASSWORD_URL, {
+    body: form,
+    method: 'POST',
+    headers: authHeaders(credentials)
+  })
+    .then((response) => response.json())
+}
+
 const fetchMutes = ({credentials}) => {
   const url = '/api/qvitter/mutes.json'
 
@@ -423,7 +439,8 @@ const apiService = {
   updateBanner,
   externalProfile,
   followImport,
-  deleteAccount
+  deleteAccount,
+  changePassword
 }
 
 export default apiService
diff --git a/src/services/backend_interactor_service/backend_interactor_service.js b/src/services/backend_interactor_service/backend_interactor_service.js
index c5807bed..14173558 100644
--- a/src/services/backend_interactor_service/backend_interactor_service.js
+++ b/src/services/backend_interactor_service/backend_interactor_service.js
@@ -62,6 +62,7 @@ const backendInteractorService = (credentials) => {
   const followImport = ({params}) => apiService.followImport({params, credentials})
 
   const deleteAccount = ({password}) => apiService.deleteAccount({credentials, password})
+  const changePassword = ({password, newPassword, newPasswordConfirmation}) => apiService.changePassword({credentials, password, newPassword, newPasswordConfirmation})
 
   const backendInteractorServiceInstance = {
     fetchStatus,
@@ -85,7 +86,8 @@ const backendInteractorService = (credentials) => {
     updateProfile,
     externalProfile,
     followImport,
-    deleteAccount
+    deleteAccount,
+    changePassword
   }
 
   return backendInteractorServiceInstance