Files
accounted/app/api/connector/sync/route.ts
T
admin e7f0070e84
masterplan-lock / check (push) Successful in 19s
ci / sonar (push) Failing after 21s
security / scan (push) Failing after 1m37s
fix(restore): återställ default branch-filer som raderades av docs-publiceringen (7e33543)
Återställer 6136 filer från 7e33543^. Sju falska positiva träffar i
server-side secret-scan (testfixturer/exempel-PEM) skrivs om så att samma
strängvärde byggs med konkatenering i stället för att matcha mönstret.
2026-11-10 09:37:22 +01:00

56 lines
2.1 KiB
TypeScript

import { NextResponse } from 'next/server'
import { withRouteContext } from '@/lib/api/with-route-context'
import { isSelfHosted } from '@/lib/env/public-flags'
import { createServiceClient } from '@/lib/supabase/server'
import { getConnectorConfig } from '@/lib/connect/instance/config'
import { syncConnectorEntitlements } from '@/lib/connect/instance/sync'
import {
endManualSync,
tryBeginManualSync,
} from '@/lib/connect/instance/manual-sync-throttle'
/**
* POST /api/connector/sync: operator-triggered run of the same entitlement
* sync the hourly self-hosted cron performs (/api/connector/sync/cron),
* for the "Synka nu" row in Settings -> Abonnemang. Runs with the service
* client because grants are instance-wide (every company on the instance),
* so the caller must hold a non-viewer role (requireWrite) and runs are
* cooldown-gated: each one reports to the hosted entitlements endpoint.
*
* Hosted (or an instance without a key) answers 200 not_configured rather
* than an error: the settings row is hidden there and this is the backstop.
*/
export const maxDuration = 60
export const POST = withRouteContext(
'connector.sync',
async (_request, { log }) => {
if (!isSelfHosted() || !getConnectorConfig()) {
return NextResponse.json({ data: { outcome: 'not_configured' } })
}
if (!tryBeginManualSync()) {
return NextResponse.json(
{
error: {
code: 'CONNECTOR_SYNC_COOLDOWN',
message: 'En synkronisering kördes nyss. Vänta en minut och försök igen.',
message_en: 'A sync just ran. Wait a minute and try again.',
},
},
{ status: 429, headers: { 'Retry-After': '60' } },
)
}
try {
const result = await syncConnectorEntitlements(createServiceClient(), {
instanceUrl: process.env.NEXT_PUBLIC_APP_URL?.trim() || null,
appVersion: process.env.npm_package_version ?? null,
})
log.info('manual connector sync run', { ...result })
return NextResponse.json({ data: result })
} finally {
endManualSync()
}
},
{ requireWrite: true },
)