diff --git a/migrations/20190215215805-tokens-add-id.js b/migrations/20190215215805-tokens-add-id.js index b2ec903c1..1bf6b0bad 100644 --- a/migrations/20190215215805-tokens-add-id.js +++ b/migrations/20190215215805-tokens-add-id.js @@ -1,7 +1,7 @@ 'use strict'; -var async = require('async'); -var uuid = require('uuid'); +const async = require('async'), + crypto = require('crypto'); exports.up = function(db, callback) { async.series([ @@ -12,7 +12,7 @@ exports.up = function(db, callback) { function (done) { db.runSql('SELECT * FROM tokens', function (error, tokens) { async.eachSeries(tokens, function (token, iteratorDone) { - db.runSql('UPDATE tokens SET id=? WHERE accessToken=?', [ 'tid-'+uuid.v4(), token.accessToken ], iteratorDone); + db.runSql('UPDATE tokens SET id=? WHERE accessToken=?', [ 'tid-'+cryptorandomUUID(), token.accessToken ], iteratorDone); }, done); }); }, diff --git a/migrations/20220602050517-apps-add-storageVolumeId.js b/migrations/20220602050517-apps-add-storageVolumeId.js index 08dec7221..696272b0d 100644 --- a/migrations/20220602050517-apps-add-storageVolumeId.js +++ b/migrations/20220602050517-apps-add-storageVolumeId.js @@ -1,8 +1,8 @@ 'use strict'; -const path = require('path'), - safe = require('safetydance'), - uuid = require('uuid'); +const crypto = require('crypto'), + path = require('path'), + safe = require('safetydance'); function getMountPoint(dataDir) { const output = safe.child_process.execSync(`df --output=target "${dataDir}" | tail -1`, { encoding: 'utf8' }); @@ -37,7 +37,7 @@ exports.up = async function(db) { continue; } - const id = uuid.v4().replace(/-/g, ''); // to make systemd mount file names more readable + const id = crypto.randomUUID().replace(/-/g, ''); // to make systemd mount file names more readable const name = `appdata-${id}`; const type = app.dataDir === mountPoint ? 'filesystem' : 'mountpoint'; diff --git a/migrations/20250507122501-dockerRegistries-create-table.js b/migrations/20250507122501-dockerRegistries-create-table.js index 09628af34..efe6aa8bd 100644 --- a/migrations/20250507122501-dockerRegistries-create-table.js +++ b/migrations/20250507122501-dockerRegistries-create-table.js @@ -1,6 +1,6 @@ 'use strict'; -const uuid = require('uuid'); +const crypto = require('crypto'); exports.up = async function (db) { const cmd = 'CREATE TABLE IF NOT EXISTS dockerRegistries(' + @@ -22,7 +22,7 @@ exports.up = async function (db) { if (registryConfig.provider !== 'noop') { await db.runSql('INSERT INTO dockerRegistries (id, provider, serverAddress, username, email, password) VALUES (?, ?, ?, ?, ?, ?)', - [ `rc-${uuid.v4()}`, registryConfig.provider, registryConfig.serverAddress, registryConfig.username, registryConfig.email || null, registryConfig.password ]); + [ `rc-${crypto.randomUUID()}`, registryConfig.provider, registryConfig.serverAddress, registryConfig.username, registryConfig.email || null, registryConfig.password ]); } await db.runSql('DELETE FROM settings WHERE name=?', [ 'registry_config']); diff --git a/migrations/20250724102340-backupTargets-create-table.js b/migrations/20250724102340-backupTargets-create-table.js index c99c20bcb..2bbaf2542 100644 --- a/migrations/20250724102340-backupTargets-create-table.js +++ b/migrations/20250724102340-backupTargets-create-table.js @@ -1,7 +1,7 @@ 'use strict'; -const paths = require('../src/paths.js'), - uuid = require('uuid'); +const crypto = require('crypto'), + paths = require('../src/paths.js'); exports.up = async function (db) { const cmd = 'CREATE TABLE IF NOT EXISTS backupTargets(' + @@ -58,7 +58,7 @@ exports.up = async function (db) { await db.runSql('START TRANSACTION'); await db.runSql('INSERT INTO backupTargets (id, label, provider, configJson, limitsJson, retentionJson, schedule, encryptionJson, format, main) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', - [ `bc-${uuid.v4()}`, label, provider, JSON.stringify(config), JSON.stringify(limits), JSON.stringify(retention), schedule, JSON.stringify(encryption), format, main ]); + [ `bc-${crypto.randomUUID()}`, label, provider, JSON.stringify(config), JSON.stringify(limits), JSON.stringify(retention), schedule, JSON.stringify(encryption), format, main ]); await db.runSql('DELETE FROM settings WHERE name=? OR name=? OR name=?', [ 'backup_storage', 'backup_limits', 'backup_policy' ]); await db.runSql('COMMIT'); diff --git a/migrations/20250724141339-backups-add-targetId.js b/migrations/20250724141339-backups-add-targetId.js index e0c4a9945..481024381 100644 --- a/migrations/20250724141339-backups-add-targetId.js +++ b/migrations/20250724141339-backups-add-targetId.js @@ -1,6 +1,6 @@ 'use strict'; -const uuid = require('uuid'); +const crypto = require('crypto'); exports.up = async function(db) { let results = await db.runSql('SELECT format, COUNT(*) AS count FROM backups GROUP BY format WITH ROLLUP', []); // https://dev.mysql.com/doc/refman/8.4/en/group-by-modifiers.html @@ -19,7 +19,7 @@ exports.up = async function(db) { const current = results[0]; let clone = null; if (current.format !== theOneFormat) { - clone = Object.assign({}, results[0], { id: `bc-${uuid.v4()}` }); + clone = Object.assign({}, results[0], { id: `bc-${crypto.randomUUID()}` }); clone.format = current.format === 'rsync' ? 'tgz' : 'rsync'; clone.priority = false; clone.schedule = 'never'; diff --git a/package-lock.json b/package-lock.json index bef14f724..8595f5800 100644 --- a/package-lock.json +++ b/package-lock.json @@ -51,7 +51,6 @@ "tar-stream": "^3.1.7", "tldjs": "^2.3.2", "ua-parser-js": "^2.0.4", - "uuid": "^11.1.0", "ws": "^8.18.3", "xml2js": "^0.6.2" }, @@ -8283,19 +8282,6 @@ "node": ">= 0.4.0" } }, - "node_modules/uuid": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", - "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/esm/bin/uuid" - } - }, "node_modules/validator": { "version": "13.15.15", "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.15.tgz", diff --git a/package.json b/package.json index 2a9306a58..22ce6326f 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,6 @@ "tar-stream": "^3.1.7", "tldjs": "^2.3.2", "ua-parser-js": "^2.0.4", - "uuid": "^11.1.0", "ws": "^8.18.3", "xml2js": "^0.6.2" }, diff --git a/src/applinks.js b/src/applinks.js index 7a2f84e41..e40e9eda4 100644 --- a/src/applinks.js +++ b/src/applinks.js @@ -12,12 +12,12 @@ exports = module.exports = { const assert = require('assert'), apps = require('./apps.js'), BoxError = require('./boxerror.js'), + crypto = require('crypto'), database = require('./database.js'), debug = require('debug')('box:applinks'), jsdom = require('jsdom'), safe = require('safetydance'), - superagent = require('@cloudron/superagent'), - uuid = require('uuid'); + superagent = require('@cloudron/superagent'); const APPLINKS_FIELDS= [ 'id', 'accessRestrictionJson', 'creationTime', 'updateTime', 'ts', 'label', 'tagsJson', 'icon', 'upstreamUri' ].join(','); @@ -181,7 +181,7 @@ async function add(applink) { } const data = { - id: uuid.v4(), + id: crypto.randomUUID(), accessRestrictionJson: applink.accessRestriction ? JSON.stringify(applink.accessRestriction) : null, label: applink.label || '', tagsJson: applink.tags ? JSON.stringify(applink.tags) : null, diff --git a/src/apppasswords.js b/src/apppasswords.js index 1bc29ac57..83b073171 100644 --- a/src/apppasswords.js +++ b/src/apppasswords.js @@ -15,7 +15,6 @@ const assert = require('assert'), database = require('./database.js'), hat = require('./hat.js'), safe = require('safetydance'), - uuid = require('uuid'), _ = require('./underscore.js'); const APP_PASSWORD_FIELDS = [ 'id', 'name', 'userId', 'identifier', 'hashedPassword', 'creationTime' ].join(','); @@ -55,7 +54,7 @@ async function add(userId, identifier, name) { const hashedPassword = crypto.createHash('sha256').update(password).digest('base64'); const appPassword = { - id: 'uid-' + uuid.v4(), + id: 'uid-' + crypto.randomUUID(), name, userId, identifier, diff --git a/src/apps.js b/src/apps.js index 2ecc13a47..07441ae3d 100644 --- a/src/apps.js +++ b/src/apps.js @@ -155,6 +155,7 @@ const appTaskManager = require('./apptaskmanager.js'), backupTargets = require('./backuptargets.js'), BoxError = require('./boxerror.js'), constants = require('./constants.js'), + crypto = require('crypto'), { CronTime } = require('cron'), dashboard = require('./dashboard.js'), database = require('./database.js'), @@ -186,7 +187,6 @@ const appTaskManager = require('./apptaskmanager.js'), TransformStream = require('stream').Transform, users = require('./users.js'), util = require('util'), - uuid = require('uuid'), volumes = require('./volumes.js'), _ = require('./underscore.js'); @@ -1479,7 +1479,7 @@ async function install(data, auditSource) { if (constants.DEMO && (await getCount() >= constants.DEMO_APP_LIMIT)) throw new BoxError(BoxError.BAD_STATE, 'Too many installed apps, please uninstall a few and try again'); - const appId = uuid.v4(); + const appId = crypto.randomUUID(); debug(`Installing app ${appId}`); const app = { @@ -2457,7 +2457,7 @@ async function clone(app, data, user, auditSource) { const mailboxName = manifest.addons?.sendmail ? mailboxNameForSubdomain(subdomain, manifest) : null; const mailboxDomain = manifest.addons?.sendmail ? domain : null; - const newAppId = uuid.v4(); + const newAppId = crypto.randomUUID(); // label, checklist intentionally omitted . icon is loaded in apptask from the backup const dolly = _.pick(backup.appConfig || app, ['memoryLimit', 'cpuQuota', 'crontab', 'reverseProxyConfig', 'env', 'servicesConfig', 'tags', 'devices', @@ -2533,7 +2533,7 @@ async function unarchive(archive, data, auditSource) { if (error) throw error; const portBindings = translateToPortBindings(data.ports || null, manifest); - const appId = uuid.v4(); + const appId = crypto.randomUUID(); // appConfig is null for pre-8.2 backups const dolly = _.pick(backup.appConfig || {}, ['memoryLimit', 'cpuQuota', 'crontab', 'reverseProxyConfig', 'env', 'servicesConfig', diff --git a/src/archives.js b/src/archives.js index d45e04d59..d855ea348 100644 --- a/src/archives.js +++ b/src/archives.js @@ -12,10 +12,10 @@ exports = module.exports = { const assert = require('assert'), BoxError = require('./boxerror.js'), + crypto = require('crypto'), database = require('./database.js'), eventlog = require('./eventlog.js'), - safe = require('safetydance'), - uuid = require('uuid'); + safe = require('safetydance'); const ARCHIVE_FIELDS = [ 'archives.id', 'backupId', 'archives.creationTime', 'backups.remotePath', 'backups.manifestJson', 'backups.appConfigJson', '(archives.icon IS NOT NULL) AS hasIcon', '(archives.appStoreIcon IS NOT NULL) AS hasAppStoreIcon' ]; @@ -68,7 +68,7 @@ async function add(backupId, data, auditSource) { assert.strictEqual(typeof data, 'object'); assert(auditSource && typeof auditSource === 'object'); - const id = uuid.v4(); + const id = crypto.randomUUID(); const [error] = await safe(database.query('INSERT INTO archives (id, backupId, icon, appStoreIcon) VALUES (?, ?, ?, ?)', [ id, backupId, data.icon, data.appStoreIcon ])); diff --git a/src/backuptargets.js b/src/backuptargets.js index 0cac1402e..03d524b0f 100644 --- a/src/backuptargets.js +++ b/src/backuptargets.js @@ -38,6 +38,7 @@ const assert = require('assert'), constants = require('./constants.js'), cron = require('./cron.js'), { CronTime } = require('cron'), + crypto = require('crypto'), database = require('./database.js'), debug = require('debug')('box:backups'), eventlog = require('./eventlog.js'), @@ -48,8 +49,7 @@ const assert = require('assert'), paths = require('./paths.js'), safe = require('safetydance'), storage = require('./storage.js'), - tasks = require('./tasks.js'), - uuid = require('uuid'); + tasks = require('./tasks.js'); const BACKUP_TARGET_FIELDS = [ 'id', 'label', 'provider', 'configJson', 'limitsJson', 'retentionJson', 'schedule', 'encryptionJson', 'format', 'main', 'creationTime', 'ts' ].join(','); @@ -460,7 +460,7 @@ async function add(data, auditSource) { debug('setStorage: setting up new storage configuration'); await storage.setupManagedMount(provider, config, paths.MANAGED_BACKUP_MOUNT_DIR); - const id = `bc-${uuid.v4()}`; + const id = `bc-${crypto.randomUUID()}`; await database.query('INSERT INTO backupTargets (id, label, provider, configJson, limitsJson, retentionJson, schedule, encryptionJson, format, main) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', [ id, label, provider, JSON.stringify(config), JSON.stringify(limits), JSON.stringify(retention), schedule, JSON.stringify(encryption), format, false ]); diff --git a/src/database.js b/src/database.js index 585507e4a..8128089f9 100644 --- a/src/database.js +++ b/src/database.js @@ -66,7 +66,7 @@ async function initialize() { // await connection.query('SET NAMES utf8mb4 COLLATE utf8mb4_bin'); await conn.query('SET SESSION sql_mode = \'strict_all_tables\''); // disable type coercion etc // GROUP_CONCAT has only 1024 default. we use it in the groups API which doesn't support pagination yet - // a uuid v4 is 36 in length. so the value below provides for roughly 10k users + // a crypto.randomUUID is 36 in length. so the value below provides for roughly 10k users await conn.query('SET SESSION group_concat_max_len = 360000'); } catch (error) { debug(`failed to init new db connection ${connection.threadId}:`, error); // only log. we will let the app handle the exception when it calls query()/transaction() diff --git a/src/dockerregistries.js b/src/dockerregistries.js index 01b706177..3a739ca85 100644 --- a/src/dockerregistries.js +++ b/src/dockerregistries.js @@ -13,13 +13,13 @@ exports = module.exports = { const assert = require('assert'), BoxError = require('./boxerror.js'), constants = require('./constants.js'), + crypto = require('crypto'), database = require('./database.js'), Docker = require('dockerode'), eventlog = require('./eventlog.js'), paths = require('./paths.js'), safe = require('safetydance'), - tld = require('tldjs'), - uuid = require('uuid'); + tld = require('tldjs'); const REGISTRY_FIELDS = [ 'id', 'provider', 'serverAddress', 'username', 'email', 'password' ].join(','); @@ -78,7 +78,7 @@ async function add(registry, auditSource) { await testRegistryConfig(registry); - const id = `rc-${uuid.v4()}`; + const id = `rc-${crypto.randomUUID()}`; await database.query('INSERT INTO dockerRegistries (id, provider, serverAddress, username, email, password) VALUES (?, ?, ?, ?, ?, ?)', [ id , registry.provider, registry.serverAddress, registry.username || null, registry.email || null, registry.password || null ]); diff --git a/src/eventlog.js b/src/eventlog.js index 559f9493f..fe680e354 100644 --- a/src/eventlog.js +++ b/src/eventlog.js @@ -116,12 +116,12 @@ exports = module.exports = { }; const assert = require('assert'), + crypto = require('crypto'), database = require('./database.js'), debug = require('debug')('box:eventlog'), mysql = require('mysql2'), notifications = require('./notifications.js'), - safe = require('safetydance'), - uuid = require('uuid'); + safe = require('safetydance'); const EVENTLOG_FIELDS = [ 'id', 'action', 'sourceJson', 'dataJson', 'creationTime' ].join(','); @@ -141,7 +141,7 @@ async function add(action, source, data) { assert.strictEqual(typeof source, 'object'); // an AuditSource assert.strictEqual(typeof data, 'object'); - const id = uuid.v4(); + const id = crypto.randomUUID(); await database.query('INSERT INTO eventlog (id, action, sourceJson, dataJson) VALUES (?, ?, ?, ?)', [ id, action, JSON.stringify(source), JSON.stringify(data) ]); await notifications.onEvent(id, action, source, data); return id; diff --git a/src/groups.js b/src/groups.js index e5dc5428d..0eb2c0632 100644 --- a/src/groups.js +++ b/src/groups.js @@ -30,10 +30,10 @@ const apps = require('./apps.js'), assert = require('assert'), BoxError = require('./boxerror.js'), constants = require('./constants.js'), + crypto = require('crypto'), database = require('./database.js'), eventlog = require('./eventlog.js'), - safe = require('safetydance'), - uuid = require('uuid'); + safe = require('safetydance'); const GROUPS_FIELDS = [ 'id', 'name', 'source' ].join(','); @@ -75,7 +75,7 @@ async function add(group, auditSource) { error = validateSource(source); if (error) throw error; - const id = `gid-${uuid.v4()}`; + const id = `gid-${crypto.randomUUID()}`; [error] = await safe(database.query('INSERT INTO userGroups (id, name, source) VALUES (?, ?, ?)', [ id, name, source ])); if (error && error.code === 'ER_DUP_ENTRY') throw new BoxError(BoxError.ALREADY_EXISTS, error); diff --git a/src/tokens.js b/src/tokens.js index 1b79e0b8c..878a8af16 100644 --- a/src/tokens.js +++ b/src/tokens.js @@ -24,11 +24,11 @@ const TOKENS_FIELDS = [ 'id', 'accessToken', 'identifier', 'clientId', 'scopeJso const assert = require('assert'), BoxError = require('./boxerror.js'), + crypto = require('crypto'), database = require('./database.js'), hat = require('./hat.js'), ipaddr = require('./ipaddr.js'), - safe = require('safetydance'), - uuid = require('uuid'); + safe = require('safetydance'); const gParsedRangesCache = new Map(); // indexed by token.id @@ -110,7 +110,7 @@ async function add(token) { parseIpRanges(allowedIpRanges); // validate - const id = 'tid-' + uuid.v4(); + const id = 'tid-' + crypto.randomUUID(); const accessToken = token.accessToken || hat(8 * 32); await database.query('INSERT INTO tokens (id, accessToken, identifier, clientId, expires, scopeJson, name, allowedIpRanges) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', [ id, accessToken, identifier, clientId, expires, JSON.stringify(scope), name, allowedIpRanges ]); diff --git a/src/users.js b/src/users.js index 24567dec9..4a2ed177a 100644 --- a/src/users.js +++ b/src/users.js @@ -100,7 +100,6 @@ const appPasswords = require('./apppasswords.js'), translations = require('./translations.js'), uaParser = require('ua-parser-js'), userDirectory = require('./user-directory.js'), - uuid = require('uuid'), superagent = require('@cloudron/superagent'), util = require('util'), validator = require('./validator.js'), @@ -257,7 +256,7 @@ async function add(email, data, auditSource) { if (pbkdf2Error) throw new BoxError(BoxError.CRYPTO_ERROR, pbkdf2Error); const user = { - id: 'uid-' + uuid.v4(), + id: 'uid-' + crypto.randomUUID(), username, email, fallbackEmail, diff --git a/src/volumes.js b/src/volumes.js index 19fb085c2..a238c36dc 100644 --- a/src/volumes.js +++ b/src/volumes.js @@ -19,6 +19,7 @@ exports = module.exports = { const assert = require('assert'), BoxError = require('./boxerror.js'), constants = require('./constants.js'), + crypto = require('crypto'), database = require('./database.js'), debug = require('debug')('box:volumes'), eventlog = require('./eventlog.js'), @@ -26,8 +27,7 @@ const assert = require('assert'), path = require('path'), paths = require('./paths.js'), safe = require('safetydance'), - services = require('./services.js'), - uuid = require('uuid'); + services = require('./services.js'); const VOLUMES_FIELDS = [ 'id', 'name', 'hostPath', 'creationTime', 'mountType', 'mountOptionsJson' ].join(','); @@ -83,7 +83,7 @@ async function add(volume, auditSource) { error = mounts.validateMountOptions(mountType, mountOptions); if (error) throw error; - const id = uuid.v4().replace(/-/g, ''); // to make systemd mount file names more readable + const id = crypto.randomUUID().replace(/-/g, ''); // to make systemd mount file names more readable let hostPath; if (mountType === mounts.MOUNT_TYPE_MOUNTPOINT || mountType === mounts.MOUNT_TYPE_FILESYSTEM) {