Browse Source

Create default user

KernelDeimos 1 năm trước cách đây
mục cha
commit
4845bd28a1

+ 40 - 0
package-lock.json

@@ -9637,6 +9637,45 @@
       "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz",
       "integrity": "sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A=="
     },
+    "node_modules/string-length": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/string-length/-/string-length-6.0.0.tgz",
+      "integrity": "sha512-1U361pxZHEQ+FeSjzqRpV+cu2vTzYeWeafXFLykiFlv4Vc0n3njgU8HrMbyik5uwm77naWMuVG8fhEF+Ovb1Kg==",
+      "dependencies": {
+        "strip-ansi": "^7.1.0"
+      },
+      "engines": {
+        "node": ">=16"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/string-length/node_modules/ansi-regex": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
+      "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+      }
+    },
+    "node_modules/string-length/node_modules/strip-ansi": {
+      "version": "7.1.0",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+      "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+      "dependencies": {
+        "ansi-regex": "^6.0.1"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+      }
+    },
     "node_modules/string-width": {
       "version": "4.2.3",
       "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
@@ -10807,6 +10846,7 @@
         "socket.io": "^4.6.2",
         "ssh2": "^1.13.0",
         "string-hash": "^1.1.3",
+        "string-length": "^6.0.0",
         "svgo": "^3.0.2",
         "tiktoken": "^1.0.11",
         "uglify-js": "^3.17.4",

+ 1 - 0
packages/backend/package.json

@@ -61,6 +61,7 @@
     "socket.io": "^4.6.2",
     "ssh2": "^1.13.0",
     "string-hash": "^1.1.3",
+    "string-length": "^6.0.0",
     "svgo": "^3.0.2",
     "tiktoken": "^1.0.11",
     "uglify-js": "^3.17.4",

+ 3 - 0
packages/backend/src/CoreModule.js

@@ -182,6 +182,9 @@ const install = async ({ services, app }) => {
     const { EventService } = require('./services/EventService');
     services.registerService('event', EventService);
 
+    const DefaultUserService = require('./services/DefaultUserService');
+    services.registerService('__default-user', DefaultUserService);
+
 }
 
 const install_legacy = async ({ services }) => {

+ 1 - 0
packages/backend/src/Kernel.js

@@ -183,6 +183,7 @@ class Kernel extends AdvancedBase {
 
 
         await services.emit('start.webserver');
+        await services.emit('ready.webserver');
     }
 }
 

+ 32 - 0
packages/backend/src/fun/dev-console-ui-utils.js

@@ -0,0 +1,32 @@
+const { TeePromise } = require('../util/promise');
+
+const es_import_promise = new TeePromise();
+let stringLength;
+(async () => {
+    stringLength = (await import('string-length')).default;
+    es_import_promise.resolve();
+    // console.log('STRING LENGTH', stringLength);
+    // process.exit(0);
+})();
+const surrounding_box = (col, lines, lengths) => {
+    if ( ! lengths ) {
+        lengths = lines.map(line => stringLength(line));
+    }
+
+    const max_length = Math.max(...lengths);
+    const c = str => `\x1b[${col}m${str}\x1b[0m`;
+    const bar = c(Array(max_length + 4).fill('━').join(''));
+    for ( let i = 0 ; i < lines.length ; i++ ) {
+        while ( stringLength(lines[i]) < max_length ) {
+            lines[i] += ' ';
+        }
+        lines[i] = `${c('┃ ')} ${lines[i]} ${c(' ┃')}`;
+    }
+    lines.unshift(`${c('┏')}${bar}${c('┓')}`);
+    lines.push(`${c('┗')}${bar}${c('┛')}`);
+};
+
+module.exports = {
+    surrounding_box,
+    es_import_promise,
+};

+ 80 - 0
packages/backend/src/services/DefaultUserService.js

@@ -0,0 +1,80 @@
+const { surrounding_box } = require("../fun/dev-console-ui-utils");
+const { get_user, generate_system_fsentries } = require("../helpers");
+const { asyncSafeSetInterval } = require("../util/promise");
+const BaseService = require("./BaseService");
+const { DB_WRITE } = require("./database/consts");
+
+const DEFAULT_PASSWORD = 'changeme';
+const USERNAME = 'default_user';
+
+class DefaultUserService extends BaseService {
+    static MODULES = {
+        bcrypt: require('bcrypt'),
+        uuidv4: require('uuid').v4,
+    }
+    async _init () {
+    }
+    async ['__on_ready.webserver'] () {
+        // check if a user named `default-user` exists
+        let user = await get_user({ username: USERNAME });
+        if ( ! user ) user = await this.create_default_user_();
+
+        // check if user named `default-user` is using default password
+        const require = this.require;
+        const bcrypt = require('bcrypt');
+        const is_default_password = await bcrypt.compare(DEFAULT_PASSWORD, user.password);
+        if ( ! is_default_password ) return;
+
+        // show console widget
+        this.default_user_widget = () => {
+            const lines = [
+                `Your default user has been created!`,
+                `\x1B[31;1musername:\x1B[0m ${USERNAME}`,
+                `\x1B[32;1mpassword:\x1B[0m ${DEFAULT_PASSWORD}`,
+                `(change the password to remove this message)`
+            ];
+            surrounding_box('31;1', lines);
+            return lines;
+        };
+        this.start_poll_();
+        const svc_devConsole = this.services.get('dev-console');
+        svc_devConsole.add_widget(this.default_user_widget);
+    }
+    start_poll_ () {
+        const interval = 1000 * 3; // 3 seconds
+        const poll_interval = asyncSafeSetInterval(async () => {
+            const user = await get_user({ username: USERNAME });
+            const require = this.require;
+            const bcrypt = require('bcrypt');
+            const is_default_password = await bcrypt.compare(DEFAULT_PASSWORD, user.password);
+            if ( ! is_default_password ) {
+                const svc_devConsole = this.services.get('dev-console');
+                svc_devConsole.remove_widget(this.default_user_widget);
+                clearInterval(poll_interval);
+                return;
+            }
+        }, interval);
+    }
+    async create_default_user_ () {
+        const require = this.require;
+        const bcrypt = require('bcrypt');
+        const db = this.services.get('database').get(DB_WRITE, 'default-user');
+        await db.write(
+            `
+                INSERT INTO user (uuid, username, password, free_storage)
+                VALUES (?, ?, ?, ?)
+            `,
+            [
+                this.modules.uuidv4(),
+                USERNAME,
+                await bcrypt.hash(DEFAULT_PASSWORD, 8),
+                1024 * 1024 * 1024 * 10, // 10 GB
+            ],
+        );
+        const user = await get_user({ username: USERNAME });
+        await generate_system_fsentries(user);
+        return user;
+    }
+}
+
+module.exports = DefaultUserService;

+ 4 - 12
packages/backend/src/services/WebServerService.js

@@ -27,6 +27,7 @@ var http = require('http');
 const fs = require('fs');
 const auth = require('../middleware/auth');
 const { osclink } = require('../util/strutil');
+const { surrounding_box, es_import_promise } = require('../fun/dev-console-ui-utils');
 
 class WebServerService extends BaseService {
     static MODULES = {
@@ -42,6 +43,7 @@ class WebServerService extends BaseService {
     };
 
     async ['__on_start.webserver'] () {
+        await es_import_promise;
 
         // error handling middleware goes last, as per the
         // expressjs documentation:
@@ -122,17 +124,7 @@ class WebServerService extends BaseService {
                 lines[2].length,
                 0,
             ];
-            const max_length = Math.max(...lengths);
-            const c = str => `\x1b[34;1m${str}\x1b[0m`;
-            const bar = c(Array(max_length + 4).fill('━').join(''));
-            for ( let i = 0 ; i < lines.length ; i++ ) {
-                while ( lines[i].length < max_length ) {
-                    lines[i] += ' ';
-                }
-                lines[i] = `${c('┃ ')} ${lines[i]} ${c(' ┃')}`;
-            }
-            lines.unshift(`${c('┏')}${bar}${c('┓')}`);
-            lines.push(`${c('┗')}${bar}${c('┛')}`);
+            surrounding_box('34;1', lines, lengths);
             return lines;
         };
         {
@@ -360,7 +352,7 @@ class WebServerService extends BaseService {
             const pad = (width - last_logo.sz) / 2;
             const asymmetrical = pad % 1 !== 0;
             const pad_left = Math.floor(pad);
-            const pad_right = Math.ceil(pad) + (asymmetrical ? 1 : 0);
+            const pad_right = Math.ceil(pad);
             for ( let i = 0 ; i < lines.length ; i++ ) {
                 lines[i] = ' '.repeat(pad_left) + lines[i] + ' '.repeat(pad_right);
             }