mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-10-26 08:36:12 +01:00
refactor: deprecate picture update socket call, new API routes for picture update
This commit is contained in:
@@ -52,6 +52,8 @@ paths:
|
||||
$ref: 'write/users.yaml'
|
||||
/users/{uid}:
|
||||
$ref: 'write/users/uid.yaml'
|
||||
/users/{uid}/picture:
|
||||
$ref: 'write/users/uid/picture.yaml'
|
||||
/users/{uid}/content:
|
||||
$ref: 'write/users/uid/content.yaml'
|
||||
/users/{uid}/account:
|
||||
|
||||
43
public/openapi/write/users/uid/picture.yaml
Normal file
43
public/openapi/write/users/uid/picture.yaml
Normal file
@@ -0,0 +1,43 @@
|
||||
put:
|
||||
tags:
|
||||
- users
|
||||
summary: update user picture or icon background colour
|
||||
parameters:
|
||||
- in: path
|
||||
name: uid
|
||||
schema:
|
||||
type: integer
|
||||
required: true
|
||||
description: uid of the user
|
||||
example: 1
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
description: The source of the picture
|
||||
enum: ['default', 'uploaded', 'external']
|
||||
example: default
|
||||
url:
|
||||
type: string
|
||||
description: Only used for `external` type, specifies the source of the external image to use as avatar
|
||||
example: ''
|
||||
bgColor:
|
||||
type: string
|
||||
description: A hexadecimal colour representation
|
||||
example: '#ff0000'
|
||||
responses:
|
||||
'200':
|
||||
description: successfully updated user picture
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
$ref: ../../../components/schemas/Status.yaml#/Status
|
||||
response:
|
||||
type: object
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
define('accounts/picture', [
|
||||
'pictureCropper',
|
||||
], (pictureCropper) => {
|
||||
'api',
|
||||
], (pictureCropper, api) => {
|
||||
const Picture = {};
|
||||
|
||||
Picture.openChangeModal = () => {
|
||||
@@ -89,14 +90,10 @@ define('accounts/picture', [
|
||||
var type = modal.find('.list-group-item.active').attr('data-type');
|
||||
const iconBgColor = document.querySelector('.modal.picture-switcher input[type="radio"]:checked').value || 'transparent';
|
||||
|
||||
changeUserPicture(type, iconBgColor, function (err) {
|
||||
if (err) {
|
||||
return app.alertError(err.message);
|
||||
}
|
||||
|
||||
changeUserPicture(type, iconBgColor).then(() => {
|
||||
Picture.updateHeader(type === 'default' ? '' : modal.find('.list-group-item.active img').attr('src'), iconBgColor);
|
||||
ajaxify.refresh();
|
||||
});
|
||||
}).catch(app.alertError);
|
||||
}
|
||||
|
||||
function onCloseModal() {
|
||||
@@ -212,12 +209,8 @@ define('accounts/picture', [
|
||||
});
|
||||
}
|
||||
|
||||
function changeUserPicture(type, bgColor, callback) {
|
||||
socket.emit('user.changePicture', {
|
||||
type,
|
||||
bgColor,
|
||||
uid: ajaxify.data.theirid,
|
||||
}, callback);
|
||||
function changeUserPicture(type, bgColor) {
|
||||
return api.put(`/users/${ajaxify.data.theirid}/picture`, { type, bgColor });
|
||||
}
|
||||
|
||||
return Picture;
|
||||
|
||||
@@ -341,3 +341,44 @@ usersAPI.search = async function (caller, data) {
|
||||
filters: filters,
|
||||
});
|
||||
};
|
||||
|
||||
usersAPI.changePicture = async (caller, data) => {
|
||||
if (!data) {
|
||||
throw new Error('[[error:invalid-data]]');
|
||||
}
|
||||
|
||||
const { type, url } = data;
|
||||
let picture = '';
|
||||
|
||||
await user.checkMinReputation(caller.uid, data.uid, 'min:rep:profile-picture');
|
||||
const canEdit = await privileges.users.canEdit(caller.uid, data.uid);
|
||||
if (!canEdit) {
|
||||
throw new Error('[[error:no-privileges]]');
|
||||
}
|
||||
|
||||
if (type === 'default') {
|
||||
picture = '';
|
||||
} else if (type === 'uploaded') {
|
||||
picture = await user.getUserField(data.uid, 'uploadedpicture');
|
||||
} else if (type === 'external' && url) {
|
||||
picture = validator.escape(url);
|
||||
} else {
|
||||
const returnData = await plugins.hooks.fire('filter:user.getPicture', {
|
||||
uid: caller.uid,
|
||||
type: type,
|
||||
picture: undefined,
|
||||
});
|
||||
picture = returnData && returnData.picture;
|
||||
}
|
||||
|
||||
const validBackgrounds = await user.getIconBackgrounds(caller.uid);
|
||||
if (!validBackgrounds.includes(data.bgColor)) {
|
||||
data.bgColor = validBackgrounds[0];
|
||||
}
|
||||
|
||||
await user.updateProfile(caller.uid, {
|
||||
uid: data.uid,
|
||||
picture: picture,
|
||||
'icon:bgColor': data.bgColor,
|
||||
}, ['picture', 'icon:bgColor']);
|
||||
};
|
||||
|
||||
@@ -76,6 +76,11 @@ Users.deleteMany = async (req, res) => {
|
||||
helpers.formatApiResponse(200, res);
|
||||
};
|
||||
|
||||
Users.changePicture = async (req, res) => {
|
||||
await api.users.changePicture(req, { ...req.body, uid: req.params.uid });
|
||||
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);
|
||||
|
||||
@@ -22,6 +22,7 @@ function authenticatedRoutes() {
|
||||
setupApiRoute(router, 'get', '/:uid', [...middlewares, middleware.assert.user], controllers.write.users.get);
|
||||
setupApiRoute(router, 'put', '/:uid', [...middlewares, middleware.assert.user], controllers.write.users.update);
|
||||
setupApiRoute(router, 'delete', '/:uid', [...middlewares, middleware.assert.user], controllers.write.users.delete);
|
||||
setupApiRoute(router, 'put', '/:uid/picture', [...middlewares, middleware.assert.user], controllers.write.users.changePicture);
|
||||
setupApiRoute(router, 'delete', '/:uid/content', [...middlewares, middleware.assert.user], controllers.write.users.deleteContent);
|
||||
setupApiRoute(router, 'delete', '/:uid/account', [...middlewares, middleware.assert.user], controllers.write.users.deleteAccount);
|
||||
|
||||
|
||||
@@ -3,42 +3,13 @@
|
||||
const user = require('../../user');
|
||||
const plugins = require('../../plugins');
|
||||
|
||||
const websockets = require('../index');
|
||||
const api = require('../../api');
|
||||
|
||||
module.exports = function (SocketUser) {
|
||||
SocketUser.changePicture = async function (socket, data) {
|
||||
if (!socket.uid) {
|
||||
throw new Error('[[error:invalid-uid]]');
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
throw new Error('[[error:invalid-data]]');
|
||||
}
|
||||
|
||||
const { type } = data;
|
||||
let picture = '';
|
||||
await user.isAdminOrGlobalModOrSelf(socket.uid, data.uid);
|
||||
if (type === 'default') {
|
||||
picture = '';
|
||||
} else if (type === 'uploaded') {
|
||||
picture = await user.getUserField(data.uid, 'uploadedpicture');
|
||||
} else {
|
||||
const returnData = await plugins.hooks.fire('filter:user.getPicture', {
|
||||
uid: socket.uid,
|
||||
type: type,
|
||||
picture: undefined,
|
||||
});
|
||||
picture = returnData && returnData.picture;
|
||||
}
|
||||
|
||||
const validBackgrounds = await user.getIconBackgrounds(socket.uid);
|
||||
if (!validBackgrounds.includes(data.bgColor)) {
|
||||
data.bgColor = validBackgrounds[0];
|
||||
}
|
||||
|
||||
await user.updateProfile(socket.uid, {
|
||||
uid: data.uid,
|
||||
picture: picture,
|
||||
'icon:bgColor': data.bgColor,
|
||||
}, ['picture', 'icon:bgColor']);
|
||||
websockets.warnDeprecated(socket, 'PUT /api/v3/users/:uid/picture');
|
||||
await api.users.changePicture(socket, data);
|
||||
};
|
||||
|
||||
SocketUser.removeUploadedPicture = async function (socket, data) {
|
||||
|
||||
Reference in New Issue
Block a user