mirror of
https://github.com/xuthus83/pigallery2.git
synced 2024-11-03 21:04:03 +08:00
improving code quality. restricting secret to be accessible through rest api
This commit is contained in:
parent
b68d5d174d
commit
19d3f10d35
14
gulpfile.ts
14
gulpfile.ts
@ -43,13 +43,7 @@ gulp.task('build-backend', function () {
|
||||
|
||||
});
|
||||
|
||||
const handleError = (cb: (err: any) => void) => {
|
||||
return (err: any, stdout: string, stderr: string) => {
|
||||
console.log(stdout);
|
||||
console.log(stderr);
|
||||
cb(err);
|
||||
};
|
||||
};
|
||||
|
||||
const createDynamicTranslationFile = async (language: string) => {
|
||||
// load
|
||||
const folder = './src/frontend/' + translationFolder;
|
||||
@ -290,7 +284,7 @@ const translate = async (list: any[], cb: (err?: any) => void) => {
|
||||
'--source-lang="en" ' +
|
||||
'--source-file="./locale.source.xlf" ' +
|
||||
'--destination-filename="messages" ' +
|
||||
'--destination-folder="./src/frontend/"' + translationFolder + ' --destination-languages=' + localsStr);
|
||||
'--destination-folder="./src/frontend/"' + translationFolder + ' --destination-languages=' + localsStr);
|
||||
console.log(stdout);
|
||||
console.error(stderr);
|
||||
cb();
|
||||
@ -318,10 +312,10 @@ const merge = async (list: any[], cb: (err?: any) => void) => {
|
||||
};
|
||||
|
||||
gulp.task('update-translation-only', function (cb) {
|
||||
translate(getLanguages(), cb);
|
||||
translate(getLanguages(), cb).catch(console.error);
|
||||
});
|
||||
gulp.task('merge-translation-only', function (cb) {
|
||||
merge(getLanguages(), cb);
|
||||
merge(getLanguages(), cb).catch(console.error);
|
||||
});
|
||||
|
||||
gulp.task('update-translation', gulp.series('extract-locale', 'update-translation-only'));
|
||||
|
@ -54,7 +54,9 @@ export class RenderingMWs {
|
||||
|
||||
|
||||
public static renderConfig(req: Request, res: Response, next: NextFunction) {
|
||||
const message = new Message<ConfigClass>(null, Config.original());
|
||||
const originalConf = Config.original();
|
||||
originalConf.Server.sessionSecret = null;
|
||||
const message = new Message<ConfigClass>(null, originalConf);
|
||||
res.json(message);
|
||||
}
|
||||
|
||||
|
@ -6,8 +6,6 @@ import {ConfigTemplateEntry, DefaultsJobs} from '../../../../common/entities/job
|
||||
import {ServerConfig} from '../../../../common/config/private/IPrivateConfig';
|
||||
import {JobProgressStates} from '../../../../common/entities/job/JobProgressDTO';
|
||||
|
||||
declare var global: NodeJS.Global;
|
||||
const LOG_TAG = '[IndexingJob]';
|
||||
|
||||
export class IndexingJob extends Job {
|
||||
public readonly Name = DefaultsJobs[DefaultsJobs.Indexing];
|
||||
|
@ -7,8 +7,6 @@ import {MediaDTO} from '../../../../common/entities/MediaDTO';
|
||||
import {FileDTO} from '../../../../common/entities/FileDTO';
|
||||
import {backendTexts} from '../../../../common/BackendTexts';
|
||||
|
||||
const LOG_TAG = '[ThumbnailGenerationJob]';
|
||||
|
||||
|
||||
export class ThumbnailGenerationJob extends FileJob<{ sizes: number[], indexedOnly: boolean }> {
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import {IPrivateConfig, ServerConfig} from './IPrivateConfig';
|
||||
import * as path from 'path';
|
||||
import * as crypto from 'crypto';
|
||||
import {ConfigLoader} from 'typeconfig';
|
||||
import {Utils} from '../../Utils';
|
||||
import {UserRoles} from '../../entities/UserDTO';
|
||||
@ -61,14 +62,10 @@ export class ConfigClass extends PrivateConfigDefaultsClass implements IPrivateC
|
||||
}
|
||||
|
||||
if (Array.isArray(this.Server.sessionSecret) === false) {
|
||||
const s4 = (): string => {
|
||||
return Math.floor((1 + Math.random()) * 0x10000)
|
||||
.toString(16)
|
||||
.substring(1);
|
||||
};
|
||||
this.Server.sessionSecret = ['key1' + s4() + s4() + s4() + s4(),
|
||||
'key2' + s4() + s4() + s4() + s4(),
|
||||
'key3' + s4() + s4() + s4() + s4()];
|
||||
// if not secret is set, generate one randomly
|
||||
this.Server.sessionSecret = [crypto.randomBytes(256).toString('hex'),
|
||||
crypto.randomBytes(256).toString('hex'),
|
||||
crypto.randomBytes(256).toString('hex')];
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
import {Component, OnDestroy, OnInit} from '@angular/core';
|
||||
import {AuthenticationService} from './model/network/authentication.service';
|
||||
import {UserDTO} from '../../common/entities/UserDTO';
|
||||
import {Router} from '@angular/router';
|
||||
import {Config} from '../../common/config/public/Config';
|
||||
import {Title} from '@angular/platform-browser';
|
||||
|
@ -16,21 +16,13 @@ export class InfoPanelLightboxComponent {
|
||||
@Input() media: MediaDTO;
|
||||
@Output() closed = new EventEmitter();
|
||||
|
||||
public mapEnabled = true;
|
||||
public readonly mapEnabled: boolean;
|
||||
|
||||
constructor(public queryService: QueryService,
|
||||
public mapService: MapService) {
|
||||
this.mapEnabled = Config.Client.Map.enabled;
|
||||
}
|
||||
|
||||
isPhoto() {
|
||||
return this.media && MediaDTO.isPhoto(this.media);
|
||||
}
|
||||
|
||||
calcMpx() {
|
||||
return (this.media.metadata.size.width * this.media.metadata.size.height / 1000000).toFixed(2);
|
||||
}
|
||||
|
||||
get FullPath(): string {
|
||||
return Utils.concatUrls(this.media.directory.path, this.media.directory.name, this.media.name);
|
||||
}
|
||||
@ -39,21 +31,39 @@ export class InfoPanelLightboxComponent {
|
||||
return Utils.concatUrls(this.media.directory.path, this.media.directory.name);
|
||||
}
|
||||
|
||||
get VideoData(): VideoMetadata {
|
||||
if (typeof (<VideoDTO>this.media).metadata.bitRate === 'undefined') {
|
||||
return null;
|
||||
}
|
||||
return (<VideoDTO>this.media).metadata;
|
||||
}
|
||||
|
||||
get PositionData(): PositionMetaData {
|
||||
return (<PhotoDTO>this.media).metadata.positionData;
|
||||
}
|
||||
|
||||
get CameraData(): CameraMetadata {
|
||||
return (<PhotoDTO>this.media).metadata.cameraData;
|
||||
}
|
||||
|
||||
isPhoto() {
|
||||
return this.media && MediaDTO.isPhoto(this.media);
|
||||
}
|
||||
|
||||
calcMpx() {
|
||||
return (this.media.metadata.size.width * this.media.metadata.size.height / 1000000).toFixed(2);
|
||||
}
|
||||
|
||||
isThisYear() {
|
||||
return (new Date()).getFullYear() ===
|
||||
(new Date(this.media.metadata.creationDate)).getFullYear();
|
||||
}
|
||||
|
||||
|
||||
getTime() {
|
||||
const date = new Date(this.media.metadata.creationDate);
|
||||
return date.toTimeString().split(' ')[0];
|
||||
}
|
||||
|
||||
|
||||
toFraction(f: number) {
|
||||
if (f > 1) {
|
||||
return f;
|
||||
@ -61,13 +71,6 @@ export class InfoPanelLightboxComponent {
|
||||
return '1/' + (1 / f);
|
||||
}
|
||||
|
||||
get VideoData(): VideoMetadata {
|
||||
if (typeof (<VideoDTO>this.media).metadata.bitRate === 'undefined') {
|
||||
return null;
|
||||
}
|
||||
return (<VideoDTO>this.media).metadata;
|
||||
}
|
||||
|
||||
hasPositionData(): boolean {
|
||||
return !!(<PhotoDTO>this.media).metadata.positionData &&
|
||||
!!((<PhotoDTO>this.media).metadata.positionData.city ||
|
||||
@ -80,10 +83,6 @@ export class InfoPanelLightboxComponent {
|
||||
(<PhotoDTO>this.media).metadata.positionData.GPSData.latitude && (<PhotoDTO>this.media).metadata.positionData.GPSData.longitude;
|
||||
}
|
||||
|
||||
get PositionData(): PositionMetaData {
|
||||
return (<PhotoDTO>this.media).metadata.positionData;
|
||||
}
|
||||
|
||||
getPositionText(): string {
|
||||
if (!(<PhotoDTO>this.media).metadata.positionData) {
|
||||
return '';
|
||||
@ -99,10 +98,6 @@ export class InfoPanelLightboxComponent {
|
||||
return str;
|
||||
}
|
||||
|
||||
get CameraData(): CameraMetadata {
|
||||
return (<PhotoDTO>this.media).metadata.cameraData;
|
||||
}
|
||||
|
||||
close() {
|
||||
this.closed.emit();
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ describe('UserRouter', () => {
|
||||
await rimrafPR(tempDir);
|
||||
});
|
||||
|
||||
describe('/GET login', () => {
|
||||
describe('/POST login', () => {
|
||||
it('it should GET all the books', async () => {
|
||||
const srv = new Server();
|
||||
await srv.onStarted.wait();
|
||||
|
48
test/backend/integration/routers/admin/SettingsRouter.ts
Normal file
48
test/backend/integration/routers/admin/SettingsRouter.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import * as path from 'path';
|
||||
import * as util from 'util';
|
||||
import * as rimraf from 'rimraf';
|
||||
import {Config} from '../../../../../src/common/config/private/Config';
|
||||
import {ServerConfig} from '../../../../../src/common/config/private/IPrivateConfig';
|
||||
import {SQLConnection} from '../../../../../src/backend/model/database/sql/SQLConnection';
|
||||
import {Server} from '../../../../../src/backend/server';
|
||||
|
||||
process.env.NODE_ENV = 'test';
|
||||
const chai: any = require('chai');
|
||||
const chaiHttp = require('chai-http');
|
||||
const should = chai.should();
|
||||
chai.use(chaiHttp);
|
||||
|
||||
const rimrafPR = util.promisify(rimraf);
|
||||
describe('SettingsRouter', () => {
|
||||
|
||||
const tempDir = path.join(__dirname, '../../tmp');
|
||||
beforeEach(async () => {
|
||||
await rimrafPR(tempDir);
|
||||
Config.Server.Threading.enabled = false;
|
||||
Config.Server.Database.type = ServerConfig.DatabaseType.sqlite;
|
||||
Config.Server.Database.dbFolder = tempDir;
|
||||
});
|
||||
|
||||
|
||||
afterEach(async () => {
|
||||
await SQLConnection.close();
|
||||
await rimrafPR(tempDir);
|
||||
});
|
||||
|
||||
describe('/GET settings', () => {
|
||||
it('it should GET all the books', async () => {
|
||||
const originalSettings = Config.original();
|
||||
originalSettings.Server.sessionSecret = null;
|
||||
const srv = new Server();
|
||||
await srv.onStarted.wait();
|
||||
const result = await chai.request(srv.App)
|
||||
.get('/api/settings');
|
||||
|
||||
result.res.should.have.status(200);
|
||||
result.body.should.be.a('object');
|
||||
should.equal(result.body.error, null);
|
||||
result.body.result.should.deep.equal(originalSettings);
|
||||
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user