Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 12x 12x 12x 12x 48x 12x 12x 1x 1x 1x 1x 1x 1x 12x 12x 12x 12x 12x 48x 40x 12x 12x 12x 1x 1x 12x 12x 12x 12x 12x 12x 1x 1x 1x 1x 1x 1x 1x | import { VariableType, type Quota } from '@amalia/amalia-lang/tokens/types';
import { toTimestamp, type UnixTimestampInSeconds } from '@amalia/ext/dates';
import { assert } from '@amalia/ext/typescript';
import {
type AdminScopesContainerDehydrated,
type AdminScopesContainerInterface,
type AdminScopesContainerParams,
} from '@amalia/kernel/auth/types';
import { type Plan } from '@amalia/payout-definition/plans/types';
import { type UserContract } from '@amalia/tenants/users/types';
export class AdminScopesContainer implements AdminScopesContainerInterface {
private readonly scope: AdminScopesContainerParams['scope'];
private readonly planAssignments: AdminScopesContainerParams['planAssignments'];
public constructor({ scope, planAssignments }: AdminScopesContainerParams) {
this.scope = scope;
this.planAssignments = planAssignments;
planAssignments.forEach((pa) => {
if (!scope.planIds.includes(pa.planId)) {
throw new Error(`Invalid plan assignment ${pa.id}, not part of plans of scope ${scope.id}`);
}
});
}
public dehydrate(): AdminScopesContainerDehydrated {
return {
scope: this.scope,
planAssignments: this.planAssignments,
};
}
public static hydrate(dehydrated: AdminScopesContainerDehydrated) {
return new AdminScopesContainer(dehydrated);
}
public allUsersInMyScope(date: Date | UnixTimestampInSeconds): UserContract[] {
const observationDateTimestamp = toTimestamp(date);
return this.planAssignments
.filter(
(pa) =>
(!pa.effectiveAsOf || pa.effectiveAsOf <= observationDateTimestamp) &&
(!pa.effectiveUntil || observationDateTimestamp <= pa.effectiveUntil),
)
.map((pa) => pa.user!);
}
public userIsInScope(userId: UserContract['id'], date: Date | UnixTimestampInSeconds): boolean {
const observationDateTimestamp = toTimestamp(date);
const allUsersInMyScope = this.allUsersInMyScope(observationDateTimestamp);
return allUsersInMyScope.some((user) => user.id === userId);
}
public canAccessQuotaValue(quotaValue: {
quotaType: VariableType;
quotaId?: Quota['id'];
userId?: string | null;
planId?: string | null;
date?: Date | UnixTimestampInSeconds | null;
}): boolean {
assert(quotaValue.quotaId, 'quotaValue.quotaId is required');
assert(quotaValue.quotaType, 'quotaValue.quotaType is required');
// In any case, check first that the quota is in the scope.
if (!this.scope.quotaIds.includes(quotaValue.quotaId)) {
return false;
}
if (quotaValue.quotaType === VariableType.plan) {
assert(quotaValue.planId, 'quotaValue.planId is required');
assert(quotaValue.quotaType, 'quotaValue.quotaType is required');
return this.scope.planIds.includes(quotaValue.planId);
}
if (quotaValue.quotaType === VariableType.user) {
assert(quotaValue.userId, 'quotaValue.userId is required');
// If no date is provided (quota without frequency), use today.
return this.userIsInScope(quotaValue.userId, quotaValue.date ?? new Date());
}
return false;
}
public listPlansInMyScope(): Plan['id'][] {
return this.scope.planIds;
}
public listQuotasInMyScope(): Quota['id'][] {
return this.scope.quotaIds;
}
}
|