diff --git a/apps/web/lib/database.types.ts b/apps/web/lib/database.types.ts index 7500b2499..936d36fdf 100644 --- a/apps/web/lib/database.types.ts +++ b/apps/web/lib/database.types.ts @@ -667,7 +667,7 @@ export type Database = { can_action_account_member: { Args: { target_team_account_id: string - user_id: string + target_user_id: string } Returns: boolean } @@ -747,6 +747,10 @@ export type Database = { Args: Record Returns: Json } + get_upper_system_role: { + Args: Record + Returns: string + } has_more_elevated_role: { Args: { target_user_id: string @@ -770,6 +774,14 @@ export type Database = { } Returns: boolean } + has_same_role_hierarchy_level: { + Args: { + target_user_id: string + target_account_id: string + role_name: string + } + Returns: boolean + } is_account_owner: { Args: { account_id: string diff --git a/apps/web/middleware.ts b/apps/web/middleware.ts index 8d47312e9..cb6e4da12 100644 --- a/apps/web/middleware.ts +++ b/apps/web/middleware.ts @@ -1,7 +1,7 @@ import type { NextRequest } from 'next/server'; import { NextResponse, URLPattern } from 'next/server'; -import csrf from 'edge-csrf'; +import { CsrfError, createCsrfProtect } from '@edge-csrf/nextjs'; import { checkRequiresMultiFactorAuthentication } from '@kit/supabase/check-requires-mfa'; import { createMiddlewareClient } from '@kit/supabase/middleware-client'; @@ -46,7 +46,7 @@ async function withCsrfMiddleware( response = new NextResponse(), ) { // set up CSRF protection - const csrfMiddleware = csrf({ + const csrfProtect = createCsrfProtect({ cookie: { secure: appConfig.production, name: CSRF_SECRET_COOKIE, @@ -58,17 +58,20 @@ async function withCsrfMiddleware( ['GET', 'HEAD', 'OPTIONS'], }); - const csrfError = await csrfMiddleware(request, response); + try { + await csrfProtect(request, response); - // if there is a CSRF error, return a 403 response - if (csrfError) { - return NextResponse.json('Invalid CSRF token', { - status: 401, - }); + return response; + } catch (error) { + // if there is a CSRF error, return a 403 response + if (error instanceof CsrfError) { + return NextResponse.json('Invalid CSRF token', { + status: 401, + }); + } + + throw error; } - - // otherwise, return the response - return response; } function isServerAction(request: NextRequest) { diff --git a/apps/web/package.json b/apps/web/package.json index 2c63e158a..c76d0ef2e 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -57,7 +57,7 @@ "@tanstack/react-query-next-experimental": "^5.29.2", "@tanstack/react-table": "^8.16.0", "date-fns": "^3.6.0", - "edge-csrf": "1.0.12-sveltekit-1", + "@edge-csrf/nextjs": "2.0.0", "i18next": "^23.11.2", "i18next-resources-to-backend": "^1.2.1", "lucide-react": "^0.368.0", diff --git a/packages/features/team-accounts/src/server/services/account-members.service.ts b/packages/features/team-accounts/src/server/services/account-members.service.ts index 758f63738..954f14ff1 100644 --- a/packages/features/team-accounts/src/server/services/account-members.service.ts +++ b/packages/features/team-accounts/src/server/services/account-members.service.ts @@ -74,7 +74,7 @@ export class AccountMembersService { const { data: canActionAccountMember, error: accountError } = await this.client.rpc('can_action_account_member', { - user_id: params.userId, + target_user_id: params.userId, target_team_account_id: params.accountId, }); diff --git a/packages/supabase/src/database.types.ts b/packages/supabase/src/database.types.ts index 7500b2499..936d36fdf 100644 --- a/packages/supabase/src/database.types.ts +++ b/packages/supabase/src/database.types.ts @@ -667,7 +667,7 @@ export type Database = { can_action_account_member: { Args: { target_team_account_id: string - user_id: string + target_user_id: string } Returns: boolean } @@ -747,6 +747,10 @@ export type Database = { Args: Record Returns: Json } + get_upper_system_role: { + Args: Record + Returns: string + } has_more_elevated_role: { Args: { target_user_id: string @@ -770,6 +774,14 @@ export type Database = { } Returns: boolean } + has_same_role_hierarchy_level: { + Args: { + target_user_id: string + target_account_id: string + role_name: string + } + Returns: boolean + } is_account_owner: { Args: { account_id: string