Skip to content

Commit

Permalink
feat: password reset frontend done, backend started
Browse files Browse the repository at this point in the history
  • Loading branch information
PhantomMantis committed Apr 5, 2024
1 parent 7a982e2 commit d15e0a1
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,18 @@ class Logout(Resource):
def post(self):
"""Logout the currently logged in user"""
return AuthenticationModel.logout_user()

@api.route("/change_password")
@api.route("/change_password/", doc=False)
class ChangePassword(Resource):
"""API resource for changing the user's password"""

method_decorators = [jwt_required()]

@api.doc(description="Change the user's password")
@api.response(200, "Password changed")
@api.response(401, "Invalid password")
@api.response(500, "Internal server error")
def post(self):
"""Change the user's password"""
return AuthenticationModel.change_password(request.form)
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ def validate_password(self, _, value):
if not check_password_hash(self._user.password, value):
raise ValidationError("Invalid Username or Password")


# ANCHOR - Perform migration of old passwords
def _migrate_password(self):
# Migrate to scrypt from sha 256
Expand Down Expand Up @@ -237,6 +236,17 @@ def login_user(self):
info(f"Account {self._user.username} successfully logged in")
return resp

# ANCHOR - Perform migration of old passwords
def change_password(self):
# verify the old password id the same as the current password

# if it is, then update the password

# else, return an error message

pass


# ANCHOR - Logout User
@staticmethod
def logout_user():
Expand Down
41 changes: 40 additions & 1 deletion apps/wizarr-frontend/src/api/authentication.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { errorToast, infoToast } from "../ts/utils/toasts";
import { errorToast, infoToast, successToast } from "../ts/utils/toasts";
import { startAuthentication, startRegistration } from "@simplewebauthn/browser";

import type { APIUser } from "@/types/api/auth/User";
Expand All @@ -14,6 +14,7 @@ class Auth {
// Local toast functions
private errorToast = errorToast;
private infoToast = infoToast;
private successToast = successToast;

// Router and axios instance
private router = useRouter();
Expand Down Expand Up @@ -220,6 +221,44 @@ class Auth {
return this.handleAuthData(response.data.auth.user, response.data.auth.token, response.data.auth.refresh_token);
}

/**
* Change Password
* This method is change the password of the user
*
* @param old_password The old password of the user
* @param new_password The new password of the user
*
* @returns The response from the server
*/
async changePassword(old_password?: string, new_password?: string) {
const AuthStore = useAuthStore();
const userStore = useUserStore();

// verify if the user is authenticated
if (!this.isAuthenticated()) {
this.errorToast("User is not authenticated");
return;
}

// check if old assword is correct
const username = userStore.user?.display_name || userStore.user?.username;

// send request to server to change password
await this.axios
.post("/api/auth/change_password", {
old_password: old_password,
new_password: new_password,
username: username,
})
.then((response) => {
return response;
})
.catch(() => {
this.errorToast("Failed to change password, please try again");
return;
});
}

/**
* Logout of the application
* This method is used to logout the user
Expand Down
2 changes: 1 addition & 1 deletion apps/wizarr-frontend/src/modules/settings/pages/Main.vue
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ export default defineComponent({
description: this.__("Change your password"),
icon: "fas fa-lock",
url: "/admin/settings/password",
disabled: true,
disabled: false,
},
{
title: this.__("Sessions"),
Expand Down
60 changes: 60 additions & 0 deletions apps/wizarr-frontend/src/modules/settings/pages/Password.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<template>
<FormKit type="form" @submit="changePassword" :actions="false">
<div class="space-y-4">
<FormKit type="password" v-model="old_password" label="Old Password" name="old_password" placeholder="Old Password" required autocomplete="current-password" />
<!-- <FormKit type="password" v-model="new_password" label="New Password" name="new_password" placeholder="New Password" required autocomplete="new-password" validation="length:20|*required" /> -->
<FormKit type="password" v-model="new_password" label="New Password" name="new_password" placeholder="New Password" required autocomplete="new-password" />
<FormKit type="password" v-model="confirm_password" label="Confirm New Password" name="confirm_password" placeholder="Confirm New Password" required autocomplete="new-password" />

<div class="">
<FormKit type="submit" :classes="{ outer: 'w-auto', input: 'text-xs w-auto justify-center !font-bold' }">
{{ __("Confirm") }}
</FormKit>
</div>
</div>
</FormKit>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import DefaultNavBar from "@/components/NavBars/DefaultNavBar.vue";
import DefaultLoading from "@/components/Loading/DefaultLoading.vue";
import Auth from "@/api/authentication";
export default defineComponent({
name: "LoginView",
components: {
DefaultNavBar,
DefaultLoading,
},
data() {
return {
auth: new Auth(),
old_password: "",
new_password: "",
confirm_password: "",
};
},
methods: {
resetForm() {
this.old_password = "";
this.new_password = "";
this.confirm_password = "";
},
async changePassword({ old_password, new_password, confirm_password }: { old_password: string; new_password: string; confirm_password: string }) {
if (new_password !== confirm_password) {
this.$toast.error("Passwords do not match");
return;
}
await this.auth.changePassword(old_password, new_password).then((res) => {
if (res !== undefined) {
this.$toast.success("Password changed successfully");
}
});
this.resetForm();
},
},
});
</script>
9 changes: 9 additions & 0 deletions apps/wizarr-frontend/src/modules/settings/router/children.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@ const children: RouteRecordRaw[] = [
subheader: "Configure multi-factor authentication",
},
},
{
path: "password",
name: "admin-settings-password",
component: () => import("../pages/Password.vue"),
meta: {
header: "Manage Password",
subheader: "Change your account password",
},
},
{
path: "tasks",
name: "admin-settings-tasks",
Expand Down
2 changes: 1 addition & 1 deletion apps/wizarr-frontend/src/plugins/sentry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const isBugReporting = () => {

if (localStorage !== null) {
const server = JSON.parse(localStorage);
return server.settings.bug_reporting === "false";
return server.settings?.bug_reporting === "false";
}

return true;
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit d15e0a1

Please sign in to comment.