initial pass at status support

This commit is contained in:
Wyatt Johnson
2017-11-02 17:16:57 -06:00
parent 1f3722edc1
commit 76a255fb7b
49 changed files with 1112 additions and 1598 deletions
-6
View File
@@ -1,6 +0,0 @@
module.exports = [
'ACTIVE',
'BANNED',
'PENDING',
'APPROVED' // Indicates that the users' username has been approved
];
+25
View File
@@ -0,0 +1,25 @@
module.exports = [
// UNSET is used when the username can be changed, and does not necessarily
// require moderator action to become active. This can be used when the user
// signs up with a social login and has the option of setting their own
// username.
'UNSET',
// SET is used when the username has been set for the first time, but cannot
// change without the username being rejected by a moderator and that moderator
// agreeing that the username should be allowed to change.
'SET',
// APPROVED is used when the username was changed, and subsequently approved by
// said moderator.
'APPROVED',
// REJECTED is used when the username was changed, and subsequently rejected by
// said moderator.
'REJECTED',
// CHANGED is used after a user has changed their username after it was
// rejected.
'CHANGED',
];
+107 -34
View File
@@ -10,8 +10,9 @@ const can = require('../perms');
// USER_ROLES is the array of roles that is permissible as a user role.
const USER_ROLES = require('./enum/user_roles');
// USER_STATUS is the list of statuses that are permitted for the user status.
const USER_STATUS = require('./enum/user_status');
// USER_STATUS_USERNAME is the list of statuses that are supported by storing
// the username state.
const USER_STATUS_USERNAME = require('./enum/user_status_username');
// ProfileSchema is the mongoose schema defined as the representation of a
// User's profile stored in MongoDB.
@@ -73,10 +74,6 @@ const UserSchema = new Schema({
unique: true
},
// This is true when the user account is disabled, no action should be
// acknowledged when they are disabled. Logins are also prevented.
disabled: Boolean,
// This provides a source of identity proof for users who login using the
// local provider. A local provider will be assumed for users who do not
// have any social profiles.
@@ -97,41 +94,85 @@ const UserSchema = new Schema({
enum: USER_ROLES
}],
// Status provides a string that says in which state the account is.
// When the account is banned, the user login is disabled.
// Status stores the user status information regarding permissions,
// capabilities and moderation state.
status: {
type: String,
enum: USER_STATUS,
default: 'ACTIVE'
},
// Determines whether the user can edit their username.
canEditName: {
type: Boolean,
default: false
},
// Username stores the current user status for the username as well as the
// history of changes.
username: {
// User's suspension details.
suspension: {
until: {
type: Date,
default: null,
// Status stores the current username status.
status: {
type: String,
enum: USER_STATUS_USERNAME,
},
// History stores the history of username status changes.
history: [{
// Status stores the historical username status.
status: {
type: String,
enum: USER_STATUS_USERNAME,
},
// assigned_by stores the user id of the user who assigned this status.
assigned_by: {type: String, default: null},
// created_at stores the date when this status was assigned.
created_at: {type: Date, default: Date.now}
}],
},
},
// User's settings
settings: {
bio: {
type: String,
default: ''
// Banned stores the current user banned status as well as the history of
// changes.
banned: {
// Status stores the current user banned status.
status: {
type: Boolean,
required: true,
default: false,
},
history: [{
// Status stores the historical banned status.
status: Boolean,
// assigned_by stores the user id of the user who assigned this status.
assigned_by: {type: String, default: null},
// created_at stores the date when this status was assigned.
created_at: {type: Date, default: Date.now}
}],
},
// Suspension stores the current user suspension status as well as the
// history of changes.
suspension: {
// until is the date that the user is suspended until.
until: {
type: Date,
default: null,
},
history: [{
// until is the date that the user is suspended until.
until: Date,
// assigned_by stores the user id of the user who assigned this status.
assigned_by: {type: String, default: null},
// created_at stores the date when this status was assigned.
created_at: {type: Date, default: Date.now}
}]
}
},
ignoresUsers: [{
// user id of another user
type: String,
}],
// IgnoresUsers is an array of user id's that the current user is ignoring.
ignoresUsers: [String],
// Tags are added by the self or by administrators.
tags: [TagLinkSchema],
@@ -158,7 +199,7 @@ const UserSchema = new Schema({
}
});
// Add the indixies on the user profile data.
// Add the index on the user profile data.
UserSchema.index({
'profiles.id': 1,
'profiles.provider': 1
@@ -201,6 +242,38 @@ UserSchema.method('can', function(...actions) {
return can(this, ...actions);
});
/**
* banned returns true when the user is currently banned, and sets the banned
* status locally.
*/
UserSchema.virtual('banned')
.get(function() {
return this.status.banned.status;
})
.set(function(status) {
this.status.banned.status = status;
this.status.banned.history.push({
status,
created_at: new Date()
});
});
/**
* suspended returns true when the user is currently suspended, and sets the
* suspension status locally.
*/
UserSchema.virtual('suspended')
.get(function() {
return Boolean(this.status.suspension.until && this.status.suspension.until > new Date());
})
.set(function(until) {
this.status.suspension.until = until;
this.status.suspension.history.push({
until,
created_at: new Date()
});
});
// Create the User model.
const UserModel = mongoose.model('User', UserSchema);