diff --git a/gulpfile.js b/gulpfile.js index 4659bb1b4..f7be34c74 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -80,7 +80,6 @@ gulp.task('js-index', function () { return gulp.src([ 'src/js/index.js', 'src/js/client.js', - 'src/js/appstore.js', 'src/js/main.js', 'src/views/*.js' ]) @@ -198,7 +197,7 @@ gulp.task('watch', function (done) { gulp.watch(['src/js/restore.js', 'src/js/client.js'], gulp.series(['js-restore'])); gulp.watch(['src/js/logs.js', 'src/js/client.js'], gulp.series(['js-logs'])); gulp.watch(['src/js/terminal.js', 'src/js/client.js'], gulp.series(['js-terminal'])); - gulp.watch(['src/js/index.js', 'src/js/client.js', 'src/js/appstore.js', 'src/js/main.js', 'src/views/*.js'], gulp.series(['js-index'])); + gulp.watch(['src/js/index.js', 'src/js/client.js', 'src/js/main.js', 'src/views/*.js'], gulp.series(['js-index'])); gulp.watch(['src/3rdparty/**/*'], gulp.series(['3rdparty'])); done(); }); diff --git a/src/js/appstore.js b/src/js/appstore.js deleted file mode 100644 index 38b482070..000000000 --- a/src/js/appstore.js +++ /dev/null @@ -1,93 +0,0 @@ -'use strict'; - -/* global angular:false */ - -angular.module('Application').service('AppStore', ['$http', '$base64', 'Client', function ($http, $base64, Client) { - - function AppStoreError(statusCode, message) { - Error.call(this); - this.name = this.constructor.name; - this.statusCode = statusCode; - if (typeof message == 'string') { - this.message = message; - } else { - this.message = JSON.stringify(message); - } - } - - function AppStore() { - } - - AppStore.prototype.register = function (email, password, callback) { - if (Client.getConfig().apiServerOrigin === null) return callback(new AppStoreError(420, 'Enhance Your Calm')); - - var data = { - email: email, - password: password - }; - - $http.post(Client.getConfig().apiServerOrigin + '/api/v1/users', data).success(function (data, status) { - if (status !== 201) return callback(new AppStoreError(status, data)); - return callback(null, data); - }).error(function (data, status) { - return callback(new AppStoreError(status, data)); - }); - }; - - AppStore.prototype.login = function (email, password, totpToken, callback) { - if (Client.getConfig().apiServerOrigin === null) return callback(new AppStoreError(420, 'Enhance Your Calm')); - - var data = { - email: email, - password: password, - persistent: true, - totpToken: totpToken - }; - - $http.post(Client.getConfig().apiServerOrigin + '/api/v1/login', data).success(function (data, status) { - if (status !== 200) return callback(new AppStoreError(status, data)); - return callback(null, data); - }).error(function (data, status) { - return callback(new AppStoreError(status, data)); - }); - }; - - AppStore.prototype.logout = function (email, password, callback) { - if (Client.getConfig().apiServerOrigin === null) return callback(new AppStoreError(420, 'Enhance Your Calm')); - - $http.post(Client.getConfig().apiServerOrigin + '/api/v1/logout').success(function (data, status) { - if (status !== 200) return callback(new AppStoreError(status, data)); - return callback(null); - }).error(function (data, status) { - return callback(new AppStoreError(status, data)); - }); - }; - - AppStore.prototype.getProfile = function (token, callback) { - if (Client.getConfig().apiServerOrigin === null) return callback(new AppStoreError(420, 'Enhance Your Calm')); - - $http.get(Client.getConfig().apiServerOrigin + '/api/v1/profile', { params: { accessToken: token }}).success(function (data, status) { - if (status !== 200) return callback(new AppStoreError(status, data)); - - // just some helper property, since angular bindings cannot dot his easily - data.profile.emailEncoded = encodeURIComponent(data.profile.email); - - return callback(null, data.profile); - }).error(function (data, status) { - return callback(new AppStoreError(status, data)); - }); - }; - - AppStore.prototype.getSubscription = function (appstoreConfig, callback) { - if (Client.getConfig().apiServerOrigin === null) return callback(new AppStoreError(420, 'Enhance Your Calm')); - - $http.get(Client.getConfig().apiServerOrigin + '/api/v1/users/' + appstoreConfig.userId + '/cloudrons/' + appstoreConfig.cloudronId + '/subscription', { params: { accessToken: appstoreConfig.token }}).success(function (data, status) { - if (status !== 200) return callback(new AppStoreError(status, data)); - return callback(null, data.subscription); - }).error(function (data, status) { - return callback(new AppStoreError(status, data)); - }); - }; - - return new AppStore(); -}]); diff --git a/src/js/client.js b/src/js/client.js index fc97f5977..2dd87a219 100644 --- a/src/js/client.js +++ b/src/js/client.js @@ -611,24 +611,6 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N }); }; - Client.prototype.setAppstoreConfig = function (appstoreConfig, callback) { - post('/api/v1/settings/appstore_config', appstoreConfig, null, function (error, data, status) { - if (error) return callback(error); - if (status !== 202) return callback(new ClientError(status, data)); - - callback(null); - }); - }; - - Client.prototype.getAppstoreConfig = function (callback) { - get('/api/v1/settings/appstore_config', null, function (error, data, status) { - if (error) return callback(error); - if (status !== 200) return callback(new ClientError(status, data)); - - callback(null, data); - }); - }; - Client.prototype.getRemoteSupport = function (callback) { get('/api/v1/support/remote_support', null, function (error, data, status) { if (error) return callback(error); diff --git a/src/js/main.js b/src/js/main.js index 6a0240cf6..9c94a6360 100644 --- a/src/js/main.js +++ b/src/js/main.js @@ -3,7 +3,7 @@ /* global angular:false */ /* global $:false */ -angular.module('Application').controller('MainController', ['$scope', '$route', '$timeout', '$location', 'Client', 'AppStore', function ($scope, $route, $timeout, $location, Client, AppStore) { +angular.module('Application').controller('MainController', ['$scope', '$route', '$timeout', '$location', 'Client', function ($scope, $route, $timeout, $location, Client) { $scope.initialized = false; // used to animate the UI $scope.user = Client.getUserInfo(); $scope.installedApps = Client.getInstalledApps(); diff --git a/src/views/appstore.html b/src/views/appstore.html index adca97592..0864d7746 100644 --- a/src/views/appstore.html +++ b/src/views/appstore.html @@ -161,7 +161,7 @@ - Setup Subscription + Setup Subscription @@ -189,7 +189,7 @@ -
+

Sign up with Cloudron.io

Login to Cloudron.io

@@ -255,12 +255,12 @@
-
+


-
+

diff --git a/src/views/appstore.js b/src/views/appstore.js index 4108e1374..09df3bf17 100644 --- a/src/views/appstore.js +++ b/src/views/appstore.js @@ -3,7 +3,7 @@ /* global angular:false */ /* global $:false */ -angular.module('Application').controller('AppStoreController', ['$scope', '$location', '$timeout', '$routeParams', 'Client', 'AppStore', function ($scope, $location, $timeout, $routeParams, Client, AppStore) { +angular.module('Application').controller('AppStoreController', ['$scope', '$location', '$timeout', '$routeParams', 'Client', function ($scope, $location, $timeout, $routeParams, Client) { Client.onReady(function () { if (!Client.getUserInfo().admin) $location.path('/'); }); $scope.HOST_PORT_MIN = 1024; @@ -19,9 +19,9 @@ angular.module('Application').controller('AppStoreController', ['$scope', '$loca $scope.category = ''; $scope.cachedCategory = ''; // used to cache the selected category while searching $scope.searchString = ''; - $scope.validAppstoreAccount = false; - $scope.appstoreConfig = null; + $scope.validSubscription = false; $scope.unstableApps = false; + $scope.subscription = {}; $scope.showView = function (view) { // wait for dialog to be fully closed to avoid modal behavior breakage when moving to a different view already @@ -241,70 +241,7 @@ angular.module('Application').controller('AppStoreController', ['$scope', '$loca $scope.appstoreLogin.error = {}; $scope.appstoreLogin.busy = true; - function login() { - AppStore.login($scope.appstoreLogin.email, $scope.appstoreLogin.password, $scope.appstoreLogin.totpToken, function (error, result) { - if (error) { - $scope.appstoreLogin.busy = false; - - if (error.statusCode === 401) { - if (error.message.indexOf('TOTP token missing') !== -1) { - $scope.appstoreLogin.error.totpToken = 'A 2FA token is required'; - setTimeout(function () { $('#inputAppstoreLoginTotpToken').focus(); }, 0); - } else if (error.message.indexOf('TOTP token invalid') !== -1) { - $scope.appstoreLogin.error.totpToken = 'Wrong 2FA token'; - $scope.appstoreLogin.totpToken = ''; - setTimeout(function () { $('#inputAppstoreLoginTotpToken').focus(); }, 0); - } else { - $scope.appstoreLogin.error.password = 'Wrong email or password'; - $scope.appstoreLogin.password = ''; - $('#inputAppstoreLoginPassword').focus(); - $scope.appstoreLoginForm.password.$setPristine(); - } - } else { - console.error(error); - } - - return; - } - - var config = { - userId: result.userId, - token: result.accessToken - }; - - Client.setAppstoreConfig(config, function (error) { - if (error) { - $scope.appstoreLogin.busy = false; - - if (error.statusCode === 424) { - if (error.message === 'wrong user') { - $scope.appstoreLogin.error.generic = 'Wrong cloudron.io account'; - $scope.appstoreLogin.email = ''; - $scope.appstoreLogin.password = ''; - $scope.appstoreLoginForm.email.$setPristine(); - $scope.appstoreLoginForm.password.$setPristine(); - $('#inputAppstoreLoginEmail').focus(); - } else { - console.error(error); - $scope.appstoreLogin.error.generic = 'Please retry later'; - } - } else { - console.error(error); - } - - return; - } - - fetchAppstoreConfig(function (error) { - if (error) return console.error('Unable to fetch appstore config.', error); - }); - }); - }); - } - - if (!$scope.appstoreLogin.register) return login(); - - AppStore.register($scope.appstoreLogin.email, $scope.appstoreLogin.password, function (error) { + Client.subscribeCloudron($scope.appstoreLogin.email, $scope.appstoreLogin.password, $scope.appstoreLogin.totpToken, $scope.appstoreLogin.register, function (error) { if (error) { $scope.appstoreLogin.busy = false; @@ -314,6 +251,32 @@ angular.module('Application').controller('AppStoreController', ['$scope', '$loca $scope.appstoreLoginForm.email.$setPristine(); $scope.appstoreLoginForm.password.$setPristine(); $('#inputAppstoreLoginEmail').focus(); + } else if (error.statusCode === 412) { + if (error.message.indexOf('TOTP token missing') !== -1) { + $scope.appstoreLogin.error.totpToken = 'A 2FA token is required'; + setTimeout(function () { $('#inputAppstoreLoginTotpToken').focus(); }, 0); + } else if (error.message.indexOf('TOTP token invalid') !== -1) { + $scope.appstoreLogin.error.totpToken = 'Wrong 2FA token'; + $scope.appstoreLogin.totpToken = ''; + setTimeout(function () { $('#inputAppstoreLoginTotpToken').focus(); }, 0); + } else { + $scope.appstoreLogin.error.password = 'Wrong email or password'; + $scope.appstoreLogin.password = ''; + $('#inputAppstoreLoginPassword').focus(); + $scope.appstoreLoginForm.password.$setPristine(); + } + } else if (error.statusCode === 424) { + if (error.message === 'wrong user') { + $scope.appstoreLogin.error.generic = 'Wrong cloudron.io account'; + $scope.appstoreLogin.email = ''; + $scope.appstoreLogin.password = ''; + $scope.appstoreLoginForm.email.$setPristine(); + $scope.appstoreLoginForm.password.$setPristine(); + $('#inputAppstoreLoginEmail').focus(); + } else { + console.error(error); + $scope.appstoreLogin.error.generic = error.message; + } } else { console.error(error); $scope.appstoreLogin.error.generic = 'Please retry later'; @@ -321,8 +284,6 @@ angular.module('Application').controller('AppStoreController', ['$scope', '$loca return; } - - login(); }); } }; @@ -475,42 +436,21 @@ angular.module('Application').controller('AppStoreController', ['$scope', '$loca }); } - function fetchAppstoreConfig(callback) { - callback = callback || function (error) { if (error) console.error(error); }; + function getSubscription(callback) { + Client.getSubscription(function (error, subscription) { + if (error) { // error.statusCode will be 402 + $scope.validSubscription = false; + } else { + $scope.subscription = subscription; + } - if ($scope.user.admin && $scope.config.managed) { - $scope.validAppstoreAccount = true; - return callback(); - } + // clear busy state when a login/signup was performed + $scope.appstoreLogin.busy = false; - Client.getAppstoreConfig(function (error, result) { - if (error) return callback(error); + // also update the root controller status + if ($scope.$parent) $scope.$parent.updateSubscriptionStatus(); - if (!result.token || !result.cloudronId) return callback(); - - var appstoreConfig = result; - - AppStore.getProfile(appstoreConfig.token, function (error, result) { - if (error) return console.error(error); - - // assign late to avoid UI flicketing on update - appstoreConfig.profile = result; - $scope.appstoreConfig = appstoreConfig; - - $scope.validAppstoreAccount = true; - - // clear busy state when a login/signup was performed - $scope.appstoreLogin.busy = false; - - // also update the root controller status - if ($scope.$parent) { - $scope.$parent.fetchAppstoreProfileAndSubscription(function (error) { - if (error) console.error(error); - }); - } - - callback(); - }); + callback(); }); } @@ -541,7 +481,7 @@ angular.module('Application').controller('AppStoreController', ['$scope', '$loca // hashChangeListener calls $apply, so make sure we don't double digest here setTimeout(hashChangeListener, 1); - fetchAppstoreConfig(function (error) { + getSubscription(function (error) { if (error) console.error(error); $scope.ready = true; @@ -575,7 +515,7 @@ angular.module('Application').controller('AppStoreController', ['$scope', '$loca }); // autofocus if appstore login is shown - $scope.$watch('validAppstoreAccount', function (newValue/*, oldValue */) { + $scope.$watch('validSubscription', function (newValue/*, oldValue */) { if (!newValue) setTimeout(function () { $('[name=appstoreLoginForm]').find('[autofocus]:first').focus(); }, 1000); }); diff --git a/src/views/settings.js b/src/views/settings.js index 19747e578..4cbfb6e8e 100644 --- a/src/views/settings.js +++ b/src/views/settings.js @@ -3,7 +3,7 @@ /* global angular:false */ /* global $:false */ -angular.module('Application').controller('SettingsController', ['$scope', '$location', '$rootScope', '$timeout', 'Client', 'AppStore', function ($scope, $location, $rootScope, $timeout, Client, AppStore) { +angular.module('Application').controller('SettingsController', ['$scope', '$location', '$rootScope', '$timeout', 'Client', function ($scope, $location, $rootScope, $timeout, Client) { Client.onReady(function () { if (!Client.getUserInfo().admin) $location.path('/'); }); $scope.client = Client; @@ -314,7 +314,7 @@ angular.module('Application').controller('SettingsController', ['$scope', '$loca $scope.subscription = result; // also reload the subscription on the main controller - $scope.$parent.updateSubscriptionStatus(function () {}); + $scope.$parent.updateSubscriptionStatus(); // check again to give more immediate feedback once a subscription was setup if (result.plan.id === 'free') $timeout(getSubscription, 10000);