import Session from "./session"; import Logging from "@hibas123/nodelogging"; interface IRule { ".write"?: T ".read"?: T } type IRuleConfig = { [segment: string]: IRuleConfig; } | IRule; type IRuleRaw = IRuleConfig; type IRuleParsed = IRuleConfig; const resolve = (value: any) => { if (value === true) { return true; } else if (typeof value === "string") { } return undefined; } export class Rules { rules: IRuleParsed; constructor(private config: string) { let parsed: IRuleRaw = JSON.parse(config); const analyze = (raw: IRuleRaw) => { let r: IRuleParsed = {}; if (raw[".read"]) { let res = resolve(raw[".read"]); if (res) { r[".read"] = res; } delete raw[".read"]; } if (raw[".write"]) { let res = resolve(raw[".write"]); if (res) { r[".write"] = res; } delete raw[".write"]; } for (let segment in raw) { if (segment.startsWith(".")) continue; r[segment] = analyze(raw[segment]); } return r; } this.rules = analyze(parsed); } hasPermission(path: string[], session: Session): { read: boolean, write: boolean } { let read = this.rules[".read"] || false; let write = this.rules[".write"] || false; let rules = this.rules; for (let segment of path) { if (segment.startsWith("$") || segment.startsWith(".")) { read = false; write = false; Logging.log("Invalid query path (started with '$' or '.'):", path); break; } let k = Object.keys(rules) .filter(e => e.startsWith("$")) .find(e => { switch (e) { case "$uid": if (segment === session.uid) return true; break; } return false; }) rules = (k ? rules[k] : undefined) || rules[segment] || rules["*"]; if (rules) { if (rules[".read"]) { read = rules[".read"] } if (rules[".write"]) { read = rules[".write"] } } else { break; } } return { read: read as boolean, write: write as boolean } } toJSON() { return this.config; } }