mirror of
https://github.com/xuthus83/pigallery2.git
synced 2025-01-14 14:43:17 +08:00
fixing folder navigation error
This commit is contained in:
parent
06dd15a0ab
commit
6ce8e081ab
@ -4,23 +4,13 @@ import {ObjectManagers} from '../model/ObjectManagers';
|
|||||||
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';
|
import {QueryParams} from '../../common/QueryParams';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
const LOG_TAG = '[SharingMWs]';
|
const LOG_TAG = '[SharingMWs]';
|
||||||
|
|
||||||
export class SharingMWs {
|
export class SharingMWs {
|
||||||
|
|
||||||
|
|
||||||
private static generateKey(): string {
|
|
||||||
function s4() {
|
|
||||||
return Math.floor((1 + Math.random()) * 0x10000)
|
|
||||||
.toString(16)
|
|
||||||
.substring(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return s4() + s4();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static async getSharing(req: Request, res: Response, next: NextFunction) {
|
public static async getSharing(req: Request, res: Response, next: NextFunction) {
|
||||||
if (Config.Client.Sharing.enabled === false) {
|
if (Config.Client.Sharing.enabled === false) {
|
||||||
return next();
|
return next();
|
||||||
@ -59,7 +49,7 @@ export class SharingMWs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const directoryName = req.params.directory || '/';
|
const directoryName = path.normalize(req.params.directory || '/');
|
||||||
const sharing: SharingDTO = {
|
const sharing: SharingDTO = {
|
||||||
id: null,
|
id: null,
|
||||||
sharingKey: sharingKey,
|
sharingKey: sharingKey,
|
||||||
@ -90,7 +80,7 @@ export class SharingMWs {
|
|||||||
return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'updateSharing filed is missing'));
|
return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'updateSharing filed is missing'));
|
||||||
}
|
}
|
||||||
const updateSharing: CreateSharingDTO = req.body.updateSharing;
|
const updateSharing: CreateSharingDTO = req.body.updateSharing;
|
||||||
const directoryName = req.params.directory || '/';
|
const directoryName = path.normalize(req.params.directory || '/');
|
||||||
const sharing: SharingDTO = {
|
const sharing: SharingDTO = {
|
||||||
id: updateSharing.id,
|
id: updateSharing.id,
|
||||||
path: directoryName,
|
path: directoryName,
|
||||||
@ -110,4 +100,14 @@ export class SharingMWs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static generateKey(): string {
|
||||||
|
function s4() {
|
||||||
|
return Math.floor((1 + Math.random()) * 0x10000)
|
||||||
|
.toString(16)
|
||||||
|
.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return s4() + s4();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ export class ThumbnailGeneratorMWs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// load parameters
|
// load parameters
|
||||||
const mediaPath = path.resolve(ProjectPath.ImageFolder, photo.directory.path, photo.directory.name, photo.name);
|
const mediaPath = path.join(ProjectPath.ImageFolder, photo.directory.path, photo.directory.name, photo.name);
|
||||||
const size: number = Config.Client.Thumbnail.personThumbnailSize;
|
const size: number = Config.Client.Thumbnail.personThumbnailSize;
|
||||||
const personName = photo.metadata.faces[0].name;
|
const personName = photo.metadata.faces[0].name;
|
||||||
// generate thumbnail path
|
// generate thumbnail path
|
||||||
|
@ -7,6 +7,7 @@ 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';
|
import {QueryParams} from '../../../common/QueryParams';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
export class AuthenticationMWs {
|
export class AuthenticationMWs {
|
||||||
|
|
||||||
@ -54,21 +55,30 @@ export class AuthenticationMWs {
|
|||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static authoriseDirectory(req: Request, res: Response, next: NextFunction) {
|
|
||||||
if (req.session.user.permissions == null ||
|
|
||||||
req.session.user.permissions.length === 0 ||
|
|
||||||
req.session.user.permissions[0] === '/*') {
|
|
||||||
return next();
|
|
||||||
}
|
|
||||||
|
|
||||||
const directoryName = req.params.directory || '/';
|
public static normalizePathParam(paramName: string) {
|
||||||
if (UserDTO.isPathAvailable(directoryName, req.session.user.permissions) === true) {
|
return (req: Request, res: Response, next: NextFunction) => {
|
||||||
|
req.params[paramName] = path.normalize(req.params[paramName] || path.sep).replace(/^(\.\.[\/\\])+/, '');
|
||||||
return next();
|
return next();
|
||||||
}
|
};
|
||||||
|
|
||||||
return next(new ErrorDTO(ErrorCodes.PERMISSION_DENIED));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static authorisePath(paramName: string, isDirectory: boolean) {
|
||||||
|
return (req: Request, res: Response, next: NextFunction) => {
|
||||||
|
let p: string = req.params[paramName];
|
||||||
|
if (!isDirectory) {
|
||||||
|
p = path.dirname(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!UserDTO.isDirectoryPathAvailable(p, req.session.user.permissions, path.sep)) {
|
||||||
|
return res.sendStatus(403);
|
||||||
|
}
|
||||||
|
|
||||||
|
return next();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static authorise(role: UserRoles) {
|
public static authorise(role: UserRoles) {
|
||||||
return (req: Request, res: Response, next: NextFunction) => {
|
return (req: Request, res: Response, next: NextFunction) => {
|
||||||
if (req.session.user.role < role) {
|
if (req.session.user.role < role) {
|
||||||
@ -102,12 +112,12 @@ export class AuthenticationMWs {
|
|||||||
return next(new ErrorDTO(ErrorCodes.CREDENTIAL_NOT_FOUND));
|
return next(new ErrorDTO(ErrorCodes.CREDENTIAL_NOT_FOUND));
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = sharing.path;
|
let sharingPath = sharing.path;
|
||||||
if (sharing.includeSubfolders === true) {
|
if (sharing.includeSubfolders === true) {
|
||||||
path += '*';
|
sharingPath += '*';
|
||||||
}
|
}
|
||||||
|
|
||||||
req.session.user = <UserDTO>{name: 'Guest', role: UserRoles.LimitedGuest, permissions: [path]};
|
req.session.user = <UserDTO>{name: 'Guest', role: UserRoles.LimitedGuest, permissions: [sharingPath]};
|
||||||
return next();
|
return next();
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -152,6 +162,12 @@ export class AuthenticationMWs {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static logout(req: Request, res: Response, next: NextFunction) {
|
||||||
|
delete req.session.user;
|
||||||
|
delete req.session.rememberMe;
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
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.params[QueryParams.gallery.sharingKey_short] || !!req.params[QueryParams.gallery.sharingKey_long])) {
|
(!!req.params[QueryParams.gallery.sharingKey_short] || !!req.params[QueryParams.gallery.sharingKey_long])) {
|
||||||
@ -166,20 +182,19 @@ export class AuthenticationMWs {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = sharing.path;
|
let sharingPath = sharing.path;
|
||||||
if (sharing.includeSubfolders === true) {
|
if (sharing.includeSubfolders === true) {
|
||||||
path += '*';
|
sharingPath += '*';
|
||||||
}
|
}
|
||||||
return <UserDTO>{name: 'Guest', role: UserRoles.LimitedGuest, permissions: [path]};
|
return <UserDTO>{
|
||||||
|
name: 'Guest',
|
||||||
|
role: UserRoles.LimitedGuest,
|
||||||
|
permissions: [sharingPath],
|
||||||
|
usedSharingKey: sharing.sharingKey
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static logout(req: Request, res: Response, next: NextFunction) {
|
|
||||||
delete req.session.user;
|
|
||||||
delete req.session.rememberMe;
|
|
||||||
return next();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ export class Localizations {
|
|||||||
public static init() {
|
public static init() {
|
||||||
const notLanguage = ['assets'];
|
const notLanguage = ['assets'];
|
||||||
const dirCont = fs.readdirSync(ProjectPath.FrontendFolder)
|
const dirCont = fs.readdirSync(ProjectPath.FrontendFolder)
|
||||||
.filter(f => fs.statSync(path.resolve(ProjectPath.FrontendFolder, f)).isDirectory());
|
.filter(f => fs.statSync(path.join(ProjectPath.FrontendFolder, f)).isDirectory());
|
||||||
Config.Client.languages = dirCont.filter(d => notLanguage.indexOf(d) === -1);
|
Config.Client.languages = dirCont.filter(d => notLanguage.indexOf(d) === -1);
|
||||||
Config.Client.languages.push('en');
|
Config.Client.languages.push('en');
|
||||||
}
|
}
|
||||||
|
@ -257,7 +257,6 @@ export class SearchManager implements ISearchManager {
|
|||||||
const rawAndEntities = await query.orderBy('media.id').getRawAndEntities();
|
const rawAndEntities = await query.orderBy('media.id').getRawAndEntities();
|
||||||
const media: MediaEntity[] = rawAndEntities.entities;
|
const media: MediaEntity[] = rawAndEntities.entities;
|
||||||
|
|
||||||
// console.log(rawAndEntities.raw);
|
|
||||||
let rawIndex = 0;
|
let rawIndex = 0;
|
||||||
for (let i = 0; i < media.length; i++) {
|
for (let i = 0; i < media.length; i++) {
|
||||||
if (rawAndEntities.raw[rawIndex].faces_id === null ||
|
if (rawAndEntities.raw[rawIndex].faces_id === null ||
|
||||||
|
@ -69,7 +69,7 @@ export class DiskMangerWorker {
|
|||||||
try {
|
try {
|
||||||
for (let i = 0; i < list.length; i++) {
|
for (let i = 0; i < list.length; i++) {
|
||||||
const file = list[i];
|
const file = list[i];
|
||||||
const fullFilePath = path.normalize(path.resolve(absoluteDirectoryName, file));
|
const fullFilePath = path.normalize(path.join(absoluteDirectoryName, file));
|
||||||
if (fs.statSync(fullFilePath).isDirectory()) {
|
if (fs.statSync(fullFilePath).isDirectory()) {
|
||||||
if (photosOnly === true) {
|
if (photosOnly === true) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import {AuthenticationMWs} from '../middlewares/user/AuthenticationMWs';
|
import {AuthenticationMWs} from '../middlewares/user/AuthenticationMWs';
|
||||||
import {Express, NextFunction, Request, Response} from 'express';
|
import {Express} from 'express';
|
||||||
import {GalleryMWs} from '../middlewares/GalleryMWs';
|
import {GalleryMWs} from '../middlewares/GalleryMWs';
|
||||||
import {RenderingMWs} from '../middlewares/RenderingMWs';
|
import {RenderingMWs} from '../middlewares/RenderingMWs';
|
||||||
import {ThumbnailGeneratorMWs} from '../middlewares/thumbnail/ThumbnailGeneratorMWs';
|
import {ThumbnailGeneratorMWs} from '../middlewares/thumbnail/ThumbnailGeneratorMWs';
|
||||||
@ -28,7 +28,8 @@ export class GalleryRouter {
|
|||||||
private static addDirectoryList(app: Express) {
|
private static addDirectoryList(app: Express) {
|
||||||
app.get(['/api/gallery/content/:directory(*)', '/api/gallery/', '/api/gallery//'],
|
app.get(['/api/gallery/content/:directory(*)', '/api/gallery/', '/api/gallery//'],
|
||||||
AuthenticationMWs.authenticate,
|
AuthenticationMWs.authenticate,
|
||||||
AuthenticationMWs.authoriseDirectory,
|
AuthenticationMWs.normalizePathParam('directory'),
|
||||||
|
AuthenticationMWs.authorisePath('directory', true),
|
||||||
VersionMWs.injectGalleryVersion,
|
VersionMWs.injectGalleryVersion,
|
||||||
GalleryMWs.listDirectory,
|
GalleryMWs.listDirectory,
|
||||||
ThumbnailGeneratorMWs.addThumbnailInformation,
|
ThumbnailGeneratorMWs.addThumbnailInformation,
|
||||||
@ -41,7 +42,8 @@ export class GalleryRouter {
|
|||||||
private static addGetImage(app: Express) {
|
private static addGetImage(app: Express) {
|
||||||
app.get(['/api/gallery/content/:mediaPath(*\.(jpg|jpeg|jpe|webp|png|gif|svg))'],
|
app.get(['/api/gallery/content/:mediaPath(*\.(jpg|jpeg|jpe|webp|png|gif|svg))'],
|
||||||
AuthenticationMWs.authenticate,
|
AuthenticationMWs.authenticate,
|
||||||
// TODO: authorize path
|
AuthenticationMWs.normalizePathParam('mediaPath'),
|
||||||
|
AuthenticationMWs.authorisePath('mediaPath', false),
|
||||||
GalleryMWs.loadFile,
|
GalleryMWs.loadFile,
|
||||||
RenderingMWs.renderFile
|
RenderingMWs.renderFile
|
||||||
);
|
);
|
||||||
@ -50,7 +52,8 @@ export class GalleryRouter {
|
|||||||
private static addGetVideo(app: Express) {
|
private static addGetVideo(app: Express) {
|
||||||
app.get(['/api/gallery/content/:mediaPath(*\.(mp4|ogg|ogv|webm))'],
|
app.get(['/api/gallery/content/:mediaPath(*\.(mp4|ogg|ogv|webm))'],
|
||||||
AuthenticationMWs.authenticate,
|
AuthenticationMWs.authenticate,
|
||||||
// TODO: authorize path
|
AuthenticationMWs.normalizePathParam('mediaPath'),
|
||||||
|
AuthenticationMWs.authorisePath('mediaPath', false),
|
||||||
GalleryMWs.loadFile,
|
GalleryMWs.loadFile,
|
||||||
RenderingMWs.renderFile
|
RenderingMWs.renderFile
|
||||||
);
|
);
|
||||||
@ -59,7 +62,8 @@ export class GalleryRouter {
|
|||||||
private static addGetMetaFile(app: Express) {
|
private static addGetMetaFile(app: Express) {
|
||||||
app.get(['/api/gallery/content/:mediaPath(*\.(gpx))'],
|
app.get(['/api/gallery/content/:mediaPath(*\.(gpx))'],
|
||||||
AuthenticationMWs.authenticate,
|
AuthenticationMWs.authenticate,
|
||||||
// TODO: authorize path
|
AuthenticationMWs.normalizePathParam('mediaPath'),
|
||||||
|
AuthenticationMWs.authorisePath('mediaPath', false),
|
||||||
GalleryMWs.loadFile,
|
GalleryMWs.loadFile,
|
||||||
RenderingMWs.renderFile
|
RenderingMWs.renderFile
|
||||||
);
|
);
|
||||||
@ -68,8 +72,8 @@ export class GalleryRouter {
|
|||||||
private static addRandom(app: Express) {
|
private static addRandom(app: Express) {
|
||||||
app.get(['/api/gallery/random'],
|
app.get(['/api/gallery/random'],
|
||||||
AuthenticationMWs.authenticate,
|
AuthenticationMWs.authenticate,
|
||||||
|
AuthenticationMWs.authorise(UserRoles.Guest),
|
||||||
VersionMWs.injectGalleryVersion,
|
VersionMWs.injectGalleryVersion,
|
||||||
// TODO: authorize path
|
|
||||||
GalleryMWs.getRandomImage,
|
GalleryMWs.getRandomImage,
|
||||||
GalleryMWs.loadFile,
|
GalleryMWs.loadFile,
|
||||||
RenderingMWs.renderFile
|
RenderingMWs.renderFile
|
||||||
@ -79,7 +83,8 @@ export class GalleryRouter {
|
|||||||
private static addGetImageThumbnail(app: Express) {
|
private static addGetImageThumbnail(app: Express) {
|
||||||
app.get('/api/gallery/content/:mediaPath(*\.(jpg|jpeg|jpe|webp|png|gif|svg))/thumbnail/:size?',
|
app.get('/api/gallery/content/:mediaPath(*\.(jpg|jpeg|jpe|webp|png|gif|svg))/thumbnail/:size?',
|
||||||
AuthenticationMWs.authenticate,
|
AuthenticationMWs.authenticate,
|
||||||
// TODO: authorize path
|
AuthenticationMWs.normalizePathParam('mediaPath'),
|
||||||
|
AuthenticationMWs.authorisePath('mediaPath', false),
|
||||||
GalleryMWs.loadFile,
|
GalleryMWs.loadFile,
|
||||||
ThumbnailGeneratorMWs.generateThumbnailFactory(ThumbnailSourceType.Image),
|
ThumbnailGeneratorMWs.generateThumbnailFactory(ThumbnailSourceType.Image),
|
||||||
RenderingMWs.renderFile
|
RenderingMWs.renderFile
|
||||||
@ -89,7 +94,8 @@ export class GalleryRouter {
|
|||||||
private static addGetVideoThumbnail(app: Express) {
|
private static addGetVideoThumbnail(app: Express) {
|
||||||
app.get('/api/gallery/content/:mediaPath(*\.(mp4|ogg|ogv|webm))/thumbnail/:size?',
|
app.get('/api/gallery/content/:mediaPath(*\.(mp4|ogg|ogv|webm))/thumbnail/:size?',
|
||||||
AuthenticationMWs.authenticate,
|
AuthenticationMWs.authenticate,
|
||||||
// TODO: authorize path
|
AuthenticationMWs.normalizePathParam('mediaPath'),
|
||||||
|
AuthenticationMWs.authorisePath('mediaPath', false),
|
||||||
GalleryMWs.loadFile,
|
GalleryMWs.loadFile,
|
||||||
ThumbnailGeneratorMWs.generateThumbnailFactory(ThumbnailSourceType.Video),
|
ThumbnailGeneratorMWs.generateThumbnailFactory(ThumbnailSourceType.Video),
|
||||||
RenderingMWs.renderFile
|
RenderingMWs.renderFile
|
||||||
@ -100,7 +106,8 @@ export class GalleryRouter {
|
|||||||
private static addGetVideoIcon(app: Express) {
|
private static addGetVideoIcon(app: Express) {
|
||||||
app.get('/api/gallery/content/:mediaPath(*\.(mp4|ogg|ogv|webm))/icon',
|
app.get('/api/gallery/content/:mediaPath(*\.(mp4|ogg|ogv|webm))/icon',
|
||||||
AuthenticationMWs.authenticate,
|
AuthenticationMWs.authenticate,
|
||||||
// TODO: authorize path
|
AuthenticationMWs.normalizePathParam('mediaPath'),
|
||||||
|
AuthenticationMWs.authorisePath('mediaPath', false),
|
||||||
GalleryMWs.loadFile,
|
GalleryMWs.loadFile,
|
||||||
ThumbnailGeneratorMWs.generateIconFactory(ThumbnailSourceType.Video),
|
ThumbnailGeneratorMWs.generateIconFactory(ThumbnailSourceType.Video),
|
||||||
RenderingMWs.renderFile
|
RenderingMWs.renderFile
|
||||||
@ -110,7 +117,8 @@ export class GalleryRouter {
|
|||||||
private static addGetImageIcon(app: Express) {
|
private static addGetImageIcon(app: Express) {
|
||||||
app.get('/api/gallery/content/:mediaPath(*\.(jpg|jpeg|jpe|webp|png|gif|svg))/icon',
|
app.get('/api/gallery/content/:mediaPath(*\.(jpg|jpeg|jpe|webp|png|gif|svg))/icon',
|
||||||
AuthenticationMWs.authenticate,
|
AuthenticationMWs.authenticate,
|
||||||
// TODO: authorize path
|
AuthenticationMWs.normalizePathParam('mediaPath'),
|
||||||
|
AuthenticationMWs.authorisePath('mediaPath', false),
|
||||||
GalleryMWs.loadFile,
|
GalleryMWs.loadFile,
|
||||||
ThumbnailGeneratorMWs.generateIconFactory(ThumbnailSourceType.Image),
|
ThumbnailGeneratorMWs.generateIconFactory(ThumbnailSourceType.Image),
|
||||||
RenderingMWs.renderFile
|
RenderingMWs.renderFile
|
||||||
|
@ -44,7 +44,7 @@ export class PublicRouter {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const renderIndex = (req: Request, res: Response, next: Function) => {
|
const renderIndex = (req: Request, res: Response, next: Function) => {
|
||||||
ejs.renderFile(path.resolve(ProjectPath.FrontendFolder, req['localePath'], 'index.html'),
|
ejs.renderFile(path.join(ProjectPath.FrontendFolder, req['localePath'], 'index.html'),
|
||||||
res.tpl, (err, str) => {
|
res.tpl, (err, str) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, err.message));
|
return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, err.message));
|
||||||
@ -79,7 +79,7 @@ export class PublicRouter {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
app.get(['/', '/login', '/gallery*', '/share*', '/admin', '/duplicates', '/faces', '/search*'],
|
app.get(['/', '/login', '/gallery*', '/share*', '/admin', '/duplicates', '/faces', '/search*'],
|
||||||
AuthenticationMWs.tryAuthenticate,
|
AuthenticationMWs.tryAuthenticate,
|
||||||
setLocale,
|
setLocale,
|
||||||
renderIndex
|
renderIndex
|
||||||
@ -90,28 +90,26 @@ export class PublicRouter {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const renderFile = (subDir: string = '') => {
|
||||||
|
return (req: Request, res: Response) => {
|
||||||
|
const file = path.join(ProjectPath.FrontendFolder, req['localePath'], subDir, req.params.file);
|
||||||
|
fs.exists(file, (exists: boolean) => {
|
||||||
|
if (!exists) {
|
||||||
|
return res.sendStatus(404);
|
||||||
|
}
|
||||||
|
res.sendFile(file);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
app.get('/assets/:file(*)',
|
app.get('/assets/:file(*)',
|
||||||
setLocale,
|
setLocale,
|
||||||
(req: Request, res: Response) => {
|
AuthenticationMWs.normalizePathParam('file'),
|
||||||
const file = path.resolve(ProjectPath.FrontendFolder, req['localePath'], 'assets', req.params.file);
|
renderFile('assets'));
|
||||||
fs.exists(file, (exists: boolean) => {
|
|
||||||
if (!exists) {
|
|
||||||
return res.sendStatus(404);
|
|
||||||
}
|
|
||||||
res.sendFile(file);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
app.get('/:file',
|
app.get('/:file',
|
||||||
setLocale,
|
setLocale,
|
||||||
(req: Request, res: Response) => {
|
AuthenticationMWs.normalizePathParam('file'),
|
||||||
const file = path.resolve(ProjectPath.FrontendFolder, req['localePath'], req.params.file);
|
renderFile());
|
||||||
fs.exists(file, (exists: boolean) => {
|
|
||||||
if (!exists) {
|
|
||||||
return res.sendStatus(404);
|
|
||||||
}
|
|
||||||
res.sendFile(file);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -15,25 +15,26 @@ export interface UserDTO {
|
|||||||
name: string;
|
name: string;
|
||||||
password: string;
|
password: string;
|
||||||
role: UserRoles;
|
role: UserRoles;
|
||||||
|
usedSharingKey?: string;
|
||||||
permissions: string[]; // user can only see these permissions. if ends with *, its recursive
|
permissions: string[]; // user can only see these permissions. if ends with *, its recursive
|
||||||
}
|
}
|
||||||
|
|
||||||
export module UserDTO {
|
export module UserDTO {
|
||||||
|
|
||||||
export const isPathAvailable = (path: string, permissions: string[]): boolean => {
|
export const isDirectoryPathAvailable = (path: string, permissions: string[], separator = '/'): boolean => {
|
||||||
if (permissions == null || permissions.length === 0 || permissions[0] === '/*') {
|
if (permissions == null || permissions.length === 0 || permissions[0] === separator + '*') {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
for (let i = 0; i < permissions.length; i++) {
|
for (let i = 0; i < permissions.length; i++) {
|
||||||
let permission = permissions[i];
|
let permission = permissions[i];
|
||||||
if (permission[permission.length - 1] === '*') {
|
if (permission[permission.length - 1] === '*') {
|
||||||
permission = permission.slice(0, -1);
|
permission = permission.slice(0, -1);
|
||||||
if (path.startsWith(permission)) {
|
if (path.startsWith(permission) && (!path[permission.length] || path[permission.length] === separator)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (path === permission) {
|
} else if (path === permission) {
|
||||||
return true;
|
return true;
|
||||||
} else if (path === '.' && permission === '/') {
|
} else if (path === '.' && permission === separator) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,7 +43,6 @@ export module UserDTO {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const isDirectoryAvailable = (directory: DirectoryDTO, permissions: string[]): boolean => {
|
export const isDirectoryAvailable = (directory: DirectoryDTO, permissions: string[]): boolean => {
|
||||||
|
return isDirectoryPathAvailable(Utils.concatUrls(directory.path, directory.name), permissions);
|
||||||
return isPathAvailable(Utils.concatUrls(directory.path, directory.name), permissions);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,6 @@ export class GalleryComponent implements OnInit, OnDestroy {
|
|||||||
private rndService: SeededRandomService) {
|
private rndService: SeededRandomService) {
|
||||||
this.mapEnabled = Config.Client.Map.enabled;
|
this.mapEnabled = Config.Client.Map.enabled;
|
||||||
this.SearchTypes = SearchTypes;
|
this.SearchTypes = SearchTypes;
|
||||||
|
|
||||||
PageHelper.showScrollY();
|
PageHelper.showScrollY();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,9 @@ export class GalleryService {
|
|||||||
|
|
||||||
public content: BehaviorSubject<ContentWrapper>;
|
public content: BehaviorSubject<ContentWrapper>;
|
||||||
public sorting: BehaviorSubject<SortingMethods>;
|
public sorting: BehaviorSubject<SortingMethods>;
|
||||||
|
lastRequest: { directory: string } = {
|
||||||
|
directory: null
|
||||||
|
};
|
||||||
private lastDirectory: DirectoryDTO;
|
private lastDirectory: DirectoryDTO;
|
||||||
private searchId: any;
|
private searchId: any;
|
||||||
private ongoingSearch: {
|
private ongoingSearch: {
|
||||||
@ -38,10 +41,6 @@ export class GalleryService {
|
|||||||
this.sorting = new BehaviorSubject<SortingMethods>(Config.Client.Other.defaultPhotoSortingMethod);
|
this.sorting = new BehaviorSubject<SortingMethods>(Config.Client.Other.defaultPhotoSortingMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
lastRequest: { directory: string } = {
|
|
||||||
directory: null
|
|
||||||
};
|
|
||||||
|
|
||||||
setSorting(sorting: SortingMethods): void {
|
setSorting(sorting: SortingMethods): void {
|
||||||
this.sorting.next(sorting);
|
this.sorting.next(sorting);
|
||||||
if (this.content.value.directory) {
|
if (this.content.value.directory) {
|
||||||
|
@ -70,7 +70,7 @@ export class GalleryNavigatorComponent implements OnChanges {
|
|||||||
if (dirs.length === 0) {
|
if (dirs.length === 0) {
|
||||||
arr.push({name: this.RootFolderName, route: null});
|
arr.push({name: this.RootFolderName, route: null});
|
||||||
} else {
|
} else {
|
||||||
arr.push({name: this.RootFolderName, route: UserDTO.isPathAvailable('/', user.permissions) ? '/' : null});
|
arr.push({name: this.RootFolderName, route: UserDTO.isDirectoryPathAvailable('/', user.permissions) ? '/' : null});
|
||||||
}
|
}
|
||||||
|
|
||||||
// create rest navigation
|
// create rest navigation
|
||||||
@ -79,7 +79,7 @@ export class GalleryNavigatorComponent implements OnChanges {
|
|||||||
if (dirs.length - 1 === index) {
|
if (dirs.length - 1 === index) {
|
||||||
arr.push({name: name, route: null});
|
arr.push({name: name, route: null});
|
||||||
} else {
|
} else {
|
||||||
arr.push({name: name, route: UserDTO.isPathAvailable(route, user.permissions) ? route : null});
|
arr.push({name: name, route: UserDTO.isDirectoryPathAvailable(route, user.permissions) ? route : null});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2,8 +2,9 @@ import {Injectable} from '@angular/core';
|
|||||||
import {NetworkService} from '../model/network/network.service';
|
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, Observable} from 'rxjs';
|
||||||
import {QueryParams} from '../../../common/QueryParams';
|
import {QueryParams} from '../../../common/QueryParams';
|
||||||
|
import {UserDTO} from '../../../common/entities/UserDTO';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ShareService {
|
export class ShareService {
|
||||||
@ -17,7 +18,8 @@ export class ShareService {
|
|||||||
private resolve: () => void;
|
private resolve: () => void;
|
||||||
|
|
||||||
|
|
||||||
constructor(private _networkService: NetworkService, private router: Router) {
|
constructor(private networkService: NetworkService,
|
||||||
|
private router: Router) {
|
||||||
this.sharing = new BehaviorSubject(null);
|
this.sharing = new BehaviorSubject(null);
|
||||||
this.ReadyPR = new Promise((resolve: () => void) => {
|
this.ReadyPR = new Promise((resolve: () => void) => {
|
||||||
if (this.inited === true) {
|
if (this.inited === true) {
|
||||||
@ -30,28 +32,52 @@ export class ShareService {
|
|||||||
if (val instanceof RoutesRecognized) {
|
if (val instanceof RoutesRecognized) {
|
||||||
this.param = val.state.root.firstChild.params[QueryParams.gallery.sharingKey_long] || null;
|
this.param = val.state.root.firstChild.params[QueryParams.gallery.sharingKey_long] || null;
|
||||||
this.queryParam = val.state.root.firstChild.queryParams[QueryParams.gallery.sharingKey_short] || 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 || this.sharingKey;
|
||||||
this.getSharing();
|
this.getSharing();
|
||||||
}
|
}
|
||||||
if (this.resolve) {
|
if (this.resolve) {
|
||||||
this.resolve();
|
this.resolve();
|
||||||
|
this.resolve = null;
|
||||||
this.inited = true;
|
this.inited = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public setUserObs(userOB: Observable<UserDTO>) {
|
||||||
|
|
||||||
|
userOB.subscribe((user) => {
|
||||||
|
console.log(user);
|
||||||
|
if (user && !!user.usedSharingKey) {
|
||||||
|
if (user.usedSharingKey !== this.sharingKey) {
|
||||||
|
this.sharingKey = user.usedSharingKey;
|
||||||
|
this.getSharing();
|
||||||
|
}
|
||||||
|
if (this.resolve) {
|
||||||
|
this.resolve();
|
||||||
|
this.resolve = null;
|
||||||
|
this.inited = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public wait(): Promise<void> {
|
public wait(): Promise<void> {
|
||||||
|
if (this.inited) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
return this.ReadyPR;
|
return this.ReadyPR;
|
||||||
}
|
}
|
||||||
|
|
||||||
public createSharing(dir: string, includeSubfolders: boolean, valid: number): Promise<SharingDTO> {
|
public createSharing(dir: string, includeSubfolders: boolean, valid: number): Promise<SharingDTO> {
|
||||||
return this._networkService.postJson('/share/' + dir, {
|
return this.networkService.postJson('/share/' + dir, {
|
||||||
createSharing: <CreateSharingDTO>{
|
createSharing: <CreateSharingDTO>{
|
||||||
includeSubfolders: includeSubfolders,
|
includeSubfolders: includeSubfolders,
|
||||||
valid: valid
|
valid: valid
|
||||||
@ -60,7 +86,7 @@ export class ShareService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public updateSharing(dir: string, sharingId: number, includeSubfolders: boolean, password: string, valid: number): Promise<SharingDTO> {
|
public updateSharing(dir: string, sharingId: number, includeSubfolders: boolean, password: string, valid: number): Promise<SharingDTO> {
|
||||||
return this._networkService.putJson('/share/' + dir, {
|
return this.networkService.putJson('/share/' + dir, {
|
||||||
updateSharing: <CreateSharingDTO>{
|
updateSharing: <CreateSharingDTO>{
|
||||||
id: sharingId,
|
id: sharingId,
|
||||||
includeSubfolders: includeSubfolders,
|
includeSubfolders: includeSubfolders,
|
||||||
@ -80,7 +106,7 @@ export class ShareService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async getSharing(): Promise<SharingDTO> {
|
public async getSharing(): Promise<SharingDTO> {
|
||||||
const sharing = await this._networkService.getJson<SharingDTO>('/share/' + this.getSharingKey());
|
const sharing = await this.networkService.getJson<SharingDTO>('/share/' + this.getSharingKey());
|
||||||
this.sharing.next(sharing);
|
this.sharing.next(sharing);
|
||||||
return sharing;
|
return sharing;
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ export class NavigationService {
|
|||||||
public async toGallery() {
|
public async toGallery() {
|
||||||
await this._shareService.wait();
|
await this._shareService.wait();
|
||||||
if (this._shareService.isSharing()) {
|
if (this._shareService.isSharing()) {
|
||||||
return this._router.navigate(['gallery', ''], {queryParams: {sk: this._shareService.getSharingKey()}});
|
return this._router.navigate(['share', this._shareService.getSharingKey()]);
|
||||||
} else {
|
} else {
|
||||||
return this._router.navigate(['gallery', '']);
|
return this._router.navigate(['gallery', '']);
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import {Config} from '../../../../common/config/public/Config';
|
|||||||
import {NetworkService} from './network.service';
|
import {NetworkService} from './network.service';
|
||||||
import {ErrorCodes, ErrorDTO} from '../../../../common/entities/Error';
|
import {ErrorCodes, ErrorDTO} from '../../../../common/entities/Error';
|
||||||
import {CookieNames} from '../../../../common/CookieNames';
|
import {CookieNames} from '../../../../common/CookieNames';
|
||||||
|
import {ShareService} from '../../gallery/share.service';
|
||||||
|
|
||||||
declare module ServerInject {
|
declare module ServerInject {
|
||||||
export let user: UserDTO;
|
export let user: UserDTO;
|
||||||
@ -19,9 +20,10 @@ export class AuthenticationService {
|
|||||||
public user: BehaviorSubject<UserDTO>;
|
public user: BehaviorSubject<UserDTO>;
|
||||||
|
|
||||||
constructor(private _userService: UserService,
|
constructor(private _userService: UserService,
|
||||||
private _networkService: NetworkService) {
|
private _networkService: NetworkService,
|
||||||
|
private shareSerice: ShareService) {
|
||||||
this.user = new BehaviorSubject(null);
|
this.user = new BehaviorSubject(null);
|
||||||
|
this.shareSerice.setUserObs(this.user);
|
||||||
// picking up session..
|
// picking up session..
|
||||||
if (this.isAuthenticated() === false && Cookie.get(CookieNames.session) != null) {
|
if (this.isAuthenticated() === false && Cookie.get(CookieNames.session) != null) {
|
||||||
if (typeof ServerInject !== 'undefined' && typeof ServerInject.user !== 'undefined') {
|
if (typeof ServerInject !== 'undefined' && typeof ServerInject.user !== 'undefined') {
|
||||||
@ -48,6 +50,34 @@ export class AuthenticationService {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async login(credential: LoginCredential): Promise<UserDTO> {
|
||||||
|
const user = await this._userService.login(credential);
|
||||||
|
this.user.next(user);
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async shareLogin(password: string): Promise<UserDTO> {
|
||||||
|
const user = await this._userService.shareLogin(password);
|
||||||
|
this.user.next(user);
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isAuthenticated(): boolean {
|
||||||
|
if (Config.Client.authenticationRequired === false) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return !!this.user.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isAuthorized(role: UserRoles) {
|
||||||
|
return this.user.value && this.user.value.role >= role;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async logout() {
|
||||||
|
await this._userService.logout();
|
||||||
|
this.user.next(null);
|
||||||
|
}
|
||||||
|
|
||||||
private async getSessionUser(): Promise<void> {
|
private async getSessionUser(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
this.user.next(await this._userService.getSessionUser());
|
this.user.next(await this._userService.getSessionUser());
|
||||||
@ -58,35 +88,4 @@ export class AuthenticationService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public async login(credential: LoginCredential): Promise<UserDTO> {
|
|
||||||
const user = await this._userService.login(credential);
|
|
||||||
this.user.next(user);
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public async shareLogin(password: string): Promise<UserDTO> {
|
|
||||||
const user = await this._userService.shareLogin(password);
|
|
||||||
this.user.next(user);
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public isAuthenticated(): boolean {
|
|
||||||
if (Config.Client.authenticationRequired === false) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return !!(this.user.value && this.user.value != null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public isAuthorized(role: UserRoles) {
|
|
||||||
return this.user.value && this.user.value.role >= role;
|
|
||||||
}
|
|
||||||
|
|
||||||
public logout() {
|
|
||||||
this._userService.logout();
|
|
||||||
this.user.next(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ export class UserService {
|
|||||||
await this._shareService.wait();
|
await this._shareService.wait();
|
||||||
if (Config.Client.Sharing.enabled === true) {
|
if (Config.Client.Sharing.enabled === true) {
|
||||||
if (this._shareService.isSharing()) {
|
if (this._shareService.isSharing()) {
|
||||||
return this._networkService.getJson<UserDTO>('/user/login?sk=' + this._shareService.getSharingKey());
|
return this._networkService.getJson<UserDTO>('/user/login', {sk: this._shareService.getSharingKey()});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this._networkService.getJson<UserDTO>('/user/login');
|
return this._networkService.getJson<UserDTO>('/user/login');
|
||||||
|
20
package-lock.json
generated
20
package-lock.json
generated
@ -14438,6 +14438,26 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"tslint-no-unused-expression-chai": {
|
||||||
|
"version": "0.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslint-no-unused-expression-chai/-/tslint-no-unused-expression-chai-0.1.4.tgz",
|
||||||
|
"integrity": "sha512-frEWKNTcq7VsaWKgUxMDOB2N/cmQadVkUtUGIut+2K4nv/uFXPfgJyPjuNC/cHyfUVqIkHMAvHOCL+d/McU3nQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"tsutils": "^3.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"tsutils": {
|
||||||
|
"version": "3.8.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.8.0.tgz",
|
||||||
|
"integrity": "sha512-XQdPhgcoTbCD8baXC38PQ0vpTZ8T3YrE+vR66YIj/xvDt1//8iAhafpIT/4DmvzzC1QFapEImERu48Pa01dIUA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"tslib": "^1.8.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"tsutils": {
|
"tsutils": {
|
||||||
"version": "2.29.0",
|
"version": "2.29.0",
|
||||||
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
|
||||||
|
@ -114,13 +114,13 @@
|
|||||||
"run-sequence": "2.2.1",
|
"run-sequence": "2.2.1",
|
||||||
"rxjs": "6.4.0",
|
"rxjs": "6.4.0",
|
||||||
"rxjs-compat": "6.4.0",
|
"rxjs-compat": "6.4.0",
|
||||||
|
"terser": "3.16.1",
|
||||||
"ts-helpers": "1.1.2",
|
"ts-helpers": "1.1.2",
|
||||||
"ts-node": "8.0.2",
|
"ts-node": "8.0.2",
|
||||||
"tslint": "5.12.1",
|
"tslint": "5.12.1",
|
||||||
"typescript": "3.2.4",
|
"typescript": "3.2.4",
|
||||||
"xlf-google-translate": "1.0.0-beta.13",
|
"xlf-google-translate": "1.0.0-beta.13",
|
||||||
"zone.js": "0.8.29",
|
"zone.js": "0.8.29"
|
||||||
"terser": "3.16.1"
|
|
||||||
},
|
},
|
||||||
"//": [
|
"//": [
|
||||||
"TODO: remove terser version lock once webpack is fixed"
|
"TODO: remove terser version lock once webpack is fixed"
|
||||||
|
@ -18,8 +18,8 @@ export class SQLTestHelper {
|
|||||||
dbPath: string;
|
dbPath: string;
|
||||||
|
|
||||||
constructor(public dbType: DatabaseType) {
|
constructor(public dbType: DatabaseType) {
|
||||||
this.tempDir = path.resolve(__dirname, './tmp');
|
this.tempDir = path.join(__dirname, './tmp');
|
||||||
this.dbPath = path.resolve(__dirname, './tmp', 'test.db');
|
this.dbPath = path.join(__dirname, './tmp', 'test.db');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,8 +6,13 @@ import {ObjectManagers} from '../../../../../backend/model/ObjectManagers';
|
|||||||
import {UserManager} from '../../../../../backend/model/memory/UserManager';
|
import {UserManager} from '../../../../../backend/model/memory/UserManager';
|
||||||
import {Config} from '../../../../../common/config/private/Config';
|
import {Config} from '../../../../../common/config/private/Config';
|
||||||
import {IUserManager} from '../../../../../backend/model/interfaces/IUserManager';
|
import {IUserManager} from '../../../../../backend/model/interfaces/IUserManager';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
|
|
||||||
|
declare const describe: any;
|
||||||
|
declare const it: any;
|
||||||
|
declare const beforeEach: any;
|
||||||
|
|
||||||
describe('Authentication middleware', () => {
|
describe('Authentication middleware', () => {
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@ -15,7 +20,7 @@ describe('Authentication middleware', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('authenticate', () => {
|
describe('authenticate', () => {
|
||||||
it('should call next on authenticated', (done) => {
|
it('should call next on authenticated', (done: () => void) => {
|
||||||
const req: any = {
|
const req: any = {
|
||||||
session: {
|
session: {
|
||||||
user: 'A user'
|
user: 'A user'
|
||||||
@ -24,7 +29,7 @@ describe('Authentication middleware', () => {
|
|||||||
query: {},
|
query: {},
|
||||||
params: {}
|
params: {}
|
||||||
};
|
};
|
||||||
const next: any = (err: ErrorDTO) => {
|
const next = (err: ErrorDTO) => {
|
||||||
expect(err).to.be.undefined;
|
expect(err).to.be.undefined;
|
||||||
done();
|
done();
|
||||||
};
|
};
|
||||||
@ -32,7 +37,7 @@ describe('Authentication middleware', () => {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call next with error on not authenticated', (done) => {
|
it('should call next with error on not authenticated', (done: () => void) => {
|
||||||
const req: any = {
|
const req: any = {
|
||||||
session: {},
|
session: {},
|
||||||
sessionOptions: {},
|
sessionOptions: {},
|
||||||
@ -40,8 +45,7 @@ describe('Authentication middleware', () => {
|
|||||||
params: {}
|
params: {}
|
||||||
};
|
};
|
||||||
Config.Client.authenticationRequired = true;
|
Config.Client.authenticationRequired = true;
|
||||||
const res: any = {};
|
const next = (err: ErrorDTO) => {
|
||||||
const next: any = (err: ErrorDTO) => {
|
|
||||||
expect(err).not.to.be.undefined;
|
expect(err).not.to.be.undefined;
|
||||||
expect(err.code).to.be.eql(ErrorCodes.NOT_AUTHENTICATED);
|
expect(err.code).to.be.eql(ErrorCodes.NOT_AUTHENTICATED);
|
||||||
done();
|
done();
|
||||||
@ -51,15 +55,69 @@ describe('Authentication middleware', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe('authorisePath', () => {
|
||||||
|
|
||||||
|
const req = {
|
||||||
|
session: {
|
||||||
|
user: {permissions: <string[]>null}
|
||||||
|
},
|
||||||
|
sessionOptions: {},
|
||||||
|
query: {},
|
||||||
|
params: {
|
||||||
|
path: '/test'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const authoriseDirPath = AuthenticationMWs.authorisePath('path', true);
|
||||||
|
const test = (relativePath: string): Promise<string | number> => {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
req.params.path = path.normalize(relativePath);
|
||||||
|
authoriseDirPath(<any>req, <any>{sendStatus: resolve}, () => {
|
||||||
|
resolve('ok');
|
||||||
|
});
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
it('should catch unauthorized path usage', async () => {
|
||||||
|
req.session.user.permissions = [path.normalize('/sub/subsub')];
|
||||||
|
expect(await test('/sub/subsub')).to.be.eql('ok');
|
||||||
|
expect(await test('/test')).to.be.eql(403);
|
||||||
|
expect(await test('/')).to.be.eql(403);
|
||||||
|
expect(await test('/sub/test')).to.be.eql(403);
|
||||||
|
expect(await test('/sub/subsub/test')).to.be.eql(403);
|
||||||
|
expect(await test('/sub/subsub/test/test2')).to.be.eql(403);
|
||||||
|
req.session.user.permissions = [path.normalize('/sub/subsub'), path.normalize('/sub/subsub2')];
|
||||||
|
expect(await test('/sub/subsub2')).to.be.eql('ok');
|
||||||
|
expect(await test('/sub/subsub')).to.be.eql('ok');
|
||||||
|
expect(await test('/test')).to.be.eql(403);
|
||||||
|
expect(await test('/')).to.be.eql(403);
|
||||||
|
expect(await test('/sub/test')).to.be.eql(403);
|
||||||
|
expect(await test('/sub/subsub/test')).to.be.eql(403);
|
||||||
|
expect(await test('/sub/subsub2/test')).to.be.eql(403);
|
||||||
|
req.session.user.permissions = [path.normalize('/sub/subsub*')];
|
||||||
|
expect(await test('/b')).to.be.eql(403);
|
||||||
|
expect(await test('/sub')).to.be.eql(403);
|
||||||
|
expect(await test('/sub/subsub2')).to.be.eql(403);
|
||||||
|
expect(await test('/sub/subsub2/test')).to.be.eql(403);
|
||||||
|
expect(await test('/sub/subsub')).to.be.eql('ok');
|
||||||
|
expect(await test('/sub/subsub/test')).to.be.eql('ok');
|
||||||
|
expect(await test('/sub/subsub/test/two')).to.be.eql('ok');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
describe('inverseAuthenticate', () => {
|
describe('inverseAuthenticate', () => {
|
||||||
|
|
||||||
it('should call next with error on authenticated', (done) => {
|
it('should call next with error on authenticated', (done: () => void) => {
|
||||||
const req: any = {
|
const req: any = {
|
||||||
session: {},
|
session: {},
|
||||||
sessionOptions: {},
|
sessionOptions: {},
|
||||||
};
|
};
|
||||||
const res: any = {};
|
const res: any = {};
|
||||||
const next: any = (err:ErrorDTO) => {
|
const next: any = (err: ErrorDTO) => {
|
||||||
expect(err).to.be.undefined;
|
expect(err).to.be.undefined;
|
||||||
done();
|
done();
|
||||||
};
|
};
|
||||||
@ -68,15 +126,14 @@ describe('Authentication middleware', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should call next error on authenticated', (done) => {
|
it('should call next error on authenticated', (done: () => void) => {
|
||||||
const req: any = {
|
const req: any = {
|
||||||
session: {
|
session: {
|
||||||
user: 'A user'
|
user: 'A user'
|
||||||
},
|
},
|
||||||
sessionOptions: {},
|
sessionOptions: {},
|
||||||
};
|
};
|
||||||
const res: any = {};
|
const next = (err: ErrorDTO) => {
|
||||||
const next: any = (err: ErrorDTO) => {
|
|
||||||
expect(err).not.to.be.undefined;
|
expect(err).not.to.be.undefined;
|
||||||
expect(err.code).to.be.eql(ErrorCodes.ALREADY_AUTHENTICATED);
|
expect(err.code).to.be.eql(ErrorCodes.ALREADY_AUTHENTICATED);
|
||||||
done();
|
done();
|
||||||
@ -87,7 +144,7 @@ describe('Authentication middleware', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('authorise', () => {
|
describe('authorise', () => {
|
||||||
it('should call next on authorised', (done) => {
|
it('should call next on authorised', (done: () => void) => {
|
||||||
const req: any = {
|
const req: any = {
|
||||||
session: {
|
session: {
|
||||||
user: {
|
user: {
|
||||||
@ -96,7 +153,7 @@ describe('Authentication middleware', () => {
|
|||||||
},
|
},
|
||||||
sessionOptions: {}
|
sessionOptions: {}
|
||||||
};
|
};
|
||||||
const next: any = (err:ErrorDTO) => {
|
const next = (err: ErrorDTO) => {
|
||||||
expect(err).to.be.undefined;
|
expect(err).to.be.undefined;
|
||||||
done();
|
done();
|
||||||
};
|
};
|
||||||
@ -104,7 +161,7 @@ describe('Authentication middleware', () => {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call next with error on not authorised', (done) => {
|
it('should call next with error on not authorised', (done: () => void) => {
|
||||||
const req: any = {
|
const req: any = {
|
||||||
session: {
|
session: {
|
||||||
user: {
|
user: {
|
||||||
@ -113,7 +170,7 @@ describe('Authentication middleware', () => {
|
|||||||
},
|
},
|
||||||
sessionOptions: {}
|
sessionOptions: {}
|
||||||
};
|
};
|
||||||
const next: any = (err: ErrorDTO) => {
|
const next = (err: ErrorDTO) => {
|
||||||
expect(err).not.to.be.undefined;
|
expect(err).not.to.be.undefined;
|
||||||
expect(err.code).to.be.eql(ErrorCodes.NOT_AUTHORISED);
|
expect(err.code).to.be.eql(ErrorCodes.NOT_AUTHORISED);
|
||||||
done();
|
done();
|
||||||
@ -129,12 +186,12 @@ describe('Authentication middleware', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('should call input ErrorDTO next on missing...', () => {
|
describe('should call input ErrorDTO next on missing...', () => {
|
||||||
it('body', (done) => {
|
it('body', (done: () => void) => {
|
||||||
const req: any = {
|
const req: any = {
|
||||||
query: {},
|
query: {},
|
||||||
params: {}
|
params: {}
|
||||||
};
|
};
|
||||||
const next: any = (err: ErrorDTO) => {
|
const next = (err: ErrorDTO) => {
|
||||||
expect(err).not.to.be.undefined;
|
expect(err).not.to.be.undefined;
|
||||||
expect(err.code).to.be.eql(ErrorCodes.INPUT_ERROR);
|
expect(err.code).to.be.eql(ErrorCodes.INPUT_ERROR);
|
||||||
done();
|
done();
|
||||||
@ -143,13 +200,13 @@ describe('Authentication middleware', () => {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loginCredential', (done) => {
|
it('loginCredential', (done: () => void) => {
|
||||||
const req: any = {
|
const req: any = {
|
||||||
body: {},
|
body: {},
|
||||||
query: {},
|
query: {},
|
||||||
params: {}
|
params: {}
|
||||||
};
|
};
|
||||||
const next: any = (err: ErrorDTO) => {
|
const next = (err: ErrorDTO) => {
|
||||||
expect(err).not.to.be.undefined;
|
expect(err).not.to.be.undefined;
|
||||||
expect(err.code).to.be.eql(ErrorCodes.INPUT_ERROR);
|
expect(err.code).to.be.eql(ErrorCodes.INPUT_ERROR);
|
||||||
done();
|
done();
|
||||||
@ -160,13 +217,13 @@ describe('Authentication middleware', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('loginCredential content', (done) => {
|
it('loginCredential content', (done: () => void) => {
|
||||||
const req: any = {
|
const req: any = {
|
||||||
body: {loginCredential: {}},
|
body: {loginCredential: {}},
|
||||||
query: {},
|
query: {},
|
||||||
params: {}
|
params: {}
|
||||||
};
|
};
|
||||||
const next: any = (err: ErrorDTO) => {
|
const next = (err: ErrorDTO) => {
|
||||||
expect(err).not.to.be.undefined;
|
expect(err).not.to.be.undefined;
|
||||||
expect(err.code).to.be.eql(ErrorCodes.INPUT_ERROR);
|
expect(err.code).to.be.eql(ErrorCodes.INPUT_ERROR);
|
||||||
done();
|
done();
|
||||||
@ -177,7 +234,7 @@ describe('Authentication middleware', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
it('should call next with error on not finding user', (done) => {
|
it('should call next with error on not finding user', (done: () => void) => {
|
||||||
const req: any = {
|
const req: any = {
|
||||||
body: {
|
body: {
|
||||||
loginCredential: {
|
loginCredential: {
|
||||||
@ -188,7 +245,7 @@ describe('Authentication middleware', () => {
|
|||||||
query: {},
|
query: {},
|
||||||
params: {}
|
params: {}
|
||||||
};
|
};
|
||||||
const next: any = (err: ErrorDTO) => {
|
const next = (err: ErrorDTO) => {
|
||||||
expect(err).not.to.be.undefined;
|
expect(err).not.to.be.undefined;
|
||||||
expect(err.code).to.be.eql(ErrorCodes.CREDENTIAL_NOT_FOUND);
|
expect(err.code).to.be.eql(ErrorCodes.CREDENTIAL_NOT_FOUND);
|
||||||
done();
|
done();
|
||||||
@ -203,7 +260,7 @@ describe('Authentication middleware', () => {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call next with user on the session on finding user', (done) => {
|
it('should call next with user on the session on finding user', (done: () => void) => {
|
||||||
const req: any = {
|
const req: any = {
|
||||||
session: {},
|
session: {},
|
||||||
body: {
|
body: {
|
||||||
@ -215,7 +272,7 @@ describe('Authentication middleware', () => {
|
|||||||
query: {},
|
query: {},
|
||||||
params: {}
|
params: {}
|
||||||
};
|
};
|
||||||
const next: any = (err: ErrorDTO) => {
|
const next = (err: ErrorDTO) => {
|
||||||
expect(err).to.be.undefined;
|
expect(err).to.be.undefined;
|
||||||
expect(req.session.user).to.be.eql('test user');
|
expect(req.session.user).to.be.eql('test user');
|
||||||
done();
|
done();
|
||||||
@ -233,7 +290,7 @@ describe('Authentication middleware', () => {
|
|||||||
|
|
||||||
|
|
||||||
describe('logout', () => {
|
describe('logout', () => {
|
||||||
it('should call next on logout', (done) => {
|
it('should call next on logout', (done: () => void) => {
|
||||||
const req: any = {
|
const req: any = {
|
||||||
session: {
|
session: {
|
||||||
user: {
|
user: {
|
||||||
@ -241,7 +298,7 @@ describe('Authentication middleware', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const next: any = (err:ErrorDTO) => {
|
const next: any = (err: ErrorDTO) => {
|
||||||
expect(err).to.be.undefined;
|
expect(err).to.be.undefined;
|
||||||
expect(req.session.user).to.be.undefined;
|
expect(req.session.user).to.be.undefined;
|
||||||
done();
|
done();
|
||||||
|
@ -5,14 +5,14 @@ describe('UserDTO', () => {
|
|||||||
|
|
||||||
|
|
||||||
it('should check available path', () => {
|
it('should check available path', () => {
|
||||||
expect(UserDTO.isPathAvailable('/', ['/'])).to.be.equals(true);
|
expect(UserDTO.isDirectoryPathAvailable('/', ['/'])).to.be.equals(true);
|
||||||
expect(UserDTO.isPathAvailable('/', ['/subfolder', '/'])).to.be.equals(true);
|
expect(UserDTO.isDirectoryPathAvailable('/', ['/subfolder', '/'])).to.be.equals(true);
|
||||||
expect(UserDTO.isPathAvailable('/abc', ['/subfolder', '/'])).to.be.equals(false);
|
expect(UserDTO.isDirectoryPathAvailable('/abc', ['/subfolder', '/'])).to.be.equals(false);
|
||||||
expect(UserDTO.isPathAvailable('/abc', ['/subfolder', '/*'])).to.be.equals(true);
|
expect(UserDTO.isDirectoryPathAvailable('/abc', ['/subfolder', '/*'])).to.be.equals(true);
|
||||||
expect(UserDTO.isPathAvailable('/abc', ['/subfolder'])).to.be.equals(false);
|
expect(UserDTO.isDirectoryPathAvailable('/abc', ['/subfolder'])).to.be.equals(false);
|
||||||
expect(UserDTO.isPathAvailable('/abc/two', ['/subfolder'])).to.be.equals(false);
|
expect(UserDTO.isDirectoryPathAvailable('/abc/two', ['/subfolder'])).to.be.equals(false);
|
||||||
expect(UserDTO.isPathAvailable('/abc/two', ['/'])).to.be.equals(false);
|
expect(UserDTO.isDirectoryPathAvailable('/abc/two', ['/'])).to.be.equals(false);
|
||||||
expect(UserDTO.isPathAvailable('/abc/two', ['/*'])).to.be.equals(true);
|
expect(UserDTO.isDirectoryPathAvailable('/abc/two', ['/*'])).to.be.equals(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should check directory', () => {
|
it('should check directory', () => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user