mirror of
https://github.com/bpatrik/pigallery2.git
synced 2025-01-12 04:23:09 +02:00
adding sqlite support, removing mysql required dependency
This commit is contained in:
parent
93ac783a09
commit
0618105857
@ -2,7 +2,7 @@ import {NextFunction, Request, Response} from "express";
|
||||
import {ErrorCodes, ErrorDTO} from "../../common/entities/Error";
|
||||
import {ObjectManagerRepository} from "../model/ObjectManagerRepository";
|
||||
import {Logger} from "../Logger";
|
||||
import {MySQLConnection} from "../model/mysql/MySQLConnection";
|
||||
import {SQLConnection} from "../model/sql/SQLConnection";
|
||||
import {DataBaseConfig, DatabaseType, ThumbnailConfig} from "../../common/config/private/IPrivateConfig";
|
||||
import {Config} from "../../common/config/private/Config";
|
||||
import {ConfigDiagnostics} from "../model/ConfigDiagnostics";
|
||||
@ -25,8 +25,8 @@ export class AdminMWs {
|
||||
const databaseSettings = <DataBaseConfig>req.body.settings;
|
||||
|
||||
try {
|
||||
if (databaseSettings.type == DatabaseType.mysql) {
|
||||
await MySQLConnection.tryConnection(databaseSettings);
|
||||
if (databaseSettings.type != DatabaseType.memory) {
|
||||
await SQLConnection.tryConnection(databaseSettings);
|
||||
}
|
||||
Config.Server.database = databaseSettings;
|
||||
//only updating explicitly set config (not saving config set by the diagnostics)
|
||||
@ -42,8 +42,8 @@ export class AdminMWs {
|
||||
Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t'));
|
||||
|
||||
ObjectManagerRepository.reset();
|
||||
if (Config.Server.database.type == DatabaseType.mysql) {
|
||||
await ObjectManagerRepository.InitMySQLManagers();
|
||||
if (Config.Server.database.type != DatabaseType.memory) {
|
||||
await ObjectManagerRepository.InitSQLManagers();
|
||||
} else {
|
||||
await ObjectManagerRepository.InitMemoryManagers();
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import {
|
||||
import {Logger} from "../Logger";
|
||||
import {NotificationManager} from "./NotifocationManager";
|
||||
import {ProjectPath} from "../ProjectPath";
|
||||
import {MySQLConnection} from "./mysql/MySQLConnection";
|
||||
import {SQLConnection} from "./sql/SQLConnection";
|
||||
import * as fs from "fs";
|
||||
import {ClientConfig} from "../../common/config/public/ConfigClass";
|
||||
|
||||
@ -17,8 +17,8 @@ const LOG_TAG = "[ConfigDiagnostics]";
|
||||
export class ConfigDiagnostics {
|
||||
|
||||
static async testDatabase(databaseConfig: DataBaseConfig) {
|
||||
if (databaseConfig.type == DatabaseType.mysql) {
|
||||
await MySQLConnection.tryConnection(databaseConfig);
|
||||
if (databaseConfig.type != DatabaseType.memory) {
|
||||
await SQLConnection.tryConnection(databaseConfig);
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,13 +112,13 @@ export class ConfigDiagnostics {
|
||||
|
||||
static async runDiagnostics() {
|
||||
|
||||
if (Config.Server.database.type == DatabaseType.mysql) {
|
||||
if (Config.Server.database.type != DatabaseType.memory) {
|
||||
try {
|
||||
await ConfigDiagnostics.testDatabase(Config.Server.database);
|
||||
} catch (err) {
|
||||
Logger.warn(LOG_TAG, "[MYSQL error]", err);
|
||||
Logger.warn(LOG_TAG, "Error during initializing mysql falling back temporally to memory DB");
|
||||
NotificationManager.warning("Error during initializing mysql falling back temporally to memory DB", err);
|
||||
Logger.warn(LOG_TAG, "[SQL error]", err);
|
||||
Logger.warn(LOG_TAG, "Error during initializing SQL falling back temporally to memory DB");
|
||||
NotificationManager.warning("Error during initializing SQL falling back temporally to memory DB", err);
|
||||
Config.setDatabaseType(DatabaseType.memory);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import {IUserManager} from "./interfaces/IUserManager";
|
||||
import {IGalleryManager} from "./interfaces/IGalleryManager";
|
||||
import {ISearchManager} from "./interfaces/ISearchManager";
|
||||
import {MySQLConnection} from "./mysql/MySQLConnection";
|
||||
import {SQLConnection} from "./sql/SQLConnection";
|
||||
import {ISharingManager} from "./interfaces/ISharingManager";
|
||||
import {Logger} from "../Logger";
|
||||
|
||||
@ -26,18 +26,18 @@ export class ObjectManagerRepository {
|
||||
ObjectManagerRepository.getInstance().SharingManager = new SharingManager();
|
||||
}
|
||||
|
||||
public static async InitMySQLManagers() {
|
||||
public static async InitSQLManagers() {
|
||||
await ObjectManagerRepository.reset();
|
||||
await MySQLConnection.init();
|
||||
const GalleryManager = require("./mysql/GalleryManager").GalleryManager;
|
||||
const UserManager = require("./mysql/UserManager").UserManager;
|
||||
const SearchManager = require("./mysql/SearchManager").SearchManager;
|
||||
const SharingManager = require("./mysql/SharingManager").SharingManager;
|
||||
await SQLConnection.init();
|
||||
const GalleryManager = require("./sql/GalleryManager").GalleryManager;
|
||||
const UserManager = require("./sql/UserManager").UserManager;
|
||||
const SearchManager = require("./sql/SearchManager").SearchManager;
|
||||
const SharingManager = require("./sql/SharingManager").SharingManager;
|
||||
ObjectManagerRepository.getInstance().GalleryManager = new GalleryManager();
|
||||
ObjectManagerRepository.getInstance().UserManager = new UserManager();
|
||||
ObjectManagerRepository.getInstance().SearchManager = new SearchManager();
|
||||
ObjectManagerRepository.getInstance().SharingManager = new SharingManager();
|
||||
Logger.debug("MySQL DB inited");
|
||||
Logger.debug("SQL DB inited");
|
||||
}
|
||||
|
||||
public static getInstance() {
|
||||
@ -48,7 +48,7 @@ export class ObjectManagerRepository {
|
||||
}
|
||||
|
||||
public static async reset() {
|
||||
await MySQLConnection.close();
|
||||
await SQLConnection.close();
|
||||
this._instance = null;
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ import {DirectoryDTO} from "../../../common/entities/DirectoryDTO";
|
||||
import * as path from "path";
|
||||
import * as fs from "fs";
|
||||
import {DirectoryEntity} from "./enitites/DirectoryEntity";
|
||||
import {MySQLConnection} from "./MySQLConnection";
|
||||
import {SQLConnection} from "./SQLConnection";
|
||||
import {DiskManager} from "../DiskManger";
|
||||
import {PhotoEntity, PhotoMetadataEntity} from "./enitites/PhotoEntity";
|
||||
import {Utils} from "../../../common/Utils";
|
||||
@ -19,7 +19,7 @@ export class GalleryManager implements IGalleryManager {
|
||||
relativeDirectoryName = path.normalize(path.join("." + path.sep, relativeDirectoryName));
|
||||
const directoryName = path.basename(relativeDirectoryName);
|
||||
const directoryParent = path.join(path.dirname(relativeDirectoryName), path.sep);
|
||||
const connection = await MySQLConnection.getConnection();
|
||||
const connection = await SQLConnection.getConnection();
|
||||
const stat = fs.statSync(path.join(ProjectPath.ImageFolder, relativeDirectoryName));
|
||||
const lastModified = Math.max(stat.ctime.getTime(), stat.mtime.getTime());
|
||||
let dir = await connection
|
||||
@ -95,7 +95,7 @@ export class GalleryManager implements IGalleryManager {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
const scannedDirectory = await DiskManager.scanDirectory(relativeDirectoryName);
|
||||
const connection = await MySQLConnection.getConnection();
|
||||
const connection = await SQLConnection.getConnection();
|
||||
|
||||
//returning with the result
|
||||
scannedDirectory.photos.forEach(p => p.readyThumbnails = []);
|
@ -1,16 +1,17 @@
|
||||
import "reflect-metadata";
|
||||
import {Connection, createConnection, getConnection} from "typeorm";
|
||||
import {Connection, createConnection, DriverOptions, getConnection} 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";
|
||||
import {SharingEntity} from "./enitites/SharingEntity";
|
||||
import {DataBaseConfig} from "../../../common/config/private/IPrivateConfig";
|
||||
import {DataBaseConfig, DatabaseType} from "../../../common/config/private/IPrivateConfig";
|
||||
import {PasswordHelper} from "../PasswordHelper";
|
||||
import {ProjectPath} from "../../ProjectPath";
|
||||
|
||||
|
||||
export class MySQLConnection {
|
||||
export class SQLConnection {
|
||||
|
||||
constructor() {
|
||||
|
||||
@ -22,16 +23,10 @@ export class MySQLConnection {
|
||||
public static async getConnection(): Promise<Connection> {
|
||||
|
||||
if (this.connection == null) {
|
||||
|
||||
this.connection = await createConnection({
|
||||
name: "main",
|
||||
driver: {
|
||||
type: "mysql",
|
||||
host: Config.Server.database.mysql.host,
|
||||
port: 3306,
|
||||
username: Config.Server.database.mysql.username,
|
||||
password: Config.Server.database.mysql.password,
|
||||
database: Config.Server.database.mysql.database
|
||||
},
|
||||
driver: this.getDriver(Config.Server.database),
|
||||
entities: [
|
||||
UserEntity,
|
||||
DirectoryEntity,
|
||||
@ -59,17 +54,30 @@ export class MySQLConnection {
|
||||
}
|
||||
const conn = await createConnection({
|
||||
name: "test",
|
||||
driver: {
|
||||
driver: this.getDriver(config)
|
||||
});
|
||||
await conn.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
private static getDriver(config: DataBaseConfig): DriverOptions {
|
||||
let driver: DriverOptions = null;
|
||||
if (config.type == DatabaseType.mysql) {
|
||||
driver = {
|
||||
type: "mysql",
|
||||
host: config.mysql.host,
|
||||
port: 3306,
|
||||
username: config.mysql.username,
|
||||
password: config.mysql.password,
|
||||
database: config.mysql.database
|
||||
}
|
||||
});
|
||||
await conn.close();
|
||||
return true;
|
||||
};
|
||||
} else if (config.type == DatabaseType.sqlite) {
|
||||
driver = {
|
||||
type: "sqlite",
|
||||
storage: ProjectPath.getAbsolutePath(config.sqlite.storage)
|
||||
};
|
||||
}
|
||||
return driver;
|
||||
}
|
||||
|
||||
public static async init(): Promise<void> {
|
@ -1,7 +1,7 @@
|
||||
import {AutoCompleteItem, SearchTypes} from "../../../common/entities/AutoCompleteItem";
|
||||
import {ISearchManager} from "../interfaces/ISearchManager";
|
||||
import {SearchResultDTO} from "../../../common/entities/SearchResultDTO";
|
||||
import {MySQLConnection} from "./MySQLConnection";
|
||||
import {SQLConnection} from "./SQLConnection";
|
||||
import {PhotoEntity} from "./enitites/PhotoEntity";
|
||||
import {DirectoryEntity} from "./enitites/DirectoryEntity";
|
||||
import {PositionMetaData} from "../../../common/entities/PhotoDTO";
|
||||
@ -10,7 +10,7 @@ export class SearchManager implements ISearchManager {
|
||||
|
||||
async autocomplete(text: string) {
|
||||
|
||||
const connection = await MySQLConnection.getConnection();
|
||||
const connection = await SQLConnection.getConnection();
|
||||
|
||||
let result: Array<AutoCompleteItem> = [];
|
||||
let photoRepository = connection.getRepository(PhotoEntity);
|
||||
@ -64,7 +64,7 @@ export class SearchManager implements ISearchManager {
|
||||
}
|
||||
|
||||
async search(text: string, searchType: SearchTypes) {
|
||||
const connection = await MySQLConnection.getConnection();
|
||||
const connection = await SQLConnection.getConnection();
|
||||
|
||||
let result: SearchResultDTO = <SearchResultDTO>{
|
||||
searchText: text,
|
||||
@ -119,7 +119,7 @@ export class SearchManager implements ISearchManager {
|
||||
}
|
||||
|
||||
async instantSearch(text: string) {
|
||||
const connection = await MySQLConnection.getConnection();
|
||||
const connection = await SQLConnection.getConnection();
|
||||
|
||||
let result: SearchResultDTO = <SearchResultDTO>{
|
||||
searchText: text,
|
@ -1,31 +1,21 @@
|
||||
import {ISharingManager} from "../interfaces/ISharingManager";
|
||||
import {SharingDTO} from "../../../common/entities/SharingDTO";
|
||||
import {MySQLConnection} from "./MySQLConnection";
|
||||
import {SQLConnection} from "./SQLConnection";
|
||||
import {SharingEntity} from "./enitites/SharingEntity";
|
||||
import {Config} from "../../../common/config/private/Config";
|
||||
import {PasswordHelper} from "../PasswordHelper";
|
||||
|
||||
export class SharingManager implements ISharingManager {
|
||||
|
||||
private async removeExpiredLink() {
|
||||
const connection = await MySQLConnection.getConnection();
|
||||
return connection
|
||||
.getRepository(SharingEntity)
|
||||
.createQueryBuilder("share")
|
||||
.where("expires < :now", {now: Date.now()})
|
||||
.delete()
|
||||
.execute();
|
||||
}
|
||||
|
||||
async findOne(filter: any): Promise<SharingDTO> {
|
||||
await this.removeExpiredLink();
|
||||
const connection = await MySQLConnection.getConnection();
|
||||
const connection = await SQLConnection.getConnection();
|
||||
return await connection.getRepository(SharingEntity).findOne(filter);
|
||||
}
|
||||
|
||||
async createSharing(sharing: SharingDTO): Promise<SharingDTO> {
|
||||
await this.removeExpiredLink();
|
||||
const connection = await MySQLConnection.getConnection();
|
||||
const connection = await SQLConnection.getConnection();
|
||||
if (sharing.password) {
|
||||
sharing.password = PasswordHelper.cryptPassword(sharing.password);
|
||||
}
|
||||
@ -35,7 +25,7 @@ export class SharingManager implements ISharingManager {
|
||||
}
|
||||
|
||||
async updateSharing(inSharing: SharingDTO): Promise<SharingDTO> {
|
||||
const connection = await MySQLConnection.getConnection();
|
||||
const connection = await SQLConnection.getConnection();
|
||||
|
||||
let sharing = await connection.getRepository(SharingEntity).findOne({
|
||||
id: inSharing.id,
|
||||
@ -54,5 +44,15 @@ export class SharingManager implements ISharingManager {
|
||||
return await connection.getRepository(SharingEntity).persist(sharing);
|
||||
}
|
||||
|
||||
private async removeExpiredLink() {
|
||||
const connection = await SQLConnection.getConnection();
|
||||
return connection
|
||||
.getRepository(SharingEntity)
|
||||
.createQueryBuilder("share")
|
||||
.where("expires < :now", {now: Date.now()})
|
||||
.delete()
|
||||
.execute();
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import {UserDTO, UserRoles} from "../../../common/entities/UserDTO";
|
||||
import {IUserManager} from "../interfaces/IUserManager";
|
||||
import {UserEntity} from "./enitites/UserEntity";
|
||||
import {MySQLConnection} from "./MySQLConnection";
|
||||
import {SQLConnection} from "./SQLConnection";
|
||||
import {PasswordHelper} from "../PasswordHelper";
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ export class UserManager implements IUserManager {
|
||||
|
||||
|
||||
public async findOne(filter: any) {
|
||||
const connection = await MySQLConnection.getConnection();
|
||||
const connection = await SQLConnection.getConnection();
|
||||
let pass = filter.password;
|
||||
delete filter.password;
|
||||
const user = (await connection.getRepository(UserEntity).findOne(filter));
|
||||
@ -29,7 +29,7 @@ export class UserManager implements IUserManager {
|
||||
};
|
||||
|
||||
public async find(filter: any) {
|
||||
const connection = await MySQLConnection.getConnection();
|
||||
const connection = await SQLConnection.getConnection();
|
||||
return (await connection.getRepository(UserEntity).find(filter)).map(user => {
|
||||
if (user.permissions && user.permissions != null) {
|
||||
user.permissions = <any>JSON.parse(<any>user.permissions);
|
||||
@ -39,7 +39,7 @@ export class UserManager implements IUserManager {
|
||||
}
|
||||
|
||||
public async createUser(user: UserDTO) {
|
||||
const connection = await MySQLConnection.getConnection();
|
||||
const connection = await SQLConnection.getConnection();
|
||||
if (user.permissions && user.permissions != null) {
|
||||
user.permissions = <any>JSON.stringify(<any>user.permissions);
|
||||
}
|
||||
@ -48,14 +48,14 @@ export class UserManager implements IUserManager {
|
||||
}
|
||||
|
||||
public async deleteUser(id: number) {
|
||||
const connection = await MySQLConnection.getConnection();
|
||||
const connection = await SQLConnection.getConnection();
|
||||
const user = await connection.getRepository(UserEntity).findOne({id: id});
|
||||
return await connection.getRepository(UserEntity).remove(user);
|
||||
}
|
||||
|
||||
public async changeRole(id: number, newRole: UserRoles) {
|
||||
|
||||
const connection = await MySQLConnection.getConnection();
|
||||
const connection = await SQLConnection.getConnection();
|
||||
let userRepository = connection.getRepository(UserEntity);
|
||||
const user = await userRepository.findOne({id: id});
|
||||
user.role = newRole;
|
@ -67,8 +67,8 @@ export class Server {
|
||||
|
||||
DiskManager.init();
|
||||
ThumbnailGeneratorMWs.init();
|
||||
if (Config.Server.database.type == DatabaseType.mysql) {
|
||||
await ObjectManagerRepository.InitMySQLManagers();
|
||||
if (Config.Server.database.type != DatabaseType.memory) {
|
||||
await ObjectManagerRepository.InitSQLManagers();
|
||||
} else {
|
||||
await ObjectManagerRepository.InitMemoryManagers();
|
||||
}
|
||||
|
@ -1,13 +1,14 @@
|
||||
import {ClientConfig} from "../public/ConfigClass";
|
||||
|
||||
export enum DatabaseType{
|
||||
memory = 0, mysql = 1
|
||||
export enum DatabaseType {
|
||||
memory = 0, mysql = 1, sqlite = 2
|
||||
}
|
||||
|
||||
export enum LogLevel {
|
||||
error, warn, info, debug, verbose
|
||||
}
|
||||
|
||||
export enum ThumbnailProcessingLib{
|
||||
export enum ThumbnailProcessingLib {
|
||||
Jimp = 0,
|
||||
gm = 1,
|
||||
sharp = 2
|
||||
@ -19,18 +20,27 @@ export interface MySQLConfig {
|
||||
username: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
export interface SQLiteConfig {
|
||||
storage: string;
|
||||
}
|
||||
|
||||
export interface DataBaseConfig {
|
||||
type: DatabaseType;
|
||||
mysql?: MySQLConfig;
|
||||
sqlite?: SQLiteConfig;
|
||||
}
|
||||
|
||||
export interface ThumbnailConfig {
|
||||
folder: string;
|
||||
processingLibrary: ThumbnailProcessingLib;
|
||||
qualityPriority: boolean;
|
||||
}
|
||||
|
||||
export interface SharingConfig {
|
||||
updateTimeout: number;
|
||||
}
|
||||
|
||||
export interface ServerConfig {
|
||||
port: number;
|
||||
imagesFolder: string;
|
||||
@ -42,6 +52,7 @@ export interface ServerConfig {
|
||||
folderPreviewSize: number;
|
||||
cachedFolderTimeout: number;//Do not rescans the folder if seems ok
|
||||
}
|
||||
|
||||
export interface IPrivateConfig {
|
||||
Server: ServerConfig;
|
||||
Client: ClientConfig.Config;
|
||||
|
@ -18,13 +18,16 @@ export class PrivateConfigClass extends PublicConfigClass implements IPrivateCon
|
||||
},
|
||||
sessionTimeout: 1000 * 60 * 60 * 24 * 7,
|
||||
database: {
|
||||
type: DatabaseType.mysql,
|
||||
type: DatabaseType.sqlite,
|
||||
mysql: {
|
||||
host: "",
|
||||
username: "",
|
||||
password: "",
|
||||
database: ""
|
||||
|
||||
},
|
||||
sqlite: {
|
||||
storage: "sqlite.db"
|
||||
}
|
||||
},
|
||||
sharing: {
|
||||
|
@ -10,6 +10,9 @@
|
||||
<option *ngFor="let type of types" [ngValue]="type.key">{{type.value}}
|
||||
</option>
|
||||
</select>
|
||||
<span *ngIf="settings.type == DatabaseType.mysql"
|
||||
class="help-block">Install manually mysql node module to use mysql (npm install mysql)</span>
|
||||
|
||||
<ng-container *ngIf="settings.type == DatabaseType.mysql">
|
||||
<p class="title">MySQL settings:</p>
|
||||
<input type="text" class="form-control" placeholder="Host" autofocus
|
||||
@ -21,6 +24,11 @@
|
||||
<input type="password" class="form-control" placeholder="Password"
|
||||
[(ngModel)]="settings.mysql.password" name="password">
|
||||
</ng-container>
|
||||
<ng-container *ngIf="settings.type == DatabaseType.sqlite">
|
||||
<p class="title">SQLie settings:</p>
|
||||
<input type="text" class="form-control" placeholder="storage" autofocus
|
||||
[(ngModel)]="settings.sqlite.storage" name="host" required>
|
||||
</ng-container>
|
||||
|
||||
</form>
|
||||
<button class="btn btn-success pull-right"
|
||||
|
@ -32,8 +32,8 @@
|
||||
"express": "4.15.3",
|
||||
"flat-file-db": "1.0.0",
|
||||
"jimp": "0.2.28",
|
||||
"mysql": "2.13.0",
|
||||
"reflect-metadata": "0.1.10",
|
||||
"sqlite3": "^3.1.8",
|
||||
"ts-exif-parser": "^0.1.23",
|
||||
"ts-node-iptc": "^1.0.9",
|
||||
"typeconfig": "1.0.4",
|
||||
|
Loading…
Reference in New Issue
Block a user