@accounter/server
Version:
Accounter GraphQL server
48 lines (39 loc) • 1.49 kB
text/typescript
import { GraphQLError } from 'graphql';
import { Injectable, Scope } from 'graphql-modules';
import { TenantAwareDBClient } from '../../app-providers/tenant-db-client.js';
import { AuthContextProvider } from '../../auth/providers/auth-context.provider.js';
import { AuthorizationProvider } from '../../auth/providers/authorization.provider.js';
({ scope: Scope.Operation })
export class ChargesAuthorizationProvider extends AuthorizationProvider {
constructor(
authProvider: AuthContextProvider,
private db: TenantAwareDBClient,
) {
super(authProvider);
}
async canReadCharges(): Promise<void> {
await this.requireAuth();
}
async canWriteCharge(): Promise<void> {
await this.requireRole(['business_owner', 'accountant', 'gmail_listener', 'scraper']);
}
async canDeleteChargesByIds(chargeIds: readonly string[]): Promise<void> {
await this.requireRole(['business_owner', 'accountant']);
if (!chargeIds.length) {
return;
}
const uniqueChargeIds = [...new Set(chargeIds)];
const { rows } = await this.db.query(
'SELECT id FROM accounter_schema.charges WHERE id = ANY($1::uuid[])',
[uniqueChargeIds],
);
if (rows.length !== uniqueChargeIds.length) {
throw new GraphQLError('Charge not found or access denied', {
extensions: { code: 'NOT_FOUND' },
});
}
}
async canDeleteCharge(chargeId: string): Promise<void> {
await this.canDeleteChargesByIds([chargeId]);
}
}