diff --git a/app/components/Sidebar.vue b/app/components/Sidebar.vue index 87d5049..5e822c1 100644 --- a/app/components/Sidebar.vue +++ b/app/components/Sidebar.vue @@ -83,6 +83,11 @@ const navigationItems = [ to: '/favoritos', icon: 'mdi:heart-outline' }, + { + label: 'Reviews', + to: '/reviews', + icon: 'mdi:star-outline' + }, { label: 'Catálogo', to: '/catalogo', diff --git a/app/pages/(protected)/reviews/index.vue b/app/pages/(protected)/reviews/index.vue new file mode 100644 index 0000000..346885c --- /dev/null +++ b/app/pages/(protected)/reviews/index.vue @@ -0,0 +1,651 @@ + + + diff --git a/server/api/profile/[id].get.ts b/server/api/profile/[id].get.ts new file mode 100644 index 0000000..ad96f53 --- /dev/null +++ b/server/api/profile/[id].get.ts @@ -0,0 +1,29 @@ +import { prisma } from '../../utils/prisma' +import { requireAuthContext } from '../../utils/require-auth' + +/** + * Retorna o nome de exibição de um usuário pelo ID (sub do JWT). + * Usado para resolver nomes de autores de reviews. + * Responde com { displayName: string | null } — null quando o ID + * pertence a outro sistema (usuário externo). + */ +export default defineEventHandler(async (event) => { + requireAuthContext(event) + + const id = getRouterParam(event, 'id') + + if (!id) { + throw createError({ statusCode: 400, statusMessage: 'ID obrigatório' }) + } + + const user = await prisma.user.findUnique({ + where: { id }, + select: { email: true } + }) + + if (!user) { + return { displayName: null } + } + + return { displayName: user.email.split('@')[0] } +}) diff --git a/server/types/auth.ts b/server/types/auth.ts index a08acda..94ccb26 100644 --- a/server/types/auth.ts +++ b/server/types/auth.ts @@ -14,4 +14,6 @@ export interface AccessTokenClaims { export interface AuthRouteRequirement { method: string path: string + /** Quando true, protege qualquer rota cujo caminho comece com `path` */ + prefix?: boolean } diff --git a/server/utils/auth-rules.ts b/server/utils/auth-rules.ts index cffffcf..cee5a7c 100644 --- a/server/utils/auth-rules.ts +++ b/server/utils/auth-rules.ts @@ -8,6 +8,11 @@ const PROTECTED_ROUTES: AuthRouteRequirement[] = [ { method: 'GET', path: '/dashboard' + }, + { + method: 'GET', + path: '/api/profile/', + prefix: true } ] @@ -37,8 +42,10 @@ export function getRouteRequirement(method: string, path: string): AuthRouteRequ const normalizedPath = normalizePath(path) return ( - PROTECTED_ROUTES.find( - (route) => route.method === normalizedMethod && route.path === normalizedPath - ) ?? null + PROTECTED_ROUTES.find((route) => { + if (route.method !== normalizedMethod) return false + if (route.prefix) return normalizedPath.startsWith(route.path) + return route.path === normalizedPath + }) ?? null ) }