fix: Security Issues (#3530)

Co-authored-by: boc-the-git <3479092+boc-the-git@users.noreply.github.com>
This commit is contained in:
Michael Genson 2024-04-30 15:53:55 -05:00 committed by GitHub
parent 2ff37c86d6
commit ec458a0a08
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 11 additions and 36 deletions

View File

@ -1,10 +1,9 @@
import { BaseCRUDAPI } from "../base/base-clients"; import { BaseCRUDAPI } from "../base/base-clients";
import { QueryValue, route } from "~/lib/api/base/route"; import { QueryValue, route } from "~/lib/api/base/route";
import { PaginationData, RequestResponse } from "~/lib/api/types/non-generated"; import { PaginationData } from "~/lib/api/types/non-generated";
import { import {
ChangePassword, ChangePassword,
DeleteTokenResponse, DeleteTokenResponse,
GroupInDB,
LongLiveTokenIn, LongLiveTokenIn,
LongLiveTokenOut, LongLiveTokenOut,
ResetPassword, ResetPassword,
@ -30,7 +29,6 @@ const routes = {
groupUsers: `${prefix}/users/group-users`, groupUsers: `${prefix}/users/group-users`,
usersSelf: `${prefix}/users/self`, usersSelf: `${prefix}/users/self`,
ratingsSelf: `${prefix}/users/self/ratings`, ratingsSelf: `${prefix}/users/self/ratings`,
groupsSelf: `${prefix}/users/self/group`,
passwordReset: `${prefix}/users/reset-password`, passwordReset: `${prefix}/users/reset-password`,
passwordChange: `${prefix}/users/password`, passwordChange: `${prefix}/users/password`,
users: `${prefix}/users`, users: `${prefix}/users`,
@ -57,10 +55,6 @@ export class UserApi extends BaseCRUDAPI<UserIn, UserOut, UserBase> {
return await this.requests.get<PaginationData<UserSummary>>(route(routes.groupUsers, { page, perPage, ...params })); return await this.requests.get<PaginationData<UserSummary>>(route(routes.groupUsers, { page, perPage, ...params }));
} }
async getSelfGroup(): Promise<RequestResponse<GroupInDB>> {
return await this.requests.get(routes.groupsSelf, {});
}
async addFavorite(id: string, slug: string) { async addFavorite(id: string, slug: string) {
return await this.requests.post(routes.usersIdFavoritesSlug(id, slug), {}); return await this.requests.post(routes.usersIdFavoritesSlug(id, slug), {});
} }

View File

@ -156,6 +156,7 @@ export default {
propertyName: "access_token", propertyName: "access_token",
}, },
refresh: { url: "api/auth/refresh", method: "post" }, refresh: { url: "api/auth/refresh", method: "post" },
logout: { url: "api/auth/logout", method: "post" },
user: { url: "api/users/self", method: "get" }, user: { url: "api/users/self", method: "get" },
}, },
}, },

View File

@ -190,7 +190,6 @@
<script lang="ts"> <script lang="ts">
import { computed, defineComponent, useContext, ref, toRefs, reactive, useAsync, useRoute } from "@nuxtjs/composition-api"; import { computed, defineComponent, useContext, ref, toRefs, reactive, useAsync, useRoute } from "@nuxtjs/composition-api";
import { invoke, until } from "@vueuse/core";
import UserProfileLinkCard from "@/components/Domain/User/UserProfileLinkCard.vue"; import UserProfileLinkCard from "@/components/Domain/User/UserProfileLinkCard.vue";
import { useUserApi } from "~/composables/api"; import { useUserApi } from "~/composables/api";
import { validators } from "~/composables/use-validators"; import { validators } from "~/composables/use-validators";
@ -198,7 +197,7 @@ import { alert } from "~/composables/use-toast";
import UserAvatar from "@/components/Domain/User/UserAvatar.vue"; import UserAvatar from "@/components/Domain/User/UserAvatar.vue";
import { useAsyncKey } from "~/composables/use-utils"; import { useAsyncKey } from "~/composables/use-utils";
import StatsCards from "~/components/global/StatsCards.vue"; import StatsCards from "~/components/global/StatsCards.vue";
import { GroupInDB, UserOut } from "~/lib/api/types/user"; import { UserOut } from "~/lib/api/types/user";
export default defineComponent({ export default defineComponent({
name: "UserProfile", name: "UserProfile",
@ -216,7 +215,6 @@ export default defineComponent({
// @ts-ignore $auth.user is typed as unknown, but it's a user // @ts-ignore $auth.user is typed as unknown, but it's a user
const user = computed<UserOut | null>(() => $auth.user); const user = computed<UserOut | null>(() => $auth.user);
const group = ref<GroupInDB | null>(null);
const showPublicLink = ref(false); const showPublicLink = ref(false);
const publicLink = ref(""); const publicLink = ref("");
@ -225,16 +223,6 @@ export default defineComponent({
const token = ref(""); const token = ref("");
const api = useUserApi(); const api = useUserApi();
invoke(async () => {
await until(user.value).not.toBeNull();
if (!user.value) {
return;
}
const { data } = await api.users.getSelfGroup();
group.value = data;
});
async function getSignupLink() { async function getSignupLink() {
const { data } = await api.groups.createInvitation({ uses: 1 }); const { data } = await api.groups.createInvitation({ uses: 1 });
if (data) { if (data) {
@ -333,7 +321,6 @@ export default defineComponent({
getStatsTitle, getStatsTitle,
getStatsIcon, getStatsIcon,
getStatsTo, getStatsTo,
group,
stats, stats,
user, user,
constructLink, constructLink,

View File

@ -72,3 +72,9 @@ async def refresh_token(current_user: PrivateUser = Depends(get_current_user)):
"""Use a valid token to get another token""" """Use a valid token to get another token"""
access_token = security.create_access_token(data=dict(sub=str(current_user.id))) access_token = security.create_access_token(data=dict(sub=str(current_user.id)))
return MealieAuthToken.respond(access_token) return MealieAuthToken.respond(access_token)
@user_router.post("/logout")
async def logout(response: Response):
response.delete_cookie("mealie.access_token")
return {"message": "Logged out"}

View File

@ -11,14 +11,7 @@ from mealie.routes.users._helpers import assert_user_change_allowed
from mealie.schema.response import ErrorResponse, SuccessResponse from mealie.schema.response import ErrorResponse, SuccessResponse
from mealie.schema.response.pagination import PaginationQuery from mealie.schema.response.pagination import PaginationQuery
from mealie.schema.user import ChangePassword, UserBase, UserIn, UserOut from mealie.schema.user import ChangePassword, UserBase, UserIn, UserOut
from mealie.schema.user.user import ( from mealie.schema.user.user import UserPagination, UserRatings, UserRatingSummary, UserSummary, UserSummaryPagination
GroupInDB,
UserPagination,
UserRatings,
UserRatingSummary,
UserSummary,
UserSummaryPagination,
)
user_router = UserAPIRouter(prefix="/users", tags=["Users: CRUD"]) user_router = UserAPIRouter(prefix="/users", tags=["Users: CRUD"])
admin_router = AdminAPIRouter(prefix="/users", tags=["Users: Admin CRUD"]) admin_router = AdminAPIRouter(prefix="/users", tags=["Users: Admin CRUD"])
@ -100,10 +93,6 @@ class UserController(BaseUserController):
def get_logged_in_user_favorites(self): def get_logged_in_user_favorites(self):
return UserRatings(ratings=self.repos.user_ratings.get_by_user(self.user.id, favorites_only=True)) return UserRatings(ratings=self.repos.user_ratings.get_by_user(self.user.id, favorites_only=True))
@user_router.get("/self/group", response_model=GroupInDB)
def get_logged_in_user_group(self):
return self.group
@user_router.put("/password") @user_router.put("/password")
def update_password(self, password_change: ChangePassword): def update_password(self, password_change: ChangePassword):
"""Resets the User Password""" """Resets the User Password"""

View File

@ -206,7 +206,7 @@ class UpdateGroup(GroupBase):
class GroupInDB(UpdateGroup): class GroupInDB(UpdateGroup):
users: list[UserOut] | None = None users: list[UserSummary] | None = None
preferences: ReadGroupPreferences | None = None preferences: ReadGroupPreferences | None = None
webhooks: list[ReadWebhook] = [] webhooks: list[ReadWebhook] = []

View File

@ -183,8 +183,6 @@ users_self = "/api/users/self"
"""`/api/users/self`""" """`/api/users/self`"""
users_self_favorites = "/api/users/self/favorites" users_self_favorites = "/api/users/self/favorites"
"""`/api/users/self/favorites`""" """`/api/users/self/favorites`"""
users_self_group = "/api/users/self/group"
"""`/api/users/self/group`"""
users_self_ratings = "/api/users/self/ratings" users_self_ratings = "/api/users/self/ratings"
"""`/api/users/self/ratings`""" """`/api/users/self/ratings`"""
utils_download = "/api/utils/download" utils_download = "/api/utils/download"