diff --git a/src/apppasswords.js b/src/apppasswords.js index fcde74099..49e4ab768 100644 --- a/src/apppasswords.js +++ b/src/apppasswords.js @@ -66,8 +66,8 @@ async function add(userId, identifier, name) { const args = [ appPassword.id, appPassword.userId, appPassword.identifier, appPassword.name, appPassword.hashedPassword ]; [error] = await safe(database.query(query, args)); - if (error && error.code === 'ER_DUP_ENTRY' && error.sqlMessage.indexOf('appPasswords_name_userId_identifier') !== -1) throw new BoxError(BoxError.ALREADY_EXISTS, 'name/app combination already exists'); - if (error && error.code === 'ER_NO_REFERENCED_ROW_2' && error.sqlMessage.indexOf('userId')) throw new BoxError(BoxError.NOT_FOUND, 'user not found'); + if (error && error.sqlCode === 'ER_DUP_ENTRY' && error.sqlMessage.indexOf('appPasswords_name_userId_identifier') !== -1) throw new BoxError(BoxError.ALREADY_EXISTS, 'name/app combination already exists'); + if (error && error.sqlCode === 'ER_NO_REFERENCED_ROW_2' && error.sqlMessage.indexOf('userId')) throw new BoxError(BoxError.NOT_FOUND, 'user not found'); if (error) throw error; return { id: appPassword.id, password: appPassword.password }; diff --git a/src/apps.js b/src/apps.js index 5f5b147d5..b45a54ca1 100644 --- a/src/apps.js +++ b/src/apps.js @@ -988,8 +988,8 @@ async function add(id, appStoreId, manifest, subdomain, domain, portBindings, da } const [error] = await safe(database.transaction(queries)); - if (error && error.code === 'ER_DUP_ENTRY') throw new BoxError(BoxError.ALREADY_EXISTS, error.message); - if (error && error.code === 'ER_NO_REFERENCED_ROW_2') throw new BoxError(BoxError.NOT_FOUND, 'no such domain'); + if (error && error.sqlCode === 'ER_DUP_ENTRY') throw new BoxError(BoxError.ALREADY_EXISTS, error.message); + if (error && error.sqlCode === 'ER_NO_REFERENCED_ROW_2') throw new BoxError(BoxError.NOT_FOUND, 'no such domain'); if (error) throw new BoxError(BoxError.DATABASE_ERROR, error); } @@ -1088,7 +1088,7 @@ async function updateWithConstraints(id, app, constraints) { } const [error, results] = await safe(database.transaction(queries)); - if (error && error.code === 'ER_DUP_ENTRY') throw new BoxError(BoxError.ALREADY_EXISTS, error.message); + if (error && error.sqlCode === 'ER_DUP_ENTRY') throw new BoxError(BoxError.ALREADY_EXISTS, error.message); if (error) throw new BoxError(BoxError.DATABASE_ERROR, error); if (results[results.length - 1].affectedRows !== 1) throw new BoxError(BoxError.NOT_FOUND, 'App not found'); } diff --git a/src/archives.js b/src/archives.js index fdcf0d501..68e2109dc 100644 --- a/src/archives.js +++ b/src/archives.js @@ -73,8 +73,8 @@ async function add(backupId, data, auditSource) { const [error] = await safe(database.query('INSERT INTO archives (id, backupId, icon, appStoreIcon) VALUES (?, ?, ?, ?)', [ id, backupId, data.icon, data.appStoreIcon ])); - if (error && error.code === 'ER_NO_REFERENCED_ROW_2') throw new BoxError(BoxError.NOT_FOUND, 'Backup not found'); - if (error && error.code === 'ER_DUP_ENTRY') throw new BoxError(BoxError.ALREADY_EXISTS, 'Archive already exists'); + if (error && error.sqlCode === 'ER_NO_REFERENCED_ROW_2') throw new BoxError(BoxError.NOT_FOUND, 'Backup not found'); + if (error && error.sqlCode === 'ER_DUP_ENTRY') throw new BoxError(BoxError.ALREADY_EXISTS, 'Archive already exists'); if (error) throw error; await eventlog.add(eventlog.ACTION_ARCHIVES_ADD, auditSource, { id, backupId }); diff --git a/src/backups.js b/src/backups.js index 901206ba1..082c454a5 100644 --- a/src/backups.js +++ b/src/backups.js @@ -87,7 +87,7 @@ async function add(data) { const [error] = await safe(database.query('INSERT INTO backups (id, remotePath, identifier, encryptionVersion, packageVersion, type, creationTime, state, dependsOnJson, manifestJson, preserveSecs, appConfigJson, siteId, statsJson, integrityJson) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', [ id, data.remotePath, data.identifier, data.encryptionVersion, data.packageVersion, data.type, creationTime, data.state, JSON.stringify(data.dependsOn), manifestJson, data.preserveSecs, appConfigJson, data.siteId, statsJson, integrityJson ])); - if (error && error.code === 'ER_DUP_ENTRY') throw new BoxError(BoxError.ALREADY_EXISTS, 'Backup already exists'); + if (error && error.sqlCode === 'ER_DUP_ENTRY') throw new BoxError(BoxError.ALREADY_EXISTS, 'Backup already exists'); if (error) throw error; return id; diff --git a/src/backupsites.js b/src/backupsites.js index 91c9a62b8..d85df46e7 100644 --- a/src/backupsites.js +++ b/src/backupsites.js @@ -357,7 +357,7 @@ async function del(backupSite, auditSource) { ]; const [error, result] = await safe(database.transaction(queries)); - if (error && error.code === 'ER_NO_REFERENCED_ROW_2') throw new BoxError(BoxError.NOT_FOUND, error); + if (error && error.sqlCode === 'ER_NO_REFERENCED_ROW_2') throw new BoxError(BoxError.NOT_FOUND, error); if (error) throw error; if (result[2].affectedRows !== 1) throw new BoxError(BoxError.NOT_FOUND, 'Target not found'); await eventlog.add(eventlog.ACTION_BACKUP_TARGET_REMOVE, auditSource, { backupSite: removePrivateFields(backupSite) }); diff --git a/src/boxerror.js b/src/boxerror.js index 91eeb56bd..742b09b42 100644 --- a/src/boxerror.js +++ b/src/boxerror.js @@ -19,8 +19,6 @@ function BoxError(reason, errorOrMessage, extra = {}) { this.name = this.constructor.name; this.reason = reason; this.details = {}; - this.code = extra.code; - this.sqlMessage = extra.sqlMessage; if (typeof errorOrMessage === 'string') { this.message = errorOrMessage; diff --git a/src/database.js b/src/database.js index d296bbff0..91b396dcf 100644 --- a/src/database.js +++ b/src/database.js @@ -95,7 +95,7 @@ async function query(...args) { assert.notStrictEqual(gConnectionPool, null, 'Database connection is already closed'); const [error, result] = await safe(gConnectionPool.query(...args)); // this is same as getConnection/query/release - if (error) throw new BoxError(BoxError.DATABASE_ERROR, error, { code: error.code, sqlMessage: error.sqlMessage || null }); + if (error) throw new BoxError(BoxError.DATABASE_ERROR, error, { sqlCode: error.code, sqlMessage: error.sqlMessage || null }); return result[0]; // the promise version returns a tuple of [rows, fields] } @@ -103,7 +103,7 @@ async function transaction(queries) { assert(Array.isArray(queries)); const [error, connection] = await safe(gConnectionPool.getConnection()); - if (error) throw new BoxError(BoxError.DATABASE_ERROR, error, { code: error.code, sqlMessage: error.sqlMessage }); + if (error) throw new BoxError(BoxError.DATABASE_ERROR, error, { sqlCode: error.code, sqlMessage: error.sqlMessage }); try { await connection.beginTransaction(); @@ -118,7 +118,7 @@ async function transaction(queries) { } catch (error) { await safe(connection.rollback(), { debug }); connection.release(); // no await! - throw new BoxError(BoxError.DATABASE_ERROR, error, { code: error.code, sqlMessage: error.sqlMessage || null }); + throw new BoxError(BoxError.DATABASE_ERROR, error, { sqlCode: error.code, sqlMessage: error.sqlMessage || null }); } } diff --git a/src/dns.js b/src/dns.js index a8dc4d00a..c783a00fb 100644 --- a/src/dns.js +++ b/src/dns.js @@ -301,7 +301,7 @@ async function unregisterLocation(location, recordType, recordValue) { const retryable = error.reason === BoxError.BUSY || error.reason === BoxError.EXTERNAL_ERROR; debug(`unregisterLocation: Error unregistering location ${recordType}. retryable: ${retryable}. ${error.message}`); - throw new BoxError(BoxError.EXTERNAL_ERROR, error.message, { domain: location, retryable }); + throw new BoxError(BoxError.EXTERNAL_ERROR, error, { domain: location, retryable }); } async function unregisterLocations(locations, progressCallback) { diff --git a/src/domains.js b/src/domains.js index 49312411c..d305f14a1 100644 --- a/src/domains.js +++ b/src/domains.js @@ -178,7 +178,7 @@ async function add(domain, data, auditSource) { ]; [error] = await safe(database.transaction(queries)); - if (error && error.code === 'ER_DUP_ENTRY') throw new BoxError(BoxError.ALREADY_EXISTS, 'Domain already exists'); + if (error && error.sqlCode === 'ER_DUP_ENTRY') throw new BoxError(BoxError.ALREADY_EXISTS, 'Domain already exists'); if (error) throw new BoxError(BoxError.DATABASE_ERROR, error); await reverseProxy.setFallbackCertificate(domain, fallbackCertificate); @@ -298,7 +298,8 @@ async function del(domain, auditSource) { ]; const [error, results] = await safe(database.transaction(queries)); - if (error && error.code === 'ER_ROW_IS_REFERENCED_2') { +console.dir(error); + if (error && error.sqlCode === 'ER_ROW_IS_REFERENCED_2') { if (error.message.includes('mailboxes_aliasDomain_constraint')) throw new BoxError(BoxError.CONFLICT, 'Domain is in use in a mailbox, list or an alias'); if (error.message.includes('mailboxes_domain_constraint')) throw new BoxError(BoxError.CONFLICT, 'Domain is in use in a mailbox, list or an alias'); if (error.message.includes('apps_mailDomain_constraint')) throw new BoxError(BoxError.CONFLICT, 'Domain is in use in an app\'s mailbox section'); diff --git a/src/groups.js b/src/groups.js index 622e469aa..344daedc0 100644 --- a/src/groups.js +++ b/src/groups.js @@ -78,7 +78,7 @@ async function add(group, auditSource) { 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); + if (error && error.sqlCode === 'ER_DUP_ENTRY') throw new BoxError(BoxError.ALREADY_EXISTS, error); if (error) throw error; await eventlog.add(eventlog.ACTION_GROUP_ADD, auditSource, { id, name, source }); @@ -207,8 +207,8 @@ async function setLocalMembership(user, localGroupIds) { } const [error] = await safe(database.transaction(queries)); - if (error && error.code === 'ER_NO_REFERENCED_ROW_2') throw new BoxError(BoxError.NOT_FOUND, 'Group not found'); - if (error && error.code === 'ER_DUP_ENTRY') throw new BoxError(BoxError.CONFLICT, 'Already member'); + if (error && error.sqlCode === 'ER_NO_REFERENCED_ROW_2') throw new BoxError(BoxError.NOT_FOUND, 'Group not found'); + if (error && error.sqlCode === 'ER_DUP_ENTRY') throw new BoxError(BoxError.CONFLICT, 'Already member'); if (error) throw error; } @@ -227,8 +227,8 @@ async function setMembers(group, userIds, options, auditSource) { } const [error] = await safe(database.transaction(queries)); - if (error && error.code === 'ER_NO_REFERENCED_ROW_2') throw new BoxError(BoxError.NOT_FOUND, 'Group not found'); - if (error && error.code === 'ER_DUP_ENTRY') throw new BoxError(BoxError.CONFLICT, 'Duplicate member in list'); + if (error && error.sqlCode === 'ER_NO_REFERENCED_ROW_2') throw new BoxError(BoxError.NOT_FOUND, 'Group not found'); + if (error && error.sqlCode === 'ER_DUP_ENTRY') throw new BoxError(BoxError.CONFLICT, 'Duplicate member in list'); if (error) throw error; await eventlog.add(eventlog.ACTION_GROUP_MEMBERSHIP, auditSource, { group, userIds }); diff --git a/src/mail.js b/src/mail.js index 4c2769ef9..f0964f91b 100644 --- a/src/mail.js +++ b/src/mail.js @@ -924,8 +924,8 @@ async function addMailbox(name, domain, data, auditSource) { [error] = await safe(database.query('INSERT INTO mailboxes (name, type, domain, ownerId, ownerType, active, storageQuota, messagesQuota, enablePop3) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)', [ name, exports.TYPE_MAILBOX, domain, ownerId, ownerType, active, storageQuota, messagesQuota, enablePop3 ])); - if (error && error.code === 'ER_DUP_ENTRY') throw new BoxError(BoxError.ALREADY_EXISTS, 'mailbox already exists'); - if (error && error.code === 'ER_NO_REFERENCED_ROW_2' && error.sqlMessage.includes('mailboxes_domain_constraint')) throw new BoxError(BoxError.NOT_FOUND, `no such domain '${domain}'`); + if (error && error.sqlCode === 'ER_DUP_ENTRY') throw new BoxError(BoxError.ALREADY_EXISTS, 'mailbox already exists'); + if (error && error.sqlCode === 'ER_NO_REFERENCED_ROW_2' && error.sqlMessage.includes('mailboxes_domain_constraint')) throw new BoxError(BoxError.NOT_FOUND, `no such domain '${domain}'`); if (error) throw error; await eventlog.add(eventlog.ACTION_MAIL_MAILBOX_ADD, auditSource, { name, domain, ownerId, ownerType, active, storageQuota, enablePop3, messageQuota: messagesQuota }); @@ -1064,7 +1064,7 @@ async function setAliases(name, domain, aliases, auditSource) { } const [error] = await safe(database.transaction(queries)); - if (error && error.code === 'ER_DUP_ENTRY' && error.message.indexOf('mailboxes_name_domain_unique_index') !== -1) { + if (error && error.sqlCode === 'ER_DUP_ENTRY' && error.message.indexOf('mailboxes_name_domain_unique_index') !== -1) { const aliasMatch = error.message.match(new RegExp(`Duplicate entry '(.*)-${domain}' for key 'mailboxes_name_domain_unique_index'`)); if (!aliasMatch) throw new BoxError(BoxError.ALREADY_EXISTS, error.message); @@ -1124,7 +1124,7 @@ async function addList(name, domain, data, auditSource) { } [error] = await safe(database.query('INSERT INTO mailboxes (name, type, domain, ownerId, ownerType, membersJson, membersOnly, active) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', [ name, exports.TYPE_LIST, domain, 'admin', 'user', JSON.stringify(members), membersOnly, active ])); - if (error && error.code === 'ER_DUP_ENTRY') throw new BoxError(BoxError.ALREADY_EXISTS, 'mailbox already exists'); + if (error && error.sqlCode === 'ER_DUP_ENTRY') throw new BoxError(BoxError.ALREADY_EXISTS, 'mailbox already exists'); if (error) throw error; await eventlog.add(eventlog.ACTION_MAIL_LIST_ADD, auditSource, { name, domain, members, membersOnly, active }); diff --git a/src/oidcclients.js b/src/oidcclients.js index 813d394e7..183ac2b09 100644 --- a/src/oidcclients.js +++ b/src/oidcclients.js @@ -57,7 +57,7 @@ async function add(data) { const args = [ id, secret, data.name, data.appId, data.loginRedirectUri, data.tokenSignatureAlgorithm ]; const [error] = await safe(database.query(query, args)); - if (error && error.code === 'ER_DUP_ENTRY') throw new BoxError(BoxError.ALREADY_EXISTS, 'client already exists'); + if (error && error.sqlCode === 'ER_DUP_ENTRY') throw new BoxError(BoxError.ALREADY_EXISTS, 'client already exists'); if (error) throw error; return { id, secret }; diff --git a/src/users.js b/src/users.js index 7c3a4e8fd..82845be15 100644 --- a/src/users.js +++ b/src/users.js @@ -276,9 +276,9 @@ async function add(email, data, auditSource) { const args = [ user.id, user.username, user.password, user.email, user.fallbackEmail, user.salt, user.resetToken, user.inviteToken, user.displayName, user.source, user.role, user.avatar, user.language, user.notificationConfigJson ]; [error] = await safe(database.query(query, args)); - if (error && error.code === 'ER_DUP_ENTRY' && error.sqlMessage.indexOf('users_email') !== -1) throw new BoxError(BoxError.ALREADY_EXISTS, 'email already exists'); - if (error && error.code === 'ER_DUP_ENTRY' && error.sqlMessage.indexOf('users_username') !== -1) throw new BoxError(BoxError.ALREADY_EXISTS, 'username already exists'); - if (error && error.code === 'ER_DUP_ENTRY' && error.sqlMessage.indexOf('PRIMARY') !== -1) throw new BoxError(BoxError.ALREADY_EXISTS, 'id already exists'); + if (error && error.sqlCode === 'ER_DUP_ENTRY' && error.sqlMessage.indexOf('users_email') !== -1) throw new BoxError(BoxError.ALREADY_EXISTS, 'email already exists'); + if (error && error.sqlCode === 'ER_DUP_ENTRY' && error.sqlMessage.indexOf('users_username') !== -1) throw new BoxError(BoxError.ALREADY_EXISTS, 'username already exists'); + if (error && error.sqlCode === 'ER_DUP_ENTRY' && error.sqlMessage.indexOf('PRIMARY') !== -1) throw new BoxError(BoxError.ALREADY_EXISTS, 'id already exists'); if (error) throw error; // when this is used to create the owner, then we have to patch the auditSource to contain himself @@ -479,7 +479,7 @@ async function del(user, auditSource) { queries.push({ query: 'DELETE FROM users WHERE id = ?', args: [ user.id ] }); const [error, result] = await safe(database.transaction(queries)); - if (error && error.code === 'ER_NO_REFERENCED_ROW_2') throw new BoxError(BoxError.NOT_FOUND, error); + if (error && error.sqlCode === 'ER_NO_REFERENCED_ROW_2') throw new BoxError(BoxError.NOT_FOUND, error); if (error) throw error; if (result[3].affectedRows !== 1) throw new BoxError(BoxError.NOT_FOUND, 'User not found'); @@ -654,8 +654,8 @@ async function update(user, data, auditSource) { args.push(user.id); const [error, result] = await safe(database.query('UPDATE users SET ' + fields.join(', ') + ' WHERE id = ?', args)); - if (error && error.code === 'ER_DUP_ENTRY' && error.sqlMessage.indexOf('users_email') !== -1) throw new BoxError(BoxError.ALREADY_EXISTS, 'email already exists'); - if (error && error.code === 'ER_DUP_ENTRY' && error.sqlMessage.indexOf('users_username') !== -1) throw new BoxError(BoxError.ALREADY_EXISTS, 'username already exists'); + if (error && error.sqlCode === 'ER_DUP_ENTRY' && error.sqlMessage.indexOf('users_email') !== -1) throw new BoxError(BoxError.ALREADY_EXISTS, 'email already exists'); + if (error && error.sqlCode === 'ER_DUP_ENTRY' && error.sqlMessage.indexOf('users_username') !== -1) throw new BoxError(BoxError.ALREADY_EXISTS, 'username already exists'); if (error) throw new BoxError(BoxError.DATABASE_ERROR, error); if (result.affectedRows !== 1) throw new BoxError(BoxError.NOT_FOUND, 'User not found'); diff --git a/src/volumes.js b/src/volumes.js index 049936884..c33a31755 100644 --- a/src/volumes.js +++ b/src/volumes.js @@ -97,9 +97,9 @@ async function add(volume, auditSource) { } [error] = await safe(database.query('INSERT INTO volumes (id, name, hostPath, mountType, mountOptionsJson) VALUES (?, ?, ?, ?, ?)', [ id, name, hostPath, mountType, JSON.stringify(mountOptions) ])); - if (error && error.code === 'ER_DUP_ENTRY' && error.sqlMessage.indexOf('name') !== -1) throw new BoxError(BoxError.ALREADY_EXISTS, 'name already exists'); - if (error && error.code === 'ER_DUP_ENTRY' && error.sqlMessage.indexOf('hostPath') !== -1) throw new BoxError(BoxError.ALREADY_EXISTS, 'directory or mountpoint already in use'); - if (error && error.code === 'ER_DUP_ENTRY' && error.sqlMessage.indexOf('PRIMARY') !== -1) throw new BoxError(BoxError.ALREADY_EXISTS, 'id already exists'); + if (error && error.sqlCode === 'ER_DUP_ENTRY' && error.sqlMessage.indexOf('name') !== -1) throw new BoxError(BoxError.ALREADY_EXISTS, 'name already exists'); + if (error && error.sqlCode === 'ER_DUP_ENTRY' && error.sqlMessage.indexOf('hostPath') !== -1) throw new BoxError(BoxError.ALREADY_EXISTS, 'directory or mountpoint already in use'); + if (error && error.sqlCode === 'ER_DUP_ENTRY' && error.sqlMessage.indexOf('PRIMARY') !== -1) throw new BoxError(BoxError.ALREADY_EXISTS, 'id already exists'); if (error) throw error; await eventlog.add(eventlog.ACTION_VOLUME_ADD, auditSource, { id, name, hostPath }); @@ -195,7 +195,7 @@ async function del(volume, auditSource) { assert.strictEqual(typeof auditSource, 'object'); const [error, result] = await safe(database.query('DELETE FROM volumes WHERE id=?', [ volume.id ])); - if (error && error.code === 'ER_ROW_IS_REFERENCED_2') throw new BoxError(BoxError.CONFLICT, 'Volume is in use'); + if (error && error.sqlCode === 'ER_ROW_IS_REFERENCED_2') throw new BoxError(BoxError.CONFLICT, 'Volume is in use'); if (error) throw error; if (result.affectedRows !== 1) throw new BoxError(BoxError.NOT_FOUND, 'Volume not found');