From 173aeb80ddbacca1b7aaa2a27bfef8381d0e2c16 Mon Sep 17 00:00:00 2001 From: tahaa karim Date: Wed, 8 Jun 2016 14:02:30 +0530 Subject: [PATCH] add aliases feature add aliases feature add aliases feature mapper entity service and controller for aliases comments and fixes minor bug fix minor changes aliases js service, database update and some security fixes minor fixes for saving and loading aliases send mail from composer using alias small fixes fix most test, delete alias work, better ui set an alias name with alias id using alias name when sending email works big fixes big fixes reply composer using aliases bug fixes and aliases collection minor bug fixes minor fix radio for aliases controller and service fix for when refrshing settings page fix email length in the database [tx-robot] updated from transifex change to secure connection remove secure http: false [tx-robot] updated from transifex Correct return for getFolderById - fixes #1514 account !== folder fetch UIDs and DATEs of all messages and do the pagination client side use search strategy only if SORT is not supported update changelog for 0.5.2 Update composerlock to https remove more message button is obsolete with infinite scroll [tx-robot] updated from transifex [tx-robot] updated from transifex [tx-robot] updated from transifex refactor message 'load' event parameters messagecontent -> foldercontent pass account/folder via constructor also use the new collection when refreshing inject messages collection Fix jscs errors sync karma require config with runtime require config open first mailbox when clicking the account's email address fix jscs error update grunt 0.5.3 version bump update/unify license headers use underscore to debounce search filters; do not re-search the same term remove obsolete folder reset event + event handler smoother transition when adding another account remove user id from alias table and js bug fix and optimization add new keyboard channel and port existing key listener allow navigation with j, k allow left/right arrow to switch messages use 'mail' instead of 'Mail' for bower to prevent warning merge conflict resolve squash and rebase commits fix AccountsControllerTest::testIndex travis js fix alias collection update adding aliases collection and bug fixes big fixes show you when mail is sent to an alias or email select current account as default in composer fix for selecting default account on composer fix grunt issues --- appinfo/database.xml | 33 ++++++ appinfo/routes.php | 1 + js/app.js | 2 + js/controller/aliasescontroller.js | 75 ++++++++++++ js/models/account.js | 8 +- js/models/alias.js | 38 ++++++ js/models/aliasescollection.js | 25 ++++ js/radio.js | 3 +- js/routecontroller.js | 14 +++ js/router.js | 3 +- js/service/aliasesservice.js | 125 ++++++++++++++++++++ js/service/messageservice.js | 6 +- js/templates/account.html | 5 +- js/templates/accountsettings.html | 13 ++ js/templates/aliases-list.html | 14 +++ js/templates/composer.html | 4 +- js/views/account.js | 12 +- js/views/accountsettings.js | 84 +++++++++++++ js/views/aliases-list.js | 54 +++++++++ js/views/aliases.js | 26 ++++ js/views/appview.js | 14 ++- js/views/composer.js | 86 ++++++++++++-- js/views/helper.js | 4 +- js/views/message.js | 10 +- lib/account.php | 16 ++- lib/controller/accountscontroller.php | 19 ++- lib/controller/aliasescontroller.php | 103 ++++++++++++++++ lib/db/alias.php | 31 +++++ lib/db/aliasmapper.php | 50 ++++++++ lib/service/aliasesservice.php | 103 ++++++++++++++++ tests/controller/accountscontrollertest.php | 25 +++- 31 files changed, 967 insertions(+), 39 deletions(-) create mode 100644 js/controller/aliasescontroller.js create mode 100644 js/models/alias.js create mode 100644 js/models/aliasescollection.js create mode 100644 js/service/aliasesservice.js create mode 100644 js/templates/accountsettings.html create mode 100644 js/templates/aliases-list.html create mode 100644 js/views/accountsettings.js create mode 100644 js/views/aliases-list.js create mode 100644 js/views/aliases.js create mode 100644 lib/controller/aliasescontroller.php create mode 100644 lib/db/alias.php create mode 100644 lib/db/aliasmapper.php create mode 100644 lib/service/aliasesservice.php diff --git a/appinfo/database.xml b/appinfo/database.xml index 388ba792..9e79a6ae 100644 --- a/appinfo/database.xml +++ b/appinfo/database.xml @@ -156,4 +156,37 @@ + + *dbprefix*mail_aliases + + + id + integer + 1 + 0 + true + 4 + + + account_id + integer + + true + 4 + + + name + text + + false + 64 + + + alias + text + true + 255 + + +
diff --git a/appinfo/routes.php b/appinfo/routes.php index 41192806..a6bcd02e 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -63,5 +63,6 @@ 'accounts' => ['url' => '/accounts'], 'folders' => ['url' => '/accounts/{accountId}/folders'], 'messages' => ['url' => '/accounts/{accountId}/folders/{folderId}/messages'], + 'aliases' => ['url' => '/accounts/{accountId}/aliases'], ] ]); diff --git a/js/app.js b/js/app.js index 33293bad..507cbca2 100644 --- a/js/app.js +++ b/js/app.js @@ -40,11 +40,13 @@ define(function(require) { // Load controllers/services require('controller/foldercontroller'); require('controller/messagecontroller'); + require('controller/aliasescontroller'); require('service/accountservice'); require('service/attachmentservice'); require('service/davservice'); require('service/folderservice'); require('service/messageservice'); + require('service/aliasesservice'); require('notification'); // Set marionette defaults diff --git a/js/controller/aliasescontroller.js b/js/controller/aliasescontroller.js new file mode 100644 index 00000000..2e1e846d --- /dev/null +++ b/js/controller/aliasescontroller.js @@ -0,0 +1,75 @@ +/** + * @author Tahaa Karim + * + * ownCloud - Mail + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + +define(function(require) { + 'use strict'; + + var $ = require('jquery'); + var _ = require('underscore'); + var Radio = require('radio'); + + Radio.aliases.reply('load:alias', loadAliases); + Radio.aliases.reply('save:alias', saveAlias); + Radio.aliases.reply('delete:alias', deleteAlias); + + /** + * @param {Account} account + * @returns {undefined} + */ + function loadAliases(account) { + var fetchingAliases = Radio.aliases.request('entities'); + + $.when(fetchingAliases).fail(function() { + Radio.ui.trigger('error:show', t('mail', 'Fetching Aliases Failed.')); + }); + + return fetchingAliases; + } + + /** + * @param {Account} account + * @param alias + * @returns {undefined} + */ + function saveAlias(account, alias) { + var savingAliases = Radio.aliases.request('save', account, alias); + + $.when(savingAliases).fail(function() { + Radio.ui.trigger('error:show', t('mail', 'Saving Aliases Failed.')); + }); + + return savingAliases; + } + + /** + * @param {Account} account + * @param aliasId + * @returns {undefined} + */ + function deleteAlias(account, aliasId) { + var deletingAliases = Radio.aliases.request('delete', account, aliasId); + + $.when(deletingAliases).fail(function() { + Radio.ui.trigger('error:show', t('mail', 'Deleting Aliases Failed.')); + }); + + return deletingAliases; + } + +}); diff --git a/js/models/account.js b/js/models/account.js index b7d88a72..04bab627 100644 --- a/js/models/account.js +++ b/js/models/account.js @@ -13,6 +13,7 @@ define(function(require) { var Backbone = require('backbone'); var FolderCollection = require('models/foldercollection'); + var AliasesCollection = require('models/aliasescollection'); var OC = require('OC'); /** @@ -20,12 +21,14 @@ define(function(require) { */ var Account = Backbone.Model.extend({ defaults: { - folders: [] + folders: [], + aliases: [] }, idAttribute: 'accountId', url: OC.generateUrl('apps/mail/accounts'), initialize: function() { this.set('folders', new FolderCollection(this.get('folders'))); + this.set('aliases', new AliasesCollection(this.get('aliases'))); }, _getFolderByIdRecursively: function(folder, folderId) { if (!folder) { @@ -67,6 +70,9 @@ define(function(require) { if (data.folders && data.folders.toJSON) { data.folders = data.folders.toJSON(); } + if (data.aliases && data.aliases.toJSON) { + data.aliases = data.aliases.toJSON(); + } if (!data.id) { data.id = this.cid; } diff --git a/js/models/alias.js b/js/models/alias.js new file mode 100644 index 00000000..62cf7a5f --- /dev/null +++ b/js/models/alias.js @@ -0,0 +1,38 @@ +/** + * ownCloud - Mail + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Tahaa Karim + * @copyright Tahaa Karim 2016 + */ + +define(function(require) { + 'use strict'; + + var Backbone = require('backbone'); + + /** + * @class Alias + */ + var Alias = Backbone.Model.extend({ + defaults: { + }, + initialize: function() { + + }, + toJSON: function() { + var data = Backbone.Model.prototype.toJSON.call(this); + if (data.alias && data.alias.toJSON) { + data.alias = data.alias.toJSON(); + } + if (!data.id) { + data.id = this.cid; + } + return data; + } + }); + + return Alias; +}); diff --git a/js/models/aliasescollection.js b/js/models/aliasescollection.js new file mode 100644 index 00000000..202a5999 --- /dev/null +++ b/js/models/aliasescollection.js @@ -0,0 +1,25 @@ +/** + * ownCloud - Mail + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Tahaa Karim + * @copyright Tahaa Karim 2016 + */ + +define(function(require) { + 'use strict'; + + var Backbone = require('backbone'); + var Alias = require('models/alias'); + + /** + * @class AliasesCollection + */ + var AliasesCollection = Backbone.Collection.extend({ + model: Alias + }); + + return AliasesCollection; +}); diff --git a/js/radio.js b/js/radio.js index c7b5ac83..8ca01fa3 100644 --- a/js/radio.js +++ b/js/radio.js @@ -23,7 +23,8 @@ define(function(require) { 'notification', 'state', 'ui', - 'keyboard' + 'keyboard', + 'aliases' ]; var channels = {}; diff --git a/js/routecontroller.js b/js/routecontroller.js index 48019e67..a6ec13cb 100644 --- a/js/routecontroller.js +++ b/js/routecontroller.js @@ -39,6 +39,7 @@ define(function(require) { Radio.navigation.on('folder', _.bind(this.showFolder, this)); Radio.navigation.on('setup', _.bind(this.showSetup, this)); + Radio.navigation.on('accountsettings', _.bind(this.showAccountSettings, this)); }, _navigate: function(route, options) { options = options || {}; @@ -123,6 +124,19 @@ define(function(require) { Radio.ui.trigger('composer:leave'); Radio.ui.trigger('navigation:hide'); Radio.ui.trigger('setup:show'); + }, + showAccountSettings: function(accountId) { + this._navigate('accounts/' + accountId + '/settings'); + var account = this.accounts.get(accountId); + if (_.isUndefined(account)) { + // Unknown account id -> redirect + Radio.ui.trigger('error:show', t('mail', 'Invalid account')); + this.default(); + return; + } + Radio.ui.trigger('composer:leave'); + Radio.ui.trigger('navigation:hide'); + Radio.ui.trigger('accountsettings:show', account); } }; diff --git a/js/router.js b/js/router.js index d3c634fb..e67348f1 100644 --- a/js/router.js +++ b/js/router.js @@ -30,7 +30,8 @@ define(function(require) { '': 'default', 'accounts/:accountId/folders/:folderId': 'showFolder', 'mailto(?:params)': 'mailTo', - 'setup': 'showSetup' + 'setup': 'showSetup', + 'accounts/:accountId/settings': 'showAccountSettings' } }); diff --git a/js/service/aliasesservice.js b/js/service/aliasesservice.js new file mode 100644 index 00000000..8ee351b9 --- /dev/null +++ b/js/service/aliasesservice.js @@ -0,0 +1,125 @@ +/** + * @author Tahaa Karim + * + * ownCloud - Mail + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + +define(function(require) { + 'use strict'; + + var $ = require('jquery'); + var OC = require('OC'); + var Radio = require('radio'); + + Radio.aliases.reply('entities', getAliasesEntities); + Radio.aliases.reply('save', saveAlias); + Radio.aliases.reply('delete', deleteAlias); + + /** + * @param {Account} account + * @returns {Promise} + */ + function getAliasesEntities(account) { + var defer = $.Deferred(); + + var url = OC.generateUrl('/apps/mail/accounts/{id}/aliases', { + id: account.get('accountId') + }); + var data = { + type: 'GET', + success: function(data) { + }, + error: function(xhr) { + + }, + data: { + accountId: account.get('accountId') + } + }; + var promise = $.ajax(url, data); + + promise.done(function(data) { + defer.resolve(data); + }); + + promise.fail(function() { + defer.reject(); + }); + + return defer.promise(); + } + + /** + * @param {Account} account + * @param alias + * @returns {undefined} + */ + function saveAlias(account, alias) { + var defer = $.Deferred(); + + var url = OC.generateUrl('/apps/mail/accounts/{id}/aliases', { + id: account.get('accountId') + }); + var data = { + type: 'POST', + data: { + accountId: account.get('accountId'), + alias: alias.alias, + aliasName: alias.name + } + }; + var promise = $.ajax(url, data); + + promise.done(function(data) { + defer.resolve(data); + }); + + promise.fail(function() { + defer.reject(); + }); + + return defer.promise(); + } + + /** + * @param {Account} account + * @param aliasId + * @returns {undefined} + */ + function deleteAlias(account, aliasId) { + var defer = $.Deferred(); + + var url = OC.generateUrl('/apps/mail/accounts/{id}/aliases/{aliasId}', { + id: account.get('accountId'), + aliasId: aliasId + }); + var data = { + type: 'DELETE' + }; + var promise = $.ajax(url, data); + + promise.done(function(data) { + defer.resolve(); + }); + + promise.fail(function() { + defer.reject(); + }); + + return defer.promise(); + } + +}); \ No newline at end of file diff --git a/js/service/messageservice.js b/js/service/messageservice.js index 95785389..3531ec8f 100644 --- a/js/service/messageservice.js +++ b/js/service/messageservice.js @@ -231,7 +231,8 @@ define(function(require) { var defer = $.Deferred(); var defaultOptions = { - draftUID: null + draftUID: null, + aliasId: null }; _.defaults(options, defaultOptions); var url = OC.generateUrl('/apps/mail/accounts/{id}/send', { @@ -259,7 +260,8 @@ define(function(require) { attachments: message.attachments, folderId: options.folder ? options.folder.get('id') : null, messageId: options.messageId, - draftUID: options.draftUID + draftUID: options.draftUID, + aliasId: options.aliasId } }; $.ajax(url, data); diff --git a/js/templates/account.html b/js/templates/account.html index 548ea085..4220a587 100644 --- a/js/templates/account.html +++ b/js/templates/account.html @@ -12,7 +12,10 @@
    -
  • +
  • +
+
    +
{{/if}} diff --git a/js/templates/accountsettings.html b/js/templates/accountsettings.html new file mode 100644 index 00000000..ee0d7dca --- /dev/null +++ b/js/templates/accountsettings.html @@ -0,0 +1,13 @@ +
+

{{ t 'Account Settings' }} - {{ email }}

+
+ +
+

{{ t 'Aliases' }}

+
+
+ + + +
+
diff --git a/js/templates/aliases-list.html b/js/templates/aliases-list.html new file mode 100644 index 00000000..2e3edd2a --- /dev/null +++ b/js/templates/aliases-list.html @@ -0,0 +1,14 @@ + + + + + + + + +
+ {{ aliases.alias }} + + {{ aliases.name }} + +
\ No newline at end of file diff --git a/js/templates/composer.html b/js/templates/composer.html index 2d307a58..19de3fba 100644 --- a/js/templates/composer.html +++ b/js/templates/composer.html @@ -1,11 +1,9 @@
- {{#unless isReply}} - {{/unless}}