From 62655eb47fde46ae980d3e8ed82297fcb9f53927 Mon Sep 17 00:00:00 2001 From: "Patrik J. Braun" Date: Wed, 28 Nov 2018 23:49:33 +0100 Subject: [PATCH] improving types --- backend/middlewares/AdminMWs.ts | 3 +- .../customtypings/ExtendedRequest.d.ts | 36 ++++++++----- backend/middlewares/customtypings/jimp.d.ts | 10 ---- .../thumbnail/ThumbnailGeneratorMWs.ts | 1 - backend/model/PasswordHelper.ts | 6 +-- .../model/diagnostics/ConfigDiagnostics.ts | 6 +-- backend/model/memory/GalleryManager.ts | 4 +- backend/model/memory/UserManager.ts | 2 +- backend/model/sql/GalleryManager.ts | 22 ++++---- backend/model/sql/IGalleryManager.ts | 4 +- backend/model/sql/IndexingManager.ts | 2 +- backend/model/sql/SearchManager.ts | 2 +- backend/model/threading/ThumbnailWorker.ts | 6 +-- backend/routes/AdminRouter.ts | 7 +-- backend/routes/ErrorRouter.ts | 7 +-- backend/routes/GalleryRouter.ts | 25 ++++----- backend/routes/LoggerRouter.ts | 31 +++++++---- backend/routes/NotificationRouter.ts | 5 +- backend/routes/PublicRouter.ts | 21 ++++++-- backend/routes/UserRouter.ts | 19 +++---- backend/server.ts | 4 +- backend/tsconfig.json | 1 + common/Utils.ts | 3 +- common/config/public/Config.ts | 2 +- frontend/app/app.component.ts | 6 ++- frontend/app/app.module.ts | 2 +- frontend/app/gallery/fullscreen.service.ts | 9 ++++ frontend/app/gallery/gallery.component.ts | 25 +++++---- frontend/app/gallery/gallery.service.ts | 7 +-- .../gallery/grid/grid.gallery.component.ts | 6 +-- .../photo/photo.grid.gallery.component.ts | 12 ++--- .../info-panel.lightbox.gallery.component.ts | 2 +- .../lightbox/lightbox.gallery.component.ts | 10 ++-- .../media/media.lightbox.gallery.component.ts | 2 +- .../lightbox.map.gallery.component.ts | 2 +- .../app/gallery/map/map.gallery.component.ts | 2 +- .../random-query-builder.gallery.component.ts | 9 ++-- .../search/search.gallery.component.ts | 9 ++-- frontend/app/gallery/share.service.ts | 13 ++--- .../gallery/share/share.gallery.component.ts | 3 +- .../network/autehentication.service.spec.ts | 6 +-- .../app/model/network/network.service.spec.ts | 16 +++--- frontend/app/model/network/network.service.ts | 6 +-- .../app/model/network/user.service.spec.ts | 8 +-- frontend/app/model/notification.service.ts | 8 +-- frontend/app/model/query.service.ts | 5 +- frontend/app/pipes/StringifyRolePipe.ts | 2 +- .../_abstract/abstract.settings.component.ts | 11 ++-- .../indexing/indexing.settings.service.ts | 2 +- package.json | 2 + .../middlewares/user/AuthenticationMWs.ts | 54 +++++++++---------- test/backend/unit/model/sql/TestHelper.ts | 7 ++- tsconfig.json | 1 + 53 files changed, 262 insertions(+), 214 deletions(-) delete mode 100644 backend/middlewares/customtypings/jimp.d.ts diff --git a/backend/middlewares/AdminMWs.ts b/backend/middlewares/AdminMWs.ts index 8dc6c46..694f892 100644 --- a/backend/middlewares/AdminMWs.ts +++ b/backend/middlewares/AdminMWs.ts @@ -13,7 +13,6 @@ import {ProjectPath} from '../ProjectPath'; import {PrivateConfigClass} from '../../common/config/private/PrivateConfigClass'; import {IndexingDTO} from '../../common/entities/settings/IndexingDTO'; - const LOG_TAG = '[AdminMWs]'; export class AdminMWs { @@ -347,7 +346,7 @@ export class AdminMWs { } } - public static async resetIndexes(req: Request, res: Response, next: NextFunction) { + public static async resetIndexes(req: Express.Request, res: Response, next: NextFunction) { try { await ObjectManagerRepository.getInstance().IndexingManager.reset(); req.resultPipe = 'ok'; diff --git a/backend/middlewares/customtypings/ExtendedRequest.d.ts b/backend/middlewares/customtypings/ExtendedRequest.d.ts index cda882a..048aed1 100644 --- a/backend/middlewares/customtypings/ExtendedRequest.d.ts +++ b/backend/middlewares/customtypings/ExtendedRequest.d.ts @@ -1,18 +1,28 @@ -declare module Express { - export interface Request { - resultPipe?: any; - body?: { - loginCredential - }; - } +import {LoginCredential} from '../../../common/entities/LoginCredential'; +import {UserEntity} from '../../model/sql/enitites/UserEntity'; - export interface Response { - tpl?: any; - } - export interface Session { - user?; - rememberMe?: boolean; + + +declare global { + namespace Express { + interface Request { + + resultPipe?: any; + body?: { + loginCredential: LoginCredential + }; + locale?: string; + } + + interface Response { + tpl?: any; + } + interface Session { + user?: UserEntity; + rememberMe?: boolean; + } } } + diff --git a/backend/middlewares/customtypings/jimp.d.ts b/backend/middlewares/customtypings/jimp.d.ts deleted file mode 100644 index 2b2445b..0000000 --- a/backend/middlewares/customtypings/jimp.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -declare module 'jimp' { - function read(fileName); - - const RESIZE_NEAREST_NEIGHBOR; - const RESIZE_BILINEAR; - const RESIZE_BICUBIC; - const RESIZE_HERMITE; - const RESIZE_BEZIER; - const AUTO: any; -} diff --git a/backend/middlewares/thumbnail/ThumbnailGeneratorMWs.ts b/backend/middlewares/thumbnail/ThumbnailGeneratorMWs.ts index 98feee0..144cbf1 100644 --- a/backend/middlewares/thumbnail/ThumbnailGeneratorMWs.ts +++ b/backend/middlewares/thumbnail/ThumbnailGeneratorMWs.ts @@ -1,4 +1,3 @@ -/// import * as path from 'path'; import * as crypto from 'crypto'; import * as fs from 'fs'; diff --git a/backend/model/PasswordHelper.ts b/backend/model/PasswordHelper.ts index 94c0390..66743d7 100644 --- a/backend/model/PasswordHelper.ts +++ b/backend/model/PasswordHelper.ts @@ -1,4 +1,4 @@ -let bcrypt; +let bcrypt: any; try { bcrypt = require('bcrypt'); } catch (err) { @@ -6,12 +6,12 @@ try { } export class PasswordHelper { - public static cryptPassword(password) { + public static cryptPassword(password: string) { const salt = bcrypt.genSaltSync(9); return bcrypt.hashSync(password, salt); } - public static comparePassword(password, encryptedPassword) { + public static comparePassword(password: string, encryptedPassword: string) { return bcrypt.compareSync(password, encryptedPassword); } } diff --git a/backend/model/diagnostics/ConfigDiagnostics.ts b/backend/model/diagnostics/ConfigDiagnostics.ts index 563cc2b..0fe6e6a 100644 --- a/backend/model/diagnostics/ConfigDiagnostics.ts +++ b/backend/model/diagnostics/ConfigDiagnostics.ts @@ -31,11 +31,11 @@ export class ConfigDiagnostics { try { if (videoConfig.enabled === true) { const ffmpeg = FFmpegFactory.get(); - ffmpeg().getAvailableCodecs((err) => { + ffmpeg().getAvailableCodecs((err: Error) => { if (err) { return reject(new Error('Error accessing ffmpeg, cant find executable: ' + err.toString())); } - ffmpeg(__dirname + '/blank.jpg').ffprobe((err2) => { + ffmpeg(__dirname + '/blank.jpg').ffprobe((err2: Error) => { if (err2) { return reject(new Error('Error accessing ffmpeg-probe, cant find executable: ' + err2.toString())); } @@ -60,7 +60,7 @@ export class ConfigDiagnostics { case ThumbnailProcessingLib.gm: const gm = require('gm'); await new Promise((resolve, reject) => { - gm(ProjectPath.FrontendFolder + '/assets/icon.png').size((err, value) => { + gm(ProjectPath.FrontendFolder + '/assets/icon.png').size((err: Error) => { if (err) { return reject(err.toString()); } diff --git a/backend/model/memory/GalleryManager.ts b/backend/model/memory/GalleryManager.ts index 122f4bd..19ac258 100644 --- a/backend/model/memory/GalleryManager.ts +++ b/backend/model/memory/GalleryManager.ts @@ -1,5 +1,5 @@ import {DirectoryDTO} from '../../../common/entities/DirectoryDTO'; -import {IGalleryManager} from '../interfaces/IGalleryManager'; +import {IGalleryManager, RandomQuery} from '../interfaces/IGalleryManager'; import * as path from 'path'; import * as fs from 'fs'; import {DiskManager} from '../DiskManger'; @@ -24,7 +24,7 @@ export class GalleryManager implements IGalleryManager { return DiskManager.scanDirectory(relativeDirectoryName); } - getRandomPhoto(RandomQuery): Promise { + getRandomPhoto(queryFilter: RandomQuery): Promise { throw new Error('Random media is not supported without database'); } } diff --git a/backend/model/memory/UserManager.ts b/backend/model/memory/UserManager.ts index 7071836..cada72d 100644 --- a/backend/model/memory/UserManager.ts +++ b/backend/model/memory/UserManager.ts @@ -9,7 +9,7 @@ import {PasswordHelper} from '../PasswordHelper'; export class UserManager implements IUserManager { private db: { users?: UserDTO[], idCounter?: number } = {}; - private readonly dbPath; + private readonly dbPath: string; generateId(): string { function s4() { diff --git a/backend/model/sql/GalleryManager.ts b/backend/model/sql/GalleryManager.ts index fd7f5d7..c0d0c8c 100644 --- a/backend/model/sql/GalleryManager.ts +++ b/backend/model/sql/GalleryManager.ts @@ -121,7 +121,7 @@ export class GalleryManager implements IGalleryManager, ISQLGalleryManager { } - public indexDirectory(relativeDirectoryName): Promise { + public indexDirectory(relativeDirectoryName: string): Promise { return new Promise(async (resolve, reject) => { try { const scannedDirectory = await DiskManager.scanDirectory(relativeDirectoryName); @@ -217,22 +217,22 @@ export class GalleryManager implements IGalleryManager, ISQLGalleryManager { if (!!currentDir) {// Updated parent dir (if it was in the DB previously) currentDir.lastModified = scannedDirectory.lastModified; currentDir.lastScanned = scannedDirectory.lastScanned; - // const media: MediaEntity[] = currentDir.media; - // delete currentDir.media; + // const media: MediaEntity[] = currentDir.media; + // delete currentDir.media; currentDir = await directoryRepository.save(currentDir); /*if (media) { media.forEach(m => m.directory = currentDir); currentDir.media = await this.saveMedia(connection, media); }*/ } else { - // const media = scannedDirectory.media; - // delete scannedDirectory.media; + // const media = scannedDirectory.media; + // delete scannedDirectory.media; (scannedDirectory).lastScanned = scannedDirectory.lastScanned; currentDir = await directoryRepository.save(scannedDirectory); - /* if (media) { - media.forEach(m => m.directory = currentDir); - currentDir.media = await this.saveMedia(connection, media); - }*/ + /* if (media) { + media.forEach(m => m.directory = currentDir); + currentDir.media = await this.saveMedia(connection, media); + }*/ } // save subdirectories @@ -296,7 +296,7 @@ export class GalleryManager implements IGalleryManager, ISQLGalleryManager { scannedDirectory.media[i].directory = scannedDirectory; media.directory = currentDir; mediaToSave.push(media); - }else if (!Utils.equalsFilter(media.metadata, scannedDirectory.media[i].metadata)) { + } else if (!Utils.equalsFilter(media.metadata, scannedDirectory.media[i].metadata)) { media.metadata = scannedDirectory.media[i].metadata; mediaToSave.push(media); } @@ -330,7 +330,7 @@ export class GalleryManager implements IGalleryManager, ISQLGalleryManager { } } await fileRepository.save(metaFilesToSave); - // await fileRepository.remove(indexedMetaFiles); + // await fileRepository.remove(indexedMetaFiles); } protected async saveMedia(connection: Connection, mediaList: MediaDTO[]): Promise { diff --git a/backend/model/sql/IGalleryManager.ts b/backend/model/sql/IGalleryManager.ts index 7f0b6ad..d256917 100644 --- a/backend/model/sql/IGalleryManager.ts +++ b/backend/model/sql/IGalleryManager.ts @@ -1,11 +1,11 @@ import {DirectoryDTO} from '../../../common/entities/DirectoryDTO'; import {IGalleryManager} from '../interfaces/IGalleryManager'; -export interface ISQLGalleryManager extends IGalleryManager{ +export interface ISQLGalleryManager extends IGalleryManager { listDirectory(relativeDirectoryName: string, knownLastModified?: number, knownLastScanned?: number): Promise; - indexDirectory(relativeDirectoryName): Promise; + indexDirectory(relativeDirectoryName: string): Promise; } diff --git a/backend/model/sql/IndexingManager.ts b/backend/model/sql/IndexingManager.ts index e335db6..538d23c 100644 --- a/backend/model/sql/IndexingManager.ts +++ b/backend/model/sql/IndexingManager.ts @@ -16,7 +16,7 @@ const LOG_TAG = '[IndexingManager]'; export class IndexingManager implements IIndexingManager { directoriesToIndex: string[] = []; - indexingProgress = null; + indexingProgress: { current: string, left: number, indexed: number } = null; enabled = false; private indexNewDirectory = async (createThumbnails: boolean = false) => { if (this.directoriesToIndex.length === 0) { diff --git a/backend/model/sql/SearchManager.ts b/backend/model/sql/SearchManager.ts index b32b69a..d750042 100644 --- a/backend/model/sql/SearchManager.ts +++ b/backend/model/sql/SearchManager.ts @@ -192,7 +192,7 @@ export class SearchManager implements ISearchManager { } private encapsulateAutoComplete(values: string[], type: SearchTypes): Array { - const res = []; + const res: AutoCompleteItem[] = []; values.forEach((value) => { res.push(new AutoCompleteItem(value, type)); }); diff --git a/backend/model/threading/ThumbnailWorker.ts b/backend/model/threading/ThumbnailWorker.ts index 3f28e87..eeb1526 100644 --- a/backend/model/threading/ThumbnailWorker.ts +++ b/backend/model/threading/ThumbnailWorker.ts @@ -9,7 +9,7 @@ export class ThumbnailWorker { private static imageRenderer: (input: RendererInput) => Promise = null; private static videoRenderer: (input: RendererInput) => Promise = null; - private static rendererType = null; + private static rendererType: ThumbnailProcessingLib = null; public static render(input: RendererInput, renderer: ThumbnailProcessingLib): Promise { if (input.type === ThumbnailSourceType.Image) { @@ -62,7 +62,7 @@ export class VideoRendererFactory { if (!!err || data === null) { return reject(err.toString()); } - /// console.log(data); + /// console.log(data); let width = null; let height = null; for (let i = 0; i < data.streams.length; i++) { @@ -151,7 +151,7 @@ export class ImageRendererFactory { image.quality(60); // set JPEG quality await new Promise((resolve, reject) => { - image.write(input.thPath, (err) => { // save + image.write(input.thPath, (err: Error | null) => { // save if (err) { return reject(err); } diff --git a/backend/routes/AdminRouter.ts b/backend/routes/AdminRouter.ts index a635999..af40137 100644 --- a/backend/routes/AdminRouter.ts +++ b/backend/routes/AdminRouter.ts @@ -2,16 +2,17 @@ import {AuthenticationMWs} from '../middlewares/user/AuthenticationMWs'; import {UserRoles} from '../../common/entities/UserDTO'; import {RenderingMWs} from '../middlewares/RenderingMWs'; import {AdminMWs} from '../middlewares/AdminMWs'; +import {Express} from 'express'; export class AdminRouter { - public static route(app: any) { + public static route(app: Express) { this.addIndexGallery(app); this.addSettings(app); } - private static addIndexGallery(app) { + private static addIndexGallery(app: Express) { app.get('/api/admin/indexes/job/progress', AuthenticationMWs.authenticate, AuthenticationMWs.authorise(UserRoles.Admin), @@ -38,7 +39,7 @@ export class AdminRouter { ); } - private static addSettings(app) { + private static addSettings(app: Express) { app.get('/api/settings', AuthenticationMWs.authenticate, AuthenticationMWs.authorise(UserRoles.Admin), diff --git a/backend/routes/ErrorRouter.ts b/backend/routes/ErrorRouter.ts index f38351f..de6e08d 100644 --- a/backend/routes/ErrorRouter.ts +++ b/backend/routes/ErrorRouter.ts @@ -3,21 +3,22 @@ import {ErrorCodes, ErrorDTO} from '../../common/entities/Error'; import {Logger} from '../Logger'; import Request = Express.Request; import Response = Express.Response; +import {Express} from 'express'; export class ErrorRouter { - public static route(app: any) { + public static route(app: Express) { this.addApiErrorHandler(app); this.addGenericHandler(app); } - private static addApiErrorHandler(app) { + private static addApiErrorHandler(app: Express) { app.use('/api/*', RenderingMWs.renderError ); } - private static addGenericHandler(app) { + private static addGenericHandler(app: Express) { app.use((err: any, req: Request, res: Response, next: Function) => { // Flush out the stack to the console Logger.error('Unexpected error:'); diff --git a/backend/routes/GalleryRouter.ts b/backend/routes/GalleryRouter.ts index 3e668fd..6b11263 100644 --- a/backend/routes/GalleryRouter.ts +++ b/backend/routes/GalleryRouter.ts @@ -1,4 +1,5 @@ import {AuthenticationMWs} from '../middlewares/user/AuthenticationMWs'; +import {Express} from 'express'; import {GalleryMWs} from '../middlewares/GalleryMWs'; import {RenderingMWs} from '../middlewares/RenderingMWs'; import {ThumbnailGeneratorMWs} from '../middlewares/thumbnail/ThumbnailGeneratorMWs'; @@ -6,7 +7,7 @@ import {UserRoles} from '../../common/entities/UserDTO'; import {ThumbnailSourceType} from '../model/threading/ThumbnailWorker'; export class GalleryRouter { - public static route(app: any) { + public static route(app: Express) { this.addGetImageIcon(app); this.addGetImageThumbnail(app); @@ -22,7 +23,7 @@ export class GalleryRouter { this.addAutoComplete(app); } - private static addDirectoryList(app) { + private static addDirectoryList(app: Express) { app.get(['/api/gallery/content/:directory(*)', '/api/gallery/', '/api/gallery//'], AuthenticationMWs.authenticate, AuthenticationMWs.authoriseDirectory, @@ -34,7 +35,7 @@ export class GalleryRouter { } - private static addGetImage(app) { + private static addGetImage(app: Express) { app.get(['/api/gallery/content/:filePath(*\.(jpg|bmp|png|gif|jpeg))'], AuthenticationMWs.authenticate, // TODO: authorize path @@ -43,7 +44,7 @@ export class GalleryRouter { ); } - private static addGetVideo(app) { + private static addGetVideo(app: Express) { app.get(['/api/gallery/content/:filePath(*\.(mp4|ogg|ogv|webm))'], AuthenticationMWs.authenticate, // TODO: authorize path @@ -52,7 +53,7 @@ export class GalleryRouter { ); } - private static addGetMetaFile(app) { + private static addGetMetaFile(app: Express) { app.get(['/api/gallery/content/:filePath(*\.(gpx))'], AuthenticationMWs.authenticate, // TODO: authorize path @@ -61,7 +62,7 @@ export class GalleryRouter { ); } - private static addRandom(app) { + private static addRandom(app: Express) { app.get(['/api/gallery/random'], AuthenticationMWs.authenticate, AuthenticationMWs.authorise(UserRoles.Guest), @@ -72,7 +73,7 @@ export class GalleryRouter { ); } - private static addGetImageThumbnail(app) { + private static addGetImageThumbnail(app: Express) { app.get('/api/gallery/content/:filePath(*\.(jpg|bmp|png|gif|jpeg))/thumbnail/:size?', AuthenticationMWs.authenticate, // TODO: authorize path @@ -82,7 +83,7 @@ export class GalleryRouter { ); } - private static addGetVideoThumbnail(app) { + private static addGetVideoThumbnail(app: Express) { app.get('/api/gallery/content/:filePath(*\.(mp4|ogg|ogv|webm))/thumbnail/:size?', AuthenticationMWs.authenticate, // TODO: authorize path @@ -92,7 +93,7 @@ export class GalleryRouter { ); } - private static addGetImageIcon(app) { + private static addGetImageIcon(app: Express) { app.get('/api/gallery/content/:filePath(*\.(jpg|bmp|png|gif|jpeg))/icon', AuthenticationMWs.authenticate, // TODO: authorize path @@ -102,7 +103,7 @@ export class GalleryRouter { ); } - private static addSearch(app) { + private static addSearch(app: Express) { app.get('/api/search/:text', AuthenticationMWs.authenticate, AuthenticationMWs.authorise(UserRoles.Guest), @@ -113,7 +114,7 @@ export class GalleryRouter { ); } - private static addInstantSearch(app) { + private static addInstantSearch(app: Express) { app.get('/api/instant-search/:text', AuthenticationMWs.authenticate, AuthenticationMWs.authorise(UserRoles.Guest), @@ -124,7 +125,7 @@ export class GalleryRouter { ); } - private static addAutoComplete(app) { + private static addAutoComplete(app: Express) { app.get('/api/autocomplete/:text', AuthenticationMWs.authenticate, AuthenticationMWs.authorise(UserRoles.Guest), diff --git a/backend/routes/LoggerRouter.ts b/backend/routes/LoggerRouter.ts index 69d95c0..a5d3c4b 100644 --- a/backend/routes/LoggerRouter.ts +++ b/backend/routes/LoggerRouter.ts @@ -1,46 +1,55 @@ -import {NextFunction, Request, Response} from 'express'; +import {Express, NextFunction, Request, Response} from 'express'; import {Logger} from '../Logger'; +declare global { + namespace Express { + interface Request { + _startTime?: number; + logged?: boolean; + } + } +} + /** * Adds logging to express */ export class LoggerRouter { - public static route(app: any) { + public static route(app: Express) { app.get('/api*', (req: Request, res: Response, next: NextFunction) => { - req['_startTime'] = Date.now(); - req['logged'] = true; + req._startTime = Date.now(); + req.logged = true; const end = res.end; res.end = (a?: any, b?: any, c?: any) => { res.end = end; res.end(a, b, c); - Logger.verbose(req.method, req.url, res.statusCode, (Date.now() - req['_startTime']) + 'ms'); + Logger.verbose(req.method, req.url, res.statusCode, (Date.now() - req._startTime) + 'ms'); }; return next(); }); app.get('/node_modules*', (req: Request, res: Response, next: NextFunction) => { - req['_startTime'] = Date.now(); - req['logged'] = true; + req._startTime = Date.now(); + req.logged = true; const end = res.end; res.end = (a?: any, b?: any, c?: any) => { res.end = end; res.end(a, b, c); - Logger.silly(req.method, req.url, res.statusCode, (Date.now() - req['_startTime']) + 'ms'); + Logger.silly(req.method, req.url, res.statusCode, (Date.now() - req._startTime) + 'ms'); }; return next(); }); app.use((req: Request, res: Response, next: NextFunction) => { - if (req['logged'] === true) { + if (req.logged === true) { return next(); } - req['_startTime'] = Date.now(); + req._startTime = Date.now(); const end = res.end; res.end = (a?: any, b?: any, c?: any) => { res.end = end; res.end(a, b, c); - Logger.debug(req.method, req.url, res.statusCode, (Date.now() - req['_startTime']) + 'ms'); + Logger.debug(req.method, req.url, res.statusCode, (Date.now() - req._startTime) + 'ms'); }; return next(); }); diff --git a/backend/routes/NotificationRouter.ts b/backend/routes/NotificationRouter.ts index 93a0bcd..fbb7c3c 100644 --- a/backend/routes/NotificationRouter.ts +++ b/backend/routes/NotificationRouter.ts @@ -2,14 +2,15 @@ import {UserRoles} from '../../common/entities/UserDTO'; import {AuthenticationMWs} from '../middlewares/user/AuthenticationMWs'; import {RenderingMWs} from '../middlewares/RenderingMWs'; import {NotificationMWs} from '../middlewares/NotificationMWs'; +import {Express} from 'express'; export class NotificationRouter { - public static route(app: any) { + public static route(app: Express) { this.addGetNotifications(app); } - private static addGetNotifications(app) { + private static addGetNotifications(app: Express) { app.get('/api/notifications', AuthenticationMWs.authenticate, AuthenticationMWs.authorise(UserRoles.Guest), diff --git a/backend/routes/PublicRouter.ts b/backend/routes/PublicRouter.ts index 99e0462..e21881a 100644 --- a/backend/routes/PublicRouter.ts +++ b/backend/routes/PublicRouter.ts @@ -1,4 +1,4 @@ -import {NextFunction, Request, Response} from 'express'; +import {Express, NextFunction, Request, Response} from 'express'; import * as path from 'path'; import * as fs from 'fs'; import * as ejs from 'ejs'; @@ -7,13 +7,26 @@ import {Config} from '../../common/config/private/Config'; import {ProjectPath} from '../ProjectPath'; import {AuthenticationMWs} from '../middlewares/user/AuthenticationMWs'; import {CookieNames} from '../../common/CookieNames'; -import {ErrorDTO} from '../../common/entities/Error'; +import {ErrorCodes, ErrorDTO} from '../../common/entities/Error'; +declare global { + namespace Express { + interface Request { + locale?: string; + localePath?: string; + tpl?: any; + } + + interface Response { + tpl?: any; + } + } +} export class PublicRouter { - public static route(app) { + public static route(app: Express) { const setLocale = (req: Request, res: Response, next: Function) => { let localePath = ''; let selectedLocale = req['locale']; @@ -34,7 +47,7 @@ export class PublicRouter { ejs.renderFile(path.resolve(ProjectPath.FrontendFolder, req['localePath'], 'index.html'), res.tpl, (err, str) => { if (err) { - return next(new ErrorDTO(err)); + return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, err.message)); } res.send(str); }); diff --git a/backend/routes/UserRouter.ts b/backend/routes/UserRouter.ts index eb5b6fb..041fafd 100644 --- a/backend/routes/UserRouter.ts +++ b/backend/routes/UserRouter.ts @@ -1,11 +1,12 @@ import {UserMWs} from '../middlewares/user/UserMWs'; +import {Express} from 'express'; import {UserRoles} from '../../common/entities/UserDTO'; import {AuthenticationMWs} from '../middlewares/user/AuthenticationMWs'; import {UserRequestConstrainsMWs} from '../middlewares/user/UserRequestConstrainsMWs'; import {RenderingMWs} from '../middlewares/RenderingMWs'; export class UserRouter { - public static route(app) { + public static route(app: Express) { this.addLogin(app); this.addLogout(app); this.addGetSessionUser(app); @@ -18,7 +19,7 @@ export class UserRouter { this.addChangeRole(app); } - private static addLogin(app) { + private static addLogin(app: Express) { app.post('/api/user/login', AuthenticationMWs.inverseAuthenticate, AuthenticationMWs.login, @@ -26,7 +27,7 @@ export class UserRouter { ); } - private static addLogout(app) { + private static addLogout(app: Express) { app.post('/api/user/logout', AuthenticationMWs.logout, RenderingMWs.renderOK @@ -34,7 +35,7 @@ export class UserRouter { } - private static addGetSessionUser(app) { + private static addGetSessionUser(app: Express) { app.get('/api/user/login', AuthenticationMWs.authenticate, RenderingMWs.renderSessionUser @@ -42,7 +43,7 @@ export class UserRouter { } - private static addChangePassword(app) { + private static addChangePassword(app: Express) { app.post('/api/user/:id/password', AuthenticationMWs.authenticate, UserRequestConstrainsMWs.forceSelfRequest, @@ -52,7 +53,7 @@ export class UserRouter { } - private static addCreateUser(app) { + private static addCreateUser(app: Express) { app.put('/api/user', AuthenticationMWs.authenticate, AuthenticationMWs.authorise(UserRoles.Admin), @@ -61,7 +62,7 @@ export class UserRouter { ); } - private static addDeleteUser(app) { + private static addDeleteUser(app: Express) { app.delete('/api/user/:id', AuthenticationMWs.authenticate, AuthenticationMWs.authorise(UserRoles.Admin), @@ -72,7 +73,7 @@ export class UserRouter { } - private static addListUsers(app) { + private static addListUsers(app: Express) { app.get('/api/user/list', AuthenticationMWs.authenticate, AuthenticationMWs.authorise(UserRoles.Admin), @@ -81,7 +82,7 @@ export class UserRouter { ); } - private static addChangeRole(app) { + private static addChangeRole(app: Express) { app.post('/api/user/:id/role', AuthenticationMWs.authenticate, AuthenticationMWs.authorise(UserRoles.Admin), diff --git a/backend/server.ts b/backend/server.ts index 6f73399..8eb79b2 100644 --- a/backend/server.ts +++ b/backend/server.ts @@ -114,9 +114,9 @@ export class Server { this.app.use(locale(Config.Client.languages, 'en')); if (Config.Server.database.type !== DatabaseType.memory) { - await ObjectManagerRepository.InitSQLManagers(); + await ObjectManagerRepository.InitSQLManagers(); } else { - await ObjectManagerRepository.InitMemoryManagers(); + await ObjectManagerRepository.InitMemoryManagers(); } PublicRouter.route(this.app); diff --git a/backend/tsconfig.json b/backend/tsconfig.json index a7e384e..d231597 100644 --- a/backend/tsconfig.json +++ b/backend/tsconfig.json @@ -1,6 +1,7 @@ { "compileOnSave": true, "compilerOptions": { + "noImplicitAny": true, "module": "commonjs", "skipLibCheck": true, "sourceMap": false, diff --git a/common/Utils.ts b/common/Utils.ts index 1ca1685..60f043d 100644 --- a/common/Utils.ts +++ b/common/Utils.ts @@ -5,7 +5,7 @@ export class Utils { return JSON.parse(JSON.stringify(object)); } - static zeroPrefix(value, length: number) { + static zeroPrefix(value: string | number, length: number) { const ret = '00000' + value; return ret.substr(ret.length - length); } @@ -34,7 +34,6 @@ export class Utils { } - /** * * @param from diff --git a/common/config/public/Config.ts b/common/config/public/Config.ts index 798037c..21333df 100644 --- a/common/config/public/Config.ts +++ b/common/config/public/Config.ts @@ -3,7 +3,7 @@ import {WebConfigLoader} from 'typeconfig/src/WebConfigLoader'; declare module ServerInject { - export const ConfigInject; + export const ConfigInject: PublicConfigClass; } export let Config = new PublicConfigClass(); diff --git a/frontend/app/app.component.ts b/frontend/app/app.component.ts index 666575c..cc299b9 100644 --- a/frontend/app/app.component.ts +++ b/frontend/app/app.component.ts @@ -7,16 +7,18 @@ import {Title} from '@angular/platform-browser'; import {NotificationService} from './model/notification.service'; import {ShareService} from './gallery/share.service'; import 'hammerjs'; +import {Subscription} from 'rxjs'; import {QueryService} from './model/query.service'; @Component({ selector: 'app-pi-gallery2', - template: ``, + template: ` + `, }) export class AppComponent implements OnInit, OnDestroy { - private subscription = null; + private subscription: Subscription = null; constructor(private _router: Router, private _authenticationService: AuthenticationService, diff --git a/frontend/app/app.module.ts b/frontend/app/app.module.ts index 9cd5e68..64f5fad 100644 --- a/frontend/app/app.module.ts +++ b/frontend/app/app.module.ts @@ -109,7 +109,7 @@ export class CustomUrlSerializer implements UrlSerializer { } // use the require method provided by webpack -declare const require; +declare const require: (path: string) => string; export function translationsFactory(locale: string) { locale = locale || 'en'; // default to english if no locale diff --git a/frontend/app/gallery/fullscreen.service.ts b/frontend/app/gallery/fullscreen.service.ts index 17720be..5f77192 100644 --- a/frontend/app/gallery/fullscreen.service.ts +++ b/frontend/app/gallery/fullscreen.service.ts @@ -1,6 +1,15 @@ import {Injectable} from '@angular/core'; import {Event} from '../../../common/event/Event'; +declare const document: { + fullscreenElement: any; + mozFullScreenElement: any; + webkitFullscreenElement: any; + exitFullscreen: () => void; + mozCancelFullScreen: () => void; + webkitExitFullscreen: () => void; +}; + @Injectable() export class FullScreenService { diff --git a/frontend/app/gallery/gallery.component.ts b/frontend/app/gallery/gallery.component.ts index 8ba2ff5..5dd8b2b 100644 --- a/frontend/app/gallery/gallery.component.ts +++ b/frontend/app/gallery/gallery.component.ts @@ -11,11 +11,12 @@ import {SearchResultDTO} from '../../../common/entities/SearchResultDTO'; import {ShareService} from './share.service'; import {NavigationService} from '../model/navigation.service'; import {UserRoles} from '../../../common/entities/UserDTO'; -import {interval} from 'rxjs'; +import {interval, Subscription, Observable} from 'rxjs'; import {ContentWrapper} from '../../../common/entities/ConentWrapper'; import {PageHelper} from '../model/page.helper'; import {SortingMethods} from '../../../common/entities/SortingMethods'; import {PhotoDTO} from '../../../common/entities/PhotoDTO'; +import {QueryService} from '../model/query.service'; @Component({ selector: 'app-gallery', @@ -33,16 +34,16 @@ export class GalleryComponent implements OnInit, OnDestroy { public directories: DirectoryDTO[] = []; public isPhotoWithLocation = false; - private $counter; - private subscription = { + private $counter: Observable; + private subscription: { [key: string]: Subscription } = { content: null, route: null, timer: null, sorting: null }; - public countDown = null; + public countDown: { day: number, hour: number, minute: number, second: number } = null; public mapEnabled = true; - SearchTypes: any = []; + readonly SearchTypes: typeof SearchTypes; constructor(public _galleryService: GalleryService, private _authService: AuthenticationService, @@ -61,7 +62,7 @@ export class GalleryComponent implements OnInit, OnDestroy { return; } t = Math.floor((this.shareService.sharing.value.expires - Date.now()) / 1000); - this.countDown = {}; + this.countDown = {}; this.countDown.day = Math.floor(t / 86400); t -= this.countDown.day * 86400; this.countDown.hour = Math.floor(t / 3600) % 24; @@ -74,21 +75,23 @@ export class GalleryComponent implements OnInit, OnDestroy { private onRoute = async (params: Params) => { const searchText = params['searchText']; if (searchText && searchText !== '') { - const typeString = params['type']; + const typeString: string = params['type']; if (typeString && typeString !== '') { - const type: SearchTypes = SearchTypes[typeString]; - this._galleryService.search(searchText, type); + const type: SearchTypes = SearchTypes[typeString]; + this._galleryService.search(searchText, type).catch(console.error); return; } - this._galleryService.search(searchText); + this._galleryService.search(searchText).catch(console.error); return; } if (params['sharingKey'] && params['sharingKey'] !== '') { const sharing = await this.shareService.getSharing(); - this._router.navigate(['/gallery', sharing.path], {queryParams: {sk: this.shareService.getSharingKey()}}); + const qParams: { [key: string]: any } = {}; + qParams[QueryService.SHARING_KEY] = this.shareService.getSharingKey(); + this._router.navigate(['/gallery', sharing.path], {queryParams: qParams}).catch(console.error); return; } diff --git a/frontend/app/gallery/gallery.service.ts b/frontend/app/gallery/gallery.service.ts index 609e4d8..ca58e57 100644 --- a/frontend/app/gallery/gallery.service.ts +++ b/frontend/app/gallery/gallery.service.ts @@ -10,6 +10,7 @@ import {Config} from '../../../common/config/public/Config'; import {ShareService} from './share.service'; import {NavigationService} from '../model/navigation.service'; import {SortingMethods} from '../../../common/entities/SortingMethods'; +import {QueryService} from '../model/query.service'; @Injectable() @@ -46,10 +47,10 @@ export class GalleryService { this.content.next(content); this.lastRequest.directory = directoryName; - const params = {}; + const params: { [key: string]: any } = {}; if (Config.Client.Sharing.enabled === true) { if (this._shareService.isSharing()) { - params['sk'] = this._shareService.getSharingKey(); + params[QueryService.SHARING_KEY] = this._shareService.getSharingKey(); } } @@ -98,7 +99,7 @@ export class GalleryService { const cw = new ContentWrapper(); cw.searchResult = this.galleryCacheService.getSearch(text, type); if (cw.searchResult == null) { - const params = {}; + const params: { type?: SearchTypes } = {}; if (typeof type !== 'undefined') { params['type'] = type; } diff --git a/frontend/app/gallery/grid/grid.gallery.component.ts b/frontend/app/gallery/grid/grid.gallery.component.ts index 1ac9c02..f933659 100644 --- a/frontend/app/gallery/grid/grid.gallery.component.ts +++ b/frontend/app/gallery/grid/grid.gallery.component.ts @@ -51,7 +51,7 @@ export class GalleryGridComponent implements OnChanges, OnInit, AfterViewInit, O private MAX_ROW_COUNT = 5; private onScrollFired = false; - private helperTime = null; + private helperTime: number = null; isAfterViewInit = false; private renderedPhotoIndex = 0; subscriptions: { @@ -96,7 +96,7 @@ export class GalleryGridComponent implements OnChanges, OnInit, AfterViewInit, O this.updateContainerDimensions(); this.sortPhotos(); this.mergeNewPhotos(); - this.helperTime = setTimeout(() => { + this.helperTime = window.setTimeout(() => { this.renderPhotos(); if (this.delayedRenderUpToPhoto) { this.renderUpToPhoto(this.delayedRenderUpToPhoto); @@ -147,7 +147,7 @@ export class GalleryGridComponent implements OnChanges, OnInit, AfterViewInit, O this.updateContainerDimensions(); this.sortPhotos(); this.clearRenderedPhotos(); - this.helperTime = setTimeout(() => { + this.helperTime = window.setTimeout(() => { this.renderPhotos(); }, 0); this.isAfterViewInit = true; diff --git a/frontend/app/gallery/grid/photo/photo.grid.gallery.component.ts b/frontend/app/gallery/grid/photo/photo.grid.gallery.component.ts index 61c9bad..f6f9d02 100644 --- a/frontend/app/gallery/grid/photo/photo.grid.gallery.component.ts +++ b/frontend/app/gallery/grid/photo/photo.grid.gallery.component.ts @@ -27,9 +27,9 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, OnDestroy { visible: false, background: 'rgba(0,0,0,0.0)' }; - animationTimer = null; + animationTimer: number = null; - SearchTypes: any = []; + readonly SearchTypes: typeof SearchTypes; searchEnabled = true; wasInView: boolean = null; @@ -90,10 +90,10 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, OnDestroy { if (this.animationTimer != null) { clearTimeout(this.animationTimer); } - this.animationTimer = setTimeout(() => { + this.animationTimer = window.setTimeout(() => { this.infoBar.background = 'rgba(0,0,0,0.8)'; if (!this.infoDiv) { - this.animationTimer = setTimeout(() => { + this.animationTimer = window.setTimeout(() => { if (!this.infoDiv) { this.infoBar.marginTop = -50; return; @@ -111,13 +111,13 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, OnDestroy { if (this.animationTimer != null) { clearTimeout(this.animationTimer); } - this.animationTimer = setTimeout(() => { + this.animationTimer = window.setTimeout(() => { this.infoBar.marginTop = 0; this.infoBar.background = 'rgba(0,0,0,0.0)'; if (this.animationTimer != null) { clearTimeout(this.animationTimer); } - this.animationTimer = setTimeout(() => { + this.animationTimer = window.setTimeout(() => { this.infoBar.visible = false; }, 500); }, 100); diff --git a/frontend/app/gallery/lightbox/infopanel/info-panel.lightbox.gallery.component.ts b/frontend/app/gallery/lightbox/infopanel/info-panel.lightbox.gallery.component.ts index 21eba7d..adcf90f 100644 --- a/frontend/app/gallery/lightbox/infopanel/info-panel.lightbox.gallery.component.ts +++ b/frontend/app/gallery/lightbox/infopanel/info-panel.lightbox.gallery.component.ts @@ -51,7 +51,7 @@ export class InfoPanelLightboxComponent { } - toFraction(f) { + toFraction(f: number) { if (f > 1) { return f; } diff --git a/frontend/app/gallery/lightbox/lightbox.gallery.component.ts b/frontend/app/gallery/lightbox/lightbox.gallery.component.ts index fb7f580..c1b652e 100644 --- a/frontend/app/gallery/lightbox/lightbox.gallery.component.ts +++ b/frontend/app/gallery/lightbox/lightbox.gallery.component.ts @@ -41,7 +41,7 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit { @ViewChild('lightbox') lightboxElement: ElementRef; public navigation = {hasPrev: true, hasNext: true}; - public blackCanvasOpacity: any = 0; + public blackCanvasOpacity = 0; private activePhotoId: number = null; public activePhoto: GalleryPhotoComponent; @@ -65,8 +65,8 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit { public infoPanelWidth = 0; public animating = false; startPhotoDimension: Dimension = {top: 0, left: 0, width: 0, height: 0}; - iPvisibilityTimer = null; - visibilityTimer = null; + iPvisibilityTimer: number = null; + visibilityTimer: number = null; delayedPhotoShow: string = null; @@ -326,7 +326,7 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit { } hideInfoPanel(_animate: boolean = true) { - this.iPvisibilityTimer = setTimeout(() => { + this.iPvisibilityTimer = window.setTimeout(() => { this.iPvisibilityTimer = null; this.infoPanelVisible = false; }, 1000); @@ -465,7 +465,7 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit { if (this.visibilityTimer != null) { clearTimeout(this.visibilityTimer); } - this.visibilityTimer = setTimeout(this.hideControls, 2000); + this.visibilityTimer = window.setTimeout(this.hideControls, 2000); } private hideControls = () => { diff --git a/frontend/app/gallery/lightbox/media/media.lightbox.gallery.component.ts b/frontend/app/gallery/lightbox/media/media.lightbox.gallery.component.ts index ed66c85..c21b0b1 100644 --- a/frontend/app/gallery/lightbox/media/media.lightbox.gallery.component.ts +++ b/frontend/app/gallery/lightbox/media/media.lightbox.gallery.component.ts @@ -16,7 +16,7 @@ export class GalleryLightboxMediaComponent implements OnChanges { @ViewChild('video') video: ElementRef; - prevGirdPhoto = null; + prevGirdPhoto: GridMedia = null; public imageSize = {width: 'auto', height: '100'}; diff --git a/frontend/app/gallery/map/lightbox/lightbox.map.gallery.component.ts b/frontend/app/gallery/map/lightbox/lightbox.map.gallery.component.ts index 5a98dcf..8ce7f52 100644 --- a/frontend/app/gallery/map/lightbox/lightbox.map.gallery.component.ts +++ b/frontend/app/gallery/map/lightbox/lightbox.map.gallery.component.ts @@ -25,7 +25,7 @@ export class GalleryMapLightboxComponent implements OnChanges, AfterViewInit { @Input() photos: PhotoDTO[]; @Input() gpxFiles: FileDTO[]; - private startPosition = null; + private startPosition: Dimension = null; public lightboxDimension: Dimension = {top: 0, left: 0, width: 0, height: 0}; public mapDimension: Dimension = {top: 0, left: 0, width: 0, height: 0}; public visible = false; diff --git a/frontend/app/gallery/map/map.gallery.component.ts b/frontend/app/gallery/map/map.gallery.component.ts index ad87d9c..19eccaf 100644 --- a/frontend/app/gallery/map/map.gallery.component.ts +++ b/frontend/app/gallery/map/map.gallery.component.ts @@ -20,7 +20,7 @@ export class GalleryMapComponent implements OnChanges, IRenderable, AfterViewIni mapPhotos: Array<{ latitude: number, longitude: number }> = []; @ViewChild('map') mapElement: ElementRef; - height = null; + height: number = null; constructor(private mapsAPILoader: MapsAPILoader) { diff --git a/frontend/app/gallery/random-query-builder/random-query-builder.gallery.component.ts b/frontend/app/gallery/random-query-builder/random-query-builder.gallery.component.ts index b1f003b..6f4f981 100644 --- a/frontend/app/gallery/random-query-builder/random-query-builder.gallery.component.ts +++ b/frontend/app/gallery/random-query-builder/random-query-builder.gallery.component.ts @@ -10,6 +10,7 @@ import {BsModalService} from 'ngx-bootstrap/modal'; import {BsModalRef} from 'ngx-bootstrap/modal/bs-modal-ref.service'; import {OrientationType, RandomQueryDTO} from '../../../../common/entities/RandomQueryDTO'; import {NetworkService} from '../../model/network/network.service'; +import {Subscription} from 'rxjs'; @Component({ @@ -31,9 +32,9 @@ export class RandomQueryBuilderGalleryComponent implements OnInit, OnDestroy { toDate: null, fromDate: null }; - contentSubscription = null; + contentSubscription: Subscription = null; - OrientationType; + readonly OrientationType: typeof OrientationType; modalRef: BsModalRef; text = { @@ -71,8 +72,8 @@ export class RandomQueryBuilderGalleryComponent implements OnInit, OnDestroy { setTimeout(() => { const data = Utils.clone(this.data); for (const key of Object.keys(data)) { - if (!data[key]) { - delete data[key]; + if (!(data)[key]) { + delete (data)[key]; } } this.url = NetworkService.buildUrl(Config.Client.publicUrl + '/api/gallery/random/', data); diff --git a/frontend/app/gallery/search/search.gallery.component.ts b/frontend/app/gallery/search/search.gallery.component.ts index c3e951c..f6f2eb5 100644 --- a/frontend/app/gallery/search/search.gallery.component.ts +++ b/frontend/app/gallery/search/search.gallery.component.ts @@ -3,6 +3,7 @@ import {AutoCompleteService} from './autocomplete.service'; import {AutoCompleteItem, SearchTypes} from '../../../../common/entities/AutoCompleteItem'; import {ActivatedRoute, Params, RouterLink} from '@angular/router'; import {GalleryService} from '../gallery.service'; +import {Subscription} from 'rxjs'; import {Config} from '../../../../common/config/public/Config'; @Component({ @@ -13,16 +14,16 @@ import {Config} from '../../../../common/config/public/Config'; }) export class GallerySearchComponent implements OnDestroy { - autoCompleteItems: Array = []; + autoCompleteItems: AutoCompleteRenderItem[] = []; public searchText = ''; private cache = { lastAutocomplete: '', lastInstantSearch: '' }; - - SearchTypes: any = []; mouseOverAutoComplete = false; - private readonly subscription = null; + + readonly SearchTypes: typeof SearchTypes; + private readonly subscription: Subscription = null; constructor(private _autoCompleteService: AutoCompleteService, private _galleryService: GalleryService, diff --git a/frontend/app/gallery/share.service.ts b/frontend/app/gallery/share.service.ts index 3256b03..3ca4056 100644 --- a/frontend/app/gallery/share.service.ts +++ b/frontend/app/gallery/share.service.ts @@ -3,22 +3,23 @@ import {NetworkService} from '../model/network/network.service'; import {CreateSharingDTO, SharingDTO} from '../../../common/entities/SharingDTO'; import {Router, RoutesRecognized} from '@angular/router'; import {BehaviorSubject} from 'rxjs'; +import {QueryService} from '../model/query.service'; @Injectable() export class ShareService { public sharing: BehaviorSubject; - param = null; - queryParam = null; - sharingKey = null; + param: string = null; + queryParam: string = null; + sharingKey: string = null; inited = false; public ReadyPR: Promise; - private resolve; + private resolve: () => void; constructor(private _networkService: NetworkService, private router: Router) { this.sharing = new BehaviorSubject(null); - this.ReadyPR = new Promise((resolve) => { + this.ReadyPR = new Promise((resolve: () => void) => { if (this.inited === true) { return resolve(); } @@ -28,7 +29,7 @@ export class ShareService { this.router.events.subscribe(val => { if (val instanceof RoutesRecognized) { this.param = val.state.root.firstChild.params['sharingKey'] || null; - this.queryParam = val.state.root.firstChild.queryParams['sk'] || null; + this.queryParam = val.state.root.firstChild.queryParams[QueryService.SHARING_KEY] || null; const changed = this.sharingKey !== this.param || this.queryParam; if (changed) { this.sharingKey = this.param || this.queryParam; diff --git a/frontend/app/gallery/share/share.gallery.component.ts b/frontend/app/gallery/share/share.gallery.component.ts index dda3618..94308b9 100644 --- a/frontend/app/gallery/share/share.gallery.component.ts +++ b/frontend/app/gallery/share/share.gallery.component.ts @@ -10,6 +10,7 @@ import {DirectoryDTO} from '../../../../common/entities/DirectoryDTO'; import {I18n} from '@ngx-translate/i18n-polyfill'; import {BsModalService} from 'ngx-bootstrap/modal'; import {BsModalRef} from 'ngx-bootstrap/modal/bs-modal-ref.service'; +import {Subscription} from 'rxjs'; @Component({ @@ -32,7 +33,7 @@ export class GalleryShareComponent implements OnInit, OnDestroy { }; currentDir = ''; sharing: SharingDTO = null; - contentSubscription = null; + contentSubscription: Subscription = null; passwordProtection = false; ValidityTypes: any; diff --git a/frontend/app/model/network/autehentication.service.spec.ts b/frontend/app/model/network/autehentication.service.spec.ts index bc18d98..797f54c 100644 --- a/frontend/app/model/network/autehentication.service.spec.ts +++ b/frontend/app/model/network/autehentication.service.spec.ts @@ -11,7 +11,7 @@ class MockUserService { return Promise.resolve({name: 'testUserName'}); } - public async getSessionUser() { + public async getSessionUser(): Promise { return null; } } @@ -34,11 +34,11 @@ describe('AuthenticationService', () => { it('should call UserDTO service login', inject([AuthenticationService, UserService], - async (authService, userService) => { + async (authService: AuthenticationService, userService: UserService) => { spyOn(userService, 'login').and.callThrough(); expect(userService.login).not.toHaveBeenCalled(); - await authService.login(); + await authService.login(null); expect(userService.login).toHaveBeenCalled(); })); diff --git a/frontend/app/model/network/network.service.spec.ts b/frontend/app/model/network/network.service.spec.ts index 71cf9b6..b474672 100644 --- a/frontend/app/model/network/network.service.spec.ts +++ b/frontend/app/model/network/network.service.spec.ts @@ -30,7 +30,7 @@ describe('NetworkService Success tests', () => { httpMock.verify(); }); - it('should call GET', inject([NetworkService], (networkService) => { + it('should call GET', inject([NetworkService], (networkService: NetworkService) => { networkService.getJson(testUrl).then((res: string) => { expect(res).toBe(testResponse); @@ -45,7 +45,7 @@ describe('NetworkService Success tests', () => { mockReq.flush(testResponseMessage); })); - it('should call POST', inject([NetworkService], (networkService) => { + it('should call POST', inject([NetworkService], (networkService: NetworkService) => { networkService.postJson(testUrl, testData).then((res: string) => { expect(res).toBe(testResponse); @@ -77,7 +77,7 @@ describe('NetworkService Success tests', () => { })); - it('should call DELETE', inject([NetworkService], (networkService) => { + it('should call DELETE', inject([NetworkService], (networkService: NetworkService) => { networkService.deleteJson(testUrl).then((res: any) => { expect(res).toBe(testResponse); @@ -89,7 +89,7 @@ describe('NetworkService Success tests', () => { mockReq.flush(testResponseMessage); })); - it('should call PUT', inject([NetworkService], (networkService) => { + it('should call PUT', inject([NetworkService], (networkService: NetworkService) => { networkService.putJson(testUrl, testData).then((res: any) => { expect(res).toBe(testResponse); @@ -142,7 +142,7 @@ describe('NetworkService Fail tests', () => { httpMock.verify(); }); - it('should call GET with error', inject([NetworkService], (networkService) => { + it('should call GET with error', inject([NetworkService], (networkService: NetworkService) => { networkService.getJson(testUrl).then((res: any) => { expect(res).toBe(null); @@ -157,7 +157,7 @@ describe('NetworkService Fail tests', () => { mockReq.error(null, {statusText: testError}); })); - it('should call POST with error', inject([NetworkService], (networkService) => { + it('should call POST with error', inject([NetworkService], (networkService: NetworkService) => { networkService.postJson(testUrl, testData).then((res: any) => { expect(res).toBe(null); @@ -172,7 +172,7 @@ describe('NetworkService Fail tests', () => { mockReq.error(null, {statusText: testError}); })); - it('should call PUT with error', inject([NetworkService], (networkService) => { + it('should call PUT with error', inject([NetworkService], (networkService: NetworkService) => { networkService.putJson(testUrl, testData).then((res: any) => { expect(res).toBe(null); @@ -189,7 +189,7 @@ describe('NetworkService Fail tests', () => { })); - it('should call DELETE with error', inject([NetworkService], (networkService) => { + it('should call DELETE with error', inject([NetworkService], (networkService: NetworkService) => { networkService.deleteJson(testUrl).then((res: any) => { expect(res).toBe(null); diff --git a/frontend/app/model/network/network.service.ts b/frontend/app/model/network/network.service.ts index 9ffdd34..33dda8f 100644 --- a/frontend/app/model/network/network.service.ts +++ b/frontend/app/model/network/network.service.ts @@ -46,7 +46,7 @@ export class NetworkService { return parser.parseFromString(res, 'text/xml'); }; - const err = (error) => { + const err = (error: any) => { this.slimLoadingBarService.complete(); return this.handleError(error); }; @@ -85,14 +85,14 @@ export class NetworkService { this.slimLoadingBarService.complete(); if (!!res.error) { if (res.error.code) { - res.error['title'] = ErrorCodes[res.error.code]; + (res.error)['title'] = ErrorCodes[res.error.code]; } throw res.error; } return res.result; }; - const err = (error) => { + const err = (error:any) => { this.slimLoadingBarService.complete(); return this.handleError(error); }; diff --git a/frontend/app/model/network/user.service.spec.ts b/frontend/app/model/network/user.service.spec.ts index 864b510..fd324bf 100644 --- a/frontend/app/model/network/user.service.spec.ts +++ b/frontend/app/model/network/user.service.spec.ts @@ -32,20 +32,20 @@ describe('UserService', () => { }); it('should call postJson at login', inject([UserService, NetworkService], - async (userService, networkService) => { + async (userService: UserService, networkService: NetworkService) => { spyOn(networkService, 'postJson'); const credential = new LoginCredential('name', 'pass'); await userService.login(credential); expect(networkService.postJson).toHaveBeenCalled(); - expect(networkService.postJson.calls.argsFor(0)).toEqual(['/user/login', {'loginCredential': credential}]); + expect((networkService.postJson).calls.argsFor(0)).toEqual(['/user/login', {'loginCredential': credential}]); })); it('should call getJson at getSessionUser', inject([UserService, NetworkService], - async (userService, networkService) => { + async (userService: UserService, networkService: NetworkService) => { spyOn(networkService, 'getJson'); await userService.getSessionUser(); expect(networkService.getJson).toHaveBeenCalled(); - expect(networkService.getJson.calls.argsFor(0)).toEqual(['/user/login']); + expect((networkService.getJson).calls.argsFor(0)).toEqual(['/user/login']); })); diff --git a/frontend/app/model/notification.service.ts b/frontend/app/model/notification.service.ts index d8e667a..87947b7 100644 --- a/frontend/app/model/notification.service.ts +++ b/frontend/app/model/notification.service.ts @@ -53,19 +53,19 @@ export class NotificationService { }); } - success(text, title = null) { + success(text: string, title: string = null): void { this._toastr.success(text, title, this.options); } - error(text, title?) { + error(text: string, title?: string): void { this._toastr.error(text, title, this.options); } - warning(text, title?) { + warning(text: string, title?: string): void { this._toastr.warning(text, title, this.options); } - info(text, title = null) { + info(text: string, title: string = null): void { this._toastr.info(text, title, this.options); } diff --git a/frontend/app/model/query.service.ts b/frontend/app/model/query.service.ts index f9a3ea1..4713a2f 100644 --- a/frontend/app/model/query.service.ts +++ b/frontend/app/model/query.service.ts @@ -7,17 +7,18 @@ import {MediaDTO} from '../../../common/entities/MediaDTO'; export class QueryService { public static readonly PHOTO_PARAM = 'p'; + public static readonly SHARING_KEY = 'sk'; constructor(private shareService: ShareService) { } getParams(media?: MediaDTO): { [key: string]: string } { - const query = {}; + const query: { [key: string]: string } = {}; if (media) { query[QueryService.PHOTO_PARAM] = media.name; } if (this.shareService.isSharing()) { - query['sk'] = this.shareService.getSharingKey(); + query[QueryService.SHARING_KEY] = this.shareService.getSharingKey(); } return query; } diff --git a/frontend/app/pipes/StringifyRolePipe.ts b/frontend/app/pipes/StringifyRolePipe.ts index e36de05..30cdfc8 100644 --- a/frontend/app/pipes/StringifyRolePipe.ts +++ b/frontend/app/pipes/StringifyRolePipe.ts @@ -4,7 +4,7 @@ import {UserRoles} from '../../../common/entities/UserDTO'; @Pipe({name: 'stringifyRole'}) export class StringifyRole implements PipeTransform { - transform(role: string): number { + transform(role: number): string { return UserRoles[role]; } } diff --git a/frontend/app/settings/_abstract/abstract.settings.component.ts b/frontend/app/settings/_abstract/abstract.settings.component.ts index a4148bc..8de06ef 100644 --- a/frontend/app/settings/_abstract/abstract.settings.component.ts +++ b/frontend/app/settings/_abstract/abstract.settings.component.ts @@ -8,9 +8,10 @@ import {NavigationService} from '../../model/navigation.service'; import {AbstractSettingsService} from './abstract.settings.service'; import {IPrivateConfig} from '../../../../common/config/private/IPrivateConfig'; import {I18n} from '@ngx-translate/i18n-polyfill'; +import {Subscription} from 'rxjs'; -export abstract class SettingsComponent = AbstractSettingsService> +export abstract class SettingsComponent = AbstractSettingsService> implements OnInit, OnDestroy, OnChanges { @Input() @@ -25,8 +26,8 @@ export abstract class SettingsComponent public inProgress = false; public error: string = null; public changed = false; - private _subscription = null; - private readonly _settingsSubscription = null; + private _subscription: Subscription = null; + private readonly _settingsSubscription: Subscription = null; public settings: T = {}; public original: T = {}; @@ -38,7 +39,7 @@ export abstract class SettingsComponent High: 'High' }; - protected constructor(private name, + protected constructor(private name: string, private _authService: AuthenticationService, private _navigation: NavigationService, public _settingsService: S, @@ -55,7 +56,7 @@ export abstract class SettingsComponent this.text.High = i18n('High'); } - onNewSettings = (s) => { + onNewSettings = (s: IPrivateConfig) => { this.settings = Utils.clone(this.sliceFN(s)); this.original = Utils.clone(this.settings); this.ngOnChanges(); diff --git a/frontend/app/settings/indexing/indexing.settings.service.ts b/frontend/app/settings/indexing/indexing.settings.service.ts index 7c6709e..6ac5d58 100644 --- a/frontend/app/settings/indexing/indexing.settings.service.ts +++ b/frontend/app/settings/indexing/indexing.settings.service.ts @@ -28,7 +28,7 @@ export class IndexingSettingsService extends AbstractSettingsService{createThumbnails: createThumbnails}); } diff --git a/package.json b/package.json index 688b15e..4b687bb 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,9 @@ "@ngx-translate/i18n-polyfill": "1.0.0", "@types/bcryptjs": "2.4.2", "@types/chai": "4.1.7", + "@types/cookie-parser": "^1.4.1", "@types/cookie-session": "2.0.36", + "@types/ejs": "^2.6.0", "@types/express": "4.16.0", "@types/fluent-ffmpeg": "^2.1.8", "@types/gm": "1.18.2", diff --git a/test/backend/unit/middlewares/user/AuthenticationMWs.ts b/test/backend/unit/middlewares/user/AuthenticationMWs.ts index e97e0c0..e04b994 100644 --- a/test/backend/unit/middlewares/user/AuthenticationMWs.ts +++ b/test/backend/unit/middlewares/user/AuthenticationMWs.ts @@ -16,7 +16,7 @@ describe('Authentication middleware', () => { describe('authenticate', () => { it('should call next on authenticated', (done) => { - let req: any = { + const req: any = { session: { user: 'A user' }, @@ -24,7 +24,7 @@ describe('Authentication middleware', () => { query: {}, params: {} }; - let next: any = (err) => { + const next: any = (err: ErrorDTO) => { expect(err).to.be.undefined; done(); }; @@ -33,15 +33,15 @@ describe('Authentication middleware', () => { }); it('should call next with error on not authenticated', (done) => { - let req: any = { + const req: any = { session: {}, sessionOptions: {}, query: {}, params: {} }; Config.Client.authenticationRequired = true; - let res: any = {}; - let next: any = (err: ErrorDTO) => { + const res: any = {}; + const next: any = (err: ErrorDTO) => { expect(err).not.to.be.undefined; expect(err.code).to.be.eql(ErrorCodes.NOT_AUTHENTICATED); done(); @@ -54,12 +54,12 @@ describe('Authentication middleware', () => { describe('inverseAuthenticate', () => { it('should call next with error on authenticated', (done) => { - let req: any = { + const req: any = { session: {}, sessionOptions: {}, }; - let res: any = {}; - let next: any = (err) => { + const res: any = {}; + const next: any = (err:ErrorDTO) => { expect(err).to.be.undefined; done(); }; @@ -69,14 +69,14 @@ describe('Authentication middleware', () => { it('should call next error on authenticated', (done) => { - let req: any = { + const req: any = { session: { user: 'A user' }, sessionOptions: {}, }; - let res: any = {}; - let next: any = (err: ErrorDTO) => { + const res: any = {}; + const next: any = (err: ErrorDTO) => { expect(err).not.to.be.undefined; expect(err.code).to.be.eql(ErrorCodes.ALREADY_AUTHENTICATED); done(); @@ -88,7 +88,7 @@ describe('Authentication middleware', () => { describe('authorise', () => { it('should call next on authorised', (done) => { - let req: any = { + const req: any = { session: { user: { role: UserRoles.LimitedGuest @@ -96,7 +96,7 @@ describe('Authentication middleware', () => { }, sessionOptions: {} }; - let next: any = (err) => { + const next: any = (err:ErrorDTO) => { expect(err).to.be.undefined; done(); }; @@ -105,7 +105,7 @@ describe('Authentication middleware', () => { }); it('should call next with error on not authorised', (done) => { - let req: any = { + const req: any = { session: { user: { role: UserRoles.LimitedGuest @@ -113,7 +113,7 @@ describe('Authentication middleware', () => { }, sessionOptions: {} }; - let next: any = (err: ErrorDTO) => { + const next: any = (err: ErrorDTO) => { expect(err).not.to.be.undefined; expect(err.code).to.be.eql(ErrorCodes.NOT_AUTHORISED); done(); @@ -130,11 +130,11 @@ describe('Authentication middleware', () => { describe('should call input ErrorDTO next on missing...', () => { it('body', (done) => { - let req: any = { + const req: any = { query: {}, params: {} }; - let next: any = (err: ErrorDTO) => { + const next: any = (err: ErrorDTO) => { expect(err).not.to.be.undefined; expect(err.code).to.be.eql(ErrorCodes.INPUT_ERROR); done(); @@ -144,12 +144,12 @@ describe('Authentication middleware', () => { }); it('loginCredential', (done) => { - let req: any = { + const req: any = { body: {}, query: {}, params: {} }; - let next: any = (err: ErrorDTO) => { + const next: any = (err: ErrorDTO) => { expect(err).not.to.be.undefined; expect(err.code).to.be.eql(ErrorCodes.INPUT_ERROR); done(); @@ -161,12 +161,12 @@ describe('Authentication middleware', () => { it('loginCredential content', (done) => { - let req: any = { + const req: any = { body: {loginCredential: {}}, query: {}, params: {} }; - let next: any = (err: ErrorDTO) => { + const next: any = (err: ErrorDTO) => { expect(err).not.to.be.undefined; expect(err.code).to.be.eql(ErrorCodes.INPUT_ERROR); done(); @@ -178,7 +178,7 @@ describe('Authentication middleware', () => { }); it('should call next with error on not finding user', (done) => { - let req: any = { + const req: any = { body: { loginCredential: { username: 'aa', @@ -188,7 +188,7 @@ describe('Authentication middleware', () => { query: {}, params: {} }; - let next: any = (err: ErrorDTO) => { + const next: any = (err: ErrorDTO) => { expect(err).not.to.be.undefined; expect(err.code).to.be.eql(ErrorCodes.CREDENTIAL_NOT_FOUND); done(); @@ -204,7 +204,7 @@ describe('Authentication middleware', () => { }); it('should call next with user on the session on finding user', (done) => { - let req: any = { + const req: any = { session: {}, body: { loginCredential: { @@ -215,7 +215,7 @@ describe('Authentication middleware', () => { query: {}, params: {} }; - let next: any = (err: ErrorDTO) => { + const next: any = (err: ErrorDTO) => { expect(err).to.be.undefined; expect(req.session.user).to.be.eql('test user'); done(); @@ -234,14 +234,14 @@ describe('Authentication middleware', () => { describe('logout', () => { it('should call next on logout', (done) => { - let req: any = { + const req: any = { session: { user: { role: UserRoles.LimitedGuest } } }; - let next: any = (err) => { + const next: any = (err:ErrorDTO) => { expect(err).to.be.undefined; expect(req.session.user).to.be.undefined; done(); diff --git a/test/backend/unit/model/sql/TestHelper.ts b/test/backend/unit/model/sql/TestHelper.ts index 3dbea4c..77cd716 100644 --- a/test/backend/unit/model/sql/TestHelper.ts +++ b/test/backend/unit/model/sql/TestHelper.ts @@ -8,7 +8,6 @@ import { import * as path from 'path'; import {OrientationTypes} from 'ts-exif-parser'; import {DirectoryEntity} from '../../../../../backend/model/sql/enitites/DirectoryEntity'; -import {Utils} from '../../../../../common/Utils'; import {VideoEntity, VideoMetadataEntity} from '../../../../../backend/model/sql/enitites/VideoEntity'; import {FileEntity} from '../../../../../backend/model/sql/enitites/FileEntity'; @@ -117,7 +116,7 @@ export class TestHelper { } - public static getRandomizedDirectoryEntry(parent: DirectoryEntity = null, forceStr = null) { + public static getRandomizedDirectoryEntry(parent: DirectoryEntity = null, forceStr: string = null) { const dir = new DirectoryEntity(); dir.name = forceStr || Math.random().toString(36).substring(7); @@ -136,7 +135,7 @@ export class TestHelper { } - public static getRandomizedGPXEntry(dir: DirectoryEntity, forceStr = null): FileEntity { + public static getRandomizedGPXEntry(dir: DirectoryEntity, forceStr: string = null): FileEntity { const d = new FileEntity(); d.name = forceStr + '_' + Math.random().toString(36).substring(7) + '.gpx'; d.directory = dir; @@ -145,7 +144,7 @@ export class TestHelper { return d; } - public static getRandomizedPhotoEntry(dir: DirectoryEntity, forceStr = null) { + public static getRandomizedPhotoEntry(dir: DirectoryEntity, forceStr: string = null) { const rndStr = () => { diff --git a/tsconfig.json b/tsconfig.json index 51a61b1..a8696cb 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,7 @@ { "compileOnSave": true, "compilerOptions": { + "noImplicitAny": true, "sourceMap": true, "declaration": false, "moduleResolution": "node",