Compare commits
No commits in common. "95983021edbcee5c2ac6d0af50ae24603768edf6" and "93c70b0e1d1305f6f15c62f9031707975d64b9b8" have entirely different histories.
95983021ed
...
93c70b0e1d
|
@ -5,7 +5,6 @@ import express, {Request, Response} from 'express';
|
||||||
import {Guid} from 'guid-typescript';
|
import {Guid} from 'guid-typescript';
|
||||||
import logger from '../../middleware/logger';
|
import logger from '../../middleware/logger';
|
||||||
import {eventsRouter} from './events/events.router';
|
import {eventsRouter} from './events/events.router';
|
||||||
import {usersRouter} from './users/users.router';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Router Definition
|
* Router Definition
|
||||||
|
@ -13,7 +12,6 @@ import {usersRouter} from './users/users.router';
|
||||||
export const calendarRouter = express.Router();
|
export const calendarRouter = express.Router();
|
||||||
|
|
||||||
calendarRouter.use('/events', eventsRouter);
|
calendarRouter.use('/events', eventsRouter);
|
||||||
calendarRouter.use('/users', usersRouter);
|
|
||||||
|
|
||||||
|
|
||||||
calendarRouter.get('/', async (req: Request, res: Response) => {
|
calendarRouter.get('/', async (req: Request, res: Response) => {
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import * as dotenv from 'dotenv';
|
import * as dotenv from 'dotenv';
|
||||||
import * as UserService from '../users/users.service';
|
|
||||||
|
|
||||||
|
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
|
@ -8,48 +7,34 @@ dotenv.config();
|
||||||
* Checks if the password gives admin privileges (view / create / edit / delete)
|
* Checks if the password gives admin privileges (view / create / edit / delete)
|
||||||
* @param password
|
* @param password
|
||||||
*/
|
*/
|
||||||
export const checkAdminPrivileges = async (sessionId: string, sessionKey: string, ip: string) => {
|
export const checkAdminPrivileges = (password: string) => {
|
||||||
if(sessionId) {
|
return password == process.env.ADMIN_CREDENTIAL;
|
||||||
let user = await UserService.checkSession(sessionId, sessionKey, ip);
|
|
||||||
return user.isActive;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the password gives member view privileges
|
* Checks if the password gives member view privileges
|
||||||
* @param password
|
* @param password
|
||||||
*/
|
*/
|
||||||
export const checkMemberPrivileges = async (sessionId: string, sessionKey: string, password: string, ip: string) => {
|
export const checkMemberPrivileges = (password: string) => {
|
||||||
if(sessionId) {
|
return password == process.env.MEMBER_CREDENTIAL || password == process.env.ADMIN_CREDENTIAL;
|
||||||
let user = await UserService.checkSession(sessionId, sessionKey, ip);
|
|
||||||
return user.isActive;
|
|
||||||
}
|
|
||||||
|
|
||||||
return password == process.env.MEMBER_CREDENTIAL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the password gives management view privileges
|
* Checks if the password gives management view privileges
|
||||||
* @param password
|
* @param password
|
||||||
*/
|
*/
|
||||||
export const checkManagementPrivileges = async (sessionId: string, sessionKey: string, password: string, ip: string) => {
|
export const checkManagementPrivileges = (password: string) => {
|
||||||
if(sessionId) {
|
return password == process.env.MANAGEMENT_CREDENTIAL || password == process.env.ADMIN_CREDENTIAL;
|
||||||
let user = await UserService.checkSession(sessionId, sessionKey, ip);
|
|
||||||
return user.isActive;
|
|
||||||
}
|
|
||||||
|
|
||||||
return password == process.env.MANAGEMENT_CREDENTIAL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const hasAccess = async (calendarName: string, sessionId: string, sessionKey: string, password: string, ip: string) => {
|
export const hasAccess = (calendarName: string, password: string) => {
|
||||||
switch (calendarName) {
|
switch (calendarName) {
|
||||||
case 'public':
|
case 'public':
|
||||||
return true;
|
return true;
|
||||||
case 'members':
|
case 'members':
|
||||||
return await checkMemberPrivileges(sessionId, sessionKey, password, ip);
|
return checkMemberPrivileges(password);
|
||||||
case 'management':
|
case 'management':
|
||||||
return await checkManagementPrivileges(sessionId, sessionKey, password, ip);
|
return checkManagementPrivileges(password);
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,7 @@ export interface Event {
|
||||||
endDateTime: Date;
|
endDateTime: Date;
|
||||||
createdDate: Date;
|
createdDate: Date;
|
||||||
location: string;
|
location: string;
|
||||||
createdBy?: string;
|
createdBy: string;
|
||||||
createdById: number,
|
|
||||||
url: string;
|
url: string;
|
||||||
wholeDay: boolean;
|
wholeDay: boolean;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ import {Event} from './event.interface';
|
||||||
import * as EventService from './events.service';
|
import * as EventService from './events.service';
|
||||||
import * as iCalService from './icalgenerator.service';
|
import * as iCalService from './icalgenerator.service';
|
||||||
import * as CredentialService from './credentials.service';
|
import * as CredentialService from './credentials.service';
|
||||||
import * as UserService from '../users/users.service';
|
|
||||||
import {Guid} from 'guid-typescript';
|
import {Guid} from 'guid-typescript';
|
||||||
import logger from '../../../middleware/logger';
|
import logger from '../../../middleware/logger';
|
||||||
|
|
||||||
|
@ -36,10 +35,7 @@ eventsRouter.get('/:calendar/json', async (req: Request, res: Response) => {
|
||||||
try {
|
try {
|
||||||
// Get request params
|
// Get request params
|
||||||
let calendarName: string = req.params.calendar as string ?? '';
|
let calendarName: string = req.params.calendar as string ?? '';
|
||||||
let sessionId: string = req.query.sessionId as string ?? '';
|
|
||||||
let sessionKey: string = req.query.sessionKey as string ?? '';
|
|
||||||
let password: string = req.query.password as string ?? '';
|
let password: string = req.query.password as string ?? '';
|
||||||
let ip: string = req.socket.remoteAddress ?? '';
|
|
||||||
|
|
||||||
if (calendarName.length < 1) {
|
if (calendarName.length < 1) {
|
||||||
res.status(400).send({'message': 'Please state the name of the calendar you want events from.'});
|
res.status(400).send({'message': 'Please state the name of the calendar you want events from.'});
|
||||||
|
@ -53,7 +49,7 @@ eventsRouter.get('/:calendar/json', async (req: Request, res: Response) => {
|
||||||
|
|
||||||
let calendarId: number = calendarNames.get(calendarName)!.id;
|
let calendarId: number = calendarNames.get(calendarName)!.id;
|
||||||
|
|
||||||
if (! await CredentialService.hasAccess(calendarName, sessionId, sessionKey, password, ip)) {
|
if (!CredentialService.hasAccess(calendarName, password)) {
|
||||||
res.status(403).send({'message': 'You do not have access to the specified calendar.'});
|
res.status(403).send({'message': 'You do not have access to the specified calendar.'});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -73,10 +69,7 @@ eventsRouter.get('/:calendar/ical', async (req: Request, res: Response) => {
|
||||||
try {
|
try {
|
||||||
// Get request params
|
// Get request params
|
||||||
let calendarName: string = req.params.calendar as string ?? '';
|
let calendarName: string = req.params.calendar as string ?? '';
|
||||||
let sessionId: string = req.query.sessionId as string ?? '';
|
|
||||||
let sessionKey: string = req.query.sessionKey as string ?? '';
|
|
||||||
let password: string = req.query.password as string ?? '';
|
let password: string = req.query.password as string ?? '';
|
||||||
let ip: string = req.socket.remoteAddress ?? '';
|
|
||||||
|
|
||||||
if (calendarName.length < 1) {
|
if (calendarName.length < 1) {
|
||||||
res.status(400).send({'message': 'Please state the name of the calendar you want events from.'});
|
res.status(400).send({'message': 'Please state the name of the calendar you want events from.'});
|
||||||
|
@ -90,7 +83,7 @@ eventsRouter.get('/:calendar/ical', async (req: Request, res: Response) => {
|
||||||
|
|
||||||
let calendarId: number = calendarNames.get(calendarName)!.id;
|
let calendarId: number = calendarNames.get(calendarName)!.id;
|
||||||
|
|
||||||
if (! await CredentialService.hasAccess(calendarName, sessionId, sessionKey, password, ip)) {
|
if (!CredentialService.hasAccess(calendarName, password)) {
|
||||||
res.status(403).send({'message': 'You do not have access to the specified calendar.'});
|
res.status(403).send({'message': 'You do not have access to the specified calendar.'});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -119,14 +112,10 @@ eventsRouter.get('/:calendar/ical', async (req: Request, res: Response) => {
|
||||||
eventsRouter.post('/', async (req: Request, res: Response) => {
|
eventsRouter.post('/', async (req: Request, res: Response) => {
|
||||||
try {
|
try {
|
||||||
// Get params
|
// Get params
|
||||||
let sessionId: string = req.query.sessionId as string ?? '';
|
let password = req.body.password;
|
||||||
let sessionKey: string = req.query.sessionKey as string ?? '';
|
|
||||||
let ip: string = req.socket.remoteAddress ?? '';
|
|
||||||
|
|
||||||
let user = await UserService.checkSession(sessionId, sessionKey, ip);
|
if (!CredentialService.checkAdminPrivileges(password)) {
|
||||||
|
res.status(403).send({'message': 'Insufficient privileges.'});
|
||||||
if (!user.isActive) {
|
|
||||||
res.status(403).send({'message': 'You do not have access to the specified calendar.'});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +123,8 @@ eventsRouter.post('/', async (req: Request, res: Response) => {
|
||||||
req.body.calendarId === undefined ||
|
req.body.calendarId === undefined ||
|
||||||
isNullOrBlank(req.body.name) ||
|
isNullOrBlank(req.body.name) ||
|
||||||
req.body.startDateTime === undefined ||
|
req.body.startDateTime === undefined ||
|
||||||
req.body.endDateTime === undefined
|
req.body.endDateTime === undefined ||
|
||||||
|
isNullOrBlank(req.body.createdBy)
|
||||||
) {
|
) {
|
||||||
res.status(400).send({'message': 'Required parameters missing'});
|
res.status(400).send({'message': 'Required parameters missing'});
|
||||||
return;
|
return;
|
||||||
|
@ -150,7 +140,7 @@ eventsRouter.post('/', async (req: Request, res: Response) => {
|
||||||
endDateTime: new Date(req.body.endDateTime),
|
endDateTime: new Date(req.body.endDateTime),
|
||||||
createdDate: new Date(),
|
createdDate: new Date(),
|
||||||
location: req.body.location ?? '',
|
location: req.body.location ?? '',
|
||||||
createdById: user.userId ?? -1,
|
createdBy: req.body.createdBy ?? '',
|
||||||
url: req.body.url ?? '',
|
url: req.body.url ?? '',
|
||||||
wholeDay: req.body.wholeDay ?? false
|
wholeDay: req.body.wholeDay ?? false
|
||||||
};
|
};
|
||||||
|
@ -175,14 +165,10 @@ eventsRouter.post('/', async (req: Request, res: Response) => {
|
||||||
eventsRouter.put('/:eventId', async (req: Request, res: Response) => {
|
eventsRouter.put('/:eventId', async (req: Request, res: Response) => {
|
||||||
try {
|
try {
|
||||||
// Get params
|
// Get params
|
||||||
let sessionId: string = req.query.sessionId as string ?? '';
|
let password = req.body.password;
|
||||||
let sessionKey: string = req.query.sessionKey as string ?? '';
|
|
||||||
let ip: string = req.socket.remoteAddress ?? '';
|
|
||||||
|
|
||||||
let user = await UserService.checkSession(sessionId, sessionKey, ip);
|
if (!CredentialService.checkAdminPrivileges(password)) {
|
||||||
|
res.status(403).send({'message': 'Insufficient privileges.'});
|
||||||
if (!user.isActive) {
|
|
||||||
res.status(403).send({'message': 'You do not have access to the specified calendar.'});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,7 +177,8 @@ eventsRouter.put('/:eventId', async (req: Request, res: Response) => {
|
||||||
req.body.calendarId === undefined ||
|
req.body.calendarId === undefined ||
|
||||||
isNullOrBlank(req.body.name) ||
|
isNullOrBlank(req.body.name) ||
|
||||||
req.body.startDateTime === undefined ||
|
req.body.startDateTime === undefined ||
|
||||||
req.body.endDateTime === undefined
|
req.body.endDateTime === undefined ||
|
||||||
|
isNullOrBlank(req.body.createdBy)
|
||||||
) {
|
) {
|
||||||
res.status(400).send({'message': 'Required parameters missing'});
|
res.status(400).send({'message': 'Required parameters missing'});
|
||||||
return;
|
return;
|
||||||
|
@ -208,7 +195,6 @@ eventsRouter.put('/:eventId', async (req: Request, res: Response) => {
|
||||||
createdDate: new Date(),
|
createdDate: new Date(),
|
||||||
location: req.body.location ?? '',
|
location: req.body.location ?? '',
|
||||||
createdBy: req.body.createdBy ?? '',
|
createdBy: req.body.createdBy ?? '',
|
||||||
createdById: user.userId ?? -1,
|
|
||||||
url: req.body.url ?? '',
|
url: req.body.url ?? '',
|
||||||
wholeDay: req.body.wholeDay ?? false
|
wholeDay: req.body.wholeDay ?? false
|
||||||
};
|
};
|
||||||
|
@ -236,14 +222,10 @@ eventsRouter.put('/:eventId', async (req: Request, res: Response) => {
|
||||||
eventsRouter.delete('/:eventId', async (req: Request, res: Response) => {
|
eventsRouter.delete('/:eventId', async (req: Request, res: Response) => {
|
||||||
try {
|
try {
|
||||||
// Get params
|
// Get params
|
||||||
let sessionId: string = req.query.sessionId as string ?? '';
|
let password = req.body.password;
|
||||||
let sessionKey: string = req.query.sessionKey as string ?? '';
|
|
||||||
let ip: string = req.socket.remoteAddress ?? '';
|
|
||||||
|
|
||||||
let user = await UserService.checkSession(sessionId, sessionKey, ip);
|
if (!CredentialService.checkAdminPrivileges(password)) {
|
||||||
|
res.status(403).send({'message': 'Insufficient privileges.'});
|
||||||
if (!user.isActive) {
|
|
||||||
res.status(403).send({'message': 'You do not have access to the specified calendar.'});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,7 +247,6 @@ eventsRouter.delete('/:eventId', async (req: Request, res: Response) => {
|
||||||
createdDate: new Date(),
|
createdDate: new Date(),
|
||||||
location: '',
|
location: '',
|
||||||
createdBy: '',
|
createdBy: '',
|
||||||
createdById: -1,
|
|
||||||
url: '',
|
url: '',
|
||||||
wholeDay: false
|
wholeDay: false
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,7 +14,7 @@ export const getAllEvents = async (calendarId: number): Promise<Event[]> => {
|
||||||
let conn = await NachklangCalendarDB.getConnection();
|
let conn = await NachklangCalendarDB.getConnection();
|
||||||
let eventRows: Event[] = [];
|
let eventRows: Event[] = [];
|
||||||
try {
|
try {
|
||||||
const eventsQuery = 'SELECT e.*, u.full_name FROM events e LEFT OUTER JOIN users u ON e.created_by_id = u.user_id WHERE calendar_id = ?';
|
const eventsQuery = 'SELECT * FROM events WHERE calendar_id = ?';
|
||||||
const eventsRes = await conn.query(eventsQuery, calendarId);
|
const eventsRes = await conn.query(eventsQuery, calendarId);
|
||||||
|
|
||||||
for (let row of eventsRes) {
|
for (let row of eventsRes) {
|
||||||
|
@ -28,8 +28,7 @@ export const getAllEvents = async (calendarId: number): Promise<Event[]> => {
|
||||||
endDateTime: row.end_datetime,
|
endDateTime: row.end_datetime,
|
||||||
createdDate: row.created_date,
|
createdDate: row.created_date,
|
||||||
location: row.location,
|
location: row.location,
|
||||||
createdBy: row.full_name,
|
createdBy: row.created_by,
|
||||||
createdById: row.created_by_id,
|
|
||||||
url: row.url,
|
url: row.url,
|
||||||
wholeDay: row.whole_day
|
wholeDay: row.whole_day
|
||||||
});
|
});
|
||||||
|
@ -52,8 +51,8 @@ export const createEvent = async (event: Event): Promise<number> => {
|
||||||
let conn = await NachklangCalendarDB.getConnection();
|
let conn = await NachklangCalendarDB.getConnection();
|
||||||
try {
|
try {
|
||||||
let eventUUID = Guid.create().toString();
|
let eventUUID = Guid.create().toString();
|
||||||
const eventsQuery = 'INSERT INTO events (calendar_id, uuid, name, description, start_datetime, end_datetime, location, created_by_id, url, whole_day) VALUES (?,?,?,?,?,?,?,?,?,?) RETURNING event_id';
|
const eventsQuery = 'INSERT INTO events (calendar_id, uuid, name, description, start_datetime, end_datetime, location, created_by, url, whole_day) VALUES (?,?,?,?,?,?,?,?,?,?) RETURNING event_id';
|
||||||
const eventsRes = await conn.execute(eventsQuery, [event.calendarId, eventUUID, event.name, event.description, event.startDateTime, event.endDateTime, event.location, event.createdById, event.url, event.wholeDay]);
|
const eventsRes = await conn.execute(eventsQuery, [event.calendarId, eventUUID, event.name, event.description, event.startDateTime, event.endDateTime, event.location, event.createdBy, event.url, event.wholeDay]);
|
||||||
|
|
||||||
return eventsRes[0].event_id;
|
return eventsRes[0].event_id;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -73,8 +72,8 @@ export const createEvent = async (event: Event): Promise<number> => {
|
||||||
export const updateEvent = async (event: Event): Promise<number> => {
|
export const updateEvent = async (event: Event): Promise<number> => {
|
||||||
let conn = await NachklangCalendarDB.getConnection();
|
let conn = await NachklangCalendarDB.getConnection();
|
||||||
try {
|
try {
|
||||||
const eventsQuery = 'UPDATE events SET name = ?, description = ?, start_datetime = ?, end_datetime = ?, location = ?, created_by_id = ?, url = ?, whole_day = ? WHERE event_id = ?';
|
const eventsQuery = 'UPDATE events SET name = ?, description = ?, start_datetime = ?, end_datetime = ?, location = ?, created_by = ?, url = ?, whole_day = ? WHERE event_id = ?';
|
||||||
const eventsRes = await conn.execute(eventsQuery, [event.name, event.description, event.startDateTime, event.endDateTime, event.location, event.createdById, event.url, event.wholeDay, event.eventId]);
|
const eventsRes = await conn.execute(eventsQuery, [event.name, event.description, event.startDateTime, event.endDateTime, event.location, event.createdBy, event.url, event.wholeDay, event.eventId]);
|
||||||
|
|
||||||
return eventsRes.affectedRows;
|
return eventsRes.affectedRows;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
export interface Session {
|
|
||||||
sessionId: number;
|
|
||||||
userId: number;
|
|
||||||
sessionKey: string;
|
|
||||||
sessionKeyHash: string;
|
|
||||||
createdDate?: Date;
|
|
||||||
validUntil?: Date;
|
|
||||||
lastIP: string;
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
export interface User {
|
|
||||||
userId: number;
|
|
||||||
fullName: string;
|
|
||||||
passwordHash: string;
|
|
||||||
email: string;
|
|
||||||
isActive: boolean;
|
|
||||||
}
|
|
|
@ -1,125 +0,0 @@
|
||||||
/**
|
|
||||||
* Required External Modules and Interfaces
|
|
||||||
*/
|
|
||||||
|
|
||||||
import express, {Request, Response} from 'express';
|
|
||||||
import * as UserService from './users.service';
|
|
||||||
import {Session} from './session.interface';
|
|
||||||
import {User} from './user.interface';
|
|
||||||
import {Guid} from 'guid-typescript';
|
|
||||||
import logger from '../../../middleware/logger';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Router Definition
|
|
||||||
*/
|
|
||||||
|
|
||||||
export const usersRouter = express.Router();
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Controller Definitions
|
|
||||||
*/
|
|
||||||
|
|
||||||
// POST users/register
|
|
||||||
usersRouter.post('/register', async (req: Request, res: Response) => {
|
|
||||||
try {
|
|
||||||
const password: string = req.body.password;
|
|
||||||
const email: string = req.body.email;
|
|
||||||
const fullName: string = req.body.fullName;
|
|
||||||
const ip: string = req.socket.remoteAddress ?? '';
|
|
||||||
|
|
||||||
if (!password || !email) {
|
|
||||||
// Missing
|
|
||||||
res.status(400).send(JSON.stringify({message: 'Missing parameters'}));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the user and a session
|
|
||||||
const session: Session = await UserService.createUser(email, password, fullName, ip);
|
|
||||||
|
|
||||||
// Send the session details back to the user
|
|
||||||
res.status(201).send({
|
|
||||||
sessionId: session.sessionId,
|
|
||||||
sessionKey: session.sessionKey
|
|
||||||
});
|
|
||||||
} catch (e: any) {
|
|
||||||
let errorGuid = Guid.create().toString();
|
|
||||||
logger.error('Error handling a request: ' + e.message, {reference: errorGuid});
|
|
||||||
res.status(500).send({
|
|
||||||
'status': 'PROCESSING_ERROR',
|
|
||||||
'message': 'Internal Server Error. Try again later.',
|
|
||||||
'reference': errorGuid
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// POST users/login
|
|
||||||
usersRouter.post('/login', async (req: Request, res: Response) => {
|
|
||||||
try {
|
|
||||||
const password: string = req.body.password;
|
|
||||||
const email: string = req.body.email;
|
|
||||||
const ip: string = req.socket.remoteAddress ?? '';
|
|
||||||
|
|
||||||
if (!password || !email) {
|
|
||||||
// Missing
|
|
||||||
res.status(400).send(JSON.stringify({message: 'Missing parameters'}));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a session
|
|
||||||
const session: Session = await UserService.login(email, password, ip);
|
|
||||||
|
|
||||||
if (!session.sessionId) {
|
|
||||||
// Error logging in, probably wrong username / password
|
|
||||||
res.status(401).send(JSON.stringify({message: 'Wrong username and / or password', sessionId: -1, sessionKey: ''}));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send the session details back to the user
|
|
||||||
res.status(200).send({
|
|
||||||
sessionId: session.sessionId,
|
|
||||||
sessionKey: session.sessionKey
|
|
||||||
});
|
|
||||||
} catch (e: any) {
|
|
||||||
let errorGuid = Guid.create().toString();
|
|
||||||
logger.error('Error handling a request: ' + e.message, {reference: errorGuid});
|
|
||||||
res.status(500).send({
|
|
||||||
'status': 'PROCESSING_ERROR',
|
|
||||||
'message': 'Internal Server Error. Try again later.',
|
|
||||||
'reference': errorGuid
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// POST users/checkSessionValid
|
|
||||||
usersRouter.post('/checkSessionValid', async (req: Request, res: Response) => {
|
|
||||||
try {
|
|
||||||
const ip: string = req.socket.remoteAddress ?? '';
|
|
||||||
const session_id = req.body.sessionId;
|
|
||||||
const session_key = req.body.sessionKey;
|
|
||||||
|
|
||||||
if (!session_id || !session_key) {
|
|
||||||
// Error logging in, probably wrong username / password
|
|
||||||
res.status(401).send(JSON.stringify({messages: ['No session detected']}));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const user: User = await UserService.checkSession(session_id, session_key, ip);
|
|
||||||
|
|
||||||
if (!user.userId) {
|
|
||||||
// Error logging in, probably wrong username / password
|
|
||||||
res.status(401).send(JSON.stringify({messages: ['Invalid session']}));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
res.status(200).send(user);
|
|
||||||
} catch (e: any) {
|
|
||||||
let errorGuid = Guid.create().toString();
|
|
||||||
logger.error('Error handling a request: ' + e.message, {reference: errorGuid});
|
|
||||||
res.status(500).send({
|
|
||||||
'status': 'PROCESSING_ERROR',
|
|
||||||
'message': 'Internal Server Error. Try again later.',
|
|
||||||
'reference': errorGuid
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,182 +0,0 @@
|
||||||
import * as dotenv from 'dotenv';
|
|
||||||
import * as bcrypt from 'bcrypt';
|
|
||||||
import {Guid} from 'guid-typescript';
|
|
||||||
import {User} from './user.interface';
|
|
||||||
import {Session} from './session.interface';
|
|
||||||
import {NachklangCalendarDB} from '../Calendar.db';
|
|
||||||
|
|
||||||
dotenv.config();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Data Model Interfaces
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Service Methods
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a user record in the database, also creates a session. Returns the session if successful.
|
|
||||||
*/
|
|
||||||
export const createUser = async (email: string, password: string, fullName: string, ip: string): Promise<Session> => {
|
|
||||||
let conn = await NachklangCalendarDB.getConnection();
|
|
||||||
try {
|
|
||||||
// Hash password and generate + hash session key
|
|
||||||
const pwHash = bcrypt.hashSync(password, 10);
|
|
||||||
const sessionKey = Guid.create().toString();
|
|
||||||
const sessionKeyHash = bcrypt.hashSync(sessionKey, 10);
|
|
||||||
|
|
||||||
// Create user entry in SQL
|
|
||||||
const userQuery = 'INSERT INTO users (email, password_hash, full_name) VALUES (?, ?, ?) RETURNING user_id';
|
|
||||||
const userIdRes = await conn.query(userQuery, [email, pwHash, fullName]);
|
|
||||||
|
|
||||||
// Get user id of the created user
|
|
||||||
let userId: number = -1;
|
|
||||||
for (const row of userIdRes) {
|
|
||||||
userId = row.user_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create session
|
|
||||||
const sessionQuery = 'INSERT INTO sessions (user_id, session_key_hash, created_date, valid_until, last_ip) VALUES (?,?,NOW(),DATE_ADD(NOW(), INTERVAL 30 DAY),?) RETURNING session_id';
|
|
||||||
const sessionIdRes = await conn.query(sessionQuery, [userId, sessionKeyHash, ip]);
|
|
||||||
await conn.commit();
|
|
||||||
|
|
||||||
// Get session id of the created session
|
|
||||||
let sessionId: number = -1;
|
|
||||||
for (const row of sessionIdRes) {
|
|
||||||
sessionId = row.session_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
sessionId: sessionId,
|
|
||||||
userId: userId,
|
|
||||||
sessionKey: sessionKey,
|
|
||||||
sessionKeyHash: 'HIDDEN',
|
|
||||||
lastIP: ip
|
|
||||||
};
|
|
||||||
} catch (err) {
|
|
||||||
throw err;
|
|
||||||
} finally {
|
|
||||||
// Return connection
|
|
||||||
await conn.end();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the given credentials are valid and creates a new session if they are.
|
|
||||||
* Returns the session information in case of a successful login
|
|
||||||
*/
|
|
||||||
export const login = async (email: string, password: string, ip: string): Promise<Session> => {
|
|
||||||
let conn = await NachklangCalendarDB.getConnection();
|
|
||||||
try {
|
|
||||||
// Get saved password hash
|
|
||||||
const query = 'SELECT user_id, password_hash FROM users WHERE email = ?';
|
|
||||||
const userRows = await conn.query(query, email);
|
|
||||||
let savedHash = '';
|
|
||||||
let userId = -1;
|
|
||||||
for (const row of userRows) {
|
|
||||||
savedHash = row.password_hash;
|
|
||||||
userId = row.user_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for correct password
|
|
||||||
if (!bcrypt.compareSync(password, savedHash)) {
|
|
||||||
// Wrong password, return invalid
|
|
||||||
return {} as Session;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate + hash session key
|
|
||||||
const sessionKey = Guid.create().toString();
|
|
||||||
const sessionKeyHash = bcrypt.hashSync(sessionKey, 10);
|
|
||||||
|
|
||||||
// Create session
|
|
||||||
const sessionQuery = 'INSERT INTO sessions (user_id, session_key_hash, created_date, valid_until, last_ip) VALUES (?,?,NOW(),DATE_ADD(NOW(), INTERVAL 30 DAY),?) RETURNING session_id';
|
|
||||||
const sessionIdRes = await conn.query(sessionQuery, [userId, sessionKeyHash, ip]);
|
|
||||||
await conn.commit();
|
|
||||||
|
|
||||||
// Get session id of the created session
|
|
||||||
let sessionId: number = -1;
|
|
||||||
for (const row of sessionIdRes) {
|
|
||||||
sessionId = row.session_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
sessionId: sessionId,
|
|
||||||
userId: userId,
|
|
||||||
sessionKey: sessionKey,
|
|
||||||
sessionKeyHash: 'HIDDEN',
|
|
||||||
lastIP: ip
|
|
||||||
};
|
|
||||||
} catch (err) {
|
|
||||||
throw err;
|
|
||||||
} finally {
|
|
||||||
// Return connection
|
|
||||||
await conn.end();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the given session information are valid and returns the user information if they are
|
|
||||||
*/
|
|
||||||
export const checkSession = async (sessionId: string, sessionKey: string, ip: string): Promise<User> => {
|
|
||||||
let conn = await NachklangCalendarDB.getConnection();
|
|
||||||
try {
|
|
||||||
// Get saved session key hash
|
|
||||||
const query = 'SELECT user_id, session_key_hash, valid_until FROM sessions WHERE session_id = ?';
|
|
||||||
const sessionRows = await conn.query(query, sessionId);
|
|
||||||
let savedHash = '';
|
|
||||||
let userId = -1;
|
|
||||||
let validUntil = new Date();
|
|
||||||
for (const row of sessionRows) {
|
|
||||||
savedHash = row.session_key_hash;
|
|
||||||
userId = row.user_id;
|
|
||||||
validUntil = row.valid_until;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for correct key
|
|
||||||
if (!bcrypt.compareSync(sessionKey, savedHash)) {
|
|
||||||
// Wrong key, return invalid
|
|
||||||
return {} as User;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the session is still valid
|
|
||||||
if (validUntil <= new Date()) {
|
|
||||||
// Session expired, return invalid
|
|
||||||
return {} as User;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update session entry in SQL
|
|
||||||
const updateSessionsQuery = 'UPDATE sessions SET last_IP = ? WHERE session_id = ?';
|
|
||||||
const userIdRes = await conn.query(updateSessionsQuery, [ip, sessionId]);
|
|
||||||
await conn.commit();
|
|
||||||
|
|
||||||
// Get the other required user information
|
|
||||||
const userQuery = 'SELECT user_id, email, full_name, is_active FROM users WHERE user_id = ?';
|
|
||||||
const userRows = await conn.query(userQuery, userId);
|
|
||||||
let username = '';
|
|
||||||
let email = '';
|
|
||||||
let fullName = '';
|
|
||||||
let is_active = false;
|
|
||||||
for (const row of userRows) {
|
|
||||||
username = row.username;
|
|
||||||
email = row.email;
|
|
||||||
fullName = row.full_name;
|
|
||||||
is_active = row.is_active;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Everything is fine, return user information
|
|
||||||
return {
|
|
||||||
userId: userId,
|
|
||||||
email: email,
|
|
||||||
passwordHash: 'HIDDEN',
|
|
||||||
fullName: fullName,
|
|
||||||
isActive: is_active
|
|
||||||
};
|
|
||||||
} catch (err) {
|
|
||||||
throw err;
|
|
||||||
} finally {
|
|
||||||
// Return connection
|
|
||||||
await conn.end();
|
|
||||||
}
|
|
||||||
};
|
|
Loading…
Reference in New Issue
Block a user