mirror of
https://github.com/bpatrik/pigallery2.git
synced 2025-05-31 23:09:48 +02:00
improving logging and configs
This commit is contained in:
parent
98681322f5
commit
7e56ef1111
@ -7,8 +7,7 @@ declare module 'winston' {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export const Logger = new winston.Logger({
|
||||
export const winstonSettings = {
|
||||
transports: [
|
||||
new winston.transports.Console({
|
||||
level: 'silly',
|
||||
@ -29,4 +28,6 @@ export const Logger = new winston.Logger({
|
||||
})
|
||||
],
|
||||
exitOnError: false
|
||||
});
|
||||
};
|
||||
|
||||
export const Logger = new winston.Logger(winstonSettings);
|
@ -1,5 +1,5 @@
|
||||
import * as path from "path";
|
||||
import {Config} from "./config/Config";
|
||||
import {Config} from "../common/config/private/Config";
|
||||
|
||||
class ProjectPathClass {
|
||||
public Root: string;
|
||||
|
@ -1,28 +0,0 @@
|
||||
import {ConfigLoader} from "./ConfigLoader";
|
||||
import * as path from "path";
|
||||
import {ConfigClass, DatabaseType} from "../../common/config/Config";
|
||||
|
||||
export let Config = new ConfigClass();
|
||||
|
||||
Config.Server = {
|
||||
port: 80,
|
||||
imagesFolder: "demo/images",
|
||||
thumbnail: {
|
||||
folder: "demo/TEMP",
|
||||
hardwareAcceleration: true
|
||||
},
|
||||
database: {
|
||||
type: DatabaseType.mysql,
|
||||
mysql: {
|
||||
host: "localhost",
|
||||
username: "root",
|
||||
password: "root",
|
||||
database: "pigallery2"
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ConfigLoader.init(Config, path.join(__dirname, './../../config.json'), [["PORT", "Server-port"]]);
|
||||
|
||||
|
@ -1,116 +0,0 @@
|
||||
import * as fs from "fs";
|
||||
import * as optimist from "optimist";
|
||||
|
||||
export class ConfigLoader {
|
||||
|
||||
static init(configObject: any, configFilePath?: string, envAlias: Array<Array<string>> = []) {
|
||||
this.processConfigFile(configFilePath, configObject);
|
||||
this.processArguments(configObject);
|
||||
this.processEnvVariables(configObject, envAlias);
|
||||
|
||||
}
|
||||
|
||||
private static processEnvVariables(configObject: any, envAlias: Array<Array<string>>) {
|
||||
let varAliases = {};
|
||||
envAlias.forEach((alias) => {
|
||||
if (process.env[alias[0]]) {
|
||||
varAliases[alias[1]] = process.env[alias[0]];
|
||||
}
|
||||
});
|
||||
this.processHierarchyVar(configObject, varAliases);
|
||||
this.processHierarchyVar(configObject, process.env);
|
||||
};
|
||||
|
||||
private static processArguments(configObject: any) {
|
||||
let argv = optimist.argv;
|
||||
delete(argv._);
|
||||
delete(argv.$0);
|
||||
this.processHierarchyVar(configObject, argv);
|
||||
};
|
||||
|
||||
|
||||
private static processHierarchyVar(configObject: any, vars: any) {
|
||||
let config = {};
|
||||
|
||||
Object.keys(vars).forEach((key) => {
|
||||
let keyArray = key.split("-");
|
||||
let value = vars[key];
|
||||
|
||||
//recursive settings
|
||||
let setObject = (object: any, keyArray: Array<string>, value: any): void => {
|
||||
let key = keyArray.shift();
|
||||
object[key] = object[key] || {};
|
||||
|
||||
if (keyArray.length == 0) {
|
||||
//convert to boolean
|
||||
if (value.toLowerCase && value.toLowerCase() === "false") {
|
||||
value = false;
|
||||
}
|
||||
if (value.toLowerCase && value.toLowerCase() === "true") {
|
||||
value = true;
|
||||
}
|
||||
|
||||
object[key] = value;
|
||||
return;
|
||||
}
|
||||
|
||||
return setObject(object[key], keyArray, value);
|
||||
};
|
||||
setObject(config, keyArray, value);
|
||||
|
||||
});
|
||||
|
||||
this.loadObject(configObject, config);
|
||||
}
|
||||
|
||||
private static processConfigFile(configFilePath: string, configObject: any) {
|
||||
if (typeof configFilePath !== 'undefined') {
|
||||
if (ConfigLoader.loadConfigFile(configFilePath, configObject) === false) {
|
||||
ConfigLoader.saveConfigFile(configFilePath, configObject);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private static loadConfigFile(configFilePath: string, configObject: any): boolean {
|
||||
if (fs.existsSync(configFilePath) === false) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
let config = JSON.parse(fs.readFileSync(configFilePath, 'utf8'));
|
||||
|
||||
this.loadObject(configObject, config);
|
||||
return true;
|
||||
} catch (err) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private static saveConfigFile(configFilePath: string, configObject: any) {
|
||||
try {
|
||||
fs.writeFileSync(configFilePath, JSON.stringify(configObject, null, 4));
|
||||
} catch (err) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static loadObject(targetObject, sourceObject) {
|
||||
Object.keys(sourceObject).forEach((key) => {
|
||||
if (typeof targetObject[key] === "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Array.isArray(targetObject[key])) {
|
||||
return targetObject[key] = sourceObject[key];
|
||||
}
|
||||
|
||||
if (typeof targetObject[key] === "object") {
|
||||
return this.loadObject(targetObject[key], sourceObject[key]);
|
||||
}
|
||||
|
||||
targetObject[key] = sourceObject[key];
|
||||
});
|
||||
}
|
||||
}
|
@ -8,9 +8,9 @@ import {AutoCompleteItem, SearchTypes} from "../../common/entities/AutoCompleteI
|
||||
import {ContentWrapper} from "../../common/entities/ConentWrapper";
|
||||
import {SearchResultDTO} from "../../common/entities/SearchResult";
|
||||
import {PhotoDTO} from "../../common/entities/PhotoDTO";
|
||||
import {Config} from "../config/Config";
|
||||
import {ProjectPath} from "../ProjectPath";
|
||||
import {Logger} from "../Logger";
|
||||
import {Config} from "../../common/config/private/Config";
|
||||
|
||||
|
||||
const LOG_TAG = "[GalleryMWs]";
|
||||
|
@ -5,12 +5,12 @@ import * as fs from "fs";
|
||||
import * as os from "os";
|
||||
import {NextFunction, Request, Response} from "express";
|
||||
import {Error, ErrorCodes} from "../../../common/entities/Error";
|
||||
import {Config} from "../../config/Config";
|
||||
import {ContentWrapper} from "../../../common/entities/ConentWrapper";
|
||||
import {DirectoryDTO} from "../../../common/entities/DirectoryDTO";
|
||||
import {ProjectPath} from "../../ProjectPath";
|
||||
import {PhotoDTO} from "../../../common/entities/PhotoDTO";
|
||||
import {hardwareRenderer, softwareRenderer} from "./THRenderers";
|
||||
import {Config} from "../../../common/config/private/Config";
|
||||
|
||||
|
||||
Config.Client.concurrentThumbnailGenerations = Math.max(1, os.cpus().length - 1);
|
||||
@ -18,14 +18,21 @@ Config.Client.concurrentThumbnailGenerations = Math.max(1, os.cpus().length - 1)
|
||||
const Pool = require('threads').Pool;
|
||||
const pool = new Pool(Config.Client.concurrentThumbnailGenerations);
|
||||
|
||||
if (Config.Server.thumbnail.hardwareAcceleration == true) {
|
||||
pool.run(hardwareRenderer);
|
||||
} else {
|
||||
pool.run(softwareRenderer);
|
||||
}
|
||||
|
||||
export class ThumbnailGeneratorMWs {
|
||||
private static poolsInited = false;
|
||||
|
||||
private static initPools() {
|
||||
if (this.poolsInited == true) {
|
||||
return
|
||||
}
|
||||
if (Config.Server.thumbnail.hardwareAcceleration == true) {
|
||||
pool.run(hardwareRenderer);
|
||||
} else {
|
||||
pool.run(softwareRenderer);
|
||||
}
|
||||
this.poolsInited = true;
|
||||
}
|
||||
|
||||
private static addThInfoTODir(directory: DirectoryDTO) {
|
||||
if (typeof directory.photos == "undefined") {
|
||||
@ -111,6 +118,7 @@ export class ThumbnailGeneratorMWs {
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static generateImage(imagePath: string, size: number, makeSquare: boolean, req: Request, res: Response, next: NextFunction) {
|
||||
|
||||
//generate thumbnail path
|
||||
@ -129,6 +137,7 @@ export class ThumbnailGeneratorMWs {
|
||||
fs.mkdirSync(ProjectPath.ThumbnailFolder);
|
||||
}
|
||||
|
||||
this.initPools();
|
||||
//run on other thread
|
||||
pool.send({imagePath: imagePath, size: size, thPath: thPath, makeSquare: makeSquare, __dirname: __dirname})
|
||||
.on('done', (out) => {
|
||||
|
@ -1,9 +1,9 @@
|
||||
///<reference path="../customtypings/ExtendedRequest.d.ts"/>
|
||||
import {NextFunction, Request, Response} from "express";
|
||||
import {Error, ErrorCodes} from "../../../common/entities/Error";
|
||||
import {UserRoles, UserDTO} from "../../../common/entities/UserDTO";
|
||||
import {UserDTO, UserRoles} from "../../../common/entities/UserDTO";
|
||||
import {ObjectManagerRepository} from "../../model/ObjectManagerRepository";
|
||||
import {Config} from "../../config/Config";
|
||||
import {Config} from "../../../common/config/private/Config";
|
||||
|
||||
export class AuthenticationMWs {
|
||||
|
||||
|
@ -2,8 +2,8 @@ import {NextFunction, Request, Response} from "express";
|
||||
import {Error, ErrorCodes} from "../../../common/entities/Error";
|
||||
import {ObjectManagerRepository} from "../../model/ObjectManagerRepository";
|
||||
import {UserDTO} from "../../../common/entities/UserDTO";
|
||||
import {Config} from "../../config/Config";
|
||||
import {Utils} from "../../../common/Utils";
|
||||
import {Config} from "../../../common/config/private/Config";
|
||||
|
||||
export class UserMWs {
|
||||
|
||||
|
@ -138,7 +138,6 @@ pool.run(
|
||||
try {
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
let file = list[i];
|
||||
console.log(list[i]);
|
||||
let fullFilePath = path.normalize(path.resolve(directoryInfo.absoluteDirectoryName, file));
|
||||
if (photosOnly == false && fs.statSync(fullFilePath).isDirectory()) {
|
||||
let promise = parseDir({
|
||||
@ -195,7 +194,7 @@ pool.run(
|
||||
|
||||
export class DiskManager {
|
||||
public static scanDirectory(relativeDirectoryName: string, cb: (error: any, result: DirectoryDTO) => void) {
|
||||
Logger.silly(LOG_TAG, "scanDirectory");
|
||||
Logger.silly(LOG_TAG, "scanning directory:", relativeDirectoryName);
|
||||
let directoryName = path.basename(relativeDirectoryName);
|
||||
let directoryParent = path.join(path.dirname(relativeDirectoryName), path.sep);
|
||||
let absoluteDirectoryName = path.join(ProjectPath.ImageFolder, relativeDirectoryName);
|
||||
|
@ -1,10 +1,10 @@
|
||||
import "reflect-metadata";
|
||||
import {createConnection, Connection} from "typeorm";
|
||||
import {Config} from "../../config/Config";
|
||||
import {Connection, createConnection} from "typeorm";
|
||||
import {UserEntity} from "./enitites/UserEntity";
|
||||
import {UserRoles} from "../../../common/entities/UserDTO";
|
||||
import {PhotoEntity, PhotoMetadataEntity} from "./enitites/PhotoEntity";
|
||||
import {DirectoryEntity} from "./enitites/DirectoryEntity";
|
||||
import {Config} from "../../../common/config/private/Config";
|
||||
|
||||
|
||||
export class MySQLConnection {
|
||||
|
@ -2,22 +2,22 @@ import {AuthenticationMWs} from "../middlewares/user/AuthenticationMWs";
|
||||
import {UserRoles} from "../../common/entities/UserDTO";
|
||||
|
||||
export class AdminRouter {
|
||||
constructor(private app: any) {
|
||||
public static route(app: any) {
|
||||
|
||||
this.addResetDB();
|
||||
this.addIndexGallery();
|
||||
this.addResetDB(app);
|
||||
this.addIndexGallery(app);
|
||||
}
|
||||
|
||||
private addResetDB() {
|
||||
this.app.post("/api/admin/db/reset",
|
||||
private static addResetDB(app) {
|
||||
app.post("/api/admin/db/reset",
|
||||
AuthenticationMWs.authenticate,
|
||||
AuthenticationMWs.authorise(UserRoles.Admin)
|
||||
//TODO: implement
|
||||
);
|
||||
};
|
||||
|
||||
private addIndexGallery() {
|
||||
this.app.post("/api/admin/gallery/index",
|
||||
private static addIndexGallery(app) {
|
||||
app.post("/api/admin/gallery/index",
|
||||
AuthenticationMWs.authenticate,
|
||||
AuthenticationMWs.authorise(UserRoles.Admin)
|
||||
//TODO: implement
|
||||
|
@ -1,26 +1,27 @@
|
||||
import {RenderingMWs} from "../middlewares/RenderingMWs";
|
||||
import {Error, ErrorCodes} from "../../common/entities/Error";
|
||||
import {Logger} from "../Logger";
|
||||
import Request = Express.Request;
|
||||
import Response = Express.Response;
|
||||
|
||||
export class ErrorRouter {
|
||||
constructor(private app: any) {
|
||||
public static route(app: any) {
|
||||
|
||||
this.addApiErrorHandler();
|
||||
this.addGenericHandler();
|
||||
this.addApiErrorHandler(app);
|
||||
this.addGenericHandler(app);
|
||||
}
|
||||
|
||||
private addApiErrorHandler() {
|
||||
this.app.use("/api/*",
|
||||
private static addApiErrorHandler(app) {
|
||||
app.use("/api/*",
|
||||
RenderingMWs.renderError
|
||||
);
|
||||
};
|
||||
|
||||
private addGenericHandler() {
|
||||
this.app.use((err: any, req: Request, res: Response, next: Function) => {
|
||||
private static addGenericHandler(app) {
|
||||
app.use((err: any, req: Request, res: Response, next: Function) => {
|
||||
|
||||
//Flush out the stack to the console
|
||||
console.error(err.stack);
|
||||
Logger.error(err);
|
||||
next(new Error(ErrorCodes.SERVER_ERROR, "Unknown server side error"));
|
||||
},
|
||||
RenderingMWs.renderError
|
||||
|
@ -4,20 +4,20 @@ import {RenderingMWs} from "../middlewares/RenderingMWs";
|
||||
import {ThumbnailGeneratorMWs} from "../middlewares/thumbnail/ThumbnailGeneratorMWs";
|
||||
|
||||
export class GalleryRouter {
|
||||
constructor(private app: any) {
|
||||
public static route(app: any) {
|
||||
|
||||
this.addGetImageIcon();
|
||||
this.addGetImageThumbnail();
|
||||
this.addGetImage();
|
||||
this.addDirectoryList();
|
||||
this.addGetImageIcon(app);
|
||||
this.addGetImageThumbnail(app);
|
||||
this.addGetImage(app);
|
||||
this.addDirectoryList(app);
|
||||
|
||||
this.addSearch();
|
||||
this.addInstantSearch();
|
||||
this.addAutoComplete();
|
||||
this.addSearch(app);
|
||||
this.addInstantSearch(app);
|
||||
this.addAutoComplete(app);
|
||||
}
|
||||
|
||||
private addDirectoryList() {
|
||||
this.app.get(["/api/gallery/content/:directory(*)", "/api/gallery/", "/api/gallery//"],
|
||||
private static addDirectoryList(app) {
|
||||
app.get(["/api/gallery/content/:directory(*)", "/api/gallery/", "/api/gallery//"],
|
||||
AuthenticationMWs.authenticate,
|
||||
GalleryMWs.listDirectory,
|
||||
ThumbnailGeneratorMWs.addThumbnailInformation,
|
||||
@ -27,16 +27,16 @@ export class GalleryRouter {
|
||||
};
|
||||
|
||||
|
||||
private addGetImage() {
|
||||
this.app.get(["/api/gallery/content/:imagePath(*\.(jpg|bmp|png|gif|jpeg))"],
|
||||
private static addGetImage(app) {
|
||||
app.get(["/api/gallery/content/:imagePath(*\.(jpg|bmp|png|gif|jpeg))"],
|
||||
AuthenticationMWs.authenticate,
|
||||
GalleryMWs.loadImage,
|
||||
RenderingMWs.renderFile
|
||||
);
|
||||
};
|
||||
|
||||
private addGetImageThumbnail() {
|
||||
this.app.get("/api/gallery/content/:imagePath(*\.(jpg|bmp|png|gif|jpeg))/thumbnail/:size?",
|
||||
private static addGetImageThumbnail(app) {
|
||||
app.get("/api/gallery/content/:imagePath(*\.(jpg|bmp|png|gif|jpeg))/thumbnail/:size?",
|
||||
AuthenticationMWs.authenticate,
|
||||
GalleryMWs.loadImage,
|
||||
ThumbnailGeneratorMWs.generateThumbnail,
|
||||
@ -44,8 +44,8 @@ export class GalleryRouter {
|
||||
);
|
||||
};
|
||||
|
||||
private addGetImageIcon() {
|
||||
this.app.get("/api/gallery/content/:imagePath(*\.(jpg|bmp|png|gif|jpeg))/icon",
|
||||
private static addGetImageIcon(app) {
|
||||
app.get("/api/gallery/content/:imagePath(*\.(jpg|bmp|png|gif|jpeg))/icon",
|
||||
AuthenticationMWs.authenticate,
|
||||
GalleryMWs.loadImage,
|
||||
ThumbnailGeneratorMWs.generateIcon,
|
||||
@ -53,8 +53,8 @@ export class GalleryRouter {
|
||||
);
|
||||
};
|
||||
|
||||
private addSearch() {
|
||||
this.app.get("/api/search/:text",
|
||||
private static addSearch(app) {
|
||||
app.get("/api/search/:text",
|
||||
AuthenticationMWs.authenticate,
|
||||
GalleryMWs.search,
|
||||
ThumbnailGeneratorMWs.addThumbnailInformation,
|
||||
@ -63,8 +63,8 @@ export class GalleryRouter {
|
||||
);
|
||||
};
|
||||
|
||||
private addInstantSearch() {
|
||||
this.app.get("/api/instant-search/:text",
|
||||
private static addInstantSearch(app) {
|
||||
app.get("/api/instant-search/:text",
|
||||
AuthenticationMWs.authenticate,
|
||||
GalleryMWs.instantSearch,
|
||||
ThumbnailGeneratorMWs.addThumbnailInformation,
|
||||
@ -73,8 +73,8 @@ export class GalleryRouter {
|
||||
);
|
||||
};
|
||||
|
||||
private addAutoComplete() {
|
||||
this.app.get("/api/autocomplete/:text",
|
||||
private static addAutoComplete(app) {
|
||||
app.get("/api/autocomplete/:text",
|
||||
AuthenticationMWs.authenticate,
|
||||
GalleryMWs.autocomplete,
|
||||
RenderingMWs.renderResult
|
||||
|
@ -2,11 +2,12 @@ import * as _express from "express";
|
||||
import {NextFunction, Request, Response} from "express";
|
||||
import * as _path from "path";
|
||||
import {Utils} from "../../common/Utils";
|
||||
import {Config} from "../config/Config";
|
||||
import {Config} from "../../common/config/private/Config";
|
||||
|
||||
export class PublicRouter {
|
||||
constructor(private app) {
|
||||
this.app.use((req:Request, res:Response, next:NextFunction) => {
|
||||
|
||||
public static route(app) {
|
||||
app.use((req: Request, res: Response, next: NextFunction) => {
|
||||
res.tpl = {};
|
||||
|
||||
res.tpl.user = null;
|
||||
@ -20,15 +21,15 @@ export class PublicRouter {
|
||||
return next();
|
||||
});
|
||||
|
||||
this.app.use(_express.static(_path.resolve(__dirname, './../../frontend')));
|
||||
this.app.use('/node_modules', _express.static(_path.resolve(__dirname, './../../node_modules')));
|
||||
this.app.use('/common', _express.static(_path.resolve(__dirname, './../../common')));
|
||||
app.use(_express.static(_path.resolve(__dirname, './../../frontend')));
|
||||
app.use('/node_modules', _express.static(_path.resolve(__dirname, './../../node_modules')));
|
||||
app.use('/common', _express.static(_path.resolve(__dirname, './../../common')));
|
||||
|
||||
const renderIndex = (req: Request, res: Response) => {
|
||||
res.render(_path.resolve(__dirname, './../../frontend/index.ejs'), res.tpl);
|
||||
};
|
||||
|
||||
this.app.get(['/', '/login', "/gallery*", "/admin", "/search*"], renderIndex);
|
||||
app.get(['/', '/login', "/gallery*", "/admin", "/search*"], renderIndex);
|
||||
|
||||
|
||||
}
|
||||
|
@ -2,22 +2,22 @@ import {AuthenticationMWs} from "../middlewares/user/AuthenticationMWs";
|
||||
import {UserRoles} from "../../common/entities/UserDTO";
|
||||
|
||||
export class SharingRouter {
|
||||
constructor(private app: any) {
|
||||
public static route(app: any) {
|
||||
|
||||
this.addGetSharing();
|
||||
this.addUpdateSharing();
|
||||
this.addGetSharing(app);
|
||||
this.addUpdateSharing(app);
|
||||
}
|
||||
|
||||
private addGetSharing() {
|
||||
this.app.get("/api/share/:directory",
|
||||
private static addGetSharing(app) {
|
||||
app.get("/api/share/:directory",
|
||||
AuthenticationMWs.authenticate,
|
||||
AuthenticationMWs.authorise(UserRoles.User)
|
||||
//TODO: implement
|
||||
);
|
||||
};
|
||||
|
||||
private addUpdateSharing() {
|
||||
this.app.post("/api/share/:directory",
|
||||
private static addUpdateSharing(app) {
|
||||
app.post("/api/share/:directory",
|
||||
AuthenticationMWs.authenticate,
|
||||
AuthenticationMWs.authorise(UserRoles.User)
|
||||
//TODO: implement
|
||||
|
@ -5,29 +5,29 @@ import {UserRequestConstrainsMWs} from "../middlewares/user/UserRequestConstrain
|
||||
import {RenderingMWs} from "../middlewares/RenderingMWs";
|
||||
|
||||
export class UserRouter {
|
||||
constructor(private app) {
|
||||
this.addLogin();
|
||||
this.addLogout();
|
||||
this.addGetSessionUser();
|
||||
this.addChangePassword();
|
||||
public static route(app) {
|
||||
this.addLogin(app);
|
||||
this.addLogout(app);
|
||||
this.addGetSessionUser(app);
|
||||
this.addChangePassword(app);
|
||||
|
||||
|
||||
this.addCreateUser();
|
||||
this.addDeleteUser();
|
||||
this.addListUsers();
|
||||
this.addChangeRole();
|
||||
this.addCreateUser(app);
|
||||
this.addDeleteUser(app);
|
||||
this.addListUsers(app);
|
||||
this.addChangeRole(app);
|
||||
}
|
||||
|
||||
private addLogin() {
|
||||
this.app.post("/api/user/login",
|
||||
private static addLogin(app) {
|
||||
app.post("/api/user/login",
|
||||
AuthenticationMWs.inverseAuthenticate,
|
||||
AuthenticationMWs.login,
|
||||
RenderingMWs.renderSessionUser
|
||||
);
|
||||
};
|
||||
|
||||
private addLogout() {
|
||||
this.app.post("/api/user/logout",
|
||||
private static addLogout(app) {
|
||||
app.post("/api/user/logout",
|
||||
AuthenticationMWs.authenticate,
|
||||
AuthenticationMWs.logout,
|
||||
RenderingMWs.renderOK
|
||||
@ -35,16 +35,16 @@ export class UserRouter {
|
||||
};
|
||||
|
||||
|
||||
private addGetSessionUser() {
|
||||
this.app.get("/api/user/login",
|
||||
private static addGetSessionUser(app) {
|
||||
app.get("/api/user/login",
|
||||
AuthenticationMWs.authenticate,
|
||||
RenderingMWs.renderSessionUser
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
private addChangePassword() {
|
||||
this.app.post("/api/user/:id/password",
|
||||
private static addChangePassword(app) {
|
||||
app.post("/api/user/:id/password",
|
||||
AuthenticationMWs.authenticate,
|
||||
UserRequestConstrainsMWs.forceSelfRequest,
|
||||
UserMWs.changePassword,
|
||||
@ -53,8 +53,8 @@ export class UserRouter {
|
||||
};
|
||||
|
||||
|
||||
private addCreateUser() {
|
||||
this.app.put("/api/user",
|
||||
private static addCreateUser(app) {
|
||||
app.put("/api/user",
|
||||
AuthenticationMWs.authenticate,
|
||||
AuthenticationMWs.authorise(UserRoles.Admin),
|
||||
UserMWs.createUser,
|
||||
@ -62,8 +62,8 @@ export class UserRouter {
|
||||
);
|
||||
};
|
||||
|
||||
private addDeleteUser() {
|
||||
this.app.delete("/api/user/:id",
|
||||
private static addDeleteUser(app) {
|
||||
app.delete("/api/user/:id",
|
||||
AuthenticationMWs.authenticate,
|
||||
AuthenticationMWs.authorise(UserRoles.Admin),
|
||||
UserRequestConstrainsMWs.notSelfRequest,
|
||||
@ -73,8 +73,8 @@ export class UserRouter {
|
||||
};
|
||||
|
||||
|
||||
private addListUsers() {
|
||||
this.app.get("/api/user/list",
|
||||
private static addListUsers(app) {
|
||||
app.get("/api/user/list",
|
||||
AuthenticationMWs.authenticate,
|
||||
AuthenticationMWs.authorise(UserRoles.Admin),
|
||||
UserMWs.listUsers,
|
||||
@ -82,8 +82,8 @@ export class UserRouter {
|
||||
);
|
||||
};
|
||||
|
||||
private addChangeRole() {
|
||||
this.app.post("/api/user/:id/role",
|
||||
private static addChangeRole(app) {
|
||||
app.post("/api/user/:id/role",
|
||||
AuthenticationMWs.authenticate,
|
||||
AuthenticationMWs.authorise(UserRoles.Admin),
|
||||
UserRequestConstrainsMWs.notSelfRequestOr2Admins,
|
||||
|
@ -1,18 +1,19 @@
|
||||
import * as _express from "express";
|
||||
import * as _session from "express-session";
|
||||
import * as _bodyParser from "body-parser";
|
||||
import * as _debug from "debug";
|
||||
import * as _http from "http";
|
||||
import * as winston from "winston";
|
||||
import * as expressWinston from "express-winston";
|
||||
import {PublicRouter} from "./routes/PublicRouter";
|
||||
import {UserRouter} from "./routes/UserRouter";
|
||||
import {GalleryRouter} from "./routes/GalleryRouter";
|
||||
import {AdminRouter} from "./routes/AdminRouter";
|
||||
import {ErrorRouter} from "./routes/ErrorRouter";
|
||||
import {SharingRouter} from "./routes/SharingRouter";
|
||||
import {DatabaseType} from "../common/config/Config";
|
||||
import {ObjectManagerRepository} from "./model/ObjectManagerRepository";
|
||||
import {Config} from "./config/Config";
|
||||
import {Logger} from "./Logger";
|
||||
import {Config} from "../common/config/private/Config";
|
||||
import {DatabaseType} from "../common/config/private/IPrivateConfig";
|
||||
|
||||
const LOG_TAG = "[server]";
|
||||
export class Server {
|
||||
@ -22,18 +23,46 @@ export class Server {
|
||||
private server: any;
|
||||
|
||||
constructor() {
|
||||
this.init();
|
||||
}
|
||||
|
||||
async init() {
|
||||
Logger.info(LOG_TAG, "config:");
|
||||
Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t'));
|
||||
|
||||
this.debug = _debug("PiGallery2:server");
|
||||
this.app = _express();
|
||||
|
||||
this.app.set('view engine', 'ejs');
|
||||
this.app.use(expressWinston.logger({
|
||||
transports: [
|
||||
new winston.transports.Console({
|
||||
level: 'silly',
|
||||
json: false,
|
||||
colorize: true,
|
||||
timestamp: function () {
|
||||
return (new Date()).toLocaleString();
|
||||
},
|
||||
formatter: (options) => {
|
||||
// Return string will be passed to logger.
|
||||
return options.timestamp() + '[' + winston['config']['colorize'](options.level, options.level.toUpperCase()) + '] ' +
|
||||
(undefined !== options.message ? options.message : '') +
|
||||
(options.meta && Object.keys(options.meta).length ? '\n\t' + JSON.stringify(options.meta) : '' );
|
||||
},
|
||||
debugStdout: true
|
||||
})
|
||||
],
|
||||
meta: false, // optional: control whether you want to log the meta data about the request (default to true)
|
||||
msg: "HTTP {{req.method}} {{req.url}}", // optional: customize the default logging message. E.g. "{{res.statusCode}} {{req.method}} {{res.responseTime}}ms {{req.url}}"
|
||||
expressFormat: true, // Use the default Express/morgan request formatting. Enabling this will override any msg if true. Will only output colors with colorize set to true
|
||||
colorize: true, // Color the text and status code, using the Express/morgan color palette (text: gray, status: default green, 3XX cyan, 4XX yellow, 5XX red).
|
||||
level: (req) => {
|
||||
if (req.url.indexOf("/api/") !== -1) {
|
||||
return "verbose";
|
||||
}
|
||||
return req.url.indexOf("node_modules") !== -1 ? "silly" : "debug"
|
||||
}
|
||||
}));
|
||||
|
||||
if (process.env.DEBUG) {
|
||||
let _morgan = require('morgan');
|
||||
this.app.use(_morgan('dev'));
|
||||
}
|
||||
this.app.set('view engine', 'ejs');
|
||||
|
||||
|
||||
/**
|
||||
@ -57,19 +86,26 @@ export class Server {
|
||||
this.app.use(_bodyParser.json());
|
||||
|
||||
if (Config.Server.database.type == DatabaseType.mysql) {
|
||||
ObjectManagerRepository.InitMySQLManagers().catch((err) => {
|
||||
Logger.warn(LOG_TAG, "Error during initailizing mysql falling back to memory DB", err);
|
||||
try {
|
||||
await ObjectManagerRepository.InitMySQLManagers();
|
||||
} catch (err) {
|
||||
Logger.warn(LOG_TAG, "[MYSQL error]", err);
|
||||
Logger.warn(LOG_TAG, "Error during initializing mysql falling back to memory DB");
|
||||
Config.setDatabaseType(DatabaseType.memory);
|
||||
ObjectManagerRepository.InitMemoryManagers();
|
||||
});
|
||||
await ObjectManagerRepository.InitMemoryManagers();
|
||||
}
|
||||
} else {
|
||||
ObjectManagerRepository.InitMemoryManagers();
|
||||
await ObjectManagerRepository.InitMemoryManagers();
|
||||
}
|
||||
|
||||
if (Config.Server.thumbnail.hardwareAcceleration == true) {
|
||||
try {
|
||||
const sharp = require.resolve("sharp");
|
||||
const sharp = require("sharp");
|
||||
sharp();
|
||||
|
||||
} catch (err) {
|
||||
Logger.warn(LOG_TAG, "[Thumbnail hardware acceleration] sharp module error: ", err);
|
||||
|
||||
Logger.warn(LOG_TAG, "Thumbnail hardware acceleration is not possible." +
|
||||
" 'Sharp' node module is not found." +
|
||||
" Falling back to JS based thumbnail generation");
|
||||
@ -77,14 +113,14 @@ export class Server {
|
||||
}
|
||||
}
|
||||
|
||||
new PublicRouter(this.app);
|
||||
PublicRouter.route(this.app);
|
||||
|
||||
new UserRouter(this.app);
|
||||
new GalleryRouter(this.app);
|
||||
new SharingRouter(this.app);
|
||||
new AdminRouter(this.app);
|
||||
UserRouter.route(this.app);
|
||||
GalleryRouter.route(this.app);
|
||||
SharingRouter.route(this.app);
|
||||
AdminRouter.route(this.app);
|
||||
|
||||
new ErrorRouter(this.app);
|
||||
ErrorRouter.route(this.app);
|
||||
|
||||
|
||||
// Get PORT from environment and store in Express.
|
||||
@ -138,7 +174,7 @@ export class Server {
|
||||
const bind = typeof addr === 'string'
|
||||
? 'pipe ' + addr
|
||||
: 'port ' + addr.port;
|
||||
Logger.debug(LOG_TAG, 'Listening on ' + bind);
|
||||
Logger.info(LOG_TAG, 'Listening on ' + bind);
|
||||
};
|
||||
|
||||
}
|
||||
|
12
common/config/private/Config.ts
Normal file
12
common/config/private/Config.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import * as path from "path";
|
||||
import {PrivateConfigClass} from "./PrivateConfigClass";
|
||||
import {ConfigLoader} from "typeconfig";
|
||||
|
||||
|
||||
export let Config = new PrivateConfigClass();
|
||||
|
||||
|
||||
ConfigLoader.loadBackendConfig(Config,
|
||||
path.join(__dirname, './../../../config.json'),
|
||||
[["PORT", "Server-port"]]);
|
||||
|
28
common/config/private/IPrivateConfig.ts
Normal file
28
common/config/private/IPrivateConfig.ts
Normal file
@ -0,0 +1,28 @@
|
||||
export enum DatabaseType{
|
||||
memory = 0, mysql = 1
|
||||
}
|
||||
export enum LogLevel {
|
||||
error, warn, info, debug, verbose
|
||||
}
|
||||
|
||||
export interface MySQLConfig {
|
||||
host: string;
|
||||
database: string;
|
||||
username: string;
|
||||
password: string;
|
||||
}
|
||||
export interface DataBaseConfig {
|
||||
type: DatabaseType;
|
||||
mysql?: MySQLConfig;
|
||||
}
|
||||
export interface ThumbnailConfig {
|
||||
folder: string;
|
||||
hardwareAcceleration: boolean;
|
||||
}
|
||||
|
||||
export interface ServerConfig {
|
||||
port: number;
|
||||
imagesFolder: string;
|
||||
thumbnail: ThumbnailConfig;
|
||||
database: DataBaseConfig;
|
||||
}
|
39
common/config/private/PrivateConfigClass.ts
Normal file
39
common/config/private/PrivateConfigClass.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import {PublicConfigClass} from "../public/ConfigClass";
|
||||
import {DatabaseType, ServerConfig} from "./IPrivateConfig";
|
||||
|
||||
|
||||
/**
|
||||
* This configuration will be only at backend
|
||||
*/
|
||||
export class PrivateConfigClass extends PublicConfigClass {
|
||||
|
||||
public Server: ServerConfig = {
|
||||
port: 80,
|
||||
imagesFolder: "demo/images",
|
||||
thumbnail: {
|
||||
folder: "demo/TEMP",
|
||||
hardwareAcceleration: true
|
||||
},
|
||||
database: {
|
||||
type: DatabaseType.mysql,
|
||||
mysql: {
|
||||
host: "localhost",
|
||||
username: "root",
|
||||
password: "root",
|
||||
database: "pigallery2"
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public setDatabaseType(type: DatabaseType) {
|
||||
this.Server.database.type = type;
|
||||
if (type === DatabaseType.memory) {
|
||||
this.Client.Search.searchEnabled = false;
|
||||
this.Client.Search.instantSearchEnabled = false;
|
||||
this.Client.Search.autocompleteEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
15
common/config/public/Config.ts
Normal file
15
common/config/public/Config.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import {PublicConfigClass} from "./ConfigClass";
|
||||
import {WebConfigLoader} from "typeconfig/src/WebConfigLoader";
|
||||
|
||||
|
||||
declare module ServerInject {
|
||||
export const ConfigInject;
|
||||
}
|
||||
|
||||
export let Config = new PublicConfigClass();
|
||||
|
||||
if (typeof ServerInject !== "undefined" && typeof ServerInject.ConfigInject !== "undefined") {
|
||||
WebConfigLoader.loadFrontendConfig(Config.Client, ServerInject.ConfigInject);
|
||||
}
|
||||
|
||||
|
@ -1,29 +1,3 @@
|
||||
export enum DatabaseType{
|
||||
memory = 0, mysql = 1
|
||||
}
|
||||
|
||||
interface MySQLConfig {
|
||||
host: string;
|
||||
database: string;
|
||||
username: string;
|
||||
password: string;
|
||||
}
|
||||
interface DataBaseConfig {
|
||||
type: DatabaseType;
|
||||
mysql?: MySQLConfig;
|
||||
}
|
||||
interface ThumbnailConfig {
|
||||
folder: string;
|
||||
hardwareAcceleration: boolean;
|
||||
}
|
||||
|
||||
interface ServerConfig {
|
||||
port: number;
|
||||
imagesFolder: string;
|
||||
thumbnail: ThumbnailConfig;
|
||||
database: DataBaseConfig;
|
||||
}
|
||||
|
||||
interface SearchConfig {
|
||||
searchEnabled: boolean
|
||||
instantSearchEnabled: boolean
|
||||
@ -41,9 +15,11 @@ interface ClientConfig {
|
||||
authenticationRequired: boolean;
|
||||
googleApiKey: string;
|
||||
}
|
||||
export class ConfigClass {
|
||||
|
||||
public Server: ServerConfig = null;
|
||||
/**
|
||||
* These configuration will be available at frontend and backend too
|
||||
*/
|
||||
export class PublicConfigClass {
|
||||
|
||||
public Client: ClientConfig = {
|
||||
thumbnailSizes: [200, 400, 600],
|
||||
@ -61,14 +37,5 @@ export class ConfigClass {
|
||||
googleApiKey: ""
|
||||
};
|
||||
|
||||
public setDatabaseType(type: DatabaseType) {
|
||||
this.Server.database.type = type;
|
||||
if (type === DatabaseType.memory) {
|
||||
this.Client.Search.searchEnabled = false;
|
||||
this.Client.Search.instantSearchEnabled = false;
|
||||
this.Client.Search.autocompleteEnabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@ import {Component, OnInit} from "@angular/core";
|
||||
import {AuthenticationService} from "../model/network/authentication.service";
|
||||
import {Router} from "@angular/router";
|
||||
import {UserRoles} from "../../../common/entities/UserDTO";
|
||||
import {Config} from "../config/Config";
|
||||
import {Config} from "../../../common/config/public/Config";
|
||||
@Component({
|
||||
selector: 'admin',
|
||||
templateUrl: 'app/admin/admin.component.html',
|
||||
|
@ -26,11 +26,11 @@ import {LoginComponent} from "./login/login.component";
|
||||
import {AdminComponent} from "./admin/admin.component";
|
||||
import {GalleryComponent} from "./gallery/gallery.component";
|
||||
import {StringifyRole} from "./pipes/StringifyRolePipe";
|
||||
import {Config} from "./config/Config";
|
||||
import {GalleryMapComponent} from "./gallery/map/map.gallery.component";
|
||||
import {GalleryMapLightboxComponent} from "./gallery/map/lightbox/lightbox.map.gallery.component";
|
||||
import {ThumbnailManagerService} from "./gallery/thumnailManager.service";
|
||||
import {OverlayService} from "./gallery/overlay.service";
|
||||
import {Config} from "../../common/config/public/Config";
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
|
@ -1,12 +0,0 @@
|
||||
import {ConfigClass} from "../../../common/config/Config";
|
||||
import {Utils} from "../../../common/Utils";
|
||||
|
||||
declare module ServerInject {
|
||||
export let ConfigInject: ConfigClass;
|
||||
}
|
||||
|
||||
export let Config = new ConfigClass();
|
||||
|
||||
if (typeof ServerInject !== "undefined" && typeof ServerInject.ConfigInject !== "undefined") {
|
||||
Utils.updateKeys(Config.Client, ServerInject.ConfigInject);
|
||||
}
|
@ -2,7 +2,7 @@ import {Component, ViewEncapsulation} from "@angular/core";
|
||||
import {RouterLink} from "@angular/router";
|
||||
import {AuthenticationService} from "../model/network/authentication.service";
|
||||
import {UserDTO} from "../../../common/entities/UserDTO";
|
||||
import {Config} from "../config/Config";
|
||||
import {Config} from "../../../common/config/public/Config";
|
||||
|
||||
@Component({
|
||||
selector: 'app-frame',
|
||||
|
@ -1,7 +1,7 @@
|
||||
import {PhotoDTO} from "../../../common/entities/PhotoDTO";
|
||||
import {Utils} from "../../../common/Utils";
|
||||
import {Config} from "../config/Config";
|
||||
import {IconPhoto} from "./IconPhoto";
|
||||
import {Config} from "../../../common/config/public/Config";
|
||||
export class Photo extends IconPhoto {
|
||||
|
||||
|
||||
|
@ -2,7 +2,7 @@ import {Injectable} from "@angular/core";
|
||||
import {PhotoDTO} from "../../../common/entities/PhotoDTO";
|
||||
import {DirectoryDTO} from "../../../common/entities/DirectoryDTO";
|
||||
import {Utils} from "../../../common/Utils";
|
||||
import {Config} from "../config/Config";
|
||||
import {Config} from "../../../common/config/public/Config";
|
||||
|
||||
@Injectable()
|
||||
export class GalleryCacheService {
|
||||
|
@ -1,11 +1,11 @@
|
||||
import {Component, OnInit, ViewChild} from "@angular/core";
|
||||
import {AuthenticationService} from "../model/network/authentication.service";
|
||||
import {Router, ActivatedRoute, Params} from "@angular/router";
|
||||
import {ActivatedRoute, Params, Router} from "@angular/router";
|
||||
import {GalleryService} from "./gallery.service";
|
||||
import {GalleryGridComponent} from "./grid/grid.gallery.component";
|
||||
import {GallerySearchComponent} from "./search/search.gallery.component";
|
||||
import {Config} from "../config/Config";
|
||||
import {SearchTypes} from "../../../common/entities/AutoCompleteItem";
|
||||
import {Config} from "../../../common/config/public/Config";
|
||||
|
||||
@Component({
|
||||
selector: 'gallery',
|
||||
|
@ -15,8 +15,8 @@ import {GridRowBuilder} from "./GridRowBuilder";
|
||||
import {GalleryLightboxComponent} from "../lightbox/lightbox.gallery.component";
|
||||
import {GridPhoto} from "./GridPhoto";
|
||||
import {GalleryPhotoComponent} from "./photo/photo.grid.gallery.component";
|
||||
import {Config} from "../../config/Config";
|
||||
import {OverlayService} from "../overlay.service";
|
||||
import {Config} from "../../../../common/config/public/Config";
|
||||
|
||||
@Component({
|
||||
selector: 'gallery-grid',
|
||||
|
@ -1,10 +1,10 @@
|
||||
import {Component, Input, ElementRef, ViewChild, OnInit, OnDestroy} from "@angular/core";
|
||||
import {IRenderable, Dimension} from "../../../model/IRenderable";
|
||||
import {Component, ElementRef, Input, OnDestroy, OnInit, ViewChild} from "@angular/core";
|
||||
import {Dimension, IRenderable} from "../../../model/IRenderable";
|
||||
import {GridPhoto} from "../GridPhoto";
|
||||
import {SearchTypes} from "../../../../../common/entities/AutoCompleteItem";
|
||||
import {RouterLink} from "@angular/router";
|
||||
import {Config} from "../../../config/Config";
|
||||
import {Thumbnail, ThumbnailManagerService} from "../../thumnailManager.service";
|
||||
import {Config} from "../../../../../common/config/public/Config";
|
||||
|
||||
@Component({
|
||||
selector: 'gallery-grid-photo',
|
||||
|
@ -1,10 +1,10 @@
|
||||
import {Component} from "@angular/core";
|
||||
import {AutoCompleteService} from "./autocomplete.service";
|
||||
import {AutoCompleteItem, SearchTypes} from "../../../../common/entities/AutoCompleteItem";
|
||||
import {RouterLink, ActivatedRoute, Params} from "@angular/router";
|
||||
import {ActivatedRoute, Params, RouterLink} from "@angular/router";
|
||||
import {Message} from "../../../../common/entities/Message";
|
||||
import {GalleryService} from "../gallery.service";
|
||||
import {Config} from "../../config/Config";
|
||||
import {Config} from "../../../../common/config/public/Config";
|
||||
|
||||
@Component({
|
||||
selector: 'gallery-search',
|
||||
|
@ -1,9 +1,9 @@
|
||||
import {Injectable} from "@angular/core";
|
||||
import {Config} from "../config/Config";
|
||||
import {GalleryCacheService} from "./cache.gallery.service";
|
||||
import {Photo} from "./Photo";
|
||||
import {IconPhoto} from "./IconPhoto";
|
||||
import {PhotoDTO} from "../../../common/entities/PhotoDTO";
|
||||
import {Config} from "../../../common/config/public/Config";
|
||||
|
||||
export enum ThumbnailLoadingPriority{
|
||||
high, medium, low
|
||||
|
@ -6,7 +6,7 @@ import {LoginCredential} from "../../../../common/entities/LoginCredential";
|
||||
import {Message} from "../../../../common/entities/Message";
|
||||
import {Cookie} from "ng2-cookies";
|
||||
import {ErrorCodes} from "../../../../common/entities/Error";
|
||||
import {Config} from "../../config/Config";
|
||||
import {Config} from "../../../../common/config/public/Config";
|
||||
|
||||
declare module ServerInject {
|
||||
export let user: UserDTO;
|
||||
|
@ -27,7 +27,8 @@
|
||||
'rxjs': 'npm:rxjs',
|
||||
|
||||
'@agm/core': 'npm:@agm/core/core.umd.js',
|
||||
'ng2-cookies': 'npm:ng2-cookies/ng2-cookies'
|
||||
'ng2-cookies': 'npm:ng2-cookies/ng2-cookies',
|
||||
'typeconfig': 'npm:typeconfig'
|
||||
},
|
||||
// packages tells the System loader how to load when no filename and/or no extension
|
||||
packages: {
|
||||
|
@ -4,7 +4,7 @@ import {Error, ErrorCodes} from "../../../../../common/entities/Error";
|
||||
import {UserRoles} from "../../../../../common/entities/UserDTO";
|
||||
import {ObjectManagerRepository} from "../../../../../backend/model/ObjectManagerRepository";
|
||||
import {UserManager} from "../../../../../backend/model/memory/UserManager";
|
||||
import {Config} from "../../../../../backend/config/Config";
|
||||
import {Config} from "../../../../../common/config/private/Config";
|
||||
|
||||
|
||||
describe('Authentication middleware', () => {
|
||||
|
Loading…
x
Reference in New Issue
Block a user