feat(MED-105): create audit entry on analysis results view
This commit is contained in:
@@ -15,6 +15,8 @@ import { redirect } from 'next/navigation';
|
|||||||
import { getOrders } from '~/lib/services/order.service';
|
import { getOrders } from '~/lib/services/order.service';
|
||||||
import { AnalysisElement, getAnalysisElements } from '~/lib/services/analysis-element.service';
|
import { AnalysisElement, getAnalysisElements } from '~/lib/services/analysis-element.service';
|
||||||
import type { UserAnalysisElement } from '@kit/accounts/types/accounts';
|
import type { UserAnalysisElement } from '@kit/accounts/types/accounts';
|
||||||
|
import { loadCurrentUserAccount } from '@/app/home/(user)/_lib/server/load-user-account';
|
||||||
|
import { createPageViewLog } from '~/lib/services/audit/pageView.service';
|
||||||
|
|
||||||
export const generateMetadata = async () => {
|
export const generateMetadata = async () => {
|
||||||
const i18n = await createI18nServerInstance();
|
const i18n = await createI18nServerInstance();
|
||||||
@@ -26,6 +28,11 @@ export const generateMetadata = async () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
async function AnalysisResultsPage() {
|
async function AnalysisResultsPage() {
|
||||||
|
const account = await loadCurrentUserAccount()
|
||||||
|
if (!account) {
|
||||||
|
throw new Error('Account not found');
|
||||||
|
}
|
||||||
|
|
||||||
const analysisList = await loadUserAnalysis();
|
const analysisList = await loadUserAnalysis();
|
||||||
|
|
||||||
const orders = await getOrders().catch(() => null);
|
const orders = await getOrders().catch(() => null);
|
||||||
@@ -35,6 +42,11 @@ async function AnalysisResultsPage() {
|
|||||||
redirect(pathsConfig.auth.signIn);
|
redirect(pathsConfig.auth.signIn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await createPageViewLog({
|
||||||
|
accountId: account.id,
|
||||||
|
action: 'VIEW_ANALYSIS_RESULTS',
|
||||||
|
});
|
||||||
|
|
||||||
const analysisElementIds = [
|
const analysisElementIds = [
|
||||||
...new Set(orders?.flatMap((order) => order.analysis_element_ids).filter(Boolean) as number[]),
|
...new Set(orders?.flatMap((order) => order.analysis_element_ids).filter(Boolean) as number[]),
|
||||||
];
|
];
|
||||||
|
|||||||
35
lib/services/audit/pageView.service.ts
Normal file
35
lib/services/audit/pageView.service.ts
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import { getSupabaseServerClient } from '@kit/supabase/server-client';
|
||||||
|
|
||||||
|
export const createPageViewLog = async ({
|
||||||
|
accountId,
|
||||||
|
action,
|
||||||
|
}: {
|
||||||
|
accountId: string;
|
||||||
|
action: 'VIEW_ANALYSIS_RESULTS';
|
||||||
|
}) => {
|
||||||
|
try {
|
||||||
|
const supabase = getSupabaseServerClient();
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: { user },
|
||||||
|
error: userError,
|
||||||
|
} = await supabase.auth.getUser();
|
||||||
|
|
||||||
|
if (userError || !user) {
|
||||||
|
console.error('No authenticated user found; skipping audit insert');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await supabase
|
||||||
|
.schema('audit')
|
||||||
|
.from('page_views')
|
||||||
|
.insert({
|
||||||
|
account_id: accountId,
|
||||||
|
action,
|
||||||
|
changed_by: user.id,
|
||||||
|
})
|
||||||
|
.throwOnError();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to insert page view log', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -81,6 +81,30 @@ export type Database = {
|
|||||||
}
|
}
|
||||||
Relationships: []
|
Relationships: []
|
||||||
}
|
}
|
||||||
|
page_views: {
|
||||||
|
Row: {
|
||||||
|
account_id: string
|
||||||
|
action: string
|
||||||
|
changed_by: string
|
||||||
|
created_at: string
|
||||||
|
id: number
|
||||||
|
}
|
||||||
|
Insert: {
|
||||||
|
account_id: string
|
||||||
|
action: string
|
||||||
|
changed_by: string
|
||||||
|
created_at?: string
|
||||||
|
id?: number
|
||||||
|
}
|
||||||
|
Update: {
|
||||||
|
account_id?: string
|
||||||
|
action: string
|
||||||
|
changed_by?: string
|
||||||
|
created_at?: string
|
||||||
|
id?: number
|
||||||
|
}
|
||||||
|
Relationships: []
|
||||||
|
}
|
||||||
request_entries: {
|
request_entries: {
|
||||||
Row: {
|
Row: {
|
||||||
comment: string | null
|
comment: string | null
|
||||||
|
|||||||
24
supabase/migrations/20250811065135_audit_page_views.sql
Normal file
24
supabase/migrations/20250811065135_audit_page_views.sql
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
create table "audit"."page_views" (
|
||||||
|
"id" bigint generated by default as identity not null,
|
||||||
|
"account_id" text not null,
|
||||||
|
"action" text not null,
|
||||||
|
"created_at" timestamp with time zone not null default now(),
|
||||||
|
"changed_by" uuid not null
|
||||||
|
);
|
||||||
|
|
||||||
|
grant usage on schema audit to authenticated;
|
||||||
|
grant select, insert, update, delete on table audit.page_views to authenticated;
|
||||||
|
|
||||||
|
alter table "audit"."page_views" enable row level security;
|
||||||
|
|
||||||
|
create policy "insert_own"
|
||||||
|
on "audit"."page_views"
|
||||||
|
as permissive
|
||||||
|
for insert
|
||||||
|
to authenticated
|
||||||
|
with check (auth.uid() = changed_by);
|
||||||
|
|
||||||
|
create policy "service_role_select" on "audit"."page_views" for select to service_role using (true);
|
||||||
|
create policy "service_role_insert" on "audit"."page_views" for insert to service_role with check (true);
|
||||||
|
create policy "service_role_update" on "audit"."page_views" for update to service_role using (true);
|
||||||
|
create policy "service_role_delete" on "audit"."page_views" for delete to service_role using (true);
|
||||||
Reference in New Issue
Block a user