|
@@ -10,10 +10,8 @@ import loggerFactory from '~/utils/logger';
|
|
|
import { aclService } from '../service/acl';
|
|
import { aclService } from '../service/acl';
|
|
|
import { configManager } from '../service/config-manager';
|
|
import { configManager } from '../service/config-manager';
|
|
|
import { getModelSafely } from '../util/mongoose-utils';
|
|
import { getModelSafely } from '../util/mongoose-utils';
|
|
|
-
|
|
|
|
|
import { Attachment } from './attachment';
|
|
import { Attachment } from './attachment';
|
|
|
|
|
|
|
|
-
|
|
|
|
|
const crypto = require('crypto');
|
|
const crypto = require('crypto');
|
|
|
|
|
|
|
|
const mongoose = require('mongoose');
|
|
const mongoose = require('mongoose');
|
|
@@ -24,7 +22,6 @@ const logger = loggerFactory('growi:models:user');
|
|
|
|
|
|
|
|
/** @param {import('~/server/crowi').default | null} crowi Crowi instance */
|
|
/** @param {import('~/server/crowi').default | null} crowi Crowi instance */
|
|
|
const factory = (crowi) => {
|
|
const factory = (crowi) => {
|
|
|
-
|
|
|
|
|
const userModelExists = getModelSafely('User');
|
|
const userModelExists = getModelSafely('User');
|
|
|
if (userModelExists != null) {
|
|
if (userModelExists != null) {
|
|
|
return userModelExists;
|
|
return userModelExists;
|
|
@@ -35,8 +32,9 @@ const factory = (crowi) => {
|
|
|
const STATUS_SUSPENDED = 3;
|
|
const STATUS_SUSPENDED = 3;
|
|
|
const STATUS_DELETED = 4;
|
|
const STATUS_DELETED = 4;
|
|
|
const STATUS_INVITED = 5;
|
|
const STATUS_INVITED = 5;
|
|
|
- const USER_FIELDS_EXCEPT_CONFIDENTIAL = '_id image isEmailPublished isGravatarEnabled googleId name username email introduction'
|
|
|
|
|
- + ' status lang createdAt lastLoginAt admin imageUrlCached';
|
|
|
|
|
|
|
+ const USER_FIELDS_EXCEPT_CONFIDENTIAL =
|
|
|
|
|
+ '_id image isEmailPublished isGravatarEnabled googleId name username email introduction' +
|
|
|
|
|
+ ' status lang createdAt lastLoginAt admin imageUrlCached';
|
|
|
|
|
|
|
|
const PAGE_ITEMS = 50;
|
|
const PAGE_ITEMS = 50;
|
|
|
|
|
|
|
@@ -48,53 +46,63 @@ const factory = (crowi) => {
|
|
|
userEvent.on('activated', userEvent.onActivated);
|
|
userEvent.on('activated', userEvent.onActivated);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-
|
|
|
|
|
- const userSchema = new mongoose.Schema({
|
|
|
|
|
- userId: String,
|
|
|
|
|
- image: String,
|
|
|
|
|
- imageAttachment: { type: mongoose.Schema.Types.ObjectId, ref: 'Attachment' },
|
|
|
|
|
- imageUrlCached: String,
|
|
|
|
|
- isGravatarEnabled: { type: Boolean, default: false },
|
|
|
|
|
- isEmailPublished: { type: Boolean, default: true },
|
|
|
|
|
- googleId: String,
|
|
|
|
|
- name: { type: String, index: true },
|
|
|
|
|
- username: { type: String, required: true, unique: true },
|
|
|
|
|
- email: { type: String, unique: true, sparse: true },
|
|
|
|
|
- slackMemberId: { type: String, unique: true, sparse: true },
|
|
|
|
|
- // === Crowi settings
|
|
|
|
|
- // username: { type: String, index: true },
|
|
|
|
|
- // email: { type: String, required: true, index: true },
|
|
|
|
|
- // === crowi-plus (>= 2.1.0, <2.3.0) settings
|
|
|
|
|
- // email: { type: String, required: true, unique: true },
|
|
|
|
|
- introduction: String,
|
|
|
|
|
- password: String,
|
|
|
|
|
- apiToken: { type: String, index: true },
|
|
|
|
|
- lang: {
|
|
|
|
|
- type: String,
|
|
|
|
|
- enum: i18n.locales,
|
|
|
|
|
- default: 'en_US',
|
|
|
|
|
- },
|
|
|
|
|
- status: {
|
|
|
|
|
- type: Number, required: true, default: STATUS_ACTIVE, index: true,
|
|
|
|
|
|
|
+ const userSchema = new mongoose.Schema(
|
|
|
|
|
+ {
|
|
|
|
|
+ userId: String,
|
|
|
|
|
+ image: String,
|
|
|
|
|
+ imageAttachment: {
|
|
|
|
|
+ type: mongoose.Schema.Types.ObjectId,
|
|
|
|
|
+ ref: 'Attachment',
|
|
|
|
|
+ },
|
|
|
|
|
+ imageUrlCached: String,
|
|
|
|
|
+ isGravatarEnabled: { type: Boolean, default: false },
|
|
|
|
|
+ isEmailPublished: { type: Boolean, default: true },
|
|
|
|
|
+ googleId: String,
|
|
|
|
|
+ name: { type: String, index: true },
|
|
|
|
|
+ username: { type: String, required: true, unique: true },
|
|
|
|
|
+ email: { type: String, unique: true, sparse: true },
|
|
|
|
|
+ slackMemberId: { type: String, unique: true, sparse: true },
|
|
|
|
|
+ // === Crowi settings
|
|
|
|
|
+ // username: { type: String, index: true },
|
|
|
|
|
+ // email: { type: String, required: true, index: true },
|
|
|
|
|
+ // === crowi-plus (>= 2.1.0, <2.3.0) settings
|
|
|
|
|
+ // email: { type: String, required: true, unique: true },
|
|
|
|
|
+ introduction: String,
|
|
|
|
|
+ password: String,
|
|
|
|
|
+ apiToken: { type: String, index: true },
|
|
|
|
|
+ lang: {
|
|
|
|
|
+ type: String,
|
|
|
|
|
+ enum: i18n.locales,
|
|
|
|
|
+ default: 'en_US',
|
|
|
|
|
+ },
|
|
|
|
|
+ status: {
|
|
|
|
|
+ type: Number,
|
|
|
|
|
+ required: true,
|
|
|
|
|
+ default: STATUS_ACTIVE,
|
|
|
|
|
+ index: true,
|
|
|
|
|
+ },
|
|
|
|
|
+ lastLoginAt: { type: Date, index: true },
|
|
|
|
|
+ admin: { type: Boolean, default: 0, index: true },
|
|
|
|
|
+ readOnly: { type: Boolean, default: 0 },
|
|
|
|
|
+ isInvitationEmailSended: { type: Boolean, default: false },
|
|
|
},
|
|
},
|
|
|
- lastLoginAt: { type: Date, index: true },
|
|
|
|
|
- admin: { type: Boolean, default: 0, index: true },
|
|
|
|
|
- readOnly: { type: Boolean, default: 0 },
|
|
|
|
|
- isInvitationEmailSended: { type: Boolean, default: false },
|
|
|
|
|
- }, {
|
|
|
|
|
- timestamps: true,
|
|
|
|
|
- toObject: {
|
|
|
|
|
- transform: (doc, ret, opt) => {
|
|
|
|
|
- return omitInsecureAttributes(ret);
|
|
|
|
|
|
|
+ {
|
|
|
|
|
+ timestamps: true,
|
|
|
|
|
+ toObject: {
|
|
|
|
|
+ transform: (doc, ret, opt) => {
|
|
|
|
|
+ return omitInsecureAttributes(ret);
|
|
|
|
|
+ },
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
- });
|
|
|
|
|
|
|
+ );
|
|
|
userSchema.plugin(mongoosePaginate);
|
|
userSchema.plugin(mongoosePaginate);
|
|
|
userSchema.plugin(uniqueValidator);
|
|
userSchema.plugin(uniqueValidator);
|
|
|
|
|
|
|
|
function validateCrowi() {
|
|
function validateCrowi() {
|
|
|
if (crowi == null) {
|
|
if (crowi == null) {
|
|
|
- throw new Error('"crowi" is null. Init User model with "crowi" argument first.');
|
|
|
|
|
|
|
+ throw new Error(
|
|
|
|
|
+ '"crowi" is null. Init User model with "crowi" argument first.',
|
|
|
|
|
+ );
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -107,7 +115,9 @@ const factory = (crowi) => {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// status decided depends on registrationMode
|
|
// status decided depends on registrationMode
|
|
|
- const registrationMode = configManager.getConfig('security:registrationMode');
|
|
|
|
|
|
|
+ const registrationMode = configManager.getConfig(
|
|
|
|
|
+ 'security:registrationMode',
|
|
|
|
|
+ );
|
|
|
switch (registrationMode) {
|
|
switch (registrationMode) {
|
|
|
case aclService.labels.SECURITY_REGISTRATION_MODE_OPEN:
|
|
case aclService.labels.SECURITY_REGISTRATION_MODE_OPEN:
|
|
|
return STATUS_ACTIVE;
|
|
return STATUS_ACTIVE;
|
|
@@ -120,7 +130,8 @@ const factory = (crowi) => {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function generateRandomTempPassword() {
|
|
function generateRandomTempPassword() {
|
|
|
- const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!=-_';
|
|
|
|
|
|
|
+ const chars =
|
|
|
|
|
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!=-_';
|
|
|
let password = '';
|
|
let password = '';
|
|
|
const len = 12;
|
|
const len = 12;
|
|
|
|
|
|
|
@@ -148,20 +159,18 @@ const factory = (crowi) => {
|
|
|
|
|
|
|
|
function generateApiToken(user) {
|
|
function generateApiToken(user) {
|
|
|
const hasher = crypto.createHash('sha256');
|
|
const hasher = crypto.createHash('sha256');
|
|
|
- hasher.update((new Date()).getTime() + user._id);
|
|
|
|
|
|
|
+ hasher.update(new Date().getTime() + user._id);
|
|
|
|
|
|
|
|
return hasher.digest('base64');
|
|
return hasher.digest('base64');
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- userSchema.methods.isUniqueEmail = async function() {
|
|
|
|
|
|
|
+ userSchema.methods.isUniqueEmail = async function () {
|
|
|
const query = this.model('User').find();
|
|
const query = this.model('User').find();
|
|
|
|
|
|
|
|
- const count = await query.count((
|
|
|
|
|
- {
|
|
|
|
|
- username: { $ne: this.username },
|
|
|
|
|
- email: this.email,
|
|
|
|
|
- }
|
|
|
|
|
- ));
|
|
|
|
|
|
|
+ const count = await query.count({
|
|
|
|
|
+ username: { $ne: this.username },
|
|
|
|
|
+ email: this.email,
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
if (count > 0) {
|
|
if (count > 0) {
|
|
|
return false;
|
|
return false;
|
|
@@ -169,66 +178,66 @@ const factory = (crowi) => {
|
|
|
return true;
|
|
return true;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.methods.isPasswordSet = function() {
|
|
|
|
|
|
|
+ userSchema.methods.isPasswordSet = function () {
|
|
|
if (this.password) {
|
|
if (this.password) {
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
|
return false;
|
|
return false;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.methods.isPasswordValid = function(password) {
|
|
|
|
|
|
|
+ userSchema.methods.isPasswordValid = function (password) {
|
|
|
return this.password === generatePassword(password);
|
|
return this.password === generatePassword(password);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.methods.setPassword = function(password) {
|
|
|
|
|
|
|
+ userSchema.methods.setPassword = function (password) {
|
|
|
this.password = generatePassword(password);
|
|
this.password = generatePassword(password);
|
|
|
return this;
|
|
return this;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.methods.isEmailSet = function() {
|
|
|
|
|
|
|
+ userSchema.methods.isEmailSet = function () {
|
|
|
if (this.email) {
|
|
if (this.email) {
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
|
return false;
|
|
return false;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.methods.updateLastLoginAt = function(lastLoginAt, callback) {
|
|
|
|
|
|
|
+ userSchema.methods.updateLastLoginAt = function (lastLoginAt, callback) {
|
|
|
this.lastLoginAt = lastLoginAt;
|
|
this.lastLoginAt = lastLoginAt;
|
|
|
this.save((err, userData) => {
|
|
this.save((err, userData) => {
|
|
|
return callback(err, userData);
|
|
return callback(err, userData);
|
|
|
});
|
|
});
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.methods.updateIsGravatarEnabled = async function(isGravatarEnabled) {
|
|
|
|
|
|
|
+ userSchema.methods.updateIsGravatarEnabled = async function (
|
|
|
|
|
+ isGravatarEnabled,
|
|
|
|
|
+ ) {
|
|
|
this.isGravatarEnabled = isGravatarEnabled;
|
|
this.isGravatarEnabled = isGravatarEnabled;
|
|
|
await this.updateImageUrlCached();
|
|
await this.updateImageUrlCached();
|
|
|
const userData = await this.save();
|
|
const userData = await this.save();
|
|
|
return userData;
|
|
return userData;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.methods.updatePassword = async function(password) {
|
|
|
|
|
|
|
+ userSchema.methods.updatePassword = async function (password) {
|
|
|
this.setPassword(password);
|
|
this.setPassword(password);
|
|
|
const userData = await this.save();
|
|
const userData = await this.save();
|
|
|
return userData;
|
|
return userData;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.methods.updateApiToken = async function() {
|
|
|
|
|
- const self = this;
|
|
|
|
|
-
|
|
|
|
|
- self.apiToken = generateApiToken(this);
|
|
|
|
|
- const userData = await self.save();
|
|
|
|
|
|
|
+ userSchema.methods.updateApiToken = async function () {
|
|
|
|
|
+ this.apiToken = generateApiToken(this);
|
|
|
|
|
+ const userData = await this.save();
|
|
|
return userData;
|
|
return userData;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
// TODO: create UserService and transplant this method because image uploading depends on AttachmentService
|
|
// TODO: create UserService and transplant this method because image uploading depends on AttachmentService
|
|
|
- userSchema.methods.updateImage = async function(attachment) {
|
|
|
|
|
|
|
+ userSchema.methods.updateImage = async function (attachment) {
|
|
|
this.imageAttachment = attachment;
|
|
this.imageAttachment = attachment;
|
|
|
await this.updateImageUrlCached();
|
|
await this.updateImageUrlCached();
|
|
|
return this.save();
|
|
return this.save();
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
// TODO: create UserService and transplant this method because image deletion depends on AttachmentService
|
|
// TODO: create UserService and transplant this method because image deletion depends on AttachmentService
|
|
|
- userSchema.methods.deleteImage = async function() {
|
|
|
|
|
|
|
+ userSchema.methods.deleteImage = async function () {
|
|
|
validateCrowi();
|
|
validateCrowi();
|
|
|
|
|
|
|
|
// the 'image' field became DEPRECATED in v3.3.8
|
|
// the 'image' field became DEPRECATED in v3.3.8
|
|
@@ -244,11 +253,11 @@ const factory = (crowi) => {
|
|
|
return this.save();
|
|
return this.save();
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.methods.updateImageUrlCached = async function() {
|
|
|
|
|
|
|
+ userSchema.methods.updateImageUrlCached = async function () {
|
|
|
this.imageUrlCached = await this.generateImageUrlCached();
|
|
this.imageUrlCached = await this.generateImageUrlCached();
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.methods.generateImageUrlCached = async function() {
|
|
|
|
|
|
|
+ userSchema.methods.generateImageUrlCached = async function () {
|
|
|
if (this.isGravatarEnabled) {
|
|
if (this.isGravatarEnabled) {
|
|
|
return generateGravatarSrc(this.email);
|
|
return generateGravatarSrc(this.email);
|
|
|
}
|
|
}
|
|
@@ -262,23 +271,29 @@ const factory = (crowi) => {
|
|
|
return '/images/icons/user.svg';
|
|
return '/images/icons/user.svg';
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.methods.updateGoogleId = function(googleId, callback) {
|
|
|
|
|
|
|
+ userSchema.methods.updateGoogleId = function (googleId, callback) {
|
|
|
this.googleId = googleId;
|
|
this.googleId = googleId;
|
|
|
this.save((err, userData) => {
|
|
this.save((err, userData) => {
|
|
|
return callback(err, userData);
|
|
return callback(err, userData);
|
|
|
});
|
|
});
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.methods.deleteGoogleId = function(callback) {
|
|
|
|
|
|
|
+ userSchema.methods.deleteGoogleId = function (callback) {
|
|
|
return this.updateGoogleId(null, callback);
|
|
return this.updateGoogleId(null, callback);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.methods.activateInvitedUser = async function(username, name, password) {
|
|
|
|
|
|
|
+ userSchema.methods.activateInvitedUser = async function (
|
|
|
|
|
+ username,
|
|
|
|
|
+ name,
|
|
|
|
|
+ password,
|
|
|
|
|
+ ) {
|
|
|
this.setPassword(password);
|
|
this.setPassword(password);
|
|
|
this.name = name;
|
|
this.name = name;
|
|
|
this.username = username;
|
|
this.username = username;
|
|
|
this.status = STATUS_ACTIVE;
|
|
this.status = STATUS_ACTIVE;
|
|
|
- this.isEmailPublished = configManager.getConfig('customize:isEmailPublishedForNewUser');
|
|
|
|
|
|
|
+ this.isEmailPublished = configManager.getConfig(
|
|
|
|
|
+ 'customize:isEmailPublishedForNewUser',
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
this.save((err, userData) => {
|
|
this.save((err, userData) => {
|
|
|
userEvent.emit('activated', userData);
|
|
userEvent.emit('activated', userData);
|
|
@@ -289,58 +304,61 @@ const factory = (crowi) => {
|
|
|
});
|
|
});
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.methods.grantAdmin = async function() {
|
|
|
|
|
|
|
+ userSchema.methods.grantAdmin = async function () {
|
|
|
logger.debug('Grant Admin', this);
|
|
logger.debug('Grant Admin', this);
|
|
|
this.admin = 1;
|
|
this.admin = 1;
|
|
|
return this.save();
|
|
return this.save();
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.methods.revokeAdmin = async function() {
|
|
|
|
|
|
|
+ userSchema.methods.revokeAdmin = async function () {
|
|
|
logger.debug('Revove admin', this);
|
|
logger.debug('Revove admin', this);
|
|
|
this.admin = 0;
|
|
this.admin = 0;
|
|
|
return this.save();
|
|
return this.save();
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.methods.grantReadOnly = async function() {
|
|
|
|
|
|
|
+ userSchema.methods.grantReadOnly = async function () {
|
|
|
logger.debug('Grant read only access', this);
|
|
logger.debug('Grant read only access', this);
|
|
|
this.readOnly = 1;
|
|
this.readOnly = 1;
|
|
|
return this.save();
|
|
return this.save();
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.methods.revokeReadOnly = async function() {
|
|
|
|
|
|
|
+ userSchema.methods.revokeReadOnly = async function () {
|
|
|
logger.debug('Revoke read only access', this);
|
|
logger.debug('Revoke read only access', this);
|
|
|
this.readOnly = 0;
|
|
this.readOnly = 0;
|
|
|
return this.save();
|
|
return this.save();
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.methods.asyncGrantAdmin = async function(callback) {
|
|
|
|
|
|
|
+ userSchema.methods.asyncGrantAdmin = async function (callback) {
|
|
|
this.admin = 1;
|
|
this.admin = 1;
|
|
|
return this.save();
|
|
return this.save();
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.methods.statusActivate = async function() {
|
|
|
|
|
|
|
+ userSchema.methods.statusActivate = async function () {
|
|
|
logger.debug('Activate User', this);
|
|
logger.debug('Activate User', this);
|
|
|
this.status = STATUS_ACTIVE;
|
|
this.status = STATUS_ACTIVE;
|
|
|
const userData = await this.save();
|
|
const userData = await this.save();
|
|
|
return userEvent.emit('activated', userData);
|
|
return userEvent.emit('activated', userData);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.methods.statusSuspend = async function() {
|
|
|
|
|
|
|
+ userSchema.methods.statusSuspend = async function () {
|
|
|
logger.debug('Suspend User', this);
|
|
logger.debug('Suspend User', this);
|
|
|
this.status = STATUS_SUSPENDED;
|
|
this.status = STATUS_SUSPENDED;
|
|
|
- if (this.email === undefined || this.email === null) { // migrate old data
|
|
|
|
|
|
|
+ if (this.email === undefined || this.email === null) {
|
|
|
|
|
+ // migrate old data
|
|
|
this.email = '-';
|
|
this.email = '-';
|
|
|
}
|
|
}
|
|
|
- if (this.name === undefined || this.name === null) { // migrate old data
|
|
|
|
|
|
|
+ if (this.name === undefined || this.name === null) {
|
|
|
|
|
+ // migrate old data
|
|
|
this.name = `-${Date.now()}`;
|
|
this.name = `-${Date.now()}`;
|
|
|
}
|
|
}
|
|
|
- if (this.username === undefined || this.usename === null) { // migrate old data
|
|
|
|
|
|
|
+ if (this.username === undefined || this.usename === null) {
|
|
|
|
|
+ // migrate old data
|
|
|
this.username = '-';
|
|
this.username = '-';
|
|
|
}
|
|
}
|
|
|
return this.save();
|
|
return this.save();
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.methods.statusDelete = async function() {
|
|
|
|
|
|
|
+ userSchema.methods.statusDelete = async function () {
|
|
|
logger.debug('Delete User', this);
|
|
logger.debug('Delete User', this);
|
|
|
|
|
|
|
|
const now = new Date();
|
|
const now = new Date();
|
|
@@ -357,7 +375,7 @@ const factory = (crowi) => {
|
|
|
return this.save();
|
|
return this.save();
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.statics.getUserStatusLabels = function() {
|
|
|
|
|
|
|
+ userSchema.statics.getUserStatusLabels = () => {
|
|
|
const userStatus = {};
|
|
const userStatus = {};
|
|
|
userStatus[STATUS_REGISTERED] = 'Approval Pending';
|
|
userStatus[STATUS_REGISTERED] = 'Approval Pending';
|
|
|
userStatus[STATUS_ACTIVE] = 'Active';
|
|
userStatus[STATUS_ACTIVE] = 'Active';
|
|
@@ -368,7 +386,7 @@ const factory = (crowi) => {
|
|
|
return userStatus;
|
|
return userStatus;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.statics.isEmailValid = function(email, callback) {
|
|
|
|
|
|
|
+ userSchema.statics.isEmailValid = (email, callback) => {
|
|
|
validateCrowi();
|
|
validateCrowi();
|
|
|
|
|
|
|
|
const whitelist = configManager.getConfig('security:registrationWhitelist');
|
|
const whitelist = configManager.getConfig('security:registrationWhitelist');
|
|
@@ -383,7 +401,7 @@ const factory = (crowi) => {
|
|
|
return true;
|
|
return true;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.statics.findUsers = function(options, callback) {
|
|
|
|
|
|
|
+ userSchema.statics.findUsers = function (options, callback) {
|
|
|
const sort = options.sort || { status: 1, createdAt: 1 };
|
|
const sort = options.sort || { status: 1, createdAt: 1 };
|
|
|
|
|
|
|
|
this.find()
|
|
this.find()
|
|
@@ -395,7 +413,7 @@ const factory = (crowi) => {
|
|
|
});
|
|
});
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.statics.findAllUsers = function(option) {
|
|
|
|
|
|
|
+ userSchema.statics.findAllUsers = function (option) {
|
|
|
// eslint-disable-next-line no-param-reassign
|
|
// eslint-disable-next-line no-param-reassign
|
|
|
option = option || {};
|
|
option = option || {};
|
|
|
|
|
|
|
@@ -408,12 +426,16 @@ const factory = (crowi) => {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return this.find()
|
|
return this.find()
|
|
|
- .or(status.map((s) => { return { status: s } }))
|
|
|
|
|
|
|
+ .or(
|
|
|
|
|
+ status.map((s) => {
|
|
|
|
|
+ return { status: s };
|
|
|
|
|
+ }),
|
|
|
|
|
+ )
|
|
|
.select(fields)
|
|
.select(fields)
|
|
|
.sort(sort);
|
|
.sort(sort);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.statics.findUsersByIds = function(ids, option) {
|
|
|
|
|
|
|
+ userSchema.statics.findUsersByIds = function (ids, option) {
|
|
|
// eslint-disable-next-line no-param-reassign
|
|
// eslint-disable-next-line no-param-reassign
|
|
|
option = option || {};
|
|
option = option || {};
|
|
|
|
|
|
|
@@ -426,7 +448,7 @@ const factory = (crowi) => {
|
|
|
.sort(sort);
|
|
.sort(sort);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.statics.findAdmins = async function(option) {
|
|
|
|
|
|
|
+ userSchema.statics.findAdmins = async function (option) {
|
|
|
const sort = option?.sort ?? { createdAt: -1 };
|
|
const sort = option?.sort ?? { createdAt: -1 };
|
|
|
|
|
|
|
|
let status = option?.status ?? [STATUS_ACTIVE];
|
|
let status = option?.status ?? [STATUS_ACTIVE];
|
|
@@ -434,25 +456,24 @@ const factory = (crowi) => {
|
|
|
status = [status];
|
|
status = [status];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- return this.find({ admin: true, status: { $in: status } })
|
|
|
|
|
- .sort(sort);
|
|
|
|
|
|
|
+ return this.find({ admin: true, status: { $in: status } }).sort(sort);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.statics.findUserByUsername = function(username) {
|
|
|
|
|
|
|
+ userSchema.statics.findUserByUsername = function (username) {
|
|
|
if (username == null) {
|
|
if (username == null) {
|
|
|
return Promise.resolve(null);
|
|
return Promise.resolve(null);
|
|
|
}
|
|
}
|
|
|
return this.findOne({ username });
|
|
return this.findOne({ username });
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.statics.findUserByApiToken = function(apiToken) {
|
|
|
|
|
|
|
+ userSchema.statics.findUserByApiToken = function (apiToken) {
|
|
|
if (apiToken == null) {
|
|
if (apiToken == null) {
|
|
|
return Promise.resolve(null);
|
|
return Promise.resolve(null);
|
|
|
}
|
|
}
|
|
|
return this.findOne({ apiToken }).lean();
|
|
return this.findOne({ apiToken }).lean();
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.statics.findUserByGoogleId = function(googleId, callback) {
|
|
|
|
|
|
|
+ userSchema.statics.findUserByGoogleId = function (googleId, callback) {
|
|
|
if (googleId == null) {
|
|
if (googleId == null) {
|
|
|
callback(null, null);
|
|
callback(null, null);
|
|
|
}
|
|
}
|
|
@@ -461,25 +482,30 @@ const factory = (crowi) => {
|
|
|
});
|
|
});
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.statics.findUserByUsernameOrEmail = function(usernameOrEmail, password, callback) {
|
|
|
|
|
|
|
+ userSchema.statics.findUserByUsernameOrEmail = function (
|
|
|
|
|
+ usernameOrEmail,
|
|
|
|
|
+ password,
|
|
|
|
|
+ callback,
|
|
|
|
|
+ ) {
|
|
|
this.findOne()
|
|
this.findOne()
|
|
|
- .or([
|
|
|
|
|
- { username: usernameOrEmail },
|
|
|
|
|
- { email: usernameOrEmail },
|
|
|
|
|
- ])
|
|
|
|
|
|
|
+ .or([{ username: usernameOrEmail }, { email: usernameOrEmail }])
|
|
|
.exec((err, userData) => {
|
|
.exec((err, userData) => {
|
|
|
callback(err, userData);
|
|
callback(err, userData);
|
|
|
});
|
|
});
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.statics.findUserByEmailAndPassword = function(email, password, callback) {
|
|
|
|
|
|
|
+ userSchema.statics.findUserByEmailAndPassword = function (
|
|
|
|
|
+ email,
|
|
|
|
|
+ password,
|
|
|
|
|
+ callback,
|
|
|
|
|
+ ) {
|
|
|
const hashedPassword = generatePassword(password);
|
|
const hashedPassword = generatePassword(password);
|
|
|
this.findOne({ email, password: hashedPassword }, (err, userData) => {
|
|
this.findOne({ email, password: hashedPassword }, (err, userData) => {
|
|
|
callback(err, userData);
|
|
callback(err, userData);
|
|
|
});
|
|
});
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.statics.isUserCountExceedsUpperLimit = async function() {
|
|
|
|
|
|
|
+ userSchema.statics.isUserCountExceedsUpperLimit = async function () {
|
|
|
const userUpperLimit = configManager.getConfig('security:userUpperLimit');
|
|
const userUpperLimit = configManager.getConfig('security:userUpperLimit');
|
|
|
|
|
|
|
|
const activeUsers = await this.countActiveUsers();
|
|
const activeUsers = await this.countActiveUsers();
|
|
@@ -490,11 +516,12 @@ const factory = (crowi) => {
|
|
|
return false;
|
|
return false;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.statics.countActiveUsers = async function() {
|
|
|
|
|
|
|
+ userSchema.statics.countActiveUsers = async function () {
|
|
|
return this.countListByStatus(STATUS_ACTIVE);
|
|
return this.countListByStatus(STATUS_ACTIVE);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.statics.countListByStatus = async function(status) {
|
|
|
|
|
|
|
+ userSchema.statics.countListByStatus = async function (status) {
|
|
|
|
|
+ // biome-ignore lint/complexity/noUselessThisAlias: ignore
|
|
|
const User = this;
|
|
const User = this;
|
|
|
const conditions = { status };
|
|
const conditions = { status };
|
|
|
|
|
|
|
@@ -502,7 +529,7 @@ const factory = (crowi) => {
|
|
|
return User.count(conditions);
|
|
return User.count(conditions);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.statics.isRegisterableUsername = async function(username) {
|
|
|
|
|
|
|
+ userSchema.statics.isRegisterableUsername = async function (username) {
|
|
|
let usernameUsable = true;
|
|
let usernameUsable = true;
|
|
|
|
|
|
|
|
const userData = await this.findOne({ username });
|
|
const userData = await this.findOne({ username });
|
|
@@ -512,7 +539,7 @@ const factory = (crowi) => {
|
|
|
return usernameUsable;
|
|
return usernameUsable;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.statics.isRegisterableEmail = async function(email) {
|
|
|
|
|
|
|
+ userSchema.statics.isRegisterableEmail = async function (email) {
|
|
|
let isEmailUsable = true;
|
|
let isEmailUsable = true;
|
|
|
|
|
|
|
|
const userData = await this.findOne({ email });
|
|
const userData = await this.findOne({ email });
|
|
@@ -522,13 +549,14 @@ const factory = (crowi) => {
|
|
|
return isEmailUsable;
|
|
return isEmailUsable;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.statics.isRegisterable = function(email, username, callback) {
|
|
|
|
|
|
|
+ userSchema.statics.isRegisterable = function (email, username, callback) {
|
|
|
|
|
+ // biome-ignore lint/complexity/noUselessThisAlias: ignore
|
|
|
const User = this;
|
|
const User = this;
|
|
|
let emailUsable = true;
|
|
let emailUsable = true;
|
|
|
let usernameUsable = true;
|
|
let usernameUsable = true;
|
|
|
|
|
|
|
|
// username check
|
|
// username check
|
|
|
- this.findOne({ username }, (err, userData) => {
|
|
|
|
|
|
|
+ User.findOne({ username }, (err, userData) => {
|
|
|
if (userData) {
|
|
if (userData) {
|
|
|
usernameUsable = false;
|
|
usernameUsable = false;
|
|
|
}
|
|
}
|
|
@@ -540,7 +568,10 @@ const factory = (crowi) => {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (!emailUsable || !usernameUsable) {
|
|
if (!emailUsable || !usernameUsable) {
|
|
|
- return callback(false, { email: emailUsable, username: usernameUsable });
|
|
|
|
|
|
|
+ return callback(false, {
|
|
|
|
|
+ email: emailUsable,
|
|
|
|
|
+ username: usernameUsable,
|
|
|
|
|
+ });
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return callback(true, {});
|
|
return callback(true, {});
|
|
@@ -548,7 +579,7 @@ const factory = (crowi) => {
|
|
|
});
|
|
});
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.statics.resetPasswordByRandomString = async function(id) {
|
|
|
|
|
|
|
+ userSchema.statics.resetPasswordByRandomString = async function (id) {
|
|
|
const user = await this.findById(id);
|
|
const user = await this.findById(id);
|
|
|
|
|
|
|
|
if (!user) {
|
|
if (!user) {
|
|
@@ -562,7 +593,8 @@ const factory = (crowi) => {
|
|
|
return newPassword;
|
|
return newPassword;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.statics.createUserByEmail = async function(email) {
|
|
|
|
|
|
|
+ userSchema.statics.createUserByEmail = async function (email) {
|
|
|
|
|
+ // biome-ignore lint/complexity/noUselessThisAlias: ignore
|
|
|
const User = this;
|
|
const User = this;
|
|
|
const newUser = new User();
|
|
const newUser = new User();
|
|
|
|
|
|
|
@@ -588,21 +620,28 @@ const factory = (crowi) => {
|
|
|
password,
|
|
password,
|
|
|
user: newUserData,
|
|
user: newUserData,
|
|
|
};
|
|
};
|
|
|
- }
|
|
|
|
|
- catch (err) {
|
|
|
|
|
|
|
+ } catch (err) {
|
|
|
return {
|
|
return {
|
|
|
email,
|
|
email,
|
|
|
};
|
|
};
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.statics.createUsersByEmailList = async function(emailList) {
|
|
|
|
|
|
|
+ userSchema.statics.createUsersByEmailList = async function (emailList) {
|
|
|
|
|
+ // biome-ignore lint/complexity/noUselessThisAlias: ignore
|
|
|
const User = this;
|
|
const User = this;
|
|
|
|
|
|
|
|
// check exists and get list of try to create
|
|
// check exists and get list of try to create
|
|
|
- const existingUserList = await User.find({ email: { $in: emailList }, userStatus: { $ne: STATUS_DELETED } });
|
|
|
|
|
- const existingEmailList = existingUserList.map((user) => { return user.email });
|
|
|
|
|
- const creationEmailList = emailList.filter((email) => { return existingEmailList.indexOf(email) === -1 });
|
|
|
|
|
|
|
+ const existingUserList = await User.find({
|
|
|
|
|
+ email: { $in: emailList },
|
|
|
|
|
+ userStatus: { $ne: STATUS_DELETED },
|
|
|
|
|
+ });
|
|
|
|
|
+ const existingEmailList = existingUserList.map((user) => {
|
|
|
|
|
+ return user.email;
|
|
|
|
|
+ });
|
|
|
|
|
+ const creationEmailList = emailList.filter((email) => {
|
|
|
|
|
+ return existingEmailList.indexOf(email) === -1;
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
const createdUserList = [];
|
|
const createdUserList = [];
|
|
|
const failedToCreateUserEmailList = [];
|
|
const failedToCreateUserEmailList = [];
|
|
@@ -612,8 +651,7 @@ const factory = (crowi) => {
|
|
|
// eslint-disable-next-line no-await-in-loop
|
|
// eslint-disable-next-line no-await-in-loop
|
|
|
const createdUser = await this.createUserByEmail(email);
|
|
const createdUser = await this.createUserByEmail(email);
|
|
|
createdUserList.push(createdUser);
|
|
createdUserList.push(createdUser);
|
|
|
- }
|
|
|
|
|
- catch (err) {
|
|
|
|
|
|
|
+ } catch (err) {
|
|
|
logger.error(err);
|
|
logger.error(err);
|
|
|
failedToCreateUserEmailList.push({
|
|
failedToCreateUserEmailList.push({
|
|
|
email,
|
|
email,
|
|
@@ -625,12 +663,22 @@ const factory = (crowi) => {
|
|
|
return { createdUserList, existingEmailList, failedToCreateUserEmailList };
|
|
return { createdUserList, existingEmailList, failedToCreateUserEmailList };
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.statics.createUserByEmailAndPasswordAndStatus = async function(name, username, email, password, lang, status, callback) {
|
|
|
|
|
|
|
+ userSchema.statics.createUserByEmailAndPasswordAndStatus = async function (
|
|
|
|
|
+ name,
|
|
|
|
|
+ username,
|
|
|
|
|
+ email,
|
|
|
|
|
+ password,
|
|
|
|
|
+ lang,
|
|
|
|
|
+ status,
|
|
|
|
|
+ callback,
|
|
|
|
|
+ ) {
|
|
|
|
|
+ // biome-ignore lint/complexity/noUselessThisAlias: ignore
|
|
|
const User = this;
|
|
const User = this;
|
|
|
const newUser = new User();
|
|
const newUser = new User();
|
|
|
|
|
|
|
|
// check user upper limit
|
|
// check user upper limit
|
|
|
- const isUserCountExceedsUpperLimit = await User.isUserCountExceedsUpperLimit();
|
|
|
|
|
|
|
+ const isUserCountExceedsUpperLimit =
|
|
|
|
|
+ await User.isUserCountExceedsUpperLimit();
|
|
|
if (isUserCountExceedsUpperLimit) {
|
|
if (isUserCountExceedsUpperLimit) {
|
|
|
const err = new UserUpperLimitException();
|
|
const err = new UserUpperLimitException();
|
|
|
return callback(err);
|
|
return callback(err);
|
|
@@ -651,7 +699,9 @@ const factory = (crowi) => {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Default email show/hide is up to the administrator
|
|
// Default email show/hide is up to the administrator
|
|
|
- newUser.isEmailPublished = configManager.getConfig('customize:isEmailPublishedForNewUser');
|
|
|
|
|
|
|
+ newUser.isEmailPublished = configManager.getConfig(
|
|
|
|
|
+ 'customize:isEmailPublishedForNewUser',
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
const globalLang = configManager.getConfig('app:globalLang');
|
|
const globalLang = configManager.getConfig('app:globalLang');
|
|
|
if (globalLang != null) {
|
|
if (globalLang != null) {
|
|
@@ -680,8 +730,23 @@ const factory = (crowi) => {
|
|
|
* A wrapper function of createUserByEmailAndPasswordAndStatus with callback
|
|
* A wrapper function of createUserByEmailAndPasswordAndStatus with callback
|
|
|
*
|
|
*
|
|
|
*/
|
|
*/
|
|
|
- userSchema.statics.createUserByEmailAndPassword = function(name, username, email, password, lang, callback) {
|
|
|
|
|
- this.createUserByEmailAndPasswordAndStatus(name, username, email, password, lang, undefined, callback);
|
|
|
|
|
|
|
+ userSchema.statics.createUserByEmailAndPassword = function (
|
|
|
|
|
+ name,
|
|
|
|
|
+ username,
|
|
|
|
|
+ email,
|
|
|
|
|
+ password,
|
|
|
|
|
+ lang,
|
|
|
|
|
+ callback,
|
|
|
|
|
+ ) {
|
|
|
|
|
+ this.createUserByEmailAndPasswordAndStatus(
|
|
|
|
|
+ name,
|
|
|
|
|
+ username,
|
|
|
|
|
+ email,
|
|
|
|
|
+ password,
|
|
|
|
|
+ lang,
|
|
|
|
|
+ undefined,
|
|
|
|
|
+ callback,
|
|
|
|
|
+ );
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -689,20 +754,36 @@ const factory = (crowi) => {
|
|
|
*
|
|
*
|
|
|
* @return {Promise<User>}
|
|
* @return {Promise<User>}
|
|
|
*/
|
|
*/
|
|
|
- userSchema.statics.createUser = function(name, username, email, password, lang, status) {
|
|
|
|
|
|
|
+ userSchema.statics.createUser = function (
|
|
|
|
|
+ name,
|
|
|
|
|
+ username,
|
|
|
|
|
+ email,
|
|
|
|
|
+ password,
|
|
|
|
|
+ lang,
|
|
|
|
|
+ status,
|
|
|
|
|
+ ) {
|
|
|
|
|
+ // biome-ignore lint/complexity/noUselessThisAlias: ignore
|
|
|
const User = this;
|
|
const User = this;
|
|
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
return new Promise((resolve, reject) => {
|
|
|
- User.createUserByEmailAndPasswordAndStatus(name, username, email, password, lang, status, (err, userData) => {
|
|
|
|
|
- if (err) {
|
|
|
|
|
- return reject(err);
|
|
|
|
|
- }
|
|
|
|
|
- return resolve(userData);
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ User.createUserByEmailAndPasswordAndStatus(
|
|
|
|
|
+ name,
|
|
|
|
|
+ username,
|
|
|
|
|
+ email,
|
|
|
|
|
+ password,
|
|
|
|
|
+ lang,
|
|
|
|
|
+ status,
|
|
|
|
|
+ (err, userData) => {
|
|
|
|
|
+ if (err) {
|
|
|
|
|
+ return reject(err);
|
|
|
|
|
+ }
|
|
|
|
|
+ return resolve(userData);
|
|
|
|
|
+ },
|
|
|
|
|
+ );
|
|
|
});
|
|
});
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.statics.isExistUserByUserPagePath = async function(path) {
|
|
|
|
|
|
|
+ userSchema.statics.isExistUserByUserPagePath = async function (path) {
|
|
|
const username = pagePathUtils.getUsernameByPath(path);
|
|
const username = pagePathUtils.getUsernameByPath(path);
|
|
|
|
|
|
|
|
if (username == null) {
|
|
if (username == null) {
|
|
@@ -713,7 +794,7 @@ const factory = (crowi) => {
|
|
|
return user != null;
|
|
return user != null;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.statics.updateIsInvitationEmailSended = async function(id) {
|
|
|
|
|
|
|
+ userSchema.statics.updateIsInvitationEmailSended = async function (id) {
|
|
|
const user = await this.findById(id);
|
|
const user = await this.findById(id);
|
|
|
|
|
|
|
|
if (user == null) {
|
|
if (user == null) {
|
|
@@ -728,7 +809,7 @@ const factory = (crowi) => {
|
|
|
user.save();
|
|
user.save();
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.statics.findUserBySlackMemberId = async function(slackMemberId) {
|
|
|
|
|
|
|
+ userSchema.statics.findUserBySlackMemberId = async function (slackMemberId) {
|
|
|
const user = this.findOne({ slackMemberId });
|
|
const user = this.findOne({ slackMemberId });
|
|
|
if (user == null) {
|
|
if (user == null) {
|
|
|
throw new Error('User not found');
|
|
throw new Error('User not found');
|
|
@@ -736,7 +817,9 @@ const factory = (crowi) => {
|
|
|
return user;
|
|
return user;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.statics.findUsersBySlackMemberIds = async function(slackMemberIds) {
|
|
|
|
|
|
|
+ userSchema.statics.findUsersBySlackMemberIds = async function (
|
|
|
|
|
+ slackMemberIds,
|
|
|
|
|
+ ) {
|
|
|
const users = this.find({ slackMemberId: { $in: slackMemberIds } });
|
|
const users = this.find({ slackMemberId: { $in: slackMemberIds } });
|
|
|
if (users.length === 0) {
|
|
if (users.length === 0) {
|
|
|
throw new Error('No user found');
|
|
throw new Error('No user found');
|
|
@@ -744,30 +827,36 @@ const factory = (crowi) => {
|
|
|
return users;
|
|
return users;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- userSchema.statics.findUserByUsernameRegexWithTotalCount = async function(username, status, option) {
|
|
|
|
|
|
|
+ userSchema.statics.findUserByUsernameRegexWithTotalCount = async function (
|
|
|
|
|
+ username,
|
|
|
|
|
+ status,
|
|
|
|
|
+ option,
|
|
|
|
|
+ ) {
|
|
|
const opt = option || {};
|
|
const opt = option || {};
|
|
|
const sortOpt = opt.sortOpt || { username: 1 };
|
|
const sortOpt = opt.sortOpt || { username: 1 };
|
|
|
const offset = opt.offset || 0;
|
|
const offset = opt.offset || 0;
|
|
|
const limit = opt.limit || 10;
|
|
const limit = opt.limit || 10;
|
|
|
|
|
|
|
|
- const conditions = { username: { $regex: username, $options: 'i' }, status: { $in: status } };
|
|
|
|
|
|
|
+ const conditions = {
|
|
|
|
|
+ username: { $regex: username, $options: 'i' },
|
|
|
|
|
+ status: { $in: status },
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
const users = await this.find(conditions)
|
|
const users = await this.find(conditions)
|
|
|
.sort(sortOpt)
|
|
.sort(sortOpt)
|
|
|
.skip(offset)
|
|
.skip(offset)
|
|
|
.limit(limit);
|
|
.limit(limit);
|
|
|
|
|
|
|
|
- const totalCount = (await this.find(conditions).distinct('username')).length;
|
|
|
|
|
|
|
+ const totalCount = (await this.find(conditions).distinct('username'))
|
|
|
|
|
+ .length;
|
|
|
|
|
|
|
|
return { users, totalCount };
|
|
return { users, totalCount };
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
class UserUpperLimitException {
|
|
class UserUpperLimitException {
|
|
|
-
|
|
|
|
|
constructor() {
|
|
constructor() {
|
|
|
this.name = this.constructor.name;
|
|
this.name = this.constructor.name;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
userSchema.statics.STATUS_REGISTERED = STATUS_REGISTERED;
|
|
userSchema.statics.STATUS_REGISTERED = STATUS_REGISTERED;
|
|
@@ -775,7 +864,8 @@ const factory = (crowi) => {
|
|
|
userSchema.statics.STATUS_SUSPENDED = STATUS_SUSPENDED;
|
|
userSchema.statics.STATUS_SUSPENDED = STATUS_SUSPENDED;
|
|
|
userSchema.statics.STATUS_DELETED = STATUS_DELETED;
|
|
userSchema.statics.STATUS_DELETED = STATUS_DELETED;
|
|
|
userSchema.statics.STATUS_INVITED = STATUS_INVITED;
|
|
userSchema.statics.STATUS_INVITED = STATUS_INVITED;
|
|
|
- userSchema.statics.USER_FIELDS_EXCEPT_CONFIDENTIAL = USER_FIELDS_EXCEPT_CONFIDENTIAL;
|
|
|
|
|
|
|
+ userSchema.statics.USER_FIELDS_EXCEPT_CONFIDENTIAL =
|
|
|
|
|
+ USER_FIELDS_EXCEPT_CONFIDENTIAL;
|
|
|
userSchema.statics.PAGE_ITEMS = PAGE_ITEMS;
|
|
userSchema.statics.PAGE_ITEMS = PAGE_ITEMS;
|
|
|
|
|
|
|
|
return mongoose.model('User', userSchema);
|
|
return mongoose.model('User', userSchema);
|