improving typings

This commit is contained in:
Patrik J. Braun 2018-11-30 15:36:42 +01:00
parent 62655eb47f
commit 0c8dbd7c62
15 changed files with 54 additions and 44 deletions

View File

@ -1,10 +1,9 @@
# PiGallery2 # PiGallery2
[![npm version](https://badge.fury.io/js/pigallery2.svg)](https://badge.fury.io/js/pigallery2) [![npm version](https://badge.fury.io/js/pigallery2.svg)](https://badge.fury.io/js/pigallery2)
[![Build Status](https://travis-ci.org/bpatrik/pigallery2.svg?branch=master)](https://travis-ci.org/bpatrik/pigallery2) [![Build Status](https://travis-ci.org/bpatrik/pigallery2.svg?branch=master)](https://travis-ci.org/bpatrik/pigallery2)
[![Coverage Status](https://coveralls.io/repos/github/bpatrik/PiGallery2/badge.svg?branch=master)](https://coveralls.io/github/bpatrik/PiGallery2?branch=master)
[![Heroku](https://heroku-badge.herokuapp.com/?app=pigallery2&style=flat)](https://pigallery2.herokuapp.com) [![Heroku](https://heroku-badge.herokuapp.com/?app=pigallery2&style=flat)](https://pigallery2.herokuapp.com)
[![Dependency Status](https://david-dm.org/bpatrik/pigallery2.svg)](https://david-dm.org/bpatrik/pigallery2) [![dependencies Status](https://david-dm.org/bpatrik/pigallery2/status.svg)](https://david-dm.org/bpatrik/pigallery2)
[![devDependency Status](https://david-dm.org/bpatrik/pigallery2/dev-status.svg)](https://david-dm.org/bpatrik/pigallery2#info=devDependencies) [![devDependencies Status](https://david-dm.org/bpatrik/pigallery2/dev-status.svg)](https://david-dm.org/bpatrik/pigallery2?type=dev)
This is a directory-first photo gallery website, optimised for running on low resource servers (especially on raspberry pi) This is a directory-first photo gallery website, optimised for running on low resource servers (especially on raspberry pi)

View File

@ -2,7 +2,7 @@ import * as winston from 'winston';
export const winstonSettings = { export const winstonSettings = {
transports: [ transports: [
new winston.transports.Console({ new winston.transports.Console(<any>{
level: process.env.NODE_ENV === 'production' ? 'info' : 'silly', level: process.env.NODE_ENV === 'production' ? 'info' : 'silly',
handleExceptions: true, handleExceptions: true,
json: false, json: false,
@ -11,9 +11,9 @@ export const winstonSettings = {
return (new Date()).toLocaleString(); return (new Date()).toLocaleString();
}, },
label: 'innerLabel', label: 'innerLabel',
formatter: (options) => { formatter: (options: any) => {
// Return string will be passed to logger. // Return string will be passed to logger.
return options.timestamp() + '[' + winston['config']['colorize'](options.level, options.level.toUpperCase()) + '] ' + return options.timestamp() + '[' + (<any>winston)['config']['colorize'](options.level, options.level.toUpperCase()) + '] ' +
(undefined !== options.message ? options.message : '') + (undefined !== options.message ? options.message : '') +
(options.meta && Object.keys(options.meta).length ? '\n\t' + JSON.stringify(options.meta) : ''); (options.meta && Object.keys(options.meta).length ? '\n\t' + JSON.stringify(options.meta) : '');
}, },
@ -23,4 +23,4 @@ export const winstonSettings = {
exitOnError: false exitOnError: false
}; };
export const Logger = new winston.Logger(winstonSettings); export const Logger = new (<any>winston).Logger(winstonSettings);

View File

@ -3,6 +3,7 @@ import {CreateSharingDTO, SharingDTO} from '../../common/entities/SharingDTO';
import {ObjectManagerRepository} from '../model/ObjectManagerRepository'; import {ObjectManagerRepository} from '../model/ObjectManagerRepository';
import {ErrorCodes, ErrorDTO} from '../../common/entities/Error'; import {ErrorCodes, ErrorDTO} from '../../common/entities/Error';
import {Config} from '../../common/config/private/Config'; import {Config} from '../../common/config/private/Config';
import {QueryParams} from '../../common/QueryParams';
const LOG_TAG = '[SharingMWs]'; const LOG_TAG = '[SharingMWs]';
@ -24,7 +25,7 @@ export class SharingMWs {
if (Config.Client.Sharing.enabled === false) { if (Config.Client.Sharing.enabled === false) {
return next(); return next();
} }
const sharingKey = req.params.sharingKey; const sharingKey = req.params[QueryParams.gallery.sharingKey_long];
try { try {
req.resultPipe = await ObjectManagerRepository.getInstance().SharingManager.findOne({sharingKey: sharingKey}); req.resultPipe = await ObjectManagerRepository.getInstance().SharingManager.findOne({sharingKey: sharingKey});

View File

@ -6,6 +6,7 @@ import {ObjectManagerRepository} from '../../model/ObjectManagerRepository';
import {Config} from '../../../common/config/private/Config'; import {Config} from '../../../common/config/private/Config';
import {PasswordHelper} from '../../model/PasswordHelper'; import {PasswordHelper} from '../../model/PasswordHelper';
import {Utils} from '../../../common/Utils'; import {Utils} from '../../../common/Utils';
import {QueryParams} from '../../../common/QueryParams';
export class AuthenticationMWs { export class AuthenticationMWs {
@ -48,7 +49,7 @@ export class AuthenticationMWs {
if (req.session.rememberMe === true) { if (req.session.rememberMe === true) {
req.sessionOptions.expires = new Date(Date.now() + Config.Server.sessionTimeout); req.sessionOptions.expires = new Date(Date.now() + Config.Server.sessionTimeout);
} else { } else {
delete(req.sessionOptions.expires); delete (req.sessionOptions.expires);
} }
return next(); return next();
} }
@ -83,7 +84,7 @@ export class AuthenticationMWs {
return next(); return next();
} }
// not enough parameter // not enough parameter
if ((!req.query.sk && !req.params.sharingKey)) { if ((!req.query[QueryParams.gallery.sharingKey_short] && !req.params[QueryParams.gallery.sharingKey_long])) {
return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'no sharing key provided')); return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'no sharing key provided'));
} }
@ -91,7 +92,7 @@ export class AuthenticationMWs {
const password = (req.body ? req.body.password : null) || null; const password = (req.body ? req.body.password : null) || null;
const sharing = await ObjectManagerRepository.getInstance().SharingManager.findOne({ const sharing = await ObjectManagerRepository.getInstance().SharingManager.findOne({
sharingKey: req.query.sk || req.params.sharingKey, sharingKey: req.query[QueryParams.gallery.sharingKey_short] || req.params[QueryParams.gallery.sharingKey_long]
}); });
console.log(sharing); console.log(sharing);
@ -154,9 +155,9 @@ export class AuthenticationMWs {
private static async getSharingUser(req: Request) { private static async getSharingUser(req: Request) {
if (Config.Client.Sharing.enabled === true && if (Config.Client.Sharing.enabled === true &&
(!!req.query.sk || !!req.params.sharingKey)) { (!!req.params[QueryParams.gallery.sharingKey_short] || !!req.params[QueryParams.gallery.sharingKey_long])) {
const sharing = await ObjectManagerRepository.getInstance().SharingManager.findOne({ const sharing = await ObjectManagerRepository.getInstance().SharingManager.findOne({
sharingKey: req.query.sk || req.params.sharingKey, sharingKey: req.query[QueryParams.gallery.sharingKey_short] || req.params[QueryParams.gallery.sharingKey_long],
}); });
if (!sharing || sharing.expires < Date.now()) { if (!sharing || sharing.expires < Date.now()) {
return null; return null;

View File

@ -3,6 +3,7 @@ import {UserRoles} from '../../common/entities/UserDTO';
import {RenderingMWs} from '../middlewares/RenderingMWs'; import {RenderingMWs} from '../middlewares/RenderingMWs';
import {SharingMWs} from '../middlewares/SharingMWs'; import {SharingMWs} from '../middlewares/SharingMWs';
import * as express from 'express'; import * as express from 'express';
import {QueryParams} from '../../common/QueryParams';
export class SharingRouter { export class SharingRouter {
public static route(app: express.Express) { public static route(app: express.Express) {
@ -22,7 +23,7 @@ export class SharingRouter {
} }
private static addGetSharing(app: express.Express) { private static addGetSharing(app: express.Express) {
app.get('/api/share/:sharingKey', app.get('/api/share/:' + QueryParams.gallery.sharingKey_long,
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.LimitedGuest), AuthenticationMWs.authorise(UserRoles.LimitedGuest),
SharingMWs.getSharing, SharingMWs.getSharing,

View File

@ -2,6 +2,7 @@ import * as _express from 'express';
import * as _bodyParser from 'body-parser'; import * as _bodyParser from 'body-parser';
import * as cookieParser from 'cookie-parser'; import * as cookieParser from 'cookie-parser';
import * as _http from 'http'; import * as _http from 'http';
// @ts-ignore
import * as locale from 'locale'; import * as locale from 'locale';
import {PublicRouter} from './routes/PublicRouter'; import {PublicRouter} from './routes/PublicRouter';
import {UserRouter} from './routes/UserRouter'; import {UserRouter} from './routes/UserRouter';
@ -68,7 +69,7 @@ export class Server {
constructor() { constructor() {
if (!(process.env.NODE_ENV === 'production')) { if (!(process.env.NODE_ENV === 'production')) {
Logger.debug(LOG_TAG, 'Running in DEBUG mode'); Logger.debug(LOG_TAG, 'Running in DEBUG mode, set env variable NODE_ENV=production to disable ');
} }
this.init(); this.init();
} }

View File

@ -8,6 +8,9 @@ export const QueryParams = {
toDate: 'toDate', toDate: 'toDate',
minResolution: 'fromRes', minResolution: 'fromRes',
maxResolution: 'toRes' maxResolution: 'toRes'
} },
photo: 'p',
sharingKey_short: 'sk',
sharingKey_long: 'sharingKey'
} }
}; };

View File

@ -4,6 +4,7 @@ import {LoginComponent} from './login/login.component';
import {GalleryComponent} from './gallery/gallery.component'; import {GalleryComponent} from './gallery/gallery.component';
import {AdminComponent} from './admin/admin.component'; import {AdminComponent} from './admin/admin.component';
import {ShareLoginComponent} from './sharelogin/share-login.component'; import {ShareLoginComponent} from './sharelogin/share-login.component';
import {QueryParams} from '../../common/QueryParams';
const ROUTES: Routes = [ const ROUTES: Routes = [
{ {
@ -31,7 +32,7 @@ const ROUTES: Routes = [
component: GalleryComponent component: GalleryComponent
}, },
{ {
path: 'share/:sharingKey', path: 'share/:' + QueryParams.gallery.sharingKey_long,
component: GalleryComponent component: GalleryComponent
}, },
{path: '', redirectTo: '/login', pathMatch: 'full'}, {path: '', redirectTo: '/login', pathMatch: 'full'},

View File

@ -16,7 +16,7 @@ import {ContentWrapper} from '../../../common/entities/ConentWrapper';
import {PageHelper} from '../model/page.helper'; import {PageHelper} from '../model/page.helper';
import {SortingMethods} from '../../../common/entities/SortingMethods'; import {SortingMethods} from '../../../common/entities/SortingMethods';
import {PhotoDTO} from '../../../common/entities/PhotoDTO'; import {PhotoDTO} from '../../../common/entities/PhotoDTO';
import {QueryService} from '../model/query.service'; import {QueryParams} from '../../../common/QueryParams';
@Component({ @Component({
selector: 'app-gallery', selector: 'app-gallery',
@ -90,7 +90,7 @@ export class GalleryComponent implements OnInit, OnDestroy {
if (params['sharingKey'] && params['sharingKey'] !== '') { if (params['sharingKey'] && params['sharingKey'] !== '') {
const sharing = await this.shareService.getSharing(); const sharing = await this.shareService.getSharing();
const qParams: { [key: string]: any } = {}; const qParams: { [key: string]: any } = {};
qParams[QueryService.SHARING_KEY] = this.shareService.getSharingKey(); qParams[QueryParams.gallery.sharingKey_short] = this.shareService.getSharingKey();
this._router.navigate(['/gallery', sharing.path], {queryParams: qParams}).catch(console.error); this._router.navigate(['/gallery', sharing.path], {queryParams: qParams}).catch(console.error);
return; return;
} }

View File

@ -10,7 +10,7 @@ import {Config} from '../../../common/config/public/Config';
import {ShareService} from './share.service'; import {ShareService} from './share.service';
import {NavigationService} from '../model/navigation.service'; import {NavigationService} from '../model/navigation.service';
import {SortingMethods} from '../../../common/entities/SortingMethods'; import {SortingMethods} from '../../../common/entities/SortingMethods';
import {QueryService} from '../model/query.service'; import {QueryParams} from '../../../common/QueryParams';
@Injectable() @Injectable()
@ -25,7 +25,7 @@ export class GalleryService {
constructor(private networkService: NetworkService, constructor(private networkService: NetworkService,
private galleryCacheService: GalleryCacheService, private galleryCacheService: GalleryCacheService,
private _shareService: ShareService, private _shareService: ShareService,
private navigatoinService: NavigationService) { private navigationService: NavigationService) {
this.content = new BehaviorSubject<ContentWrapper>(new ContentWrapper()); this.content = new BehaviorSubject<ContentWrapper>(new ContentWrapper());
this.sorting = new BehaviorSubject<SortingMethods>(Config.Client.Other.defaultPhotoSortingMethod); this.sorting = new BehaviorSubject<SortingMethods>(Config.Client.Other.defaultPhotoSortingMethod);
} }
@ -44,13 +44,15 @@ export class GalleryService {
content.directory = this.galleryCacheService.getDirectory(directoryName); content.directory = this.galleryCacheService.getDirectory(directoryName);
content.searchResult = null; content.searchResult = null;
console.log(content.directory);
this.content.next(content); this.content.next(content);
this.lastRequest.directory = directoryName; this.lastRequest.directory = directoryName;
const params: { [key: string]: any } = {}; const params: { [key: string]: any } = {};
if (Config.Client.Sharing.enabled === true) { if (Config.Client.Sharing.enabled === true) {
if (this._shareService.isSharing()) { if (this._shareService.isSharing()) {
params[QueryService.SHARING_KEY] = this._shareService.getSharingKey(); params[QueryParams.gallery.sharingKey_short] = this._shareService.getSharingKey();
} }
} }
@ -82,8 +84,9 @@ export class GalleryService {
this.content.next(cw); this.content.next(cw);
}).catch(() => { }).catch((e) => {
this.navigatoinService.toGallery(); console.error(e);
this.navigationService.toGallery();
}); });
} }

View File

@ -26,6 +26,7 @@ import {QueryService} from '../../model/query.service';
import {GalleryService} from '../gallery.service'; import {GalleryService} from '../gallery.service';
import {SortingMethods} from '../../../../common/entities/SortingMethods'; import {SortingMethods} from '../../../../common/entities/SortingMethods';
import {MediaDTO} from '../../../../common/entities/MediaDTO'; import {MediaDTO} from '../../../../common/entities/MediaDTO';
import {QueryParams} from '../../../../common/QueryParams';
@Component({ @Component({
selector: 'app-gallery-grid', selector: 'app-gallery-grid',
@ -73,13 +74,13 @@ export class GalleryGridComponent implements OnChanges, OnInit, AfterViewInit, O
ngOnInit() { ngOnInit() {
this.subscriptions.route = this.route.queryParams.subscribe((params: Params) => { this.subscriptions.route = this.route.queryParams.subscribe((params: Params) => {
if (params[QueryService.PHOTO_PARAM] && params[QueryService.PHOTO_PARAM] !== '') { if (params[QueryParams.gallery.photo] && params[QueryParams.gallery.photo] !== '') {
this.delayedRenderUpToPhoto = params[QueryService.PHOTO_PARAM]; this.delayedRenderUpToPhoto = params[QueryParams.gallery.photo];
if (!this.photos || this.photos.length === 0) { if (!this.photos || this.photos.length === 0) {
return; return;
} }
this.renderUpToPhoto(params[QueryService.PHOTO_PARAM]); this.renderUpToPhoto(params[QueryParams.gallery.photo]);
} }
}); });
this.subscriptions.sorting = this.galleryService.sorting.subscribe(() => { this.subscriptions.sorting = this.galleryService.sorting.subscribe(() => {

View File

@ -10,7 +10,6 @@ import {
QueryList, QueryList,
ViewChild ViewChild
} from '@angular/core'; } from '@angular/core';
import {PhotoDTO} from '../../../../common/entities/PhotoDTO';
import {GalleryPhotoComponent} from '../grid/photo/photo.grid.gallery.component'; import {GalleryPhotoComponent} from '../grid/photo/photo.grid.gallery.component';
import {Dimension} from '../../model/IRenderable'; import {Dimension} from '../../model/IRenderable';
import {FullScreenService} from '../fullscreen.service'; import {FullScreenService} from '../fullscreen.service';
@ -23,6 +22,7 @@ import {ActivatedRoute, Params, Router} from '@angular/router';
import {PageHelper} from '../../model/page.helper'; import {PageHelper} from '../../model/page.helper';
import {QueryService} from '../../model/query.service'; import {QueryService} from '../../model/query.service';
import {MediaDTO} from '../../../../common/entities/MediaDTO'; import {MediaDTO} from '../../../../common/entities/MediaDTO';
import {QueryParams} from '../../../../common/QueryParams';
export enum LightboxStates { export enum LightboxStates {
Open = 1, Open = 1,
@ -82,11 +82,11 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit {
ngOnInit(): void { ngOnInit(): void {
this.timer = timer(1000, 2000); this.timer = timer(1000, 2000);
this.subscription.route = this.route.queryParams.subscribe((params: Params) => { this.subscription.route = this.route.queryParams.subscribe((params: Params) => {
if (params[QueryService.PHOTO_PARAM] && params[QueryService.PHOTO_PARAM] !== '') { if (params[QueryParams.gallery.photo] && params[QueryParams.gallery.photo] !== '') {
if (!this.gridPhotoQL) { if (!this.gridPhotoQL) {
return this.delayedPhotoShow = params[QueryService.PHOTO_PARAM]; return this.delayedPhotoShow = params[QueryParams.gallery.photo];
} }
this.onNavigateTo(params[QueryService.PHOTO_PARAM]); this.onNavigateTo(params[QueryParams.gallery.photo]);
} else if (this.status === LightboxStates.Open) { } else if (this.status === LightboxStates.Open) {
this.delayedPhotoShow = null; this.delayedPhotoShow = null;
this.hideLigthbox(); this.hideLigthbox();

View File

@ -3,7 +3,7 @@ import {NetworkService} from '../model/network/network.service';
import {CreateSharingDTO, SharingDTO} from '../../../common/entities/SharingDTO'; import {CreateSharingDTO, SharingDTO} from '../../../common/entities/SharingDTO';
import {Router, RoutesRecognized} from '@angular/router'; import {Router, RoutesRecognized} from '@angular/router';
import {BehaviorSubject} from 'rxjs'; import {BehaviorSubject} from 'rxjs';
import {QueryService} from '../model/query.service'; import {QueryParams} from '../../../common/QueryParams';
@Injectable() @Injectable()
export class ShareService { export class ShareService {
@ -28,8 +28,8 @@ export class ShareService {
this.router.events.subscribe(val => { this.router.events.subscribe(val => {
if (val instanceof RoutesRecognized) { if (val instanceof RoutesRecognized) {
this.param = val.state.root.firstChild.params['sharingKey'] || null; this.param = val.state.root.firstChild.params[QueryParams.gallery.sharingKey_long] || null;
this.queryParam = val.state.root.firstChild.queryParams[QueryService.SHARING_KEY] || null; this.queryParam = val.state.root.firstChild.queryParams[QueryParams.gallery.sharingKey_short] || null;
const changed = this.sharingKey !== this.param || this.queryParam; const changed = this.sharingKey !== this.param || this.queryParam;
if (changed) { if (changed) {
this.sharingKey = this.param || this.queryParam; this.sharingKey = this.param || this.queryParam;

View File

@ -2,12 +2,11 @@ import {Injectable} from '@angular/core';
import {ShareService} from '../gallery/share.service'; import {ShareService} from '../gallery/share.service';
import {PhotoDTO} from '../../../common/entities/PhotoDTO'; import {PhotoDTO} from '../../../common/entities/PhotoDTO';
import {MediaDTO} from '../../../common/entities/MediaDTO'; import {MediaDTO} from '../../../common/entities/MediaDTO';
import {QueryParams} from '../../../common/QueryParams';
@Injectable() @Injectable()
export class QueryService { export class QueryService {
public static readonly PHOTO_PARAM = 'p';
public static readonly SHARING_KEY = 'sk';
constructor(private shareService: ShareService) { constructor(private shareService: ShareService) {
} }
@ -15,10 +14,10 @@ export class QueryService {
getParams(media?: MediaDTO): { [key: string]: string } { getParams(media?: MediaDTO): { [key: string]: string } {
const query: { [key: string]: string } = {}; const query: { [key: string]: string } = {};
if (media) { if (media) {
query[QueryService.PHOTO_PARAM] = media.name; query[QueryParams.gallery.photo] = media.name;
} }
if (this.shareService.isSharing()) { if (this.shareService.isSharing()) {
query[QueryService.SHARING_KEY] = this.shareService.getSharingKey(); query[QueryParams.gallery.sharingKey_short] = this.shareService.getSharingKey();
} }
return query; return query;
} }

View File

@ -8,7 +8,7 @@
"main": "./backend/index.js", "main": "./backend/index.js",
"bin": "./backend/index.js", "bin": "./backend/index.js",
"scripts": { "scripts": {
"install": "tsc && gulp build-prod", "installx": "tsc && gulp build-prod",
"build-release": "gulp build-release", "build-release": "gulp build-release",
"pretest": "tsc", "pretest": "tsc",
"test": "ng test && mocha --recursive test/backend/unit && mocha --recursive test/backend/integration && mocha --recursive test/common/unit ", "test": "ng test && mocha --recursive test/backend/unit && mocha --recursive test/backend/integration && mocha --recursive test/common/unit ",
@ -34,7 +34,7 @@
"cookie-session": "2.0.0-beta.3", "cookie-session": "2.0.0-beta.3",
"ejs": "2.6.1", "ejs": "2.6.1",
"express": "4.16.4", "express": "4.16.4",
"fluent-ffmpeg": "^2.1.2", "fluent-ffmpeg": "2.1.2",
"jimp": "0.5.6", "jimp": "0.5.6",
"locale": "0.1.0", "locale": "0.1.0",
"reflect-metadata": "0.1.12", "reflect-metadata": "0.1.12",
@ -64,16 +64,16 @@
"@ngx-translate/i18n-polyfill": "1.0.0", "@ngx-translate/i18n-polyfill": "1.0.0",
"@types/bcryptjs": "2.4.2", "@types/bcryptjs": "2.4.2",
"@types/chai": "4.1.7", "@types/chai": "4.1.7",
"@types/cookie-parser": "^1.4.1", "@types/cookie-parser": "1.4.1",
"@types/cookie-session": "2.0.36", "@types/cookie-session": "2.0.36",
"@types/ejs": "^2.6.0", "@types/ejs": "2.6.0",
"@types/express": "4.16.0", "@types/express": "4.16.0",
"@types/fluent-ffmpeg": "^2.1.8", "@types/fluent-ffmpeg": "2.1.8",
"@types/gm": "1.18.2", "@types/gm": "1.18.2",
"@types/jasmine": "3.3.0", "@types/jasmine": "3.3.0",
"@types/node": "10.12.10", "@types/node": "10.12.10",
"@types/sharp": "0.21.0", "@types/sharp": "0.21.0",
"@types/winston": "2.4.4", "@types/winston": "2.3.9",
"bootstrap": "4.1.3", "bootstrap": "4.1.3",
"chai": "4.2.0", "chai": "4.2.0",
"codelyzer": "4.5.0", "codelyzer": "4.5.0",