aboutsummaryrefslogtreecommitdiff
path: root/src/client/util/SharingManager.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/util/SharingManager.tsx')
-rw-r--r--src/client/util/SharingManager.tsx203
1 files changed, 41 insertions, 162 deletions
diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx
index 64b2bb5b8..d3241009a 100644
--- a/src/client/util/SharingManager.tsx
+++ b/src/client/util/SharingManager.tsx
@@ -6,10 +6,9 @@ import * as React from 'react';
import Select from 'react-select';
import * as RequestPromise from 'request-promise';
import { Doc, DocListCast, DocListCastAsync, HierarchyMapping, ReverseHierarchyMap } from '../../fields/Doc';
-import { AclAdmin, AclPrivate, AclUnset, DocAcl, DocData } from '../../fields/DocSymbols';
+import { AclAdmin, AclPrivate, DocAcl, DocData } from '../../fields/DocSymbols';
import { Id } from '../../fields/FieldSymbols';
-import { List } from '../../fields/List';
-import { DocCast, NumCast, StrCast } from '../../fields/Types';
+import { StrCast } from '../../fields/Types';
import { distributeAcls, GetEffectiveAcl, normalizeEmail, SharingPermissions, TraceMobx } from '../../fields/util';
import { Utils } from '../../Utils';
import { DocServer } from '../DocServer';
@@ -73,13 +72,11 @@ export class SharingManager extends React.Component<{}> {
@observable private individualSort: 'ascending' | 'descending' | 'none' = 'none'; // sorting options for the list of individuals
@observable private groupSort: 'ascending' | 'descending' | 'none' = 'none'; // sorting options for the list of groups
private shareDocumentButtonRef: React.RefObject<HTMLButtonElement> = React.createRef(); // ref for the share button, used for the position of the popup
- private distributeAclsButtonRef: React.RefObject<HTMLButtonElement> = React.createRef(); // ref for the distribute button, used for the position of the popup
// if both showUserOptions and showGroupOptions are false then both are displayed
@observable private showUserOptions: boolean = false; // whether to show individuals as options when sharing (in the react-select component)
@observable private showGroupOptions: boolean = false; // // whether to show groups as options when sharing (in the react-select component)
private populating: boolean = false; // whether the list of users is populating or not
@observable private layoutDocAcls: boolean = false; // whether the layout doc or data doc's acls are to be used
- @observable private overrideNested: boolean = false; // whether child docs in a collection/dashboard should be changed to be less private
@observable private myDocAcls: boolean = false; // whether the My Docs checkbox is selected or not
// private get linkVisible() {
@@ -110,7 +107,6 @@ export class SharingManager extends React.Component<{}> {
500
);
this.layoutDocAcls = false;
- this.overrideNested = false;
});
constructor(props: {}) {
@@ -153,41 +149,19 @@ export class SharingManager extends React.Component<{}> {
/**
* Shares the document with a user.
*/
- setInternalSharing = (recipient: ValidatedUser, permission: string, targetDoc?: Doc) => {
+ setInternalSharing = (recipient: ValidatedUser, permission: string, targetDoc: Doc | undefined) => {
const { user, sharingDoc } = recipient;
const target = targetDoc || this.targetDoc!;
const acl = `acl-${normalizeEmail(user.email)}`;
const myAcl = `acl-${Doc.CurrentUserEmailNormalized}`;
- const isDashboard = DocListCast(Doc.MyDashboards.data).indexOf(target) !== -1;
-
- // setting the same acl for a docs within the doc being shared if they haven't been set yet
- // or if the 'Override Nested' checkbox is selected
- var childDocs = DocListCast(target.data);
- childDocs.map(doc => {
- if (this.overrideNested || doc[acl] == undefined) {
- this.setInternalSharing(recipient, permission, doc);
- }
- });
-
- const docs = SelectionManager.Views().length < 2 ? [target] : SelectionManager.Views().map(docView => docView.props.Document);
-
- // ! ensures it returns true if document has been shared successfully, false otherwise
- return !docs
- .map(doc => (this.layoutDocAcls ? doc : Doc.GetProto(doc)))
- .map(doc => {
- doc.author === Doc.CurrentUserEmail && !doc[myAcl] && distributeAcls(myAcl, SharingPermissions.Admin, doc, undefined, undefined, isDashboard);
+ const docs = SelectionManager.Views().length < 2 ? [target] : SelectionManager.Views().map(docView => docView.rootDoc);
+ docs.map(doc => (this.layoutDocAcls ? doc : Doc.GetProto(doc))).forEach(doc => {
+ doc.author === Doc.CurrentUserEmail && !doc[myAcl] && distributeAcls(myAcl, SharingPermissions.Admin, doc, undefined, undefined);
- if (permission === SharingPermissions.None) {
- if (doc[acl] && doc[acl] !== SharingPermissions.None) doc.numUsersShared = NumCast(doc.numUsersShared, 1) - 1;
- } else {
- if (!doc[acl] || doc[acl] === SharingPermissions.None) doc.numUsersShared = NumCast(doc.numUsersShared, 0) + 1;
- }
- distributeAcls(acl, permission as SharingPermissions, doc, undefined, undefined, isDashboard);
- this.setDashboardBackground(doc, permission as SharingPermissions);
- if (permission !== SharingPermissions.None) return Doc.AddDocToList(sharingDoc, storage, doc);
- return GetEffectiveAcl(doc, user.email) === AclPrivate && Doc.RemoveDocFromList(sharingDoc, storage, (doc.createdFrom as Doc) || doc);
- })
- .some(success => !success);
+ distributeAcls(acl, permission as SharingPermissions, doc, undefined, 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);
+ });
};
/**
@@ -199,51 +173,24 @@ export class SharingManager extends React.Component<{}> {
const target = targetDoc || this.targetDoc!;
const key = normalizeEmail(StrCast(group.title));
let acl = `acl-${key}`;
- const isDashboard = DocListCast(Doc.MyDashboards.data).indexOf(target) !== -1;
-
- // setting the same acl for a docs within the doc being shared if they haven't been set yet
- // or if the 'Override Private' checkbox is selected
- var childDocs = DocListCast(target.data);
- childDocs.map(doc => {
- if (this.overrideNested || doc[acl] == undefined) {
- this.setInternalGroupSharing(group, permission, doc);
- }
- });
-
- const docs = SelectionManager.Views().length < 2 ? [target] : SelectionManager.Views().map(docView => docView.props.Document);
-
- if (acl == 'acl-Public' && this.layoutDocAcls) acl = 'acl-Public-layout';
- // ! ensures it returns true if document has been shared successfully, false otherwise
- return !docs
- .map(doc => (this.layoutDocAcls ? doc : doc[DocData]))
- .map(doc => {
- doc.author === Doc.CurrentUserEmail && !doc[`acl-${Doc.CurrentUserEmailNormalized}`] && distributeAcls(`acl-${Doc.CurrentUserEmailNormalized}`, SharingPermissions.Admin, doc, undefined, undefined, isDashboard);
-
- if (permission === SharingPermissions.None) {
- if (doc[acl] && doc[acl] !== SharingPermissions.None) doc.numGroupsShared = NumCast(doc.numGroupsShared, 1) - 1;
- } else {
- if (!doc[acl] || doc[acl] === SharingPermissions.None) doc.numGroupsShared = NumCast(doc.numGroupsShared, 0) + 1;
- }
- distributeAcls(acl, permission as SharingPermissions, doc, undefined, undefined, isDashboard);
- this.setDashboardBackground(doc, permission as SharingPermissions);
+ const docs = SelectionManager.Views().length < 2 ? [target] : SelectionManager.Views().map(docView => docView.rootDoc);
+ docs.map(doc => (this.layoutDocAcls ? doc : Doc.GetProto(doc))).forEach(doc => {
+ doc.author === Doc.CurrentUserEmail && !doc[`acl-${Doc.CurrentUserEmailNormalized}`] && distributeAcls(`acl-${Doc.CurrentUserEmailNormalized}`, SharingPermissions.Admin, doc, undefined, undefined);
- if (group instanceof Doc) {
- const members: string[] = JSON.parse(StrCast(group.members));
- const users: ValidatedUser[] = this.users.filter(({ user: { email } }) => members.includes(email));
+ distributeAcls(acl, permission as SharingPermissions, doc, undefined, undefined);
- // if documents have been shared, add the doc to that list if it doesn't already exist, otherwise create a new list with the doc
- group.docsShared ? Doc.IndexOf(doc, DocListCast(group.docsShared)) === -1 && (group.docsShared as List<Doc>).push(doc) : (group.docsShared = new List<Doc>([doc]));
+ if (group instanceof Doc) {
+ Doc.AddDocToList(group, 'docsShared', doc);
- return users
- .map(({ user, sharingDoc }) => {
- if (permission !== SharingPermissions.None) return Doc.AddDocToList(sharingDoc, storage, doc); // add the doc to the sharingDoc if it hasn't already been added
- else return GetEffectiveAcl(doc, user.email) === AclPrivate && Doc.RemoveDocFromList(sharingDoc, storage, (doc.createdFrom as Doc) || doc); // remove the doc from the list if it already exists
- })
- .some(success => !success);
- }
- })
- .some(success => success);
+ this.users
+ .filter(({ user: { email } }) => JSON.parse(StrCast(group.members)).includes(email))
+ .forEach(({ user, sharingDoc }) => {
+ if (permission !== SharingPermissions.None) Doc.AddDocToList(sharingDoc, storage, doc); // add the doc to the sharingDoc if it hasn't already been added
+ else GetEffectiveAcl(doc, user.email) === AclPrivate && Doc.RemoveDocFromList(sharingDoc, storage, (doc.createdFrom as Doc) || doc); // remove the doc from the list if it already exists
+ });
+ }
+ });
};
/**
@@ -279,45 +226,16 @@ export class SharingManager extends React.Component<{}> {
else this.setInternalGroupSharing(GroupManager.Instance.getGroup(shareWith)!, permission, doc);
});
} else {
- const dashboards = DocListCast(Doc.MyDashboards.data);
docs.forEach(doc => {
- const isDashboard = dashboards.indexOf(doc) !== -1;
- if (this.overrideNested) {
- this.shareFromPropertiesSidebar(shareWith, permission, DocListCast(doc.data), layout);
- }
if (GetEffectiveAcl(doc) === AclAdmin) {
- if (shareWith == 'Public' && layout) shareWith = 'Public-layout';
- distributeAcls(`acl-${shareWith}`, permission, doc, undefined, undefined, isDashboard);
+ distributeAcls(`acl-${shareWith}`, permission, doc, undefined, undefined);
}
- this.setDashboardBackground(doc, permission as SharingPermissions);
});
}
this.layoutDocAcls = false;
};
/**
- * Sets the background of the Dashboard if it has been shared as a visual indicator
- */
- setDashboardBackground = (doc: Doc, permission: SharingPermissions) => {
- if (Doc.IndexOf(doc, DocListCast(Doc.MyDashboards.data)) !== -1) {
- if (permission !== SharingPermissions.None) {
- doc.isShared = true;
- doc.backgroundColor = 'green';
- } else {
- const acls = doc[DocData][DocAcl];
- if (
- Object.keys(acls)
- .filter(key => key !== `acl-${Doc.CurrentUserEmailNormalized}` && key !== 'acl-Me')
- .every(key => [AclUnset, AclPrivate].includes(acls[key]))
- ) {
- doc.isShared = undefined;
- doc.backgroundColor = undefined;
- }
- }
- }
- };
-
- /**
* Removes the documents shared with a user through a group when the user is removed from the group.
* @param group
* @param emailId
@@ -341,12 +259,9 @@ export class SharingManager extends React.Component<{}> {
*/
removeGroup = (group: Doc) => {
if (group.docsShared) {
- const dashboards = DocListCast(Doc.MyDashboards.data);
DocListCast(group.docsShared).forEach(doc => {
const acl = `acl-${StrCast(group.title)}`;
- const isDashboard = dashboards.indexOf(doc) !== -1;
- distributeAcls(acl, SharingPermissions.None, doc, undefined, undefined, isDashboard);
- distributeAcls(acl, SharingPermissions.None, Doc.GetProto(doc), undefined, undefined, isDashboard);
+ distributeAcls(acl, SharingPermissions.None, doc, undefined, undefined);
const members: string[] = JSON.parse(StrCast(group.members));
const users: ValidatedUser[] = this.users.filter(({ user: { email } }) => members.includes(email));
@@ -440,7 +355,7 @@ export class SharingManager extends React.Component<{}> {
if (this.selectedUsers) {
this.selectedUsers.forEach(user => {
if (user.value.includes(indType)) {
- this.setInternalSharing(this.users.find(u => u.user.email === user.label)!, this.permissions);
+ this.setInternalSharing(this.users.find(u => u.user.email === user.label)!, this.permissions, undefined);
} else {
this.setInternalGroupSharing(GroupManager.Instance.getGroup(user.label)!, this.permissions);
}
@@ -457,7 +372,6 @@ export class SharingManager extends React.Component<{}> {
);
this.layoutDocAcls = false;
- this.overrideNested = false;
this.selectedUsers = null;
}
};
@@ -509,8 +423,7 @@ export class SharingManager extends React.Component<{}> {
const users = this.individualSort === 'ascending' ? this.users.slice().sort(this.sortUsers) : this.individualSort === 'descending' ? this.users.slice().sort(this.sortUsers).reverse() : this.users;
const groups = this.groupSort === 'ascending' ? groupList.slice().sort(this.sortGroups) : this.groupSort === 'descending' ? groupList.slice().sort(this.sortGroups).reverse() : groupList;
- // handles the case where multiple documents are selected
- let docs = SelectionManager.Views().length < 2 ? [this.layoutDocAcls ? this.targetDoc : this.targetDoc?.[DocData]] : SelectionManager.Views().map(docView => (this.layoutDocAcls ? docView.props.Document : docView.props.Document?.[DocData]));
+ let docs = SelectionManager.Views().length < 2 ? [this.targetDoc] : SelectionManager.Views().map(docView => docView.rootDoc);
if (this.myDocAcls) {
const newDocs: Doc[] = [];
@@ -518,36 +431,32 @@ export class SharingManager extends React.Component<{}> {
docs = newDocs.filter(doc => GetEffectiveAcl(doc) === AclAdmin);
}
- const targetDoc: Doc = this.layoutDocAcls ? docs[0] : docs[0]?.[DocData];
+ const targetDoc = this.layoutDocAcls ? docs[0] : docs[0]?.[DocData];
// tslint:disable-next-line: no-unnecessary-callback-wrapper
const effectiveAcls = docs.map(doc => GetEffectiveAcl(doc));
const admin = this.myDocAcls ? Boolean(docs.length) : effectiveAcls.every(acl => acl === AclAdmin);
// users in common between all docs
- const commonKeys = intersection(...docs.map(doc => (this.layoutDocAcls ? doc : doc[DocData])).map(doc => doc?.[DocAcl] && Object.keys(doc[DocAcl])));
+ const commonKeys = intersection(docs).reduce((list, doc) => (doc?.[DocAcl] ? [...list, ...Object.keys(doc[DocAcl])] : list), [] as string[]);
// the list of users shared with
- const userListContents: (JSX.Element | null)[] = users
+ const userListContents = users
// .filter(({ user }) => (docs.length > 1 ? commonKeys.includes(`acl-${normalizeEmail(user.email)}`) : docs[0]?.author !== user.email))
.filter(({ user }) => docs[0]?.author !== user.email)
.map(({ user, linkDatabase, sharingDoc, userColor }) => {
const userKey = `acl-${normalizeEmail(user.email)}`;
- const uniform = docs.map(doc => (this.layoutDocAcls ? doc : doc[DocData])).every(doc => doc?.[DocAcl]?.[userKey] === docs[0]?.[DocAcl]?.[userKey]);
+ const uniform = docs.every(doc => doc?.[DocAcl]?.[userKey] === docs[0]?.[DocAcl]?.[userKey]);
// const permissions = uniform ? StrCast(targetDoc?.[userKey]) : '-multiple-';
- let permissions = this.layoutDocAcls ? (targetDoc[DocAcl][userKey] ? HierarchyMapping.get(targetDoc[DocAcl][userKey])?.name : StrCast(Doc.GetProto(targetDoc)[userKey])) : StrCast(targetDoc[userKey]);
- if (this.layoutDocAcls) {
- if (targetDoc[DocAcl][userKey]) permissions = HierarchyMapping.get(targetDoc[DocAcl][userKey])?.name;
- else if (targetDoc['embedContainer']) permissions = StrCast(Doc.GetProto(DocCast(targetDoc['embedContainer']))[userKey]);
- else permissions = uniform ? StrCast(Doc.GetProto(targetDoc)?.[userKey]) : '-multiple-';
- } else permissions = uniform ? StrCast(targetDoc?.[userKey]) : '-multiple-';
+ let permissions = targetDoc[DocAcl][userKey] ? HierarchyMapping.get(targetDoc[DocAcl][userKey])?.name : StrCast(targetDoc[userKey]);
+ permissions = uniform ? StrCast(targetDoc?.[userKey]) : '-multiple-';
return !permissions ? null : (
<div key={userKey} className={'container'}>
<span className={'padding'}>{user.email}</span>
<div className="edit-actions">
{admin || this.myDocAcls ? (
- <select className={`permissions-dropdown-${permissions}`} value={permissions} onChange={e => this.setInternalSharing({ user, linkDatabase, sharingDoc, userColor }, e.currentTarget.value)}>
+ <select className={`permissions-dropdown-${permissions}`} value={permissions} onChange={e => this.setInternalSharing({ user, linkDatabase, sharingDoc, userColor }, e.currentTarget.value, undefined)}>
{this.sharingOptions(uniform)}
</select>
) : (
@@ -566,12 +475,7 @@ export class SharingManager extends React.Component<{}> {
// the owner of the doc and the current user are placed at the top of the user list.
const userKey = `acl-${normalizeEmail(Doc.CurrentUserEmail)}`;
- var curUserPermission;
- if (this.layoutDocAcls) {
- if (targetDoc[DocAcl][userKey]) curUserPermission = HierarchyMapping.get(targetDoc[DocAcl][userKey])?.name;
- else if (targetDoc['embedContainer']) curUserPermission = StrCast(Doc.GetProto(DocCast(targetDoc['embedContainer']))[userKey]);
- else curUserPermission = StrCast(Doc.GetProto(targetDoc)?.[userKey]);
- } else curUserPermission = StrCast(targetDoc[userKey]);
+ const curUserPermission = StrCast(targetDoc[userKey]);
// const curUserPermission = HierarchyMapping.get(effectiveAcls[0])!.name
userListContents.unshift(
sameAuthor ? (
@@ -600,20 +504,8 @@ export class SharingManager extends React.Component<{}> {
groupListMap.unshift({ title: 'Public' }); //, { title: "ALL" });
const groupListContents = groupListMap.map(group => {
let groupKey = `acl-${StrCast(group.title)}`;
- const uniform = docs
- .map(doc => (this.layoutDocAcls ? doc : doc[DocData]))
- .every(doc => (this.layoutDocAcls ? doc?.[DocAcl]?.[groupKey] === docs[0]?.[DocAcl]?.[groupKey] : doc?.[DocData]?.[DocAcl]?.[groupKey] === docs[0]?.[DocData]?.[DocAcl]?.[groupKey]));
- // const permissions = uniform ? StrCast(targetDoc?.[`acl-${StrCast(group.title)}`]) : '-multiple-';
- let permissions = this.layoutDocAcls ? (targetDoc[DocAcl][groupKey] ? HierarchyMapping.get(targetDoc[DocAcl][groupKey])?.name : StrCast(Doc.GetProto(targetDoc)[groupKey])) : StrCast(targetDoc[groupKey]);
- if (this.layoutDocAcls) {
- if (groupKey == 'acl-Public') groupKey = 'acl-Public-layout';
- if (targetDoc[DocAcl][groupKey]) permissions = HierarchyMapping.get(targetDoc[DocAcl][groupKey])?.name;
- else {
- if (groupKey == 'acl-Public-layout') groupKey = 'acl-Public';
- if (targetDoc['embedContainer']) permissions = StrCast(Doc.GetProto(DocCast(targetDoc['embedContainer']))[groupKey]);
- else permissions = uniform ? StrCast(Doc.GetProto(targetDoc)?.[groupKey]) : '-multiple-';
- }
- } else permissions = uniform ? StrCast(targetDoc?.[groupKey]) : '-multiple-';
+ const uniform = docs.every(doc => doc?.[DocAcl]?.[groupKey] === docs[0]?.[DocAcl]?.[groupKey]);
+ const permissions = uniform ? StrCast(targetDoc?.[groupKey]) : '-multiple-';
return !permissions ? null : (
<div key={groupKey} className={'container'}>
@@ -693,7 +585,6 @@ export class SharingManager extends React.Component<{}> {
<div className="acl-container">
{Doc.noviceMode ? null : (
<div className="layoutDoc-acls">
- <input type="checkbox" onChange={action(() => (this.overrideNested = !this.overrideNested))} checked={this.overrideNested} /> <label>Override Nested </label>
<input type="checkbox" onChange={action(() => (this.layoutDocAcls = !this.layoutDocAcls))} checked={this.layoutDocAcls} /> <label>Layout</label>
</div>
)}
@@ -713,16 +604,10 @@ export class SharingManager extends React.Component<{}> {
<div className="user-sort" onClick={action(() => (this.individualSort = this.individualSort === 'ascending' ? 'descending' : this.individualSort === 'descending' ? 'none' : 'ascending'))}>
<div className="title-individual">
Individuals &nbsp;
- {this.individualSort === 'ascending' ? (
- <FontAwesomeIcon icon={'caret-up'} size={'xs'} />
- ) : this.individualSort === 'descending' ? (
- <FontAwesomeIcon icon={'caret-down'} size={'xs'} />
- ) : (
- <FontAwesomeIcon icon={'caret-right'} size={'xs'} />
- )}
+ <FontAwesomeIcon icon={this.individualSort === 'ascending' ? 'caret-up' : this.individualSort === 'descending' ? 'caret-down' : 'caret-right'} size="xs" />
</div>
</div>
- <div className={'users-list'}>{userListContents}</div>
+ <div className="users-list">{userListContents}</div>
</div>
<div className={'group-container'}>
<div className="user-sort" onClick={action(() => (this.groupSort = this.groupSort === 'ascending' ? 'descending' : this.groupSort === 'descending' ? 'none' : 'ascending'))}>
@@ -732,13 +617,7 @@ export class SharingManager extends React.Component<{}> {
<FontAwesomeIcon icon={'info-circle'} color={'#e8e8e8'} size={'sm'} style={{ backgroundColor: '#1e89d7', borderRadius: '100%', border: '1px solid #1e89d7' }} />
</div>
&nbsp;
- {this.groupSort === 'ascending' ? (
- <FontAwesomeIcon icon={'caret-up'} size={'xs'} />
- ) : this.groupSort === 'descending' ? (
- <FontAwesomeIcon icon={'caret-down'} size={'xs'} />
- ) : (
- <FontAwesomeIcon icon={'caret-right'} size={'xs'} />
- )}
+ <FontAwesomeIcon icon={this.groupSort === 'ascending' ? 'caret-up' : this.groupSort === 'descending' ? 'caret-down' : 'caret-right'} size="xs" />
</div>
</div>
<div className={'groups-list'}>{groupListContents}</div>