@tmlmobilidade/types
Version:
555 lines (554 loc) • 22.2 kB
TypeScript
import { z } from 'zod';
export declare const PermissionSchema: z.ZodDiscriminatedUnion<"scope", [z.ZodObject<{
action: z.ZodEnum<["create", "delete", "read", "lock", "update"]>;
scope: z.ZodLiteral<"agencies">;
}, "strip", z.ZodTypeAny, {
scope: "agencies";
action: "create" | "delete" | "read" | "lock" | "update";
}, {
scope: "agencies";
action: "create" | "delete" | "read" | "lock" | "update";
}>, z.ZodObject<{
action: z.ZodEnum<["create", "delete", "read", "lock", "update", "update_texts", "update_dates", "update_publish_status"]>;
resources: z.ZodDefault<z.ZodObject<{
agency_ids: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
reference_types: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
}, "strip", z.ZodTypeAny, {
agency_ids: string[];
reference_types: string[];
}, {
agency_ids?: string[] | undefined;
reference_types?: string[] | undefined;
}>>;
scope: z.ZodLiteral<"alerts">;
}, "strip", z.ZodTypeAny, {
scope: "alerts";
action: "create" | "delete" | "read" | "lock" | "update" | "update_texts" | "update_dates" | "update_publish_status";
resources: {
agency_ids: string[];
reference_types: string[];
};
}, {
scope: "alerts";
action: "create" | "delete" | "read" | "lock" | "update" | "update_texts" | "update_dates" | "update_publish_status";
resources?: {
agency_ids?: string[] | undefined;
reference_types?: string[] | undefined;
} | undefined;
}>, z.ZodObject<{
action: z.ZodEnum<["acceptance_change_status", "acceptance_justify", "acceptance_lock", "acceptance_read", "analsys_lock", "analysis_lock", "analysis_read", "analysis_reprocess", "analysis_update", "audit_lock", "audit_read", "audit_update", "acceptance_comment_activity"]>;
resources: z.ZodDefault<z.ZodObject<{
agency_ids: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
}, "strip", z.ZodTypeAny, {
agency_ids: string[];
}, {
agency_ids?: string[] | undefined;
}>>;
scope: z.ZodLiteral<"rides">;
}, "strip", z.ZodTypeAny, {
scope: "rides";
action: "acceptance_change_status" | "acceptance_justify" | "acceptance_lock" | "acceptance_read" | "analsys_lock" | "analysis_lock" | "analysis_read" | "analysis_reprocess" | "analysis_update" | "audit_lock" | "audit_read" | "audit_update" | "acceptance_comment_activity";
resources: {
agency_ids: string[];
};
}, {
scope: "rides";
action: "acceptance_change_status" | "acceptance_justify" | "acceptance_lock" | "acceptance_read" | "analsys_lock" | "analysis_lock" | "analysis_read" | "analysis_reprocess" | "analysis_update" | "audit_lock" | "audit_read" | "audit_update" | "acceptance_comment_activity";
resources?: {
agency_ids?: string[] | undefined;
} | undefined;
}>, z.ZodObject<{
action: z.ZodEnum<["read", "export"]>;
scope: z.ZodLiteral<"sams">;
}, "strip", z.ZodTypeAny, {
scope: "sams";
action: "read" | "export";
}, {
scope: "sams";
action: "read" | "export";
}>, z.ZodObject<{
action: z.ZodEnum<["create", "read", "lock", "request_approval", "update_processing_status"]>;
resources: z.ZodDefault<z.ZodObject<{
agency_ids: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
}, "strip", z.ZodTypeAny, {
agency_ids: string[];
}, {
agency_ids?: string[] | undefined;
}>>;
scope: z.ZodLiteral<"gtfs_validations">;
}, "strip", z.ZodTypeAny, {
scope: "gtfs_validations";
action: "create" | "read" | "lock" | "request_approval" | "update_processing_status";
resources: {
agency_ids: string[];
};
}, {
scope: "gtfs_validations";
action: "create" | "read" | "lock" | "request_approval" | "update_processing_status";
resources?: {
agency_ids?: string[] | undefined;
} | undefined;
}>, z.ZodObject<{
action: z.ZodEnum<["read_links", "read_wiki"]>;
scope: z.ZodLiteral<"home">;
}, "strip", z.ZodTypeAny, {
scope: "home";
action: "read_links" | "read_wiki";
}, {
scope: "home";
action: "read_links" | "read_wiki";
}>, z.ZodObject<{
action: z.ZodEnum<["create", "delete", "read", "lock", "update"]>;
scope: z.ZodLiteral<"organizations">;
}, "strip", z.ZodTypeAny, {
scope: "organizations";
action: "create" | "delete" | "read" | "lock" | "update";
}, {
scope: "organizations";
action: "create" | "delete" | "read" | "lock" | "update";
}>, z.ZodObject<{
action: z.ZodEnum<["read"]>;
scope: z.ZodLiteral<"performance">;
}, "strip", z.ZodTypeAny, {
scope: "performance";
action: "read";
}, {
scope: "performance";
action: "read";
}>, z.ZodObject<{
action: z.ZodEnum<["create", "delete", "read", "read_controller", "read_pcgi_legacy", "lock", "update", "update_controller", "update_feed_info_dates", "update_gtfs_plan", "update_pcgi_legacy", "read_apex_file", "update_apex_file", "delete_apex_file"]>;
resources: z.ZodDefault<z.ZodObject<{
agency_ids: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
}, "strip", z.ZodTypeAny, {
agency_ids: string[];
}, {
agency_ids?: string[] | undefined;
}>>;
scope: z.ZodLiteral<"plans">;
}, "strip", z.ZodTypeAny, {
scope: "plans";
action: "create" | "delete" | "read" | "lock" | "update" | "read_controller" | "read_pcgi_legacy" | "update_controller" | "update_feed_info_dates" | "update_gtfs_plan" | "update_pcgi_legacy" | "read_apex_file" | "update_apex_file" | "delete_apex_file";
resources: {
agency_ids: string[];
};
}, {
scope: "plans";
action: "create" | "delete" | "read" | "lock" | "update" | "read_controller" | "read_pcgi_legacy" | "update_controller" | "update_feed_info_dates" | "update_gtfs_plan" | "update_pcgi_legacy" | "read_apex_file" | "update_apex_file" | "delete_apex_file";
resources?: {
agency_ids?: string[] | undefined;
} | undefined;
}>, z.ZodObject<{
action: z.ZodEnum<["create", "delete", "read", "lock", "update"]>;
scope: z.ZodLiteral<"roles">;
}, "strip", z.ZodTypeAny, {
scope: "roles";
action: "create" | "delete" | "read" | "lock" | "update";
}, {
scope: "roles";
action: "create" | "delete" | "read" | "lock" | "update";
}>, z.ZodObject<{
action: z.ZodEnum<["create", "delete", "read", "lock", "update", "export", "edit_coordinates", "edit_name"]>;
resources: z.ZodDefault<z.ZodObject<{
agency_ids: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
municipality_ids: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
}, "strip", z.ZodTypeAny, {
municipality_ids: string[];
agency_ids: string[];
}, {
municipality_ids?: string[] | undefined;
agency_ids?: string[] | undefined;
}>>;
scope: z.ZodLiteral<"stops">;
}, "strip", z.ZodTypeAny, {
scope: "stops";
action: "create" | "delete" | "read" | "lock" | "update" | "export" | "edit_coordinates" | "edit_name";
resources: {
municipality_ids: string[];
agency_ids: string[];
};
}, {
scope: "stops";
action: "create" | "delete" | "read" | "lock" | "update" | "export" | "edit_coordinates" | "edit_name";
resources?: {
municipality_ids?: string[] | undefined;
agency_ids?: string[] | undefined;
} | undefined;
}>, z.ZodObject<{
action: z.ZodEnum<["create", "delete", "read", "lock", "update"]>;
scope: z.ZodLiteral<"users">;
}, "strip", z.ZodTypeAny, {
scope: "users";
action: "create" | "delete" | "read" | "lock" | "update";
}, {
scope: "users";
action: "create" | "delete" | "read" | "lock" | "update";
}>, z.ZodObject<{
action: z.ZodEnum<["create", "delete", "read", "lock", "update"]>;
resources: z.ZodDefault<z.ZodObject<{
agency_ids: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
}, "strip", z.ZodTypeAny, {
agency_ids: string[];
}, {
agency_ids?: string[] | undefined;
}>>;
scope: z.ZodLiteral<"vehicles">;
}, "strip", z.ZodTypeAny, {
scope: "vehicles";
action: "create" | "delete" | "read" | "lock" | "update";
resources: {
agency_ids: string[];
};
}, {
scope: "vehicles";
action: "create" | "delete" | "read" | "lock" | "update";
resources?: {
agency_ids?: string[] | undefined;
} | undefined;
}>, z.ZodObject<{
action: z.ZodEnum<["create", "delete", "lock", "nav", "update"]>;
resources: z.ZodDefault<z.ZodObject<{
agency_ids: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
}, "strip", z.ZodTypeAny, {
agency_ids: string[];
}, {
agency_ids?: string[] | undefined;
}>>;
scope: z.ZodLiteral<"fares">;
}, "strip", z.ZodTypeAny, {
scope: "fares";
action: "create" | "delete" | "lock" | "update" | "nav";
resources: {
agency_ids: string[];
};
}, {
scope: "fares";
action: "create" | "delete" | "lock" | "update" | "nav";
resources?: {
agency_ids?: string[] | undefined;
} | undefined;
}>, z.ZodObject<{
action: z.ZodEnum<["create", "delete", "read", "lock", "update"]>;
resources: z.ZodDefault<z.ZodObject<{
agency_ids: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
}, "strip", z.ZodTypeAny, {
agency_ids: string[];
}, {
agency_ids?: string[] | undefined;
}>>;
scope: z.ZodLiteral<"annotations">;
}, "strip", z.ZodTypeAny, {
scope: "annotations";
action: "create" | "delete" | "read" | "lock" | "update";
resources: {
agency_ids: string[];
};
}, {
scope: "annotations";
action: "create" | "delete" | "read" | "lock" | "update";
resources?: {
agency_ids?: string[] | undefined;
} | undefined;
}>, z.ZodObject<{
action: z.ZodEnum<["create", "delete", "read", "lock", "update"]>;
resources: z.ZodDefault<z.ZodObject<{
agency_ids: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
}, "strip", z.ZodTypeAny, {
agency_ids: string[];
}, {
agency_ids?: string[] | undefined;
}>>;
scope: z.ZodLiteral<"year_periods">;
}, "strip", z.ZodTypeAny, {
scope: "year_periods";
action: "create" | "delete" | "read" | "lock" | "update";
resources: {
agency_ids: string[];
};
}, {
scope: "year_periods";
action: "create" | "delete" | "read" | "lock" | "update";
resources?: {
agency_ids?: string[] | undefined;
} | undefined;
}>, z.ZodObject<{
action: z.ZodEnum<["create", "delete", "read", "lock", "update"]>;
resources: z.ZodDefault<z.ZodObject<{
agency_ids: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
}, "strip", z.ZodTypeAny, {
agency_ids: string[];
}, {
agency_ids?: string[] | undefined;
}>>;
scope: z.ZodLiteral<"holidays">;
}, "strip", z.ZodTypeAny, {
scope: "holidays";
action: "create" | "delete" | "read" | "lock" | "update";
resources: {
agency_ids: string[];
};
}, {
scope: "holidays";
action: "create" | "delete" | "read" | "lock" | "update";
resources?: {
agency_ids?: string[] | undefined;
} | undefined;
}>, z.ZodObject<{
action: z.ZodEnum<["create", "delete", "read", "lock", "update"]>;
resources: z.ZodDefault<z.ZodObject<{
agency_ids: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
}, "strip", z.ZodTypeAny, {
agency_ids: string[];
}, {
agency_ids?: string[] | undefined;
}>>;
scope: z.ZodLiteral<"events">;
}, "strip", z.ZodTypeAny, {
scope: "events";
action: "create" | "delete" | "read" | "lock" | "update";
resources: {
agency_ids: string[];
};
}, {
scope: "events";
action: "create" | "delete" | "read" | "lock" | "update";
resources?: {
agency_ids?: string[] | undefined;
} | undefined;
}>, z.ZodObject<{
action: z.ZodEnum<["create", "delete", "lock", "nav", "update"]>;
resources: z.ZodDefault<z.ZodObject<{
agency_ids: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
}, "strip", z.ZodTypeAny, {
agency_ids: string[];
}, {
agency_ids?: string[] | undefined;
}>>;
scope: z.ZodLiteral<"zones">;
}, "strip", z.ZodTypeAny, {
scope: "zones";
action: "create" | "delete" | "lock" | "update" | "nav";
resources: {
agency_ids: string[];
};
}, {
scope: "zones";
action: "create" | "delete" | "lock" | "update" | "nav";
resources?: {
agency_ids?: string[] | undefined;
} | undefined;
}>, z.ZodObject<{
action: z.ZodEnum<["create", "delete", "lock", "nav", "update"]>;
resources: z.ZodDefault<z.ZodObject<{
agency_ids: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
}, "strip", z.ZodTypeAny, {
agency_ids: string[];
}, {
agency_ids?: string[] | undefined;
}>>;
scope: z.ZodLiteral<"typologies">;
}, "strip", z.ZodTypeAny, {
scope: "typologies";
action: "create" | "delete" | "lock" | "update" | "nav";
resources: {
agency_ids: string[];
};
}, {
scope: "typologies";
action: "create" | "delete" | "lock" | "update" | "nav";
resources?: {
agency_ids?: string[] | undefined;
} | undefined;
}>, z.ZodObject<{
action: z.ZodEnum<["create", "delete", "read", "lock", "update"]>;
resources: z.ZodDefault<z.ZodObject<{
agency_ids: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
}, "strip", z.ZodTypeAny, {
agency_ids: string[];
}, {
agency_ids?: string[] | undefined;
}>>;
scope: z.ZodLiteral<"lines">;
}, "strip", z.ZodTypeAny, {
scope: "lines";
action: "create" | "delete" | "read" | "lock" | "update";
resources: {
agency_ids: string[];
};
}, {
scope: "lines";
action: "create" | "delete" | "read" | "lock" | "update";
resources?: {
agency_ids?: string[] | undefined;
} | undefined;
}>]>;
export type Permission = z.infer<typeof PermissionSchema>;
export type ActionsOf<S extends Permission['scope']> = Extract<Permission, {
scope: S;
}>['action'];
export type PermissionCatalogType = {
[S in Permission['scope']]: {
actions: {
[A in ActionsOf<S>]: A;
};
scope: S;
};
};
/**
* Arguments for hasPermissionResource function.
* @param T The type of the resource.
*/
export interface HasPermissionResourceArgs {
action: string;
permissions: Permission[];
resource_key: string;
scope: string;
value: unknown;
}
/**
* A scope/action pair used to collect resource access from one or more permissions.
*/
export interface PermissionResourceCheck<S extends Permission['scope'] = Permission['scope']> {
action: ActionsOf<S>;
scope: S;
}
/**
* Arguments for getPermissionResourceAccess function.
*/
export interface GetPermissionResourceAccessArgs {
checks: PermissionResourceCheck[];
permissions: Permission[];
resource_key: string;
}
/**
* Aggregated access to a permission resource key.
* When allowAll is true, callers should ignore values and treat the user
* as having access to every value for that resource key.
*/
export interface PermissionResourceAccess<TValue = string> {
allowAll: boolean;
values: TValue[];
}
/**
* Arguments for getScopePermissions function.
*/
export interface GetScopePermissionsArgs<S extends Permission['scope']> {
actions: PermissionCatalogType[S]['actions'];
permissions: Permission[];
resource?: {
key: string;
requireAll?: boolean;
value: unknown;
};
scope: S;
}
/**
* Result object containing permission checks for a scope.
* Maps each action of the scope to a boolean indicating if the user has that permission.
*/
export type ScopePermissions<S extends Permission['scope']> = Record<ActionsOf<S>, boolean>;
/**
* PermissionCatalog provides a structured catalog of all available permissions
* in the system, categorized by scope and their respective actions.
* Use it to reference required permissions in components and services.
*/
export declare class PermissionCatalog {
static readonly ALLOW_ALL_FLAG = "allow_all";
/**
* Generates the complete permission catalog by extracting
* scopes and actions from the defined PermissionSchema.
* @return A catalog object mapping scopes to their actions.
*/
static get all(): PermissionCatalogType;
/**
* Get a specific permission from a full list by scope and action.
* @param permissionEntries The full list of permissions of the user.
* @param scope The resource scope of the permission to filter by.
* @param action The action of the permission to filter by.
* @returns The filtered Permission object or undefined if not found.
*/
static get<S extends Permission['scope']>(permissionEntries: Permission[], scope: S, action: ActionsOf<S>): Extract<Permission, {
action: ActionsOf<S>;
scope: S;
}> | undefined;
/**
* Get all permissions for a given scope and set of actions in one call.
* More efficient than calling hasPermission or hasPermissionResource multiple times.
* @param args Arguments object containing permissions, scope, actions, and optional resource.
* @param args.resource.requireAll If true, uses hasPermissionResourceAll (user must have permission for ALL values in array). If false/undefined, uses hasPermissionResource (user needs permission for ANY value).
* @returns Object with boolean values for each action in the scope.
*/
static getScopePermissions<S extends Permission['scope']>({ actions, permissions, resource, scope }: GetScopePermissionsArgs<S>): ScopePermissions<S>;
/**
* Check if a list of permission entries has the requested scope/action pair.
* @param permissionEntries The list of permission entries to check against.
* @param scope The required scope to check.
* @param action The required action to check.
* @returns The permission object or undefined if not found.
*/
static hasPermission<S extends Permission['scope']>(permissionEntries: Permission[], scope: S, action: ActionsOf<S>): boolean;
/**
* Collect allowed values for a resource key across multiple scope/action checks.
*
* Use this when a caller needs to build a database filter before loading
* documents. For example, a list endpoint can combine `lines.read`,
* `lines.update`, and `zones.nav` permissions into a single set of
* allowed `agency_ids`, then query MongoDB with `{ agency_ids: { $in: values } }`.
*
* This complements `hasPermissionResource`: that method answers whether
* a user can access a known resource value, while this method answers which
* resource values the user can access for a set of allowed permissions.
*
* If any matching permission contains PermissionCatalog.ALLOW_ALL_FLAG for
* the resource key, this returns `{ allowAll: true, values: [] }`.
*
* @param permissions The list of permissions from a user or request.
* @param checks The scope/action pairs whose resource values should be merged.
* @param resource_key The permission resource key to collect, e.g. `agency_ids`.
* @returns The aggregated resource access for the requested checks.
*/
static getPermissionResourceAccess<TValue = string>(args: GetPermissionResourceAccessArgs): PermissionResourceAccess<TValue>;
/**
* Check if a permission exists in a list of permissions, with additional check for a given resource value.
* If a `value` exists in a `resource` of a User `permissions` object that
* matches the given `action` and `scope`. For example, if you want to check if
* a user has access to a specific `agency_id`, you set `value=43` and `resource_key='agency_ids'`.
* If the provided `permissions` object contains the value `43` inside the `scope='plans'`,
* `action='create'` and `resource_key='agency_ids'` the function will return true.
* @param permissions The list of permissions (from a user or request).
* @param value The permission value to check against.
* @param resource_key The key of the resource.
* @param scope The scope of the permission.
* @param action The action of the permission.
* @returns The permission.
*/
static hasPermissionResource({ action, permissions, resource_key, scope, value }: HasPermissionResourceArgs): boolean;
/**
* Checks whether the user has permission to perform a specific action
* within a specific scope for ALL values in an array.
* This is stricter than `hasPermissionResource` which only requires permission for ANY value.
* Use this for operations like update/delete where the user must have permission for all agencies involved.
* @param permissions The list of permissions (from a user or request).
* @param value The permission value(s) to check against - if array, ALL values must be permitted.
* @param resource_key The key of the resource.
* @param scope The scope of the permission.
* @param action The action of the permission.
* @returns True if user has permission for ALL values, false otherwise.
*/
static hasPermissionResourceAll({ action, permissions, resource_key, scope, value }: HasPermissionResourceArgs): boolean;
/**
* Sanitizes a list of permissions by removing any entries
* that do not correspond to valid scopes and actions
* defined in the PermissionCatalog.
* @param existingEntries Array of Permission objects to sanitize.
* @return A cleaned array containing only valid permissions.
*/
static sanitize(existingEntries: Permission[]): Permission[];
/**
* Sanitizes a list of permissions by removing any entries
* that do not correspond to valid scopes and actions
* defined in the PermissionCatalog.
* @param existingEntries Array of Permission objects to sanitize.
* @return A cleaned array containing only valid permissions.
*/
static updatePermissionResource<S extends Permission['scope']>(permissionEntries: Permission[], scope: S, action: ActionsOf<S>, resources: Record<string, unknown>): Permission[];
}