gristlabs_grist-core/app/server/lib/idUtils.ts
Paul Fitzpatrick 438f259687 (core) start reconciling forking with granular access
Summary:
This allows a fork to be made by a user if:
 * That user is an owner of the document being forked, or
 * That user has full read access to the document being forked.

The bulk of the diff is reorganization of how forking is done.  ActiveDoc.fork is now responsible for creating a fork, not just a docId/urlId for the fork. Since fork creation should not be limited to the doc worker hosting the trunk, a helper endpoint is added for placing the fork.

The change required sanitizing worker allocation a bit, and allowed session knowledge to be removed from HostedStorageManager.

Test Plan: Added test; existing tests pass.

Reviewers: dsagal

Reviewed By: dsagal

Differential Revision: https://phab.getgrist.com/D2700
2021-01-12 14:08:49 -05:00

43 lines
2.0 KiB
TypeScript

import {ForkResult} from 'app/common/ActiveDocAPI';
import {buildUrlId, parseUrlId} from 'app/common/gristUrls';
import {padStart} from 'app/common/gutil';
import {IDocWorkerMap} from 'app/server/lib/DocWorkerMap';
import * as shortUUID from 'short-uuid';
// make an id that is a standard UUID compressed into fewer characters.
export function makeId(): string {
// Generate a flickr-style id, by converting a regular uuid interpreted
// as a hex number (without dashes) into a number expressed in a bigger
// base. That number is encoded as characters chosen for url safety and
// lack of confusability. The character encoding zero is '1'. We pad the
// result so that the length of the id remains consistent, since there is
// routing that depends on the id length exceeding a minimum threshold.
return padStart(shortUUID.generate(), 22, '1');
}
/**
* Construct an id for a fork, given the userId, whether the user is the anonymous user,
* and the id of a reference document (the trunk).
* If the userId is null, the user will be treated as the anonymous user.
*/
export function makeForkIds(options: { userId: number|null, isAnonymous: boolean,
trunkDocId: string, trunkUrlId: string }): ForkResult {
const forkId = makeId();
const forkUserId = options.isAnonymous ? undefined :
(options.userId !== null ? options.userId : undefined);
// TODO: we will want to support forks of forks, but for now we do not -
// forks are always forks of the trunk.
const docId = parseUrlId(options.trunkDocId).trunkId;
const urlId = parseUrlId(options.trunkUrlId).trunkId;
return {
docId: buildUrlId({trunkId: docId, forkId, forkUserId}),
urlId: buildUrlId({trunkId: urlId, forkId, forkUserId}),
};
}
// This used to do a hack for importing, but now does nothing.
// Instead, the server will interpret the special docId "import".
export function getAssignmentId(docWorkerMap: IDocWorkerMap, docId: string): string {
return docId;
}