mirror of
https://github.com/hay-kot/mealie.git
synced 2025-08-22 14:33:33 -07:00
feature/password-reset (#227)
* add reset default password * add warning * add version tag * bumb version * remove old footer Co-authored-by: hay-kot <hay-kot@pm.me>
This commit is contained in:
parent
09765979e3
commit
ab60306335
8 changed files with 95 additions and 70 deletions
|
@ -39,6 +39,8 @@ As of version v0.4.0 users have limited functionality, but they will offer more
|
|||
- Mealplan Settings
|
||||
- Webhooks
|
||||
|
||||
!!! warning
|
||||
As of v0.4.0 any authenticated user is able to perform any action on the backend server through the API. To limit a standard users scope, the pages on the frontend are limited. Proper support for permission structures on the backend API will come in a later version.
|
||||
|
||||
|
||||
## Startup
|
||||
|
@ -81,4 +83,4 @@ You can easily create and manage groups via the frontend in the admin panel unde
|
|||
User Groups can only be deleted if no users are apart of the group. If you want to delete a group, you must assign the users to another group before removing.
|
||||
|
||||
## Password Reset
|
||||
// TODO
|
||||
If a user forgets their password an administrator is able to reset their password through the user management page. In the user table, select edit. In the popup windows click the "Reset Password" to reset a users password to the default. This is either 'MyPassword' or set through an environment variable. See the [Installation Page](/getting-started/install/) for more details on environmental variables
|
||||
|
|
|
@ -34,8 +34,8 @@
|
|||
<AddRecipeFab v-if="loggedIn" />
|
||||
</v-slide-x-reverse-transition>
|
||||
<router-view></router-view>
|
||||
<FlashMessage :position="'right bottom'"></FlashMessage>
|
||||
</v-main>
|
||||
<FlashMessage :position="'right bottom'"></FlashMessage>
|
||||
</v-app>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -9,12 +9,12 @@ const authURLs = {
|
|||
refresh: `${authPrefix}/refresh`,
|
||||
};
|
||||
|
||||
|
||||
const usersURLs = {
|
||||
users: `${userPrefix}`,
|
||||
self: `${userPrefix}/self`,
|
||||
userID: id => `${userPrefix}/${id}`,
|
||||
password: id => `${userPrefix}/${id}/password`,
|
||||
resetPassword: id => `${userPrefix}/${id}/reset-password`,
|
||||
};
|
||||
|
||||
export default {
|
||||
|
@ -60,4 +60,8 @@ export default {
|
|||
let response = await apiReq.delete(usersURLs.userID(id));
|
||||
return response.data;
|
||||
},
|
||||
async resetPassword(id) {
|
||||
let response = await apiReq.put(usersURLs.resetPassword(id));
|
||||
return response.data;
|
||||
},
|
||||
};
|
||||
|
|
|
@ -72,6 +72,32 @@
|
|||
<v-list-item-title>{{ nav.title }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
|
||||
<v-list nav dense class="fixedBottom">
|
||||
<v-list-item href="">
|
||||
<v-list-item-icon class="mr-3 pt-1">
|
||||
<v-icon :color="newVersionAvailable ? 'red--text' : ''">
|
||||
mdi-information
|
||||
</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>
|
||||
{{ $t("settings.current") }}
|
||||
{{ version }}
|
||||
</v-list-item-title>
|
||||
<v-list-item-subtitle>
|
||||
<a
|
||||
href="https://github.com/hay-kot/mealie/releases/latest"
|
||||
target="_blank"
|
||||
:class="newVersionAvailable ? 'red--text' : 'green--text'"
|
||||
>
|
||||
{{ $t("settings.latest") }}
|
||||
{{ latestVersion }}
|
||||
</a>
|
||||
</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-navigation-drawer>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -80,10 +106,14 @@
|
|||
import { validators } from "@/mixins/validators";
|
||||
import { initials } from "@/mixins/initials";
|
||||
import { user } from "@/mixins/user";
|
||||
import api from "@/api";
|
||||
import axios from "axios";
|
||||
export default {
|
||||
mixins: [validators, initials, user],
|
||||
data() {
|
||||
return {
|
||||
latestVersion: null,
|
||||
version: null,
|
||||
hideImage: false,
|
||||
showSidebar: false,
|
||||
mobile: false,
|
||||
|
@ -92,39 +122,39 @@ export default {
|
|||
{
|
||||
icon: "mdi-cog",
|
||||
to: "/admin/settings",
|
||||
title: this.$t('settings.site-settings'),
|
||||
title: this.$t("settings.site-settings"),
|
||||
},
|
||||
{
|
||||
icon: "mdi-account-group",
|
||||
to: "/admin/manage-users",
|
||||
title: this.$t('settings.manage-users'),
|
||||
title: this.$t("settings.manage-users"),
|
||||
},
|
||||
{
|
||||
icon: "mdi-backup-restore",
|
||||
to: "/admin/backups",
|
||||
title: this.$t('settings.backup-and-exports'),
|
||||
title: this.$t("settings.backup-and-exports"),
|
||||
},
|
||||
{
|
||||
icon: "mdi-database-import",
|
||||
to: "/admin/migrations",
|
||||
title: this.$t('settings.migrations'),
|
||||
title: this.$t("settings.migrations"),
|
||||
},
|
||||
],
|
||||
baseLinks: [
|
||||
{
|
||||
icon: "mdi-account",
|
||||
to: "/admin/profile",
|
||||
title: this.$t('settings.profile'),
|
||||
title: this.$t("settings.profile"),
|
||||
},
|
||||
{
|
||||
icon: "mdi-format-color-fill",
|
||||
to: "/admin/themes",
|
||||
title: this.$t('general.themes'),
|
||||
title: this.$t("general.themes"),
|
||||
},
|
||||
{
|
||||
icon: "mdi-food",
|
||||
to: "/admin/meal-planner",
|
||||
title: this.$t('meal-plan.meal-planner'),
|
||||
title: this.$t("meal-plan.meal-planner"),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
@ -132,12 +162,18 @@ export default {
|
|||
async mounted() {
|
||||
this.mobile = this.viewScale();
|
||||
this.showSidebar = !this.viewScale();
|
||||
this.getVersion();
|
||||
let versionData = await api.meta.get_version();
|
||||
this.version = versionData.version;
|
||||
},
|
||||
|
||||
computed: {
|
||||
userProfileImage() {
|
||||
return `api/users/${this.user.id}/image`;
|
||||
},
|
||||
newVersionAvailable() {
|
||||
return this.latestVersion == this.version ? false : true;
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
@ -151,9 +187,26 @@ export default {
|
|||
return false;
|
||||
}
|
||||
},
|
||||
async getVersion() {
|
||||
let response = await axios.get(
|
||||
"https://api.github.com/repos/hay-kot/mealie/releases/latest",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
Authorization: null,
|
||||
},
|
||||
}
|
||||
);
|
||||
this.latestVersion = response.data.tag_name;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.fixedBottom {
|
||||
position: fixed !important;
|
||||
bottom: 0 !important;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
|
@ -93,6 +93,9 @@
|
|||
</v-card-text>
|
||||
|
||||
<v-card-actions>
|
||||
<v-btn color="info" text @click="resetPassword">
|
||||
Reset Password
|
||||
</v-btn>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn color="grey" text @click="close">
|
||||
{{ $t("general.cancel") }}
|
||||
|
@ -269,6 +272,10 @@ export default {
|
|||
}
|
||||
await this.initialize();
|
||||
},
|
||||
resetPassword() {
|
||||
console.log(this.activeId);
|
||||
api.users.resetPassword(this.editedItem.id );
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,75 +1,21 @@
|
|||
<template>
|
||||
<div>
|
||||
<v-container height="100%">
|
||||
<AdminSidebar />
|
||||
<v-container>
|
||||
<v-slide-x-transition hide-on-leave>
|
||||
<router-view></router-view>
|
||||
</v-slide-x-transition>
|
||||
<AdminSidebar />
|
||||
</v-container>
|
||||
<!-- <v-footer absolute>
|
||||
<div class="flex text-center" cols="12">
|
||||
{{ $t("settings.current") }}
|
||||
{{ version }} |
|
||||
{{ $t("settings.latest") }}
|
||||
{{ latestVersion }}
|
||||
·
|
||||
<a href="https://hay-kot.github.io/mealie/" target="_blank">
|
||||
{{ $t("settings.explore-the-docs") }}
|
||||
</a>
|
||||
·
|
||||
<a
|
||||
href="https://hay-kot.github.io/mealie/contributors/non-coders/"
|
||||
target="_blank"
|
||||
>
|
||||
{{ $t("settings.contribute") }}
|
||||
</a>
|
||||
</div>
|
||||
</v-footer> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AdminSidebar from "@/components/Admin/AdminSidebar";
|
||||
import axios from "axios";
|
||||
import api from "@/api";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
AdminSidebar,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
latestVersion: null,
|
||||
version: null,
|
||||
};
|
||||
},
|
||||
async mounted() {
|
||||
this.getVersion();
|
||||
let versionData = await api.meta.get_version();
|
||||
this.version = versionData.version;
|
||||
},
|
||||
computed: {
|
||||
newVersion() {
|
||||
if ((this.latestVersion != null) & (this.latestVersion != this.version)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async getVersion() {
|
||||
let response = await axios.get(
|
||||
"https://api.github.com/repos/hay-kot/mealie/releases/latest",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
Authorization: null,
|
||||
},
|
||||
}
|
||||
);
|
||||
this.latestVersion = response.data.tag_name;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@ from pathlib import Path
|
|||
|
||||
import dotenv
|
||||
|
||||
APP_VERSION = "v0.3.0"
|
||||
DB_VERSION = "v0.3.0"
|
||||
APP_VERSION = "v0.4.0"
|
||||
DB_VERSION = "v0.4.0"
|
||||
|
||||
CWD = Path(__file__).parent
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ from datetime import timedelta
|
|||
from fastapi import APIRouter, Depends, File, UploadFile
|
||||
from fastapi.responses import FileResponse
|
||||
from mealie.core import security
|
||||
from mealie.core.config import USER_DIR
|
||||
from mealie.core.config import DEFAULT_PASSWORD, USER_DIR
|
||||
from mealie.core.security import get_password_hash, verify_password
|
||||
from mealie.db.database import db
|
||||
from mealie.db.db_setup import generate_session
|
||||
|
@ -58,6 +58,19 @@ async def get_user_by_id(
|
|||
return db.users.get(session, id)
|
||||
|
||||
|
||||
@router.put("/{id}/reset-password")
|
||||
async def reset_user_password(
|
||||
id: int,
|
||||
current_user: UserInDB = Depends(get_current_user),
|
||||
session: Session = Depends(generate_session),
|
||||
):
|
||||
|
||||
new_password = get_password_hash(DEFAULT_PASSWORD)
|
||||
db.users.update_password(session, id, new_password)
|
||||
|
||||
return SnackResponse.success("Users Password Reset")
|
||||
|
||||
|
||||
@router.put("/{id}")
|
||||
async def update_user(
|
||||
id: int,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue