Implement authentication and access control

This commit is contained in:
Zaid Abdulla committed 2018-12-26 00:22:07 -08:00
1 parent e1bdcda191
commit 327cb78f1a
27 files changed
+600 -167

No files matched your search

+78
View File
@@ -0,0 +1,78 @@
"use strict";
const validators = {
pass: require("./validators/pass"),
test: require("./validators/test")
};
class Authorizer {
constructor(permissionSets) {
this.permissionSets = permissionSets;
this.validtorCache = new WeakMap();
this.hasAccessCache = {};
}
hasAccess(resourceType, access) {
const cacheKey = `${resourceType}-${access}`;
if (cacheKey in this.hasAccessCache)
return this.hasAccessCache[cacheKey];
let has = false;
for (const permissionSet of this.permissionSets) {
for (const perm of permissionSet) {
if (perm[resourceType]) {
if (perm[resourceType].access >= access) {
has = true;
break;
}
}
}
}
this.hasAccessCache[cacheKey] = has;
return has;
}
getValidator(resourceType, resource) {
if (this.validtorCache.has(resource))
return this.validtorCache.get(resource);
let funcs = {};
for (let permissionSet of this.permissionSets)
for (let perm of permissionSet)
if (perm[resourceType]) {
if (perm[resourceType].access >= 3) {
if (perm[resourceType].validate)
for (let [k, v] of Object.entries(perm[resourceType].validate))
funcs[k] = v;
} else {
funcs = {};
}
}
const validator = (mutationType, mutation, any) => {
let valid = false;
for (let [k, v] of Object.entries(funcs))
if (v) {
let res = validators[k](
resourceType,
resource,
mutationType,
mutation,
any
);
if (res > 0) valid = true;
else if (res < 0) return false;
}
return valid;
};
this.validtorCache.set(resource, validator);
return validator;
}
}
module.exports = Authorizer;
+5 -3
View File
@@ -17,9 +17,10 @@ function* permute(arr) {
class Filter {
constructor(str) {
if (Array.isArray(str)) this.ast = str;
if (!str) this.ast = null;
else if (Array.isArray(str)) this.ast = str;
else if (str instanceof Filter) this.ast = str.ast;
else if (!str) this.ast = null;
else if (Array.isArray(str.ast) || str.ast === null) this.ast = str.ast;
else this.ast = filterParser.parse(str);
}
@@ -33,6 +34,7 @@ class Filter {
or(fltr) {
if (!fltr || !this.ast) return this;
else if (!fltr.ast) return fltr;
let f = ["OR"];
@@ -46,7 +48,7 @@ class Filter {
}
and(fltr) {
if (!fltr) return this;
if (!fltr || !fltr.ast) return this;
else if (!this.ast) return fltr;
let f = ["AND"];
+5
View File
@@ -0,0 +1,5 @@
function pass() {
return 1;
}
module.exports = pass;
+14
View File
@@ -0,0 +1,14 @@
function test(resourceType, resource) {
if (resourceType === "devices") {
if (resource["Tags.test"] && resource["Tags.test"].value[0]) return 1;
} else if (resourceType === "presets") {
if (resource["_id"].startsWith("test-"))
// TODO check "test" tag too
return 1;
} else if (resourceType === "provisions") {
if (resource["_id"].startsWith("test-")) return 1;
}
return -1;
}
module.exports = test;