(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
This commit is contained in:
Paul Fitzpatrick
2021-01-12 10:48:40 -05:00
parent 68a682f876
commit 438f259687
16 changed files with 193 additions and 69 deletions

View File

@@ -3,6 +3,7 @@ import {BrowserSettings} from 'app/common/BrowserSettings';
import {ErrorWithCode} from 'app/common/ErrorWithCode';
import {UserProfile} from 'app/common/LoginSessionAPI';
import {getLoginState, LoginState} from 'app/common/LoginState';
import {ANONYMOUS_USER_EMAIL} from 'app/common/UserAPI';
import {User} from 'app/gen-server/entity/User';
import {HomeDBManager} from 'app/gen-server/lib/HomeDBManager';
import {ActiveDoc} from 'app/server/lib/ActiveDoc';
@@ -297,10 +298,17 @@ export class Client {
// practice via a change to profile, but let's not make any assumptions here.)
this._userId = null;
this._firstLoginAt = null;
this._isAnonymous = false;
this._isAnonymous = !profile;
}
public getProfile(): UserProfile|null {
if (this._isAnonymous) {
return {
name: 'Anonymous',
email: ANONYMOUS_USER_EMAIL,
anonymous: true,
};
}
return this._profile;
}
@@ -315,10 +323,16 @@ export class Client {
// Returns the userId for profile.email, or null when profile is not set; with caching.
public async getUserId(dbManager: HomeDBManager): Promise<number|null> {
if (!this._userId) {
const user = await this._fetchUser(dbManager);
this._userId = (user && user.id) || null;
this._isAnonymous = this._userId && dbManager.getAnonymousUserId() === this._userId || false;
this._firstLoginAt = (user && user.firstLoginAt) || null;
if (this._profile) {
const user = await this._fetchUser(dbManager);
this._userId = (user && user.id) || null;
this._isAnonymous = this._userId && dbManager.getAnonymousUserId() === this._userId || false;
this._firstLoginAt = (user && user.firstLoginAt) || null;
} else {
this._userId = dbManager.getAnonymousUserId();
this._isAnonymous = true;
this._firstLoginAt = null;
}
}
return this._userId;
}