aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/util/GroupManager.tsx34
-rw-r--r--src/client/util/SharingManager.tsx199
-rw-r--r--src/client/views/nodes/DocumentView.tsx3
-rw-r--r--src/fields/Doc.ts8
-rw-r--r--src/fields/util.ts2
5 files changed, 141 insertions, 105 deletions
diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx
index e352d46a8..c8d3be49b 100644
--- a/src/client/util/GroupManager.tsx
+++ b/src/client/util/GroupManager.tsx
@@ -3,11 +3,11 @@ import { observable, action, runInAction, computed } from "mobx";
import { SelectionManager } from "./SelectionManager";
import MainViewModal from "../views/MainViewModal";
import { observer } from "mobx-react";
-import { Doc, DocListCast, Opt } from "../../fields/Doc";
+import { Doc, DocListCast, Opt, DocListCastAsync } from "../../fields/Doc";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import * as fa from '@fortawesome/free-solid-svg-icons';
import { library } from "@fortawesome/fontawesome-svg-core";
-import SharingManager, { User } from "./SharingManager";
+import { User } from "./SharingManager";
import { Utils } from "../../Utils";
import * as RequestPromise from "request-promise";
import Select from 'react-select';
@@ -33,6 +33,7 @@ export default class GroupManager extends React.Component<{}> {
@observable private selectedUsers: UserOptions[] | null = null; // list of users selected in the "Select users" dropdown.
@observable currentGroup: Opt<Doc>; // the currently selected group.
private inputRef: React.RefObject<HTMLInputElement> = React.createRef(); // the ref for the input box.
+ private currentUserGroups: Doc[] = [];
constructor(props: Readonly<{}>) {
super(props);
@@ -42,6 +43,26 @@ export default class GroupManager extends React.Component<{}> {
// sets up the list of users
componentDidMount() {
this.populateUsers().then(resolved => runInAction(() => this.users = resolved));
+
+ // this.getAllGroups().forEach(group => {
+ // const members: string[] = JSON.parse(StrCast(group.members));
+ // if (members.includes(Doc.CurrentUserEmail)) this.currentUserGroups.push(group);
+ // });
+ DocListCastAsync(this.GroupManagerDoc?.data).then(groups => {
+ groups?.forEach(group => {
+ const members: string[] = JSON.parse(StrCast(group.members));
+ if (members.includes(Doc.CurrentUserEmail)) this.currentUserGroups.push(group);
+ });
+ })
+ .finally(() => console.log(this.currentUserGroups));
+
+ // (this.GroupManagerDoc?.data as List<Doc>).forEach(group => {
+ // Promise.resolve(group).then(resolvedGroup => {
+ // const members: string[] = JSON.parse(StrCast(resolvedGroup.members));
+ // if (members.includes(Doc.CurrentUserEmail)) this.currentUserGroups.push(resolvedGroup);
+ // });
+ // });
+
}
/**
@@ -49,8 +70,8 @@ export default class GroupManager extends React.Component<{}> {
*/
populateUsers = async () => {
const userList: User[] = JSON.parse(await RequestPromise.get(Utils.prepend("/getUsers")));
- const currentUserIndex = userList.findIndex(user => user.email === Doc.CurrentUserEmail);
- currentUserIndex !== -1 && userList.splice(currentUserIndex, 1);
+ // const currentUserIndex = userList.findIndex(user => user.email === Doc.CurrentUserEmail);
+ // currentUserIndex !== -1 && userList.splice(currentUserIndex, 1);
return userList.map(user => user.email);
}
@@ -61,6 +82,11 @@ export default class GroupManager extends React.Component<{}> {
return this.users.map(user => ({ label: user, value: user }));
}
+
+ get groupMemberships() {
+ return this.currentUserGroups;
+ }
+
/**
* Makes the GroupManager visible.
*/
diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx
index 491abe1dc..b4977f8ea 100644
--- a/src/client/util/SharingManager.tsx
+++ b/src/client/util/SharingManager.tsx
@@ -85,7 +85,7 @@ export default class SharingManager extends React.Component<{}> {
@observable private dialogueBoxOpacity = 1;
@observable private overlayOpacity = 0.4;
@observable private selectedUsers: UserOptions[] | null = null;
- @observable private permissions: SharingPermissions = SharingPermissions.None;
+ @observable private permissions: SharingPermissions = SharingPermissions.Edit;
// private get linkVisible() {
// return this.sharingDoc ? this.sharingDoc[PublicKey] !== SharingPermissions.None : false;
@@ -98,9 +98,9 @@ export default class SharingManager extends React.Component<{}> {
this.targetDoc = target.props.Document;
DictationOverlay.Instance.hasActiveModal = true;
this.isOpen = true;
- if (!this.sharingDoc) {
- this.sharingDoc = new Doc;
- }
+ // if (!this.sharingDoc) {
+ // this.sharingDoc = new Doc;
+ // }
}));
// runInAction(() => this.groups = GroupManager.Instance.getAllGroups());
@@ -116,13 +116,13 @@ export default class SharingManager extends React.Component<{}> {
}), 500);
});
- private get sharingDoc() {
- return this.targetDoc ? Cast(this.targetDoc[SharingKey], Doc) as Doc : undefined;
- }
+ // private get sharingDoc() {
+ // return this.targetDoc ? Cast(this.targetDoc[SharingKey], Doc) as Doc : undefined;
+ // }
- private set sharingDoc(value: Doc | undefined) {
- this.targetDoc && (this.targetDoc[SharingKey] = value);
- }
+ // private set sharingDoc(value: Doc | undefined) {
+ // this.targetDoc && (this.targetDoc[SharingKey] = value);
+ // }
constructor(props: {}) {
super(props);
@@ -153,76 +153,79 @@ export default class SharingManager extends React.Component<{}> {
const members: string[] = JSON.parse(StrCast(group.members));
const users: ValidatedUser[] = this.users.filter(user => members.includes(user.user.email));
- const sharingDoc = this.sharingDoc!;
- console.log(sharingDoc)
- if (permission === SharingPermissions.None) {
- const metadata = sharingDoc[StrCast(group.groupName)];
- if (metadata) sharingDoc[StrCast(group.groupName)] = undefined;
- }
- else {
- sharingDoc[StrCast(group.groupName)] = permission;
- }
+ const target = this.targetDoc!;
+ const ACL = `ACL-${StrCast(group.groupName)}`;
+
+ target[ACL] = permission;
+ // const sharingDoc = this.sharingDoc!;
+ // if (permission === SharingPermissions.None) {
+ // const metadata = sharingDoc[StrCast(group.groupName)];
+ // if (metadata) sharingDoc[StrCast(group.groupName)] = undefined;
+ // }
+ // else {
+ // sharingDoc[StrCast(group.groupName)] = permission;
+ // }
- users.forEach(user => {
- this.setInternalSharing(user, permission, group);
+ users.forEach(({ notificationDoc }) => {
+ Doc.AddDocToList(notificationDoc, storage, target);
});
}
- setInternalSharing = async (recipient: ValidatedUser, state: string, group?: Doc) => {
+ setInternalSharing = (recipient: ValidatedUser, permission: string, group?: Doc) => {
const { user, notificationDoc } = recipient;
const target = this.targetDoc!;
- const manager = this.sharingDoc!;
+ // const manager = this.sharingDoc!;
const key = user.userDocumentId;
- let metadata = await DocCastAsync(manager[key]);
- const permissions: { [key: string]: number } = metadata?.permissions ? JSON.parse(StrCast(metadata.permissions)) : {};
- permissions[StrCast(group ? group.groupName : Doc.CurrentUserEmail)] = parseInt(HierarchyMapping.get(state)!);
- const max = Math.max(...Object.values(permissions));
-
- // let max = 0;
- // const keys: string[] = [];
- // for (const [key, value] of Object.entries(permissions)) {
- // if (value === max && max !== 0) {
- // keys.push(key);
- // }
- // else if (value > max) {
- // keys.splice(0, keys.length);
- // keys.push(key);
- // max = value;
- // }
- // }
+ const ACL = `ACL-${key}`;
- switch (max) {
- case 0:
- if (metadata) {
- const sharedAlias = (await DocCastAsync(metadata.sharedAlias))!;
- Doc.RemoveDocFromList(notificationDoc, storage, sharedAlias);
- manager[key] = undefined;
- }
- break;
-
- case 1: case 2: case 3:
- if (!metadata) {
- metadata = new Doc;
- const sharedAlias = Doc.MakeAlias(target);
- Doc.AddDocToList(notificationDoc, storage, sharedAlias);
- metadata.sharedAlias = sharedAlias;
- manager[key] = metadata;
- }
- metadata.permissions = JSON.stringify(permissions);
- // metadata.usersShared = JSON.stringify(keys);
- break;
- }
+ // const permissions: { [key: string]: number } = target[ACL] ? JSON.parse(StrCast(target[ACL])) : {};
+
+ target[ACL] = permission;
+
+ Doc.AddDocToList(notificationDoc, storage, target);
- if (metadata) metadata.maxPermission = HierarchyMapping.get(`${max}`);
+
+ // let metadata = await DocCastAsync(manager[key]);
+ // const permissions: { [key: string]: number } = metadata?.permissions ? JSON.parse(StrCast(metadata.permissions)) : {};
+ // permissions[StrCast(group ? group.groupName : Doc.CurrentUserEmail)] = parseInt(HierarchyMapping.get(permission)!);
+ // const max = Math.max(...Object.values(permissions));
+
+ // switch (max) {
+ // case 0:
+ // // if (metadata) {
+ // // const sharedAlias = (await DocCastAsync(metadata.sharedAlias))!;
+ // // Doc.RemoveDocFromList(notificationDoc, storage, sharedAlias);
+ // // manager[key] = undefined;
+ // // }
+ // Doc.RemoveDocFromList(notificationDoc, storage, target);
+ // break;
+
+ // case 1: case 2: case 3:
+
+ // Doc.AddDocToList(notificationDoc, storage, target);
+
+ // if (!metadata) {
+ // metadata = new Doc;
+ // const sharedAlias = Doc.MakeAlias(target);
+ // Doc.AddDocToList(notificationDoc, storage, target);
+ // metadata.sharedAlias = sharedAlias;
+ // manager[key] = metadata;
+ // }
+ // metadata.permissions = JSON.stringify(permissions);
+ // // metadata.usersShared = JSON.stringify(keys);
+ // break;
+ // }
+
+ // if (metadata) metadata.maxPermission = HierarchyMapping.get(`${max}`);
}
- // private setExternalSharing = (state: string) => {
+ // private setExternalSharing = (permission: string) => {
// const sharingDoc = this.sharingDoc;
// if (!sharingDoc) {
// return;
// }
- // sharingDoc[PublicKey] = state;
+ // sharingDoc[PublicKey] = permission;
// }
private get sharingUrl() {
@@ -281,15 +284,21 @@ export default class SharingManager extends React.Component<{}> {
}
private computePermissions = (userKey: string) => {
- const sharingDoc = this.sharingDoc;
- if (!sharingDoc) {
- return SharingPermissions.None;
- }
- const metadata = sharingDoc[userKey] as Doc | string;
- if (!metadata) {
- return SharingPermissions.None;
- }
- return StrCast(metadata instanceof Doc ? metadata.maxPermission : metadata, SharingPermissions.None);
+ // const sharingDoc = this.sharingDoc;
+ // if (!sharingDoc) {
+ // return SharingPermissions.None;
+ // }
+ // const metadata = sharingDoc[userKey] as Doc | string;
+
+ if (!this.targetDoc) return SharingPermissions.None;
+
+ const ACL = `ACL-${userKey}`;
+ const permission = StrCast(this.targetDoc[ACL]);
+
+ // if (!metadata) {
+ // return SharingPermissions.None;
+ // }
+ return StrCast(this.targetDoc[ACL], SharingPermissions.None);
}
@action
@@ -314,7 +323,6 @@ export default class SharingManager extends React.Component<{}> {
this.setInternalGroupSharing(GroupManager.Instance.getGroup(user.label)!, this.permissions);
}
});
-
this.selectedUsers = null;
}
@@ -377,27 +385,30 @@ export default class SharingManager extends React.Component<{}> {
<div className={"hr-substitute"} /> */}
<div className="sharing-contents">
<p className={"share-title"}><b>Share </b>{this.focusOn(StrCast(this.targetDoc?.title, "this document"))}</p>
- <div className="share-setup">
- <Select
- className={"user-search"}
- placeholder={"Enter user or group name..."}
- isMulti
- closeMenuOnSelect={false}
- options={options}
- onChange={this.handleUsersChange}
- value={this.selectedUsers}
- />
- <select className="permissions-select" onChange={this.handlePermissionsChange}>
- {this.sharingOptions}
- </select>
- <button className="share-button" onClick={this.share}>
- Share
- </button>
- </div>
+ {this.targetDoc?.author !== Doc.CurrentUserEmail ? null
+ :
+ <div className="share-setup">
+ <Select
+ className={"user-search"}
+ placeholder={"Enter user or group name..."}
+ isMulti
+ closeMenuOnSelect={false}
+ options={options}
+ onChange={this.handleUsersChange}
+ value={this.selectedUsers}
+ />
+ <select className="permissions-select" onChange={this.handlePermissionsChange}>
+ {this.sharingOptions}
+ </select>
+ <button className="share-button" onClick={this.share}>
+ Share
+ </button>
+ </div>
+ }
<div className="main-container">
<div className={"individual-container"}>
<div className={"users-list"} style={{ display: existOtherUsers ? "block" : "flex", minHeight: existOtherUsers ? undefined : 150 }}>{/*200*/}
- {!existOtherUsers ? "There are no other users in your database." :
+ {
this.users.map(({ user, notificationDoc }) => { // can't use async here
const userKey = user.userDocumentId;
const permissions = this.computePermissions(userKey);
@@ -434,8 +445,8 @@ export default class SharingManager extends React.Component<{}> {
</div>
<div className={"group-container"}>
<div className={"groups-list"} style={{ display: existGroups ? "block" : "flex", minHeight: existOtherUsers ? undefined : 150 }}>{/*200*/}
- {!existGroups ? "There are no groups in your database." :
- GroupManager.Instance.getAllGroups().map(group => {
+ {
+ GroupManager.Instance?.getAllGroups().map(group => {
const permissions = this.computePermissions(StrCast(group.groupName));
// const color = ColorMapping.get(permissions);
return permissions === SharingPermissions.None ? null : (
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 09eeaee36..21b6d8310 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1169,9 +1169,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
}
render() {
- if (!(this.props.Document instanceof Doc)) return (null);
if (this.props.Document[AclSym] && this.props.Document[AclSym] === AclPrivate) return (null);
- if (this.props.Document.hidden) return (null);
+ if (!(this.props.Document instanceof Doc)) return (null);
const backgroundColor = Doc.UserDoc().renderStyle === "comic" ? undefined : this.props.forcedBackgroundColor?.(this.Document) || StrCast(this.layoutDoc._backgroundColor) || StrCast(this.layoutDoc.backgroundColor) || StrCast(this.Document.backgroundColor) || this.props.backgroundColor?.(this.Document);
const opacity = Cast(this.layoutDoc._opacity, "number", Cast(this.layoutDoc.opacity, "number", Cast(this.Document.opacity, "number", null)));
const finalOpacity = this.props.opacity ? this.props.opacity() : opacity;
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index e4d11dd4d..7b1db1042 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -96,13 +96,13 @@ export const AclSym = Symbol("Acl");
export const AclPrivate = Symbol("AclOwnerOnly");
export const AclReadonly = Symbol("AclReadOnly");
export const AclAddonly = Symbol("AclAddonly");
-export const AclReadWrite = Symbol("AclReadWrite");
+export const AclEdit = Symbol("AclEdit");
export const UpdatingFromServer = Symbol("UpdatingFromServer");
const CachedUpdates = Symbol("Cached updates");
export function fetchProto(doc: Doc) {
- if (doc.author !== Doc.CurrentUserEmail) {
+ if (doc.author !== Doc.CurrentUserEmail) { // storing acls for groups needs to be extended here - AclSym should store a datastructure that stores information about permissions
const acl = Doc.Get(doc, "ACL", true);
switch (acl) {
case "ownerOnly":
@@ -114,8 +114,8 @@ export function fetchProto(doc: Doc) {
case "addOnly":
doc[AclSym] = AclAddonly;
break;
- case "write":
- doc[AclSym] = AclReadWrite;
+ case "edit":
+ doc[AclSym] = AclEdit;
}
}
diff --git a/src/fields/util.ts b/src/fields/util.ts
index 2dc21c987..7bb090a93 100644
--- a/src/fields/util.ts
+++ b/src/fields/util.ts
@@ -111,7 +111,7 @@ const layoutProps = ["panX", "panY", "width", "height", "nativeWidth", "nativeHe
"chromeStatus", "viewType", "gridGap", "xMargin", "yMargin", "autoHeight"];
export function setter(target: any, in_prop: string | symbol | number, value: any, receiver: any): boolean {
let prop = in_prop;
- if (target[AclSym] && !_overrideAcl && !DocServer.PlaygroundFields.includes(in_prop.toString())) return true;
+ if (target[AclSym] && !_overrideAcl && !DocServer.PlaygroundFields.includes(in_prop.toString())) return true; // generalise to a testpermission function
if (typeof prop === "string" && prop !== "__id" && prop !== "__fields" && (prop.startsWith("_") || layoutProps.includes(prop))) {
if (!prop.startsWith("_")) {
console.log(prop + " is deprecated - switch to _" + prop);