1
0
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:
Patrik Braun 2017-07-20 23:37:10 +02:00
parent 93ac783a09
commit 0618105857
17 changed files with 101 additions and 71 deletions

View File

@ -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();
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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 = []);

View File

@ -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> {

View File

@ -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,

View File

@ -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();
}
}

View File

@ -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;

View File

@ -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();
}

View File

@ -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;

View File

@ -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: {

View File

@ -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"

View File

@ -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",