gristlabs_grist-core/app/server/lib/Permit.ts

70 lines
2.3 KiB
TypeScript
Raw Normal View History

/**
* An exceptional grant of rights on a resource, for when work needs to be
* initiated by Grist systems rather than a user. Cases where this may happen:
*
* - Deletion of documents and workspaces in the trash
*
* Permits are stored in redis (or, in a single-process dev environment, in memory)
* as json, in keys that expire within minutes. The keys should be effectively
* unguessable.
*
* To use a permit:
*
* - Prepare a Permit object that includes the id of the document or
* workspace to be operated on.
*
* - It the operation you care about involves the database, check
* that "allowSpecialPermit" is enabled for it in HomeDBManager
* (currently only deletion of docs/workspaces has this enabled).
*
* - Save the permit in the permit store, with setPermit, noting its
* generated key.
*
* - Call the API with a "Permit: <permit-key>" header.
*
* - Optionally, remove the permit with removePermit().
*/
export interface Permit {
docId?: string; // A particular document.
workspaceId?: number; // A particular workspace.
org?: string|number; // A particular org.
otherDocId?: string; // For operations involving two documents.
sessionId?: string; // A particular session.
url?: string; // A particular url.
action?: string; // A string denoting what kind of action the permit applies to.
}
/* A store of permits */
export interface IPermitStore {
// Store a permit, and return the key it is stored in.
// Permits are transient, and will expire.
setPermit(permit: Permit, ttlMs?: number): Promise<string>;
// Get any permit associated with the given key, or null if none.
getPermit(permitKey: string): Promise<Permit|null>;
// Remove any permit associated with the given key.
removePermit(permitKey: string): Promise<void>;
// Close down the permit store.
close(): Promise<void>;
// Get the permit key prefix.
getKeyPrefix(): string;
}
export interface IPermitStores {
getPermitStore(prefix: string, defaultTtlMs?: number): IPermitStore;
}
// Create a well formatted permit key from a seed string.
export function formatPermitKey(seed: string, prefix: string) {
return `permit-${prefix}-${seed}`;
}
// Check that permit key is well formatted.
export function checkPermitKey(key: string, prefix: string): boolean {
return key.startsWith(`permit-${prefix}-`);
}