1
0
mirror of https://github.com/bpatrik/pigallery2.git synced 2024-11-21 17:56:45 +02:00

Fixing tests after adding extension manager #753

This commit is contained in:
Patrik J. Braun 2023-11-16 23:41:05 +01:00
parent 75d277040d
commit a323634351
20 changed files with 169 additions and 120 deletions

View File

@ -121,7 +121,7 @@ export class BenchmarkRunner {
const bm = new Benchmark('List directory', req,
async (): Promise<void> => {
await ObjectManagers.reset();
await ObjectManagers.InitManagers();
await ObjectManagers.getInstance().init();
}, null,
async (): Promise<void> => {
Config.Indexing.reIndexingSensitivity = ReIndexingSensitivity.low;
@ -135,7 +135,7 @@ export class BenchmarkRunner {
async bmListPersons(): Promise<BenchmarkResult[]> {
const bm = new Benchmark('Listing Faces', Utils.clone(this.requestTemplate), async (): Promise<void> => {
await ObjectManagers.reset();
await ObjectManagers.InitManagers();
await ObjectManagers.getInstance().init();
}, null,
async (): Promise<void> => {
Config.Indexing.reIndexingSensitivity = ReIndexingSensitivity.low;
@ -289,7 +289,7 @@ export class BenchmarkRunner {
await fs.promises.rm(ProjectPath.DBFolder, {recursive: true, force: true});
Config.Database.type = DatabaseType.sqlite;
Config.Jobs.scheduled = [];
await ObjectManagers.InitManagers();
await ObjectManagers.getInstance().init();
};
private async setupDB(): Promise<void> {

View File

@ -34,11 +34,98 @@ export class ObjectManagers {
private locationManager: LocationManager;
private albumManager: AlbumManager;
private extensionManager: ExtensionManager;
private initDone = false;
constructor() {
this.managers = [];
}
public static getInstance(): ObjectManagers {
if (!this.instance) {
this.instance = new ObjectManagers();
}
return this.instance;
}
public static async reset(): Promise<void> {
Logger.silly(LOG_TAG, 'Object manager reset begin');
if (ObjectManagers.isReady()) {
if (
ObjectManagers.getInstance().IndexingManager &&
ObjectManagers.getInstance().IndexingManager.IsSavingInProgress
) {
await ObjectManagers.getInstance().IndexingManager.SavingReady;
}
for (const manager of ObjectManagers.getInstance().managers) {
if (manager === ObjectManagers.getInstance().versionManager) {
continue;
}
if (manager.cleanUp) {
await manager.cleanUp();
}
}
}
await SQLConnection.close();
this.instance = null;
Logger.debug(LOG_TAG, 'Object manager reset done');
}
public static isReady(): boolean {
return this.instance && this.instance.initDone;
}
public async init(): Promise<void> {
if (this.initDone) {
return;
}
await SQLConnection.init();
await this.initManagers();
Logger.debug(LOG_TAG, 'SQL DB inited');
this.initDone = true;
}
private async initManagers(): Promise<void> {
this.AlbumManager = new AlbumManager();
this.GalleryManager = new GalleryManager();
this.IndexingManager = new IndexingManager();
this.PersonManager = new PersonManager();
this.CoverManager = new CoverManager();
this.SearchManager = new SearchManager();
this.SharingManager = new SharingManager();
this.UserManager = new UserManager();
this.VersionManager = new VersionManager();
this.JobManager = new JobManager();
this.LocationManager = new LocationManager();
this.ExtensionManager = new ExtensionManager();
for (const manager of ObjectManagers.getInstance().managers) {
if (manager === ObjectManagers.getInstance().versionManager) {
continue;
}
if (manager.init) {
await manager.init();
}
}
}
public async onDataChange(
changedDir: ParentDirectoryDTO = null
): Promise<void> {
await this.VersionManager.onNewDataVersion();
for (const manager of this.managers) {
if (manager === this.versionManager) {
continue;
}
if (manager.onNewDataVersion) {
await manager.onNewDataVersion(changedDir);
}
}
}
get VersionManager(): VersionManager {
return this.versionManager;
}
@ -182,79 +269,4 @@ export class ObjectManagers {
this.extensionManager = value;
this.managers.push(this.extensionManager as IObjectManager);
}
public static getInstance(): ObjectManagers {
if (this.instance === null) {
this.instance = new ObjectManagers();
}
return this.instance;
}
public static async reset(): Promise<void> {
Logger.silly(LOG_TAG, 'Object manager reset begin');
if (
ObjectManagers.getInstance().IndexingManager &&
ObjectManagers.getInstance().IndexingManager.IsSavingInProgress
) {
await ObjectManagers.getInstance().IndexingManager.SavingReady;
}
for (const manager of ObjectManagers.getInstance().managers) {
if (manager === ObjectManagers.getInstance().versionManager) {
continue;
}
if (manager.cleanUp) {
await manager.cleanUp();
}
}
await SQLConnection.close();
this.instance = null;
Logger.debug(LOG_TAG, 'Object manager reset done');
}
public static async InitManagers(): Promise<void> {
await ObjectManagers.reset();
await SQLConnection.init();
await this.initManagers();
Logger.debug(LOG_TAG, 'SQL DB inited');
}
private static async initManagers(): Promise<void> {
ObjectManagers.getInstance().AlbumManager = new AlbumManager();
ObjectManagers.getInstance().GalleryManager = new GalleryManager();
ObjectManagers.getInstance().IndexingManager = new IndexingManager();
ObjectManagers.getInstance().PersonManager = new PersonManager();
ObjectManagers.getInstance().CoverManager = new CoverManager();
ObjectManagers.getInstance().SearchManager = new SearchManager();
ObjectManagers.getInstance().SharingManager = new SharingManager();
ObjectManagers.getInstance().UserManager = new UserManager();
ObjectManagers.getInstance().VersionManager = new VersionManager();
ObjectManagers.getInstance().JobManager = new JobManager();
ObjectManagers.getInstance().LocationManager = new LocationManager();
ObjectManagers.getInstance().ExtensionManager = new ExtensionManager();
for (const manager of ObjectManagers.getInstance().managers) {
if (manager === ObjectManagers.getInstance().versionManager) {
continue;
}
if (manager.init) {
await manager.init();
}
}
}
public async onDataChange(
changedDir: ParentDirectoryDTO = null
): Promise<void> {
await this.VersionManager.onNewDataVersion();
for (const manager of this.managers) {
if (manager === this.versionManager) {
continue;
}
if (manager.onNewDataVersion) {
await manager.onNewDataVersion(changedDir);
}
}
}
}

View File

@ -13,8 +13,10 @@ export class ExtensionConfigWrapper {
const pc = ConfigClassBuilder.attachPrivateInterface(new PrivateConfigClass());
try {
await pc.load();
for (const ext of Object.values(ObjectManagers.getInstance().ExtensionManager.extObjects)) {
ext.config.loadToConfig(ConfigClassBuilder.attachPrivateInterface(pc));
if (ObjectManagers.isReady()) {
for (const ext of Object.values(ObjectManagers.getInstance().ExtensionManager.extObjects)) {
ext.config.loadToConfig(ConfigClassBuilder.attachPrivateInterface(pc));
}
}
} catch (e) {
console.error('Error during loading original config. Reverting to defaults.');

View File

@ -8,8 +8,13 @@ export const ExtensionDecorator = <I extends [], O>(fn: (ee: IExtensionEvents) =
propertyName: string,
descriptor: PropertyDescriptor
) => {
const targetMethod = descriptor.value;
descriptor.value = async function(...args: I) {
if (!ObjectManagers.isReady()) {
return await targetMethod.apply(this, args);
}
const event = fn(ObjectManagers.getInstance().ExtensionManager.events) as ExtensionEvent<I, O>;
const eventObj = {stopPropagation: false};
const input = await event.triggerBefore({inputs: args}, eventObj);

View File

@ -28,6 +28,9 @@ export class ExtensionManager implements IObjectManager {
public async init() {
this.extObjects = {};
this.initEvents();
if (!Config.Extensions.enabled) {
return;
}
this.router = express.Router();
Server.getInstance().app.use(ExtensionManager.EXTENSION_API_PATH, this.router);
this.loadExtensionsList();
@ -117,6 +120,9 @@ export class ExtensionManager implements IObjectManager {
public async cleanUp() {
if (!Config.Extensions.enabled) {
return;
}
this.initEvents(); // reset events
await this.cleanUpExtensions();
Server.getInstance().app.use(ExtensionManager.EXTENSION_API_PATH, express.Router());

View File

@ -38,7 +38,7 @@ export class Server {
static instance: Server = null;
public static getInstance(): Server {
if (this.instance === null) {
if (!this.instance) {
this.instance = new Server();
}
return this.instance;
@ -54,11 +54,16 @@ export class Server {
this.init().catch(console.error);
}
get App(): any {
get Server(): HttpServer {
return this.server;
}
async init(): Promise<void> {
this.app = express();
LoggerRouter.route(this.app);
this.app.set('view engine', 'ejs');
Logger.info(LOG_TAG, 'running diagnostics...');
await ConfigDiagnostics.runDiagnostics();
Logger.verbose(
@ -78,11 +83,6 @@ export class Server {
return v;
}, 2));
this.app = express();
LoggerRouter.route(this.app);
this.app.set('view engine', 'ejs');
/**
* Session above all
@ -130,7 +130,7 @@ export class Server {
Localizations.init();
this.app.use(locale(Config.Server.languages, 'en'));
await ObjectManagers.InitManagers();
await ObjectManagers.getInstance().init();
Router.route(this.app);

View File

@ -11,6 +11,7 @@ import {
} from '../../entities/job/JobScheduleDTO';
import {
ClientConfig,
ClientExtensionsConfig,
ClientGPXCompressingConfig,
ClientMediaConfig,
ClientMetaFileConfig,
@ -1015,7 +1016,7 @@ export class ServerServiceConfig extends ClientServiceConfig {
@SubConfigClass<TAGS>({softReadonly: true})
export class ServerExtensionsConfig {
export class ServerExtensionsConfig extends ClientExtensionsConfig {
@ConfigProperty({volatile: true})
list: string[] = [];

View File

@ -1424,6 +1424,16 @@ export class ClientUserConfig {
unAuthenticatedUserRole: UserRoles = UserRoles.Admin;
}
@SubConfigClass({tags: {client: true}, softReadonly: true})
export class ClientExtensionsConfig {
@ConfigProperty({
tags: {
name: $localize`Enabled`,
priority: ConfigPriority.advanced,
}
})
enabled: boolean = true;
}
@SubConfigClass<TAGS>({tags: {client: true}, softReadonly: true})
export class ClientConfig {
@ -1496,4 +1506,13 @@ export class ClientConfig {
description: $localize`This feature enables you to generate 'random photo' urls. That URL returns a photo random selected from your gallery. You can use the url with 3rd party application like random changing desktop background. Note: With the current implementation, random link also requires login.`
})
RandomPhoto: ClientRandomPhotoConfig = new ClientRandomPhotoConfig();
@ConfigProperty({
tags: {
name: $localize`Extensions`,
uiIcon: 'ionCloudOutline'
} as TAGS,
})
Extensions: ClientExtensionsConfig = new ClientExtensionsConfig();
}

View File

@ -2,7 +2,7 @@ import {Config} from '../../src/common/config/private/Config';
import * as path from 'path';
import * as fs from 'fs';
import {SQLConnection} from '../../src/backend/model/database/SQLConnection';
import {DatabaseType, LogLevel} from '../../src/common/config/private/PrivateConfig';
import {DatabaseType} from '../../src/common/config/private/PrivateConfig';
import {ProjectPath} from '../../src/backend/ProjectPath';
import {DirectoryBaseDTO, ParentDirectoryDTO, SubDirectoryDTO} from '../../src/common/entities/DirectoryDTO';
import {ObjectManagers} from '../../src/backend/model/ObjectManagers';
@ -111,7 +111,7 @@ export class DBTestHelper {
}
public static async persistTestDir(directory: DirectoryBaseDTO): Promise<ParentDirectoryDTO> {
await ObjectManagers.InitManagers();
await ObjectManagers.getInstance().init();
const connection = await SQLConnection.getConnection();
ObjectManagers.getInstance().IndexingManager.indexDirectory = () => Promise.resolve(null);
@ -122,20 +122,20 @@ export class DBTestHelper {
// await im.saveToDB(subDir2);
if (ObjectManagers.getInstance().IndexingManager &&
ObjectManagers.getInstance().IndexingManager.IsSavingInProgress) {
ObjectManagers.getInstance().IndexingManager.IsSavingInProgress) {
await ObjectManagers.getInstance().IndexingManager.SavingReady;
}
const gm = new GalleryManagerTest();
const dir = await gm.getParentDirFromId(connection,
(await gm.getDirIdAndTime(connection, directory.name, path.join(directory.path, path.sep))).id);
(await gm.getDirIdAndTime(connection, directory.name, path.join(directory.path, path.sep))).id);
const populateDir = async (d: DirectoryBaseDTO) => {
for (let i = 0; i < d.directories.length; i++) {
d.directories[i] = await gm.getParentDirFromId(connection,
(await gm.getDirIdAndTime(connection, d.directories[i].name,
path.join(DiskManager.pathFromParent(d), path.sep))).id);
(await gm.getDirIdAndTime(connection, d.directories[i].name,
path.join(DiskManager.pathFromParent(d), path.sep))).id);
await populateDir(d.directories[i]);
}
};
@ -147,6 +147,7 @@ export class DBTestHelper {
public async initDB(): Promise<void> {
await Config.load();
Config.Extensions.enabled = false; // make all tests clean
if (this.dbType === DatabaseType.sqlite) {
await this.initSQLite();
} else if (this.dbType === DatabaseType.mysql) {
@ -197,7 +198,7 @@ export class DBTestHelper {
const conn = await SQLConnection.getConnection();
await conn.query('CREATE DATABASE IF NOT EXISTS ' + conn.options.database);
await SQLConnection.close();
await ObjectManagers.InitManagers();
await ObjectManagers.getInstance().init();
}
private async clearUpMysql(): Promise<void> {
@ -218,7 +219,7 @@ export class DBTestHelper {
private async resetSQLite(): Promise<void> {
Logger.debug(LOG_TAG, 'resetting sqlite');
await this.clearUpSQLite();
await ObjectManagers.InitManagers();
await ObjectManagers.getInstance().init();
}
private async clearUpSQLite(): Promise<void> {

View File

@ -48,7 +48,7 @@ describe('GalleryRouter', (sqlHelper: DBTestHelper) => {
afterEach(tearDown);
it('should load gallery', async () => {
const result = await (chai.request(server.App) as SuperAgentStatic)
const result = await (chai.request(server.Server) as SuperAgentStatic)
.get(Config.Server.apiPath + '/gallery/content/');
(result.should as any).have.status(200);
@ -59,10 +59,10 @@ describe('GalleryRouter', (sqlHelper: DBTestHelper) => {
it('should load gallery twice (to force loading form db)', async () => {
Config.Indexing.reIndexingSensitivity = ReIndexingSensitivity.low;
const _ = await (chai.request(server.App) as SuperAgentStatic)
const _ = await (chai.request(server.Server) as SuperAgentStatic)
.get(Config.Server.apiPath + '/gallery/content/orientation');
const result = await (chai.request(server.App) as SuperAgentStatic)
const result = await (chai.request(server.Server) as SuperAgentStatic)
.get(Config.Server.apiPath + '/gallery/content/orientation');
(result.should as any).have.status(200);
@ -80,7 +80,7 @@ describe('GalleryRouter', (sqlHelper: DBTestHelper) => {
afterEach(tearDown);
it('should get video without transcoding', async () => {
const result = await (chai.request(server.App) as SuperAgentStatic)
const result = await (chai.request(server.Server) as SuperAgentStatic)
.get(Config.Server.apiPath + '/gallery/content/video.mp4/bestFit');
(result.should as any).have.status(200);

View File

@ -41,7 +41,7 @@ describe('PublicRouter', () => {
server = new Server();
await server.onStarted.wait();
await ObjectManagers.InitManagers();
await ObjectManagers.getInstance().init();
await ObjectManagers.getInstance().UserManager.createUser(Utils.clone(testUser));
await SQLConnection.close();
};
@ -71,7 +71,7 @@ describe('PublicRouter', () => {
afterEach(tearDown);
const fistLoad = async (srv: Server, sharingKey: string): Promise<any> => {
return (chai.request(srv.App) as SuperAgentStatic)
return (chai.request(srv.Server) as SuperAgentStatic)
.get('/share/' + sharingKey);
};

View File

@ -42,7 +42,7 @@ describe('SharingRouter', () => {
server = new Server();
await server.onStarted.wait();
await ObjectManagers.InitManagers();
await ObjectManagers.getInstance().init();
await ObjectManagers.getInstance().UserManager.createUser(Utils.clone(testUser));
await SQLConnection.close();
};
@ -62,7 +62,7 @@ describe('SharingRouter', () => {
};
const shareLogin = async (srv: Server, sharingKey: string, password?: string): Promise<any> => {
return (chai.request(srv.App) as SuperAgentStatic)
return (chai.request(srv.Server) as SuperAgentStatic)
.post(Config.Server.apiPath + '/share/login?' + QueryParams.gallery.sharingKey_query + '=' + sharingKey)
.send({password});

View File

@ -42,7 +42,7 @@ describe('UserRouter', () => {
server = new Server();
await server.onStarted.wait();
await ObjectManagers.InitManagers();
await ObjectManagers.getInstance().init();
await ObjectManagers.getInstance().UserManager.createUser(Utils.clone(testUser));
await SQLConnection.close();
};
@ -62,7 +62,7 @@ describe('UserRouter', () => {
};
const login = async (srv: Server): Promise<any> => {
const result = await (chai.request(srv.App) as SuperAgentStatic)
const result = await (chai.request(srv.Server) as SuperAgentStatic)
.post(Config.Server.apiPath + '/user/login')
.send({
loginCredential: {
@ -87,7 +87,7 @@ describe('UserRouter', () => {
});
it('it skip login', async () => {
Config.Users.authenticationRequired = false;
const result = await chai.request(server.App)
const result = await chai.request(server.Server)
.post(Config.Server.apiPath + '/user/login');
result.res.should.have.status(404);
@ -105,7 +105,7 @@ describe('UserRouter', () => {
const loginRes = await login(server);
const result = await chai.request(server.App)
const result = await chai.request(server.Server)
.get(Config.Server.apiPath + '/user/me')
.set('Cookie', loginRes.res.headers['set-cookie'])
.set('CSRF-Token', loginRes.body.result.csrfToken);
@ -116,7 +116,7 @@ describe('UserRouter', () => {
it('it should not authenticate', async () => {
Config.Users.authenticationRequired = true;
const result = await chai.request(server.App)
const result = await chai.request(server.Server)
.get(Config.Server.apiPath + '/user/me');
result.res.should.have.status(401);
@ -133,7 +133,7 @@ describe('UserRouter', () => {
const loginRes = await login(server);
const q: Record<string, string> = {};
q[QueryParams.gallery.sharingKey_query] = sharingKey;
const result = await chai.request(server.App)
const result = await chai.request(server.Server)
.get(Config.Server.apiPath + '/user/me?' + QueryParams.gallery.sharingKey_query + '=' + sharingKey)
.set('Cookie', loginRes.res.headers['set-cookie'])
.set('CSRF-Token', loginRes.body.result.csrfToken);
@ -152,7 +152,7 @@ describe('UserRouter', () => {
const q: Record<string, string> = {};
q[QueryParams.gallery.sharingKey_query] = sharing.sharingKey;
const result = await chai.request(server.App)
const result = await chai.request(server.Server)
.get(Config.Server.apiPath + '/user/me?' + QueryParams.gallery.sharingKey_query + '=' + sharing.sharingKey);
checkUserResult(result, RouteTestingHelper.getExpectedSharingUser(sharing));
@ -167,7 +167,7 @@ describe('UserRouter', () => {
const q: Record<string, string> = {};
q[QueryParams.gallery.sharingKey_query] = sharing.sharingKey;
const result = await chai.request(server.App)
const result = await chai.request(server.Server)
.get(Config.Server.apiPath + '/user/me?' + QueryParams.gallery.sharingKey_query + '=' + sharing.sharingKey);
result.should.have.status(401);
@ -179,7 +179,7 @@ describe('UserRouter', () => {
it('it should authenticate as guest', async () => {
Config.Users.authenticationRequired = false;
const result = await chai.request(server.App)
const result = await chai.request(server.Server)
.get(Config.Server.apiPath + '/user/me');
const expectedGuestUser = {

View File

@ -38,7 +38,7 @@ describe('SettingsRouter', () => {
const originalSettings = await ExtensionConfigWrapper.original();
const srv = new Server();
await srv.onStarted.wait();
const result = await chai.request(srv.App)
const result = await chai.request(srv.Server)
.get(Config.Server.apiPath + '/settings');
result.res.should.have.status(200);

View File

@ -22,7 +22,7 @@ describe('Settings middleware', () => {
beforeEach(async () => {
await ObjectManagers.reset();
await fs.promises.rm(tempDir, {recursive: true, force: true});
await ObjectManagers.InitManagers();
await ObjectManagers.getInstance().init();
});
it('should save empty enforced users settings', (done: (err?: any) => void) => {

View File

@ -33,7 +33,7 @@ describe('AlbumManager', (sqlHelper: DBTestHelper) => {
const setUpSqlDB = async () => {
await sqlHelper.initDB();
await sqlHelper.setUpTestGallery();
await ObjectManagers.InitManagers();
await ObjectManagers.getInstance().init();
};

View File

@ -122,7 +122,7 @@ describe('CoverManager', (sqlHelper: DBTestHelper) => {
const setUpSqlDB = async () => {
await sqlHelper.initDB();
await setUpTestGallery();
await ObjectManagers.InitManagers();
await ObjectManagers.getInstance().init();
};

View File

@ -146,7 +146,7 @@ describe('SearchManager', (sqlHelper: DBTestHelper) => {
const setUpSqlDB = async () => {
await sqlHelper.initDB();
await setUpTestGallery();
await ObjectManagers.InitManagers();
await ObjectManagers.getInstance().init();
};

View File

@ -15,6 +15,7 @@ describe('DiskMangerWorker', () => {
Config.Database.type = DatabaseType.sqlite;
Config.Faces.enabled = true;
Config.Faces.keywordsToPersons = true;
Config.Extensions.enabled = false;
});
@ -24,6 +25,7 @@ describe('DiskMangerWorker', () => {
const dir = await DiskManager.scanDirectory('/');
// should match the number of media (photo/video) files in the assets folder
expect(dir.media.length).to.be.equals(10);
// eslint-disable-next-line @typescript-eslint/no-var-requires
const expected = require(path.join(__dirname, '/../../../assets/test image öüóőúéáű-.,.json'));
const i = dir.media.findIndex(m => m.name === 'test image öüóőúéáű-.,.jpg');
expect(Utils.clone(dir.media[i].name)).to.be.deep.equal('test image öüóőúéáű-.,.jpg');

View File

@ -18,6 +18,7 @@ describe('MetadataLoader', () => {
Config.Database.type = DatabaseType.sqlite;
Config.Faces.enabled = true;
Config.Faces.keywordsToPersons = true;
Config.Extensions.enabled = false;
});
@ -66,7 +67,7 @@ describe('MetadataLoader', () => {
});
it('jpg 2', async () => {
const data = await MetadataLoader.loadPhotoMetadata(
path.join(__dirname, '/../../../assets/orientation/broken_orientation_exif2.jpg'));
path.join(__dirname, '/../../../assets/orientation/broken_orientation_exif2.jpg'));
const expected = require(path.join(__dirname, '/../../../assets/orientation/broken_orientation_exif2.json'));
expect(Utils.clone(data)).to.be.deep.equal(expected);
});