111 lines
2.5 KiB
TypeScript
111 lines
2.5 KiB
TypeScript
import Session from "./session";
|
|
import Logging from "@hibas123/nodelogging";
|
|
|
|
interface IRule<T> {
|
|
".write"?: T
|
|
".read"?: T
|
|
}
|
|
|
|
type IRuleConfig<T> = {
|
|
[segment: string]: IRuleConfig<T>;
|
|
} | IRule<T>;
|
|
|
|
type IRuleRaw = IRuleConfig<string>;
|
|
type IRuleParsed = IRuleConfig<boolean>;
|
|
|
|
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;
|
|
}
|
|
} |