2016-05-26 22:34:04 -07:00
'use strict' ;
exports = module . exports = {
2018-04-05 15:01:28 -07:00
addMailbox : addMailbox ,
2018-04-05 15:46:13 -07:00
addGroup : addGroup ,
2018-04-05 15:01:28 -07:00
updateMailbox : updateMailbox ,
updateList : updateList ,
2016-05-26 22:34:04 -07:00
del : del ,
2016-09-25 23:21:55 -07:00
listAliases : listAliases ,
listMailboxes : listMailboxes ,
2018-01-26 10:22:50 +01:00
listGroups : listGroups ,
2016-09-25 23:21:55 -07:00
2016-09-25 18:59:11 -07:00
getMailbox : getMailbox ,
getGroup : getGroup ,
getAlias : getAlias ,
2016-09-25 23:21:55 -07:00
2016-09-26 14:02:23 -07:00
getAliasesForName : getAliasesForName ,
setAliasesForName : setAliasesForName ,
2016-09-25 23:21:55 -07:00
2016-09-23 17:35:48 -07:00
getByOwnerId : getByOwnerId ,
2016-09-22 15:55:18 -07:00
delByOwnerId : delByOwnerId ,
2018-02-11 01:18:29 -08:00
delByDomain : delByDomain ,
2016-05-26 22:34:04 -07:00
2016-12-15 16:13:16 +01:00
updateName : updateName ,
2016-09-22 15:55:18 -07:00
_clear : clear ,
TYPE _USER : 'user' ,
TYPE _APP : 'app' ,
TYPE _GROUP : 'group'
2016-05-26 22:34:04 -07:00
} ;
var assert = require ( 'assert' ) ,
database = require ( './database.js' ) ,
2016-05-27 19:20:42 -07:00
DatabaseError = require ( './databaseerror.js' ) ,
2018-04-05 15:46:13 -07:00
safe = require ( 'safetydance' ) ,
2016-05-27 19:20:42 -07:00
util = require ( 'util' ) ;
2016-05-26 22:34:04 -07:00
2018-04-05 15:46:13 -07:00
var MAILBOX _FIELDS = [ 'name' , 'ownerId' , 'ownerType' , 'aliasTarget' , 'creationTime' , 'membersJson' , 'domain' ] . join ( ',' ) ;
function postProcess ( data ) {
data . members = safe . JSON . parse ( data . membersJson ) || [ ] ;
delete data . membersJson ;
return data ;
}
2016-05-26 22:34:04 -07:00
2018-04-05 15:01:28 -07:00
function addMailbox ( name , domain , ownerId , ownerType , callback ) {
assert . strictEqual ( typeof name , 'string' ) ;
assert . strictEqual ( typeof domain , 'string' ) ;
assert . strictEqual ( typeof ownerId , 'string' ) ;
assert . strictEqual ( typeof ownerType , 'string' ) ;
assert . strictEqual ( typeof callback , 'function' ) ;
database . query ( 'INSERT INTO mailboxes (name, domain, ownerId, ownerType) VALUES (?, ?, ?, ?)' , [ name , domain , ownerId , ownerType ] , function ( error ) {
if ( error && error . code === 'ER_DUP_ENTRY' ) return callback ( new DatabaseError ( DatabaseError . ALREADY _EXISTS , 'mailbox already exists' ) ) ;
if ( error ) return callback ( new DatabaseError ( DatabaseError . INTERNAL _ERROR , error ) ) ;
callback ( null ) ;
} ) ;
}
function updateMailbox ( name , domain , ownerId , ownerType , callback ) {
assert . strictEqual ( typeof name , 'string' ) ;
assert . strictEqual ( typeof domain , 'string' ) ;
assert . strictEqual ( typeof ownerId , 'string' ) ;
assert . strictEqual ( typeof ownerType , 'string' ) ;
assert . strictEqual ( typeof callback , 'function' ) ;
database . query ( 'UPDATE mailboxes SET ownerId = ? WHERE name = ? AND domain = ? AND ownerType = ?' , [ ownerId , name , domain , ownerType ] , function ( error , result ) {
if ( error ) return callback ( new DatabaseError ( DatabaseError . INTERNAL _ERROR , error ) ) ;
if ( result . affectedRows === 0 ) return callback ( new DatabaseError ( DatabaseError . NOT _FOUND ) ) ;
callback ( null ) ;
} ) ;
}
2018-04-05 15:46:13 -07:00
function addGroup ( name , domain , members , callback ) {
2016-05-26 22:34:04 -07:00
assert . strictEqual ( typeof name , 'string' ) ;
2017-11-09 23:45:29 +01:00
assert . strictEqual ( typeof domain , 'string' ) ;
2018-04-05 15:46:13 -07:00
assert ( Array . isArray ( members ) ) ;
2016-05-26 22:34:04 -07:00
assert . strictEqual ( typeof callback , 'function' ) ;
2018-04-05 15:46:13 -07:00
database . query ( 'INSERT INTO mailboxes (name, domain, ownerId, ownerType, membersJson) VALUES (?, ?, ?, ?, ?)' ,
[ name , domain , 'admin' , exports . TYPE _GROUP , JSON . stringify ( members ) ] , function ( error ) {
if ( error && error . code === 'ER_DUP_ENTRY' ) return callback ( new DatabaseError ( DatabaseError . ALREADY _EXISTS , 'mailbox already exists' ) ) ;
if ( error ) return callback ( new DatabaseError ( DatabaseError . INTERNAL _ERROR , error ) ) ;
2016-09-21 15:34:58 -07:00
2018-04-05 15:46:13 -07:00
callback ( null ) ;
} ) ;
2018-04-03 14:12:43 -07:00
}
2018-04-05 15:46:13 -07:00
function updateList ( name , domain , members , callback ) {
2018-04-03 14:12:43 -07:00
assert . strictEqual ( typeof name , 'string' ) ;
assert . strictEqual ( typeof domain , 'string' ) ;
2018-04-05 15:46:13 -07:00
assert ( Array . isArray ( members ) ) ;
2018-04-03 14:12:43 -07:00
assert . strictEqual ( typeof callback , 'function' ) ;
2018-04-05 15:46:13 -07:00
database . query ( 'UPDATE mailboxes SET membersJson = ? WHERE name = ? AND domain = ?' ,
[ JSON . stringify ( members ) , name , domain ] , function ( error , result ) {
if ( error ) return callback ( new DatabaseError ( DatabaseError . INTERNAL _ERROR , error ) ) ;
if ( result . affectedRows === 0 ) return callback ( new DatabaseError ( DatabaseError . NOT _FOUND ) ) ;
2018-04-03 14:12:43 -07:00
2018-04-05 15:46:13 -07:00
callback ( null ) ;
} ) ;
2016-09-21 15:34:58 -07:00
}
2016-05-26 22:34:04 -07:00
function clear ( callback ) {
assert . strictEqual ( typeof callback , 'function' ) ;
database . query ( 'TRUNCATE TABLE mailboxes' , [ ] , function ( error ) {
if ( error ) return callback ( new DatabaseError ( DatabaseError . INTERNAL _ERROR , error ) ) ;
callback ( null ) ;
} ) ;
}
2017-11-09 23:45:29 +01:00
function del ( name , domain , callback ) {
2016-05-27 19:20:42 -07:00
assert . strictEqual ( typeof name , 'string' ) ;
2017-11-09 23:45:29 +01:00
assert . strictEqual ( typeof domain , 'string' ) ;
2016-05-26 22:34:04 -07:00
assert . strictEqual ( typeof callback , 'function' ) ;
2016-05-27 19:20:42 -07:00
// deletes aliases as well
2017-11-09 23:45:29 +01:00
database . query ( 'DELETE FROM mailboxes WHERE (name=? OR aliasTarget = ?) AND domain = ?' , [ name , name , domain ] , function ( error , result ) {
2016-05-26 22:34:04 -07:00
if ( error ) return callback ( new DatabaseError ( DatabaseError . INTERNAL _ERROR , error ) ) ;
2016-05-27 17:43:25 -07:00
if ( result . affectedRows === 0 ) return callback ( new DatabaseError ( DatabaseError . NOT _FOUND ) ) ;
2016-05-26 22:34:04 -07:00
callback ( null ) ;
} ) ;
}
2018-02-11 01:18:29 -08:00
function delByDomain ( domain , callback ) {
assert . strictEqual ( typeof domain , 'string' ) ;
assert . strictEqual ( typeof callback , 'function' ) ;
// deletes aliases as well
database . query ( 'DELETE FROM mailboxes WHERE domain = ?' , [ domain ] , function ( error ) {
if ( error ) return callback ( new DatabaseError ( DatabaseError . INTERNAL _ERROR , error ) ) ;
callback ( null ) ;
} ) ;
}
2016-09-22 15:55:18 -07:00
function delByOwnerId ( id , callback ) {
assert . strictEqual ( typeof id , 'string' ) ;
assert . strictEqual ( typeof callback , 'function' ) ;
// deletes aliases as well
2016-09-25 23:21:55 -07:00
database . query ( 'DELETE FROM mailboxes WHERE ownerId=?' , [ id ] , function ( error ) {
2016-09-22 15:55:18 -07:00
if ( error ) return callback ( new DatabaseError ( DatabaseError . INTERNAL _ERROR , error ) ) ;
callback ( null ) ;
} ) ;
}
2017-11-09 23:45:29 +01:00
function updateName ( oldName , oldDomain , newName , newDomain , callback ) {
2016-12-15 16:13:16 +01:00
assert . strictEqual ( typeof oldName , 'string' ) ;
2017-11-09 23:45:29 +01:00
assert . strictEqual ( typeof oldDomain , 'string' ) ;
2016-12-15 16:13:16 +01:00
assert . strictEqual ( typeof newName , 'string' ) ;
2017-11-09 23:45:29 +01:00
assert . strictEqual ( typeof newDomain , 'string' ) ;
2016-12-15 16:13:16 +01:00
assert . strictEqual ( typeof callback , 'function' ) ;
2016-12-15 16:42:11 +01:00
// skip if no changes
2017-11-09 23:45:29 +01:00
if ( oldName === newName && oldDomain === newDomain ) return callback ( null ) ;
2016-12-15 16:42:11 +01:00
2017-11-09 23:45:29 +01:00
database . query ( 'UPDATE mailboxes SET name=?, domain=? WHERE name=? AND domain = ?' , [ newName , newDomain , oldName , oldDomain ] , function ( error , result ) {
2016-12-15 16:13:16 +01:00
if ( error && error . code === 'ER_DUP_ENTRY' ) return callback ( new DatabaseError ( DatabaseError . ALREADY _EXISTS , 'mailbox already exists' ) ) ;
if ( error ) return callback ( new DatabaseError ( DatabaseError . INTERNAL _ERROR , error ) ) ;
if ( result . affectedRows !== 1 ) return callback ( new DatabaseError ( DatabaseError . NOT _FOUND ) ) ;
callback ( null ) ;
} ) ;
}
2017-11-09 23:45:29 +01:00
function getMailbox ( name , domain , callback ) {
2016-09-25 18:59:11 -07:00
assert . strictEqual ( typeof name , 'string' ) ;
2017-11-09 23:45:29 +01:00
assert . strictEqual ( typeof domain , 'string' ) ;
2016-09-25 18:59:11 -07:00
assert . strictEqual ( typeof callback , 'function' ) ;
2017-11-09 23:45:29 +01:00
database . query ( 'SELECT ' + MAILBOX _FIELDS + ' FROM mailboxes WHERE name = ? AND domain = ? AND (ownerType = ? OR ownerType = ?) AND aliasTarget IS NULL' , [ name , domain , exports . TYPE _APP , exports . TYPE _USER ] , function ( error , results ) {
2016-09-25 18:59:11 -07:00
if ( error ) return callback ( new DatabaseError ( DatabaseError . INTERNAL _ERROR , error ) ) ;
if ( results . length === 0 ) return callback ( new DatabaseError ( DatabaseError . NOT _FOUND ) ) ;
2018-04-05 15:46:13 -07:00
callback ( null , postProcess ( results [ 0 ] ) ) ;
2016-09-25 18:59:11 -07:00
} ) ;
}
2017-11-09 23:45:29 +01:00
function listMailboxes ( domain , callback ) {
assert . strictEqual ( typeof domain , 'string' ) ;
2016-09-25 18:59:11 -07:00
assert . strictEqual ( typeof callback , 'function' ) ;
2017-11-09 23:45:29 +01:00
database . query ( 'SELECT ' + MAILBOX _FIELDS + ' FROM mailboxes WHERE domain = ? AND (ownerType = ? OR ownerType = ?) AND aliasTarget IS NULL ORDER BY name' , [ domain , exports . TYPE _APP , exports . TYPE _USER ] , function ( error , results ) {
2016-09-25 18:59:11 -07:00
if ( error ) return callback ( new DatabaseError ( DatabaseError . INTERNAL _ERROR , error ) ) ;
2018-04-05 15:46:13 -07:00
results . forEach ( function ( result ) { postProcess ( result ) ; } ) ;
2016-09-25 18:59:11 -07:00
callback ( null , results ) ;
} ) ;
}
2018-01-26 10:22:50 +01:00
function listGroups ( domain , callback ) {
assert . strictEqual ( typeof domain , 'string' ) ;
assert . strictEqual ( typeof callback , 'function' ) ;
2018-04-05 15:46:13 -07:00
database . query ( 'SELECT ' + MAILBOX _FIELDS + ' FROM mailboxes WHERE domain = ? AND ownerType = ? AND aliasTarget IS NULL' , [ domain , exports . TYPE _GROUP ] , function ( error , results ) {
2018-01-26 10:22:50 +01:00
if ( error ) return callback ( new DatabaseError ( DatabaseError . INTERNAL _ERROR , error ) ) ;
2018-04-05 15:46:13 -07:00
results . forEach ( function ( result ) { postProcess ( result ) ; } ) ;
2018-01-26 10:22:50 +01:00
callback ( null , results ) ;
} ) ;
}
2017-11-09 23:45:29 +01:00
function getGroup ( name , domain , callback ) {
2016-09-25 18:59:11 -07:00
assert . strictEqual ( typeof name , 'string' ) ;
2017-11-09 23:45:29 +01:00
assert . strictEqual ( typeof domain , 'string' ) ;
2016-09-25 18:59:11 -07:00
assert . strictEqual ( typeof callback , 'function' ) ;
2017-11-09 23:45:29 +01:00
database . query ( 'SELECT ' + MAILBOX _FIELDS + ' FROM mailboxes WHERE name = ? AND domain = ? AND ownerType = ? AND aliasTarget IS NULL' , [ name , domain , exports . TYPE _GROUP ] , function ( error , results ) {
2016-09-25 18:59:11 -07:00
if ( error ) return callback ( new DatabaseError ( DatabaseError . INTERNAL _ERROR , error ) ) ;
if ( results . length === 0 ) return callback ( new DatabaseError ( DatabaseError . NOT _FOUND ) ) ;
2018-04-05 15:46:13 -07:00
callback ( null , postProcess ( results [ 0 ] ) ) ;
2016-09-25 18:59:11 -07:00
} ) ;
}
2016-09-23 17:35:48 -07:00
function getByOwnerId ( ownerId , callback ) {
assert . strictEqual ( typeof ownerId , 'string' ) ;
assert . strictEqual ( typeof callback , 'function' ) ;
2016-09-25 23:21:55 -07:00
database . query ( 'SELECT ' + MAILBOX _FIELDS + ' FROM mailboxes WHERE ownerId = ? ORDER BY name' , [ ownerId ] , function ( error , results ) {
2016-09-23 17:35:48 -07:00
if ( error ) return callback ( new DatabaseError ( DatabaseError . INTERNAL _ERROR , error ) ) ;
if ( results . length === 0 ) return callback ( new DatabaseError ( DatabaseError . NOT _FOUND ) ) ;
2018-04-05 15:46:13 -07:00
results . forEach ( function ( result ) { postProcess ( result ) ; } ) ;
2016-09-25 23:21:55 -07:00
callback ( null , results ) ;
2016-09-23 17:35:48 -07:00
} ) ;
}
2017-11-09 23:45:29 +01:00
function setAliasesForName ( name , domain , aliases , callback ) {
2016-05-27 19:20:42 -07:00
assert . strictEqual ( typeof name , 'string' ) ;
2017-11-09 23:45:29 +01:00
assert . strictEqual ( typeof domain , 'string' ) ;
2016-05-27 19:20:42 -07:00
assert ( util . isArray ( aliases ) ) ;
assert . strictEqual ( typeof callback , 'function' ) ;
2017-11-09 23:45:29 +01:00
database . query ( 'SELECT ' + MAILBOX _FIELDS + ' FROM mailboxes WHERE name = ? AND domain = ?' , [ name , domain ] , function ( error , results ) {
2016-05-27 19:20:42 -07:00
if ( error ) return callback ( new DatabaseError ( DatabaseError . INTERNAL _ERROR , error ) ) ;
2016-09-25 23:21:55 -07:00
if ( results . length === 0 ) return callback ( new DatabaseError ( DatabaseError . NOT _FOUND ) ) ;
2016-05-27 19:20:42 -07:00
2016-09-25 23:21:55 -07:00
var queries = [ ] ;
2017-11-09 23:45:29 +01:00
queries . push ( { query : 'DELETE FROM mailboxes WHERE aliasTarget = ? AND domain = ?' , args : [ name , domain ] } ) ;
2016-09-25 23:21:55 -07:00
aliases . forEach ( function ( alias ) {
2017-11-09 23:45:29 +01:00
queries . push ( { query : 'INSERT INTO mailboxes (name, domain, aliasTarget, ownerId, ownerType) VALUES (?, ?, ?, ?, ?)' ,
2018-01-20 22:17:53 -08:00
args : [ alias , domain , name , results [ 0 ] . ownerId , results [ 0 ] . ownerType ] } ) ;
2016-09-25 23:21:55 -07:00
} ) ;
database . transaction ( queries , function ( error ) {
if ( error && error . code === 'ER_DUP_ENTRY' ) return callback ( new DatabaseError ( DatabaseError . ALREADY _EXISTS , error . message ) ) ;
if ( error ) return callback ( new DatabaseError ( DatabaseError . INTERNAL _ERROR , error ) ) ;
callback ( null ) ;
} ) ;
2016-05-27 19:20:42 -07:00
} ) ;
}
2017-11-09 23:45:29 +01:00
function getAliasesForName ( name , domain , callback ) {
2016-05-27 19:20:42 -07:00
assert . strictEqual ( typeof name , 'string' ) ;
2017-11-09 23:45:29 +01:00
assert . strictEqual ( typeof domain , 'string' ) ;
2016-05-27 19:20:42 -07:00
assert . strictEqual ( typeof callback , 'function' ) ;
2017-11-09 23:45:29 +01:00
database . query ( 'SELECT name FROM mailboxes WHERE aliasTarget = ? AND domain = ? ORDER BY name' , [ name , domain ] , function ( error , results ) {
2016-05-26 22:34:04 -07:00
if ( error ) return callback ( new DatabaseError ( DatabaseError . INTERNAL _ERROR , error ) ) ;
2016-05-27 19:20:42 -07:00
results = results . map ( function ( r ) { return r . name ; } ) ;
2016-05-26 22:34:04 -07:00
callback ( null , results ) ;
} ) ;
}
2016-09-25 18:59:11 -07:00
2017-11-09 23:45:29 +01:00
function listAliases ( domain , callback ) {
assert . strictEqual ( typeof domain , 'string' ) ;
2016-09-25 18:59:11 -07:00
assert . strictEqual ( typeof callback , 'function' ) ;
2017-11-09 23:45:29 +01:00
database . query ( 'SELECT ' + MAILBOX _FIELDS + ' FROM mailboxes WHERE domain = ? AND aliasTarget IS NOT NULL ORDER BY name' , [ domain ] , function ( error , results ) {
2016-09-25 18:59:11 -07:00
if ( error ) return callback ( new DatabaseError ( DatabaseError . INTERNAL _ERROR , error ) ) ;
2018-04-05 15:46:13 -07:00
results . forEach ( function ( result ) { postProcess ( result ) ; } ) ;
2016-09-25 18:59:11 -07:00
callback ( null , results ) ;
} ) ;
}
2017-11-09 23:45:29 +01:00
function getAlias ( name , domain , callback ) {
2016-09-25 18:59:11 -07:00
assert . strictEqual ( typeof name , 'string' ) ;
2017-11-09 23:45:29 +01:00
assert . strictEqual ( typeof domain , 'string' ) ;
2016-09-25 18:59:11 -07:00
assert . strictEqual ( typeof callback , 'function' ) ;
2017-11-09 23:45:29 +01:00
database . query ( 'SELECT ' + MAILBOX _FIELDS + ' FROM mailboxes WHERE name = ? AND domain = ? AND aliasTarget IS NOT NULL' , [ name , domain ] , function ( error , results ) {
2016-09-25 18:59:11 -07:00
if ( error ) return callback ( new DatabaseError ( DatabaseError . INTERNAL _ERROR , error ) ) ;
if ( results . length === 0 ) return callback ( new DatabaseError ( DatabaseError . NOT _FOUND ) ) ;
2018-04-05 15:46:13 -07:00
results . forEach ( function ( result ) { postProcess ( result ) ; } ) ;
2016-09-25 18:59:11 -07:00
callback ( null , results [ 0 ] ) ;
} ) ;
}