Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

users.js 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. /*
  2. * @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
  3. *
  4. * @author John Molakvoæ <skjnldsv@protonmail.com>
  5. *
  6. * @license GNU AGPL version 3 or any later version
  7. *
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU Affero General Public License as
  10. * published by the Free Software Foundation, either version 3 of the
  11. * License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU Affero General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Affero General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. *
  21. */
  22. import api from './api';
  23. const orderGroups = function(groups, orderBy) {
  24. /* const SORT_USERCOUNT = 1;
  25. * const SORT_GROUPNAME = 2;
  26. * https://github.com/nextcloud/server/blob/208e38e84e1a07a49699aa90dc5b7272d24489f0/lib/private/Group/MetaData.php#L34
  27. */
  28. if (orderBy === 1) {
  29. return groups.sort((a, b) => a.usercount-a.disabled < b.usercount - b.disabled);
  30. } else {
  31. return groups.sort((a, b) => a.name.localeCompare(b.name));
  32. }
  33. };
  34. const defaults = {
  35. group: {
  36. id: '',
  37. name: '',
  38. usercount: 0,
  39. disabled: 0
  40. }
  41. }
  42. const state = {
  43. users: [],
  44. groups: [],
  45. orderBy: 1,
  46. minPasswordLength: 0,
  47. usersOffset: 0,
  48. usersLimit: 25,
  49. userCount: 0
  50. };
  51. const mutations = {
  52. appendUsers(state, usersObj) {
  53. // convert obj to array
  54. let users = state.users.concat(Object.keys(usersObj).map(userid => usersObj[userid]));
  55. state.usersOffset += state.usersLimit;
  56. state.users = users;
  57. },
  58. setPasswordPolicyMinLength(state, length) {
  59. state.minPasswordLength = length!=='' ? length : 0;
  60. },
  61. initGroups(state, {groups, orderBy, userCount}) {
  62. state.groups = groups.map(group => Object.assign({}, defaults.group, group));
  63. state.orderBy = orderBy;
  64. state.userCount = userCount;
  65. state.groups = orderGroups(state.groups, state.orderBy);
  66. },
  67. addGroup(state, {gid, displayName}) {
  68. try {
  69. // extend group to default values
  70. let group = Object.assign({}, defaults.group, {
  71. id: gid,
  72. name: displayName,
  73. });
  74. state.groups.push(group);
  75. state.groups = orderGroups(state.groups, state.orderBy);
  76. } catch (e) {
  77. console.log('Can\'t create group', e);
  78. }
  79. },
  80. removeGroup(state, gid) {
  81. let groupIndex = state.groups.findIndex(groupSearch => groupSearch.id == gid);
  82. if (groupIndex >= 0) {
  83. state.groups.splice(groupIndex, 1);
  84. }
  85. },
  86. addUserGroup(state, { userid, gid }) {
  87. let group = state.groups.find(groupSearch => groupSearch.id == gid);
  88. let user = state.users.find(user => user.id == userid);
  89. // increase count if user is enabled
  90. if (group && user.enabled) {
  91. group.usercount++;
  92. }
  93. let groups = user.groups;
  94. groups.push(gid);
  95. state.groups = orderGroups(state.groups, state.orderBy);
  96. },
  97. removeUserGroup(state, { userid, gid }) {
  98. let group = state.groups.find(groupSearch => groupSearch.id == gid);
  99. let user = state.users.find(user => user.id == userid);
  100. // lower count if user is enabled
  101. if (group && user.enabled) {
  102. group.usercount--;
  103. }
  104. let groups = user.groups;
  105. groups.splice(groups.indexOf(gid),1);
  106. state.groups = orderGroups(state.groups, state.orderBy);
  107. },
  108. addUserSubAdmin(state, { userid, gid }) {
  109. let groups = state.users.find(user => user.id == userid).subadmin;
  110. groups.push(gid);
  111. },
  112. removeUserSubAdmin(state, { userid, gid }) {
  113. let groups = state.users.find(user => user.id == userid).subadmin;
  114. groups.splice(groups.indexOf(gid),1);
  115. },
  116. deleteUser(state, userid) {
  117. let userIndex = state.users.findIndex(user => user.id == userid);
  118. state.users.splice(userIndex, 1);
  119. },
  120. addUserData(state, response) {
  121. state.users.push(response.data.ocs.data);
  122. },
  123. enableDisableUser(state, { userid, enabled }) {
  124. let user = state.users.find(user => user.id == userid);
  125. user.enabled = enabled;
  126. // increment or not
  127. state.groups.find(group => group.id == 'disabled').usercount += enabled ? -1 : 1;
  128. state.userCount += enabled ? 1 : -1;
  129. user.groups.forEach(group => {
  130. // Increment disabled count
  131. state.groups.find(groupSearch => groupSearch.id == group).disabled += enabled ? -1 : 1;
  132. });
  133. },
  134. setUserData(state, { userid, key, value }) {
  135. if (key === 'quota') {
  136. let humanValue = OC.Util.computerFileSize(value);
  137. state.users.find(user => user.id == userid)[key][key] = humanValue!==null ? humanValue : value;
  138. } else {
  139. state.users.find(user => user.id == userid)[key] = value;
  140. }
  141. },
  142. /**
  143. * Reset users list
  144. */
  145. resetUsers(state) {
  146. state.users = [];
  147. state.usersOffset = 0;
  148. }
  149. };
  150. const getters = {
  151. getUsers(state) {
  152. return state.users;
  153. },
  154. getGroups(state) {
  155. return state.groups;
  156. },
  157. getSubadminGroups(state) {
  158. // Can't be subadmin of admin or disabled
  159. return state.groups.filter(group => group.id !== 'admin' && group.id !== 'disabled');
  160. },
  161. getPasswordPolicyMinLength(state) {
  162. return state.minPasswordLength;
  163. },
  164. getUsersOffset(state) {
  165. return state.usersOffset;
  166. },
  167. getUsersLimit(state) {
  168. return state.usersLimit;
  169. },
  170. getUserCount(state) {
  171. return state.userCount;
  172. }
  173. };
  174. const actions = {
  175. /**
  176. * Get all users with full details
  177. *
  178. * @param {Object} context
  179. * @param {Object} options
  180. * @param {int} options.offset List offset to request
  181. * @param {int} options.limit List number to return from offset
  182. * @param {string} options.search Search amongst users
  183. * @param {string} options.group Get users from group
  184. * @returns {Promise}
  185. */
  186. getUsers(context, { offset, limit, search, group }) {
  187. search = typeof search === 'string' ? search : '';
  188. group = typeof group === 'string' ? group : '';
  189. if (group !== '') {
  190. return api.get(OC.linkToOCS(`cloud/groups/${group}/users/details?offset=${offset}&limit=${limit}&search=${search}`, 2))
  191. .then((response) => {
  192. if (Object.keys(response.data.ocs.data.users).length > 0) {
  193. context.commit('appendUsers', response.data.ocs.data.users);
  194. return true;
  195. }
  196. return false;
  197. })
  198. .catch((error) => context.commit('API_FAILURE', error));
  199. }
  200. return api.get(OC.linkToOCS(`cloud/users/details?offset=${offset}&limit=${limit}&search=${search}`, 2))
  201. .then((response) => {
  202. if (Object.keys(response.data.ocs.data.users).length > 0) {
  203. context.commit('appendUsers', response.data.ocs.data.users);
  204. return true;
  205. }
  206. return false;
  207. })
  208. .catch((error) => context.commit('API_FAILURE', error));
  209. },
  210. getGroups(context, { offset, limit, search }) {
  211. search = typeof search === 'string' ? search : '';
  212. return api.get(OC.linkToOCS(`cloud/groups?offset=${offset}&limit=${limit}&search=${search}`, 2))
  213. .then((response) => {
  214. if (Object.keys(response.data.ocs.data.groups).length > 0) {
  215. response.data.ocs.data.groups.forEach(function(group) {
  216. context.commit('addGroup', {gid: group, displayName: group});
  217. });
  218. return true;
  219. }
  220. return false;
  221. })
  222. .catch((error) => context.commit('API_FAILURE', error));
  223. },
  224. /**
  225. * Get all users with full details
  226. *
  227. * @param {Object} context
  228. * @param {Object} options
  229. * @param {int} options.offset List offset to request
  230. * @param {int} options.limit List number to return from offset
  231. * @returns {Promise}
  232. */
  233. getUsersFromList(context, { offset, limit, search }) {
  234. search = typeof search === 'string' ? search : '';
  235. return api.get(OC.linkToOCS(`cloud/users/details?offset=${offset}&limit=${limit}&search=${search}`, 2))
  236. .then((response) => {
  237. if (Object.keys(response.data.ocs.data.users).length > 0) {
  238. context.commit('appendUsers', response.data.ocs.data.users);
  239. return true;
  240. }
  241. return false;
  242. })
  243. .catch((error) => context.commit('API_FAILURE', error));
  244. },
  245. /**
  246. * Get all users with full details from a groupid
  247. *
  248. * @param {Object} context
  249. * @param {Object} options
  250. * @param {int} options.offset List offset to request
  251. * @param {int} options.limit List number to return from offset
  252. * @returns {Promise}
  253. */
  254. getUsersFromGroup(context, { groupid, offset, limit }) {
  255. return api.get(OC.linkToOCS(`cloud/users/${groupid}/details?offset=${offset}&limit=${limit}`, 2))
  256. .then((response) => context.commit('getUsersFromList', response.data.ocs.data.users))
  257. .catch((error) => context.commit('API_FAILURE', error));
  258. },
  259. getPasswordPolicyMinLength(context) {
  260. if(oc_capabilities.password_policy && oc_capabilities.password_policy.minLength) {
  261. context.commit('setPasswordPolicyMinLength', oc_capabilities.password_policy.minLength);
  262. return oc_capabilities.password_policy.minLength;
  263. }
  264. return false;
  265. },
  266. /**
  267. * Add group
  268. *
  269. * @param {Object} context
  270. * @param {string} gid Group id
  271. * @returns {Promise}
  272. */
  273. addGroup(context, gid) {
  274. return api.requireAdmin().then((response) => {
  275. return api.post(OC.linkToOCS(`cloud/groups`, 2), {groupid: gid})
  276. .then((response) => context.commit('addGroup', {gid: gid, displayName: gid}))
  277. .catch((error) => {throw error;});
  278. }).catch((error) => {
  279. context.commit('API_FAILURE', { gid, error });
  280. // let's throw one more time to prevent the view
  281. // from adding the user to a group that doesn't exists
  282. throw error;
  283. });
  284. },
  285. /**
  286. * Remove group
  287. *
  288. * @param {Object} context
  289. * @param {string} gid Group id
  290. * @returns {Promise}
  291. */
  292. removeGroup(context, gid) {
  293. return api.requireAdmin().then((response) => {
  294. return api.delete(OC.linkToOCS(`cloud/groups/${gid}`, 2))
  295. .then((response) => context.commit('removeGroup', gid))
  296. .catch((error) => {throw error;});
  297. }).catch((error) => context.commit('API_FAILURE', { gid, error }));
  298. },
  299. /**
  300. * Add user to group
  301. *
  302. * @param {Object} context
  303. * @param {Object} options
  304. * @param {string} options.userid User id
  305. * @param {string} options.gid Group id
  306. * @returns {Promise}
  307. */
  308. addUserGroup(context, { userid, gid }) {
  309. return api.requireAdmin().then((response) => {
  310. return api.post(OC.linkToOCS(`cloud/users/${userid}/groups`, 2), { groupid: gid })
  311. .then((response) => context.commit('addUserGroup', { userid, gid }))
  312. .catch((error) => {throw error;});
  313. }).catch((error) => context.commit('API_FAILURE', { userid, error }));
  314. },
  315. /**
  316. * Remove user from group
  317. *
  318. * @param {Object} context
  319. * @param {Object} options
  320. * @param {string} options.userid User id
  321. * @param {string} options.gid Group id
  322. * @returns {Promise}
  323. */
  324. removeUserGroup(context, { userid, gid }) {
  325. return api.requireAdmin().then((response) => {
  326. return api.delete(OC.linkToOCS(`cloud/users/${userid}/groups`, 2), { groupid: gid })
  327. .then((response) => context.commit('removeUserGroup', { userid, gid }))
  328. .catch((error) => {throw error;});
  329. }).catch((error) => {
  330. context.commit('API_FAILURE', { userid, error });
  331. // let's throw one more time to prevent
  332. // the view from removing the user row on failure
  333. throw error;
  334. });
  335. },
  336. /**
  337. * Add user to group admin
  338. *
  339. * @param {Object} context
  340. * @param {Object} options
  341. * @param {string} options.userid User id
  342. * @param {string} options.gid Group id
  343. * @returns {Promise}
  344. */
  345. addUserSubAdmin(context, { userid, gid }) {
  346. return api.requireAdmin().then((response) => {
  347. return api.post(OC.linkToOCS(`cloud/users/${userid}/subadmins`, 2), { groupid: gid })
  348. .then((response) => context.commit('addUserSubAdmin', { userid, gid }))
  349. .catch((error) => {throw error;});
  350. }).catch((error) => context.commit('API_FAILURE', { userid, error }));
  351. },
  352. /**
  353. * Remove user from group admin
  354. *
  355. * @param {Object} context
  356. * @param {Object} options
  357. * @param {string} options.userid User id
  358. * @param {string} options.gid Group id
  359. * @returns {Promise}
  360. */
  361. removeUserSubAdmin(context, { userid, gid }) {
  362. return api.requireAdmin().then((response) => {
  363. return api.delete(OC.linkToOCS(`cloud/users/${userid}/subadmins`, 2), { groupid: gid })
  364. .then((response) => context.commit('removeUserSubAdmin', { userid, gid }))
  365. .catch((error) => {throw error;});
  366. }).catch((error) => context.commit('API_FAILURE', { userid, error }));
  367. },
  368. /**
  369. * Delete a user
  370. *
  371. * @param {Object} context
  372. * @param {string} userid User id
  373. * @returns {Promise}
  374. */
  375. deleteUser(context, { userid }) {
  376. return api.requireAdmin().then((response) => {
  377. return api.delete(OC.linkToOCS(`cloud/users/${userid}`, 2))
  378. .then((response) => context.commit('deleteUser', userid))
  379. .catch((error) => {throw error;});
  380. }).catch((error) => context.commit('API_FAILURE', { userid, error }));
  381. },
  382. /**
  383. * Add a user
  384. *
  385. * @param {Object} context
  386. * @param {Object} options
  387. * @param {string} options.userid User id
  388. * @param {string} options.password User password
  389. * @param {string} options.email User email
  390. * @param {string} options.groups User groups
  391. * @param {string} options.subadmin User subadmin groups
  392. * @param {string} options.quota User email
  393. * @returns {Promise}
  394. */
  395. addUser({commit, dispatch}, { userid, password, email, groups, subadmin, quota, language }) {
  396. return api.requireAdmin().then((response) => {
  397. return api.post(OC.linkToOCS(`cloud/users`, 2), { userid, password, email, groups, subadmin, quota, language })
  398. .then((response) => dispatch('addUserData', userid))
  399. .catch((error) => {throw error;});
  400. }).catch((error) => commit('API_FAILURE', { userid, error }));
  401. },
  402. /**
  403. * Get user data and commit addition
  404. *
  405. * @param {Object} context
  406. * @param {string} userid User id
  407. * @returns {Promise}
  408. */
  409. addUserData(context, userid) {
  410. return api.requireAdmin().then((response) => {
  411. return api.get(OC.linkToOCS(`cloud/users/${userid}`, 2))
  412. .then((response) => context.commit('addUserData', response))
  413. .catch((error) => {throw error;});
  414. }).catch((error) => context.commit('API_FAILURE', { userid, error }));
  415. },
  416. /** Enable or disable user
  417. *
  418. * @param {Object} context
  419. * @param {Object} options
  420. * @param {string} options.userid User id
  421. * @param {boolean} options.enabled User enablement status
  422. * @returns {Promise}
  423. */
  424. enableDisableUser(context, { userid, enabled = true }) {
  425. let userStatus = enabled ? 'enable' : 'disable';
  426. return api.requireAdmin().then((response) => {
  427. return api.put(OC.linkToOCS(`cloud/users/${userid}/${userStatus}`, 2))
  428. .then((response) => context.commit('enableDisableUser', { userid, enabled }))
  429. .catch((error) => {throw error;});
  430. }).catch((error) => context.commit('API_FAILURE', { userid, error }));
  431. },
  432. /**
  433. * Edit user data
  434. *
  435. * @param {Object} context
  436. * @param {Object} options
  437. * @param {string} options.userid User id
  438. * @param {string} options.key User field to edit
  439. * @param {string} options.value Value of the change
  440. * @returns {Promise}
  441. */
  442. setUserData(context, { userid, key, value }) {
  443. let allowedEmpty = ['email', 'displayname'];
  444. if (['email', 'language', 'quota', 'displayname', 'password'].indexOf(key) !== -1) {
  445. // We allow empty email or displayname
  446. if (typeof value === 'string' &&
  447. (
  448. (allowedEmpty.indexOf(key) === -1 && value.length > 0) ||
  449. allowedEmpty.indexOf(key) !== -1
  450. )
  451. ) {
  452. return api.requireAdmin().then((response) => {
  453. return api.put(OC.linkToOCS(`cloud/users/${userid}`, 2), { key: key, value: value })
  454. .then((response) => context.commit('setUserData', { userid, key, value }))
  455. .catch((error) => {throw error;});
  456. }).catch((error) => context.commit('API_FAILURE', { userid, error }));
  457. }
  458. }
  459. return Promise.reject(new Error('Invalid request data'));
  460. }
  461. };
  462. export default { state, mutations, getters, actions };