feat: report feature flags in /whoami

This commit is contained in:
KernelDeimos 2024-08-15 19:14:38 -04:00
parent 8e39f41dd4
commit 4561b8937d
4 changed files with 51 additions and 1 deletions

View File

@ -61,7 +61,10 @@ const WHOAMI_GET = eggspress('/whoami', {
// Get whoami values from other services // Get whoami values from other services
const svc_whoami = req.services.get('whoami'); const svc_whoami = req.services.get('whoami');
const provider_details = await svc_whoami.get_details({ user: req.user }); const provider_details = await svc_whoami.get_details({
user: req.user,
actor: actor,
});
Object.assign(details, provider_details); Object.assign(details, provider_details);
if ( ! is_user ) { if ( ! is_user ) {

View File

@ -8,6 +8,20 @@ const BaseService = require("./BaseService");
* are enabled or disabled for the current user. * are enabled or disabled for the current user.
*/ */
class FeatureFlagService extends BaseService { class FeatureFlagService extends BaseService {
_construct () {
this.known_flags = new Map();
}
register (name, spec) {
this.known_flags.set(name, spec);
}
async _init () {
const svc_detailProvider = this.services.get('whoami');
svc_detailProvider.register_provider(async (context, out) => {
console.log(`\x1B[36;1mCALLED\x1B[0m`);
if ( ! context.actor ) return;
out.feature_flags = await this.get_summary(context.actor);
});
}
async check (...a) { async check (...a) {
// allows binding call with multiple options objects; // allows binding call with multiple options objects;
// the last argument is the permission to check // the last argument is the permission to check
@ -25,6 +39,9 @@ class FeatureFlagService extends BaseService {
return { options, value }; return { options, value };
})(); })();
if ( ! this.known_flags.has(permission) ) {
this.known_flags.set(permission, true);
}
const actor = options.actor ?? Context.get('actor'); const actor = options.actor ?? Context.get('actor');
@ -35,6 +52,22 @@ class FeatureFlagService extends BaseService {
if ( l.length === 0 ) return false; if ( l.length === 0 ) return false;
return true; return true;
} }
async get_summary (actor) {
const summary = {};
for ( const [key, value] of this.known_flags.entries() ) {
if ( value.$ === 'config-flag' ) {
summary[key] = value.value;
continue;
}
const svc_permission = this.services.get('permission');
const reading = await svc_permission.scan(actor, `feature:`);
const l = PermissionUtil.reading_to_options(reading);
summary[key] = l.length > 0;
}
return summary;
}
} }
module.exports = { module.exports = {

View File

@ -37,6 +37,13 @@ class ShareService extends BaseService {
async _init () { async _init () {
this.db = await this.services.get('database').get(DB_WRITE, 'share'); this.db = await this.services.get('database').get(DB_WRITE, 'share');
// registry "share" as a feature flag so gui is informed
// about whether or not a user has access to this feature
const svc_featureFlag = this.services.get('feature-flag');
svc_featureFlag.register('share', {
$: 'permission-flag'
});
} }
['__on_install.routes'] (_, { app }) { ['__on_install.routes'] (_, { app }) {

View File

@ -25,6 +25,13 @@ const { AppUnderUserActorType, UserActorType, Actor, SystemActorType, AccessToke
const { PermissionUtil } = require("./PermissionService"); const { PermissionUtil } = require("./PermissionService");
class ACLService extends BaseService { class ACLService extends BaseService {
async _init () {
const svc_featureFlag = this.services.get('feature-flag');
svc_featureFlag.register('public-folders', {
$: 'config-flag',
value: this.global_config.enable_public_folders ?? false,
});
}
async check (actor, resource, mode) { async check (actor, resource, mode) {
const ld = (Context.get('logdent') ?? 0) + 1; const ld = (Context.get('logdent') ?? 0) + 1;
return await Context.get().sub({ logdent: ld }).arun(async () => { return await Context.get().sub({ logdent: ld }).arun(async () => {