feat: implement viewer role permissions for bank transaction imports and connections (#234)

This commit is contained in:
Mattsson
2026-04-13 19:43:28 +02:00
committed by GitHub
parent 9753f18533
commit cd376e1cad
10 changed files with 305 additions and 42 deletions
+52
View File
@@ -1,6 +1,7 @@
import { NextResponse } from 'next/server'
import type { SupabaseClient } from '@supabase/supabase-js'
import { getActiveCompanyId } from '@/lib/company/context'
import type { CompanyRole } from '@/types'
/**
* Write-permission guard for API routes.
@@ -61,3 +62,54 @@ export async function requireWritePermission(
return { ok: true }
}
/**
* Resolves the caller's role in the active company without blocking viewers.
*
* Unlike `requireWritePermission()` (which returns 403 for viewers), this
* returns the actual role so the caller can make conditional decisions —
* e.g. allowing viewers to import raw bank transactions but nothing else.
*
* Use `requireWritePermission()` for routes that are fully off-limits to
* viewers. Use `getCompanyRole()` only when the route needs viewer-
* conditional behavior.
*/
export type CompanyRoleResult =
| { ok: true; role: CompanyRole; companyId: string }
| { ok: false; response: NextResponse }
export async function getCompanyRole(
supabase: SupabaseClient,
userId: string,
): Promise<CompanyRoleResult> {
const companyId = await getActiveCompanyId(supabase, userId)
if (!companyId) {
return {
ok: false,
response: NextResponse.json(
{ error: 'Inget aktivt företag.' },
{ status: 403 },
),
}
}
const { data: membership } = await supabase
.from('company_members')
.select('role')
.eq('company_id', companyId)
.eq('user_id', userId)
.maybeSingle()
if (!membership) {
return {
ok: false,
response: NextResponse.json(
{ error: 'Du har ingen roll i detta företag.' },
{ status: 403 },
),
}
}
return { ok: true, role: membership.role as CompanyRole, companyId }
}