summaryrefslogtreecommitdiffstats
path: root/apps/settings/src/store
diff options
context:
space:
mode:
authorChristoph Wurst <christoph@winzerhof-wurst.at>2019-09-17 16:33:27 +0200
committernpmbuildbot[bot] <npmbuildbot[bot]@users.noreply.github.com>2019-09-28 09:39:28 +0000
commitde6940352a2f708376219a89ec84a8e6d25ca59e (patch)
tree459bacfc183b24d611be1877fbe22bbcd4efb1d6 /apps/settings/src/store
parentc8cd607681ac128228f57114ce14dd67ab05de04 (diff)
downloadnextcloud-server-de6940352a2f708376219a89ec84a8e6d25ca59e.tar.gz
nextcloud-server-de6940352a2f708376219a89ec84a8e6d25ca59e.zip
Move settings to an app
Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at> Signed-off-by: npmbuildbot[bot] <npmbuildbot[bot]@users.noreply.github.com>
Diffstat (limited to 'apps/settings/src/store')
-rw-r--r--apps/settings/src/store/admin-security.js63
-rw-r--r--apps/settings/src/store/api.js81
-rw-r--r--apps/settings/src/store/apps.js327
-rw-r--r--apps/settings/src/store/index.js57
-rw-r--r--apps/settings/src/store/oc.js47
-rw-r--r--apps/settings/src/store/settings.js40
-rw-r--r--apps/settings/src/store/users.js532
7 files changed, 1147 insertions, 0 deletions
diff --git a/apps/settings/src/store/admin-security.js b/apps/settings/src/store/admin-security.js
new file mode 100644
index 00000000000..997aab2af58
--- /dev/null
+++ b/apps/settings/src/store/admin-security.js
@@ -0,0 +1,63 @@
+/*
+ * @copyright 2019 Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @author 2019 Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import Vue from 'vue'
+import Vuex from 'vuex'
+
+Vue.use(Vuex)
+
+export const mutations = {
+ setEnforced(state, enabled) {
+ Vue.set(state, 'enforced', enabled)
+ },
+ setEnforcedGroups(state, total) {
+ Vue.set(state, 'enforcedGroups', total)
+ },
+ setExcludedGroups(state, used) {
+ Vue.set(state, 'excludedGroups', used)
+ }
+}
+
+export const actions = {
+ save ({commit}, ) {
+ commit('setEnabled', false);
+
+ return generateCodes()
+ .then(({codes, state}) => {
+ commit('setEnabled', state.enabled);
+ commit('setTotal', state.total);
+ commit('setUsed', state.used);
+ commit('setCodes', codes);
+ return true;
+ });
+ }
+}
+
+export default new Vuex.Store({
+ strict: process.env.NODE_ENV !== 'production',
+ state: {
+ enforced: false,
+ enforcedGroups: [],
+ excludedGroups: [],
+ },
+ mutations,
+ actions
+})
diff --git a/apps/settings/src/store/api.js b/apps/settings/src/store/api.js
new file mode 100644
index 00000000000..185e80253a3
--- /dev/null
+++ b/apps/settings/src/store/api.js
@@ -0,0 +1,81 @@
+/**
+ * @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
+ *
+ * @author John Molakvoæ <skjnldsv@protonmail.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+import axios from 'nextcloud-axios'
+import confirmPassword from 'nextcloud-password-confirmation'
+
+const sanitize = function(url) {
+ return url.replace(/\/$/, ''); // Remove last url slash
+};
+
+export default {
+
+ /**
+ * This Promise is used to chain a request that require an admin password confirmation
+ * Since chaining Promise have a very precise behavior concerning catch and then,
+ * you'll need to be careful when using it.
+ * e.g
+ * // store
+ * action(context) {
+ * return api.requireAdmin().then((response) => {
+ * return api.get('url')
+ * .then((response) => {API success})
+ * .catch((error) => {API failure});
+ * }).catch((error) => {requireAdmin failure});
+ * }
+ * // vue
+ * this.$store.dispatch('action').then(() => {always executed})
+ *
+ * Since Promise.then().catch().then() will always execute the last then
+ * this.$store.dispatch('action').then will always be executed
+ *
+ * If you want requireAdmin failure to also catch the API request failure
+ * you will need to throw a new error in the api.get.catch()
+ *
+ * e.g
+ * api.requireAdmin().then((response) => {
+ * api.get('url')
+ * .then((response) => {API success})
+ * .catch((error) => {throw error;});
+ * }).catch((error) => {requireAdmin OR API failure});
+ *
+ * @returns {Promise}
+ */
+ requireAdmin() {
+ return confirmPassword();
+ },
+ get(url) {
+ return axios.get(sanitize(url));
+ },
+ post(url, data) {
+ return axios.post(sanitize(url), data);
+ },
+ patch(url, data) {
+ return axios.patch(sanitize(url), data);
+ },
+ put(url, data) {
+ return axios.put(sanitize(url), data);
+ },
+ delete(url, data) {
+ return axios.delete(sanitize(url), { data: data });
+ }
+}; \ No newline at end of file
diff --git a/apps/settings/src/store/apps.js b/apps/settings/src/store/apps.js
new file mode 100644
index 00000000000..8074eac2e00
--- /dev/null
+++ b/apps/settings/src/store/apps.js
@@ -0,0 +1,327 @@
+/*
+ * @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
+ *
+ * @author Julius Härtl <jus@bitgrid.net>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+import api from './api';
+import Vue from 'vue';
+
+const state = {
+ apps: [],
+ categories: [],
+ updateCount: 0,
+ loading: {},
+ loadingList: false,
+};
+
+const mutations = {
+
+ APPS_API_FAILURE(state, error) {
+ OC.Notification.showHtml(t('settings','An error occured during the request. Unable to proceed.')+'<br>'+error.error.response.data.data.message, {timeout: 7});
+ console.log(state, error);
+ },
+
+ initCategories(state, {categories, updateCount}) {
+ state.categories = categories;
+ state.updateCount = updateCount;
+ },
+
+ setUpdateCount(state, updateCount) {
+ state.updateCount = updateCount;
+ },
+
+ addCategory(state, category) {
+ state.categories.push(category);
+ },
+
+ appendCategories(state, categoriesArray) {
+ // convert obj to array
+ state.categories = categoriesArray;
+ },
+
+ setAllApps(state, apps) {
+ state.apps = apps;
+ },
+
+ setError(state, {appId, error}) {
+ if (!Array.isArray(appId)) {
+ appId = [appId];
+ }
+ appId.forEach((_id) => {
+ let app = state.apps.find(app => app.id === _id);
+ app.error = error;
+ });
+ },
+
+ clearError(state, {appId, error}) {
+ let app = state.apps.find(app => app.id === appId);
+ app.error = null;
+ },
+
+ enableApp(state, {appId, groups}) {
+ let app = state.apps.find(app => app.id === appId);
+ app.active = true;
+ app.groups = groups;
+ },
+
+ disableApp(state, appId) {
+ let app = state.apps.find(app => app.id === appId);
+ app.active = false;
+ app.groups = [];
+ if (app.removable) {
+ app.canUnInstall = true;
+ }
+ },
+
+ uninstallApp(state, appId) {
+ state.apps.find(app => app.id === appId).active = false;
+ state.apps.find(app => app.id === appId).groups = [];
+ state.apps.find(app => app.id === appId).needsDownload = true;
+ state.apps.find(app => app.id === appId).installed = false;
+ state.apps.find(app => app.id === appId).canUnInstall = false;
+ state.apps.find(app => app.id === appId).canInstall = true;
+ },
+
+ updateApp(state, appId) {
+ let app = state.apps.find(app => app.id === appId);
+ let version = app.update;
+ app.update = null;
+ app.version = version;
+ state.updateCount--;
+
+ },
+
+ resetApps(state) {
+ state.apps = [];
+ },
+ reset(state) {
+ state.apps = [];
+ state.categories = [];
+ state.updateCount = 0;
+ },
+ startLoading(state, id) {
+ if (Array.isArray(id)) {
+ id.forEach((_id) => {
+ Vue.set(state.loading, _id, true);
+ })
+ } else {
+ Vue.set(state.loading, id, true);
+ }
+ },
+ stopLoading(state, id) {
+ if (Array.isArray(id)) {
+ id.forEach((_id) => {
+ Vue.set(state.loading, _id, false);
+ })
+ } else {
+ Vue.set(state.loading, id, false);
+ }
+ },
+};
+
+const getters = {
+ loading(state) {
+ return function(id) {
+ return state.loading[id];
+ }
+ },
+ getCategories(state) {
+ return state.categories;
+ },
+ getAllApps(state) {
+ return state.apps;
+ },
+ getUpdateCount(state) {
+ return state.updateCount;
+ }
+};
+
+const actions = {
+
+ enableApp(context, { appId, groups }) {
+ let apps;
+ if (Array.isArray(appId)) {
+ apps = appId;
+ } else {
+ apps = [appId];
+ }
+ return api.requireAdmin().then((response) => {
+ context.commit('startLoading', apps);
+ context.commit('startLoading', 'install');
+ return api.post(OC.generateUrl(`settings/apps/enable`), {appIds: apps, groups: groups})
+ .then((response) => {
+ context.commit('stopLoading', apps);
+ context.commit('stopLoading', 'install');
+ apps.forEach(_appId => {
+ context.commit('enableApp', {appId: _appId, groups: groups});
+ });
+
+ // check for server health
+ return api.get(OC.generateUrl('apps/files'))
+ .then(() => {
+ if (response.data.update_required) {
+ OC.dialogs.info(
+ t(
+ 'settings',
+ 'The app has been enabled but needs to be updated. You will be redirected to the update page in 5 seconds.'
+ ),
+ t('settings','App update'),
+ function () {
+ window.location.reload();
+ },
+ true
+ );
+ setTimeout(function() {
+ location.reload();
+ }, 5000);
+ }
+ })
+ .catch((error) => {
+ if (!Array.isArray(appId)) {
+ context.commit('setError', {
+ appId: apps,
+ error: t('settings', 'Error: This app can not be enabled because it makes the server unstable')
+ });
+ }
+ });
+ })
+ .catch((error) => {
+ context.commit('stopLoading', apps);
+ context.commit('stopLoading', 'install');
+ context.commit('setError', {
+ appId: apps,
+ error: error.response.data.data.message
+ });
+ context.commit('APPS_API_FAILURE', { appId, error});
+ })
+ }).catch((error) => context.commit('API_FAILURE', { appId, error }));
+ },
+ forceEnableApp(context, { appId, groups }) {
+ let apps;
+ if (Array.isArray(appId)) {
+ apps = appId;
+ } else {
+ apps = [appId];
+ }
+ return api.requireAdmin().then(() => {
+ context.commit('startLoading', apps);
+ context.commit('startLoading', 'install');
+ return api.post(OC.generateUrl(`settings/apps/force`), {appId})
+ .then((response) => {
+ // TODO: find a cleaner solution
+ location.reload();
+ })
+ .catch((error) => {
+ context.commit('stopLoading', apps);
+ context.commit('stopLoading', 'install');
+ context.commit('setError', {
+ appId: apps,
+ error: error.response.data.data.message
+ });
+ context.commit('APPS_API_FAILURE', { appId, error});
+ })
+ }).catch((error) => context.commit('API_FAILURE', { appId, error }));
+ },
+ disableApp(context, { appId }) {
+ let apps;
+ if (Array.isArray(appId)) {
+ apps = appId;
+ } else {
+ apps = [appId];
+ }
+ return api.requireAdmin().then((response) => {
+ context.commit('startLoading', apps);
+ return api.post(OC.generateUrl(`settings/apps/disable`), {appIds: apps})
+ .then((response) => {
+ context.commit('stopLoading', apps);
+ apps.forEach(_appId => {
+ context.commit('disableApp', _appId);
+ });
+ return true;
+ })
+ .catch((error) => {
+ context.commit('stopLoading', apps);
+ context.commit('APPS_API_FAILURE', { appId, error })
+ })
+ }).catch((error) => context.commit('API_FAILURE', { appId, error }));
+ },
+ uninstallApp(context, { appId }) {
+ return api.requireAdmin().then((response) => {
+ context.commit('startLoading', appId);
+ return api.get(OC.generateUrl(`settings/apps/uninstall/${appId}`))
+ .then((response) => {
+ context.commit('stopLoading', appId);
+ context.commit('uninstallApp', appId);
+ return true;
+ })
+ .catch((error) => {
+ context.commit('stopLoading', appId);
+ context.commit('APPS_API_FAILURE', { appId, error })
+ })
+ }).catch((error) => context.commit('API_FAILURE', { appId, error }));
+ },
+
+ updateApp(context, { appId }) {
+ return api.requireAdmin().then((response) => {
+ context.commit('startLoading', appId);
+ context.commit('startLoading', 'install');
+ return api.get(OC.generateUrl(`settings/apps/update/${appId}`))
+ .then((response) => {
+ context.commit('stopLoading', 'install');
+ context.commit('stopLoading', appId);
+ context.commit('updateApp', appId);
+ return true;
+ })
+ .catch((error) => {
+ context.commit('stopLoading', appId);
+ context.commit('stopLoading', 'install');
+ context.commit('APPS_API_FAILURE', { appId, error })
+ })
+ }).catch((error) => context.commit('API_FAILURE', { appId, error }));
+ },
+
+ getAllApps(context) {
+ context.commit('startLoading', 'list');
+ return api.get(OC.generateUrl(`settings/apps/list`))
+ .then((response) => {
+ context.commit('setAllApps', response.data.apps);
+ context.commit('stopLoading', 'list');
+ return true;
+ })
+ .catch((error) => context.commit('API_FAILURE', error))
+ },
+
+ getCategories(context) {
+ context.commit('startLoading', 'categories');
+ return api.get(OC.generateUrl('settings/apps/categories'))
+ .then((response) => {
+ if (response.data.length > 0) {
+ context.commit('appendCategories', response.data);
+ context.commit('stopLoading', 'categories');
+ return true;
+ }
+ return false;
+ })
+ .catch((error) => context.commit('API_FAILURE', error));
+ },
+
+};
+
+export default { state, mutations, getters, actions }; \ No newline at end of file
diff --git a/apps/settings/src/store/index.js b/apps/settings/src/store/index.js
new file mode 100644
index 00000000000..00bcd67db39
--- /dev/null
+++ b/apps/settings/src/store/index.js
@@ -0,0 +1,57 @@
+/*
+ * @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
+ *
+ * @author John Molakvoæ <skjnldsv@protonmail.com>
+ * @author Julius Härtl <jus@bitgrid.net>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+import Vue from 'vue';
+import Vuex from 'vuex';
+import users from './users';
+import apps from './apps';
+import settings from './settings';
+import oc from './oc';
+
+Vue.use(Vuex)
+
+const debug = process.env.NODE_ENV !== 'production';
+
+const mutations = {
+ API_FAILURE(state, error) {
+ try {
+ let message = error.error.response.data.ocs.meta.message;
+ OC.Notification.showHtml(t('settings','An error occured during the request. Unable to proceed.')+'<br>'+message, {timeout: 7});
+ } catch(e) {
+ OC.Notification.showTemporary(t('settings','An error occured during the request. Unable to proceed.'));
+ }
+ console.log(state, error);
+ }
+};
+
+export default new Vuex.Store({
+ modules: {
+ users,
+ apps,
+ settings,
+ oc
+ },
+ strict: debug,
+
+ mutations
+});
diff --git a/apps/settings/src/store/oc.js b/apps/settings/src/store/oc.js
new file mode 100644
index 00000000000..afa13fe6b18
--- /dev/null
+++ b/apps/settings/src/store/oc.js
@@ -0,0 +1,47 @@
+/*
+ * @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
+ *
+ * @author John Molakvoæ <skjnldsv@protonmail.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+import api from './api';
+
+const state = {};
+const mutations = {};
+const getters = {};
+const actions = {
+ /**
+ * Set application config in database
+ *
+ * @param {Object} context
+ * @param {Object} options
+ * @param {string} options.app Application name
+ * @param {boolean} options.key Config key
+ * @param {boolean} options.value Value to set
+ * @returns{Promise}
+ */
+ setAppConfig(context, {app, key, value}) {
+ return api.requireAdmin().then((response) => {
+ return api.post(OC.linkToOCS(`apps/provisioning_api/api/v1/config/apps/${app}/${key}`, 2), {value: value})
+ .catch((error) => {throw error;});
+ }).catch((error) => context.commit('API_FAILURE', { app, key, value, error }));;
+ }
+};
+
+export default {state, mutations, getters, actions};
diff --git a/apps/settings/src/store/settings.js b/apps/settings/src/store/settings.js
new file mode 100644
index 00000000000..5f0bcfa60aa
--- /dev/null
+++ b/apps/settings/src/store/settings.js
@@ -0,0 +1,40 @@
+/*
+ * @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
+ *
+ * @author John Molakvoæ <skjnldsv@protonmail.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+import api from './api';
+
+const state = {
+ serverData: {}
+};
+const mutations = {
+ setServerData(state, data) {
+ state.serverData = data;
+ }
+};
+const getters = {
+ getServerData(state) {
+ return state.serverData;
+ }
+};
+const actions = {};
+
+export default {state, mutations, getters, actions};
diff --git a/apps/settings/src/store/users.js b/apps/settings/src/store/users.js
new file mode 100644
index 00000000000..1b174b21bf4
--- /dev/null
+++ b/apps/settings/src/store/users.js
@@ -0,0 +1,532 @@
+/*
+ * @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
+ *
+ * @author John Molakvoæ <skjnldsv@protonmail.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+import api from './api';
+
+const orderGroups = function(groups, orderBy) {
+ /* const SORT_USERCOUNT = 1;
+ * const SORT_GROUPNAME = 2;
+ * https://github.com/nextcloud/server/blob/208e38e84e1a07a49699aa90dc5b7272d24489f0/lib/private/Group/MetaData.php#L34
+ */
+ if (orderBy === 1) {
+ return groups.sort((a, b) => a.usercount-a.disabled < b.usercount - b.disabled);
+ } else {
+ return groups.sort((a, b) => a.name.localeCompare(b.name));
+ }
+};
+
+const defaults = {
+ group: {
+ id: '',
+ name: '',
+ usercount: 0,
+ disabled: 0,
+ canAdd: true,
+ canRemove: true
+ }
+};
+
+const state = {
+ users: [],
+ groups: [],
+ orderBy: 1,
+ minPasswordLength: 0,
+ usersOffset: 0,
+ usersLimit: 25,
+ userCount: 0
+};
+
+const mutations = {
+ appendUsers(state, usersObj) {
+ // convert obj to array
+ let users = state.users.concat(Object.keys(usersObj).map(userid => usersObj[userid]));
+ state.usersOffset += state.usersLimit;
+ state.users = users;
+ },
+ setPasswordPolicyMinLength(state, length) {
+ state.minPasswordLength = length!=='' ? length : 0;
+ },
+ initGroups(state, {groups, orderBy, userCount}) {
+ state.groups = groups.map(group => Object.assign({}, defaults.group, group));
+ state.orderBy = orderBy;
+ state.userCount = userCount;
+ state.groups = orderGroups(state.groups, state.orderBy);
+
+ },
+ addGroup(state, {gid, displayName}) {
+ try {
+ if (typeof state.groups.find((group) => group.id === gid) !== 'undefined') {
+ return;
+ }
+ // extend group to default values
+ let group = Object.assign({}, defaults.group, {
+ id: gid,
+ name: displayName,
+ });
+ state.groups.push(group);
+ state.groups = orderGroups(state.groups, state.orderBy);
+ } catch (e) {
+ console.log('Can\'t create group', e);
+ }
+ },
+ removeGroup(state, gid) {
+ let groupIndex = state.groups.findIndex(groupSearch => groupSearch.id == gid);
+ if (groupIndex >= 0) {
+ state.groups.splice(groupIndex, 1);
+ }
+ },
+ addUserGroup(state, { userid, gid }) {
+ let group = state.groups.find(groupSearch => groupSearch.id == gid);
+ let user = state.users.find(user => user.id == userid);
+ // increase count if user is enabled
+ if (group && user.enabled) {
+ group.usercount++;
+ }
+ let groups = user.groups;
+ groups.push(gid);
+ state.groups = orderGroups(state.groups, state.orderBy);
+ },
+ removeUserGroup(state, { userid, gid }) {
+ let group = state.groups.find(groupSearch => groupSearch.id == gid);
+ let user = state.users.find(user => user.id == userid);
+ // lower count if user is enabled
+ if (group && user.enabled) {
+ group.usercount--;
+ }
+ let groups = user.groups;
+ groups.splice(groups.indexOf(gid),1);
+ state.groups = orderGroups(state.groups, state.orderBy);
+ },
+ addUserSubAdmin(state, { userid, gid }) {
+ let groups = state.users.find(user => user.id == userid).subadmin;
+ groups.push(gid);
+ },
+ removeUserSubAdmin(state, { userid, gid }) {
+ let groups = state.users.find(user => user.id == userid).subadmin;
+ groups.splice(groups.indexOf(gid),1);
+ },
+ deleteUser(state, userid) {
+ let userIndex = state.users.findIndex(user => user.id == userid);
+ state.users.splice(userIndex, 1);
+ },
+ addUserData(state, response) {
+ state.users.push(response.data.ocs.data);
+ },
+ enableDisableUser(state, { userid, enabled }) {
+ let user = state.users.find(user => user.id == userid);
+ user.enabled = enabled;
+ // increment or not
+ state.groups.find(group => group.id == 'disabled').usercount += enabled ? -1 : 1;
+ state.userCount += enabled ? 1 : -1;
+ user.groups.forEach(group => {
+ // Increment disabled count
+ state.groups.find(groupSearch => groupSearch.id == group).disabled += enabled ? -1 : 1;
+ });
+ },
+ setUserData(state, { userid, key, value }) {
+ if (key === 'quota') {
+ let humanValue = OC.Util.computerFileSize(value);
+ state.users.find(user => user.id == userid)[key][key] = humanValue!==null ? humanValue : value;
+ } else {
+ state.users.find(user => user.id == userid)[key] = value;
+ }
+ },
+
+ /**
+ * Reset users list
+ */
+ resetUsers(state) {
+ state.users = [];
+ state.usersOffset = 0;
+ }
+};
+
+const getters = {
+ getUsers(state) {
+ return state.users;
+ },
+ getGroups(state) {
+ return state.groups;
+ },
+ getSubadminGroups(state) {
+ // Can't be subadmin of admin or disabled
+ return state.groups.filter(group => group.id !== 'admin' && group.id !== 'disabled');
+ },
+ getPasswordPolicyMinLength(state) {
+ return state.minPasswordLength;
+ },
+ getUsersOffset(state) {
+ return state.usersOffset;
+ },
+ getUsersLimit(state) {
+ return state.usersLimit;
+ },
+ getUserCount(state) {
+ return state.userCount;
+ }
+};
+
+const actions = {
+
+ /**
+ * Get all users with full details
+ *
+ * @param {Object} context
+ * @param {Object} options
+ * @param {int} options.offset List offset to request
+ * @param {int} options.limit List number to return from offset
+ * @param {string} options.search Search amongst users
+ * @param {string} options.group Get users from group
+ * @returns {Promise}
+ */
+ getUsers(context, { offset, limit, search, group }) {
+ search = typeof search === 'string' ? search : '';
+ group = typeof group === 'string' ? group : '';
+ if (group !== '') {
+ return api.get(OC.linkToOCS(`cloud/groups/${group}/users/details?offset=${offset}&limit=${limit}&search=${search}`, 2))
+ .then((response) => {
+ if (Object.keys(response.data.ocs.data.users).length > 0) {
+ context.commit('appendUsers', response.data.ocs.data.users);
+ return true;
+ }
+ return false;
+ })
+ .catch((error) => context.commit('API_FAILURE', error));
+ }
+
+ return api.get(OC.linkToOCS(`cloud/users/details?offset=${offset}&limit=${limit}&search=${search}`, 2))
+ .then((response) => {
+ if (Object.keys(response.data.ocs.data.users).length > 0) {
+ context.commit('appendUsers', response.data.ocs.data.users);
+ return true;
+ }
+ return false;
+ })
+ .catch((error) => context.commit('API_FAILURE', error));
+ },
+
+ getGroups(context, { offset, limit, search }) {
+ search = typeof search === 'string' ? search : '';
+ let limitParam = limit === -1 ? '' : `&limit=${limit}`;
+ return api.get(OC.linkToOCS(`cloud/groups?offset=${offset}&search=${search}${limitParam}`, 2))
+ .then((response) => {
+ if (Object.keys(response.data.ocs.data.groups).length > 0) {
+ response.data.ocs.data.groups.forEach(function(group) {
+ context.commit('addGroup', {gid: group, displayName: group});
+ });
+ return true;
+ }
+ return false;
+ })
+ .catch((error) => context.commit('API_FAILURE', error));
+ },
+
+ /**
+ * Get all users with full details
+ *
+ * @param {Object} context
+ * @param {Object} options
+ * @param {int} options.offset List offset to request
+ * @param {int} options.limit List number to return from offset
+ * @returns {Promise}
+ */
+ getUsersFromList(context, { offset, limit, search }) {
+ search = typeof search === 'string' ? search : '';
+ return api.get(OC.linkToOCS(`cloud/users/details?offset=${offset}&limit=${limit}&search=${search}`, 2))
+ .then((response) => {
+ if (Object.keys(response.data.ocs.data.users).length > 0) {
+ context.commit('appendUsers', response.data.ocs.data.users);
+ return true;
+ }
+ return false;
+ })
+ .catch((error) => context.commit('API_FAILURE', error));
+ },
+
+ /**
+ * Get all users with full details from a groupid
+ *
+ * @param {Object} context
+ * @param {Object} options
+ * @param {int} options.offset List offset to request
+ * @param {int} options.limit List number to return from offset
+ * @returns {Promise}
+ */
+ getUsersFromGroup(context, { groupid, offset, limit }) {
+ return api.get(OC.linkToOCS(`cloud/users/${groupid}/details?offset=${offset}&limit=${limit}`, 2))
+ .then((response) => context.commit('getUsersFromList', response.data.ocs.data.users))
+ .catch((error) => context.commit('API_FAILURE', error));
+ },
+
+
+ getPasswordPolicyMinLength(context) {
+ if(OC.getCapabilities().password_policy && OC.getCapabilities().password_policy.minLength) {
+ context.commit('setPasswordPolicyMinLength', OC.getCapabilities().password_policy.minLength);
+ return OC.getCapabilities().password_policy.minLength;
+ }
+ return false;
+ },
+
+ /**
+ * Add group
+ *
+ * @param {Object} context
+ * @param {string} gid Group id
+ * @returns {Promise}
+ */
+ addGroup(context, gid) {
+ return api.requireAdmin().then((response) => {
+ return api.post(OC.linkToOCS(`cloud/groups`, 2), {groupid: gid})
+ .then((response) => {
+ context.commit('addGroup', {gid: gid, displayName: gid})
+ return {gid: gid, displayName: gid}
+ })
+ .catch((error) => {throw error;});
+ }).catch((error) => {
+ context.commit('API_FAILURE', { gid, error });
+ // let's throw one more time to prevent the view
+ // from adding the user to a group that doesn't exists
+ throw error;
+ });
+ },
+
+ /**
+ * Remove group
+ *
+ * @param {Object} context
+ * @param {string} gid Group id
+ * @returns {Promise}
+ */
+ removeGroup(context, gid) {
+ return api.requireAdmin().then((response) => {
+ return api.delete(OC.linkToOCS(`cloud/groups/${gid}`, 2))
+ .then((response) => context.commit('removeGroup', gid))
+ .catch((error) => {throw error;});
+ }).catch((error) => context.commit('API_FAILURE', { gid, error }));
+ },
+
+ /**
+ * Add user to group
+ *
+ * @param {Object} context
+ * @param {Object} options
+ * @param {string} options.userid User id
+ * @param {string} options.gid Group id
+ * @returns {Promise}
+ */
+ addUserGroup(context, { userid, gid }) {
+ return api.requireAdmin().then((response) => {
+ return api.post(OC.linkToOCS(`cloud/users/${userid}/groups`, 2), { groupid: gid })
+ .then((response) => context.commit('addUserGroup', { userid, gid }))
+ .catch((error) => {throw error;});
+ }).catch((error) => context.commit('API_FAILURE', { userid, error }));
+ },
+
+ /**
+ * Remove user from group
+ *
+ * @param {Object} context
+ * @param {Object} options
+ * @param {string} options.userid User id
+ * @param {string} options.gid Group id
+ * @returns {Promise}
+ */
+ removeUserGroup(context, { userid, gid }) {
+ return api.requireAdmin().then((response) => {
+ return api.delete(OC.linkToOCS(`cloud/users/${userid}/groups`, 2), { groupid: gid })
+ .then((response) => context.commit('removeUserGroup', { userid, gid }))
+ .catch((error) => {throw error;});
+ }).catch((error) => {
+ context.commit('API_FAILURE', { userid, error });
+ // let's throw one more time to prevent
+ // the view from removing the user row on failure
+ throw error;
+ });
+ },
+
+ /**
+ * Add user to group admin
+ *
+ * @param {Object} context
+ * @param {Object} options
+ * @param {string} options.userid User id
+ * @param {string} options.gid Group id
+ * @returns {Promise}
+ */
+ addUserSubAdmin(context, { userid, gid }) {
+ return api.requireAdmin().then((response) => {
+ return api.post(OC.linkToOCS(`cloud/users/${userid}/subadmins`, 2), { groupid: gid })
+ .then((response) => context.commit('addUserSubAdmin', { userid, gid }))
+ .catch((error) => {throw error;});
+ }).catch((error) => context.commit('API_FAILURE', { userid, error }));
+ },
+
+ /**
+ * Remove user from group admin
+ *
+ * @param {Object} context
+ * @param {Object} options
+ * @param {string} options.userid User id
+ * @param {string} options.gid Group id
+ * @returns {Promise}
+ */
+ removeUserSubAdmin(context, { userid, gid }) {
+ return api.requireAdmin().then((response) => {
+ return api.delete(OC.linkToOCS(`cloud/users/${userid}/subadmins`, 2), { groupid: gid })
+ .then((response) => context.commit('removeUserSubAdmin', { userid, gid }))
+ .catch((error) => {throw error;});
+ }).catch((error) => context.commit('API_FAILURE', { userid, error }));
+ },
+
+ /**
+ * Mark all user devices for remote wipe
+ *
+ * @param {Object} context
+ * @param {string} userid User id
+ * @returns {Promise}
+ */
+ wipeUserDevices(context, userid) {
+ return api.requireAdmin().then((response) => {
+ return api.post(OC.linkToOCS(`cloud/users/${userid}/wipe`, 2))
+ .catch((error) => {throw error;});
+ }).catch((error) => context.commit('API_FAILURE', { userid, error }));
+ },
+
+ /**
+ * Delete a user
+ *
+ * @param {Object} context
+ * @param {string} userid User id
+ * @returns {Promise}
+ */
+ deleteUser(context, userid) {
+ return api.requireAdmin().then((response) => {
+ return api.delete(OC.linkToOCS(`cloud/users/${userid}`, 2))
+ .then((response) => context.commit('deleteUser', userid))
+ .catch((error) => {throw error;});
+ }).catch((error) => context.commit('API_FAILURE', { userid, error }));
+ },
+
+ /**
+ * Add a user
+ *
+ * @param {Object} context
+ * @param {Object} options
+ * @param {string} options.userid User id
+ * @param {string} options.password User password
+ * @param {string} options.displayName User display name
+ * @param {string} options.email User email
+ * @param {string} options.groups User groups
+ * @param {string} options.subadmin User subadmin groups
+ * @param {string} options.quota User email
+ * @returns {Promise}
+ */
+ addUser({commit, dispatch}, { userid, password, displayName, email, groups, subadmin, quota, language }) {
+ return api.requireAdmin().then((response) => {
+ return api.post(OC.linkToOCS(`cloud/users`, 2), { userid, password, displayName, email, groups, subadmin, quota, language })
+ .then((response) => dispatch('addUserData', userid || response.data.ocs.data.id))
+ .catch((error) => {throw error;});
+ }).catch((error) => {
+ commit('API_FAILURE', { userid, error });
+ throw error;
+ });
+ },
+
+ /**
+ * Get user data and commit addition
+ *
+ * @param {Object} context
+ * @param {string} userid User id
+ * @returns {Promise}
+ */
+ addUserData(context, userid) {
+ return api.requireAdmin().then((response) => {
+ return api.get(OC.linkToOCS(`cloud/users/${userid}`, 2))
+ .then((response) => context.commit('addUserData', response))
+ .catch((error) => {throw error;});
+ }).catch((error) => context.commit('API_FAILURE', { userid, error }));
+ },
+
+ /** Enable or disable user
+ *
+ * @param {Object} context
+ * @param {Object} options
+ * @param {string} options.userid User id
+ * @param {boolean} options.enabled User enablement status
+ * @returns {Promise}
+ */
+ enableDisableUser(context, { userid, enabled = true }) {
+ let userStatus = enabled ? 'enable' : 'disable';
+ return api.requireAdmin().then((response) => {
+ return api.put(OC.linkToOCS(`cloud/users/${userid}/${userStatus}`, 2))
+ .then((response) => context.commit('enableDisableUser', { userid, enabled }))
+ .catch((error) => {throw error;});
+ }).catch((error) => context.commit('API_FAILURE', { userid, error }));
+ },
+
+ /**
+ * Edit user data
+ *
+ * @param {Object} context
+ * @param {Object} options
+ * @param {string} options.userid User id
+ * @param {string} options.key User field to edit
+ * @param {string} options.value Value of the change
+ * @returns {Promise}
+ */
+ setUserData(context, { userid, key, value }) {
+ let allowedEmpty = ['email', 'displayname'];
+ if (['email', 'language', 'quota', 'displayname', 'password'].indexOf(key) !== -1) {
+ // We allow empty email or displayname
+ if (typeof value === 'string' &&
+ (
+ (allowedEmpty.indexOf(key) === -1 && value.length > 0) ||
+ allowedEmpty.indexOf(key) !== -1
+ )
+ ) {
+ return api.requireAdmin().then((response) => {
+ return api.put(OC.linkToOCS(`cloud/users/${userid}`, 2), { key: key, value: value })
+ .then((response) => context.commit('setUserData', { userid, key, value }))
+ .catch((error) => {throw error;});
+ }).catch((error) => context.commit('API_FAILURE', { userid, error }));
+ }
+ }
+ return Promise.reject(new Error('Invalid request data'));
+ },
+
+ /**
+ * Send welcome mail
+ *
+ * @param {Object} context
+ * @param {string} userid User id
+ * @returns {Promise}
+ */
+ sendWelcomeMail(context, userid) {
+ return api.requireAdmin().then((response) => {
+ return api.post(OC.linkToOCS(`cloud/users/${userid}/welcome`, 2))
+ .then(response => true)
+ .catch((error) => {throw error;});
+ }).catch((error) => context.commit('API_FAILURE', { userid, error }));
+ }
+};
+
+export default { state, mutations, getters, actions };