diff --git a/.circleci/config.yml b/.circleci/config.yml index 7eaf394d..8909d058 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -37,10 +37,10 @@ jobs: steps: - checkout - restore_cache: - key: package-node-v6-{{ arch }}-{{ .Branch }}-{{checksum "backend/package.json"}} + key: package-node-v7-{{ arch }}-{{ .Branch }}-{{checksum "backend/package.json"}} - run: npm install --prefix backend - save_cache: - key: package-node-v6-{{ arch }}-{{ .Branch }}-{{checksum "backend/package.json"}} + key: package-node-v7-{{ arch }}-{{ .Branch }}-{{checksum "backend/package.json"}} paths: - backend/node_modules - run: @@ -53,10 +53,10 @@ jobs: steps: - checkout - restore_cache: - key: package-node-v6-{{ arch }}-{{ .Branch }}-{{checksum "backend/package.json"}} + key: package-node-v7-{{ arch }}-{{ .Branch }}-{{checksum "backend/package.json"}} - run: npm install --prefix backend - save_cache: - key: package-node-v6-{{ arch }}-{{ .Branch }}-{{checksum "backend/package.json"}} + key: package-node-v7-{{ arch }}-{{ .Branch }}-{{checksum "backend/package.json"}} paths: - backend/node_modules - run: npm run --prefix backend build:no-check @@ -66,10 +66,10 @@ jobs: steps: - checkout - restore_cache: - key: package-node-v6-{{ arch }}-{{ .Branch }}-{{checksum "backend/package.json"}} + key: package-node-v7-{{ arch }}-{{ .Branch }}-{{checksum "backend/package.json"}} - run: npm install --prefix backend - save_cache: - key: package-node-v6-{{ arch }}-{{ .Branch }}-{{checksum "backend/package.json"}} + key: package-node-v7-{{ arch }}-{{ .Branch }}-{{checksum "backend/package.json"}} paths: - backend/node_modules - run: npm run --prefix backend test diff --git a/backend/package-lock.json b/backend/package-lock.json index ebf207bb..c3667bf0 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -8883,6 +8883,14 @@ "safe-buffer": "~5.1.0" } }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, "stringify-object": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", diff --git a/backend/src/controllers/PointsController.ts b/backend/src/controllers/PointsController.ts index 5c71cf12..3a910628 100644 --- a/backend/src/controllers/PointsController.ts +++ b/backend/src/controllers/PointsController.ts @@ -16,7 +16,6 @@ export class PointsController { @OpenAPI({ security: [{ TokenAuth: [] }] }) async getAllInducteePoints(): Promise { const points: InducteePointsView[] = await this.appUserService.getAllInducteePoints(); - const pointResponses = points.map((point: InducteePointsView) => { const res = new InducteePointsResponse(); res.points = point.points; diff --git a/backend/src/controllers/UserController.ts b/backend/src/controllers/UserController.ts index 6c6e1bcc..501e4d01 100644 --- a/backend/src/controllers/UserController.ts +++ b/backend/src/controllers/UserController.ts @@ -59,7 +59,6 @@ export class UserController { @QueryParams() multipleUserQuery: MultipleUserQuery ): Promise { const multipleUsers = await this.appUserService.getAllAppUsers(multipleUserQuery); - return { users: multipleUsers }; } diff --git a/backend/src/decorators/index.ts b/backend/src/decorators/index.ts index ac7c9d21..512782dd 100644 --- a/backend/src/decorators/index.ts +++ b/backend/src/decorators/index.ts @@ -1 +1,2 @@ export { checkCurrentUserToken } from './currentUser'; +export { LogMethod } from './logging'; diff --git a/backend/src/decorators/logging/LogMethod.ts b/backend/src/decorators/logging/LogMethod.ts new file mode 100644 index 00000000..5b09f255 --- /dev/null +++ b/backend/src/decorators/logging/LogMethod.ts @@ -0,0 +1,50 @@ +import { logger, AdditionalLogContent, isLogLevel, ENDPOINT_HANDLER } from '@Logger'; + +interface MethodTypes { + [key: number]: string; +} + +const methodTypes: MethodTypes = { + 0: 'genericMethod', + 1: 'serviceMethod', + 2: 'endpointHandler', + 3: 'mapperMethod', +}; + +const isValidMethodType = (methodType: number) => { + return Object.keys(methodTypes).includes(methodType.toString()); +}; + +export function LogMethod( + methodType: number, + level: string, + message: string, + moreLogContent: AdditionalLogContent +) { + return function(target: Object, propertyKey: string, descriptor: PropertyDescriptor) { + if (!isValidMethodType(methodType)) { + throw new Error( + `Invalid method type "${methodType}" for @LogMethod decorator in ${propertyKey}` + ); + } else if (!isLogLevel(level)) { + throw new Error(`Invalid log level "${level}" for @LogMethod decorator in ${propertyKey}`); + } + + const originalMethod = descriptor.value; + descriptor.value = function(...args: any[]) { + const logContent = { + ...moreLogContent, + calledMethod: propertyKey, + methodType: methodTypes[methodType], + params: args, + }; + logger.log(level, message, logContent); + + const result = originalMethod.apply(this, args); + + return result; + }; + + return descriptor; + }; +} diff --git a/backend/src/decorators/logging/index.ts b/backend/src/decorators/logging/index.ts new file mode 100644 index 00000000..1ad00a1e --- /dev/null +++ b/backend/src/decorators/logging/index.ts @@ -0,0 +1 @@ +export { LogMethod } from './LogMethod'; diff --git a/backend/src/logging.ts b/backend/src/logging.ts index 39538a52..5f0d2f6a 100644 --- a/backend/src/logging.ts +++ b/backend/src/logging.ts @@ -1,11 +1,106 @@ -import winston from 'winston'; - +import { createLogger, format, transports } from 'winston'; import { config } from '@Config'; +export interface AdditionalLogContent { + [key: string]: string; +} + +// Function parameters are represented as an object with keys as +// parameter names and values as parameter values +interface FuncParams { + [key: string]: any; +} + +const { combine, json, timestamp, colorize, prettyPrint } = format; const logLevels = { error: 0, warn: 1, info: 2, debug: 3 }; -const logger = winston.createLogger({ +export const GENERIC_METHOD = 0, + SERVICE_METHOD = 1, + ENDPOINT_HANDLER = 2, + MAPPER_METHOD = 3; + +export const isLogLevel = (level: string): boolean => { + return ['error', 'warn', 'info', 'debug'].includes(level); +}; + +export const logger = createLogger({ levels: logLevels, - transports: [new winston.transports.Console({ level: config.maxLogLevel })], + format: combine( + colorize(), // colorize() must be the first param, per https://github.com/winstonjs/winston#colorizing-standard-logging-levels + json(), + timestamp(), + prettyPrint() + ), + transports: [new transports.Console({ level: config.maxLogLevel })], }); -export default logger; + +/** + * Logs information regarding a variable, i.e. its name, value and anything else one would + * like to log (in moreLogContent). + * + * @param {string} variableName Name of the variable being logged + * @param {any} variableValue Value of the variable being logged + * @param {string} message Default message field of log + * @param {Object} moreLogContent Other contents of the log, in JS object format + * @param {string} level Severity of log (error, warn, info or debug), default is info + */ +export const logVar = ( + variableName: string, + variableValue: any, + message = '', + moreLogContent = {}, + level = 'info' +) => { + let logLevel = level; + + if (!isLogLevel(level)) { + // Either throw an error or this, opted with this because it is not as disruptive + logLevel = 'info'; + } + + const additionalLogContent = { + variableName, + variableValue, + ...moreLogContent, + }; + + logger.log(logLevel, message, additionalLogContent); +}; + +/** + * Logs information regarding a function/method, i.e. its name, value, the file it belongs to, etc. + * and anything else one would like to log (in moreLogContent). + * + * @param {string} funcName Name of the function being logged + * @param {FuncParams} funcParams Parameters of the function being logged + * @param {string} fileName The file at which the function resides + * @param {string} message Default message field of log + * @param {Object} moreLogContent Other contents of the log, in JS object format + * @param {string} level Severity of log (error, warn, info or debug), default is info + */ +export const logFunc = ( + funcName: string, + funcParams?: FuncParams, + fileName = '', + message = '', + moreLogContent = {}, + level = 'info' +) => { + let logLevel = level; + + if (!isLogLevel(level)) { + logLevel = 'info'; + } + + const params = funcParams === undefined ? [] : funcParams; + const funcFile = fileName === '' ? '' : `in ${fileName}`; + const logMsg = `Called ${funcName}() ${funcFile}\n${message}`; + + const additionalLogContent = { + funcName, + params, + ...moreLogContent, + }; + + logger.log(logLevel, logMsg, additionalLogContent); +}; diff --git a/backend/src/services/AccountService.ts b/backend/src/services/AccountService.ts index 77a0df34..dda5443b 100644 --- a/backend/src/services/AccountService.ts +++ b/backend/src/services/AccountService.ts @@ -1,6 +1,10 @@ import admin from 'firebase-admin'; import '@firebase/auth'; +import { logFunc } from '@Logger'; + +const FILE_NAME = 'AccountService.ts'; + export class AccountService { // getAuthService is needed instead of just AuthService because we need to wait for firebase to // load first :))) @@ -16,6 +20,8 @@ export class AccountService { * process succeeds. */ async createNewAccount(id: number, email: string, password: string): Promise { + logFunc('createNewAccount', { id }, FILE_NAME); // Do not expose email or password + try { const newFirebaseUser = await this.getAuthService().createUser({ uid: id.toString(10), diff --git a/backend/src/services/AppUserService.ts b/backend/src/services/AppUserService.ts index cc498a42..4ee2a351 100644 --- a/backend/src/services/AppUserService.ts +++ b/backend/src/services/AppUserService.ts @@ -6,8 +6,11 @@ import { Availabilities, } from '@Entities'; import { MultipleUserQuery } from '@Payloads'; +import { logFunc } from '@Logger'; import { Any, getRepository, FindManyOptions } from 'typeorm'; +const FILE_NAME = 'AppUserService.ts'; + export class AppUserService { /** * Builds a query object for TypeORM to filter rows when calling find() on AppUser table. @@ -16,6 +19,8 @@ export class AppUserService { * @returns {FindManyOptions} The query object used by TypeORM to filter rows by the query parameters. */ private buildMultipleUserQuery(multipleUserQuery: MultipleUserQuery): FindManyOptions { + logFunc('buildMultipleEventQuery', { multipleUserQuery }, FILE_NAME, '', {}, 'debug'); + const { names, officers } = multipleUserQuery; const query: FindManyOptions = {}; @@ -38,8 +43,9 @@ export class AppUserService { * @returns {Promise} The saved AppUser entity. */ async saveAppUser(appUser: AppUser): Promise { - const appUserRepository = getRepository(AppUser); + logFunc('saveAppUser', { appUser }, FILE_NAME); + const appUserRepository = getRepository(AppUser); return appUserRepository.save(appUser); } @@ -50,6 +56,8 @@ export class AppUserService { * @returns {AppUser[]} Array of AppUser entities */ getAllAppUsers(multipleUserQuery: MultipleUserQuery): Promise { + logFunc('getAllAppUser', { multipleUserQuery }, FILE_NAME); + const appUserRepository = getRepository(AppUser); const query = this.buildMultipleUserQuery(multipleUserQuery); @@ -63,8 +71,9 @@ export class AppUserService { * @returns {AppUser[]} Array of AppUser entities. */ getMultipleAppUsers(ids: number[]): Promise { - const appUserRepository = getRepository(AppUser); + logFunc('getMultipleAppUsers', { ids }, FILE_NAME); + const appUserRepository = getRepository(AppUser); return appUserRepository.find({ id: Any(ids) }); } @@ -75,8 +84,9 @@ export class AppUserService { * @returns {Promise} An AppUser entity if it exists in AppUser table. */ getAppUserById(id: number): Promise { - const appUserRepository = getRepository(AppUser); + logFunc('getAppUserById', { id }, FILE_NAME); + const appUserRepository = getRepository(AppUser); return appUserRepository.findOne({ id }); } @@ -87,8 +97,9 @@ export class AppUserService { * @returns {Promise} The role of the user if they exist in the AppUser table. */ async getAppUserRoleById(id: number): Promise { - const appUser = await this.getAppUserById(id); + logFunc('getAppUserRoleById', { id }, FILE_NAME); + const appUser = await this.getAppUserById(id); return appUser?.role; } @@ -99,8 +110,9 @@ export class AppUserService { * @returns {Promise} An AppUser entity if it exists in AppUser table. */ getAppUserByEmail(email: string): Promise { - const appUserRepository = getRepository(AppUser); + logFunc('getAppUserByEmail', { email }, FILE_NAME); + const appUserRepository = getRepository(AppUser); return appUserRepository.findOne({ email }); } @@ -112,6 +124,8 @@ export class AppUserService { * @returns {Promise} The saved AppUser entity that is a non-affiliate. */ async saveNonAffiliate(appUser: AppUser): Promise { + logFunc('saveNonAffiliate', { appUser }, FILE_NAME); + const { role } = appUser; if (role !== undefined && role !== AppUserRole.GUEST) { @@ -134,8 +148,9 @@ export class AppUserService { * the one they put in the URL parameter userID. */ isUnauthedUserOrNonOfficer(appUser: AppUser, urlUserID: number): boolean { - const { role, id: requesterID } = appUser; + logFunc('isUnauthedUserOrNonOfficer', { appUser, urlUserID }, FILE_NAME); + const { role, id: requesterID } = appUser; return ( !(role === AppUserRole.ADMIN || role === AppUserRole.OFFICER) && requesterID != urlUserID ); @@ -148,6 +163,8 @@ export class AppUserService { * @returns {boolean} Whether the passed-in AppUser has officer or admin role or not. */ isOfficer(appUser: AppUser): boolean { + logFunc('isOfficer', { appUser }, FILE_NAME); + return appUser.role === AppUserRole.OFFICER || appUser.role === AppUserRole.ADMIN; } @@ -158,10 +175,14 @@ export class AppUserService { * @returns {boolean} Whether the passed-in AppUser has guest role or not. */ isGuest(appUser: AppUser): boolean { + logFunc('isGuest', { appUser }, FILE_NAME); + return appUser.role === AppUserRole.GUEST; } async getAllInducteePoints(): Promise { + logFunc('getAllInducteePoints', {}, FILE_NAME); + const inducteePointsRepo = getRepository(InducteePointsView); return await inducteePointsRepo.find({}); } @@ -172,6 +193,8 @@ export class AppUserService { * @returns {InducteePoints} */ async getInducteePoints(appUserID: number): Promise { + logFunc('getInducteePoints', { appUserID }, FILE_NAME); + const inducteePointsRepo = getRepository(InducteePointsView); return await inducteePointsRepo.findOne({ user: appUserID }); } @@ -182,6 +205,8 @@ export class AppUserService { * @returns {InducteePoints} */ async getMemberPoints(appUserID: number): Promise { + logFunc('getMemberPoints', { appUserID }, FILE_NAME); + const memberPointsRepo = getRepository(MemberPointsView); return await memberPointsRepo.findOne({ user: appUserID }); } @@ -190,6 +215,8 @@ export class AppUserService { appUser: AppUser, availabilities: Availabilities ): Promise { + logFunc('updateInterviewAvailabilities', { appUser, availabilities }, FILE_NAME); + appUser.availabilities = availabilities; return this.saveAppUser(appUser); } diff --git a/backend/src/services/AttendanceService.ts b/backend/src/services/AttendanceService.ts index 16d73140..5ba464e6 100644 --- a/backend/src/services/AttendanceService.ts +++ b/backend/src/services/AttendanceService.ts @@ -54,6 +54,8 @@ export class AttendanceService { * is no such entity in the DB. */ async getAttendance(attendeeId: number, eventId: number): Promise { + logFunc('getAttendance', { attendeeId, eventId }, FILE_NAME); + const attendanceRepository = getRepository(Attendance); return attendanceRepository.findOne( { @@ -70,6 +72,8 @@ export class AttendanceService { * Gets all attendances of specified user. Fetches events as well. */ async getUserAttendance(attendeeId: number): Promise { + logFunc('getUserAttendance', { attendeeId }, FILE_NAME); + const attendanceRepository = getRepository(Attendance); return attendanceRepository.find({ @@ -91,6 +95,8 @@ export class AttendanceService { event: Event, multipleAttendanceQuery: MultipleAttendanceQuery ): Promise { + logFunc('getEventAttendance', { event, multipleAttendanceQuery }, FILE_NAME); + const attendanceRepository = getRepository(Attendance); const query = this.buildMultipleAttendanceQuery(event, multipleAttendanceQuery, true); @@ -112,6 +118,8 @@ export class AttendanceService { attendeeId: number, officerId: number ): Promise { + logFunc('checkOffAttendance', { eventId, attendeeId, officerId }, FILE_NAME); + const attendanceRepository = getRepository(Attendance); const attendance: Attendance = await this.getAttendance(attendeeId, eventId); @@ -128,6 +136,8 @@ export class AttendanceService { // Precondition: event is fetched within attendance getAttendancePoints(attendance: Attendance): number { + logFunc('getAttendancePoints', { attendance }, FILE_NAME); + if (attendance.event.type === EventType.MENTORSHIP) { return 1.0; } @@ -199,6 +209,8 @@ export class AttendanceService { * @returns {Promise} A new Attendance entity, but undefined for duplicate Attendance entities. */ async registerAttendance(event: Event, attendee: AppUser): Promise { + logFunc('registerAttendance', { event, attendee }, FILE_NAME); + const attendanceRepository = getRepository(Attendance); const { role } = attendee; diff --git a/backend/src/services/AuthenticationService.ts b/backend/src/services/AuthenticationService.ts index 91ca2a43..3b79e803 100644 --- a/backend/src/services/AuthenticationService.ts +++ b/backend/src/services/AuthenticationService.ts @@ -3,11 +3,16 @@ import admin from 'firebase-admin'; import { AppUserService, AppUserServiceImpl } from './AppUserService'; import { AppUser } from '@Entities'; import { config } from '../config'; +import { logFunc } from '@Logger'; + +const FILE_NAME = 'AuthenticationService.ts'; export class AuthenticationService { constructor(private appUserService: AppUserService) {} async firebaseVerifyIdToken(token: string): Promise { + logFunc('firebaseVerifyIdToken', {}, FILE_NAME, '', {}, 'debug'); // Never expose tokens + try { const splitToken: string[] = token.split(' '); const userToken = splitToken[1]; @@ -32,6 +37,8 @@ export class AuthenticationService { } async localVerifyIdToken(token: string): Promise { + logFunc('localVerifyIdToken', {}, FILE_NAME, '', {}, 'debug'); // Never expose tokens + try { const splitToken: string[] = token.split(' '); const userToken = splitToken[1]; @@ -49,6 +56,8 @@ export class AuthenticationService { } async verifyToken(token: string): Promise { + logFunc('verifyIdToken', {}, FILE_NAME, '', {}, 'debug'); // Never expose tokens + const { devAuth } = config; if (devAuth) { diff --git a/backend/src/services/AuthorizationService.ts b/backend/src/services/AuthorizationService.ts index 161e98f1..e7b8ba22 100644 --- a/backend/src/services/AuthorizationService.ts +++ b/backend/src/services/AuthorizationService.ts @@ -1,9 +1,13 @@ import { AppUser } from '@Entities'; +import { logFunc } from '@Logger'; + +const FILE_NAME = 'AuthorizationService.ts'; export class AuthorizationService { hasSufficientRole(permittedRoles: Array, appUserToCheck: AppUser): boolean { - const { role } = appUserToCheck; + logFunc('hasSufficientRole', { permittedRoles }, FILE_NAME); + const { role } = appUserToCheck; return permittedRoles.includes(role); } } diff --git a/backend/src/services/EventService.ts b/backend/src/services/EventService.ts index badab215..8696e087 100644 --- a/backend/src/services/EventService.ts +++ b/backend/src/services/EventService.ts @@ -4,6 +4,9 @@ import { RSVPService, RSVPServiceImpl } from './RSVPService'; import { getRepository, FindManyOptions, Not } from 'typeorm'; import { MultipleAttendanceQuery, MultipleEventQuery } from '@Payloads'; +import { logFunc } from '@Logger'; + +const FILE_NAME = 'EventService.ts'; // For logging export class EventService { constructor(private attendanceService: AttendanceService, private rsvpService: RSVPService) {} @@ -13,6 +16,15 @@ export class EventService { multipleEventQuery: MultipleEventQuery, isOfficer: boolean ): FindManyOptions { + logFunc( + 'buildMultipleEventQuery', + { multipleEventQuery, isOfficer }, + FILE_NAME, + '', + {}, + 'debug' + ); + const { pending, ready, complete } = multipleEventQuery; const query: FindManyOptions = {}; const whereArr = []; @@ -58,6 +70,8 @@ export class EventService { * @returns {Promise} Saved event. */ async saveEvent(event: Event): Promise { + logFunc('saveEvent', { event }, FILE_NAME); + const eventRepository = getRepository(Event); return eventRepository.save(event); @@ -69,6 +83,8 @@ export class EventService { * @returns {Event[]} Array of all events. */ getAllEvents(multipleEventQuery: MultipleEventQuery, isOfficer: boolean): Promise { + logFunc('getAllEvents', { multipleEventQuery, isOfficer }, FILE_NAME); + const eventRepository = getRepository(Event); const query = this.buildMultipleEventQuery(multipleEventQuery, isOfficer); @@ -82,6 +98,8 @@ export class EventService { * @returns {Promise} Event with given id. */ getEventById(id: number): Promise { + logFunc('getEventById', { id }, FILE_NAME); + const eventRepository = getRepository(Event); return eventRepository.findOne({ id }); @@ -94,6 +112,8 @@ export class EventService { * @returns {Promise} Deleted event. */ async deleteEvent(id: number): Promise { + logFunc('deleteEvent', { id }, FILE_NAME); + const eventRepository = getRepository(Event); const event = await eventRepository.findOne({ id }); @@ -104,6 +124,8 @@ export class EventService { eventId: number, multipleAttendanceQuery: MultipleAttendanceQuery ): Promise { + logFunc('getEventAttendances', { eventId, multipleAttendanceQuery }, FILE_NAME); + const event = await this.getEventById(eventId); if (event === undefined) { @@ -119,6 +141,8 @@ export class EventService { } async getEventRSVPs(eventId: number): Promise { + logFunc('getEventRSVPs', { eventId }, FILE_NAME); + const event = await this.getEventById(eventId); if (event === undefined) { @@ -143,6 +167,8 @@ export class EventService { eventId: number, appUser: AppUser ): Promise { + logFunc('registerEventAttendance', { eventId, appUser }, FILE_NAME); + const eventRepository = getRepository(Event); const event = await eventRepository.findOne({ id: eventId }); const newAttendance = await this.attendanceService.registerAttendance(event, appUser); @@ -159,6 +185,8 @@ export class EventService { * @returns {Promise} A new RSVP entity. */ async registerEventRSVP(eventId: number, appUser: AppUser): Promise { + logFunc('registerEventRSVP', { eventId, appUser }, FILE_NAME); + const eventRepository = getRepository(Event); const event = await eventRepository.findOne({ id: eventId }); const newRSVP = await this.rsvpService.registerRSVP(event, appUser); diff --git a/backend/src/services/LocalStorageService.ts b/backend/src/services/LocalStorageService.ts index ac88a14f..58de2cb8 100644 --- a/backend/src/services/LocalStorageService.ts +++ b/backend/src/services/LocalStorageService.ts @@ -1,7 +1,9 @@ import fs from 'fs'; import { Response } from 'express'; +import { logFunc } from '@Logger'; const dir_path = process.cwd() + '/local_fs/'; +const FILE_NAME = 'LocalStorageService.ts'; if (!fs.existsSync(dir_path)) { fs.mkdirSync(dir_path); @@ -9,6 +11,8 @@ if (!fs.existsSync(dir_path)) { export class LocalStorageService { async uploadFile(fileName: string, file: Express.Multer.File, options: Object): Promise { + logFunc('uploadFile', {}, FILE_NAME); + let fileNameKey = fileName; if (options) { if ('appendFileName' in options) { @@ -29,6 +33,8 @@ export class LocalStorageService { } async downloadFile(fileName: string, res: Response, options: Object): Promise { + logFunc('downloadFile', {}, FILE_NAME); + try { if (!options) { throw new Error('Options for bucket/container not specified'); diff --git a/backend/src/services/RSVPService.ts b/backend/src/services/RSVPService.ts index 5cd9d2e4..37475850 100644 --- a/backend/src/services/RSVPService.ts +++ b/backend/src/services/RSVPService.ts @@ -1,8 +1,13 @@ import { AppUser, Event, RSVP } from '@Entities'; import { getRepository, FindManyOptions } from 'typeorm'; +import { logFunc } from '@Logger'; + +const FILE_NAME = 'RSVPService.ts'; export class RSVPService { private buildMultipleRSVPQuery(event: Event, cacheOn: boolean): FindManyOptions { + logFunc('buildMultipleRSVPQuery', { event, cacheOn }, FILE_NAME, '', {}, 'debug'); + const query: FindManyOptions = {}; query.where = { event: event }; @@ -23,6 +28,8 @@ export class RSVPService { * @returns {Promise} A new RSVP entity, but undefined for duplicate RSVP. */ async registerRSVP(event: Event, appUser: AppUser): Promise { + logFunc('registerRSVP', { event, appUser }, FILE_NAME); + const rsvpRepository = getRepository(RSVP); const rsvpBeingProcessed = { event, appUser }; const newRSVP = rsvpRepository.create(rsvpBeingProcessed); @@ -37,6 +44,8 @@ export class RSVPService { } async getEventRSVPs(event: Event): Promise { + logFunc('getEventRSVPs', { event }, FILE_NAME); + const rsvpRepository = getRepository(RSVP); const query = this.buildMultipleRSVPQuery(event, true); diff --git a/backend/src/services/ResumeService.ts b/backend/src/services/ResumeService.ts index 2e40b9ac..bebae1e9 100644 --- a/backend/src/services/ResumeService.ts +++ b/backend/src/services/ResumeService.ts @@ -4,8 +4,13 @@ import multer from 'multer'; import { AppUser } from '@Entities'; import { StorageService, StorageServiceImpl } from '@Services'; import { config } from '@Config'; +import { logFunc } from '@Logger'; + +const FILE_NAME = 'ResumeService.ts'; const fileFilter = (req: Express.Request, file: Express.Multer.File, cb: Function): void => { + logFunc('fileFilter', {}, FILE_NAME); + if (file.mimetype.includes('pdf')) { cb(null, true); } else { @@ -35,6 +40,8 @@ export class ResumeService { * @return {Promise} A Promise that indicates whether the upload succeeded. */ async uploadResume(appUser: AppUser, file: Express.Multer.File): Promise { + logFunc('uploadResume', { appUser }, FILE_NAME); + const storedfileName = `${appUser.firstName}_${appUser.lastName}_Resume`; const options = { appendFileName: `${appUser.id}`, @@ -52,6 +59,8 @@ export class ResumeService { * @param {Response} res The response object. */ async downloadResume(appUser: AppUser, res: Response): Promise { + logFunc('downloadResume', { appUser }, FILE_NAME); + const storedfileName = `${appUser.firstName}_${appUser.lastName}_Resume_${appUser.id}`; const options = { bucketName: config.awsConfig.resumeBucketName, diff --git a/backend/src/services/StorageService.ts b/backend/src/services/StorageService.ts index 01ba3408..958caaec 100644 --- a/backend/src/services/StorageService.ts +++ b/backend/src/services/StorageService.ts @@ -3,7 +3,10 @@ import { Response } from 'express'; import { loadAWS_S3 } from '../loaders'; import { BadRequestError } from 'routing-controllers'; +import { logFunc } from '@Logger'; + const s3 = loadAWS_S3(); +const FILE_NAME = 'StorageService.ts'; type UploadOptions = { appendFileName: string; @@ -29,6 +32,8 @@ export class StorageService { file: Express.Multer.File, options: UploadOptions ): Promise { + logFunc('uploadFile', {}, FILE_NAME); + let params; try { let fileNameKey = fileName; @@ -87,6 +92,8 @@ export class StorageService { res: Response, options: DownloadOptions ): Promise { + logFunc('downloadFile', {}, FILE_NAME); + try { if (options) { if (!options.bucketName) { @@ -119,6 +126,8 @@ export class StorageService { * @returns {Promise | null>} A Promise that returns the list of all objects in the bucket. */ async getFileIndex(bucketName: string): Promise | null> { + logFunc('getFileIndex', {}, FILE_NAME); + try { const params = { Bucket: bucketName,