Admin panel:

Only invited user can register in strict mode,
Set mail server in admin panel,
Switch strict mode in admin panel,
Invite people to system in admin panel
This commit is contained in:
lkisme 2017-02-24 22:10:38 +08:00
parent 29fdfb9c88
commit 1dfb6ef477
20 changed files with 638 additions and 10 deletions

45
models/invitationCodes.js Normal file
View file

@ -0,0 +1,45 @@
InvitationCodes = new Mongo.Collection('invitation_codes');
InvitationCodes.attachSchema(new SimpleSchema({
code: {
type: String,
},
email: {
type: String,
unique: true,
regEx: SimpleSchema.RegEx.Email,
},
createdAt: {
type: Date,
denyUpdate: false,
},
// always be the admin if only one admin
authorId: {
type: String,
},
boardsToBeInvited: {
type: [String],
optional: true,
},
valid: {
type: Boolean,
defaultValue: true,
},
}));
InvitationCodes.helpers({
author(){
return Users.findOne(this.authorId);
},
});
// InvitationCodes.before.insert((userId, doc) => {
// doc.createdAt = new Date();
// doc.authorId = userId;
// });
if (Meteor.isServer) {
Boards.deny({
fetch: ['members'],
});
}

111
models/settings.js Normal file
View file

@ -0,0 +1,111 @@
Settings = new Mongo.Collection('settings');
Settings.attachSchema(new SimpleSchema({
strict: {
type: Boolean,
},
'mailServer.username': {
type: String,
},
'mailServer.password': {
type: String,
},
'mailServer.host': {
type: String,
},
'mailServer.port': {
type: String,
},
'mailServer.from': {
type: String,
defaultValue: 'Kanban',
},
createdAt: {
type: Date,
denyUpdate: true,
},
modifiedAt: {
type: Date,
},
}));
Settings.helpers({
mailUrl () {
const mailUrl = `smtp://${this.mailServer.username}:${this.mailServer.password}@${this.mailServer.host}:${this.mailServer.port}/`;
return mailUrl;
},
});
Settings.allow({
update(userId) {
const user = Users.findOne(userId);
return user && user.isAdmin;
},
});
Settings.before.update((userId, doc, fieldNames, modifier) => {
modifier.$set = modifier.$set || {};
modifier.$set.modifiedAt = new Date();
});
if (Meteor.isServer) {
Meteor.startup(() => {
const setting = Settings.findOne({});
if(!setting){
const now = new Date();
const defaultSetting = {strict: false, mailServer: {
username: '', password:'', host: '', port:'', from: '',
}, createdAt: now, modifiedAt: now};
Settings.insert(defaultSetting);
}
const newSetting = Settings.findOne();
process.env.MAIL_URL = newSetting.mailUrl();
Accounts.emailTemplates.from = newSetting.mailServer.from;
});
function getRandomNum (min, max) {
const range = max - min;
const rand = Math.random();
return (min + Math.round(rand * range));
}
function sendInvitationEmail (_id){
const icode = InvitationCodes.findOne(_id);
const author = Users.findOne(Meteor.userId());
try {
const params = {
email: icode.email,
inviter: Users.findOne(icode.authorId).username,
user: icode.email.split('@')[0],
icode: icode.code,
url: FlowRouter.url('sign-up'),
};
const lang = author.getLanguage();
Email.send({
to: icode.email,
from: Accounts.emailTemplates.from,
subject: TAPi18n.__('email-invite-register-subject', params, lang),
text: TAPi18n.__('email-invite-register-text', params, lang),
});
} catch (e) {
throw new Meteor.Error('email-fail', e.message);
}
}
Meteor.methods({
sendInvitation(emails, boards) {
check(emails, [String]);
check(boards, [String]);
const user = Users.findOne(Meteor.userId());
if(!user.isAdmin){
throw new Meteor.Error('not-allowed');
}
emails.forEach((email) => {
if (email && SimpleSchema.RegEx.Email.test(email)) {
const code = getRandomNum(100000, 999999);
InvitationCodes.insert({code, email, boardsToBeInvited: boards, createdAt: new Date(), authorId: Meteor.userId()}, function(err, _id){
if(!err && _id) sendInvitationEmail(_id);
});
}
});
},
});
}

View file

@ -348,7 +348,7 @@ if (Meteor.isServer) {
if (user._id === inviter._id) throw new Meteor.Error('error-user-notAllowSelf');
} else {
if (posAt <= 0) throw new Meteor.Error('error-user-doesNotExist');
if (Settings.findOne().strict) throw new Meteor.Error('error-user-notCreated');
const email = username;
username = email.substring(0, posAt);
const newUserId = Accounts.createUser({ username, email });
@ -389,6 +389,28 @@ if (Meteor.isServer) {
return { username: user.username, email: user.emails[0].address };
},
});
Accounts.onCreateUser((options, user) => {
const userCount = Users.find().count();
if (userCount === 0){
user.isAdmin = true;
return user;
}
const strict = Settings.findOne().strict;
if (!strict) {
return user;
}
const iCode = options.profile.invitationcode | '';
const invitationCode = InvitationCodes.findOne({code: iCode, valid:true});
if (!invitationCode) {
throw new Meteor.Error('error-invitation-code-not-exist');
}else{
user.profile = {icode: options.profile.invitationcode};
}
return user;
});
}
if (Meteor.isServer) {
@ -458,4 +480,25 @@ if (Meteor.isServer) {
});
});
}
Users.after.insert((userId, doc) => {
//invite user to corresponding boards
const strict = Settings.findOne().strict;
if (strict) {
const user = Users.findOne(doc._id);
const invitationCode = InvitationCodes.findOne({code: user.profile.icode, valid:true});
if (!invitationCode) {
throw new Meteor.Error('error-user-notCreated');
}else{
invitationCode.boardsToBeInvited.forEach((boardId) => {
const board = Boards.findOne(boardId);
board.addMember(doc._id);
});
user.profile = {invitedBoards: invitationCode.boardsToBeInvited};
InvitationCodes.update(invitationCode._id, {$set: {valid:false}});
}
}
});
}