From 716751fa420eda3a3f8322f579255a6532ddc7f5 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Mon, 27 Jul 2020 18:34:31 +0530 Subject: dropdown filters + comments --- src/fields/util.ts | 55 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 15 deletions(-) (limited to 'src/fields') diff --git a/src/fields/util.ts b/src/fields/util.ts index a62795e64..cf8e730fd 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -115,6 +115,7 @@ export function OVERRIDE_ACL(val: boolean) { _overrideAcl = val; } +// playground mode allows the user to add/delete documents or make layout changes without them saving to the server let playgroundMode = false; export function togglePlaygroundMode() { @@ -125,12 +126,27 @@ export function getPlaygroundMode() { return playgroundMode; } +// the list of groups that the current user is a member of let currentUserGroups: string[] = []; +// called from GroupManager once the groups have been fetched from the server export function setGroups(groups: string[]) { currentUserGroups = groups; } +/** + * These are the various levels of access a user can have to a document. + * + * Admin: a user with admin access to a document can remove/edit that document, add/remove/edit annotations (depending on permissions), as well as change others' access rights to that document. + * + * Edit: a user with edit access to a document can remove/edit that document, add/remove/edit annotations (depending on permissions), but not change any access rights to that document. + * + * Add: a user with add access to a document can add documents/annotations to that document but cannot edit or delete anything. + * + * View: a user with view access to a document can only view it - they cannot add/remove/edit anything. + * + * None: the document is not shared with that user. + */ export enum SharingPermissions { Admin = "Admin", Edit = "Can Edit", @@ -139,18 +155,21 @@ export enum SharingPermissions { None = "Not Shared" } +/** + * Calculates the effective access right to a document for the current user. + */ export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number): symbol { if (in_prop === UpdatingFromServer || target[UpdatingFromServer]) return AclAdmin; if (target[AclSym] && Object.keys(target[AclSym]).length) { + // if the current user is the author of the document / the current user is a member of the admin group if (target.__fields?.author === Doc.CurrentUserEmail || target.author === Doc.CurrentUserEmail || currentUserGroups.includes("admin")) return AclAdmin; + // if the ACL is being overriden or the property being modified is one of the playground fields (which can be freely modified) if (_overrideAcl || (in_prop && DocServer.PlaygroundFields?.includes(in_prop.toString()))) return AclEdit; let effectiveAcl = AclPrivate; - let aclPresent = false; - const HierarchyMapping = new Map([ [AclPrivate, 0], [AclReadonly, 1], @@ -160,19 +179,26 @@ export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number) ]); for (const [key, value] of Object.entries(target[AclSym])) { + // there are issues with storing fields with . in the name, so they are replaced with _ during creation + // as a result we need to restore them again during this comparison. if (currentUserGroups.includes(key.substring(4)) || Doc.CurrentUserEmail === key.substring(4).replace("_", ".")) { - if (HierarchyMapping.get(value as symbol)! >= HierarchyMapping.get(effectiveAcl)!) { - aclPresent = true; + if (HierarchyMapping.get(value as symbol)! > HierarchyMapping.get(effectiveAcl)!) { effectiveAcl = value as symbol; - if (effectiveAcl === AclEdit) break; + if (effectiveAcl === AclAdmin) break; } } } - return aclPresent ? effectiveAcl : AclEdit; + return effectiveAcl; } return AclAdmin; } - +/** + * Recursively distributes the access right for a user across the children of a document and its annotations. + * @param key the key storing the access right (e.g. ACL-groupname) + * @param acl the access right being stored (e.g. "Can Edit") + * @param target the document on which this access right is being set + * @param inheritingFromCollection whether the target is being assigned rights after being dragged into a collection (and so is inheriting the ACLs from the collection) + */ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc, inheritingFromCollection?: boolean) { const HierarchyMapping = new Map([ @@ -185,32 +211,31 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc const dataDoc = target[DataSym]; + // if it is inheriting from a collection, it only inherits if A) the key doesn't already exist or B) the right being inherited is more restrictive if (!inheritingFromCollection || !target[key] || HierarchyMapping.get(StrCast(target[key]))! > HierarchyMapping.get(acl)!) target[key] = acl; if (dataDoc && (!inheritingFromCollection || !dataDoc[key] || HierarchyMapping.get(StrCast(dataDoc[key]))! > HierarchyMapping.get(acl)!)) { dataDoc[key] = acl; + // maps over the children of the document DocListCast(dataDoc[Doc.LayoutFieldKey(dataDoc)]).map(d => { if (d.author === Doc.CurrentUserEmail && (!inheritingFromCollection || !d[key] || HierarchyMapping.get(StrCast(d[key]))! > HierarchyMapping.get(acl)!)) { - distributeAcls(key, acl, d); - d[key] = acl; + distributeAcls(key, acl, d, inheritingFromCollection); } const data = d[DataSym]; if (data && data.author === Doc.CurrentUserEmail && (!inheritingFromCollection || !data[key] || HierarchyMapping.get(StrCast(data[key]))! > HierarchyMapping.get(acl)!)) { - distributeAcls(key, acl, data); - data[key] = acl; + distributeAcls(key, acl, data, inheritingFromCollection); } }); + // maps over the annotations of the document DocListCast(dataDoc[Doc.LayoutFieldKey(dataDoc) + "-annotations"]).map(d => { if (d.author === Doc.CurrentUserEmail && (!inheritingFromCollection || !d[key] || HierarchyMapping.get(StrCast(d[key]))! > HierarchyMapping.get(acl)!)) { - distributeAcls(key, acl, d); - d[key] = acl; + distributeAcls(key, acl, d, inheritingFromCollection); } const data = d[DataSym]; if (data && data.author === Doc.CurrentUserEmail && (!inheritingFromCollection || !data[key] || HierarchyMapping.get(StrCast(data[key]))! > HierarchyMapping.get(acl)!)) { - distributeAcls(key, acl, data); - data[key] = acl; + distributeAcls(key, acl, data, inheritingFromCollection); } }); } -- cgit v1.2.3-70-g09d2 From 12b6b8150ab5e737e18b6029ba243677cdc6a90e Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Thu, 30 Jul 2020 18:37:18 +0530 Subject: added fetchproto to distributeAcls --- src/fields/util.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src/fields') diff --git a/src/fields/util.ts b/src/fields/util.ts index cf8e730fd..048b66b53 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -1,5 +1,5 @@ import { UndoManager } from "../client/util/UndoManager"; -import { Doc, FieldResult, UpdatingFromServer, LayoutSym, AclPrivate, AclEdit, AclReadonly, AclAddonly, AclSym, CachedUpdates, DataSym, DocListCast, AclAdmin, FieldsSym, HeightSym, WidthSym } from "./Doc"; +import { Doc, FieldResult, UpdatingFromServer, LayoutSym, AclPrivate, AclEdit, AclReadonly, AclAddonly, AclSym, CachedUpdates, DataSym, DocListCast, AclAdmin, FieldsSym, HeightSym, WidthSym, fetchProto } from "./Doc"; import { SerializationHelper } from "../client/util/SerializationHelper"; import { ProxyField, PrefetchProxy } from "./Proxy"; import { RefField } from "./RefField"; @@ -209,13 +209,18 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc ["Admin", 4] ]); + let changed = false; const dataDoc = target[DataSym]; // if it is inheriting from a collection, it only inherits if A) the key doesn't already exist or B) the right being inherited is more restrictive - if (!inheritingFromCollection || !target[key] || HierarchyMapping.get(StrCast(target[key]))! > HierarchyMapping.get(acl)!) target[key] = acl; + if (!inheritingFromCollection || !target[key] || HierarchyMapping.get(StrCast(target[key]))! > HierarchyMapping.get(acl)!) { + target[key] = acl; + changed = true; + } if (dataDoc && (!inheritingFromCollection || !dataDoc[key] || HierarchyMapping.get(StrCast(dataDoc[key]))! > HierarchyMapping.get(acl)!)) { dataDoc[key] = acl; + changed = true; // maps over the children of the document DocListCast(dataDoc[Doc.LayoutFieldKey(dataDoc)]).map(d => { @@ -239,6 +244,8 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc } }); } + + changed && fetchProto(target); // updates aclsym when changes to acls have been made } const layoutProps = ["panX", "panY", "width", "height", "nativeWidth", "nativeHeight", "fitWidth", "fitToBox", -- cgit v1.2.3-70-g09d2 From 19c0ca86ed6ff8d8644125fa119270fc79e0afc9 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Fri, 31 Jul 2020 13:59:04 +0530 Subject: integrated playgroundmode into geteffectiveacl, still some issues with deleting docs --- src/client/views/DocComponent.tsx | 8 ++++---- src/client/views/collections/CollectionView.tsx | 10 +++++----- .../views/collections/collectionFreeForm/MarqueeView.tsx | 4 ++-- src/client/views/nodes/WebBox.tsx | 4 ++-- src/client/views/pdf/PDFViewer.tsx | 4 ++-- src/fields/util.ts | 6 +----- 6 files changed, 16 insertions(+), 20 deletions(-) (limited to 'src/fields') diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 3bcf4b922..804c7a8d4 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -7,7 +7,7 @@ import { InteractionUtils } from '../util/InteractionUtils'; import { List } from '../../fields/List'; import { DateField } from '../../fields/DateField'; import { ScriptField } from '../../fields/ScriptField'; -import { GetEffectiveAcl, getPlaygroundMode, SharingPermissions } from '../../fields/util'; +import { GetEffectiveAcl, SharingPermissions } from '../../fields/util'; /// DocComponent returns a generic React base class used by views that don't have 'fieldKey' props (e.g.,CollectionFreeFormDocumentView, DocumentView) @@ -150,7 +150,7 @@ export function ViewBoxAnnotatableComponent

Doc.AddDocToList(targetDataDoc, this.annotationKey, doc)); } else { added.map(doc => doc.context = this.props.Document); (targetDataDoc[this.annotationKey] as List).push(...added); - if (!getPlaygroundMode()) targetDataDoc[this.annotationKey + "-lastModified"] = new DateField(new Date(Date.now())); + targetDataDoc[this.annotationKey + "-lastModified"] = new DateField(new Date(Date.now())); } } } diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 5262c8b46..7e7ea6786 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -17,7 +17,7 @@ import { listSpec } from '../../../fields/Schema'; import { ComputedField, ScriptField } from '../../../fields/ScriptField'; import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; -import { TraceMobx, GetEffectiveAcl, getPlaygroundMode, SharingPermissions } from '../../../fields/util'; +import { TraceMobx, GetEffectiveAcl, SharingPermissions } from '../../../fields/util'; import { emptyFunction, emptyPath, returnEmptyFilter, returnFalse, returnOne, returnZero, setupMoveUpEvents, Utils } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { DocumentType } from '../../documents/DocumentTypes'; @@ -142,7 +142,7 @@ export class CollectionView extends Touchable Doc.AddDocToList(targetDataDoc, this.props.fieldKey, doc)); } else { @@ -181,7 +181,7 @@ export class CollectionView extends Touchable Doc.AddDocToList(Cast(Doc.UserDoc().myCatalog, Doc, null), "data", add)); // targetDataDoc[this.props.fieldKey] = new List([...docList, ...added]); (targetDataDoc[this.props.fieldKey] as List).push(...added); - if (!getPlaygroundMode()) targetDataDoc[this.props.fieldKey + "-lastModified"] = new DateField(new Date(Date.now())); + targetDataDoc[this.props.fieldKey + "-lastModified"] = new DateField(new Date(Date.now())); } } } @@ -193,7 +193,7 @@ export class CollectionView extends Touchable { // creates annotation documents for current highlights const effectiveAcl = GetEffectiveAcl(this.props.Document); - if ([AclAddonly, AclEdit, AclAdmin].includes(effectiveAcl) || getPlaygroundMode()) { + if ([AclAddonly, AclEdit, AclAdmin].includes(effectiveAcl)) { const annotationDoc = this.makeAnnotationDocument(color); annotationDoc && Doc.AddDocToList(this.props.Document, this.annotationKey, annotationDoc); return annotationDoc; diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 954b62332..59fa6b08c 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -13,7 +13,7 @@ import { createSchema, makeInterface } from "../../../fields/Schema"; import { ScriptField } from "../../../fields/ScriptField"; import { Cast, NumCast } from "../../../fields/Types"; import { PdfField } from "../../../fields/URLField"; -import { TraceMobx, GetEffectiveAcl, getPlaygroundMode } from "../../../fields/util"; +import { TraceMobx, GetEffectiveAcl } from "../../../fields/util"; import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, emptyPath, intersectRect, returnZero, smoothScroll, Utils } from "../../../Utils"; import { Docs, DocUtils } from "../../documents/Documents"; import { DocumentType } from "../../documents/DocumentTypes"; @@ -566,7 +566,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent { // creates annotation documents for current highlights const effectiveAcl = GetEffectiveAcl(this.props.Document); - if ([AclAddonly, AclEdit, AclAdmin].includes(effectiveAcl) || getPlaygroundMode()) { + if ([AclAddonly, AclEdit, AclAdmin].includes(effectiveAcl)) { const annotationDoc = this.makeAnnotationDocument(color); annotationDoc && Doc.AddDocToList(this.props.Document, this.annotationKey, annotationDoc); return annotationDoc; diff --git a/src/fields/util.ts b/src/fields/util.ts index 048b66b53..500daf0c7 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -122,10 +122,6 @@ export function togglePlaygroundMode() { playgroundMode = !playgroundMode; } -export function getPlaygroundMode() { - return playgroundMode; -} - // the list of groups that the current user is a member of let currentUserGroups: string[] = []; @@ -188,7 +184,7 @@ export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number) } } } - return effectiveAcl; + return playgroundMode && HierarchyMapping.get(effectiveAcl)! < 3 ? AclEdit : effectiveAcl; } return AclAdmin; } -- cgit v1.2.3-70-g09d2 From 5d50404b127560d525cab4645fcd3b07367ef5a2 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Fri, 31 Jul 2020 16:19:46 +0530 Subject: comments --- src/client/util/GroupManager.tsx | 37 +++++++++++++------------------------ src/client/util/SharingManager.tsx | 8 ++++++-- src/client/views/MainViewModal.tsx | 2 +- src/fields/util.ts | 7 +++++-- 4 files changed, 25 insertions(+), 29 deletions(-) (limited to 'src/fields') diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx index a0db9a421..5215ea35f 100644 --- a/src/client/util/GroupManager.tsx +++ b/src/client/util/GroupManager.tsx @@ -38,8 +38,8 @@ export default class GroupManager extends React.Component<{}> { @observable currentGroup: Opt; // the currently selected group. @observable private createGroupModalOpen: boolean = false; private inputRef: React.RefObject = React.createRef(); // the ref for the input box. - private createGroupButtonRef: React.RefObject = React.createRef(); - private currentUserGroups: string[] = []; + private createGroupButtonRef: React.RefObject = React.createRef(); // the ref for the group creation button + private currentUserGroups: string[] = []; // the list of groups the current user is a member of @observable private buttonColour: "#979797" | "black" = "#979797"; @observable private groupSort: "ascending" | "descending" | "none" = "none"; @@ -50,6 +50,9 @@ export default class GroupManager extends React.Component<{}> { GroupManager.Instance = this; } + /** + * Populates the list of users and groups. + */ componentDidMount() { this.populateUsers(); this.populateGroups(); @@ -63,8 +66,6 @@ export default class GroupManager extends React.Component<{}> { const userList = await RequestPromise.get(Utils.prepend("/getUsers")); const raw = JSON.parse(userList) as User[]; const evaluating = raw.map(async user => { - // const isCandidate = user.email !== Doc.CurrentUserEmail; - // if (isCandidate) { const userDocument = await DocServer.GetRefField(user.userDocumentId); if (userDocument instanceof Doc) { const notificationDoc = await Cast(userDocument.rightSidebarCollection, Doc); @@ -74,11 +75,13 @@ export default class GroupManager extends React.Component<{}> { } }); } - // } }); return Promise.all(evaluating); } + /** + * Populates the list of groups the current user is a member of and sets this list to be used in the GetEffectiveAcl in util.ts + */ populateGroups = () => { DocListCastAsync(this.GroupManagerDoc?.data).then(groups => { groups?.forEach(group => { @@ -146,25 +149,8 @@ export default class GroupManager extends React.Component<{}> { } /** - * @returns a readonly copy of a single group document + * Returns an array of the list of members of a given group. */ - getGroupCopy(groupName: string): Doc | undefined { - const groupDoc = this.getGroup(groupName); - if (groupDoc) { - const { members, owners } = groupDoc; - return Doc.assign(new Doc, { groupName, members: StrCast(members), owners: StrCast(owners) }); - } - return undefined; - } - /** - * @returns a readonly copy of the list of group documents - */ - getAllGroupsCopy(): Doc[] { - return this.getAllGroups().map(({ groupName, owners, members }) => - Doc.assign(new Doc, { groupName: (StrCast(groupName)), owners: (StrCast(owners)), members: (StrCast(members)) }) - ); - } - getGroupMembers(group: string | Doc): string[] { if (group instanceof Doc) return JSON.parse(StrCast(group.members)) as string[]; else return JSON.parse(StrCast(this.getGroup(group)!.members)) as string[]; @@ -317,6 +303,9 @@ export default class GroupManager extends React.Component<{}> { } + /** + * @returns the MainViewModal which allows the user to create groups. + */ private get groupCreationModal() { const contents = (

@@ -416,7 +405,7 @@ export default class GroupManager extends React.Component<{}> {
this.groupSort = this.groupSort === "ascending" ? "descending" : this.groupSort === "descending" ? "none" : "ascending")}> - Name {this.groupSort === "ascending" ? "↑" : this.groupSort === "descending" ? "↓" : ""} {/* → */} + Name {this.groupSort === "ascending" ? "↑" : this.groupSort === "descending" ? "↓" : ""}
{groups.map(group => diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 4ab4a3c42..64dc491ed 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -81,13 +81,14 @@ export default class SharingManager extends React.Component<{}> { public open = (target: DocumentView) => { runInAction(() => this.users = []); // SelectionManager.DeselectAll(); - this.populateUsers().then(action(() => { + this.populateUsers(); + runInAction(() => { this.targetDocView = target; this.targetDoc = target.props.Document; DictationOverlay.Instance.hasActiveModal = true; this.isOpen = true; this.permissions = SharingPermissions.Edit; - })); + }); } @@ -108,6 +109,9 @@ export default class SharingManager extends React.Component<{}> { SharingManager.Instance = this; } + /** + * Populates the list of users. + */ componentDidMount() { this.populateUsers(); } diff --git a/src/client/views/MainViewModal.tsx b/src/client/views/MainViewModal.tsx index 249715511..66ea2dbf8 100644 --- a/src/client/views/MainViewModal.tsx +++ b/src/client/views/MainViewModal.tsx @@ -10,7 +10,7 @@ export interface MainViewOverlayProps { overlayStyle?: React.CSSProperties; dialogueBoxDisplayedOpacity?: number; overlayDisplayedOpacity?: number; - closeOnExternalClick?: () => void; + closeOnExternalClick?: () => void; // the close method of a MainViewModal, triggered if there is a click on the overlay (closing the modal) } @observer diff --git a/src/fields/util.ts b/src/fields/util.ts index 500daf0c7..16517f25f 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -184,6 +184,7 @@ export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number) } } } + // if we're in playground mode, return AclEdit (or AclAdmin if that's the user's effectiveAcl) return playgroundMode && HierarchyMapping.get(effectiveAcl)! < 3 ? AclEdit : effectiveAcl; } return AclAdmin; @@ -194,6 +195,7 @@ export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number) * @param acl the access right being stored (e.g. "Can Edit") * @param target the document on which this access right is being set * @param inheritingFromCollection whether the target is being assigned rights after being dragged into a collection (and so is inheriting the ACLs from the collection) + * inheritingFromCollection is not currently being used but could be used if ACL assignment defaults change */ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc, inheritingFromCollection?: boolean) { @@ -205,7 +207,7 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc ["Admin", 4] ]); - let changed = false; + let changed = false; // determines whether fetchProto should be called or not (i.e. is there a change that should be reflected in target[AclSym]) const dataDoc = target[DataSym]; // if it is inheriting from a collection, it only inherits if A) the key doesn't already exist or B) the right being inherited is more restrictive @@ -241,7 +243,7 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc }); } - changed && fetchProto(target); // updates aclsym when changes to acls have been made + changed && fetchProto(target); // updates target[AclSym] when changes to acls have been made } const layoutProps = ["panX", "panY", "width", "height", "nativeWidth", "nativeHeight", "fitWidth", "fitToBox", @@ -251,6 +253,7 @@ export function setter(target: any, in_prop: string | symbol | number, value: an const effectiveAcl = GetEffectiveAcl(target, in_prop); if (effectiveAcl !== AclEdit && effectiveAcl !== AclAdmin) 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; // if (typeof prop === "string" && prop.startsWith("ACL") && !["Can Edit", "Can Add", "Can View", "Not Shared", undefined].includes(value)) return true; -- cgit v1.2.3-70-g09d2 From 38cfa8e547c1ffb7344f83ebb5dd9798d0dd0d0c Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Fri, 31 Jul 2020 22:47:36 +0530 Subject: added alias list to docs + sharingmanager ui changes --- src/client/util/SharingManager.tsx | 37 +++++++++++++++++++++++++++---------- src/fields/Doc.ts | 4 ++++ src/fields/util.ts | 11 ++++++++++- 3 files changed, 41 insertions(+), 11 deletions(-) (limited to 'src/fields') diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 64dc491ed..196182b77 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -124,14 +124,17 @@ export default class SharingManager extends React.Component<{}> { const userList = await RequestPromise.get(Utils.prepend("/getUsers")); const raw = JSON.parse(userList) as User[]; const evaluating = raw.map(async user => { - const userDocument = await DocServer.GetRefField(user.userDocumentId); - if (userDocument instanceof Doc) { - const notificationDoc = await Cast(userDocument.rightSidebarCollection, Doc); - runInAction(() => { - if (notificationDoc instanceof Doc) { - this.users.push({ user, notificationDoc }); - } - }); + const isCandidate = user.email !== Doc.CurrentUserEmail; + if (isCandidate) { + const userDocument = await DocServer.GetRefField(user.userDocumentId); + if (userDocument instanceof Doc) { + const notificationDoc = await Cast(userDocument.rightSidebarCollection, Doc); + runInAction(() => { + if (notificationDoc instanceof Doc) { + this.users.push({ user, notificationDoc }); + } + }); + } } }); return Promise.all(evaluating); @@ -422,14 +425,28 @@ export default class SharingManager extends React.Component<{}> { key={"owner"} className={"container"} > - {this.targetDoc?.author} + {this.targetDoc?.author === Doc.CurrentUserEmail ? "Me" : this.targetDoc?.author}
Owner
- ) + ), + this.targetDoc?.author !== Doc.CurrentUserEmail ? + ( +
+ Me +
+
+ {this.targetDoc?.[`ACL-${Doc.CurrentUserEmail.replace(".", "_")}`]} +
+
+
+ ) : null ); const groupListContents = groups.map(group => { diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 267defa4b..a1acc7060 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -508,6 +508,10 @@ export namespace Doc { alias.aliasOf = doc; alias.title = ComputedField.MakeFunction(`renameAlias(this, ${Doc.GetProto(doc).aliasNumber = NumCast(Doc.GetProto(doc).aliasNumber) + 1})`); alias.author = Doc.CurrentUserEmail; + + if (!doc.aliases) doc.aliases = new List([alias]); + else Doc.AddDocToList(doc, "aliases", alias); + return alias; } diff --git a/src/fields/util.ts b/src/fields/util.ts index 16517f25f..608ef506c 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -160,7 +160,8 @@ export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number) if (target[AclSym] && Object.keys(target[AclSym]).length) { // if the current user is the author of the document / the current user is a member of the admin group - if (target.__fields?.author === Doc.CurrentUserEmail || target.author === Doc.CurrentUserEmail || currentUserGroups.includes("admin")) return AclAdmin; + // but not if the doc in question is an alias - the current user will be the author of their alias rather than the original author + if ((Doc.CurrentUserEmail === (target.__fields?.author || target.author) && !(target.aliasOf || target.__fields?.aliasOf)) || currentUserGroups.includes("admin")) return AclAdmin; // if the ACL is being overriden or the property being modified is one of the playground fields (which can be freely modified) if (_overrideAcl || (in_prop && DocServer.PlaygroundFields?.includes(in_prop.toString()))) return AclEdit; @@ -214,6 +215,14 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc if (!inheritingFromCollection || !target[key] || HierarchyMapping.get(StrCast(target[key]))! > HierarchyMapping.get(acl)!) { target[key] = acl; changed = true; + + // maps over the aliases of the document + if (target.aliases) { + DocListCast(target.aliases).map(alias => { + distributeAcls(key, acl, alias); + }); + } + } if (dataDoc && (!inheritingFromCollection || !dataDoc[key] || HierarchyMapping.get(StrCast(dataDoc[key]))! > HierarchyMapping.get(acl)!)) { -- cgit v1.2.3-70-g09d2 From 10f6686e0ed4a5d7a975fdf2f3453b069fa0ae04 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Sat, 1 Aug 2020 00:42:01 +0530 Subject: playground mode changes --- src/client/DocServer.ts | 3 +-- src/client/util/SettingsManager.tsx | 2 -- src/fields/util.ts | 12 ++++++------ 3 files changed, 7 insertions(+), 10 deletions(-) (limited to 'src/fields') diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts index f5ee6da3c..6fa8cf909 100644 --- a/src/client/DocServer.ts +++ b/src/client/DocServer.ts @@ -9,7 +9,6 @@ import GestureOverlay from './views/GestureOverlay'; import MobileInkOverlay from '../mobile/MobileInkOverlay'; import { runInAction } from 'mobx'; import { ObjectField } from '../fields/ObjectField'; -import { getPlaygroundMode } from '../fields/util'; /** * This class encapsulates the transfer and cross-client synchronization of @@ -452,7 +451,7 @@ export namespace DocServer { } function _UpdateFieldImpl(id: string, diff: any) { - (!getPlaygroundMode()) && Utils.Emit(_socket, MessageStore.UpdateField, { id, diff }); + (!DocServer.Control.isReadOnly()) && Utils.Emit(_socket, MessageStore.UpdateField, { id, diff }); } let _UpdateField: (id: string, diff: any) => void = errorFunc; diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx index fbdceb43e..207c78964 100644 --- a/src/client/util/SettingsManager.tsx +++ b/src/client/util/SettingsManager.tsx @@ -14,7 +14,6 @@ import { Doc } from "../../fields/Doc"; import GroupManager from "./GroupManager"; import HypothesisAuthenticationManager from "../apis/HypothesisAuthenticationManager"; import GoogleAuthenticationManager from "../apis/GoogleAuthenticationManager"; -import { togglePlaygroundMode } from "../../fields/util"; import { DocServer } from "../DocServer"; library.add(fa.faTimes); @@ -101,7 +100,6 @@ export default class SettingsManager extends React.Component<{}> { @action togglePlaygroundMode = () => { - //togglePlaygroundMode(); this.playgroundMode = !this.playgroundMode; if (this.playgroundMode) DocServer.Control.makeReadOnly(); else DocServer.Control.makeEditable(); diff --git a/src/fields/util.ts b/src/fields/util.ts index 608ef506c..d6d9718f2 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -74,7 +74,7 @@ const _setterImpl = action(function (target: any, prop: string | symbol | number 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 || writeMode === DocServer.WriteMode.Default) && !playgroundMode; + const writeToServer = (sameAuthor || effectiveAcl === AclEdit || effectiveAcl === AclAdmin || writeMode === DocServer.WriteMode.Default) && !DocServer.Control.isReadOnly();// && !playgroundMode; if (writeToDoc) { if (value === undefined) { @@ -116,11 +116,11 @@ export function OVERRIDE_ACL(val: boolean) { } // playground mode allows the user to add/delete documents or make layout changes without them saving to the server -let playgroundMode = false; +// let playgroundMode = false; -export function togglePlaygroundMode() { - playgroundMode = !playgroundMode; -} +// export function togglePlaygroundMode() { +// playgroundMode = !playgroundMode; +// } // the list of groups that the current user is a member of let currentUserGroups: string[] = []; @@ -186,7 +186,7 @@ export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number) } } // if we're in playground mode, return AclEdit (or AclAdmin if that's the user's effectiveAcl) - return playgroundMode && HierarchyMapping.get(effectiveAcl)! < 3 ? AclEdit : effectiveAcl; + return DocServer?.Control?.isReadOnly?.() && HierarchyMapping.get(effectiveAcl)! < 3 ? AclEdit : effectiveAcl; } return AclAdmin; } -- cgit v1.2.3-70-g09d2 From 63fd10d0940331d68a9ce58b4b77734b11e393f5 Mon Sep 17 00:00:00 2001 From: bobzel Date: Sun, 2 Aug 2020 09:22:38 -0400 Subject: fixed hiding of close button based on permsisions. --- src/client/views/DocumentDecorations.tsx | 4 ++-- src/client/views/pdf/PDFViewer.tsx | 2 +- src/fields/util.ts | 2 ++ 3 files changed, 5 insertions(+), 3 deletions(-) (limited to 'src/fields') diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 6e6ffc893..7fc4a5c99 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -586,7 +586,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> if (SnappingManager.GetIsDragging() || bounds.r - bounds.x < 2 || bounds.x === Number.MAX_VALUE || !seldoc || this._hidden || isNaN(bounds.r) || isNaN(bounds.b) || isNaN(bounds.x) || isNaN(bounds.y)) { return (null); } - const canDelete = SelectionManager.SelectedDocuments().map(docView => GetEffectiveAcl(docView.props.Document)).some(permission => permission === AclAdmin || permission === AclEdit); + const canDelete = SelectionManager.SelectedDocuments().map(docView => GetEffectiveAcl(docView.props.ContainingCollectionDoc)).some(permission => permission === AclAdmin || permission === AclEdit); const minimal = bounds.r - bounds.x < 100 ? true : false; const maximizeIcon = minimal ? (
Show context menu
} placement="top"> @@ -597,7 +597,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
{/* Currently, this is set to be enabled if there is no ink selected. It might be interesting to think about minimizing ink if it's useful? -syip2*/} -
) : null; +
) : (null); const titleArea = this._edtingTitle ? <> diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index b81baf417..5a43a076b 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -568,7 +568,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent