1
0
mirror of https://github.com/bpatrik/pigallery2.git synced 2025-02-11 13:53:28 +02:00

signaling docker sensitive options

This commit is contained in:
Patrik J. Braun 2020-02-07 23:32:41 +01:00
parent 04179f93b7
commit 2654dce9a1
14 changed files with 129 additions and 87 deletions

View File

@ -22,6 +22,8 @@ ENV NODE_ENV=production \
default-Server-Database-dbFolder=/app/data/db \ default-Server-Database-dbFolder=/app/data/db \
default-Server-Media-folder=/app/data/images \ default-Server-Media-folder=/app/data/images \
default-Server-Media-tempFolder=/app/data/tmp default-Server-Media-tempFolder=/app/data/tmp
# flagging dockerized environemnt
PI_DOCKER=true
# command line arg orverride the config.json with these settings # command line arg orverride the config.json with these settings
ENTRYPOINT ["node", "./src/backend/index", \ ENTRYPOINT ["node", "./src/backend/index", \
# after a extensive job (like video converting), pigallery calls gc, to clean up everthing as fast as possible # after a extensive job (like video converting), pigallery calls gc, to clean up everthing as fast as possible

View File

@ -20,6 +20,8 @@ ENV NODE_ENV=production \
default-Server-Database-dbFolder=/app/data/db \ default-Server-Database-dbFolder=/app/data/db \
default-Server-Media-folder=/app/data/images \ default-Server-Media-folder=/app/data/images \
default-Server-Media-tempFolder=/app/data/tmp default-Server-Media-tempFolder=/app/data/tmp
# flagging dockerized environemnt
PI_DOCKER=true
# command line arg orverride the config.json with these settings # command line arg orverride the config.json with these settings
ENTRYPOINT ["node", "./src/backend/index", \ ENTRYPOINT ["node", "./src/backend/index", \
# after a extensive job (like video converting), pigallery calls gc, to clean up everthing as fast as possible # after a extensive job (like video converting), pigallery calls gc, to clean up everthing as fast as possible

View File

@ -49,10 +49,6 @@ export class Server {
Logger.info(LOG_TAG, 'running diagnostics...'); Logger.info(LOG_TAG, 'running diagnostics...');
await ConfigDiagnostics.runDiagnostics(); await ConfigDiagnostics.runDiagnostics();
Logger.verbose(LOG_TAG, 'using config:'); Logger.verbose(LOG_TAG, 'using config:');
Config.Client.appVersion = require('../../package.json').version;
Config.Client.buildTime = require('../../package.json').buildTime;
Config.Client.buildCommitHash = require('../../package.json').buildCommitHash;
Config.Client.upTime = (new Date()).toISOString();
Logger.verbose(LOG_TAG, JSON.stringify(Config, null, '\t')); Logger.verbose(LOG_TAG, JSON.stringify(Config, null, '\t'));
this.app = _express(); this.app = _express();

View File

@ -6,6 +6,8 @@ import {ConfigClass, ConfigClassBuilder} from 'typeconfig/node';
import {ConfigProperty, IConfigClass} from 'typeconfig/common'; import {ConfigProperty, IConfigClass} from 'typeconfig/common';
declare const process: any;
@ConfigClass({ @ConfigClass({
configPath: path.join(__dirname, './../../../../config.json'), configPath: path.join(__dirname, './../../../../config.json'),
saveIfNotExist: true, saveIfNotExist: true,
@ -40,8 +42,15 @@ export class PrivateConfigClass implements IPrivateConfig {
crypto.randomBytes(256).toString('hex'), crypto.randomBytes(256).toString('hex'),
crypto.randomBytes(256).toString('hex')]; crypto.randomBytes(256).toString('hex')];
} }
this.Server.Environment.appVersion = require('../../../../package.json').version;
this.Server.Environment.buildTime = require('../../../../package.json').buildTime;
this.Server.Environment.buildCommitHash = require('../../../../package.json').buildCommitHash;
this.Server.Environment.upTime = (new Date()).toISOString();
this.Server.Environment.isDocker = !!process.env['PI_DOCKER'];
} }
async original(): Promise<PrivateConfigClass & IConfigClass> { async original(): Promise<PrivateConfigClass & IConfigClass> {
const pc = ConfigClassBuilder.attachInterface(new PrivateConfigClass()); const pc = ConfigClassBuilder.attachInterface(new PrivateConfigClass());
await pc.load(); await pc.load();

View File

@ -291,8 +291,24 @@ export module ServerConfig {
} }
@SubConfigClass()
export class EnvironmentConfig {
@ConfigProperty({volatile: true})
upTime: string;
@ConfigProperty({volatile: true})
appVersion: string;
@ConfigProperty({volatile: true})
buildTime: string;
@ConfigProperty({volatile: true})
buildCommitHash: string;
@ConfigProperty({volatile: true})
isDocker: boolean;
}
@SubConfigClass() @SubConfigClass()
export class Config { export class Config {
@ConfigProperty({volatile: true})
Environment: EnvironmentConfig = new EnvironmentConfig();
@ConfigProperty({arrayType: 'string'}) @ConfigProperty({arrayType: 'string'})
sessionSecret: string[] = []; sessionSecret: string[] = [];
@ConfigProperty({type: 'unsignedInt', envAlias: 'PORT', min: 0, max: 65535}) @ConfigProperty({type: 'unsignedInt', envAlias: 'PORT', min: 0, max: 65535})

View File

@ -153,15 +153,6 @@ export module ClientConfig {
@SubConfigClass() @SubConfigClass()
export class Config { export class Config {
@ConfigProperty({volatile: true})
upTime: string;
@ConfigProperty({volatile: true})
appVersion: string;
@ConfigProperty({volatile: true})
buildTime: string;
@ConfigProperty({volatile: true})
buildCommitHash: string;
@ConfigProperty() @ConfigProperty()
applicationTitle: string = 'PiGallery 2'; applicationTitle: string = 'PiGallery 2';
@ConfigProperty() @ConfigProperty()

View File

@ -1,3 +1,14 @@
<ng-template #popTemplate>
<span i18n>Application version</span>: v{{(settingsService.settings | async).Server.Environment.appVersion}}
<ng-container *ngIf="(settingsService.settings | async).Server.Environment.buildTime">
<br/>
<span i18n>Built at</span>: {{(settingsService.settings | async).Server.Environment.buildTime | date:'medium' }}
</ng-container>
<ng-container *ngIf="(settingsService.settings | async).Server.Environment.buildCommitHash">
<br/>
<span i18n>Git commit</span>: {{(settingsService.settings | async).Server.Environment.buildCommitHash}}
</ng-container>
</ng-template>
<app-frame> <app-frame>
<div body class="container-fluid"> <div body class="container-fluid">
@ -22,9 +33,16 @@
</div> </div>
<div class="form-horizontal"> <div class="form-horizontal">
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
<a title="{{versionExtra}}" class="version" href="https://github.com/bpatrik/pigallery2/releases"> <div>
<span i18n>App version:</span>&nbsp;v<span>{{appVersion}}</span> <a triggers="mouseenter:mouseleave"
</a> placement="bottom"
[popover]="popTemplate"
class="version"
href="https://github.com/bpatrik/pigallery2/releases">
<span
i18n>App version:</span>&nbsp;<span>{{'v'+((settingsService.settings | async).Server.Environment.appVersion || '----')}}</span>
</a>
</div>
<div class="form-group"> <div class="form-group">
<label class="control-label align-self-end mr-2" for="simplifiedMode" i18n>Mode</label> <label class="control-label align-self-end mr-2" for="simplifiedMode" i18n>Mode</label>
<bSwitch <bSwitch
@ -115,7 +133,7 @@
<div class="col-12"> <div class="col-12">
<div class="text-right"> <div class="text-right">
<ng-container i18n>Up time</ng-container><!-- <ng-container i18n>Up time</ng-container><!--
-->: {{upTime | date:'medium'}} -->: {{(settingsService.settings | async).Server.Environment.upTime | date:'medium'}}
</div> </div>
</div> </div>
</div> </div>

View File

@ -5,10 +5,9 @@ import {NotificationService} from '../../model/notification.service';
import {NotificationType} from '../../../../common/entities/NotificationDTO'; import {NotificationType} from '../../../../common/entities/NotificationDTO';
import {NavigationService} from '../../model/navigation.service'; import {NavigationService} from '../../model/navigation.service';
import {I18n} from '@ngx-translate/i18n-polyfill'; import {I18n} from '@ngx-translate/i18n-polyfill';
import {Config} from '../../../../common/config/public/Config';
import {ISettingsComponent} from '../settings/_abstract/ISettingsComponent'; import {ISettingsComponent} from '../settings/_abstract/ISettingsComponent';
import {PageHelper} from '../../model/page.helper'; import {PageHelper} from '../../model/page.helper';
import {formatDate} from '@angular/common'; import {SettingsService} from '../settings/settings.service';
@Component({ @Component({
selector: 'app-admin', selector: 'app-admin',
@ -17,9 +16,6 @@ import {formatDate} from '@angular/common';
}) })
export class AdminComponent implements OnInit, AfterViewInit { export class AdminComponent implements OnInit, AfterViewInit {
simplifiedMode = true; simplifiedMode = true;
appVersion = Config.Client.appVersion;
versionExtra = '';
upTime = Config.Client.upTime;
@ViewChildren('setting') settingsComponents: QueryList<ISettingsComponent>; @ViewChildren('setting') settingsComponents: QueryList<ISettingsComponent>;
@ViewChildren('setting', {read: ElementRef}) settingsComponentsElemRef: QueryList<ElementRef>; @ViewChildren('setting', {read: ElementRef}) settingsComponentsElemRef: QueryList<ElementRef>;
contents: ISettingsComponent[] = []; contents: ISettingsComponent[] = [];
@ -27,16 +23,9 @@ export class AdminComponent implements OnInit, AfterViewInit {
constructor(private _authService: AuthenticationService, constructor(private _authService: AuthenticationService,
private _navigation: NavigationService, private _navigation: NavigationService,
public notificationService: NotificationService, public notificationService: NotificationService,
public settingsService: SettingsService,
@Inject(LOCALE_ID) private locale: string, @Inject(LOCALE_ID) private locale: string,
public i18n: I18n) { public i18n: I18n) {
if (Config.Client.buildTime) {
this.versionExtra = i18n('Built at') + ': ' + formatDate(Config.Client.buildTime, 'medium', locale);
}
if (Config.Client.buildCommitHash) {
this.versionExtra += ', ' + i18n('git hash') + ': ' + Config.Client.buildCommitHash;
}
} }
ngAfterViewInit(): void { ngAfterViewInit(): void {

View File

@ -1,64 +1,67 @@
<ng-template #popTemplate i18n>
It seems that you are running the application in a Docker container.
This setting should not be changed in docker.
Make sure, that you know what you are doing.
</ng-template>
<ng-container *ngIf="state"> <ng-container *ngIf="state">
<div class="form-group row" *ngIf="!state.isEnumType && state.type !== 'boolean'" <div class="form-group row"
[class.changed-settings]="changed" [class.changed-settings]="changed"
[class.docker-warning]="dockerWarning"
[hidden]="shouldHide"> [hidden]="shouldHide">
<label class="col-md-2 control-label" [for]="idName">{{name}}</label> <label class="col-md-2 control-label" [for]="idName">{{name}}</label>
<div class="col-md-10"> <div class="col-md-10">
<input [type]="type" [min]="state.min" [max]="state.max" class="form-control" [placeholder]="PlaceHolder"
[title]="title"
[(ngModel)]="value"
(ngModelChange)="onChange($event)"
[name]="idName"
[disabled]="state.readonly || _disabled"
[id]="idName"
required="required">
<small class="form-text text-muted" *ngIf="description">{{description}}
</small>
</div>
</div>
<div class="form-group row" *ngIf="state.isEnumType === true"
[class.changed-settings]="changed"
[hidden]="shouldHide">
<label class="col-md-2 control-label" [for]="idName">{{name}}</label>
<div class="col-md-10">
<select [id]="idName"
[name]="idName"
[title]="title"
(ngModelChange)="onChange($event)"
[disabled]="state.readonly || _disabled"
class="form-control" [(ngModel)]="state.value">
<option *ngFor="let opt of _options" [ngValue]="opt.key">{{opt.value}}
</option>
</select>
<small class="form-text text-muted" *ngIf="description">{{description}}
</small>
<ng-content></ng-content>
</div>
</div>
<div class="form-group row" *ngIf="state.type === 'boolean'" <div class="input-group">
[class.changed-settings]="changed" <input
[hidden]="shouldHide"> *ngIf="!state.isEnumType && state.type !== 'boolean'"
<label class="col-md-2 control-label" [for]="idName">{{name}}</label> [type]="type" [min]="state.min" [max]="state.max" class="form-control" [placeholder]="PlaceHolder"
<div class="col-md-10"> [title]="title"
<bSwitch [(ngModel)]="value"
class="switch" (ngModelChange)="onChange($event)"
[id]="idName" [name]="idName"
[name]="idName" [disabled]="state.readonly || _disabled"
[title]="title" [id]="idName"
[disabled]="state.readonly || _disabled" required="required">
switch-on-color="primary"
switch-inverse="true"
switch-off-text="Disabled"
switch-on-text="Enabled"
i18n-switch-off-text
i18n-switch-on-text
switch-handle-width="100"
switch-label-width="20"
(ngModelChange)="onChange($event)"
[(ngModel)]="state.value">
</bSwitch>
<select
*ngIf="state.isEnumType === true"
[id]="idName"
[name]="idName"
[title]="title"
(ngModelChange)="onChange($event)"
[disabled]="state.readonly || _disabled"
class="form-control" [(ngModel)]="state.value">
<option *ngFor="let opt of _options" [ngValue]="opt.key">{{opt.value}}
</option>
</select>
<bSwitch
*ngIf="state.type === 'boolean'"
class="switch"
[id]="idName"
[name]="idName"
[title]="title"
[disabled]="state.readonly || _disabled"
switch-on-color="primary"
switch-inverse="true"
switch-off-text="Disabled"
switch-on-text="Enabled"
i18n-switch-off-text
i18n-switch-on-text
switch-handle-width="100"
switch-label-width="20"
(ngModelChange)="onChange($event)"
[(ngModel)]="state.value">
</bSwitch>
<div class="input-group-append">
<span
triggers="mouseenter:mouseleave"
placement="bottom"
[popover]="popTemplate"
class="oi oi-warning text-warning warning-icon ml-2" *ngIf="dockerWarning && changed"></span>
</div>
</div>
<small class="form-text text-muted" *ngIf="description">{{description}} <small class="form-text text-muted" *ngIf="description">{{description}}
</small> </small>
<ng-content></ng-content> <ng-content></ng-content>

View File

@ -26,6 +26,7 @@ export class SettingsEntryComponent implements ControlValueAccessor, Validator,
@Input() name: string; @Input() name: string;
@Input() required: boolean; @Input() required: boolean;
@Input() dockerWarning: boolean;
@Input() optionMap: (v: { key: number, value: string }) => { key: number, value: string }; @Input() optionMap: (v: { key: number, value: string }) => { key: number, value: string };
@Input() placeholder: string; @Input() placeholder: string;
@Input() options: { key: number | string, value: number | string }[]; @Input() options: { key: number | string, value: number | string }[];

View File

@ -1,7 +1,7 @@
.changed-settings input, .changed-settings select { .changed-settings input, .changed-settings select {
border-color: #007bff; border-color: #007bff;
border-width: 1.5px; border-width: 1px;
} }
.changed-settings label { .changed-settings label {
@ -9,3 +9,15 @@
font-weight: bold; font-weight: bold;
} }
.changed-settings.docker-warning label {
color: #ffc107;
}
.changed-settings.docker-warning select, .changed-settings.docker-warning input {
border-color: #ffc107;
}
.warning-icon {
font-size: x-large;
margin-top: 5px;
}

View File

@ -33,6 +33,7 @@
i18n-description i18n-name i18n-description i18n-name
[ngModel]="states.port" [ngModel]="states.port"
required="true" required="true"
[dockerWarning]="(_settingsService.Settings | async).Server.Environment.isDocker"
[simplifiedMode]="simplifiedMode"> [simplifiedMode]="simplifiedMode">
</app-settings-entry> </app-settings-entry>
@ -43,6 +44,7 @@
placeholder="path" placeholder="path"
i18n-description i18n-name i18n-description i18n-name
required required
[dockerWarning]="(_settingsService.Settings | async).Server.Environment.isDocker"
[ngModel]="states.imagesFolder"> [ngModel]="states.imagesFolder">
</app-settings-entry> </app-settings-entry>
@ -54,6 +56,7 @@
placeholder="path" placeholder="path"
i18n-description i18n-name i18n-description i18n-name
required="true" required="true"
[dockerWarning]="(_settingsService.Settings | async).Server.Environment.isDocker"
[ngModel]="states.tempFolder"> [ngModel]="states.tempFolder">
</app-settings-entry> </app-settings-entry>

View File

@ -22,6 +22,7 @@
description="All file-based data will be stored here (sqlite database, user database in case of memory db, job history data)" description="All file-based data will be stored here (sqlite database, user database in case of memory db, job history data)"
[ngModel]="states.dbFolder" [ngModel]="states.dbFolder"
i18n-name i18n-description i18n-name i18n-description
[dockerWarning]="(_settingsService.Settings | async).Server.Environment.isDocker"
required="true"> required="true">
</app-settings-entry> </app-settings-entry>

View File

@ -12,6 +12,7 @@ export class SettingsService {
constructor(private _networkService: NetworkService) { constructor(private _networkService: NetworkService) {
this.settings = new BehaviorSubject<WebConfig>(new WebConfig()); this.settings = new BehaviorSubject<WebConfig>(new WebConfig());
this.getSettings().catch(console.error);
} }
public async getSettings(): Promise<void> { public async getSettings(): Promise<void> {
@ -28,6 +29,4 @@ export class SettingsService {
} }
this.fetchingSettings = false; this.fetchingSettings = false;
} }
} }