You've already forked pigallery2
mirror of
https://github.com/bpatrik/pigallery2.git
synced 2025-11-29 22:48:28 +02:00
@@ -17,6 +17,45 @@ import {ServerTime} from './ServerTimingMWs';
|
||||
import {SortByTypes} from '../../common/entities/SortingMethods';
|
||||
|
||||
export class GalleryMWs {
|
||||
/**
|
||||
* Middleware to safely parse searchQueryDTO from URL parameters
|
||||
* Handles URL decoding and JSON parsing with proper error handling
|
||||
*/
|
||||
public static parseSearchQuery(
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
): void {
|
||||
try {
|
||||
if (!req.params['searchQueryDTO']) {
|
||||
return next();
|
||||
}
|
||||
|
||||
let rawQueryParam = req.params['searchQueryDTO'] as string;
|
||||
|
||||
let query: SearchQueryDTO;
|
||||
try {
|
||||
query = JSON.parse(rawQueryParam);
|
||||
} catch (parseError) {
|
||||
return next(
|
||||
new ErrorDTO(
|
||||
ErrorCodes.INPUT_ERROR,
|
||||
'Invalid search query JSON: ' + parseError.message,
|
||||
parseError
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Store the parsed query for use by subsequent middlewares
|
||||
req.resultPipe = query;
|
||||
return next();
|
||||
} catch (err) {
|
||||
return next(
|
||||
new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'Error parsing search query', err)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ServerTime('1.db', 'List Directory')
|
||||
public static async listDirectory(
|
||||
req: Request,
|
||||
@@ -78,13 +117,13 @@ export class GalleryMWs {
|
||||
return next();
|
||||
}
|
||||
|
||||
if (Config.Search.enabled === false || !req.params['searchQueryDTO']) {
|
||||
if (Config.Search.enabled === false || !req.resultPipe) {
|
||||
return next();
|
||||
}
|
||||
|
||||
// Handle search-query-based zip
|
||||
try {
|
||||
const query: SearchQueryDTO = JSON.parse(req.params['searchQueryDTO'] as string);
|
||||
const query: SearchQueryDTO = req.resultPipe as any;
|
||||
|
||||
// Get all media items from search
|
||||
const searchResult = await ObjectManagers.getInstance().SearchManager.search(
|
||||
@@ -251,15 +290,12 @@ export class GalleryMWs {
|
||||
try {
|
||||
if (
|
||||
Config.Search.enabled === false ||
|
||||
!req.params['searchQueryDTO']
|
||||
!req.resultPipe
|
||||
) {
|
||||
return next();
|
||||
}
|
||||
|
||||
|
||||
const query: SearchQueryDTO = JSON.parse(
|
||||
req.params['searchQueryDTO'] as string
|
||||
);
|
||||
const query: SearchQueryDTO = req.resultPipe as any;
|
||||
const result = await ObjectManagers.getInstance().SearchManager.search(
|
||||
req.session.context,
|
||||
query
|
||||
@@ -326,14 +362,12 @@ export class GalleryMWs {
|
||||
try {
|
||||
if (
|
||||
Config.RandomPhoto.enabled === false ||
|
||||
!req.params['searchQueryDTO']
|
||||
!req.resultPipe
|
||||
) {
|
||||
return next();
|
||||
}
|
||||
|
||||
const query: SearchQueryDTO = JSON.parse(
|
||||
req.params['searchQueryDTO'] as string
|
||||
);
|
||||
const query: SearchQueryDTO = req.resultPipe as any;
|
||||
|
||||
const photos =
|
||||
await ObjectManagers.getInstance().SearchManager.getNMedia(
|
||||
|
||||
@@ -274,9 +274,10 @@ export class SharingMWs {
|
||||
if (Config.Sharing.enabled === false) {
|
||||
return next();
|
||||
}
|
||||
const query: SearchQueryDTO = JSON.parse(
|
||||
req.params['searchQueryDTO'] as string
|
||||
);
|
||||
if (!req.resultPipe) {
|
||||
return next();
|
||||
}
|
||||
const query: SearchQueryDTO = req.resultPipe as any;
|
||||
if (req.session.context?.user.role >= UserRoles.Admin) {
|
||||
req.resultPipe =
|
||||
await ObjectManagers.getInstance().SharingManager.listAllForQuery(query);
|
||||
|
||||
@@ -6,11 +6,13 @@ import {SessionContext} from '../../model/SessionContext';
|
||||
declare global {
|
||||
namespace Express {
|
||||
interface Request {
|
||||
// sending data between middlewares. Next middleware will expect the output of the previous one in this field.
|
||||
resultPipe?: unknown;
|
||||
body?: {
|
||||
loginCredential?: LoginCredential;
|
||||
};
|
||||
locale?: string;
|
||||
// Stored in the session cookie. Travels to the client side
|
||||
session: {
|
||||
context?: SessionContext;
|
||||
rememberMe?: boolean;
|
||||
|
||||
@@ -56,6 +56,7 @@ export class GalleryRouter {
|
||||
AuthenticationMWs.authorise(UserRoles.LimitedGuest),
|
||||
|
||||
// specific part
|
||||
GalleryMWs.parseSearchQuery,
|
||||
ServerTimingMWs.addServerTiming,
|
||||
GalleryMWs.zipDirectory
|
||||
);
|
||||
@@ -167,6 +168,7 @@ export class GalleryRouter {
|
||||
VersionMWs.injectGalleryVersion,
|
||||
|
||||
// specific part
|
||||
GalleryMWs.parseSearchQuery,
|
||||
GalleryMWs.getRandomImage,
|
||||
GalleryMWs.loadFile,
|
||||
ServerTimingMWs.addServerTiming,
|
||||
@@ -260,6 +262,7 @@ export class GalleryRouter {
|
||||
VersionMWs.injectGalleryVersion,
|
||||
|
||||
// specific part
|
||||
GalleryMWs.parseSearchQuery,
|
||||
GalleryMWs.search,
|
||||
ThumbnailGeneratorMWs.addThumbnailInformation,
|
||||
GalleryMWs.cleanUpGalleryResults,
|
||||
|
||||
@@ -2,6 +2,7 @@ import {AuthenticationMWs} from '../middlewares/user/AuthenticationMWs';
|
||||
import {UserRoles} from '../../common/entities/UserDTO';
|
||||
import {RenderingMWs} from '../middlewares/RenderingMWs';
|
||||
import {SharingMWs} from '../middlewares/SharingMWs';
|
||||
import {GalleryMWs} from '../middlewares/GalleryMWs';
|
||||
import * as express from 'express';
|
||||
import {QueryParams} from '../../common/QueryParams';
|
||||
import {ServerTimingMWs} from '../middlewares/ServerTimingMWs';
|
||||
@@ -104,6 +105,7 @@ export class SharingRouter {
|
||||
[Config.Server.apiPath + '/share/list/:searchQueryDTO'],
|
||||
AuthenticationMWs.authenticate,
|
||||
AuthenticationMWs.authorise(UserRoles.User),
|
||||
GalleryMWs.parseSearchQuery,
|
||||
SharingMWs.listSharingForQuery,
|
||||
ServerTimingMWs.addServerTiming,
|
||||
RenderingMWs.renderSharingList
|
||||
|
||||
@@ -108,7 +108,7 @@ export class ContentLoaderService {
|
||||
let cw = this.galleryCacheService.getSearch(JSON.parse(query));
|
||||
if (!cw || cw.searchResult == null) {
|
||||
try {
|
||||
cw = await this.networkService.getJson<ContentWrapperWithError>('/search/' + query);
|
||||
cw = await this.networkService.getJson<ContentWrapperWithError>('/search/' + encodeURIComponent(query));
|
||||
this.galleryCacheService.setSearch(cw);
|
||||
} catch (e) {
|
||||
cw = cw || {
|
||||
|
||||
@@ -139,7 +139,7 @@ export class AutoCompleteService {
|
||||
acParams[QueryParams.gallery.search.type] = type;
|
||||
}
|
||||
this.networkService
|
||||
.getJson<IAutoCompleteItem[]>('/autocomplete/' + text, acParams)
|
||||
.getJson<IAutoCompleteItem[]>('/autocomplete/' + encodeURIComponent(text), acParams)
|
||||
.then((ret) => {
|
||||
this.galleryCacheService.setAutoComplete(text, type, ret);
|
||||
items.next(
|
||||
|
||||
@@ -8,7 +8,7 @@ import {QueryParams} from '../../../../common/QueryParams';
|
||||
import {UserDTO, UserRoles} from '../../../../common/entities/UserDTO';
|
||||
import {Utils} from '../../../../common/Utils';
|
||||
import {Config} from '../../../../common/config/public/Config';
|
||||
import {SearchQueryDTO, SearchQueryTypes, TextSearch, TextSearchQueryMatchTypes} from '../../../../common/entities/SearchQueryDTO';
|
||||
import {SearchQueryDTO} from '../../../../common/entities/SearchQueryDTO';
|
||||
|
||||
|
||||
@Injectable()
|
||||
@@ -169,6 +169,23 @@ export class ShareService {
|
||||
return this.sharingKey != null;
|
||||
}
|
||||
|
||||
public async getSharingListForQuery(
|
||||
query: SearchQueryDTO
|
||||
): Promise<SharingDTO[]> {
|
||||
return this.networkService.getJson('/share/list/' + encodeURIComponent(JSON.stringify(query)));
|
||||
}
|
||||
|
||||
public getSharingList(): Promise<SharingDTO[]> {
|
||||
if (!Config.Sharing.enabled) {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
return this.networkService.getJson('/share/listAll');
|
||||
}
|
||||
|
||||
public deleteSharing(sharing: SharingDTO): Promise<void> {
|
||||
return this.networkService.deleteJson('/share/' + encodeURIComponent(sharing.sharingKey));
|
||||
}
|
||||
|
||||
private async getSharing(): Promise<void> {
|
||||
try {
|
||||
this.sharingSubject.next(null);
|
||||
@@ -194,23 +211,4 @@ export class ShareService {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async getSharingListForQuery(
|
||||
query: SearchQueryDTO
|
||||
): Promise<SharingDTO[]> {
|
||||
return this.networkService.getJson('/share/list/' + JSON.stringify(query));
|
||||
}
|
||||
|
||||
|
||||
public getSharingList(): Promise<SharingDTO[]> {
|
||||
if (!Config.Sharing.enabled) {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
return this.networkService.getJson('/share/listAll');
|
||||
}
|
||||
|
||||
public deleteSharing(sharing: SharingDTO): Promise<void> {
|
||||
return this.networkService.deleteJson('/share/' + sharing.sharingKey);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user