mirror of
https://github.com/HeyPuter/puter.git
synced 2026-05-29 21:01:27 +00:00
Revert "feat: root level kv accesses, and installed app listing + server health check fix (#2719)" (#2720)
Docker Image CI / build-and-push-image (push) Has been cancelled
Maintain Release Merge PR / update-release-pr (push) Has been cancelled
Notify HeyPuter / notify (push) Has been cancelled
release-please / release-please (push) Has been cancelled
test / test-backend (24.x) (push) Has been cancelled
test / API tests (node env, api-test) (24.x) (push) Has been cancelled
test / puterjs (node env, vitest) (24.x) (push) Has been cancelled
Docker Image CI / build-and-push-image (push) Has been cancelled
Maintain Release Merge PR / update-release-pr (push) Has been cancelled
Notify HeyPuter / notify (push) Has been cancelled
release-please / release-please (push) Has been cancelled
test / test-backend (24.x) (push) Has been cancelled
test / API tests (node env, api-test) (24.x) (push) Has been cancelled
test / puterjs (node env, vitest) (24.x) (push) Has been cancelled
This reverts commit e75ccb0a41.
This commit is contained in:
@@ -16,16 +16,16 @@
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import eggspress from '../../api/eggspress.js';
|
||||
import { UserActorType } from '../../services/auth/Actor.js';
|
||||
import { Context } from '../../util/context.js';
|
||||
import { APIError } from '../../api/APIError.js';
|
||||
const eggspress = require('../../api/eggspress');
|
||||
const { UserActorType } = require('../../services/auth/Actor');
|
||||
const { Context } = require('../../util/context');
|
||||
const APIError = require('../../api/APIError');
|
||||
|
||||
export const revokeUserAppPermsRoute = eggspress('/auth/revoke-user-app', {
|
||||
module.exports = eggspress('/auth/revoke-user-app', {
|
||||
subdomain: 'api',
|
||||
auth2: true,
|
||||
allowedMethods: ['POST'],
|
||||
}, async (req, res) => {
|
||||
}, async (req, res, next) => {
|
||||
const x = Context.get();
|
||||
const svc_permission = x.get('services').get('permission');
|
||||
|
||||
|
||||
@@ -382,7 +382,7 @@ export class DynamoKVStore {
|
||||
}
|
||||
|
||||
@Span('kv:flush')
|
||||
async flush ({ optConfig}: { optConfig?: { appUuid?: string } }) {
|
||||
async flush ({ optConfig }: { optConfig?: { appUuid?: string } } = {}) {
|
||||
const actor = Context.get('actor');
|
||||
|
||||
const app = actor.type.app ?? undefined;
|
||||
|
||||
@@ -16,11 +16,10 @@
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
const { APIError } = require('../api/APIError.js');
|
||||
const { APIError } = require('openai');
|
||||
const configurable_auth = require('../middleware/configurable_auth');
|
||||
const { Endpoint } = require('../util/expressutil');
|
||||
const { BaseService } = require('./BaseService');
|
||||
const { revokeUserAppPermsRoute } = require('../routers/auth/revoke-user-app');
|
||||
const BaseService = require('./BaseService');
|
||||
|
||||
/**
|
||||
* @class PermissionAPIService
|
||||
@@ -45,7 +44,7 @@ class PermissionAPIService extends BaseService {
|
||||
async '__on_install.routes' (_, { app }) {
|
||||
app.use(require('../routers/auth/get-user-app-token'));
|
||||
app.use(require('../routers/auth/grant-user-app'));
|
||||
app.use(revokeUserAppPermsRoute);
|
||||
app.use(require('../routers/auth/revoke-user-app'));
|
||||
app.use(require('../routers/auth/grant-dev-app'));
|
||||
app.use(require('../routers/auth/revoke-dev-app'));
|
||||
app.use(require('../routers/auth/grant-user-user'));
|
||||
|
||||
@@ -16,25 +16,35 @@
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import { trace } from '@opentelemetry/api';
|
||||
import { APIError } from '../../api/APIError.js';
|
||||
import { setRedisCacheValue } from '../../clients/redis/cacheUpdate.js';
|
||||
import { deleteRedisKeys } from '../../clients/redis/deleteRedisKeys.js';
|
||||
import { redisClient } from '../../clients/redis/redisSingleton.js';
|
||||
import { hardcoded_user_group_permissions } from '../../data/hardcoded-permissions.js';
|
||||
import { ECMAP } from '../../filesystem/ECMAP.js';
|
||||
import { get_app, get_user } from '../../helpers.js';
|
||||
import scanSequence from '../../structured/sequence/scan-permission.mjs';
|
||||
import { reading_has_terminal } from '../../unstructured/permission-scan-lib.js';
|
||||
import { Context } from '../../util/context.js';
|
||||
import { spanify } from '../../util/otelutil.js';
|
||||
import { BaseService } from '../BaseService.js';
|
||||
import { Actor, UserActorType } from './Actor.js';
|
||||
import { MANAGE_PERM_PREFIX, PERM_KEY_PREFIX } from './permissionConts.mjs';
|
||||
import { PermissionScanRedisCacheSpace } from './PermissionScanRedisCacheSpace.js';
|
||||
import { PermissionExploder, PermissionImplicator, PermissionRewriter, PermissionUtil } from './permissionUtils.mjs';
|
||||
const APIError = require('../../api/APIError');
|
||||
const { hardcoded_user_group_permissions } = require('../../data/hardcoded-permissions.js');
|
||||
const { ECMAP } = require('../../filesystem/ECMAP');
|
||||
const { get_user, get_app } = require('../../helpers');
|
||||
const { reading_has_terminal } = require('../../unstructured/permission-scan-lib');
|
||||
const { trace } = require('@opentelemetry/api');
|
||||
const BaseService = require('../BaseService');
|
||||
const { DB_WRITE } = require('../database/consts');
|
||||
const { UserActorType, Actor, AppUnderUserActorType } = require('./Actor');
|
||||
const { PERM_KEY_PREFIX, MANAGE_PERM_PREFIX } = require('./permissionConts.mjs');
|
||||
const { PermissionUtil, PermissionExploder, PermissionImplicator, PermissionRewriter } = require('./permissionUtils.mjs');
|
||||
const { spanify } = require('../../util/otelutil');
|
||||
const { deleteRedisKeys } = require('../../clients/redis/deleteRedisKeys.js');
|
||||
const { setRedisCacheValue } = require('../../clients/redis/cacheUpdate.js');
|
||||
const { redisClient } = require('../../clients/redis/redisSingleton');
|
||||
const { PermissionScanRedisCacheSpace } = require('./PermissionScanRedisCacheSpace.js');
|
||||
const { Context } = require('../../util/context');
|
||||
|
||||
export class PermissionService extends BaseService {
|
||||
/**
|
||||
* @class PermissionService
|
||||
* @extends BaseService
|
||||
* @description
|
||||
* The PermissionService class manages and enforces permissions within the application. It provides methods to:
|
||||
* - Check, grant, and revoke permissions for users and applications.
|
||||
* - Scan for existing permissions.
|
||||
* - Handle permission implications, rewriting, and explosion to support complex permission hierarchies.
|
||||
* This service interacts with the database to manage permissions and logs actions for auditing purposes.
|
||||
*/
|
||||
class PermissionService extends BaseService {
|
||||
static CONCERN = 'permissions';
|
||||
/**
|
||||
* Initializes the PermissionService by setting up internal arrays for permission handling.
|
||||
@@ -56,25 +66,45 @@ export class PermissionService extends BaseService {
|
||||
* @throws {Error} If the provided exploder is not an instance of PermissionExploder.
|
||||
*/
|
||||
async _init () {
|
||||
|
||||
this.kvService = this.services.get('puter-kvstore');
|
||||
this.db = this.services.get('database');
|
||||
/**
|
||||
* @type {import('../../modules/kvstore/KVStoreInterfaceService.js').KVStoreInterface} db
|
||||
*/
|
||||
this.kvService = this.services.get('puter-kvstore').as('puter-kvstore');
|
||||
this.db = this.services.get('database').get(DB_WRITE, 'permissions');
|
||||
this._register_commands(this.services.get('commands'));
|
||||
this.kvAvgTimes = { count: 0, avg: 0, max: 0 };
|
||||
this.dbAvgTimes = { count: 0, avg: 0, max: 0 };
|
||||
}
|
||||
|
||||
async '__on_boot.consolidation' () {
|
||||
const svc_event = this.services.get('event');
|
||||
// Event to allow extensions to add permissions
|
||||
|
||||
const event = {};
|
||||
event.grant_to_everyone = permission => {
|
||||
hardcoded_user_group_permissions.system[this.global_config.default_temp_group][permission] = {};
|
||||
hardcoded_user_group_permissions.system[this.global_config.default_user_group][permission] = {};
|
||||
};
|
||||
event.grant_to_users = permission => {
|
||||
hardcoded_user_group_permissions[this.global_config.default_user_group][permission] = {};
|
||||
};
|
||||
svc_event.emit('create.permissions', event);
|
||||
|
||||
{
|
||||
const event = {};
|
||||
event.grant_to_everyone = permission => {
|
||||
/* eslint-disable */
|
||||
hardcoded_user_group_permissions
|
||||
.system
|
||||
[this.global_config.default_temp_group]
|
||||
[permission]
|
||||
= {};
|
||||
hardcoded_user_group_permissions
|
||||
.system
|
||||
[this.global_config.default_user_group]
|
||||
[permission]
|
||||
= {};
|
||||
/* eslint-enable */
|
||||
};
|
||||
event.grant_to_users = permission => {
|
||||
/* eslint-disable */
|
||||
hardcoded_user_group_permissions
|
||||
[this.global_config.default_user_group]
|
||||
[permission]
|
||||
= {};
|
||||
/* eslint-enable */
|
||||
};
|
||||
svc_event.emit('create.permissions', event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -191,12 +221,13 @@ export class PermissionService extends BaseService {
|
||||
// cylog(l, 'ACT & PERM:', actor.uid, permission_options);
|
||||
|
||||
const start_ts = Date.now();
|
||||
await scanSequence.call(this, {
|
||||
actor,
|
||||
permission_options,
|
||||
reading,
|
||||
state,
|
||||
});
|
||||
await require('../../structured/sequence/scan-permission.mjs').default
|
||||
.call(this, {
|
||||
actor,
|
||||
permission_options,
|
||||
reading,
|
||||
state,
|
||||
});
|
||||
const end_ts = Date.now();
|
||||
|
||||
// TODO: command to enable these logs
|
||||
@@ -1241,4 +1272,64 @@ export class PermissionService extends BaseService {
|
||||
|
||||
this._permission_exploders.push(exploder);
|
||||
}
|
||||
}
|
||||
|
||||
_register_commands (commands) {
|
||||
commands.registerCommands('perms', [
|
||||
{
|
||||
id: 'grant-user-app',
|
||||
handler: async (args, _log) => {
|
||||
const [username, app_uid, permission, extra] = args;
|
||||
|
||||
// actor from username
|
||||
const actor = new Actor({
|
||||
type: new UserActorType({
|
||||
user: await get_user({ username }),
|
||||
}),
|
||||
});
|
||||
|
||||
await this.grant_user_app_permission(actor, app_uid, permission, extra);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'scan',
|
||||
handler: async (args, ctx) => {
|
||||
const [username, permission] = args;
|
||||
|
||||
// actor from username
|
||||
const actor = new Actor({
|
||||
type: new UserActorType({
|
||||
user: await get_user({ username }),
|
||||
}),
|
||||
});
|
||||
|
||||
let reading = await this.scan(actor, permission);
|
||||
// reading = PermissionUtil.reading_to_options(reading);
|
||||
ctx.log(JSON.stringify(reading, undefined, ' '));
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'scan-app',
|
||||
handler: async (args, ctx) => {
|
||||
const [username, app_name, permission] = args;
|
||||
const app = await get_app({ name: app_name });
|
||||
|
||||
// actor from username
|
||||
const actor = new Actor({
|
||||
type: new AppUnderUserActorType({
|
||||
app,
|
||||
user: await get_user({ username }),
|
||||
}),
|
||||
});
|
||||
|
||||
const reading = await this.scan(actor, permission);
|
||||
// reading = PermissionUtil.reading_to_options(reading);
|
||||
ctx.log(JSON.stringify(reading, undefined, ' '));
|
||||
},
|
||||
},
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
PermissionService,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user