Commit 536ccf81 by Ali Arshad

Merge branch 'user-registration' into 'master'

Refactor-Custom-email

See merge request jibc/jibc-meteor-api!2
parents f3b4d7c1 61c560b7
......@@ -22,3 +22,4 @@ accounts-password
dburles:collection-helpers
ostrio:files
tunguska:reactive-aggregate
percolate:migrations
......@@ -56,6 +56,7 @@ npm-mongo@3.1.2
ordered-dict@1.1.0
ostrio:cookies@2.4.1
ostrio:files@1.12.2
percolate:migrations@1.0.2
promise@0.11.2
random@1.1.0
rate-limit@1.0.9
......
import { Meteor } from 'meteor/meteor';
import { Roles } from './collections/role';
import { PERMISSIONS } from './config';
export const seedDB = async () => {
// tslint:disable-next-line:ban-ts-ignore
// @ts-ignore
const allPermissions = Object.values(PERMISSIONS);
try {
if (!Roles.find({})
.fetch().length || Roles.find({})
.fetch().length === 0) {
// Roles
await Promise.all([
Roles.insert({
title: 'Admin',
permissions: allPermissions,
description: '',
}).toPromise(),
Roles.insert({
title: 'User',
permissions: [PERMISSIONS.CAN_LOGIN, PERMISSIONS.CAN_UPDATE_OWN_USER],
description: '',
}).toPromise(),
Roles.insert({
title: 'Blocked',
permissions: [],
description: '',
}),
]);
} else {
// Update Roles Permissions
await Promise.all([
Roles
.update({ title: 'Admin' }, { $set: { permissions: allPermissions } })
.toPromise(),
]);
}
if (!Meteor.users.find({})
.fetch().length && Meteor.users.find({})
.fetch().length === 0) {
Accounts.createUser({
username: 'admin',
password: 'admin',
email: 'ali.arshad@vqode.com',
profile: {
name: 'Admin User',
role: Roles.findOne({ title: 'Admin' })._id, // admin role id
},
});
}
} catch (e) {
throw new Meteor.Error('Error while seeding database.');
}
};
import { MongoObservable } from 'meteor-rxjs';
import { RoleModel } from '../models/role.model';
// tslint:disable-next-line:variable-name
export const rolesCollection = new MongoObservable.Collection<RoleModel>('roles');
import { MongoObservable } from 'meteor-rxjs';
import { Role } from '../models/role';
// tslint:disable-next-line:variable-name
export const Roles = new MongoObservable.Collection<Role>('roles');
import { MongoObservable } from 'meteor-rxjs';
export const settingsCollection = new MongoObservable.Collection('setting');
......@@ -6,3 +6,7 @@ export const PERMISSIONS = {
CAN_SEE_ALL_USERS: 'CAN_SEE_ALL_USERS',
CAN_ACCESS_DASHBOARD_PAGE: 'CAN_ACCESS_DASHBOARD_PAGE',
};
export const CONFIG = {
SiteName: 'JIBC',
};
process.env.S3 = '{"path": "files", "key":"AKIAWEWXPEPGGRRUHLH4","secret":"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","bucket":"siingio","region":"us-east-1"}';
process.env.MAIL_URL = 'smtp://postmaster%40mail.vqode.com:VQode1234@smtp.mailgun.org:587';
process.env.appUrl = 'http://localhost:4200/';
import { Meteor } from 'meteor/meteor';
import { seedDB } from './app.seeding';
import { PERMISSIONS } from './config';
import { UtilsService } from './services/utils.service';
Meteor.startup(() => {
const seed = true;
if (seed) {
seedDB();
}
// @ts-ignore
Migrations.migrateTo('latest');
// Validate Login Attempt
Accounts.validateLoginAttempt((data): boolean => {
const user: Meteor.User = data.user;
......
import { Meteor } from 'meteor/meteor';
import { EmailService } from '../services/email.service';
Meteor.methods({
sendForgotPasswordEmail(email: string): boolean {
const user: Meteor.User = Accounts.findUserByEmail(email);
if (user) {
EmailService.sendForgotPasswordEmail(user, email);
return true;
}
throw new Meteor.Error(422, 'Email address doesn\'t exist.');
},
});
import { Meteor } from 'meteor/meteor';
import { first } from 'rxjs/operators';
import { Roles } from '../collections/role';
import { rolesCollection } from '../collections/role.collection';
import { PERMISSIONS } from '../config';
import { Role } from '../models/role';
import { RoleModel } from '../models/role.model';
import { UtilsService } from '../services/utils.service';
Meteor.methods({
async saveRole(role: Role): Promise<void> {
async saveRole(role: RoleModel): Promise<void> {
try {
if (role._id && UtilsService.hasPermission(PERMISSIONS.UPDATE_ROLE)) {
await Roles.update(role._id, role)
await rolesCollection.update(role._id, role)
.pipe(first())
.toPromise();
}
......
import { Meteor } from 'meteor/meteor';
import { Roles } from '../collections/role';
import { rolesCollection } from '../collections/role.collection';
import { PERMISSIONS } from '../config';
import { UtilsService } from '../services/utils.service';
import { Query } from '../models/query';
import { QueryModel } from '../models/query.model';
import { EmailService } from '../services/email.service';
Meteor.methods({
usersGetCount(query: Query): any {
usersGetCount(query: QueryModel): any {
return {
recordsFiltered: Meteor.users.find(query.query).count(),
recordsTotal: Meteor.users.find().count(),
......@@ -15,9 +16,8 @@ Meteor.methods({
},
registerUser(user: any): string {
const defaultRole = Roles.findOne({ title: user.role });
const defaultRole = rolesCollection.findOne({ title: user.role });
if (!Accounts.findUserByEmail(user.email)) {
const userObj = {
email: user.email,
password: user.password,
......@@ -27,7 +27,10 @@ Meteor.methods({
role: defaultRole._id,
},
};
return Accounts.createUser(userObj);
const userId = Accounts.createUser(userObj);
EmailService.sendVerificationEmail(user, userId);
return userId;
}
throw new Meteor.Error(422, 'Email address already in use.');
},
......
import { settingsCollection } from './collections/setting.collections';
import { PERMISSIONS } from './config';
import { rolesCollection } from './collections/role.collection';
import { Meteor } from 'meteor/meteor';
// @ts-ignore
Migrations.add({
version: 1,
name: 'Adding Roles',
up() {
const allPermissions = Object.values(PERMISSIONS);
if (!rolesCollection.find({}).fetch().length) {
rolesCollection.insert({
title: 'Admin',
permissions: allPermissions,
description: '',
});
rolesCollection.insert({
title: 'User',
permissions: [PERMISSIONS.CAN_LOGIN, PERMISSIONS.CAN_UPDATE_OWN_USER],
description: '',
});
rolesCollection.insert({
title: 'Blocked',
permissions: [],
description: '',
});
} else {
rolesCollection.update({ title: 'Admin' }, { $set: { permissions: allPermissions } });
}
},
});
// @ts-ignore
Migrations.add({
version: 2,
name: 'Adding Admin User',
up() {
if (!Meteor.users.find({}).fetch().length) {
Accounts.createUser({
username: 'admin',
password: 'admin',
email: 'ali.arshad@vqode.com',
profile: {
name: 'Admin User',
role: rolesCollection.findOne({ title: 'Admin' })._id,
},
});
}
},
});
// @ts-ignore
Migrations.add({
version: 3,
name: 'Adding Email Templates',
up() {
if (settingsCollection.find({ REGISTER_HEADING: { $exists: true } }).fetch().length === 0) {
settingsCollection.insert({ REGISTER_HEADING: 'Welcome to $platform' });
}
if (settingsCollection.find({ REGISTER_EMAIL_BODY: { $exists: true } }).fetch().length === 0) {
settingsCollection.insert({ REGISTER_EMAIL_BODY: 'Hi $name! You are our $role now. Please click on the link <a href="$link" target="_blank">$link</a> to verify your account.' });
}
if (settingsCollection.find({ RESET_HEADING: { $exists: true } }).fetch().length === 0) {
settingsCollection.insert({ RESET_HEADING: 'Reset Password for $platform' });
}
if (settingsCollection.find({ RESET_EMAIL_BODY: { $exists: true } }).fetch().length === 0) {
settingsCollection.insert({ RESET_EMAIL_BODY: 'Hi $name! Don\'t worry. Reset your password by clicking on the following link <a href="$link" target="_blank">$link</a>.' });
}
},
});
export class Query {
export class QueryModel {
constructor(
public query = {} as any,
......
export interface Role {
export interface RoleModel {
_id?: string;
title: string;
permissions: string[];
......
import { Meteor } from 'meteor/meteor';
import { rolesCollection } from '../collections/role.collection';
Meteor.publish('roles', () => rolesCollection.find({}));
import { Meteor } from 'meteor/meteor';
import { Roles } from '../collections/role';
Meteor.publish('roles', () => Roles.find({}));
......@@ -3,13 +3,13 @@ import { Meteor } from 'meteor/meteor';
// @ts-ignore
import { publishComposite } from 'meteor/reywood:publish-composite';
import { PERMISSIONS } from '../config';
import { Query } from '../models/query';
import { QueryModel } from '../models/query.model';
import { UtilsService } from '../services/utils.service';
import { Roles } from '../collections/role';
import { rolesCollection } from '../collections/role.collection';
publishComposite('usersList', (filters = {}) => {
const queryFilters = { ...new Query(), ...filters };
const queryFilters = { ...new QueryModel(), ...filters };
if (!UtilsService.hasPermission([PERMISSIONS.CAN_SEE_ALL_USERS])) {
throw new Meteor.Error(403, 'Not enough permissions to get all users');
......@@ -22,7 +22,7 @@ publishComposite('usersList', (filters = {}) => {
children: [
{
find(user): any {
return Roles.find({ _id: user.profile.role });
return rolesCollection.find({ _id: user.profile.role });
},
},
],
......
import { CONFIG } from '../config';
import { settingsCollection } from '../collections/setting.collections';
export class EmailService {
static sendVerificationEmail(user: any, userId: string): void {
Accounts.emailTemplates.siteName = CONFIG.SiteName;
// Will uncomment it later with domain email
// Accounts.emailTemplates.from = CONFIG.DomainEmail;
Accounts.emailTemplates.verifyEmail = {
subject() {
const content: any = settingsCollection.findOne({ REGISTER_HEADING: { $exists: true } });
return content ? content.REGISTER_HEADING.replace('$platform', CONFIG.SiteName) : 'Welcome';
},
html(usr, url) {
const token = url.substr(url.lastIndexOf('/') + 1);
const link = `${process.env.appUrl}#/auth/verify-email/${token}`;
const content: any = settingsCollection.findOne({ REGISTER_EMAIL_BODY: { $exists: true } });
return content.REGISTER_EMAIL_BODY.replace(/\$name/g, user.name)
.replace(/\$role/g, user.role)
.replace(/\$link/g, link);
},
};
Accounts.sendVerificationEmail(userId, user.email);
}
static sendForgotPasswordEmail(user: Meteor.User, email: string): void {
Accounts.emailTemplates.siteName = CONFIG.SiteName;
// Will uncomment it later with domain email
// Accounts.emailTemplates.from = CONFIG.DomainEmail;
Accounts.emailTemplates.resetPassword = {
subject() {
const content: any = settingsCollection.findOne({ RESET_HEADING: { $exists: true } });
return content ? content.RESET_HEADING.replace('$platform', CONFIG.SiteName) : 'Welcome';
},
html(usr, url) {
const token = url.substr(url.lastIndexOf('/') + 1);
const link = `${process.env.appUrl}#/auth/reset-password/${token}`;
const content: any = settingsCollection.findOne({ RESET_EMAIL_BODY: { $exists: true } });
return content.RESET_EMAIL_BODY.replace(/\$name/g, user.profile.name)
.replace(/\$link/g, link);
},
};
Accounts.sendResetPasswordEmail(user._id, email);
}
}
......@@ -2,13 +2,13 @@
import AWS = require('aws-sdk');
import { Meteor } from 'meteor/meteor';
import { Observable, Subject } from 'rxjs';
import { Roles } from '../collections/role';
import { rolesCollection } from '../collections/role.collection';
export class UtilsService {
static getLoggedInUserPermissions(): string[] {
const usr: Meteor.User = Meteor.user();
const role = Roles.findOne(usr.profile.role);
const role = rolesCollection.findOne(usr.profile.role);
return role.permissions;
}
......@@ -16,7 +16,7 @@ export class UtilsService {
static hasPermission(permissions: string | string[]): boolean {
const usr: Meteor.User = Meteor.user();
if (usr) {
const role = Roles.findOne(usr.profile.role);
const role = rolesCollection.findOne(usr.profile.role);
if (typeof permissions === 'string') {
return role.permissions.indexOf(permissions) !== -1;
......@@ -29,7 +29,7 @@ export class UtilsService {
}
static hasPermissionOfUser(user: Meteor.User, permission: string): boolean {
const role = Roles.findOne(user.profile.role);
const role = rolesCollection.findOne(user.profile.role);
return role.permissions.indexOf(permission) !== -1;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment