-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7006dcc
commit f2f3d6f
Showing
5 changed files
with
221 additions
and
0 deletions.
There are no files selected for viewing
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,7 @@ | ||
const BaseService = require("../services/BaseService"); | ||
|
||
class Library extends BaseService { | ||
// | ||
} | ||
|
||
module.exports = Library; |
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,77 @@ | ||
const Library = require("../definitions/Library"); | ||
|
||
class ArrayUtil extends Library { | ||
/** | ||
* | ||
* @param {*} marked_map | ||
* @param {*} subject | ||
*/ | ||
remove_marked_items (marked_map, subject) { | ||
for ( let i=0 ; i < marked_map.length ; i++ ) { | ||
let ii = marked_map[i]; | ||
// track: type check | ||
if ( ! Number.isInteger(ii) ) { | ||
throw new Error( | ||
'marked_map can only contain integers' | ||
); | ||
} | ||
// track: bounds check | ||
if ( ii < 0 && ii >= subject.length ) { | ||
throw new Error( | ||
'each item in `marked_map` must be within that bounds ' + | ||
'of `subject`' | ||
); | ||
} | ||
} | ||
|
||
marked_map.sort((a, b) => b - a); | ||
|
||
for ( let i=0 ; i < marked_map.length ; i++ ) { | ||
let ii = marked_map[i]; | ||
subject.splice(ii, 1); | ||
} | ||
|
||
return subject; | ||
} | ||
|
||
_test ({ assert }) { | ||
// inner indices | ||
{ | ||
const subject = [ | ||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']; | ||
// 0 1 2 3 4 5 6 7 | ||
const marked_map = [2, 5]; | ||
this.remove_marked_items(marked_map, subject); | ||
assert(() => subject.join('') === 'abdegh'); | ||
} | ||
// left edge | ||
{ | ||
const subject = [ | ||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']; | ||
// 0 1 2 3 4 5 6 7 | ||
const marked_map = [0] | ||
this.remove_marked_items(marked_map, subject); | ||
assert(() => subject.join('') === 'bcdefgh'); | ||
} | ||
// right edge | ||
{ | ||
const subject = [ | ||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']; | ||
// 0 1 2 3 4 5 6 7 | ||
const marked_map = [7] | ||
this.remove_marked_items(marked_map, subject); | ||
assert(() => subject.join('') === 'abcdefg'); | ||
} | ||
// both edges | ||
{ | ||
const subject = [ | ||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']; | ||
// 0 1 2 3 4 5 6 7 | ||
const marked_map = [0, 7] | ||
this.remove_marked_items(marked_map, subject); | ||
assert(() => subject.join('') === 'bcdefg'); | ||
} | ||
} | ||
} | ||
|
||
module.exports = ArrayUtil; |
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,82 @@ | ||
const { AppUnderUserActorType, UserActorType } = require("../../services/auth/Actor"); | ||
const { Context } = require("../../util/context"); | ||
const { BaseES } = require("./BaseES"); | ||
|
||
class ProtectedAppES extends BaseES { | ||
async select (options){ | ||
const results = await this.upstream.select(options); | ||
|
||
const actor = Context.get('actor'); | ||
const services = Context.get('services'); | ||
|
||
const to_delete = []; | ||
for ( let i=0 ; i < results.length ; i++ ) { | ||
const entity = results[i]; | ||
|
||
if ( ! await this.check_({ actor, services }, entity) ) { | ||
continue; | ||
} | ||
|
||
to_delete.push(i); | ||
} | ||
|
||
const svc_utilArray = services.get('util-array'); | ||
svc_utilArray.remove_marked_items(to_delete, results); | ||
|
||
return results; | ||
} | ||
|
||
async read (uid){ | ||
const entity = await this.upstream.read(uid); | ||
if ( ! entity ) return null; | ||
|
||
const actor = Context.get('actor'); | ||
const services = Context.get('services'); | ||
|
||
if ( await this.check_({ actor, services }, entity) ) { | ||
return null; | ||
} | ||
|
||
return entity; | ||
} | ||
|
||
/** | ||
* returns true if the entity should not be sent downstream | ||
*/ | ||
async check_ ({ actor, services }, entity) { | ||
// track: ruleset | ||
{ | ||
// if it's not a protected app, no worries | ||
if ( ! await entity.get('protected') ) return; | ||
|
||
// if actor is this app, no worries | ||
if ( | ||
actor.type instanceof AppUnderUserActorType && | ||
await entity.get('uid') === actor.type.app.uid | ||
) return; | ||
|
||
// if actor is owner of this app, no worries | ||
if ( | ||
actor.type instanceof UserActorType && | ||
(await entity.get('owner')).id === actor.type.user.id | ||
) return; | ||
} | ||
|
||
// now we need to check for permission | ||
const app_uid = await entity.get('uid'); | ||
const svc_permission = services.get('permission'); | ||
const permission_to_check = `app:uid#${app_uid}:access`; | ||
const perm = await svc_permission.check( | ||
actor, permission_to_check, | ||
); | ||
|
||
if ( perm ) return; | ||
|
||
// `true` here means "do not send downstream" | ||
return true; | ||
} | ||
}; | ||
|
||
module.exports = { | ||
ProtectedAppES, | ||
}; |
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,44 @@ | ||
const { get_app } = require("../helpers"); | ||
const { UserActorType } = require("./auth/Actor"); | ||
const { PermissionImplicator, PermissionUtil } = require("./auth/PermissionService"); | ||
const BaseService = require("./BaseService"); | ||
|
||
class ProtectedAppService extends BaseService { | ||
async _init () { | ||
const svc_permission = this.services.get('permission'); | ||
|
||
// track: object description in comment | ||
// Owner of procted app has implicit permission to access it | ||
svc_permission.register_implicator(PermissionImplicator.create({ | ||
matcher: permission => { | ||
return permission.startsWith('app:'); | ||
}, | ||
checker: async ({ actor, permission }) => { | ||
if ( !(actor.type instanceof UserActorType) ) { | ||
return undefined; | ||
} | ||
|
||
const parts = PermissionUtil.split(permission); | ||
if ( parts.length !== 3 ) return undefined; | ||
|
||
const [_, uid_part, lvl] = parts; | ||
if ( lvl !== 'access' ) return undefined; | ||
|
||
// track: slice a prefix | ||
const uid = uid_part.slice('uid#'.length); | ||
|
||
const app = await get_app({ uid }); | ||
|
||
if ( app.owner_user_id !== actor.type.user.id ) { | ||
return undefined; | ||
} | ||
|
||
return {}; | ||
}, | ||
})); | ||
} | ||
} | ||
|
||
module.exports = { | ||
ProtectedAppService, | ||
}; |