diff options
author | bobzel <zzzman@gmail.com> | 2023-07-11 15:32:08 -0400 |
---|---|---|
committer | bobzel <zzzman@gmail.com> | 2023-07-11 15:32:08 -0400 |
commit | 06cfe3cbba127d865e788b00561f8a591af1bd81 (patch) | |
tree | 2aeb0132d33e04c90483a46a3482ab3d8c4744d8 /src | |
parent | 8a852df1c918d8e31ba0b540798895fcd420cca7 (diff) |
more fixes to simplify sharing
Diffstat (limited to 'src')
-rw-r--r-- | src/client/documents/Documents.ts | 31 | ||||
-rw-r--r-- | src/client/util/CurrentUserUtils.ts | 6 | ||||
-rw-r--r-- | src/client/util/DocumentManager.ts | 2 | ||||
-rw-r--r-- | src/client/util/SharingManager.tsx | 9 | ||||
-rw-r--r-- | src/client/views/DashboardView.tsx | 15 | ||||
-rw-r--r-- | src/client/views/DocComponent.tsx | 15 | ||||
-rw-r--r-- | src/client/views/PropertiesView.tsx | 55 | ||||
-rw-r--r-- | src/client/views/collections/CollectionDockingView.tsx | 4 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/MarqueeView.tsx | 8 | ||||
-rw-r--r-- | src/client/views/nodes/button/FontIconBox.tsx | 2 | ||||
-rw-r--r-- | src/client/views/search/SearchBox.tsx | 2 | ||||
-rw-r--r-- | src/fields/Doc.ts | 16 | ||||
-rw-r--r-- | src/fields/DocSymbols.ts | 1 | ||||
-rw-r--r-- | src/fields/util.ts | 39 |
14 files changed, 88 insertions, 117 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index f1ba852f9..4ebbfbd1c 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -169,8 +169,8 @@ export class DocumentOptions { _nativeDimModifiable?: BOOLt = new BoolInfo('native dimensions can be modified using document decoration reizers'); _nativeHeightUnfrozen?: BOOLt = new BoolInfo('native height can be changed independent of width by dragging decoration resizers'); - 'acl-Public'?: string; // public permissions - '_acl-Public'?: string; // public permissions + 'acl-Guest'?: string; // public permissions + '_acl-Guest'?: string; // public permissions type?: DTYPEt = new DTypeInfo('type of document', true); type_collection?: COLLt = new CTypeInfo('how collection is rendered'); // sub type of a collection _type_collection?: COLLt = new CTypeInfo('how collection is rendered'); // sub type of a collection @@ -825,8 +825,7 @@ export namespace Docs { const { omit: dataProps, extract: viewProps } = OmitKeys(options, viewKeys, '^_'); // dataProps['acl-Override'] = SharingPermissions.Unset; - dataProps['acl-Public'] = options['acl-Public'] ? options['acl-Public'] : Doc.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Augment; - + dataProps['acl-Guest'] = options['acl-Guest'] ?? (Doc.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.View); dataProps.isSystem = viewProps.isSystem; dataProps.isDataDoc = true; dataProps.author = Doc.CurrentUserEmail; @@ -848,16 +847,17 @@ export namespace Docs { dataDoc.proto = proto; } - const viewFirstProps: { [id: string]: any } = {}; - // viewFirstProps['acl-Public'] = options['_acl-Public'] ? options['_acl-Public'] : Doc.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Augment; - // viewFirstProps['acl-Override'] = SharingPermissions.Unset; - viewFirstProps.author = Doc.CurrentUserEmail; + const viewFirstProps: { [id: string]: any } = { author: Doc.CurrentUserEmail }; + viewFirstProps['acl-Guest'] = options['_acl-Guest'] ?? (Doc.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.View); let viewDoc: Doc; // determines whether viewDoc should be created using placeholder Doc or default if (placeholderDoc) { placeholderDoc._height = options._height !== undefined ? Number(options._height) : undefined; placeholderDoc._width = options._width !== undefined ? Number(options._width) : undefined; viewDoc = Doc.assign(placeholderDoc, viewFirstProps, true, true); + Array.from(Object.keys(placeholderDoc)) + .filter(key => key.startsWith('acl')) + .forEach(key => (dataDoc[key] = viewDoc[key] = placeholderDoc[key])); } else { viewDoc = Doc.assign(Doc.MakeDelegate(dataDoc, delegId), viewFirstProps, true, true); } @@ -997,7 +997,7 @@ export namespace Docs { I.rotation = 0; I.defaultDoubleClick = 'click'; I.author_date = new DateField(); - I['acl-Public'] = Doc.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Augment; + I['acl-Guest'] = Doc.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.View; //I['acl-Override'] = SharingPermissions.Unset; I[Initializing] = false; @@ -1169,10 +1169,13 @@ export namespace Docs { const doc = DockDocument( configs.map(c => c.doc), JSON.stringify(layoutConfig), - options, + Doc.CurrentUserEmail === 'guest' ? options : { 'acl-Guest': SharingPermissions.View, ...options }, id ); - configs.map(c => Doc.SetContainer(c.doc, doc)); + configs.map(c => { + Doc.SetContainer(c.doc, doc); + inheritParentAcls(doc, c.doc, false); + }); return doc; } @@ -1332,8 +1335,8 @@ export namespace DocUtils { source, target, { - 'acl-Public': SharingPermissions.Augment, - '_acl-Public': SharingPermissions.Augment, + 'acl-Guest': SharingPermissions.Augment, + '_acl-Guest': SharingPermissions.Augment, title: ComputedField.MakeFunction('generateLinkTitle(self)') as any, link_anchor_1_useSmallAnchor: source.useSmallAnchor ? true : undefined, link_anchor_2_useSmallAnchor: target.useSmallAnchor ? true : undefined, @@ -1854,8 +1857,6 @@ export namespace DocUtils { Doc.SetInPlace(ndoc, 'title', ndoc.title + ' ' + NumCast(dragFactory['dragFactory_count']).toString(), true); } - if (ndoc && Doc.ActiveDashboard) inheritParentAcls(Doc.ActiveDashboard, ndoc); - return ndoc; } export function delegateDragFactory(dragFactory: Doc) { diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 11a8dcaf6..2cee37380 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -765,7 +765,7 @@ export class CurrentUserUtils { linkDocs.title = "LINK DATABASE: " + Doc.CurrentUserEmail; linkDocs.author = Doc.CurrentUserEmail; linkDocs.data = new List<Doc>([]); - linkDocs["acl-Public"] = SharingPermissions.Augment; + linkDocs["acl-Guest"] = SharingPermissions.Augment; doc.myLinkDatabase = new PrefetchProxy(linkDocs); } } @@ -788,7 +788,7 @@ export class CurrentUserUtils { childContextMenuScripts: new List<ScriptField>([addToDashboards!,]), childContextMenuLabels: new List<string>(["Add to Dashboards",]), childContextMenuIcons: new List<string>(["user-plus",]), - "acl-Public": SharingPermissions.Augment, "_acl-Public": SharingPermissions.Augment, + "acl-Guest": SharingPermissions.Augment, "_acl-Guest": SharingPermissions.Augment, childDragAction: "embed", isSystem: true, contentPointerEvents: "all", childLimitHeight: 0, _yMargin: 0, _gridGap: 15, childDontRegisterViews:true, // NOTE: treeViewHideTitle & _layout_showTitle is for a TreeView's editable title, _layout_showTitle is for DocumentViews title bar _layout_showTitle: "title", treeViewHideTitle: true, ignoreClick: true, _lockedPosition: true, layout_boxShadow: "0 0", _chromeHidden: true, dontRegisterView: true, @@ -823,7 +823,7 @@ export class CurrentUserUtils { async () => { const groups = await DocListCastAsync(DocCast(doc.globalGroupDatabase).data); const mygroups = groups?.filter(group => JSON.parse(StrCast(group.members)).includes(Doc.CurrentUserEmail)) || []; - SetCachedGroups(["Public", ...mygroups?.map(g => StrCast(g.title))]); + SetCachedGroups(["Guest", ...mygroups?.map(g => StrCast(g.title))]); }, { fireImmediately: true }); doc.isSystem ?? (doc.isSystem = true); doc.title ?? (doc.title = Doc.CurrentUserEmail); diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 3f0848d00..b921b3116 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -194,7 +194,7 @@ export class DocumentManager { var containerDocContext = srcContext ? [srcContext, doc] : [doc]; while ( containerDocContext.length && - containerDocContext[0]?.embedContainer && + DocCast(containerDocContext[0]?.embedContainer) && DocCast(containerDocContext[0].embedContainer)?._type_collection !== CollectionViewType.Docking && (includeExistingViews || !DocumentManager.Instance.getDocumentView(containerDocContext[0])) ) { diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 37c813279..407396cb4 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -159,7 +159,7 @@ export class SharingManager extends React.Component<{}> { const target = targetDoc || this.targetDoc!; const acl = `acl-${normalizeEmail(user.email)}`; const docs = SelectionManager.Views().length < 2 ? [target] : SelectionManager.Views().map(docView => docView.rootDoc); - docs.map(doc => (this.layoutDocAcls ? doc : Doc.GetProto(doc))).forEach(doc => { + docs.map(doc => (this.layoutDocAcls || doc.dockingConfig ? doc : Doc.GetProto(doc))).forEach(doc => { distributeAcls(acl, permission as SharingPermissions, doc, undefined, this.overrideNested ? true : undefined); if (permission !== SharingPermissions.None) Doc.AddDocToList(sharingDoc, storage, doc); else GetEffectiveAcl(doc, user.email) === AclPrivate && Doc.RemoveDocFromList(sharingDoc, storage, (doc.createdFrom as Doc) || doc); @@ -176,7 +176,7 @@ export class SharingManager extends React.Component<{}> { const acl = `acl-${normalizeEmail(StrCast(group.title))}`; const docs = SelectionManager.Views().length < 2 ? [target] : SelectionManager.Views().map(docView => docView.rootDoc); - docs.map(doc => (this.layoutDocAcls ? doc : Doc.GetProto(doc))).forEach(doc => { + docs.map(doc => (this.layoutDocAcls || doc.dockingConfig ? doc : Doc.GetProto(doc))).forEach(doc => { distributeAcls(acl, permission as SharingPermissions, doc, undefined, this.overrideNested ? true : undefined); if (group instanceof Doc) { @@ -218,7 +218,7 @@ export class SharingManager extends React.Component<{}> { */ shareFromPropertiesSidebar = undoable((shareWith: string, permission: SharingPermissions, docs: Doc[], layout: boolean) => { if (layout) this.layoutDocAcls = true; - if (shareWith !== 'Public' && shareWith !== 'Override') { + if (shareWith !== 'Guest') { const user = this.users.find(({ user: { email } }) => email === (shareWith === 'Me' ? Doc.CurrentUserEmail : shareWith)); docs.forEach(doc => { if (user) this.setInternalSharing(user, permission, doc); @@ -291,7 +291,6 @@ export class SharingManager extends React.Component<{}> { private sharingOptions(uniform: boolean, override?: boolean) { const dropdownValues: string[] = Object.values(SharingPermissions); if (!uniform) dropdownValues.unshift('-multiple-'); - if (!override) dropdownValues.splice(dropdownValues.indexOf(SharingPermissions.Unset), 1); return dropdownValues.map(permission => ( <option key={permission} value={permission}> {concat(ReverseHierarchyMap.get(permission)?.image, ' ', permission)} @@ -504,7 +503,7 @@ export class SharingManager extends React.Component<{}> { // the list of groups shared with const groupListMap: (Doc | { title: string })[] = groups.filter(({ title }) => (docs.length > 1 ? commonKeys.includes(`acl-${normalizeEmail(StrCast(title))}`) : true)); - groupListMap.unshift({ title: 'Public' }); //, { title: "ALL" }); + groupListMap.unshift({ title: 'Guest' }); //, { title: "ALL" }); const groupListContents = groupListMap.map(group => { let groupKey = `acl-${StrCast(group.title)}`; const uniform = docs.every(doc => doc?.[DocAcl]?.[groupKey] === docs[0]?.[DocAcl]?.[groupKey]); diff --git a/src/client/views/DashboardView.tsx b/src/client/views/DashboardView.tsx index 123090fcf..9b16ecfa7 100644 --- a/src/client/views/DashboardView.tsx +++ b/src/client/views/DashboardView.tsx @@ -1,16 +1,17 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { Button, ColorPicker, FontSize, IconButton, Size } from 'browndash-components'; +import { Button, ColorPicker, Size } from 'browndash-components'; import { action, computed, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; +import { FaPlus } from 'react-icons/fa'; import { Doc, DocListCast, DocListCastAsync } from '../../fields/Doc'; -import { AclPrivate, AclUnset, DocAcl, DocData } from '../../fields/DocSymbols'; +import { AclPrivate, DocAcl } from '../../fields/DocSymbols'; import { Id } from '../../fields/FieldSymbols'; import { List } from '../../fields/List'; import { PrefetchProxy } from '../../fields/Proxy'; import { listSpec } from '../../fields/Schema'; import { ScriptField } from '../../fields/ScriptField'; -import { Cast, DocCast, ImageCast, StrCast } from '../../fields/Types'; +import { Cast, ImageCast, StrCast } from '../../fields/Types'; import { DocServer } from '../DocServer'; import { Docs, DocumentOptions, DocUtils } from '../documents/Documents'; import { CollectionViewType } from '../documents/DocumentTypes'; @@ -25,7 +26,6 @@ import './DashboardView.scss'; import { Colors } from './global/globalEnums'; import { MainViewModal } from './MainViewModal'; import { ButtonType } from './nodes/button/FontIconBox'; -import { FaPlus } from 'react-icons/fa'; enum DashboardGroup { MyDashboards, @@ -167,8 +167,8 @@ export class DashboardView extends React.Component { {this.getDashboards(this.selectedDashboardGroup).map(dashboard => { const href = ImageCast(dashboard.thumb)?.url.href; const shared = Object.keys(dashboard[DocAcl]) - .filter(key => key !== `acl-${Doc.CurrentUserEmailNormalized}` && !['acl-Me', 'acl-Public'].includes(key)) - .some(key => ![AclUnset, AclPrivate].includes(dashboard[DocAcl][key])); + .filter(key => key !== `acl-${Doc.CurrentUserEmailNormalized}` && !['acl-Me', 'acl-Guest'].includes(key)) + .some(key => dashboard[DocAcl][key] !== AclPrivate); return ( <div className="dashboard-container" key={dashboard[Id]} style={{ background: shared ? 'lightgreen' : '' }} onContextMenu={e => this.onContextMenu(dashboard, e)} onClick={e => this.clickDashboard(e, dashboard)}> <img @@ -378,9 +378,6 @@ export class DashboardView extends React.Component { const freeformDoc = Doc.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions); const dashboardDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600 }], { title: title }, id, 'row'); - // switching the tabs from the datadoc to the regular doc - const dashboardTabs = DocListCast(dashboardDoc[DocData].data); - dashboardDoc.data = new List<Doc>(dashboardTabs); dashboardDoc['pane-count'] = 1; Doc.AddDocToList(dashboards, 'data', dashboardDoc); diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 10985c3f1..a41fc8ded 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -190,23 +190,12 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps>() } const added = docs; if (added.length) { - Object.keys(Doc.GetProto(this.rootDoc)[DocAcl]) // apply all collection acls (except pseudo-acl 'Me') to each added doc - .filter(key => key !== 'acl-Me') - .forEach(key => - added.forEach(d => { - const permissionString = StrCast(Doc.GetProto(this.props.Document)[key]); - const permissionSymbol = ReverseHierarchyMap.get(permissionString)?.acl; - const permission = permissionSymbol && HierarchyMapping.get(permissionSymbol)?.name; - distributeAcls(key, permission ?? SharingPermissions.Augment, d, undefined, false); - }) - ); - if ([AclAugment, AclEdit, AclAdmin].includes(effectiveAcl)) { - added.map(doc => { + added.forEach(doc => { doc._dragOnlyWithinContainer = undefined; if (annotationKey ?? this._annotationKeySuffix()) Doc.GetProto(doc).annotationOn = this.rootDoc; Doc.SetContainer(doc, this.rootDoc); - inheritParentAcls(targetDataDoc, doc); + inheritParentAcls(targetDataDoc, doc, true); }); const annoDocs = targetDataDoc[annotationKey ?? this.annotationKey] as List<Doc>; diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 633401d58..2e10bf346 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -308,21 +308,16 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { /** * @returns the options for the permissions dropdown. */ - getPermissionsSelect(user: string, permission: string) { - const dropdownValues: string[] = Object.values(SharingPermissions); + getPermissionsSelect(user: string, permission: string, showGuestOptions: boolean) { + const dropdownValues: string[] = showGuestOptions ? [SharingPermissions.None, SharingPermissions.View] : Object.values(SharingPermissions); if (permission === '-multiple-') dropdownValues.unshift(permission); - if (user !== 'Override') { - dropdownValues.splice(dropdownValues.indexOf(SharingPermissions.Unset), 1); - } return ( <select className="propertiesView-permissions-select" value={permission} onChange={e => this.changePermissions(e, user)}> - {dropdownValues - .filter(permission => !Doc.noviceMode || ![SharingPermissions.View].includes(permission as any)) - .map(permission => ( - <option className="propertiesView-permisssions-select" key={permission} value={permission}> - {concat(ReverseHierarchyMap.get(permission)?.image, ' ', permission)} - </option> - ))} + {dropdownValues.map(permission => ( + <option className="propertiesView-permisssions-select" key={permission} value={permission}> + {concat(ReverseHierarchyMap.get(permission)?.image, ' ', permission)} + </option> + ))} </select> ); } @@ -379,7 +374,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { </div> {/* {name !== "Me" ? this.notifyIcon : null} */} <div className="propertiesView-sharingTable-item-permission"> - {this.colorACLDropDown(name, admin, permission, showExpansionIcon)} + {this.colorACLDropDown(name, admin, permission, false)} {(permission === 'Owner' && name == 'Me') || showExpansionIcon ? this.expansionIcon : null} </div> </div> @@ -389,13 +384,13 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { /** * @returns a colored dropdown bar reflective of the permission */ - colorACLDropDown(name: string, admin: boolean, permission: string, showExpansionIcon?: boolean) { + colorACLDropDown(name: string, admin: boolean, permission: string, showGuestOptions: boolean) { var shareImage = ReverseHierarchyMap.get(permission)?.image; return ( <div> <div className={'propertiesView-shareDropDown'}> <div className={`propertiesView-shareDropDown${permission}`}> - <div className="propertiesView-shareDropDown">{admin && permission !== 'Owner' ? this.getPermissionsSelect(name, permission) : concat(shareImage, ' ', permission)}</div> + <div className="propertiesView-shareDropDown">{admin && permission !== 'Owner' ? this.getPermissionsSelect(name, permission, showGuestOptions) : concat(shareImage, ' ', permission)}</div> </div> </div> </div> @@ -430,15 +425,16 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { const individualTableEntries = []; const usersAdded: string[] = []; // all shared users being added - organized by denormalized email + const seldoc = this.layoutDocAcls || !this.selectedDoc ? this.selectedDoc : Doc.GetProto(this.selectedDoc); // adds each user to usersAdded SharingManager.Instance.users.forEach(eachUser => { var userOnDoc = true; - if (this.selectedDoc) { - if (this.selectedDoc['acl-' + normalizeEmail(eachUser.user.email)] == '' || this.selectedDoc['acl-' + normalizeEmail(eachUser.user.email)] == undefined) { + if (seldoc) { + if (Doc.GetT(seldoc, 'acl-' + normalizeEmail(eachUser.user.email), 'string', true) === '' || Doc.GetT(seldoc, 'acl-' + normalizeEmail(eachUser.user.email), 'string', true) === undefined) { userOnDoc = false; } } - if (userOnDoc && !usersAdded.includes(eachUser.user.email) && eachUser.user.email != 'Public' && eachUser.user.email != target.author) { + if (userOnDoc && !usersAdded.includes(eachUser.user.email) && eachUser.user.email !== 'guest' && eachUser.user.email != target.author) { usersAdded.push(eachUser.user.email); } }); @@ -447,15 +443,16 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { usersAdded.sort(this.sortUsers); usersAdded.map(userEmail => { const userKey = `acl-${normalizeEmail(userEmail)}`; - var permission = StrCast(target[userKey]); + var aclField = Doc.GetT(this.layoutDocAcls ? target : Doc.GetProto(target), userKey, 'string', true); + var permission = StrCast(aclField); individualTableEntries.unshift(this.sharingItem(userEmail, showAdmin, permission!, false)); // adds each user }); // adds current user var userEmail = Doc.CurrentUserEmail; + if (userEmail == 'guest') userEmail = 'Guest'; const userKey = `acl-${normalizeEmail(userEmail)}`; - if (userEmail == 'guest') userEmail = 'Public'; - if (!usersAdded.includes(userEmail) && userEmail != 'Public' && userEmail != target.author) { + if (!usersAdded.includes(userEmail) && userEmail !== 'Guest' && userEmail != target.author) { var permission; if (this.layoutDocAcls) { if (target[DocAcl][userKey]) permission = HierarchyMapping.get(target[DocAcl][userKey])?.name; @@ -473,7 +470,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { const groupList = GroupManager.Instance?.allGroups || []; groupList.sort(this.sortGroups); groupList.map(group => { - if (group.title != 'Public' && this.selectedDoc) { + if (group.title != 'Guest' && this.selectedDoc) { const groupKey = 'acl-' + normalizeEmail(StrCast(group.title)); if (this.selectedDoc[groupKey] != '' && this.selectedDoc[groupKey] != undefined) { var permission; @@ -489,17 +486,11 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { }); // public permission - const publicPermission = StrCast((this.layoutDocAcls ? target : Doc.GetProto(target))['acl-Public']); + const publicPermission = StrCast((this.layoutDocAcls ? target : Doc.GetProto(target))['acl-Guest']); return ( <div> <br /> - Public / Guest Users - <div>{this.colorACLDropDown('Public', showAdmin, publicPermission!, false)}</div> - <div> - {' '} - <br></br> Individual Users with Access to this Document{' '} - </div> <div className="propertiesView-sharingTable">{<div> {individualTableEntries}</div>}</div> {groupTableEntries.length > 0 ? ( <div> @@ -510,6 +501,12 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { <div className="propertiesView-sharingTable">{<div> {groupTableEntries}</div>}</div> </div> ) : null} + Guest + <div>{this.colorACLDropDown('Guest', true, publicPermission!, true)}</div> + <div> + {' '} + <br></br> Individual Users with Access to this Document{' '} + </div> </div> ); } diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 13d3b2cdc..8d1b46ebb 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -517,7 +517,7 @@ export class CollectionDockingView extends CollectionSubView() { _layout_fitWidth: true, title: `Untitled Tab ${NumCast(dashboard['pane-count'])}`, }); - inheritParentAcls(this.rootDoc, docToAdd); + inheritParentAcls(this.rootDoc, docToAdd, false); CollectionDockingView.AddSplit(docToAdd, OpenWhereMod.none, stack); } }); @@ -560,7 +560,7 @@ export class CollectionDockingView extends CollectionSubView() { _freeform_backgroundGrid: true, title: `Untitled Tab ${NumCast(dashboard['pane-count'])}`, }); - inheritParentAcls(this.dataDoc, Doc.GetProto(docToAdd)); + inheritParentAcls(this.dataDoc, docToAdd, false); CollectionDockingView.AddSplit(docToAdd, OpenWhereMod.none, stack); } }) diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 764b1e08a..e2718b52d 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -9,7 +9,7 @@ import { RichTextField } from '../../../../fields/RichTextField'; import { SchemaHeaderField } from '../../../../fields/SchemaHeaderField'; import { Cast, DocCast, FieldValue, NumCast, StrCast } from '../../../../fields/Types'; import { ImageField } from '../../../../fields/URLField'; -import { GetEffectiveAcl, SharingPermissions } from '../../../../fields/util'; +import { distributeAcls, GetEffectiveAcl, SharingPermissions } from '../../../../fields/util'; import { intersectRect, returnFalse, Utils } from '../../../../Utils'; import { CognitiveServices } from '../../../cognitive_services/CognitiveServices'; import { Docs, DocumentOptions, DocUtils } from '../../../documents/Documents'; @@ -390,11 +390,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque newCollection.x = this.Bounds.left; newCollection.y = this.Bounds.top; newCollection.layout_fitWidth = true; - newCollection['acl-Public'] = Doc.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Augment; - selected.forEach(d => { - Doc.SetContainer(d, newCollection); - d['acl-Public'] = Doc.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Augment; - }); + selected.forEach(d => Doc.SetContainer(d, newCollection)); this.hideMarquee(); return newCollection; }); diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx index 5bba51ec8..a0b0caf98 100644 --- a/src/client/views/nodes/button/FontIconBox.tsx +++ b/src/client/views/nodes/button/FontIconBox.tsx @@ -597,7 +597,7 @@ ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: b if (contentFrameNumber !== undefined) { CollectionFreeFormDocumentView.setStringValues(contentFrameNumber, dv.rootDoc, { fieldKey: color }); } else { - dv.rootDoc['_' + fieldKey] = color; + dv.dataDoc[fieldKey] = color; } }); } else { diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index d13c09443..ab9eebd78 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -222,7 +222,7 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() { 'width', 'layout_autoHeight', 'acl-Override', - 'acl-Public', + 'acl-Guest', 'embedContainer', 'zIndex', 'height', diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 698e09915..6121668e3 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -20,7 +20,6 @@ import { AclEdit, AclPrivate, AclReadonly, - AclUnset, Animation, CachedUpdates, DirectLinks, @@ -134,7 +133,6 @@ export const HierarchyMapping: Map<symbol, { level:aclLevel; name: SharingPermis [AclAugment, { level: aclLevel.augmentable, name: SharingPermissions.Augment, image: '⬟' }], [AclEdit, { level: aclLevel.editable, name: SharingPermissions.Edit, image: '⬢' }], [AclAdmin, { level: aclLevel.admin, name: SharingPermissions.Admin, image: '⬢' }], - [AclUnset, { level: aclLevel.unset, name: SharingPermissions.Unset, image: '▲' }], ]); export const ReverseHierarchyMap: Map<string, { level: aclLevel; acl: symbol; image: string }> = new Map(Array.from(HierarchyMapping.entries()).map(value => [value[1].name, { level: value[1].level, acl: value[0], image: value[1].image }])); @@ -380,7 +378,8 @@ export class Doc extends RefField { return self.resolvedDataDoc && !self.isTemplateForField ? self : Doc.GetProto(Cast(Doc.Layout(self).resolvedDataDoc, Doc, null) || self); } @computed get __LAYOUT__(): Doc | undefined { - const templateLayoutDoc = Cast(Doc.LayoutField(this[SelfProxy]), Doc, null); + const self = this[SelfProxy]; + const templateLayoutDoc = Cast(Doc.LayoutField(self), Doc, null); if (templateLayoutDoc) { let renderFieldKey: any; const layoutField = templateLayoutDoc[StrCast(templateLayoutDoc.layout_fieldKey, 'layout')]; @@ -389,7 +388,7 @@ export class Doc extends RefField { } else { return Cast(layoutField, Doc, null); } - return Cast(this[SelfProxy][renderFieldKey + '-layout[' + templateLayoutDoc[Id] + ']'], Doc, null) || templateLayoutDoc; + return Cast(self[renderFieldKey + '-layout[' + templateLayoutDoc[Id] + ']'], Doc, null) || templateLayoutDoc; } return undefined; } @@ -480,11 +479,6 @@ export namespace Doc { export function SetContainer(doc: Doc, container: Doc) { doc.embedContainer = container; - if (Doc.GetProto(container).author === doc.author) { - Object.keys(Doc.GetProto(container)) - .filter(key => key.startsWith('acl') && !key.includes(Doc.CurrentUserEmailNormalized)) - .forEach(key => (doc[key] = Doc.GetProto(container)[key])); - } } export function RunCachedUpdate(doc: Doc, field: string) { const update = doc[CachedUpdates][field]; @@ -697,7 +691,7 @@ export namespace Doc { Doc.SetLayout(embedding, Doc.MakeEmbedding(layout)); } embedding.createdFrom = doc; - embedding.proto_embeddingId = Doc.GetProto(doc).proto_embeddingId = DocListCast(Doc.GetProto(doc).proto_embeddings).length + 1; + embedding.proto_embeddingId = Doc.GetProto(doc).proto_embeddingId = DocListCast(Doc.GetProto(doc).proto_embeddings).length - 1; embedding.title = ComputedField.MakeFunction(`renameEmbedding(this)`); embedding.author = Doc.CurrentUserEmail; @@ -1027,7 +1021,6 @@ export namespace Doc { Doc.AddDocToList(Doc.GetProto(copy)[DocData], 'proto_embeddings', copy); } copy.embedContainer = undefined; - Doc.defaultAclPrivate && (copy['acl-Public'] = 'Not Shared'); if (retitle) { copy.title = incrementTitleCopy(StrCast(copy.title)); } @@ -1087,7 +1080,6 @@ export namespace Doc { const applied = ApplyTemplateTo(templateDoc, target, targetKey, templateDoc.title + '(...' + _applyCount++ + ')'); target.layout_fieldKey = targetKey; applied && (Doc.GetProto(applied).type = templateDoc.type); - Doc.defaultAclPrivate && (applied['acl-Public'] = 'Not Shared'); return applied; } return undefined; diff --git a/src/fields/DocSymbols.ts b/src/fields/DocSymbols.ts index eab26ed10..66d1ab094 100644 --- a/src/fields/DocSymbols.ts +++ b/src/fields/DocSymbols.ts @@ -13,7 +13,6 @@ export const DocFields = Symbol('DocFields'); export const DocCss = Symbol('DocCss'); export const DocAcl = Symbol('DocAcl'); export const DirectLinks = Symbol('DocDirectLinks'); -export const AclUnset = Symbol('DocAclUnset'); export const AclPrivate = Symbol('DocAclOwnerOnly'); export const AclReadonly = Symbol('DocAclReadOnly'); export const AclAugment = Symbol('DocAclAugment'); diff --git a/src/fields/util.ts b/src/fields/util.ts index 034229319..e89cb1fb1 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -131,17 +131,19 @@ export function denormalizeEmail(email: string) { /** * Copies parent's acl fields to the child */ -export function inheritParentAcls(parent: Doc, child: Doc) { +export function inheritParentAcls(parent: Doc, child: Doc, layoutOnly: boolean) { if (GetEffectiveAcl(parent) !== AclAdmin) return; - for (const key of Object.keys(parent)) { - // if the default acl mode is private, then don't inherit the acl-Public permission, but set it to private. - // const permission: string = key === 'acl-Public' && Doc.defaultAclPrivate ? AclPrivate : parent[key]; - const symbol = ReverseHierarchyMap.get(StrCast(parent[key])); - if (symbol) { - const sharePermission = HierarchyMapping.get(symbol.acl!)!.name; - key.startsWith('acl') && distributeAcls(key, sharePermission, child); - } - } + Object.keys(parent) + .filter(key => key.startsWith('acl')) + .forEach(key => { + // if the default acl mode is private, then don't inherit the acl-guest permission, but set it to private. + // const permission: string = key === 'acl-guest' && Doc.defaultAclPrivate ? AclPrivate : parent[key]; + const parAcl = ReverseHierarchyMap.get(StrCast(parent[key]))?.acl; + if (parAcl) { + const sharePermission = HierarchyMapping.get(parAcl)?.name; + sharePermission && distributeAcls(key, sharePermission, child, undefined, false, layoutOnly); + } + }); } /** @@ -160,7 +162,6 @@ export function inheritParentAcls(parent: Doc, child: Doc) { * Unset: Remove a sharing permission (eg., used ) */ export enum SharingPermissions { - Unset = 'None', Admin = 'Admin', Edit = 'Edit', Augment = 'Augment', @@ -233,7 +234,7 @@ function getEffectiveAcl(target: any, user?: string): symbol { * @param allowUpgrade whether permissions can be made less restrictive * inheritingFromCollection is not currently being used but could be used if acl assignment defaults change */ -export function distributeAcls(key: string, acl: SharingPermissions, target: Doc, visited?: Doc[], allowUpgrade?: boolean) { +export function distributeAcls(key: string, acl: SharingPermissions, target: Doc, visited?: Doc[], allowUpgrade?: boolean, layoutOnly = false) { const selfKey = `acl-${Doc.CurrentUserEmailNormalized}`; if (!visited) visited = [] as Doc[]; if (!target || visited.includes(target) || key === selfKey) return; @@ -243,19 +244,19 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc const dataDoc = target[DocData]; const curVal = ReverseHierarchyMap.get(StrCast(dataDoc[key]))?.level ?? 0; const aclVal = ReverseHierarchyMap.get(acl)?.level ?? 0; - if (dataDoc && (allowUpgrade !== false|| !dataDoc[key] || curVal > aclVal)) { + if (!layoutOnly && dataDoc && (allowUpgrade !== false || !dataDoc[key] || curVal > aclVal)) { // propagate ACLs to links, children, and annotations - LinkManager.Links(dataDoc).forEach(link => distributeAcls(key, acl, link, visited, allowUpgrade? true: false)); + LinkManager.Links(dataDoc).forEach(link => distributeAcls(key, acl, link, visited, allowUpgrade ? true : false)); DocListCast(dataDoc[Doc.LayoutFieldKey(dataDoc)]).forEach(d => { - distributeAcls(key, acl, d, visited, allowUpgrade ? true: false); - d !== d[DocData] && distributeAcls(key, acl, d[DocData], visited, allowUpgrade ? true: false); + distributeAcls(key, acl, d, visited, allowUpgrade ? true : false); + d !== d[DocData] && distributeAcls(key, acl, d[DocData], visited, allowUpgrade ? true : false); }); DocListCast(dataDoc[Doc.LayoutFieldKey(dataDoc) + '_annotations']).forEach(d => { - distributeAcls(key, acl, d, visited, allowUpgrade? true: false); - d !== d[DocData] && distributeAcls(key, acl, d[DocData], visited, allowUpgrade? true: false); + distributeAcls(key, acl, d, visited, allowUpgrade ? true : false); + d !== d[DocData] && distributeAcls(key, acl, d[DocData], visited, allowUpgrade ? true : false); }); if (GetEffectiveAcl(dataDoc) === AclAdmin) { @@ -266,7 +267,7 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc let layoutDocChanged = false; // determines whether fetchProto should be called or not (i.e. is there a change that should be reflected in target[AclSym]) // if it is inheriting from a collection, it only inherits if A) allowUpgrade is set B) the key doesn't already exist or c) the right being inherited is more restrictive - if (GetEffectiveAcl(target) === AclAdmin && (allowUpgrade || !target[key] || ReverseHierarchyMap.get(StrCast(target[key]))!.level > ReverseHierarchyMap.get(acl)!.level)) { + if (GetEffectiveAcl(target) === AclAdmin && (allowUpgrade || !Doc.GetT(target, key, 'boolean', true) || ReverseHierarchyMap.get(StrCast(target[key]))!.level > aclVal)) { target[key] = acl; layoutDocChanged = true; } |