added admin flag to create user command

This commit is contained in:
Erik 2023-07-16 13:58:00 +03:00
parent 9ab9084391
commit b4cec3f1a5
Signed by: Navy.gif
GPG Key ID: 2532FBBB61C65A68
8 changed files with 60 additions and 42 deletions

View File

@ -48,5 +48,5 @@ export type SignupCode = {
export type IPCMessage = { export type IPCMessage = {
_id?: string, _id?: string,
[key: string]: string | number | object | undefined [key: string]: string | number | object | boolean | undefined
} }

View File

@ -19,7 +19,7 @@
"@types/cors": "^2.8.13", "@types/cors": "^2.8.13",
"@types/express-fileupload": "^1.4.1", "@types/express-fileupload": "^1.4.1",
"@types/express-session": "^1.17.7", "@types/express-session": "^1.17.7",
"@types/node": "^18.15.11", "@types/node": "^20.4.2",
"@types/passport-local": "^1.0.35", "@types/passport-local": "^1.0.35",
"@types/qrcode": "^1.5.0", "@types/qrcode": "^1.5.0",
"argon2": "^0.30.3", "argon2": "^0.30.3",

View File

@ -4,13 +4,17 @@ import Controller from './Controller.js';
abstract class BaseCommand extends Command abstract class BaseCommand extends Command
{ {
controller: Controller; #controller: Controller;
constructor (controller: Controller, opts: CommandDefinition) constructor (controller: Controller, opts: CommandDefinition)
{ {
super(opts); super(opts);
this.controller = controller; this.#controller = controller;
} }
abstract override execute(message: unknown, args?: unknown): Promise<unknown>; abstract override execute(message: unknown, args?: unknown): Promise<unknown>;
protected get controller ()
{
return this.#controller;
}
} }
export default BaseCommand; export default BaseCommand;

View File

@ -69,6 +69,9 @@ class Controller extends EventEmitter
this.#serverFilePath = path.resolve(this.#srcDir, options.serverFilePath); this.#serverFilePath = path.resolve(this.#srcDir, options.serverFilePath);
this.#shards = new Collection(); this.#shards = new Collection();
if (options.env.HTTP_PORT)
this.#options.serverOptions.http.port = parseInt(options.env.HTTP_PORT);
process.on('warning', (warn) => process.on('warning', (warn) =>
{ {
this.#logger.warn(warn.stack || warn.message); this.#logger.warn(warn.stack || warn.message);
@ -115,6 +118,21 @@ class Controller extends EventEmitter
return this.#srcDir; return this.#srcDir;
} }
get domain ()
{
return this.#options.serverOptions.domain ?? `localhost:${this.port}`;
}
get protocol ()
{
return this.#options.serverOptions.domain ? 'https' : 'http';
}
get port ()
{
return this.#options.serverOptions.http.port;
}
async init (): Promise<void> async init (): Promise<void>
{ {

View File

@ -1,23 +0,0 @@
import { ArgsResult } from '@navy.gif/commandparser';
import BaseCommand from '../BaseCommand.js';
import Controller from '../Controller.js';
class BootstrapCommand extends BaseCommand
{
constructor (controller: Controller)
{
super(controller, {
name: 'bootstrap',
options: []
});
}
override execute (_message: unknown, _args?: ArgsResult): Promise<unknown>
{
throw new Error('Method not implemented.');
}
}
export default BootstrapCommand;

View File

@ -23,7 +23,7 @@ class CreateCommand extends BaseCommand
defaultValue: 1 defaultValue: 1
}] }]
}, { }, {
name: 'account', name: 'user',
type: OptionType.SUB_COMMAND, type: OptionType.SUB_COMMAND,
options: [{ options: [{
name: 'name', name: 'name',
@ -31,6 +31,12 @@ class CreateCommand extends BaseCommand
}, { }, {
name: 'password', name: 'password',
type: OptionType.STRING type: OptionType.STRING
}, {
name: 'admin',
type: OptionType.BOOLEAN,
flag: true,
valueOptional: true,
defaultValue: true
}] }]
}] }]
}); });
@ -42,7 +48,7 @@ class CreateCommand extends BaseCommand
if (subcommand === 'registration-code') if (subcommand === 'registration-code')
return this.#code(args); return this.#code(args);
else if (subcommand === 'account') else if (subcommand === 'user')
return this.#account(args); return this.#account(args);
return 'Unknown subcommand'; return 'Unknown subcommand';
@ -50,13 +56,16 @@ class CreateCommand extends BaseCommand
async #account (args: ArgsResult) async #account (args: ArgsResult)
{ {
const { name, password } = args; const { name, password, admin } = args;
let accountName = 'admin'; let accountName = 'admin',
let accountPass = Util.randomString(); accountPass = Util.randomString(),
isAdmin = false;
if (name) if (name)
accountName = name.value as string; accountName = name.value as string;
if (password) if (password)
accountPass = password.value as string; accountPass = password.value as string;
if (admin)
isAdmin = admin.value as boolean;
const shard = this.controller.shards.random(); const shard = this.controller.shards.random();
if (!shard) if (!shard)
@ -65,7 +74,8 @@ class CreateCommand extends BaseCommand
const msg = { const msg = {
type: 'account-create', type: 'account-create',
accountName, accountName,
accountPass accountPass,
isAdmin
}; };
const response = await shard.send(msg, true) as IPCMessage; const response = await shard.send(msg, true) as IPCMessage;
if (response.success) if (response.success)
@ -87,11 +97,12 @@ class CreateCommand extends BaseCommand
return 'Did not get a response from shard'; return 'Did not get a response from shard';
const codes = response.codes as SignupCode[]; const codes = response.codes as SignupCode[];
let out = `Created codes, valid until ${new Date(codes[0].created + codes[0].validFor).toUTCString()}:\n`; const out = `Created codes, valid until ${new Date(codes[0].created + codes[0].validFor).toUTCString()}:\n`;
const codesOut = [];
for (const invite of codes) for (const invite of codes)
out += `${invite.code}\n`; codesOut.push(`${this.controller.protocol}://${this.controller.domain}/register?code=${invite.code}`);
return out; return out + codesOut.join('\n');
} }
} }

View File

@ -86,7 +86,6 @@ class Server extends EventEmitter
MONGO_MEMORY_URI, MONGO_MEMORY_HOST, MONGO_MEMORY_USER, MONGO_MEMORY_PORT, MONGO_MEMORY_URI, MONGO_MEMORY_HOST, MONGO_MEMORY_USER, MONGO_MEMORY_PORT,
MONGO_MEMORY_PASS, MONGO_MEMORY_DB, MONGO_MEMORY_AUTH_DB, MONGO_MEMORY_PASS, MONGO_MEMORY_DB, MONGO_MEMORY_AUTH_DB,
RABBIT_HOST, RABBIT_USER, RABBIT_PASS, RABBIT_VHOST, RABBIT_PORT, RABBIT_HOST, RABBIT_USER, RABBIT_PASS, RABBIT_VHOST, RABBIT_PORT,
PORT
} = process.env as { [key: string]: string }; } = process.env as { [key: string]: string };
const { http: httpOpts, databases, name } = options; const { http: httpOpts, databases, name } = options;
@ -108,8 +107,7 @@ class Server extends EventEmitter
this.#logger = new LoggerClient({ ...options.logger, name: this.constructor.name }); this.#logger = new LoggerClient({ ...options.logger, name: this.constructor.name });
// Port number is automatically incremented based on shard # // Port number is automatically incremented based on shard #
const _port = parseInt(PORT); this.#port = httpOpts.port + this.#shardId;
this.#port = isNaN(_port) ? httpOpts.port + this.#shardId : _port;
// Primarily used by the OAuth methods for the callback url // Primarily used by the OAuth methods for the callback url
if (NODE_ENV === 'development') if (NODE_ENV === 'development')
{ {
@ -409,11 +407,14 @@ class Server extends EventEmitter
{ {
const name = msg.accountName as string; const name = msg.accountName as string;
const pass = msg.accountPass as string; const pass = msg.accountPass as string;
const admin = msg.isAdmin as boolean;
this.#logger.info(`Creating account ${name}`); this.#logger.info(`Creating account ${name}`);
try try
{ {
await this.users.createUser(name, pass); const user = await this.users.createUser(name, pass);
process.send({ _id: msg._id, success: true }); process.send({ _id: msg._id, success: true });
if (admin)
await user.updatePermissions({ administrator: { default: 10 } });
} }
catch (err) catch (err)
{ {

View File

@ -2087,13 +2087,20 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@types/node@npm:*, @types/node@npm:^18.15.11": "@types/node@npm:*":
version: 18.15.11 version: 18.15.11
resolution: "@types/node@npm:18.15.11" resolution: "@types/node@npm:18.15.11"
checksum: 977b4ad04708897ff0eb049ecf82246d210939c82461922d20f7d2dcfd81bbc661582ba3af28869210f7e8b1934529dcd46bff7d448551400f9d48b9d3bddec3 checksum: 977b4ad04708897ff0eb049ecf82246d210939c82461922d20f7d2dcfd81bbc661582ba3af28869210f7e8b1934529dcd46bff7d448551400f9d48b9d3bddec3
languageName: node languageName: node
linkType: hard linkType: hard
"@types/node@npm:^20.4.2":
version: 20.4.2
resolution: "@types/node@npm:20.4.2"
checksum: 99e544ea7560d51f01f95627fc40394c24a13da8f041121a0da13e4ef0a2aa332932eaf9a5e8d0e30d1c07106e96a183be392cbba62e8cf0bf6a085d5c0f4149
languageName: node
linkType: hard
"@types/passport-local@npm:^1.0.35": "@types/passport-local@npm:^1.0.35":
version: 1.0.35 version: 1.0.35
resolution: "@types/passport-local@npm:1.0.35" resolution: "@types/passport-local@npm:1.0.35"
@ -7042,7 +7049,7 @@ __metadata:
"@types/cors": ^2.8.13 "@types/cors": ^2.8.13
"@types/express-fileupload": ^1.4.1 "@types/express-fileupload": ^1.4.1
"@types/express-session": ^1.17.7 "@types/express-session": ^1.17.7
"@types/node": ^18.15.11 "@types/node": ^20.4.2
"@types/passport-local": ^1.0.35 "@types/passport-local": ^1.0.35
"@types/qrcode": ^1.5.0 "@types/qrcode": ^1.5.0
"@typescript-eslint/eslint-plugin": ^5.58.0 "@typescript-eslint/eslint-plugin": ^5.58.0