Skip to content

Commit

Permalink
feat: grant user driver perms from admin
Browse files Browse the repository at this point in the history
  • Loading branch information
KernelDeimos committed Jul 26, 2024
1 parent f0c36a1 commit c9ded89
Show file tree
Hide file tree
Showing 6 changed files with 241 additions and 2 deletions.
3 changes: 3 additions & 0 deletions src/backend/src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ config.servers = [];
// Will disable the auto-generated temp users. If a user lands on the site, they will be required to sign up or log in.
config.disable_temp_users = false;

config.default_user_group = '78b1b1dd-c959-44d2-b02c-8735671f9997';
config.default_temp_group = 'b7220104-7905-4985-b996-649fdcdb3c8f';

config.max_file_size = 100_000_000_000,
config.max_thumb_size = 1_000,
config.max_fsentry_name_length = 767,
Expand Down
19 changes: 19 additions & 0 deletions src/backend/src/routers/signup.js
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,14 @@ module.exports = eggspress(['/signup'], {
'UPDATE `user` SET `last_activity_ts` = now() WHERE id=? LIMIT 1',
[insert_res.insertId]
);

// TODO: cache group id
const svc_group = req.services.get('group');
await svc_group.add_users({
uid: req.body.is_temp ?
config.default_temp_group : config.default_user_group,
users: [req.body.username]
});
}
// -----------------------------------
// Pseudo User converting
Expand Down Expand Up @@ -244,6 +252,17 @@ module.exports = eggspress(['/signup'], {
]
);

// TODO: cache group ids
const svc_group = req.services.get('group');
await svc_group.remove_users({
uid: config.default_temp_group,
users: [req.body.username],
});
await svc_group.add_users({
uid: config.default_user_group,
users: [req.body.username]
});

// record activity
db.write('UPDATE `user` SET `last_activity_ts` = now() WHERE id=? LIMIT 1', [pseudo_user.id]);
invalidate_cached_user_by_id(pseudo_user.id);
Expand Down
80 changes: 80 additions & 0 deletions src/backend/src/services/DefaultUserService.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,55 @@
* 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 { QuickMkdir } = require("../filesystem/hl_operations/hl_mkdir");
const { HLWrite } = require("../filesystem/hl_operations/hl_write");
const { NodePathSelector } = require("../filesystem/node/selectors");
const { surrounding_box } = require("../fun/dev-console-ui-utils");
const { get_user, generate_system_fsentries, invalidate_cached_user } = require("../helpers");
const { Context } = require("../util/context");
const { asyncSafeSetInterval } = require("../util/promise");
const { buffer_to_stream } = require("../util/streamutil");
const BaseService = require("./BaseService");
const { Actor, UserActorType } = require("./auth/Actor");
const { DB_WRITE } = require("./database/consts");

const USERNAME = 'admin';

const DEFAULT_FILES = {
'.policy': {
'drivers.json': JSON.stringify({
"temp": {
"kv": {
"rate-limit": {
"max": 1000,
"period": 30000
}
},
"es": {
"date-limit": {
"max": 1000,
"period": 30000
}
},
},
"user": {
"kv": {
"rate-limit": {
"max": 3000,
"period": 30000
}
},
"es": {
"rate-limit": {
"max": 3000,
"period": 30000
}
}
}
}, undefined, ' '),
}
};

class DefaultUserService extends BaseService {
static MODULES = {
bcrypt: require('bcrypt'),
Expand Down Expand Up @@ -100,6 +139,7 @@ class DefaultUserService extends BaseService {
users: [USERNAME]
});
const user = await get_user({ username: USERNAME, cached: false });
const actor = Actor.adapt(user);
const tmp_password = await this.get_tmp_password_(user);
const bcrypt = require('bcrypt');
const password_hashed = await bcrypt.hash(tmp_password, 8);
Expand All @@ -112,6 +152,46 @@ class DefaultUserService extends BaseService {
);
user.password = password_hashed;
await generate_system_fsentries(user);
// generate default files for admin user
const svc_fs = this.services.get('filesystem');
const make_tree_ = async ({ components, tree }) => {
const parent = await svc_fs.node(
new NodePathSelector('/'+components.join('/')),
);
for ( const k in tree ) {
if ( typeof tree[k] === 'string' ) {
const buffer = Buffer.from(tree[k], 'utf-8');
const hl_write = new HLWrite();
await hl_write.run({
destination_or_parent: parent,
specified_name: k,
file: {
size: buffer.length,
stream: buffer_to_stream(buffer),
},
user,
});
} else {
const hl_qmkdir = new QuickMkdir();
await hl_qmkdir.run({
parent,
path: k,
});
const components_ = [...components, k];
await make_tree_({
components: components_,
tree: tree[k],
});
}

}
};
await Context.get().sub({ user, actor }).arun(async () => {
await make_tree_({
components: ['admin'],
tree: DEFAULT_FILES
});
});
invalidate_cached_user(user);
await new Promise(rslv => setTimeout(rslv, 2000));
return user;
Expand Down
11 changes: 9 additions & 2 deletions src/backend/src/services/database/SqliteDatabaseAccessService.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/
const { es_import_promise } = require("../../fun/dev-console-ui-utils");
const { surrounding_box } = require("../../fun/dev-console-ui-utils");
const structutil = require("../../util/structutil");
const { BaseDatabaseAccessService } = require("./BaseDatabaseAccessService");

class SqliteDatabaseAccessService extends BaseDatabaseAccessService {
Expand All @@ -42,7 +43,7 @@ class SqliteDatabaseAccessService extends BaseDatabaseAccessService {
this.db = new Database(this.config.path);

// Database upgrade logic
const TARGET_VERSION = 23;
const TARGET_VERSION = 24;

if ( do_setup ) {
this.log.noticeme(`SETUP: creating database at ${this.config.path}`);
Expand Down Expand Up @@ -71,7 +72,8 @@ class SqliteDatabaseAccessService extends BaseDatabaseAccessService {
'0022_dev-center-max.sql',
'0023_fix-kv.sql',
'0024_default-groups.sql',
'0025_system-user.dbmig.js'
'0025_system-user.dbmig.js',
'0026_user-groups.dbmig.js',
].map(p => path_.join(__dirname, 'sqlite_setup', p));
const fs = require('fs');
for ( const filename of sql_files ) {
Expand Down Expand Up @@ -180,6 +182,10 @@ class SqliteDatabaseAccessService extends BaseDatabaseAccessService {
upgrade_files.push('0025_system-user.dbmig.js');
}

if ( user_version <= 23 ) {
upgrade_files.push('0026_user-groups.dbmig.js');
}

if ( upgrade_files.length > 0 ) {
this.log.noticeme(`Database out of date: ${this.config.path}`);
this.log.noticeme(`UPGRADING DATABASE: ${user_version} -> ${TARGET_VERSION}`);
Expand Down Expand Up @@ -299,6 +305,7 @@ class SqliteDatabaseAccessService extends BaseDatabaseAccessService {
read: this.read.bind(this),
write: this.write.bind(this),
log: this.log,
structutil,
});
await vm.runInContext(contents, context);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
const { insertId: temp_group_id } = await write(
'INSERT INTO `group` (`uid`, `owner_user_id`, `extra`, `metadata`) '+
'VALUES (?, ?, ?, ?)',
[
'b7220104-7905-4985-b996-649fdcdb3c8f',
1,
'{"critical": true, "type": "default", "name": "temp"}',
'{"title": "Guest", "color": "#777777"}'
]
);
const [{id: system_user_id}] = await read(
"SELECT id FROM `user` WHERE username='system'"
);
const [{id: user_group_id}] = await read(
'SELECT id FROM `group` WHERE uid=?',
['78b1b1dd-c959-44d2-b02c-8735671f9997']
);

const user_types = structutil.apply_keys(
['name', 'group_id'],
['temp', temp_group_id],
['user', user_group_id],
);
const drivers = structutil.apply_keys(
['driver_id', 'selector'],
['driver:puter-kvstore', 'kv'],
['driver:puter-notifications', 'es'],
['driver:puter-apps', 'es'],
['driver:puter-subdomains', 'es'],
);

const perms = structutil.cart_product(
[user_types, drivers]);

for ( const perm of perms ) {
const [user_type, driver] = perm;
log.info('permission info', { user_type, driver });
debugger;
// temp user drivers
await write(
'INSERT INTO `user_to_group_permissions` ' +
'(`user_id`, `group_id`, `permission`, `extra`) ' +
'VALUES (?, ?, ?, ?)',
[
system_user_id, user_type.group_id,
driver.driver_id,
JSON.stringify({
policy: {
$: 'json-address',
path: '/admin/.policy/drivers.json',
selector: user_type.name + '.' +
driver.selector,
}
}),
]
);
}

/*
// temp user drivers
await write(
'INSERT INTO `user_to_group_permissions` ' +
'(`user_id`, `group_id`, `permission`, `extra`) ' +
'VALUES (?, ?, ?, ?)',
[
system_user_id, temp_group_id,
'driver:puter-kvstore',
JSON.stringify({
policy: {
$: 'json-address',
path: '/admin/.policy/drivers.json',
selector: 'temp.kv',
}
}),
]
);
// registered user drivers
await write(
'INSERT INTO `user_to_group_permissions` ' +
'(`user_id`, `group_id`, `permission`, `extra`) ' +
'VALUES (?, ?, ?, ?)',
[
system_user_id, user_group_id,
'driver:puter-kvstore',
JSON.stringify({
policy: {
$: 'json-address',
path: '/admin/.policy/drivers.json',
selector: 'user.kv',
}
}),
]
);
*/
35 changes: 35 additions & 0 deletions src/backend/src/util/structutil.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
const cart_product = (obj) => {
// Get array of keys
let keys = Object.keys(obj);

// Generate the Cartesian Product
return keys.reduce((acc, key) => {
let appendArrays = Array.isArray(obj[key]) ? obj[key] : [obj[key]];

let newAcc = [];
acc.forEach(arr => {
appendArrays.forEach(item => {
newAcc.push([...arr, item]);
});
});

return newAcc;
}, [[]]); // start with the "empty product"
}

const apply_keys = (keys, ...entries) => {
const l = [];
for ( const entry of entries ) {
const o = {};
for ( let i=0 ; i < keys.length ; i++ ) {
o[keys[i]] = entry[i];
}
l.push(o);
}
return l;
}

module.exports = {
cart_product,
apply_keys,
};

0 comments on commit c9ded89

Please sign in to comment.