aboutsummaryrefslogtreecommitdiff
path: root/src/fields/util.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/fields/util.ts')
-rw-r--r--src/fields/util.ts73
1 files changed, 68 insertions, 5 deletions
diff --git a/src/fields/util.ts b/src/fields/util.ts
index 2dc21c987..77855887e 100644
--- a/src/fields/util.ts
+++ b/src/fields/util.ts
@@ -1,5 +1,5 @@
import { UndoManager } from "../client/util/UndoManager";
-import { Doc, Field, FieldResult, UpdatingFromServer, LayoutSym, AclSym, AclPrivate } from "./Doc";
+import { Doc, FieldResult, UpdatingFromServer, LayoutSym, AclPrivate, AclEdit, AclReadonly, AclAddonly, AclSym, fetchProto } from "./Doc";
import { SerializationHelper } from "../client/util/SerializationHelper";
import { ProxyField, PrefetchProxy } from "./Proxy";
import { RefField } from "./RefField";
@@ -71,7 +71,8 @@ const _setterImpl = action(function (target: any, prop: string | symbol | number
const fromServer = target[UpdatingFromServer];
const sameAuthor = fromServer || (receiver.author === Doc.CurrentUserEmail);
const writeToDoc = sameAuthor || (writeMode !== DocServer.WriteMode.LiveReadonly);
- const writeToServer = sameAuthor || (writeMode === DocServer.WriteMode.Default);
+ const writeToServer = (sameAuthor || (writeMode === DocServer.WriteMode.Default)) && !playgroundMode;
+
if (writeToDoc) {
if (value === undefined) {
delete target.__fields[prop];
@@ -79,10 +80,13 @@ const _setterImpl = action(function (target: any, prop: string | symbol | number
target.__fields[prop] = value;
}
//if (typeof value === "object" && !(value instanceof ObjectField)) debugger;
+
+ // remove below lines to prevent saving changes to server
if (writeToServer) {
if (value === undefined) target[Update]({ '$unset': { ["fields." + prop]: "" } });
else target[Update]({ '$set': { ["fields." + prop]: value instanceof ObjectField ? SerializationHelper.Serialize(value) : (value === undefined ? null : value) } });
} else {
+ console.log("not writing to server")
DocServer.registerDocWithCachedUpdate(receiver, prop as string, curValue);
}
UndoManager.AddEvent({
@@ -107,11 +111,70 @@ export function OVERRIDE_ACL(val: boolean) {
_overrideAcl = val;
}
+let playgroundMode = false;
+
+export function togglePlaygroundMode() {
+ playgroundMode = !playgroundMode;
+}
+
+export function getPlaygroundMode() {
+ return playgroundMode;
+}
+
+let currentUserGroups: string[] = [];
+
+export function setGroups(groups: string[]) {
+ currentUserGroups = groups;
+}
+
+export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number): symbol {
+
+ const HierarchyMapping = new Map<symbol, number>([
+ [AclPrivate, 0],
+ [AclReadonly, 1],
+ [AclAddonly, 2],
+ [AclEdit, 3]
+ ]);
+
+ if (!target[AclSym] && target instanceof Doc) {
+ fetchProto(target);
+ }
+
+ if (target[AclSym] && Object.keys(target[AclSym]).length) {
+
+ if (target.author === Doc.CurrentUserEmail || currentUserGroups.includes("admin")) return AclEdit;
+
+ if (_overrideAcl || (in_prop && DocServer.PlaygroundFields?.includes(in_prop.toString()))) return AclEdit;
+
+ if (target[AclSym].ACL) return target[AclSym].ACL;
+
+ let effectiveAcl = AclPrivate;
+ let aclPresent = false;
+
+ for (const [key, value] of Object.entries(target[AclSym])) {
+ if (currentUserGroups.includes(key.substring(4)) || Doc.CurrentUserEmail === key.substring(4).replace("_", ".")) {
+ if (HierarchyMapping.get(value as symbol)! >= HierarchyMapping.get(effectiveAcl)!) {
+ aclPresent = true;
+ effectiveAcl = value as symbol;
+ if (effectiveAcl === AclEdit) break;
+ }
+ }
+ }
+ return aclPresent ? effectiveAcl : AclEdit;
+ }
+ else {
+ return AclEdit;
+ }
+}
+
+
const layoutProps = ["panX", "panY", "width", "height", "nativeWidth", "nativeHeight", "fitWidth", "fitToBox",
"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 (GetEffectiveAcl(target, in_prop) !== AclEdit) {
+ return true;
+ }
if (typeof prop === "string" && prop !== "__id" && prop !== "__fields" && (prop.startsWith("_") || layoutProps.includes(prop))) {
if (!prop.startsWith("_")) {
console.log(prop + " is deprecated - switch to _" + prop);
@@ -131,7 +194,7 @@ export function setter(target: any, in_prop: string | symbol | number, value: an
export function getter(target: any, in_prop: string | symbol | number, receiver: any): any {
let prop = in_prop;
if (in_prop === AclSym) return _overrideAcl ? undefined : target[AclSym];
- if (target[AclSym] === AclPrivate && !_overrideAcl) return undefined;
+ if (GetEffectiveAcl(target) === AclPrivate && !_overrideAcl) return undefined;
if (prop === LayoutSym) {
return target.__LAYOUT__;
}
@@ -168,7 +231,7 @@ function getFieldImpl(target: any, prop: string | number, receiver: any, ignoreP
}
if (field === undefined && !ignoreProto && prop !== "proto") {
const proto = getFieldImpl(target, "proto", receiver, true);//TODO tfs: instead of receiver we could use target[SelfProxy]... I don't which semantics we want or if it really matters
- if (proto instanceof Doc && proto[AclSym] !== AclPrivate) {
+ if (proto instanceof Doc && GetEffectiveAcl(proto) !== AclPrivate) {
return getFieldImpl(proto[Self], prop, receiver, ignoreProto);
}
return undefined;