mirror of
				https://github.com/NodeBB/NodeBB.git
				synced 2025-10-31 02:55:58 +01:00 
			
		
		
		
	feat(writeapi): user settings API
This commit is contained in:
		
							
								
								
									
										143
									
								
								public/openapi/components/schemas/SettingsObj.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								public/openapi/components/schemas/SettingsObj.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,143 @@ | |||||||
|  | Settings: | ||||||
|  |   type: object | ||||||
|  |   properties: | ||||||
|  |     showemail: | ||||||
|  |       type: boolean | ||||||
|  |       description: Show user email in profile page | ||||||
|  |     usePagination: | ||||||
|  |       type: boolean | ||||||
|  |       description: Toggles between pagination (when enabled), or infinite scrolling (when disabled) | ||||||
|  |     topicsPerPage: | ||||||
|  |       type: number | ||||||
|  |       description: Number of topics displayed on a category page | ||||||
|  |     postsPerPage: | ||||||
|  |       type: number | ||||||
|  |       description: Number of posts displayed on a topic page | ||||||
|  |     topicPostSort: | ||||||
|  |       type: string | ||||||
|  |       description: Default sorting strategy of the posts in of a topic | ||||||
|  |     openOutgoingLinksInNewTab: | ||||||
|  |       type: boolean | ||||||
|  |       description: Whether to automatically open all external links in a new tab | ||||||
|  |     dailyDigestFreq: | ||||||
|  |       type: string | ||||||
|  |       description: How often to receive the scheduled digest from this forum | ||||||
|  |     showfullname: | ||||||
|  |       type: boolean | ||||||
|  |       description: Show user full name in profile page | ||||||
|  |     followTopicsOnCreate: | ||||||
|  |       type: boolean | ||||||
|  |       description: Automatically be notified of new posts in a topic, when you create a topic | ||||||
|  |     followTopicsOnReply: | ||||||
|  |       type: boolean | ||||||
|  |       description: | ||||||
|  |     restrictChat: | ||||||
|  |       type: boolean | ||||||
|  |       description: | ||||||
|  |     topicSearchEnabled: | ||||||
|  |       type: boolean | ||||||
|  |       description: | ||||||
|  |     categoryTopicSort: | ||||||
|  |       type: string | ||||||
|  |       description: | ||||||
|  |     userLang: | ||||||
|  |       type: string | ||||||
|  |       description: | ||||||
|  |     bootswatchSkin: | ||||||
|  |       type: string | ||||||
|  |       description: | ||||||
|  |     homePageRoute: | ||||||
|  |       type: string | ||||||
|  |       description: | ||||||
|  |     scrollToMyPost: | ||||||
|  |       type: boolean | ||||||
|  |       description: | ||||||
|  |     notificationType_new-chat: | ||||||
|  |       type: string | ||||||
|  |       description: | ||||||
|  |     notificationType_new-reply: | ||||||
|  |       type: string | ||||||
|  |       description: | ||||||
|  |     notificationType_post-edit: | ||||||
|  |       type: string | ||||||
|  |       description: | ||||||
|  |     sendChatNotifications: | ||||||
|  |       nullable: true | ||||||
|  |     sendPostNotifications: | ||||||
|  |       nullable: true | ||||||
|  |     notificationType_upvote: | ||||||
|  |       type: string | ||||||
|  |       description: | ||||||
|  |     notificationType_new-topic: | ||||||
|  |       type: string | ||||||
|  |       description: | ||||||
|  |     notificationType_follow: | ||||||
|  |       type: string | ||||||
|  |       description: | ||||||
|  |     notificationType_group-invite: | ||||||
|  |       type: string | ||||||
|  |       description: | ||||||
|  |     upvoteNotifFreq: | ||||||
|  |       type: string | ||||||
|  |       description: | ||||||
|  |     notificationType_mention: | ||||||
|  |       type: string | ||||||
|  |       description: | ||||||
|  |     acpLang: | ||||||
|  |       type: string | ||||||
|  |       description: | ||||||
|  |     notificationType_new-register: | ||||||
|  |       type: string | ||||||
|  |       description: | ||||||
|  |     notificationType_post-queue: | ||||||
|  |       type: string | ||||||
|  |       description: | ||||||
|  |     notificationType_new-post-flag: | ||||||
|  |       type: string | ||||||
|  |       description: | ||||||
|  |     notificationType_new-user-flag: | ||||||
|  |       type: string | ||||||
|  |       description: | ||||||
|  |     categoryWatchState: | ||||||
|  |       type: string | ||||||
|  |       description: | ||||||
|  |     notificationType_group-request-membership: | ||||||
|  |       type: string | ||||||
|  |       description: | ||||||
|  |     uid: | ||||||
|  |       type: number | ||||||
|  |       description: | ||||||
|  |       description: A user identifier | ||||||
|  |   required: | ||||||
|  |     - showemail | ||||||
|  |     - usePagination | ||||||
|  |     - topicsPerPage | ||||||
|  |     - postsPerPage | ||||||
|  |     - topicPostSort | ||||||
|  |     - openOutgoingLinksInNewTab | ||||||
|  |     - dailyDigestFreq | ||||||
|  |     - showfullname | ||||||
|  |     - followTopicsOnCreate | ||||||
|  |     - followTopicsOnReply | ||||||
|  |     - restrictChat | ||||||
|  |     - topicSearchEnabled | ||||||
|  |     - categoryTopicSort | ||||||
|  |     - userLang | ||||||
|  |     - bootswatchSkin | ||||||
|  |     - homePageRoute | ||||||
|  |     - scrollToMyPost | ||||||
|  |     - notificationType_new-chat | ||||||
|  |     - notificationType_new-reply | ||||||
|  |     - notificationType_upvote | ||||||
|  |     - notificationType_new-topic | ||||||
|  |     - notificationType_follow | ||||||
|  |     - notificationType_group-invite | ||||||
|  |     - upvoteNotifFreq | ||||||
|  |     - acpLang | ||||||
|  |     - notificationType_new-register | ||||||
|  |     - notificationType_post-queue | ||||||
|  |     - notificationType_new-post-flag | ||||||
|  |     - notificationType_new-user-flag | ||||||
|  |     - categoryWatchState | ||||||
|  |     - notificationType_group-request-membership | ||||||
|  |     - uid | ||||||
| @@ -20,114 +20,7 @@ get: | |||||||
|               - type: object |               - type: object | ||||||
|                 properties: |                 properties: | ||||||
|                   settings: |                   settings: | ||||||
|                     type: object |                     $ref: ../../../components/schemas/SettingsObj.yaml#/Settings | ||||||
|                     properties: |  | ||||||
|                       showemail: |  | ||||||
|                         type: boolean |  | ||||||
|                       usePagination: |  | ||||||
|                         type: boolean |  | ||||||
|                       topicsPerPage: |  | ||||||
|                         type: number |  | ||||||
|                       postsPerPage: |  | ||||||
|                         type: number |  | ||||||
|                       topicPostSort: |  | ||||||
|                         type: string |  | ||||||
|                       openOutgoingLinksInNewTab: |  | ||||||
|                         type: boolean |  | ||||||
|                       dailyDigestFreq: |  | ||||||
|                         type: string |  | ||||||
|                       showfullname: |  | ||||||
|                         type: boolean |  | ||||||
|                       followTopicsOnCreate: |  | ||||||
|                         type: boolean |  | ||||||
|                       followTopicsOnReply: |  | ||||||
|                         type: boolean |  | ||||||
|                       restrictChat: |  | ||||||
|                         type: boolean |  | ||||||
|                       topicSearchEnabled: |  | ||||||
|                         type: boolean |  | ||||||
|                       categoryTopicSort: |  | ||||||
|                         type: string |  | ||||||
|                       userLang: |  | ||||||
|                         type: string |  | ||||||
|                       bootswatchSkin: |  | ||||||
|                         type: string |  | ||||||
|                       homePageRoute: |  | ||||||
|                         type: string |  | ||||||
|                       scrollToMyPost: |  | ||||||
|                         type: boolean |  | ||||||
|                       notificationType_new-chat: |  | ||||||
|                         type: string |  | ||||||
|                       notificationType_new-reply: |  | ||||||
|                         type: string |  | ||||||
|                       notificationType_post-edit: |  | ||||||
|                         type: string |  | ||||||
|                       sendChatNotifications: |  | ||||||
|                         nullable: true |  | ||||||
|                       sendPostNotifications: |  | ||||||
|                         nullable: true |  | ||||||
|                       notificationType_upvote: |  | ||||||
|                         type: string |  | ||||||
|                       notificationType_new-topic: |  | ||||||
|                         type: string |  | ||||||
|                       notificationType_follow: |  | ||||||
|                         type: string |  | ||||||
|                       notificationType_group-invite: |  | ||||||
|                         type: string |  | ||||||
|                       upvoteNotifFreq: |  | ||||||
|                         type: string |  | ||||||
|                       notificationType_mention: |  | ||||||
|                         type: string |  | ||||||
|                       acpLang: |  | ||||||
|                         type: string |  | ||||||
|                       notificationType_new-register: |  | ||||||
|                         type: string |  | ||||||
|                       notificationType_post-queue: |  | ||||||
|                         type: string |  | ||||||
|                       notificationType_new-post-flag: |  | ||||||
|                         type: string |  | ||||||
|                       notificationType_new-user-flag: |  | ||||||
|                         type: string |  | ||||||
|                       categoryWatchState: |  | ||||||
|                         type: string |  | ||||||
|                       notificationType_group-request-membership: |  | ||||||
|                         type: string |  | ||||||
|                       uid: |  | ||||||
|                         type: number |  | ||||||
|                         description: A user identifier |  | ||||||
|                     required: |  | ||||||
|                       - showemail |  | ||||||
|                       - usePagination |  | ||||||
|                       - topicsPerPage |  | ||||||
|                       - postsPerPage |  | ||||||
|                       - topicPostSort |  | ||||||
|                       - openOutgoingLinksInNewTab |  | ||||||
|                       - dailyDigestFreq |  | ||||||
|                       - showfullname |  | ||||||
|                       - followTopicsOnCreate |  | ||||||
|                       - followTopicsOnReply |  | ||||||
|                       - restrictChat |  | ||||||
|                       - topicSearchEnabled |  | ||||||
|                       - categoryTopicSort |  | ||||||
|                       - userLang |  | ||||||
|                       - bootswatchSkin |  | ||||||
|                       - homePageRoute |  | ||||||
|                       - scrollToMyPost |  | ||||||
|                       - notificationType_new-chat |  | ||||||
|                       - notificationType_new-reply |  | ||||||
|                       - notificationType_upvote |  | ||||||
|                       - notificationType_new-topic |  | ||||||
|                       - notificationType_follow |  | ||||||
|                       - notificationType_group-invite |  | ||||||
|                       - upvoteNotifFreq |  | ||||||
|                       - acpLang |  | ||||||
|                       - notificationType_new-register |  | ||||||
|                       - notificationType_post-queue |  | ||||||
|                       - notificationType_new-post-flag |  | ||||||
|                       - notificationType_new-user-flag |  | ||||||
|                       - categoryWatchState |  | ||||||
|                       - notificationType_group-request-membership |  | ||||||
|                       - uid |  | ||||||
|                   languages: |                   languages: | ||||||
|                     type: array |                     type: array | ||||||
|                     items: |                     items: | ||||||
|   | |||||||
| @@ -30,6 +30,10 @@ tags: | |||||||
| paths: | paths: | ||||||
|   /users/{uid}: |   /users/{uid}: | ||||||
|     $ref: 'write/users/uid.yaml' |     $ref: 'write/users/uid.yaml' | ||||||
|  |   /users/{uid}/settings: | ||||||
|  |     $ref: 'write/users/uid/settings.yaml' | ||||||
|  |   /users/{uid}/settings/{setting}: | ||||||
|  |     $ref: 'write/users/uid/settings/setting.yaml' | ||||||
|   /users/{uid}/password: |   /users/{uid}/password: | ||||||
|     $ref: 'write/users/uid/password.yaml' |     $ref: 'write/users/uid/password.yaml' | ||||||
|   /users/{uid}/follow: |   /users/{uid}/follow: | ||||||
|   | |||||||
							
								
								
									
										35
									
								
								public/openapi/write/users/uid/settings.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								public/openapi/write/users/uid/settings.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | |||||||
|  | put: | ||||||
|  |   tags: | ||||||
|  |     - users | ||||||
|  |   summary: update user settings | ||||||
|  |   parameters: | ||||||
|  |     - in: path | ||||||
|  |       name: uid | ||||||
|  |       schema: | ||||||
|  |         type: integer | ||||||
|  |       required: true | ||||||
|  |       description: uid of the user | ||||||
|  |   requestBody: | ||||||
|  |     content: | ||||||
|  |       application/json: | ||||||
|  |         schema: | ||||||
|  |           type: object | ||||||
|  |           properties: | ||||||
|  |             settings: | ||||||
|  |               type: object | ||||||
|  |               description: An object containing key-value pairs of user settings to update | ||||||
|  |               example: | ||||||
|  |                 showemail: '0' | ||||||
|  |                 showfullname: '1' | ||||||
|  |   responses: | ||||||
|  |     '200': | ||||||
|  |       description: successfully updated user settings | ||||||
|  |       content: | ||||||
|  |         application/json: | ||||||
|  |           schema: | ||||||
|  |             type: object | ||||||
|  |             properties: | ||||||
|  |               status: | ||||||
|  |                 $ref: ../../../components/schemas/Status.yaml#/Status | ||||||
|  |               response: | ||||||
|  |                 $ref: ../../../components/schemas/SettingsObj.yaml#/Settings | ||||||
							
								
								
									
										40
									
								
								public/openapi/write/users/uid/settings/setting.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								public/openapi/write/users/uid/settings/setting.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | |||||||
|  | put: | ||||||
|  |   tags: | ||||||
|  |     - users | ||||||
|  |   summary: update one user setting | ||||||
|  |   parameters: | ||||||
|  |     - in: path | ||||||
|  |       name: uid | ||||||
|  |       schema: | ||||||
|  |         type: integer | ||||||
|  |       required: true | ||||||
|  |       description: uid of the user | ||||||
|  |       example: '1' | ||||||
|  |     - in: path | ||||||
|  |       name: setting | ||||||
|  |       schema: | ||||||
|  |         type: string | ||||||
|  |       required: true | ||||||
|  |       description: name of the setting you wish to update | ||||||
|  |       example: 'showemail' | ||||||
|  |   requestBody: | ||||||
|  |     content: | ||||||
|  |       application/json: | ||||||
|  |         schema: | ||||||
|  |           type: object | ||||||
|  |           properties: | ||||||
|  |             value: | ||||||
|  |               type: string | ||||||
|  |               example: '1' | ||||||
|  |   responses: | ||||||
|  |     '200': | ||||||
|  |       description: successfully updated user settings | ||||||
|  |       content: | ||||||
|  |         application/json: | ||||||
|  |           schema: | ||||||
|  |             type: object | ||||||
|  |             properties: | ||||||
|  |               status: | ||||||
|  |                 $ref: ../../../../components/schemas/Status.yaml#/Status | ||||||
|  |               response: | ||||||
|  |                 type: object | ||||||
| @@ -1,7 +1,7 @@ | |||||||
| 'use strict'; | 'use strict'; | ||||||
|  |  | ||||||
|  |  | ||||||
| define('forum/account/settings', ['forum/account/header', 'components', 'translator'], function (header, components, translator) { | define('forum/account/settings', ['forum/account/header', 'components', 'translator', 'api'], function (header, components, translator, api) { | ||||||
| 	var	AccountSettings = {}; | 	var	AccountSettings = {}; | ||||||
|  |  | ||||||
| 	// If page skin is changed but not saved, switch the skin back | 	// If page skin is changed but not saved, switch the skin back | ||||||
| @@ -67,11 +67,7 @@ define('forum/account/settings', ['forum/account/header', 'components', 'transla | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	function saveSettings(settings) { | 	function saveSettings(settings) { | ||||||
| 		socket.emit('user.saveSettings', { uid: ajaxify.data.theirid, settings: settings }, function (err, newSettings) { | 		api.put(`/users/${ajaxify.data.uid}/settings`, { settings }).then((newSettings) => { | ||||||
| 			if (err) { |  | ||||||
| 				return app.alertError(err.message); |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			app.alertSuccess('[[success:settings-saved]]'); | 			app.alertSuccess('[[success:settings-saved]]'); | ||||||
| 			var languageChanged = false; | 			var languageChanged = false; | ||||||
| 			for (var key in newSettings) { | 			for (var key in newSettings) { | ||||||
|   | |||||||
| @@ -24,7 +24,7 @@ define('forum/category', [ | |||||||
|  |  | ||||||
| 		topicList.init('category', loadTopicsAfter); | 		topicList.init('category', loadTopicsAfter); | ||||||
|  |  | ||||||
| 		sort.handleSort('categoryTopicSort', 'user.setCategorySort', 'category/' + ajaxify.data.slug); | 		sort.handleSort('categoryTopicSort', 'setCategorySort', 'category/' + ajaxify.data.slug); | ||||||
|  |  | ||||||
| 		if (!config.usePagination) { | 		if (!config.usePagination) { | ||||||
| 			navigator.init('[component="category/topic"]', ajaxify.data.topic_count, Category.toTop, Category.toBottom, Category.navigatorCallback); | 			navigator.init('[component="category/topic"]', ajaxify.data.topic_count, Category.toTop, Category.toBottom, Category.navigatorCallback); | ||||||
|   | |||||||
| @@ -49,7 +49,7 @@ define('forum/topic', [ | |||||||
| 		threadTools.init(tid, $('.topic')); | 		threadTools.init(tid, $('.topic')); | ||||||
| 		events.init(); | 		events.init(); | ||||||
|  |  | ||||||
| 		sort.handleSort('topicPostSort', 'user.setTopicSort', 'topic/' + ajaxify.data.slug); | 		sort.handleSort('topicPostSort', 'setTopicSort', 'topic/' + ajaxify.data.slug); | ||||||
|  |  | ||||||
| 		if (!config.usePagination) { | 		if (!config.usePagination) { | ||||||
| 			infinitescroll.init($('[component="topic"]'), posts.loadMorePosts); | 			infinitescroll.init($('[component="topic"]'), posts.loadMorePosts); | ||||||
|   | |||||||
| @@ -1,10 +1,10 @@ | |||||||
| 'use strict'; | 'use strict'; | ||||||
|  |  | ||||||
|  |  | ||||||
| define('sort', ['components'], function (components) { | define('sort', ['components', 'api'], function (components, api) { | ||||||
| 	var module = {}; | 	var module = {}; | ||||||
|  |  | ||||||
| 	module.handleSort = function (field, method, gotoOnSave) { | 	module.handleSort = function (field, key, gotoOnSave) { | ||||||
| 		var threadSort = components.get('thread/sort'); | 		var threadSort = components.get('thread/sort'); | ||||||
| 		threadSort.find('i').removeClass('fa-check'); | 		threadSort.find('i').removeClass('fa-check'); | ||||||
| 		var currentSetting = threadSort.find('a[data-sort="' + config[field] + '"]'); | 		var currentSetting = threadSort.find('a[data-sort="' + config[field] + '"]'); | ||||||
| @@ -20,10 +20,9 @@ define('sort', ['components'], function (components) { | |||||||
| 				} | 				} | ||||||
| 				var newSetting = $(this).attr('data-sort'); | 				var newSetting = $(this).attr('data-sort'); | ||||||
| 				if (app.user.uid) { | 				if (app.user.uid) { | ||||||
| 					socket.emit(method, newSetting, function (err) { | 					api.put(`/users/${app.user.uid}/settings/${key}`, { | ||||||
| 						if (err) { | 						value: newSetting, | ||||||
| 							return app.alertError(err.message); | 					}).then(() => { | ||||||
| 						} |  | ||||||
| 						refresh(newSetting, utils.params()); | 						refresh(newSetting, utils.params()); | ||||||
| 					}); | 					}); | ||||||
| 				} else { | 				} else { | ||||||
|   | |||||||
| @@ -89,6 +89,23 @@ usersAPI.deleteMany = async function (caller, data) { | |||||||
| 	} | 	} | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | usersAPI.updateSettings = async function (caller, data) { | ||||||
|  | 	if (!caller.uid || !data || !data.settings) { | ||||||
|  | 		throw new Error('[[error:invalid-data]]'); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	const canEdit = await privileges.users.canEdit(caller.uid, data.uid); | ||||||
|  | 	if (!canEdit) { | ||||||
|  | 		throw new Error('[[error:no-privileges]]'); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return await user.saveSettings(data.uid, data.settings); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | usersAPI.updateSetting = async function (caller, data) { | ||||||
|  | 	await user.setSetting(data.uid, data.setting, data.value); | ||||||
|  | }; | ||||||
|  |  | ||||||
| usersAPI.changePassword = async function (caller, data) { | usersAPI.changePassword = async function (caller, data) { | ||||||
| 	await user.changePassword(caller.uid, Object.assign(data, { ip: caller.ip })); | 	await user.changePassword(caller.uid, Object.assign(data, { ip: caller.ip })); | ||||||
| 	await events.log({ | 	await events.log({ | ||||||
|   | |||||||
| @@ -28,6 +28,16 @@ Users.deleteMany = async (req, res) => { | |||||||
| 	helpers.formatApiResponse(200, res); | 	helpers.formatApiResponse(200, res); | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | Users.updateSettings = async (req, res) => { | ||||||
|  | 	const settings = await api.users.updateSettings(req, { ...req.body, uid: req.params.uid }); | ||||||
|  | 	helpers.formatApiResponse(200, res, settings); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | Users.updateSetting = async (req, res) => { | ||||||
|  | 	await api.users.updateSetting(req, { ...req.params, value: req.body.value }); | ||||||
|  | 	helpers.formatApiResponse(200, res); | ||||||
|  | }; | ||||||
|  |  | ||||||
| Users.changePassword = async (req, res) => { | Users.changePassword = async (req, res) => { | ||||||
| 	await api.users.changePassword(req, { ...req.body, uid: req.params.uid }); | 	await api.users.changePassword(req, { ...req.body, uid: req.params.uid }); | ||||||
| 	helpers.formatApiResponse(200, res); | 	helpers.formatApiResponse(200, res); | ||||||
|   | |||||||
| @@ -21,6 +21,9 @@ function authenticatedRoutes() { | |||||||
| 	setupApiRoute(router, 'put', '/:uid', [...middlewares, middleware.assert.user], controllers.write.users.update); | 	setupApiRoute(router, 'put', '/:uid', [...middlewares, middleware.assert.user], controllers.write.users.update); | ||||||
| 	setupApiRoute(router, 'delete', '/:uid', [...middlewares, middleware.assert.user, middleware.exposePrivileges], controllers.write.users.delete); | 	setupApiRoute(router, 'delete', '/:uid', [...middlewares, middleware.assert.user, middleware.exposePrivileges], controllers.write.users.delete); | ||||||
|  |  | ||||||
|  | 	setupApiRoute(router, 'put', '/:uid/settings', [...middlewares, middleware.checkRequired.bind(null, ['settings'])], controllers.write.users.updateSettings); | ||||||
|  | 	setupApiRoute(router, 'put', '/:uid/settings/:setting', [...middlewares, middleware.checkRequired.bind(null, ['value'])], controllers.write.users.updateSetting); | ||||||
|  |  | ||||||
| 	setupApiRoute(router, 'put', '/:uid/password', [...middlewares, middleware.checkRequired.bind(null, ['newPassword']), middleware.assert.user], controllers.write.users.changePassword); | 	setupApiRoute(router, 'put', '/:uid/password', [...middlewares, middleware.checkRequired.bind(null, ['newPassword']), middleware.assert.user], controllers.write.users.changePassword); | ||||||
|  |  | ||||||
| 	setupApiRoute(router, 'put', '/:uid/follow', [...middlewares, middleware.assert.user], controllers.write.users.follow); | 	setupApiRoute(router, 'put', '/:uid/follow', [...middlewares, middleware.assert.user], controllers.write.users.follow); | ||||||
|   | |||||||
| @@ -168,22 +168,27 @@ SocketUser.unfollow = async function (socket, data) { | |||||||
| }; | }; | ||||||
|  |  | ||||||
| SocketUser.saveSettings = async function (socket, data) { | SocketUser.saveSettings = async function (socket, data) { | ||||||
| 	if (!socket.uid || !data || !data.settings) { | 	sockets.warnDeprecated(socket, 'PUT /api/v3/users/:uid/settings'); | ||||||
| 		throw new Error('[[error:invalid-data]]'); | 	const settings = await api.users.updateSettings(socket, data); | ||||||
| 	} | 	return settings; | ||||||
| 	const canEdit = await privileges.users.canEdit(socket.uid, data.uid); |  | ||||||
| 	if (!canEdit) { |  | ||||||
| 		throw new Error('[[error:no-privileges]]'); |  | ||||||
| 	} |  | ||||||
| 	return await user.saveSettings(data.uid, data.settings); |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| SocketUser.setTopicSort = async function (socket, sort) { | SocketUser.setTopicSort = async function (socket, sort) { | ||||||
| 	await user.setSetting(socket.uid, 'topicPostSort', sort); | 	sockets.warnDeprecated(socket, 'PUT /api/v3/users/:uid/setting/topicPostSort'); | ||||||
|  | 	await api.users.updateSetting(socket, { | ||||||
|  | 		uid: socket.uid, | ||||||
|  | 		setting: 'topicPostSort', | ||||||
|  | 		value: sort, | ||||||
|  | 	}); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| SocketUser.setCategorySort = async function (socket, sort) { | SocketUser.setCategorySort = async function (socket, sort) { | ||||||
| 	await user.setSetting(socket.uid, 'categoryTopicSort', sort); | 	sockets.warnDeprecated(socket, 'PUT /api/v3/users/:uid/setting/categoryTopicSort'); | ||||||
|  | 	await api.users.updateSetting(socket, { | ||||||
|  | 		uid: socket.uid, | ||||||
|  | 		setting: 'categoryTopicSort', | ||||||
|  | 		value: sort, | ||||||
|  | 	}); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| SocketUser.getUnreadCount = async function (socket) { | SocketUser.getUnreadCount = async function (socket) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user