mirror of
https://github.com/wekan/wekan.git
synced 2025-09-22 01:50:48 +02:00
Fix merge conflict.
This commit is contained in:
commit
7c9a30d8fe
19 changed files with 658 additions and 8 deletions
|
@ -119,6 +119,8 @@
|
|||
"allowIsBoardMember": true,
|
||||
"allowIsBoardMemberByCard": true,
|
||||
"Emoji": true,
|
||||
"Checklists": true
|
||||
"Checklists": true,
|
||||
"Settings": true,
|
||||
"InvitationCodes": true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
Meteor.subscribe('boards');
|
||||
Meteor.subscribe('setting');
|
||||
Meteor.subscribe('user-admin');
|
||||
|
||||
BlazeLayout.setRoot('body');
|
||||
|
||||
|
|
5
client/components/settings/invitationCode.jade
Normal file
5
client/components/settings/invitationCode.jade
Normal file
|
@ -0,0 +1,5 @@
|
|||
template(name='invitationCode')
|
||||
.at-input#invitationcode
|
||||
label(for='at-field-code') {{_ 'invitation-code'}}
|
||||
|
||||
input#at-field-invitationcode(type="text" name='at-field-invitationcode' placeholder="{{_ 'invitation-code'}}")
|
6
client/components/settings/invitationCode.js
Normal file
6
client/components/settings/invitationCode.js
Normal file
|
@ -0,0 +1,6 @@
|
|||
Template.invitationCode.onRendered(() => {
|
||||
const disableRegistration = Settings.findOne().disableRegistration;
|
||||
if(!disableRegistration){
|
||||
$('#invitationcode').hide();
|
||||
}
|
||||
});
|
71
client/components/settings/settingBody.jade
Normal file
71
client/components/settings/settingBody.jade
Normal file
|
@ -0,0 +1,71 @@
|
|||
template(name="setting")
|
||||
.setting-content
|
||||
.content-title
|
||||
span {{_ 'settings'}}
|
||||
.content-body
|
||||
.side-menu
|
||||
ul
|
||||
li.active
|
||||
a.js-setting-menu(data-id="registration-setting") {{_ 'registration'}}
|
||||
li
|
||||
a.js-setting-menu(data-id="email-setting") {{_ 'email'}}
|
||||
.main-body
|
||||
if loading.get
|
||||
+spinner
|
||||
else if generalSetting.get
|
||||
+general
|
||||
else if emailSetting.get
|
||||
+email
|
||||
|
||||
template(name="general")
|
||||
ul#registration-setting.setting-detail
|
||||
li
|
||||
a.flex.js-toggle-registration
|
||||
.materialCheckBox(class="{{#if currentSetting.disableRegistration}}is-checked{{/if}}")
|
||||
|
||||
span {{_ 'disable-self-registration'}}
|
||||
li
|
||||
.invite-people(class="{{#if currentSetting.disableRegistration}}{{else}}hide{{/if}}")
|
||||
ul
|
||||
li
|
||||
.title {{_ 'invite-people'}}
|
||||
textarea#email-to-invite.form-control(rows='5', placeholder="{{_ 'email-addresses'}}")
|
||||
li
|
||||
.title {{_ 'to-boards'}}
|
||||
.bg-white
|
||||
each boards
|
||||
a.option.flex.js-toggle-board-choose(id= _id)
|
||||
.materialCheckBox(data-id= _id)
|
||||
|
||||
span= title
|
||||
|
||||
li
|
||||
button.js-email-invite.primary {{_ 'invite'}}
|
||||
|
||||
template(name='email')
|
||||
ul#email-setting.setting-detail
|
||||
li.smtp-form
|
||||
.title {{_ 'smtp-host'}}
|
||||
.description {{_ 'smtp-host-description'}}
|
||||
.form-group
|
||||
input.form-control#mail-server-host(type="text", placeholder="smtp.domain.com" value="{{currentSetting.mailServer.host}}")
|
||||
li.smtp-form
|
||||
.title {{_ 'smtp-port'}}
|
||||
.description {{_ 'smtp-port-description'}}
|
||||
.form-group
|
||||
input.form-control#mail-server-port(type="text", placeholder="25" value="{{currentSetting.mailServer.port}}")
|
||||
li.smtp-form
|
||||
.title {{_ 'smtp-username'}}
|
||||
.form-group
|
||||
input.form-control#mail-server-username(type="text", placeholder="{{_ 'username'}}" value="{{currentSetting.mailServer.username}}")
|
||||
li.smtp-form
|
||||
.title {{_ 'smtp-password'}}
|
||||
.form-group
|
||||
input.form-control#mail-server-password(type="text", placeholder="{{_ 'password'}}" value="{{currentSetting.mailServer.password}}")
|
||||
li.smtp-form
|
||||
.title {{_ 'send-from'}}
|
||||
.form-group
|
||||
input.form-control#mail-server-from(type="email", placeholder="no-reply@domain.com" value="{{currentSetting.mailServer.from}}")
|
||||
|
||||
li
|
||||
button.js-save.primary Save
|
128
client/components/settings/settingBody.js
Normal file
128
client/components/settings/settingBody.js
Normal file
|
@ -0,0 +1,128 @@
|
|||
Meteor.subscribe('setting');
|
||||
Meteor.subscribe('mailServer');
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.error = new ReactiveVar('');
|
||||
this.loading = new ReactiveVar(false);
|
||||
this.generalSetting = new ReactiveVar(true);
|
||||
this.emailSetting = new ReactiveVar(false);
|
||||
},
|
||||
|
||||
setError(error) {
|
||||
this.error.set(error);
|
||||
},
|
||||
|
||||
setLoading(w) {
|
||||
this.loading.set(w);
|
||||
},
|
||||
|
||||
checkField(selector) {
|
||||
const value = $(selector).val();
|
||||
if(!value || value.trim() === ''){
|
||||
$(selector).parents('li.smtp-form').addClass('has-error');
|
||||
throw Error('blank field');
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
},
|
||||
|
||||
currentSetting(){
|
||||
return Settings.findOne();
|
||||
},
|
||||
|
||||
boards() {
|
||||
return Boards.find({
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
'members.isAdmin': true,
|
||||
}, {
|
||||
sort: ['title'],
|
||||
});
|
||||
},
|
||||
toggleRegistration(){
|
||||
this.setLoading(true);
|
||||
const registrationClosed = this.currentSetting().disableRegistration;
|
||||
Settings.update(Settings.findOne()._id, {$set:{disableRegistration: !registrationClosed}});
|
||||
this.setLoading(false);
|
||||
if(registrationClosed){
|
||||
$('.invite-people').slideUp();
|
||||
}else{
|
||||
$('.invite-people').slideDown();
|
||||
}
|
||||
},
|
||||
|
||||
switchMenu(event){
|
||||
const target = $(event.target);
|
||||
if(!target.hasClass('active')){
|
||||
$('.side-menu li.active').removeClass('active');
|
||||
target.parent().addClass('active');
|
||||
const targetID = target.data('id');
|
||||
this.generalSetting.set('registration-setting' === targetID);
|
||||
this.emailSetting.set('email-setting' === targetID);
|
||||
}
|
||||
},
|
||||
|
||||
checkBoard(event){
|
||||
let target = $(event.target);
|
||||
if(!target.hasClass('js-toggle-board-choose')){
|
||||
target = target.parent();
|
||||
}
|
||||
const checkboxId = target.attr('id');
|
||||
$(`#${checkboxId} .materialCheckBox`).toggleClass('is-checked');
|
||||
$(`#${checkboxId}`).toggleClass('is-checked');
|
||||
},
|
||||
|
||||
inviteThroughEmail(){
|
||||
const emails = $('#email-to-invite').val().trim().split('\n').join(',').split(',');
|
||||
const boardsToInvite = [];
|
||||
$('.js-toggle-board-choose .materialCheckBox.is-checked').each(function () {
|
||||
boardsToInvite.push($(this).data('id'));
|
||||
});
|
||||
const validEmails = [];
|
||||
emails.forEach((email) => {
|
||||
if (email && SimpleSchema.RegEx.Email.test(email.trim())) {
|
||||
validEmails.push(email.trim());
|
||||
}
|
||||
});
|
||||
if (validEmails.length) {
|
||||
this.setLoading(true);
|
||||
Meteor.call('sendInvitation', validEmails, boardsToInvite, () => {
|
||||
// if (!err) {
|
||||
// TODO - show more info to user
|
||||
// }
|
||||
this.setLoading(false);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
saveMailServerInfo(){
|
||||
this.setLoading(true);
|
||||
$('li').removeClass('has-error');
|
||||
|
||||
try{
|
||||
const host = this.checkField('#mail-server-host');
|
||||
const port = this.checkField('#mail-server-port');
|
||||
const username = this.checkField('#mail-server-username');
|
||||
const password = this.checkField('#mail-server-password');
|
||||
const from = this.checkField('#mail-server-from');
|
||||
Settings.update(Settings.findOne()._id, {$set:{'mailServer.host':host, 'mailServer.port': port, 'mailServer.username': username,
|
||||
'mailServer.password': password, 'mailServer.from': from}});
|
||||
} catch (e) {
|
||||
return;
|
||||
} finally {
|
||||
this.setLoading(false);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
events(){
|
||||
return [{
|
||||
'click a.js-toggle-registration': this.toggleRegistration,
|
||||
'click a.js-setting-menu': this.switchMenu,
|
||||
'click a.js-toggle-board-choose': this.checkBoard,
|
||||
'click button.js-email-invite': this.inviteThroughEmail,
|
||||
'click button.js-save': this.saveMailServerInfo,
|
||||
}];
|
||||
},
|
||||
}).register('setting');
|
112
client/components/settings/settingBody.styl
Normal file
112
client/components/settings/settingBody.styl
Normal file
|
@ -0,0 +1,112 @@
|
|||
.flex
|
||||
display: -webkit-box
|
||||
display: -moz-box
|
||||
display: -webkit-flex
|
||||
display: -moz-flex
|
||||
display: -ms-flexbox
|
||||
display: flex
|
||||
|
||||
.setting-content
|
||||
padding 30px
|
||||
color: #727479
|
||||
background: #dedede
|
||||
width 100%
|
||||
height 100%
|
||||
position: absolute;
|
||||
|
||||
.content-title
|
||||
font-size 20px
|
||||
|
||||
.content-body
|
||||
display flex
|
||||
padding-top 15px
|
||||
height 100%
|
||||
|
||||
.side-menu
|
||||
background-color: #f7f7f7;
|
||||
border: 1px solid #f0f0f0;
|
||||
border-radius: 4px;
|
||||
width: 250px;
|
||||
box-shadow: inset -1px -1px 3px rgba(0,0,0,.05);
|
||||
|
||||
ul
|
||||
|
||||
li
|
||||
margin: 0.1rem 0.2rem;
|
||||
|
||||
&.active
|
||||
background #fff
|
||||
box-shadow 0 1px 2px rgba(0,0,0,0.15);
|
||||
|
||||
&:hover
|
||||
background #fff
|
||||
box-shadow 0 1px 2px rgba(0,0,0,0.15);
|
||||
a
|
||||
@extends .flex
|
||||
padding: 1rem 0 1rem 1rem
|
||||
width: 100% - 5rem
|
||||
|
||||
|
||||
span
|
||||
font-size: 13px
|
||||
|
||||
.main-body
|
||||
padding: 0.1em 1em
|
||||
|
||||
ul
|
||||
li
|
||||
padding: 0.5rem 0.5rem;
|
||||
|
||||
a
|
||||
.is-checked
|
||||
border-bottom: 2px solid #2980b9;
|
||||
border-right: 2px solid #2980b9;
|
||||
|
||||
span
|
||||
padding: 0 0.5rem
|
||||
|
||||
.invite-people
|
||||
padding-left 20px;
|
||||
li
|
||||
min-width: 500px;
|
||||
|
||||
ul.no-margin-bottom
|
||||
margin-bottom: 0;
|
||||
|
||||
.bg-white
|
||||
a
|
||||
background #f7f7f7
|
||||
&.is-checked
|
||||
background #fff
|
||||
|
||||
|
||||
.option
|
||||
@extends .flex
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
background: #fff;
|
||||
text-decoration: none;
|
||||
-webkit-box-shadow: 0 1px 2px rgba(0,0,0,0.2);
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,0.2);
|
||||
margin-top: 5px;
|
||||
padding: 5px;
|
||||
|
||||
.title
|
||||
font-weight 700;
|
||||
margin-bottom 0.5rem;
|
||||
.description
|
||||
margin-bottom 0.5rem;
|
||||
.bg-white
|
||||
background #f9fbfc;
|
||||
|
||||
.form-control.has-error
|
||||
border-color: #a94442;
|
||||
box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
|
||||
|
||||
li.has-error
|
||||
color #a94442
|
||||
.form-group
|
||||
.form-control
|
||||
border-color: #a94442;
|
||||
box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
|
||||
|
21
client/components/settings/settingHeader.jade
Normal file
21
client/components/settings/settingHeader.jade
Normal file
|
@ -0,0 +1,21 @@
|
|||
template(name="settingHeaderBar")
|
||||
h1.header-setting-menu
|
||||
span {{_ 'admin-panel'}}
|
||||
|
||||
.setting-header-btns.left
|
||||
unless isMiniScreen
|
||||
unless isSandstorm
|
||||
if currentUser
|
||||
a.setting-header-btn.settings.active
|
||||
i.fa(class="fa-cog")
|
||||
span {{_ 'settings'}}
|
||||
//TODO
|
||||
// a.setting-header-btn.people
|
||||
// i.fa(class="fa-users")
|
||||
// span {{_ 'people'}}
|
||||
|
||||
else
|
||||
a.setting-header-btn.js-log-in(
|
||||
title="{{_ 'log-in'}}")
|
||||
i.fa.fa-sign-in
|
||||
span {{_ 'log-in'}}
|
25
client/components/settings/settingHeader.styl
Normal file
25
client/components/settings/settingHeader.styl
Normal file
|
@ -0,0 +1,25 @@
|
|||
#header #header-main-bar .setting-header-btn
|
||||
&.active,
|
||||
&:hover:not(.is-disabled)
|
||||
background: rgba(0, 0, 0, .15)
|
||||
color: darken(white, 5%)
|
||||
margin-left: 20px;
|
||||
padding-right: 10px;
|
||||
height: 28px;
|
||||
font-size: 13px;
|
||||
float: left;
|
||||
overflow: hidden;
|
||||
line-height: @height;
|
||||
margin: 0 2px;
|
||||
|
||||
i.fa
|
||||
float: left
|
||||
display: block
|
||||
line-height: 28px
|
||||
color: darken(white, 5%)
|
||||
margin: 0 10px
|
||||
|
||||
+ span
|
||||
display: inline-block
|
||||
margin-top: 1px
|
||||
margin-right: 10px
|
|
@ -17,6 +17,8 @@ template(name="memberMenuPopup")
|
|||
li: a.js-change-password {{_ 'changePasswordPopup-title'}}
|
||||
li: a.js-change-language {{_ 'changeLanguagePopup-title'}}
|
||||
li: a.js-edit-notification {{_ 'editNotificationPopup-title'}}
|
||||
if currentUser.isAdmin
|
||||
li: a.js-go-setting(href='/setting') {{_ 'admin-panel'}}
|
||||
hr
|
||||
ul.pop-over-list
|
||||
li: a.js-logout {{_ 'log-out'}}
|
||||
|
|
|
@ -15,6 +15,9 @@ Template.memberMenuPopup.events({
|
|||
|
||||
AccountsTemplates.logout();
|
||||
},
|
||||
'click .js-go-setting'() {
|
||||
Popup.close();
|
||||
},
|
||||
});
|
||||
|
||||
Template.editProfilePopup.events({
|
||||
|
|
|
@ -1,12 +1,21 @@
|
|||
const passwordField = AccountsTemplates.removeField('password');
|
||||
const emailField = AccountsTemplates.removeField('email');
|
||||
|
||||
AccountsTemplates.addFields([{
|
||||
_id: 'username',
|
||||
type: 'text',
|
||||
displayName: 'username',
|
||||
required: true,
|
||||
minLength: 2,
|
||||
}, emailField, passwordField]);
|
||||
}, emailField, passwordField, {
|
||||
_id: 'invitationcode',
|
||||
type: 'text',
|
||||
displayName: 'Invitation Code',
|
||||
required: false,
|
||||
minLength: 6,
|
||||
errStr: 'Invitation code doesn\'t exist',
|
||||
template: 'invitationCode',
|
||||
}]);
|
||||
|
||||
AccountsTemplates.configure({
|
||||
defaultLayout: 'userFormsLayout',
|
||||
|
@ -48,9 +57,6 @@ AccountsTemplates.configureRoute('changePwd', {
|
|||
});
|
||||
|
||||
if (Meteor.isServer) {
|
||||
if (process.env.MAIL_FROM) {
|
||||
Accounts.emailTemplates.from = process.env.MAIL_FROM;
|
||||
}
|
||||
|
||||
['resetPassword-subject', 'resetPassword-text', 'verifyEmail-subject', 'verifyEmail-text', 'enrollAccount-subject', 'enrollAccount-text'].forEach((str) => {
|
||||
const [templateName, field] = str.split('-');
|
||||
|
@ -63,3 +69,4 @@ if (Meteor.isServer) {
|
|||
};
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -99,6 +99,26 @@ FlowRouter.route('/import', {
|
|||
},
|
||||
});
|
||||
|
||||
FlowRouter.route('/setting', {
|
||||
name: 'setting',
|
||||
triggersEnter: [
|
||||
AccountsTemplates.ensureSignedIn,
|
||||
() => {
|
||||
Session.set('currentBoard', null);
|
||||
Session.set('currentCard', null);
|
||||
|
||||
Filter.reset();
|
||||
EscapeActions.executeAll();
|
||||
},
|
||||
],
|
||||
action() {
|
||||
BlazeLayout.render('defaultLayout', {
|
||||
headerBar: 'settingHeaderBar',
|
||||
content: 'setting',
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
FlowRouter.notFound = {
|
||||
action() {
|
||||
BlazeLayout.render('defaultLayout', { content: 'notFound' });
|
||||
|
|
|
@ -323,5 +323,26 @@
|
|||
"welcome-board": "Welcome Board",
|
||||
"welcome-list1": "Basics",
|
||||
"welcome-list2": "Advanced",
|
||||
"what-to-do": "What do you want to do?"
|
||||
}
|
||||
"what-to-do": "What do you want to do?",
|
||||
"admin-panel": "Admin Panel",
|
||||
"system-setting": "System Setting",
|
||||
"settings": "Settings",
|
||||
"people": "People",
|
||||
"registration": "Registration",
|
||||
"disable-self-registration": "Disable Self-Registration",
|
||||
"invite": "Invite",
|
||||
"invite-people": "Invite People",
|
||||
"to-boards": "To board(s)",
|
||||
"email-addresses":"Email Addresses",
|
||||
"smtp-host-description": "The address of the SMTP server that handles your emails.",
|
||||
"smtp-port-description": "The port your SMTP server uses for outgoing emails.",
|
||||
"smtp-host": "SMTP Host",
|
||||
"smtp-port": "SMTP Port",
|
||||
"smtp-username": "Username",
|
||||
"smtp-password": "Password",
|
||||
"send-from": "From",
|
||||
"invitation-code": "Invitation Code",
|
||||
"email-invite-register-subject": "__inviter__ sent you an invitation",
|
||||
"email-invite-register-text": "Dear __user__,\n\n__inviter__ invites you to Wekan for collaborations.\n\nPlease follow the link below:\n__url__\n\nAnd your invitation code is: __icode__\n\nThanks.\n",
|
||||
"error-invitation-code-not-exist": "Invitation code doesn't exist"
|
||||
}
|
||||
|
|
45
models/invitationCodes.js
Normal file
45
models/invitationCodes.js
Normal 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'],
|
||||
});
|
||||
}
|
116
models/settings.js
Normal file
116
models/settings.js
Normal file
|
@ -0,0 +1,116 @@
|
|||
Settings = new Mongo.Collection('settings');
|
||||
|
||||
Settings.attachSchema(new SimpleSchema({
|
||||
disableRegistration: {
|
||||
type: Boolean,
|
||||
},
|
||||
'mailServer.username': {
|
||||
type: String,
|
||||
optional: true,
|
||||
},
|
||||
'mailServer.password': {
|
||||
type: String,
|
||||
optional: true,
|
||||
},
|
||||
'mailServer.host': {
|
||||
type: String,
|
||||
optional: true,
|
||||
},
|
||||
'mailServer.port': {
|
||||
type: String,
|
||||
optional: true,
|
||||
},
|
||||
'mailServer.from': {
|
||||
type: String,
|
||||
optional: true,
|
||||
defaultValue: 'Wekan',
|
||||
},
|
||||
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 = {disableRegistration: 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);
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
|
@ -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().disableRegistration) throw new Meteor.Error('error-user-notCreated');
|
||||
// Set in lowercase email before creating account
|
||||
const email = username.toLowerCase();
|
||||
username = email.substring(0, posAt);
|
||||
|
@ -390,6 +390,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 disableRegistration = Settings.findOne().disableRegistration;
|
||||
if (!disableRegistration) {
|
||||
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) {
|
||||
|
@ -459,4 +481,25 @@ if (Meteor.isServer) {
|
|||
});
|
||||
});
|
||||
}
|
||||
|
||||
Users.after.insert((userId, doc) => {
|
||||
|
||||
//invite user to corresponding boards
|
||||
const disableRegistration = Settings.findOne().disableRegistration;
|
||||
if (disableRegistration) {
|
||||
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}});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
13
server/publications/settings.js
Normal file
13
server/publications/settings.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
Meteor.publish('setting', () => {
|
||||
return Settings.find({}, {fields:{disableRegistration: 1}});
|
||||
});
|
||||
|
||||
Meteor.publish('mailServer', function () {
|
||||
if (!Match.test(this.userId, String))
|
||||
return [];
|
||||
const user = Users.findOne(this.userId);
|
||||
if(user && user.isAdmin){
|
||||
return Settings.find({}, {fields: {mailServer: 1}});
|
||||
}
|
||||
return [];
|
||||
});
|
|
@ -9,3 +9,11 @@ Meteor.publish('user-miniprofile', function(userId) {
|
|||
},
|
||||
});
|
||||
});
|
||||
|
||||
Meteor.publish('user-admin', function() {
|
||||
return Meteor.users.find(this.userId, {
|
||||
fields: {
|
||||
isAdmin: 1,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue