diff options
Diffstat (limited to 'src/fields')
| -rw-r--r-- | src/fields/Doc.ts | 7 | ||||
| -rw-r--r-- | src/fields/util.ts | 47 |
2 files changed, 43 insertions, 11 deletions
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 4d82551db..5e2e40979 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -135,7 +135,6 @@ export const ReverseHierarchyMap: Map<string, { level: aclLevel; acl: symbol }> // this recursively updates all protos as well. export function updateCachedAcls(doc: Doc) { if (!doc) return; - const target = (doc as any)?.__fields ?? doc; const permissions: { [key: string]: symbol } = !target.author || target.author === Doc.CurrentUserEmail ? { 'acl-Me': AclAdmin } : {}; Object.keys(target).filter(key => key.startsWith('acl') && (permissions[key] = ReverseHierarchyMap.get(StrCast(target[key]))!.acl)); @@ -1117,7 +1116,7 @@ export namespace Doc { target[targetKey] = new PrefetchProxy(templateDoc); } else { titleTarget && (Doc.GetProto(target).title = titleTarget); - const setDoc = [AclAdmin, AclEdit].includes(GetEffectiveAcl(Doc.GetProto(target))) ? Doc.GetProto(target) : target; + const setDoc = [AclAdmin, AclEdit, AclAugment].includes(GetEffectiveAcl(Doc.GetProto(target))) ? Doc.GetProto(target) : target; setDoc[targetKey] = new PrefetchProxy(templateDoc); } } @@ -1295,7 +1294,9 @@ export namespace Doc { } // don't bother memoizing (caching) the result if called from a non-reactive context. (plus this avoids a warning message) export function IsBrushedDegreeUnmemoized(doc: Doc) { - if (!doc || GetEffectiveAcl(doc) === AclPrivate || GetEffectiveAcl(Doc.GetProto(doc)) === AclPrivate || doc.opacity === 0) return DocBrushStatus.unbrushed; + if (!doc || GetEffectiveAcl(doc) === AclPrivate || GetEffectiveAcl(Doc.GetProto(doc)) === AclPrivate || doc.opacity === 0) { + return DocBrushStatus.unbrushed; + } const status = brushManager.BrushedDoc.has(doc) ? DocBrushStatus.selfBrushed : brushManager.BrushedDoc.has(Doc.GetProto(doc)) ? DocBrushStatus.protoBrushed : DocBrushStatus.unbrushed; if (status === DocBrushStatus.unbrushed) { const lastBrushed = Array.from(brushManager.BrushedDoc.keys()).lastElement(); diff --git a/src/fields/util.ts b/src/fields/util.ts index eca4d1351..c1e1a7111 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -9,9 +9,11 @@ import { returnZero } from '../Utils'; import CursorField from './CursorField'; import { AclAdmin, + AclAugment, AclEdit, aclLevel, AclPrivate, + AclReadonly, AclSelfEdit, AclSym, DataSym, @@ -37,6 +39,8 @@ import { RichTextField } from './RichTextField'; import { SchemaHeaderField } from './SchemaHeaderField'; import { ComputedField } from './ScriptField'; import { ScriptCast, StrCast } from './Types'; +import { SharingManager } from '../client/util/SharingManager'; +import { PropertiesView } from '../client/views/PropertiesView'; function _readOnlySetter(): never { throw new Error("Documents can't be modified in read-only mode"); @@ -82,8 +86,8 @@ const _setterImpl = action(function (target: any, prop: string | symbol | number const writeMode = DocServer.getFieldWriteMode(prop as string); const fromServer = target[UpdatingFromServer]; const sameAuthor = fromServer || receiver.author === Doc.CurrentUserEmail; - const writeToDoc = sameAuthor || effectiveAcl === AclEdit || effectiveAcl === AclAdmin || writeMode !== DocServer.WriteMode.LiveReadonly; - const writeToServer = (sameAuthor || effectiveAcl === AclEdit || effectiveAcl === AclAdmin || (effectiveAcl === AclSelfEdit && value instanceof RichTextField)) && !DocServer.Control.isReadOnly(); + const writeToDoc = sameAuthor || effectiveAcl === AclEdit || effectiveAcl === AclAugment || effectiveAcl === AclAdmin || writeMode !== DocServer.WriteMode.LiveReadonly; + const writeToServer = (sameAuthor || effectiveAcl === AclEdit || effectiveAcl === AclAugment || effectiveAcl === AclAdmin || (effectiveAcl === AclSelfEdit && value instanceof RichTextField)) && !DocServer.Control.isReadOnly(); if (writeToDoc) { if (value === undefined) { @@ -139,13 +143,13 @@ export function denormalizeEmail(email: string) { * Copies parent's acl fields to the child */ export function inheritParentAcls(parent: Doc, child: Doc) { - return; const dataDoc = parent[DataSym]; for (const key of Object.keys(dataDoc)) { // if the default acl mode is private, then don't inherit the acl-Public permission, but set it to private. const permission = key === 'acl-Public' && Doc.defaultAclPrivate ? AclPrivate : dataDoc[key]; key.startsWith('acl') && distributeAcls(key, permission, child); } + return; } /** @@ -182,6 +186,7 @@ const getEffectiveAclCache = computedFn(function (target: any, user?: string) { * Calculates the effective access right to a document for the current user. */ export function GetEffectiveAcl(target: any, user?: string): symbol { + target = Doc.GetProto(target) if (!target) return AclPrivate; if (target[UpdatingFromServer]) return AclAdmin; return getEffectiveAclCache(target, user); // all changes received from the server must be processed as Admin. return this directly so that the acls aren't cached (UpdatingFromServer is not observable) @@ -205,8 +210,24 @@ export function SetCachedGroups(groups: string[]) { } function getEffectiveAcl(target: any, user?: string): symbol { const targetAcls = target[AclSym]; - if (targetAcls?.['acl-Me'] === AclAdmin || GetCachedGroupByName('Admin')) return AclAdmin; - + if (targetAcls?.['acl-Me'] === AclAdmin || GetCachedGroupByName(SharingPermissions.Admin)) return AclAdmin; + if (target['acl-'+normalizeEmail(Doc.CurrentUserEmail)]){ + if (target['acl-'+normalizeEmail(Doc.CurrentUserEmail)] == SharingPermissions.Admin){ + return AclAdmin + } + if (target['acl-'+normalizeEmail(Doc.CurrentUserEmail)] == SharingPermissions.Edit){ + return AclEdit + } + if (target['acl-'+normalizeEmail(Doc.CurrentUserEmail)] == SharingPermissions.Augment){ + return AclAugment + } + if (target['acl-'+normalizeEmail(Doc.CurrentUserEmail)] == SharingPermissions.View){ + return AclReadonly + } + if (target['acl-'+normalizeEmail(Doc.CurrentUserEmail)] == SharingPermissions.None){ + return AclPrivate + } + } const userChecked = user || Doc.CurrentUserEmail; // if the current user is the author of the document / the current user is a member of the admin group if (targetAcls && Object.keys(targetAcls).length) { let effectiveAcl = AclPrivate; @@ -225,13 +246,22 @@ function getEffectiveAcl(target: any, user?: string): symbol { //const override = targetAcls['acl-Override']; // if (override !== AclUnset && override !== undefined) effectiveAcl = override; - // if we're in playground mode, return AclEdit (or AclAdmin if that's the user's effectiveAcl) + return DocServer?.Control?.isReadOnly?.() && HierarchyMapping.get(effectiveAcl)!.level < aclLevel.editable ? AclEdit : effectiveAcl; } // authored documents are private until an ACL is set. const targetAuthor = target.__fields?.author || target.author; // target may be a Doc of Proxy, so check __fields.author and .author if (targetAuthor && targetAuthor !== userChecked) return AclPrivate; return AclAdmin; + let acl = AclPrivate + if (user){ + acl = target['acl-'+user] + } + else{ + acl = target['acl-'+normalizeEmail(Doc.CurrentUserEmail)] + } + console.log(target['acl-'+normalizeEmail(Doc.CurrentUserEmail)]) + return DocServer?.Control?.isReadOnly?.() && HierarchyMapping.get(acl)!.level < aclLevel.editable ? AclEdit : acl; } /** * Recursively distributes the access right for a user across the children of a document and its annotations. @@ -247,9 +277,11 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc if ((target._viewType === CollectionViewType.Docking && visited.length > 1) || Doc.GetProto(visited[0]) !== Doc.GetProto(target)) { target[key] = acl; + Doc.GetProto(target)[key] = acl if (target !== Doc.GetProto(target)) { //apparently we can't call updateCachedAcls twice (once for the main dashboard, and again for the nested dashboard...???) updateCachedAcls(target); + } return; } @@ -260,7 +292,6 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc if (GetEffectiveAcl(target) === AclAdmin && (!inheritingFromCollection || !target[key] || ReverseHierarchyMap.get(StrCast(target[key]))!.level > ReverseHierarchyMap.get(acl)!.level)) { target[key] = acl; layoutDocChanged = true; - if (isDashboard) { DocListCastAsync(target[Doc.LayoutFieldKey(target)]).then(docs => { docs?.forEach(d => distributeAcls(key, acl, d, inheritingFromCollection, visited)); @@ -299,7 +330,7 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc export function setter(target: any, in_prop: string | symbol | number, value: any, receiver: any): boolean { let prop = in_prop; const effectiveAcl = in_prop === 'constructor' || typeof in_prop === 'symbol' ? AclAdmin : getPropAcl(target, prop); - if (effectiveAcl !== AclEdit && effectiveAcl !== AclAdmin && !(effectiveAcl === AclSelfEdit && value instanceof RichTextField)) return true; + if (effectiveAcl !== AclEdit && effectiveAcl !== AclAugment && effectiveAcl !== AclAdmin && !(effectiveAcl === AclSelfEdit && value instanceof RichTextField)) return true; // if you're trying to change an acl but don't have Admin access / you're trying to change it to something that isn't an acceptable acl, you can't if (typeof prop === 'string' && prop.startsWith('acl') && (effectiveAcl !== AclAdmin || ![...Object.values(SharingPermissions), undefined].includes(value))) return true; |
