mirror of
				https://github.com/NodeBB/NodeBB.git
				synced 2025-11-03 20:45:58 +01:00 
			
		
		
		
	feat: #7743 groups/cover,create,data
This commit is contained in:
		@@ -1,80 +1,60 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
var async = require('async');
 | 
			
		||||
var path = require('path');
 | 
			
		||||
const path = require('path');
 | 
			
		||||
 | 
			
		||||
var db = require('../database');
 | 
			
		||||
var image = require('../image');
 | 
			
		||||
var file = require('../file');
 | 
			
		||||
const db = require('../database');
 | 
			
		||||
const image = require('../image');
 | 
			
		||||
const file = require('../file');
 | 
			
		||||
 | 
			
		||||
module.exports = function (Groups) {
 | 
			
		||||
	Groups.updateCoverPosition = function (groupName, position, callback) {
 | 
			
		||||
	Groups.updateCoverPosition = async function (groupName, position) {
 | 
			
		||||
		if (!groupName) {
 | 
			
		||||
			return callback(new Error('[[error:invalid-data]]'));
 | 
			
		||||
			throw new Error('[[error:invalid-data]]');
 | 
			
		||||
		}
 | 
			
		||||
		Groups.setGroupField(groupName, 'cover:position', position, callback);
 | 
			
		||||
		await Groups.setGroupField(groupName, 'cover:position', position);
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	Groups.updateCover = function (uid, data, callback) {
 | 
			
		||||
	Groups.updateCover = async function (uid, data) {
 | 
			
		||||
		let tempPath = data.file ? data.file : '';
 | 
			
		||||
		try {
 | 
			
		||||
			// Position only? That's fine
 | 
			
		||||
			if (!data.imageData && !data.file && data.position) {
 | 
			
		||||
			return Groups.updateCoverPosition(data.groupName, data.position, callback);
 | 
			
		||||
				return await Groups.updateCoverPosition(data.groupName, data.position);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		var tempPath = data.file ? data.file : '';
 | 
			
		||||
		var url;
 | 
			
		||||
 | 
			
		||||
		async.waterfall([
 | 
			
		||||
			function (next) {
 | 
			
		||||
				if (tempPath) {
 | 
			
		||||
					return next(null, tempPath);
 | 
			
		||||
			if (!tempPath) {
 | 
			
		||||
				tempPath = await image.writeImageDataToTempFile(data.imageData);
 | 
			
		||||
			}
 | 
			
		||||
				image.writeImageDataToTempFile(data.imageData, next);
 | 
			
		||||
			},
 | 
			
		||||
			function (_tempPath, next) {
 | 
			
		||||
				tempPath = _tempPath;
 | 
			
		||||
 | 
			
		||||
			const filename = 'groupCover-' + data.groupName + path.extname(tempPath);
 | 
			
		||||
				image.uploadImage(filename, 'files', {
 | 
			
		||||
			const uploadData = await image.uploadImage(filename, 'files', {
 | 
			
		||||
				path: tempPath,
 | 
			
		||||
				uid: uid,
 | 
			
		||||
				name: 'groupCover',
 | 
			
		||||
				}, next);
 | 
			
		||||
			},
 | 
			
		||||
			function (uploadData, next) {
 | 
			
		||||
				url = uploadData.url;
 | 
			
		||||
				Groups.setGroupField(data.groupName, 'cover:url', url, next);
 | 
			
		||||
			},
 | 
			
		||||
			function (next) {
 | 
			
		||||
				image.resizeImage({
 | 
			
		||||
			});
 | 
			
		||||
			const url = uploadData.url;
 | 
			
		||||
			await Groups.setGroupField(data.groupName, 'cover:url', url);
 | 
			
		||||
 | 
			
		||||
			await image.resizeImage({
 | 
			
		||||
				path: tempPath,
 | 
			
		||||
				width: 358,
 | 
			
		||||
				}, next);
 | 
			
		||||
			},
 | 
			
		||||
			function (next) {
 | 
			
		||||
				image.uploadImage('groupCoverThumb-' + data.groupName + path.extname(tempPath), 'files', {
 | 
			
		||||
			});
 | 
			
		||||
			const thumbUploadData = await image.uploadImage('groupCoverThumb-' + data.groupName + path.extname(tempPath), 'files', {
 | 
			
		||||
				path: tempPath,
 | 
			
		||||
				uid: uid,
 | 
			
		||||
				name: 'groupCover',
 | 
			
		||||
				}, next);
 | 
			
		||||
			},
 | 
			
		||||
			function (uploadData, next) {
 | 
			
		||||
				Groups.setGroupField(data.groupName, 'cover:thumb:url', uploadData.url, next);
 | 
			
		||||
			},
 | 
			
		||||
			function (next) {
 | 
			
		||||
				if (data.position) {
 | 
			
		||||
					Groups.updateCoverPosition(data.groupName, data.position, next);
 | 
			
		||||
				} else {
 | 
			
		||||
					next(null);
 | 
			
		||||
				}
 | 
			
		||||
			},
 | 
			
		||||
		], function (err) {
 | 
			
		||||
			file.delete(tempPath);
 | 
			
		||||
			callback(err, { url: url });
 | 
			
		||||
			});
 | 
			
		||||
			await Groups.setGroupField(data.groupName, 'cover:thumb:url', thumbUploadData.url);
 | 
			
		||||
 | 
			
		||||
			if (data.position) {
 | 
			
		||||
				await Groups.updateCoverPosition(data.groupName, data.position);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return { url: url };
 | 
			
		||||
		} finally {
 | 
			
		||||
			file.delete(tempPath);
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	Groups.removeCover = function (data, callback) {
 | 
			
		||||
		db.deleteObjectFields('group:' + data.groupName, ['cover:url', 'cover:thumb:url', 'cover:position'], callback);
 | 
			
		||||
	Groups.removeCover = async function (data) {
 | 
			
		||||
		await db.deleteObjectFields('group:' + data.groupName, ['cover:url', 'cover:thumb:url', 'cover:position']);
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,39 +1,32 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
var async = require('async');
 | 
			
		||||
var meta = require('../meta');
 | 
			
		||||
var plugins = require('../plugins');
 | 
			
		||||
var utils = require('../utils');
 | 
			
		||||
var db = require('../database');
 | 
			
		||||
const meta = require('../meta');
 | 
			
		||||
const plugins = require('../plugins');
 | 
			
		||||
const utils = require('../utils');
 | 
			
		||||
const db = require('../database');
 | 
			
		||||
 | 
			
		||||
module.exports = function (Groups) {
 | 
			
		||||
	Groups.create = function (data, callback) {
 | 
			
		||||
		var isSystem = isSystemGroup(data);
 | 
			
		||||
		var groupData;
 | 
			
		||||
		var timestamp = data.timestamp || Date.now();
 | 
			
		||||
		var disableJoinRequests = parseInt(data.disableJoinRequests, 10) === 1 ? 1 : 0;
 | 
			
		||||
	Groups.create = async function (data) {
 | 
			
		||||
		const isSystem = isSystemGroup(data);
 | 
			
		||||
		const timestamp = data.timestamp || Date.now();
 | 
			
		||||
		let disableJoinRequests = parseInt(data.disableJoinRequests, 10) === 1 ? 1 : 0;
 | 
			
		||||
		if (data.name === 'administrators') {
 | 
			
		||||
			disableJoinRequests = 1;
 | 
			
		||||
		}
 | 
			
		||||
		var isHidden = parseInt(data.hidden, 10) === 1;
 | 
			
		||||
		async.waterfall([
 | 
			
		||||
			function (next) {
 | 
			
		||||
				validateGroupName(data.name, next);
 | 
			
		||||
			},
 | 
			
		||||
			function (next) {
 | 
			
		||||
				meta.userOrGroupExists(data.name, next);
 | 
			
		||||
			},
 | 
			
		||||
			function (exists, next) {
 | 
			
		||||
		const isHidden = parseInt(data.hidden, 10) === 1;
 | 
			
		||||
 | 
			
		||||
		validateGroupName(data.name);
 | 
			
		||||
 | 
			
		||||
		const exists = await meta.userOrGroupExists(data.name);
 | 
			
		||||
		if (exists) {
 | 
			
		||||
					return next(new Error('[[error:group-already-exists]]'));
 | 
			
		||||
			throw new Error('[[error:group-already-exists]]');
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
				var memberCount = data.hasOwnProperty('ownerUid') ? 1 : 0;
 | 
			
		||||
				var isPrivate = data.hasOwnProperty('private') ? parseInt(data.private, 10) : 1;
 | 
			
		||||
				var slug = utils.slugify(data.name);
 | 
			
		||||
				groupData = {
 | 
			
		||||
		const memberCount = data.hasOwnProperty('ownerUid') ? 1 : 0;
 | 
			
		||||
		const isPrivate = data.hasOwnProperty('private') ? parseInt(data.private, 10) : 1;
 | 
			
		||||
		const groupData = {
 | 
			
		||||
			name: data.name,
 | 
			
		||||
					slug: slug,
 | 
			
		||||
			slug: utils.slugify(data.name),
 | 
			
		||||
			createtime: timestamp,
 | 
			
		||||
			userTitle: data.userTitle || data.name,
 | 
			
		||||
			userTitleEnabled: parseInt(data.userTitleEnabled, 10) === 1 ? 1 : 0,
 | 
			
		||||
@@ -44,36 +37,31 @@ module.exports = function (Groups) {
 | 
			
		||||
			private: isPrivate,
 | 
			
		||||
			disableJoinRequests: disableJoinRequests,
 | 
			
		||||
		};
 | 
			
		||||
				plugins.fireHook('filter:group.create', { group: groupData, data: data }, next);
 | 
			
		||||
			},
 | 
			
		||||
			function (results, next) {
 | 
			
		||||
				var tasks = [
 | 
			
		||||
					async.apply(db.sortedSetAdd, 'groups:createtime', groupData.createtime, groupData.name),
 | 
			
		||||
					async.apply(db.setObject, 'group:' + groupData.name, groupData),
 | 
			
		||||
				];
 | 
			
		||||
 | 
			
		||||
		plugins.fireHook('filter:group.create', { group: groupData, data: data });
 | 
			
		||||
 | 
			
		||||
		await db.sortedSetAdd('groups:createtime', groupData.createtime, groupData.name);
 | 
			
		||||
		await db.setObject('group:' + groupData.name, groupData);
 | 
			
		||||
 | 
			
		||||
		if (data.hasOwnProperty('ownerUid')) {
 | 
			
		||||
					tasks.push(async.apply(db.setAdd, 'group:' + groupData.name + ':owners', data.ownerUid));
 | 
			
		||||
					tasks.push(async.apply(db.sortedSetAdd, 'group:' + groupData.name + ':members', timestamp, data.ownerUid));
 | 
			
		||||
			await db.setAdd('group:' + groupData.name + ':owners', data.ownerUid);
 | 
			
		||||
			await db.sortedSetAdd('group:' + groupData.name + ':members', timestamp, data.ownerUid);
 | 
			
		||||
 | 
			
		||||
			groupData.ownerUid = data.ownerUid;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!isHidden && !isSystem) {
 | 
			
		||||
					tasks.push(async.apply(db.sortedSetAdd, 'groups:visible:createtime', timestamp, groupData.name));
 | 
			
		||||
					tasks.push(async.apply(db.sortedSetAdd, 'groups:visible:memberCount', groupData.memberCount, groupData.name));
 | 
			
		||||
					tasks.push(async.apply(db.sortedSetAdd, 'groups:visible:name', 0, groupData.name.toLowerCase() + ':' + groupData.name));
 | 
			
		||||
			await db.sortedSetAddBulk([
 | 
			
		||||
				['groups:visible:createtime', timestamp, groupData.name],
 | 
			
		||||
				['groups:visible:memberCount', groupData.memberCount, groupData.name],
 | 
			
		||||
				['groups:visible:name', 0, groupData.name.toLowerCase() + ':' + groupData.name],
 | 
			
		||||
			]);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
				tasks.push(async.apply(db.setObjectField, 'groupslug:groupname', groupData.slug, groupData.name));
 | 
			
		||||
		await db.setObjectField('groupslug:groupname', groupData.slug, groupData.name);
 | 
			
		||||
 | 
			
		||||
				async.series(tasks, next);
 | 
			
		||||
			},
 | 
			
		||||
			function (results, next) {
 | 
			
		||||
		plugins.fireHook('action:group.create', { group: groupData });
 | 
			
		||||
				next(null, groupData);
 | 
			
		||||
			},
 | 
			
		||||
		], callback);
 | 
			
		||||
		return groupData;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	function isSystemGroup(data) {
 | 
			
		||||
@@ -82,23 +70,21 @@ module.exports = function (Groups) {
 | 
			
		||||
			Groups.isPrivilegeGroup(data.name);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	function validateGroupName(name, callback) {
 | 
			
		||||
	function validateGroupName(name) {
 | 
			
		||||
		if (!name) {
 | 
			
		||||
			return callback(new Error('[[error:group-name-too-short]]'));
 | 
			
		||||
			throw new Error('[[error:group-name-too-short]]');
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!Groups.isPrivilegeGroup(name) && name.length > meta.config.maximumGroupNameLength) {
 | 
			
		||||
			return callback(new Error('[[error:group-name-too-long]]'));
 | 
			
		||||
			throw new Error('[[error:group-name-too-long]]');
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (name === 'guests' || (!Groups.isPrivilegeGroup(name) && name.includes(':'))) {
 | 
			
		||||
			return callback(new Error('[[error:invalid-group-name]]'));
 | 
			
		||||
			throw new Error('[[error:invalid-group-name]]');
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (name.includes('/') || !utils.slugify(name)) {
 | 
			
		||||
			return callback(new Error('[[error:invalid-group-name]]'));
 | 
			
		||||
			throw new Error('[[error:invalid-group-name]]');
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		callback();
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +1,11 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
var async = require('async');
 | 
			
		||||
var validator = require('validator');
 | 
			
		||||
var nconf = require('nconf');
 | 
			
		||||
const validator = require('validator');
 | 
			
		||||
const nconf = require('nconf');
 | 
			
		||||
 | 
			
		||||
var db = require('../database');
 | 
			
		||||
var plugins = require('../plugins');
 | 
			
		||||
var utils = require('../utils');
 | 
			
		||||
const db = require('../database');
 | 
			
		||||
const plugins = require('../plugins');
 | 
			
		||||
const utils = require('../utils');
 | 
			
		||||
 | 
			
		||||
const intFields = [
 | 
			
		||||
	'createtime', 'memberCount', 'hidden', 'system', 'private',
 | 
			
		||||
@@ -14,28 +13,25 @@ const intFields = [
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
module.exports = function (Groups) {
 | 
			
		||||
	Groups.getGroupsFields = function (groupNames, fields, callback) {
 | 
			
		||||
	Groups.getGroupsFields = async function (groupNames, fields) {
 | 
			
		||||
		if (!Array.isArray(groupNames) || !groupNames.length) {
 | 
			
		||||
			return callback(null, []);
 | 
			
		||||
			return [];
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var ephemeralIdx = groupNames.reduce(function (memo, cur, idx) {
 | 
			
		||||
		const ephemeralIdx = groupNames.reduce(function (memo, cur, idx) {
 | 
			
		||||
			if (Groups.ephemeralGroups.includes(cur)) {
 | 
			
		||||
				memo.push(idx);
 | 
			
		||||
			}
 | 
			
		||||
			return memo;
 | 
			
		||||
		}, []);
 | 
			
		||||
 | 
			
		||||
		async.waterfall([
 | 
			
		||||
			function (next) {
 | 
			
		||||
		let groupData;
 | 
			
		||||
		const keys = groupNames.map(groupName => 'group:' + groupName);
 | 
			
		||||
		if (fields.length) {
 | 
			
		||||
					db.getObjectsFields(keys, fields, next);
 | 
			
		||||
			groupData = await db.getObjectsFields(keys, fields);
 | 
			
		||||
		} else {
 | 
			
		||||
					db.getObjects(keys, next);
 | 
			
		||||
			groupData = await db.getObjects(keys);
 | 
			
		||||
		}
 | 
			
		||||
			},
 | 
			
		||||
			function (groupData, next) {
 | 
			
		||||
		if (ephemeralIdx.length) {
 | 
			
		||||
			ephemeralIdx.forEach(function (idx) {
 | 
			
		||||
				groupData[idx] = Groups.getEphemeralGroup(groupNames[idx]);
 | 
			
		||||
@@ -44,40 +40,27 @@ module.exports = function (Groups) {
 | 
			
		||||
 | 
			
		||||
		groupData.forEach(group => modifyGroup(group, fields));
 | 
			
		||||
 | 
			
		||||
				plugins.fireHook('filter:groups.get', { groups: groupData }, next);
 | 
			
		||||
			},
 | 
			
		||||
			function (results, next) {
 | 
			
		||||
				next(null, results.groups);
 | 
			
		||||
			},
 | 
			
		||||
		], callback);
 | 
			
		||||
		const results = await plugins.fireHook('filter:groups.get', { groups: groupData });
 | 
			
		||||
		return results.groups;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	Groups.getGroupsData = function (groupNames, callback) {
 | 
			
		||||
		Groups.getGroupsFields(groupNames, [], callback);
 | 
			
		||||
	Groups.getGroupsData = async function (groupNames) {
 | 
			
		||||
		return await Groups.getGroupsFields(groupNames, []);
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	Groups.getGroupData = function (groupName, callback) {
 | 
			
		||||
		Groups.getGroupsData([groupName], function (err, groupsData) {
 | 
			
		||||
			callback(err, Array.isArray(groupsData) && groupsData[0] ? groupsData[0] : null);
 | 
			
		||||
		});
 | 
			
		||||
	Groups.getGroupData = async function (groupName) {
 | 
			
		||||
		const groupsData = await Groups.getGroupsData([groupName]);
 | 
			
		||||
		return Array.isArray(groupsData) && groupsData[0] ? groupsData[0] : null;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	Groups.getGroupFields = function (groupName, fields, callback) {
 | 
			
		||||
		Groups.getGroupsFields([groupName], fields, function (err, groups) {
 | 
			
		||||
			callback(err, groups ? groups[0] : null);
 | 
			
		||||
		});
 | 
			
		||||
	Groups.getGroupFields = async function (groupName, fields) {
 | 
			
		||||
		const groups = await Groups.getGroupsFields([groupName], fields);
 | 
			
		||||
		return groups ? groups[0] : null;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	Groups.setGroupField = function (groupName, field, value, callback) {
 | 
			
		||||
		async.waterfall([
 | 
			
		||||
			function (next) {
 | 
			
		||||
				db.setObjectField('group:' + groupName, field, value, next);
 | 
			
		||||
			},
 | 
			
		||||
			function (next) {
 | 
			
		||||
	Groups.setGroupField = async function (groupName, field, value) {
 | 
			
		||||
		await db.setObjectField('group:' + groupName, field, value);
 | 
			
		||||
		plugins.fireHook('action:group.set', { field: field, value: value, type: 'set' });
 | 
			
		||||
				next();
 | 
			
		||||
			},
 | 
			
		||||
		], callback);
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user