-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added vanilla javascript version of the RBAC implementation that uses…
… Redis as a backing store
- Loading branch information
Showing
101 changed files
with
8,875 additions
and
1,663 deletions.
There are no files selected for viewing
File renamed without changes.
File renamed without changes.
File renamed without changes.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/*@flow*/ | ||
import type {IAuditRecord, IRealm} from './interface'; | ||
import type {UniqueIdentifier} from '../util/unique_id'; | ||
|
||
const assert = require('assert'); | ||
const _realm = Symbol('realm'); | ||
|
||
/** | ||
* AuditRecord is used to record changes to the system | ||
*/ | ||
export class AuditRecord implements IAuditRecord, UniqueIdentifier { | ||
id: number; // unique database id | ||
|
||
realmName: string; // realm-name | ||
|
||
principalName: string; // principal-name | ||
|
||
type: string | ||
|
||
action: string; | ||
|
||
resource: string; | ||
|
||
constructor(theRealm: IRealm, | ||
thePrincipalName: string, | ||
theType: string, | ||
theAction: string, | ||
theResource: string) { | ||
// | ||
assert(theRealm, 'realm is required'); | ||
assert(thePrincipalName, 'principal-name is required'); | ||
assert(theType, 'type is required'); | ||
assert(theAction, 'action is required'); | ||
assert(theResource, 'resource is required'); | ||
assert(theRealm.id, 'realm-id not specified'); | ||
|
||
// | ||
this.action = theAction; | ||
this.principalName = thePrincipalName; | ||
this.type = theType; | ||
this.action = theAction; | ||
this.resource = theResource; | ||
(this: any)[_realm] = theRealm; | ||
} | ||
|
||
realm(): IRealm { | ||
return (this: any)[_realm]; | ||
} | ||
} |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
/*@flow*/ | ||
|
||
import type {IClaim, IRealm, ClaimEffects} from './interface'; | ||
import type {UniqueIdentifier} from '../util/unique_id'; | ||
|
||
const assert = require('assert'); | ||
|
||
const _realm = Symbol('realm'); | ||
const _startDate = Symbol('startDate'); | ||
const _endDate = Symbol('endDate'); | ||
|
||
/** | ||
* Claim implements IClaim for defining access attributes | ||
*/ | ||
export class Claim implements IClaim, UniqueIdentifier { | ||
static allow = 'allow'; | ||
static deny = 'deny'; | ||
static defaultDeny = 'defaultDeny'; | ||
|
||
id: number; // unique database id | ||
|
||
action: string; // This can be a single operation or regex based multiple operations | ||
|
||
resource: string; // target resource | ||
|
||
condition: string; // This is optional for specifying runtime condition | ||
|
||
effect: ClaimEffects; // This is optional for specifying allow/deny | ||
|
||
constructor(theRealm: IRealm, | ||
theAction: string, | ||
theResource: string, | ||
theCondition: string, | ||
theEffect: ?ClaimEffects, | ||
theStartDate: ?Date, | ||
theEndDate: ?Date) { | ||
// | ||
assert(theRealm, 'realm is required'); | ||
assert(theAction, 'action is required'); | ||
assert(theResource, 'resource is required'); | ||
assert(theRealm.id, 'realm-id not specified'); | ||
|
||
// | ||
this.action = theAction; | ||
this.resource = theResource; | ||
this.condition = theCondition; | ||
this.effect = theEffect || Claim.allow; | ||
(this: any)[_realm] = theRealm; | ||
(this: any)[_startDate] = theStartDate || new Date(); | ||
(this: any)[_endDate] = theEndDate || new Date(new Date().setFullYear(new Date().getFullYear() + 5)); | ||
} | ||
|
||
uniqueKey(): string { | ||
return `${this.realm().realmName}_${this.action}_${this.resource}_${this.condition}`; | ||
} | ||
|
||
hasCondition(): boolean { | ||
return this.condition != null && this.condition != undefined && this.condition.length > 0; | ||
} | ||
|
||
realm(): IRealm { | ||
return (this: any)[_realm]; | ||
} | ||
|
||
startDate(): string { | ||
return (this: any)[_startDate].toISOString().split('T')[0]; | ||
} | ||
|
||
endDate(): string { | ||
return (this: any)[_endDate].toISOString().split('T')[0]; | ||
} | ||
|
||
/** | ||
* This method checks if given action and resource matches internal action and action. | ||
* It tries to compare action and resource directly or using regex | ||
* | ||
* @param {*} action | ||
* @param {*} resource | ||
*/ | ||
implies(theAction: string, theResource: string): boolean { | ||
return (this.action == theAction || | ||
theAction.match(this.action) != null) && | ||
this.resource == theResource; | ||
} | ||
|
||
/** | ||
* returns textual representation | ||
*/ | ||
toString() { | ||
return `(${this.id}, ${this.action}, ${this.resource}, ${this.condition})`; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
/*@flow*/ | ||
|
||
import type {ILimit, IRealm, IPrincipal} from './interface'; | ||
import type {UniqueIdentifier} from '../util/unique_id'; | ||
|
||
const assert = require('assert'); | ||
|
||
const _realm = Symbol('realm'); | ||
|
||
/** | ||
* Limit tracks resource usage by principal | ||
*/ | ||
export class Limit implements ILimit, UniqueIdentifier { | ||
id: number; // unique database id | ||
|
||
type: string; | ||
|
||
resource: string; | ||
|
||
maxAllowed: number; | ||
|
||
value: number; | ||
|
||
expirationDate: Date; | ||
|
||
principal: IPrincipal; | ||
|
||
constructor(theType: string, | ||
theResource: string, | ||
theMaxLimit: number, | ||
theUsed: number, | ||
theExpirationDate: ?Date) { | ||
// | ||
assert(theType, 'type is required'); | ||
assert(theResource, 'resource is required'); | ||
// | ||
this.type = theType; | ||
this.resource = theResource; | ||
this.maxAllowed = theMaxLimit; | ||
this.value = theUsed || 0; | ||
this.expirationDate = theExpirationDate || new Date(new Date().setFullYear(new Date().getFullYear() + 50)); | ||
} | ||
|
||
uniqueKey(): string { | ||
return `${this.principal.id}_${this.type}_${this.resource}_${this.id}`; | ||
} | ||
|
||
expirationISODate(): string { | ||
return this.expirationDate.toISOString().split('T')[0] + 'T23:59:59'; | ||
} | ||
|
||
valid(): boolean { | ||
return this.value <= this.maxAllowed && Date.parse(this.expirationISODate()) >= new Date().getTime(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
/*@flow*/ | ||
|
||
import type {IPrincipal, IClaim, IRole, IRealm, ILimit} from './interface'; | ||
import {UniqueArray} from '../util/unique_array'; | ||
import type {UniqueIdentifier} from '../util/unique_id'; | ||
|
||
const assert = require('assert'); | ||
|
||
const _realm = Symbol('realm'); | ||
|
||
export class Principal implements IPrincipal, UniqueIdentifier { | ||
/** | ||
* unique database id | ||
*/ | ||
id: number; | ||
|
||
/** | ||
* principal name such as username | ||
*/ | ||
principalName: string; | ||
|
||
/** | ||
* set of Claims | ||
*/ | ||
claims: UniqueArray<IClaim>; | ||
|
||
limits: UniqueArray<ILimit>; | ||
/** | ||
* set of roles | ||
*/ | ||
roles: UniqueArray<IRole>; | ||
|
||
properties: Map<string, any>; | ||
|
||
constructor(theRealm: IRealm, | ||
thePrincipalName: string, | ||
theProps: ?Map<string, any>) { | ||
// | ||
assert(theRealm, 'realm is required'); | ||
assert(thePrincipalName, 'principal is required'); | ||
assert(theRealm.id, 'realm-id not specified'); | ||
|
||
// | ||
(this: any)[_realm] = theRealm; | ||
this.principalName = thePrincipalName; | ||
this.claims = new UniqueArray(); | ||
this.roles = new UniqueArray(); | ||
this.limits = new UniqueArray(); | ||
this.properties = theProps || new Map(); | ||
} | ||
|
||
realm(): IRealm { | ||
return (this: any)[_realm]; | ||
} | ||
|
||
uniqueKey(): string { | ||
return `${this.realm().realmName}_${this.principalName}`; | ||
} | ||
|
||
allClaims(): UniqueArray<IClaim> { | ||
let allClaims: UniqueArray<IClaim> = new UniqueArray(); | ||
this.claims.forEach(claim => { | ||
allClaims.add(claim); | ||
}); | ||
this.roles.forEach(role => { | ||
this.___loadRoleClaims(role, allClaims); | ||
}); | ||
return allClaims; | ||
} | ||
|
||
___loadRoleClaims(role: IRole, allClaims: UniqueArray<IClaim>):void { | ||
role.claims.forEach(claim => { | ||
allClaims.add(claim); | ||
}); | ||
role.parents.forEach(parentRole => { | ||
this.___loadRoleClaims(parentRole, allClaims); | ||
}); | ||
} | ||
|
||
/** | ||
* returns textual representation | ||
*/ | ||
toString() { | ||
return `(${this.id}, ${this.principalName}, ${String(this.claims)}, ${String(this.roles)})`; | ||
} | ||
} |
File renamed without changes.
Oops, something went wrong.