Enable creating user from UI

Transactions
dan 2019-06-30 01:10:13 -06:00
parent 3d50149407
commit c37871dc39
25 changed files with 608 additions and 248 deletions

12
.vscode/launch.json vendored
View File

@ -4,6 +4,18 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "attach",
"name": "Attach by Process ID",
"processId": "${command:PickProcess}"
},
{
"type": "node",
"request": "attach",
"name": "Attach",
"port": 25776
},
{
"type": "chrome",
"request": "launch",

View File

@ -11,6 +11,7 @@ import { EventsPageComponent } from './components/events-page/events-page.compon
import { ContactPageComponent } from './components/contact-page/contact-page.component';
import { SalvationPageComponent } from './components/salvation-page/salvation-page.component';
import { CampPageComponent } from './components/camp-page/camp-page.component';
import { MembersPageComponent } from './components/members-page/members-page.component';
const routes =
[
@ -58,6 +59,10 @@ const routes =
path: 'salvation',
component: SalvationPageComponent
},
{
path: 'user',
component: MembersPageComponent
},
{
path: 'camp',
component: CampPageComponent

View File

@ -60,6 +60,9 @@ import { OfbDatePipe } from './pipes/ofb-date.pipe';
// Routing
import { AppRoutingModule } from './app-routing.module';
import { CampPageComponent } from './components/camp-page/camp-page.component';
import { MembersPageComponent } from './components/members-page/members-page.component';
import { AddUserPopupComponent } from './components/popups/add-user-popup/add-user-popup.component';
import { UserService } from './services/user.service';
@ -100,7 +103,9 @@ import { CampPageComponent } from './components/camp-page/camp-page.component';
SalvationPageComponent,
MediaPageComponent,
VideoPopupComponent,
CampPageComponent
CampPageComponent,
MembersPageComponent,
AddUserPopupComponent
],
imports: [
BrowserModule,
@ -115,7 +120,7 @@ import { CampPageComponent } from './components/camp-page/camp-page.component';
MatSnackBarModule,
MatDialogModule,
],
providers: [LoginService,GoogleAnalyticsService,SermonService,EventService,EmailService,WindowRefService],
providers: [LoginService,UserService,GoogleAnalyticsService,SermonService,EventService,EmailService,WindowRefService],
entryComponents: [AddSermonPopupComponent,
LoginPopupComponent,
OkPopupComponent,
@ -124,6 +129,7 @@ import { CampPageComponent } from './components/camp-page/camp-page.component';
UpdateSermonPopupComponent,
SharePopupComponent,
AddEventPopupComponent,
AddUserPopupComponent,
VideoPopupComponent],
bootstrap: [AppComponent]
})

View File

@ -0,0 +1,17 @@
<secondary-page-component [hideSideBarOnMobile]="true" >
<div mainContent>
<div *ngIf="loading">Loading...</div>
<div *ngIf="user && user.userName">
Welcome {{user.userName}}
<div *ngIf="canAddUser">
<button (click)="addUserModal()">Add User</button>
</div>
</div>
<div *ngIf="!user || !user.userName">
<button>Login</button>
</div>
</div>
<div sideBar class="side-bar">
</div>
</secondary-page-component>

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { MembersPageComponent } from './members-page.component';
describe('MembersPageComponent', () => {
let component: MembersPageComponent;
let fixture: ComponentFixture<MembersPageComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ MembersPageComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(MembersPageComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,39 @@
import { Component, OnInit } from '@angular/core';
import { LoginService } from 'src/app/services/login.service';
import { User } from 'src/app/interfaces/user';
import { UserRights } from 'src/app/constants/user-rights';
import { MatDialog } from '@angular/material';
import { AddUserPopupComponent } from '../popups/add-user-popup/add-user-popup.component';
import { take } from 'rxjs/operators';
@Component({
selector: 'app-members-page',
templateUrl: './members-page.component.html',
styleUrls: ['./members-page.component.css']
})
export class MembersPageComponent implements OnInit {
public loading: boolean = true;
public user: User;
public get canAddUser(): boolean {
return this.user && this.user.canDo(UserRights.userAdd);
}
constructor(private loginService: LoginService, private matDialog: MatDialog) { }
ngOnInit() {
this.loginService.isLoggedIn(true).pipe(take(1)).subscribe(r => {
this.loading = false;
console.log(r);
if (r == false) {
this.addUserModal();
}
})
this.loginService.user.subscribe(u => this.user = u);
}
addUserModal() {
let dialog = this.matDialog.open(AddUserPopupComponent);
}
}

View File

@ -4,13 +4,13 @@
<div id="header-menu" [@menuOpen]="menuOpen">
<ul class="width100">
<button mat-icon-button id="close-button" (click)="menuClick($event)"><i ofbicon>close</i></button>
<li class="width100"><icon-button-component [menuOpen]="menuOpen" animationDelay="0" icon="help_outline" routerLink="/whoweare" text="Who We Are"></icon-button-component></li>
<li class="width100"><icon-button-component [menuOpen]="menuOpen" animationDelay="50" icon="access_time" routerLink="/services" text="Service Times"></icon-button-component></li>
<li class="width100"><icon-button-component [menuOpen]="menuOpen" animationDelay="100" icon="place" routerLink="/location" text="Location"></icon-button-component></li>
<li class="width100"><icon-button-component [menuOpen]="menuOpen" animationDelay="150" icon="headset" routerLink="/sermons" text="Sermons"></icon-button-component></li>
<li class="width100"><icon-button-component [menuOpen]="menuOpen" animationDelay="200" icon="event" routerLink="/events" text="Events"></icon-button-component></li>
<li class="width100"><icon-button-component [menuOpen]="menuOpen" animationDelay="250" icon="mail_outline" routerLink="/contact" text="Contact"></icon-button-component></li>
<li class="width100"><icon-button-component [menuOpen]="menuOpen" animationDelay="300" icon="input" (click)="showLogin($event)" text="Login"></icon-button-component></li>
<li class="width100"><icon-button-component [menuOpen]="menuOpen" animationDelay="30" icon="help_outline" routerLink="/whoweare" text="Who We Are"></icon-button-component></li>
<li class="width100"><icon-button-component [menuOpen]="menuOpen" animationDelay="20" icon="access_time" routerLink="/services" text="Service Times"></icon-button-component></li>
<li class="width100"><icon-button-component [menuOpen]="menuOpen" animationDelay="10" icon="place" routerLink="/location" text="Location"></icon-button-component></li>
<li class="width100"><icon-button-component [menuOpen]="menuOpen" animationDelay="0" icon="headset" routerLink="/sermons" text="Sermons"></icon-button-component></li>
<li class="width100"><icon-button-component [menuOpen]="menuOpen" animationDelay="10" icon="event" routerLink="/events" text="Events"></icon-button-component></li>
<li class="width100"><icon-button-component [menuOpen]="menuOpen" animationDelay="20" icon="mail_outline" routerLink="/contact" text="Contact"></icon-button-component></li>
<li class="width100"><icon-button-component [menuOpen]="menuOpen" animationDelay="30" icon="input" (click)="showLogin($event)" text="Login"></icon-button-component></li>
</ul>
</div>
</div>

View File

@ -0,0 +1,3 @@
.full-width {
width: 100%;
}

View File

@ -0,0 +1,40 @@
<div md-dialog-title>
<p>Add User</p>
</div>
<div md-dialog-content>
<form #addUserForm="ngForm" (ngSubmit)="onSubmit()">
<mat-form-field>
<input matInput placeholder="First name" [(ngModel)]="firstName" name="firstName" >
</mat-form-field>
<mat-form-field>
<input matInput placeholder="Middle name" [(ngModel)]="middleName" name="middleName" >
</mat-form-field>
<mat-form-field>
<input matInput placeholder="Last name" required [(ngModel)]="lastName" name="lastName">
</mat-form-field>
<mat-form-field class="full-width">
<input matInput placeholder="Street Address" [(ngModel)]="street" name="street" >
</mat-form-field>
<mat-form-field>
<input matInput placeholder="City" [(ngModel)]="city" name="city" >
</mat-form-field>
<mat-form-field>
<input matInput placeholder="State" [(ngModel)]="state" name="state" >
</mat-form-field>
<mat-form-field>
<input matInput placeholder="Zip" [(ngModel)]="zip" name="zip" >
</mat-form-field>
<mat-form-field class="full-width">
<input matInput placeholder="Country" required [(ngModel)]="country" name="country" >
</mat-form-field>
<br><br>
<div *ngIf="errorMessages.length > 0" class="errorMessages">
<p *ngFor="let error of errorMessages">
{{error}}
</p>
</div>
<button mat-raised-button class="first" (click)="cancel($event)" >Cancel</button><!--
--><button mat-raised-button type="submit" [disabled]="!addUserForm.form.valid || addUserButtonDisabled">{{ addUserButtonText }}</button>
</form>
</div>

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { AddUserPopupComponent } from './add-user-popup.component';
describe('AddUserPopupComponent', () => {
let component: AddUserPopupComponent;
let fixture: ComponentFixture<AddUserPopupComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ AddUserPopupComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AddUserPopupComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,92 @@
import { Component, OnInit } from '@angular/core';
import { MatDialog, MatDialogRef } from '@angular/material';
import { LoginService } from 'src/app/services/login.service';
import { LoginPopupComponent } from '../login-popup/login-popup.component';
import { OkPopupComponent } from '../ok-popup/ok-popup.component';
import { UserService } from 'src/app/services/user.service';
@Component({
selector: 'app-add-user-popup',
templateUrl: './add-user-popup.component.html',
styleUrls: ['./add-user-popup.component.css']
})
export class AddUserPopupComponent implements OnInit {
public addUserButtonText: string = "Add User";
public addUserButtonDisabled: boolean = false;
// Form Fields
public firstName: string;
public lastName: string;
public street: string;
public city: string;
public state: string;
public zip: string;
public country: string = 'United States';
public errorMessages: string[] = [];
constructor(private MatDialog: MatDialog,
private MatDialogRef: MatDialogRef<AddUserPopupComponent>,
private loginService: LoginService,
private userService: UserService) { }
ngOnInit() {
}
onSubmit(){
this.updateAddButton(false);
//First check to see if we are logged in
this.loginService.isLoggedIn(true).subscribe(is => {
if (is === true){
this.addUser();
} else {
let popup = this.MatDialog.open(LoginPopupComponent);
popup.afterClosed().subscribe(r => {
if (r === true){
this.addUser();
} else {
this.updateAddButton(true);
}
});
}
},
error =>{
this.updateAddButton(true);
let errorDialog = this.MatDialog.open(OkPopupComponent,{data:{title:'Error',message:'There was an error adding the event\n' + error}});
});
}
updateAddButton(enable: boolean){
if (enable){
this.addUserButtonText = "Add User";
} else {
this.addUserButtonText = "Please Wait...";
}
this.addUserButtonDisabled = !enable;
}
private addUser(): void {
console.log("Add User");
this.userService.create(
this.firstName,
this.lastName,
this.street,
this.city,
this.state,
this.zip,
this.country).subscribe(data => {
this.MatDialogRef.close(data['user']);
}, error => {
this.updateAddButton(true);
let errorDialog = this.MatDialog.open(OkPopupComponent,{data:{title:'User Error',message:'There was an error creating the user: ' + error}});
});
}
cancel(evt){
evt.preventDefault();
this.MatDialogRef.close();
}
}

View File

@ -12,6 +12,7 @@ export const SERMON_ADD_URL = environment.baseUrl + "/api2/sermons/a/";
export const SERMON_DELETE_URL = environment.baseUrl + "/api2/sermons/a/";
export const SERMON_UPDATE_URL = environment.baseUrl + "/api2/sermons/a/";
export const SERMON_DOWNLOAD_URL = environment.baseUrl + "/api2/sermons/download/";
export const USER_CREATE_URL = environment.baseUrl + "/api2/users/a/";
export const LOGIN_URL = environment.baseUrl + '/api2/login';
export const LOGIN_VALIDATE_TOKEN = '';
export const EMAIL_URL = environment.baseUrl + "/api2/email";

View File

@ -0,0 +1,8 @@
export const UserRights = {
userAdd: "user_add",
userUpdateSelf: "user_update_self",
userDeleteSelf: "user_delete_self",
sermonsAdd: "sermons_add",
sermonsUpdate: "sermons_update",
sermonsDelete: "sermons_delete"
}

View File

@ -0,0 +1,16 @@
export class User {
id: number;
userName: string;
firstName: string;
lastName: string;
email: string;
verified: boolean;
emailVerified: boolean;
federated: boolean;
rights: string[];
canDo(right: string): boolean {
if (!this.rights || this.rights.length == 0) return false;
return this.rights.findIndex(r => r === right) > -1;
}
}

View File

@ -2,9 +2,10 @@ import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { Observable, Subject, throwError, of } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
import { catchError, map, tap } from 'rxjs/operators';
import { LOGIN_URL } from '../constants/urls';
import { User } from '../interfaces/user';
@Injectable()
export class LoginService {
@ -12,6 +13,7 @@ export class LoginService {
private onChange: Subject<{isLoggedIn: boolean}>;
private lastLoginCheck: Date;
private options: {};
public user: Subject<User> = new Subject<User>();
constructor(private httpClient: HttpClient){
this.options = {
@ -23,7 +25,16 @@ export class LoginService {
}
login(username: string, password: string){
return this.httpClient.post(LOGIN_URL, {userName: username, password: password}, this.options).pipe(catchError(this.handleError));
return this.httpClient
.post(LOGIN_URL, {userName: username, password: password}, this.options)
.pipe(
tap(res => console.log(res)),
tap(res => {
const u = (<any>res).user;
const usr = Object.assign(new User(), u);
this.user.next(usr);
}),
catchError(this.handleError));
}
isLoggedIn(fromServer: boolean = false){
@ -32,10 +43,12 @@ export class LoginService {
if (hours > 0.75 || fromServer === true){
return this.httpClient.post(LOGIN_URL + "/isloggedin",{},this.options)
.pipe(map((d:any) => {
console.log(d);
let is = d.loggedIn === true;
this.loggedIn = is;
this.lastLoginCheck = new Date();
this.onChange.next({isLoggedIn: this.loggedIn});
this.user.next(Object.assign(new User(), d.user));
return this.loggedIn;
}),
catchError(this.handleError));

View File

@ -0,0 +1,51 @@
import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { Observable, Subject, throwError, of } from 'rxjs';
import { catchError, map, tap, first } from 'rxjs/operators';
import { LOGIN_URL, USER_CREATE_URL } from '../constants/urls';
@Injectable()
export class UserService {
private options: {};
constructor(private httpClient: HttpClient){
this.options = {
withCredentials: true
};
}
create(firstName: string, lastName: string, street: string, city: string, state: string, zip: string, country: string) {
const body = {
firstName: firstName,
lastName: lastName,
street: street,
city: city,
state: state,
zip: zip,
country: country
};
console.log(body);
return this.httpClient.post(USER_CREATE_URL, body, this.options)
.pipe(tap(res => console.log(res)), catchError(this.handleError));
}
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', error.error.message);
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
console.error(
`Backend returned code ${error.status}, ` +
`body was: ${error.error}`);
console.error(error);
}
// return an observable with a user-facing error message
return throwError((error && error.error && error.error.message) ? error.error.message :
'Something bad happened; please try again later.');
};
}

View File

@ -81,5 +81,10 @@ function verifyPassword(password, combined, callback) {
});
}
function createVerificationCode() {
return crypto.randomBytes(8).toString("hex");
}
exports.hashPassword = hashPassword;
exports.verifyPassword = verifyPassword;
exports.verifyPassword = verifyPassword;
exports.createVerificationCode = createVerificationCode;

View File

@ -4,6 +4,7 @@ var hash = require("./hash");
var crypto = require("crypto");
var dbUsers = require("../database/users");
var dbTokens = require("../database/tokens");
var dbRights = require("../database/user-rights");
exports.login = function(userName, password, topCallback){
@ -33,37 +34,82 @@ exports.login = function(userName, password, topCallback){
callback("Invalid UserName or Password");
return;
}
callback(null,isMatch, user.id);
callback(null,isMatch, user);
});
},
function(isMatch, userId, callback){
function(isMatch, user, callback){
//Password is a match so lets generate a token
dbTokens.createToken(userId,function(error,token){
dbTokens.createToken(user.id,function(error,token){
if (error){
callback(error);
return;
}
callback(null, token);
callback(null, token, user);
});
},
function(token, user, callback) {
dbRights.getRights(user.id, function(error, rights){
if (error) {
callback(error);
return;
}
user.rights = rights;
callback(null, token, user);
});
}
],function(error,token){
],function(error,token, user){
if (error){
topCallback(error);
return;
}
topCallback(null, token);
user.password = undefined;
user.verificationCode = undefined;
topCallback(null, token, user);
});
}
exports.verifyToken = function(userId, tokenId, token, callback){
function verifyToken(userId, tokenId, token, callback){
if (typeof userId == 'object' && typeof tokenId == 'function'){
verifyTokenObject(userId,tokenId);
return;
}
dbTokens.verifyToken(userId, tokenId, token, callback);
dbTokens.verifyToken(userId, tokenId, token, function(error, isValid){
console.log(userId);
if (error) {
callback(error);
return;
} else if (!isValid) {
callback(null, isValid);
return;
}
dbUsers.getUser(userId, function(error, user){
if(error) {
callback(error);
return;
}
if (!user) {
callback("User not Found");
return;
}
user.password = undefined;
user.verificationCode = undefined;
dbRights.getRights(userId, function(error, rights){
if (error) {
callback(error);
return;
}
user.rights = rights;
callback(null, isValid, user);
});
});
});
}
function verifyTokenObject(tokenObj, callback){
dbTokens.verifyToken(tokenObj.userId,tokenObj.id,tokenObj.value,callback);
}
verifyToken(tokenObj.userId, tokenObj.id, tokenObj.value, callback);
//dbTokens.verifyToken(tokenObj.userId,tokenObj.id,tokenObj.value,callback);
}
exports.verifyToken = verifyToken;

View File

@ -0,0 +1,25 @@
var connection = require('./connection');
exports.query = function(sql, args) {
return new Promise(function(resolve, reject){
connection.query(sql,args,function(error,rows,fields){
if (error){
reject(error)
} else {
resolve({rows:rows,fields:fields});
}
});
});
}
exports.nonQuery = function(sql, args) {
return new Promise(function(resolve, reject){
connection.query(sql,args,function(error,result){
if (error){
reject(error)
} else {
resolve(result);
}
});
});
}

View File

@ -1,4 +1,5 @@
var connection = require("./connection");
var connectionAsync = require("./connectionasync");
var hash = require("../authentication/hash");
var dbRights = require("./user-rights");
var async = require("async");
@ -25,6 +26,10 @@ exports.getUser = function(userIdOrUserName, callback){
user.email = rows[0].Email;
user.password = rows[0].Password;
user.deletedDate = rows[0].deletedDate;
user.verified = rows[0].Verified;
user.verifiedDate = rows[0].VerifiedDate;
user.verificationCode = rows[0].VerificationCode;
user.verificationCodeDate = rows[0].verificationCodeDate;
}
console.log(user);
//console.log(fields);
@ -32,142 +37,55 @@ exports.getUser = function(userIdOrUserName, callback){
});
}
exports.insertUser = function(userNameOrUserObject, passwordOrCallbackFunction, email, topCallback){
if (typeof passwordOrCallbackFunction === 'function'){
insertUserFromObject(userNameOrUserObject,passwordOrCallbackFunction);
return;
exports.getUser2 = async function(email) {
const queryResult = await connectionAsync.query('SELECT * FROM Users WHERE UserName = ? AND DeletedDate IS NULL;', [email]);
if (queryResult && queryResult.rows && queryResult.rows.length > 0) {
const row = queryResult.rows[0];
const user = {};
user.id = row.Id;
user.userName = row.UserName;
user.password = row.Password;
user.firstName = row.FirstName;
user.lastName = row.LastName;
user.street = row.Street;
user.city = row.City;
user.state = row.State;
user.country = row.Country;
user.emailVerified = row.EmailVerified;
user.emailVerificationCode = row.EmailVerificationCode;
user.emailVerificationCodeDate = row.EmailVerificationCodeDate;
user.federated = row.Federated;
user.federationCode = row.federationCode;
return user;
} else {
return null;
}
async.waterfall([
//First step is to check if the user name already exists
function(callback){
dbUsers.getUser(userNameOrUserObject,function(error,user){
if (error){
callback(error);
return;
}
if (user){
callback("user-exists"); //The user exists
return;
} else {
callback(null,false); //The user does not exist
return;
}
});
},
//If the user does not exist - get the hashed version of the password
function(userExists,callback){
//Get the password hash
hash.hashPassword(passwordOrCallbackFunction,function(error,hashedPW){
if (error){
callback(error);
return;
}
callback(null,hashedPW);
});
},
//Insert the user into the database with the hashed password
function(hashedPW,callback){
//User does not exist. Lets add it
connection.query("INSERT INTO Users (CreatedDate,ModifiedDate,Id,UserName,Password,DeletedDate,Email) VALUES(CURRENT_TIMESTAMP,CURRENT_TIMESTAMP,NULL,?,?,NULL,?)",[userNameOrUserObject,hashedPW,email],function(error,result){
if (error){
callback(error);
return;
}
callback(null,result);
});
},
//Get the new user from the database and return it to the final function
function(insertResult,callback){
//Get the inserted user
dbUsers.getUser(insertResult.insertId,function(error,user){
if(error){
callback(error);
return;
}
if (!user){
callback("error retrieving new user");
return;
}
callback(null,user);
});
},
//add the rights for this user
function(user, callback){
var rightIdArray = [1,2];
dbRights.addRights(user.id,rightIdArray,function(error){
if (error){
callback(error);
} else {
callback(null,user);
}
});
}
],function(err,result){
//Complete
if (err == "user-exists"){
topCallback("User already Exists");
return;
}
if (err){
topCallback(err);
return;
}
result.password = "*";
topCallback(null,result);
});
}
function insertUserFromObject(sermon, callback){
dbSermons.insertUser(user.userName,user.password,user.email,callback);
}
exports.updateUser = function(userIdOrUserObject, userNameOrCallbackFunction, password, email, deletedDate, topCallback){
if (typeof userNameOrCallbackFunction == 'function'){
updateUserFromObject(userIdOrUserObject,userNameOrCallbackFunction);
return;
exports.createUser = async function(firstName, lastName, street, city, state, zip, country) {
// Check to see if email already exists
const tempUserName = firstName + " " + lastName;
const existing = await this.getUser2(tempUserName);
if (existing) {
throw `${tempUserName} already exists`;
}
async.waterfall([
//First Step: == GET Hashed Password
function(callback){
hash.hashPassword(password,function(error, hashedPW){
if (error){
callback(error);
return;
}
callback(null,hashedPW);
});
},
function(hashedPW, callback){
connection.query("UPDATE Users SET UserName = ?, Password = ?, Email = ?, DeletedDate = ? WHERE Id = ?;",[userNameOrCallbackFunction,hashedPW,email,deletedDate,userIdOrUserObject],function(error,result){
if (error){
callback(error);
return;
}
callback(null, result);
});
},
function(updateResult, callback){
dbUsers.getUser(userIdOrUserObject,function(error,user){
if (error){
callback(error);
return;
}
callback(null, user);
});
}
], function(error, updatedUser){
if (error){
topCallback(error);
return;
}
topCallback(null,updatedUser);
});
}
function updateUserFromObject(user,callback){
dbUsers.updateUser(user.id,user.userName,user.password,user.email,user.deletedDate,callback);
const newUser = {
CreatedDate: new Date(),
ModifiedDate: new Date(),
UserName: tempUserName,
FirstName: firstName,
LastName: lastName,
Street: street,
City: city,
State: state,
Zip: zip,
Country: country,
EmailVerified: false,
Federated: false,
FederationCode: hash.createVerificationCode()
};
const newUserResult = await connectionAsync.nonQuery('INSERT INTO Users Set ?', newUser);
return await this.getUser2(tempUserName);
}
exports.deleteUser = function(userIdOrUserObject, callback){

View File

@ -9,7 +9,7 @@
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz",
"integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=",
"requires": {
"mime-types": "2.1.17",
"mime-types": "~2.1.16",
"negotiator": "0.6.1"
}
},
@ -28,7 +28,7 @@
"resolved": "https://registry.npmjs.org/async/-/async-2.5.0.tgz",
"integrity": "sha512-e+lJAJeNWuPCNyxZKOBdaJGyLGHugXVQtrAwtuAe2vhxTYxFTKE73p8JuTmdH0qdQZtDvI4dhJwjZc5zsfIsYw==",
"requires": {
"lodash": "4.17.4"
"lodash": "^4.14.0"
}
},
"bignumber.js": {
@ -42,15 +42,15 @@
"integrity": "sha512-KL2pZpGvy6xuZHgYUznB1Zfw4AoGMApfRanT5NafeLvglbaSM+4CCtmlyYOv66oYXqvKL1xpaFb94V/AZVUnYg==",
"requires": {
"bytes": "3.0.0",
"content-type": "1.0.4",
"content-type": "~1.0.4",
"debug": "2.6.8",
"depd": "1.1.1",
"http-errors": "1.6.2",
"depd": "~1.1.1",
"http-errors": "~1.6.2",
"iconv-lite": "0.4.19",
"on-finished": "2.3.0",
"on-finished": "~2.3.0",
"qs": "6.5.1",
"raw-body": "2.3.2",
"type-is": "1.6.15"
"type-is": "~1.6.15"
},
"dependencies": {
"content-type": {
@ -71,7 +71,7 @@
"integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=",
"requires": {
"dicer": "0.2.5",
"readable-stream": "1.1.14"
"readable-stream": "1.1.x"
},
"dependencies": {
"isarray": {
@ -84,10 +84,10 @@
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
"requires": {
"core-util-is": "1.0.2",
"inherits": "2.0.3",
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "0.0.1",
"string_decoder": "0.10.31"
"string_decoder": "~0.10.x"
}
},
"string_decoder": {
@ -107,9 +107,9 @@
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz",
"integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=",
"requires": {
"inherits": "2.0.3",
"readable-stream": "2.3.3",
"typedarray": "0.0.6"
"inherits": "^2.0.3",
"readable-stream": "^2.2.2",
"typedarray": "^0.0.6"
}
},
"content-disposition": {
@ -174,7 +174,7 @@
"resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz",
"integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=",
"requires": {
"readable-stream": "1.1.14",
"readable-stream": "1.1.x",
"streamsearch": "0.1.2"
},
"dependencies": {
@ -188,10 +188,10 @@
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
"requires": {
"core-util-is": "1.0.2",
"inherits": "2.0.3",
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "0.0.1",
"string_decoder": "0.10.31"
"string_decoder": "~0.10.x"
}
},
"string_decoder": {
@ -226,34 +226,34 @@
"resolved": "https://registry.npmjs.org/express/-/express-4.15.4.tgz",
"integrity": "sha1-Ay4iU0ic+PzgJma+yj0R7XotrtE=",
"requires": {
"accepts": "1.3.4",
"accepts": "~1.3.3",
"array-flatten": "1.1.1",
"content-disposition": "0.5.2",
"content-type": "1.0.2",
"content-type": "~1.0.2",
"cookie": "0.3.1",
"cookie-signature": "1.0.6",
"debug": "2.6.8",
"depd": "1.1.1",
"encodeurl": "1.0.1",
"escape-html": "1.0.3",
"etag": "1.8.0",
"finalhandler": "1.0.4",
"depd": "~1.1.1",
"encodeurl": "~1.0.1",
"escape-html": "~1.0.3",
"etag": "~1.8.0",
"finalhandler": "~1.0.4",
"fresh": "0.5.0",
"merge-descriptors": "1.0.1",
"methods": "1.1.2",
"on-finished": "2.3.0",
"parseurl": "1.3.1",
"methods": "~1.1.2",
"on-finished": "~2.3.0",
"parseurl": "~1.3.1",
"path-to-regexp": "0.1.7",
"proxy-addr": "1.1.5",
"proxy-addr": "~1.1.5",
"qs": "6.5.0",
"range-parser": "1.2.0",
"range-parser": "~1.2.0",
"send": "0.15.4",
"serve-static": "1.12.4",
"setprototypeof": "1.0.3",
"statuses": "1.3.1",
"type-is": "1.6.15",
"statuses": "~1.3.1",
"type-is": "~1.6.15",
"utils-merge": "1.0.0",
"vary": "1.1.1"
"vary": "~1.1.1"
}
},
"finalhandler": {
@ -262,12 +262,12 @@
"integrity": "sha512-16l/r8RgzlXKmFOhZpHBztvye+lAhC5SU7hXavnerC9UfZqZxxXl3BzL8MhffPT3kF61lj9Oav2LKEzh0ei7tg==",
"requires": {
"debug": "2.6.8",
"encodeurl": "1.0.1",
"escape-html": "1.0.3",
"on-finished": "2.3.0",
"parseurl": "1.3.1",
"statuses": "1.3.1",
"unpipe": "1.0.0"
"encodeurl": "~1.0.1",
"escape-html": "~1.0.3",
"on-finished": "~2.3.0",
"parseurl": "~1.3.1",
"statuses": "~1.3.1",
"unpipe": "~1.0.0"
}
},
"forwarded": {
@ -288,7 +288,7 @@
"depd": "1.1.1",
"inherits": "2.0.3",
"setprototypeof": "1.0.3",
"statuses": "1.3.1"
"statuses": ">= 1.3.1 < 2"
}
},
"iconv-lite": {
@ -346,7 +346,7 @@
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz",
"integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=",
"requires": {
"mime-db": "1.30.0"
"mime-db": "~1.30.0"
}
},
"minimist": {
@ -362,6 +362,19 @@
"minimist": "0.0.8"
}
},
"moment": {
"version": "2.24.0",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
"integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg=="
},
"moment-timezone": {
"version": "0.5.25",
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.25.tgz",
"integrity": "sha512-DgEaTyN/z0HFaVcVbSyVCUU6HeFdnNC3vE4c9cgu2dgMTvjBUBdBzWfasTBmAW45u5OIMeCJtU8yNjM22DHucw==",
"requires": {
"moment": ">= 2.9.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@ -372,14 +385,14 @@
"resolved": "https://registry.npmjs.org/multer/-/multer-1.3.0.tgz",
"integrity": "sha1-CSsmcPaEb6SRSWXvyM+Uwg/sbNI=",
"requires": {
"append-field": "0.1.0",
"busboy": "0.2.14",
"concat-stream": "1.6.0",
"mkdirp": "0.5.1",
"object-assign": "3.0.0",
"on-finished": "2.3.0",
"type-is": "1.6.15",
"xtend": "4.0.1"
"append-field": "^0.1.0",
"busboy": "^0.2.11",
"concat-stream": "^1.5.0",
"mkdirp": "^0.5.1",
"object-assign": "^3.0.0",
"on-finished": "^2.3.0",
"type-is": "^1.6.4",
"xtend": "^4.0.0"
}
},
"mysql": {
@ -436,7 +449,7 @@
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.5.tgz",
"integrity": "sha1-ccDuOxAt4/IC87ZPYI0XP8uhqRg=",
"requires": {
"forwarded": "0.1.0",
"forwarded": "~0.1.0",
"ipaddr.js": "1.4.0"
}
},
@ -466,13 +479,13 @@
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
"integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==",
"requires": {
"core-util-is": "1.0.2",
"inherits": "2.0.3",
"isarray": "1.0.0",
"process-nextick-args": "1.0.7",
"safe-buffer": "5.1.1",
"string_decoder": "1.0.3",
"util-deprecate": "1.0.2"
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~1.0.6",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.0.3",
"util-deprecate": "~1.0.1"
}
},
"safe-buffer": {
@ -486,18 +499,18 @@
"integrity": "sha1-mF+qPihLAnPHkzZKNcZze9k5Bbk=",
"requires": {
"debug": "2.6.8",
"depd": "1.1.1",
"destroy": "1.0.4",
"encodeurl": "1.0.1",
"escape-html": "1.0.3",
"etag": "1.8.0",
"depd": "~1.1.1",
"destroy": "~1.0.4",
"encodeurl": "~1.0.1",
"escape-html": "~1.0.3",
"etag": "~1.8.0",
"fresh": "0.5.0",
"http-errors": "1.6.2",
"http-errors": "~1.6.2",
"mime": "1.3.4",
"ms": "2.0.0",
"on-finished": "2.3.0",
"range-parser": "1.2.0",
"statuses": "1.3.1"
"on-finished": "~2.3.0",
"range-parser": "~1.2.0",
"statuses": "~1.3.1"
}
},
"serve-static": {
@ -505,9 +518,9 @@
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.12.4.tgz",
"integrity": "sha1-m2qpjutyU8Tu3Ewfb9vKYJkBqWE=",
"requires": {
"encodeurl": "1.0.1",
"escape-html": "1.0.3",
"parseurl": "1.3.1",
"encodeurl": "~1.0.1",
"escape-html": "~1.0.3",
"parseurl": "~1.3.1",
"send": "0.15.4"
}
},
@ -536,7 +549,7 @@
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
"requires": {
"safe-buffer": "5.1.1"
"safe-buffer": "~5.1.0"
}
},
"type-is": {
@ -545,7 +558,7 @@
"integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=",
"requires": {
"media-typer": "0.3.0",
"mime-types": "2.1.17"
"mime-types": "~2.1.15"
}
},
"typedarray": {

View File

@ -10,7 +10,7 @@ router.post("/",function(req,res){
res.status(200).json({"status":200,"message":"userName and password is needed to login!"});
return;
}
auth.login(req.body.userName,req.body.password,function(error,token){
auth.login(req.body.userName,req.body.password,function(error,token,user){
if (error){
res.status(400).json({"status":400,"message":"Error logging in","error":error});
return;
@ -19,7 +19,7 @@ router.post("/",function(req,res){
res.cookie("tokenId",token.id,{ httpOnly: true, secured: true, signed: true });
res.cookie("tokenValue",token.value,{ httpOnly: true, secured: true, signed: true });
res.cookie("tokenUser",token.userId,{ httpOnly: true, secured: true, signed: true});
res.status(200).json({"status":200,"message":"Logged In"});
res.status(200).json({"status":200,"message":"Logged In","user":user});
});
});
@ -32,11 +32,11 @@ router.post("/isloggedin",function(req,res){
}
var token = {};
token.userId = req.signedCookies.tokenUser;
token.userId = +req.signedCookies.tokenUser;
token.id = req.signedCookies.tokenId;
token.value = req.signedCookies.tokenValue;
auth.verifyToken(token,function(error,isValid){
auth.verifyToken(token,function(error,isValid,user){
if (error){
res.status(400).json({"status":400,"message":"error validating token","loggedIn":loggedIn});
return;
@ -46,7 +46,7 @@ router.post("/isloggedin",function(req,res){
return;
} else {
loggedIn = true;
res.status(200).json({"status":200,"message":"valid token","loggedIn":loggedIn});
res.status(200).json({"status":200,"message":"valid token","loggedIn":loggedIn,"user":user});
}
}
});

View File

@ -41,8 +41,8 @@ router.use(upload.single('file'),function(req,res,next){
}
var token = {};
token.userId = req.signedCookies.tokenUser;
token.id = req.signedCookies.tokenId;
token.userId = +req.signedCookies.tokenUser;
token.id = +req.signedCookies.tokenId;
token.value = req.signedCookies.tokenValue;
auth.verifyToken(token,function(error,isValid){
@ -57,14 +57,14 @@ router.use(upload.single('file'),function(req,res,next){
return;
}
}
});
if (req.file){
req.body.file = req.file.originalname;
req.body.finalPath = finalStorage + req.file.filename;
req.body.tmpPath = req.file.destination + req.file.filename;
}
next();
if (req.file){
req.body.file = req.file.originalname;
req.body.finalPath = finalStorage + req.file.filename;
req.body.tmpPath = req.file.destination + req.file.filename;
}
next();
});
});

View File

@ -3,19 +3,19 @@ var router = express.Router();
var dbUsers = require("../../database/users");
router.post("/a/",function(req,res){
router.post("/a/",async function(req,res) {
console.log("new user");
if (!req.body.userName || !req.body.password || !req.body.email){
res.status(400).json({"status":400,"message":"userName, password, and email are required fields in the body"});
console.log(req.body);
if (!req.body.lastName){
res.status(400).json({"status":400,"message":"last name is required fields in the body"});
return;
}
dbUsers.insertUser(req.body.userName,req.body.password,req.body.email,function(error,newUser){
if (error){
res.status(400).json({"status":400,"message":"error creating new user","error":error});
return;
}
try {
var newUser = await dbUsers.createUser(req.body.firstName, req.body.lastName, req.body.street, req.body.city, req.body.state, req.body.zip, req.body.country);
res.status(201).json({"status":201,"message":"user created","user":newUser});
});
} catch (ex) {
res.status(500).json({"status":500,"message":ex});
}
});
router.put("/a/",function(req,res){