mirror of
https://github.com/bpatrik/pigallery2.git
synced 2024-11-28 08:58:49 +02:00
Merge pull request #693 from bpatrik/sharing-history
Showing sharing history and preventing accidental sharing
This commit is contained in:
commit
d64670751c
@ -1,11 +1,11 @@
|
|||||||
import { NextFunction, Request, Response } from 'express';
|
import {NextFunction, Request, Response} from 'express';
|
||||||
import { CreateSharingDTO, SharingDTO } from '../../common/entities/SharingDTO';
|
import {CreateSharingDTO, SharingDTO} from '../../common/entities/SharingDTO';
|
||||||
import { ObjectManagers } from '../model/ObjectManagers';
|
import {ObjectManagers} from '../model/ObjectManagers';
|
||||||
import { ErrorCodes, ErrorDTO } from '../../common/entities/Error';
|
import {ErrorCodes, ErrorDTO} from '../../common/entities/Error';
|
||||||
import { Config } from '../../common/config/private/Config';
|
import {Config} from '../../common/config/private/Config';
|
||||||
import { QueryParams } from '../../common/QueryParams';
|
import {QueryParams} from '../../common/QueryParams';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { UserRoles } from '../../common/entities/UserDTO';
|
import {UserRoles} from '../../common/entities/UserDTO';
|
||||||
|
|
||||||
export class SharingMWs {
|
export class SharingMWs {
|
||||||
public static async getSharing(
|
public static async getSharing(
|
||||||
@ -20,9 +20,7 @@ export class SharingMWs {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
req.resultPipe =
|
req.resultPipe =
|
||||||
await ObjectManagers.getInstance().SharingManager.findOne({
|
await ObjectManagers.getInstance().SharingManager.findOne(sharingKey);
|
||||||
sharingKey,
|
|
||||||
});
|
|
||||||
return next();
|
return next();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return next(
|
return next(
|
||||||
@ -58,9 +56,7 @@ export class SharingMWs {
|
|||||||
// eslint-disable-next-line no-constant-condition
|
// eslint-disable-next-line no-constant-condition
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
await ObjectManagers.getInstance().SharingManager.findOne({
|
await ObjectManagers.getInstance().SharingManager.findOne(sharingKey);
|
||||||
sharingKey,
|
|
||||||
});
|
|
||||||
sharingKey = this.generateKey();
|
sharingKey = this.generateKey();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
break;
|
break;
|
||||||
@ -173,6 +169,13 @@ export class SharingMWs {
|
|||||||
const sharingKey: string = req.params['sharingKey'];
|
const sharingKey: string = req.params['sharingKey'];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// Check if user has the right to delete sharing.
|
||||||
|
if (req.session['user'].role < UserRoles.Admin) {
|
||||||
|
const s = await ObjectManagers.getInstance().SharingManager.findOne(sharingKey);
|
||||||
|
if (s.creator.id !== req.session['user'].id) {
|
||||||
|
return next(new ErrorDTO(ErrorCodes.NOT_AUTHORISED, 'Can\'t delete sharing.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
req.resultPipe =
|
req.resultPipe =
|
||||||
await ObjectManagers.getInstance().SharingManager.deleteSharing(
|
await ObjectManagers.getInstance().SharingManager.deleteSharing(
|
||||||
sharingKey
|
sharingKey
|
||||||
@ -213,6 +216,36 @@ export class SharingMWs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async listSharingForDir(
|
||||||
|
req: Request,
|
||||||
|
res: Response,
|
||||||
|
next: NextFunction
|
||||||
|
): Promise<void> {
|
||||||
|
if (Config.Sharing.enabled === false) {
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
const dir = path.normalize(req.params['directory'] || '/');
|
||||||
|
try {
|
||||||
|
if (req.session['user'].role >= UserRoles.Admin) {
|
||||||
|
req.resultPipe =
|
||||||
|
await ObjectManagers.getInstance().SharingManager.listAllForDir(dir);
|
||||||
|
} else {
|
||||||
|
req.resultPipe =
|
||||||
|
await ObjectManagers.getInstance().SharingManager.listAllForDir(dir, req.session['user']);
|
||||||
|
}
|
||||||
|
return next();
|
||||||
|
} catch (err) {
|
||||||
|
return next(
|
||||||
|
new ErrorDTO(
|
||||||
|
ErrorCodes.GENERAL_ERROR,
|
||||||
|
'Error during listing shares',
|
||||||
|
err
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static generateKey(): string {
|
private static generateKey(): string {
|
||||||
function s4(): string {
|
function s4(): string {
|
||||||
return Math.floor((1 + Math.random()) * 0x10000)
|
return Math.floor((1 + Math.random()) * 0x10000)
|
||||||
|
@ -151,11 +151,7 @@ export class AuthenticationMWs {
|
|||||||
const sharingKey: string =
|
const sharingKey: string =
|
||||||
(req.query[QueryParams.gallery.sharingKey_query] as string) ||
|
(req.query[QueryParams.gallery.sharingKey_query] as string) ||
|
||||||
(req.params[QueryParams.gallery.sharingKey_params] as string);
|
(req.params[QueryParams.gallery.sharingKey_params] as string);
|
||||||
const sharing = await ObjectManagers.getInstance().SharingManager.findOne(
|
const sharing = await ObjectManagers.getInstance().SharingManager.findOne(sharingKey);
|
||||||
{
|
|
||||||
sharingKey,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!sharing ||
|
!sharing ||
|
||||||
@ -264,11 +260,7 @@ export class AuthenticationMWs {
|
|||||||
const sharingKey: string =
|
const sharingKey: string =
|
||||||
(req.query[QueryParams.gallery.sharingKey_query] as string) ||
|
(req.query[QueryParams.gallery.sharingKey_query] as string) ||
|
||||||
(req.params[QueryParams.gallery.sharingKey_params] as string);
|
(req.params[QueryParams.gallery.sharingKey_params] as string);
|
||||||
const sharing = await ObjectManagers.getInstance().SharingManager.findOne(
|
const sharing = await ObjectManagers.getInstance().SharingManager.findOne(sharingKey);
|
||||||
{
|
|
||||||
sharingKey,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
if (!sharing || sharing.expires < Date.now()) {
|
if (!sharing || sharing.expires < Date.now()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,8 @@ import {SQLConnection} from './SQLConnection';
|
|||||||
import {SharingEntity} from './enitites/SharingEntity';
|
import {SharingEntity} from './enitites/SharingEntity';
|
||||||
import {Config} from '../../../common/config/private/Config';
|
import {Config} from '../../../common/config/private/Config';
|
||||||
import {PasswordHelper} from '../PasswordHelper';
|
import {PasswordHelper} from '../PasswordHelper';
|
||||||
import {DeleteResult, FindOptionsWhere} from 'typeorm';
|
import {DeleteResult, SelectQueryBuilder} from 'typeorm';
|
||||||
|
import {UserDTO} from '../../../common/entities/UserDTO';
|
||||||
|
|
||||||
export class SharingManager {
|
export class SharingManager {
|
||||||
private static async removeExpiredLink(): Promise<DeleteResult> {
|
private static async removeExpiredLink(): Promise<DeleteResult> {
|
||||||
@ -34,10 +35,29 @@ export class SharingManager {
|
|||||||
.getMany();
|
.getMany();
|
||||||
}
|
}
|
||||||
|
|
||||||
async findOne(filter: FindOptionsWhere<SharingDTO>): Promise<SharingDTO> {
|
|
||||||
|
async listAllForDir(dir: string, user?: UserDTO): Promise<SharingDTO[]> {
|
||||||
await SharingManager.removeExpiredLink();
|
await SharingManager.removeExpiredLink();
|
||||||
const connection = await SQLConnection.getConnection();
|
const connection = await SQLConnection.getConnection();
|
||||||
return await connection.getRepository(SharingEntity).findOneBy(filter);
|
const q: SelectQueryBuilder<SharingEntity> = connection
|
||||||
|
.getRepository(SharingEntity)
|
||||||
|
.createQueryBuilder('share')
|
||||||
|
.leftJoinAndSelect('share.creator', 'creator')
|
||||||
|
.where('path = :dir', {dir});
|
||||||
|
if (user) {
|
||||||
|
q.andWhere('share.creator = :user', {user: user.id});
|
||||||
|
}
|
||||||
|
return await q.getMany();
|
||||||
|
}
|
||||||
|
|
||||||
|
async findOne(sharingKey: string): Promise<SharingDTO> {
|
||||||
|
await SharingManager.removeExpiredLink();
|
||||||
|
const connection = await SQLConnection.getConnection();
|
||||||
|
return await connection.getRepository(SharingEntity)
|
||||||
|
.createQueryBuilder('share')
|
||||||
|
.leftJoinAndSelect('share.creator', 'creator')
|
||||||
|
.where('share.sharingKey = :sharingKey', {sharingKey})
|
||||||
|
.getOne();
|
||||||
}
|
}
|
||||||
|
|
||||||
async createSharing(sharing: SharingDTO): Promise<SharingDTO> {
|
async createSharing(sharing: SharingDTO): Promise<SharingDTO> {
|
||||||
|
@ -14,6 +14,7 @@ export class SharingRouter {
|
|||||||
this.addCreateSharing(app);
|
this.addCreateSharing(app);
|
||||||
this.addUpdateSharing(app);
|
this.addUpdateSharing(app);
|
||||||
this.addListSharing(app);
|
this.addListSharing(app);
|
||||||
|
this.addListSharingForDir(app);
|
||||||
this.addDeleteSharing(app);
|
this.addDeleteSharing(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,7 +65,7 @@ export class SharingRouter {
|
|||||||
app.delete(
|
app.delete(
|
||||||
[Config.Server.apiPath + '/share/:' + QueryParams.gallery.sharingKey_params],
|
[Config.Server.apiPath + '/share/:' + QueryParams.gallery.sharingKey_params],
|
||||||
AuthenticationMWs.authenticate,
|
AuthenticationMWs.authenticate,
|
||||||
AuthenticationMWs.authorise(UserRoles.Admin),
|
AuthenticationMWs.authorise(UserRoles.User),
|
||||||
SharingMWs.deleteSharing,
|
SharingMWs.deleteSharing,
|
||||||
ServerTimingMWs.addServerTiming,
|
ServerTimingMWs.addServerTiming,
|
||||||
RenderingMWs.renderResult
|
RenderingMWs.renderResult
|
||||||
@ -73,12 +74,25 @@ export class SharingRouter {
|
|||||||
|
|
||||||
private static addListSharing(app: express.Express): void {
|
private static addListSharing(app: express.Express): void {
|
||||||
app.get(
|
app.get(
|
||||||
[Config.Server.apiPath + '/share/list'],
|
[Config.Server.apiPath + '/share/listAll'],
|
||||||
AuthenticationMWs.authenticate,
|
AuthenticationMWs.authenticate,
|
||||||
AuthenticationMWs.authorise(UserRoles.User),
|
AuthenticationMWs.authorise(UserRoles.Admin),
|
||||||
SharingMWs.listSharing,
|
SharingMWs.listSharing,
|
||||||
ServerTimingMWs.addServerTiming,
|
ServerTimingMWs.addServerTiming,
|
||||||
RenderingMWs.renderSharingList
|
RenderingMWs.renderSharingList
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static addListSharingForDir(app: express.Express): void {
|
||||||
|
app.get(
|
||||||
|
[Config.Server.apiPath + '/share/list/:directory(*)',
|
||||||
|
Config.Server.apiPath + '/share/list//',
|
||||||
|
Config.Server.apiPath + '/share/list'],
|
||||||
|
AuthenticationMWs.authenticate,
|
||||||
|
AuthenticationMWs.authorise(UserRoles.User),
|
||||||
|
SharingMWs.listSharingForDir,
|
||||||
|
ServerTimingMWs.addServerTiming,
|
||||||
|
RenderingMWs.renderSharingList
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,8 @@ import {BehaviorSubject} from 'rxjs';
|
|||||||
import {distinctUntilChanged, filter} from 'rxjs/operators';
|
import {distinctUntilChanged, filter} from 'rxjs/operators';
|
||||||
import {QueryParams} from '../../../../common/QueryParams';
|
import {QueryParams} from '../../../../common/QueryParams';
|
||||||
import {UserDTO} from '../../../../common/entities/UserDTO';
|
import {UserDTO} from '../../../../common/entities/UserDTO';
|
||||||
|
import {Utils} from '../../../../common/Utils';
|
||||||
|
import {Config} from '../../../../common/config/public/Config';
|
||||||
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@ -61,6 +63,11 @@ export class ShareService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getUrl(share: SharingDTO): string {
|
||||||
|
return Utils.concatUrls(Config.Server.publicUrl, '/share/', share.sharingKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
onNewUser = async (user: UserDTO) => {
|
onNewUser = async (user: UserDTO) => {
|
||||||
if (user && !!user.usedSharingKey) {
|
if (user && !!user.usedSharingKey) {
|
||||||
if (
|
if (
|
||||||
@ -135,4 +142,23 @@ export class ShareService {
|
|||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async getSharingListForDir(
|
||||||
|
dir: string
|
||||||
|
): Promise<SharingDTO[]> {
|
||||||
|
return this.networkService.getJson('/share/list/' + dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,3 +24,12 @@ a.dropdown-item, button.dropdown-item, div.dropdown-item {
|
|||||||
a.dropdown-item span, button.dropdown-item span, div.dropdown-item span {
|
a.dropdown-item span, button.dropdown-item span, div.dropdown-item span {
|
||||||
padding-right: 0.8rem;
|
padding-right: 0.8rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a.list-shares-button {
|
||||||
|
cursor: pointer;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.list-shares-button:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
@ -28,16 +28,25 @@
|
|||||||
class="form-control input-md"
|
class="form-control input-md"
|
||||||
type="text"
|
type="text"
|
||||||
readonly
|
readonly
|
||||||
[disabled]="!shareForm.form.valid"
|
[disabled]="!shareForm.form.valid || !urlValid"
|
||||||
[ngModel]="shareForm.form.valid ? url: invalidSettings">
|
[ngModel]="shareForm.form.valid ? url: invalidSettings">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-5 col-sm-3">
|
<div class="col-5 col-sm-3">
|
||||||
<button id="copyButton" name="copyButton"
|
<button
|
||||||
ngxClipboard
|
*ngIf="!sharing"
|
||||||
[cbContent]="url"
|
id="getShareButton" name="getShareButton"
|
||||||
(cbOnSuccess)="onCopy()"
|
(click)="share()"
|
||||||
[disabled]="!shareForm.form.valid"
|
[disabled]="!shareForm.form.valid"
|
||||||
class="btn btn-primary btn-block" i18n>Copy
|
class="btn btn-primary btn-block float-end" i18n>Share
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
*ngIf="sharing"
|
||||||
|
id="copyButton" name="copyButton"
|
||||||
|
ngxClipboard
|
||||||
|
[cbContent]="url"
|
||||||
|
(cbOnSuccess)="onCopy()"
|
||||||
|
[disabled]="!shareForm.form.valid"
|
||||||
|
class="btn btn-primary btn-block float-end" i18n>Copy
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -118,4 +127,38 @@
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="modal-footer" *ngIf="activeShares && activeShares.length>0">
|
||||||
|
<a *ngIf="!showSharingList"
|
||||||
|
(click)="showSharingList = true"
|
||||||
|
class="list-shares-button m-0">
|
||||||
|
<span class="badge text-bg-secondary me-1">{{activeShares.length}}</span>
|
||||||
|
<ng-container i18n>active share(s) for this folder.
|
||||||
|
</ng-container>
|
||||||
|
<span class="oi oi-chevron-right ms-1"></span>
|
||||||
|
</a>
|
||||||
|
<table class="table table-hover table-sm" *ngIf="showSharingList">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th i18n>Sharing</th>
|
||||||
|
<th *ngIf="IsAdmin" i18n>Creator</th>
|
||||||
|
<th i18n>Expires</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr *ngFor="let share of activeShares">
|
||||||
|
<td><a [href]="sharingService.getUrl(share)">{{share.sharingKey}}</a></td>
|
||||||
|
<td *ngIf="IsAdmin">{{share.creator.name}}</td>
|
||||||
|
<td>{{share.expires | date}}</td>
|
||||||
|
<td>
|
||||||
|
<button (click)="deleteSharing(share)"
|
||||||
|
[disabled]="share.sharingKey == sharing?.sharingKey"
|
||||||
|
class="btn btn-danger float-end">
|
||||||
|
<span class="oi oi-trash" aria-hidden="true" aria-label="Delete"></span>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
@ -9,6 +9,9 @@ import {NotificationService} from '../../../model/notification.service';
|
|||||||
import {BsModalService} from 'ngx-bootstrap/modal';
|
import {BsModalService} from 'ngx-bootstrap/modal';
|
||||||
import {BsModalRef} from 'ngx-bootstrap/modal/bs-modal-ref.service';
|
import {BsModalRef} from 'ngx-bootstrap/modal/bs-modal-ref.service';
|
||||||
import {Subscription} from 'rxjs';
|
import {Subscription} from 'rxjs';
|
||||||
|
import {UserRoles} from '../../../../../common/entities/UserDTO';
|
||||||
|
import {AuthenticationService} from '../../../model/network/authentication.service';
|
||||||
|
import {ClipboardService} from 'ngx-clipboard';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-gallery-share',
|
selector: 'app-gallery-share',
|
||||||
@ -19,6 +22,8 @@ export class GalleryShareComponent implements OnInit, OnDestroy {
|
|||||||
enabled = true;
|
enabled = true;
|
||||||
@Input() dropDownItem = false;
|
@Input() dropDownItem = false;
|
||||||
url = '';
|
url = '';
|
||||||
|
urlValid = false;
|
||||||
|
showSharingList = false;
|
||||||
|
|
||||||
input = {
|
input = {
|
||||||
includeSubfolders: true,
|
includeSubfolders: true,
|
||||||
@ -37,24 +42,33 @@ export class GalleryShareComponent implements OnInit, OnDestroy {
|
|||||||
modalRef: BsModalRef;
|
modalRef: BsModalRef;
|
||||||
invalidSettings = $localize`Invalid settings`;
|
invalidSettings = $localize`Invalid settings`;
|
||||||
|
|
||||||
|
activeShares: SharingDTO[] = [];
|
||||||
|
|
||||||
text = {
|
text = {
|
||||||
Yes: 'Yes',
|
Yes: 'Yes',
|
||||||
No: 'No',
|
No: 'No',
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private sharingService: ShareService,
|
public sharingService: ShareService,
|
||||||
public galleryService: ContentService,
|
public galleryService: ContentService,
|
||||||
private notification: NotificationService,
|
private notification: NotificationService,
|
||||||
private modalService: BsModalService
|
private modalService: BsModalService,
|
||||||
|
public authService: AuthenticationService,
|
||||||
|
private clipboardService: ClipboardService
|
||||||
) {
|
) {
|
||||||
this.text.Yes = $localize`Yes`;
|
this.text.Yes = $localize`Yes`;
|
||||||
this.text.No = $localize`No`;
|
this.text.No = $localize`No`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get IsAdmin() {
|
||||||
|
return this.authService.user.value.role > UserRoles.Admin;
|
||||||
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.contentSubscription = this.galleryService.content.subscribe(
|
this.contentSubscription = this.galleryService.content.subscribe(
|
||||||
(content: ContentWrapper) => {
|
async (content: ContentWrapper) => {
|
||||||
|
this.activeShares = [];
|
||||||
this.enabled = !!content.directory;
|
this.enabled = !!content.directory;
|
||||||
if (!this.enabled) {
|
if (!this.enabled) {
|
||||||
return;
|
return;
|
||||||
@ -63,6 +77,7 @@ export class GalleryShareComponent implements OnInit, OnDestroy {
|
|||||||
content.directory.path,
|
content.directory.path,
|
||||||
content.directory.name
|
content.directory.name
|
||||||
);
|
);
|
||||||
|
await this.updateActiveSharesList();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -73,6 +88,21 @@ export class GalleryShareComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async deleteSharing(sharing: SharingDTO): Promise<void> {
|
||||||
|
await this.sharingService.deleteSharing(sharing);
|
||||||
|
await this.updateActiveSharesList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async updateActiveSharesList() {
|
||||||
|
try {
|
||||||
|
this.activeShares = await this.sharingService.getSharingListForDir(this.currentDir);
|
||||||
|
} catch (e) {
|
||||||
|
this.activeShares = [];
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
calcValidity(): number {
|
calcValidity(): number {
|
||||||
switch (parseInt(this.input.valid.type.toString(), 10)) {
|
switch (parseInt(this.input.valid.type.toString(), 10)) {
|
||||||
case ValidityTypes.Minutes:
|
case ValidityTypes.Minutes:
|
||||||
@ -93,6 +123,7 @@ export class GalleryShareComponent implements OnInit, OnDestroy {
|
|||||||
if (this.sharing == null) {
|
if (this.sharing == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this.urlValid = false;
|
||||||
this.url = $localize`loading..`;
|
this.url = $localize`loading..`;
|
||||||
this.sharing = await this.sharingService.updateSharing(
|
this.sharing = await this.sharingService.updateSharing(
|
||||||
this.currentDir,
|
this.currentDir,
|
||||||
@ -101,31 +132,37 @@ export class GalleryShareComponent implements OnInit, OnDestroy {
|
|||||||
this.input.password,
|
this.input.password,
|
||||||
this.calcValidity()
|
this.calcValidity()
|
||||||
);
|
);
|
||||||
this.url = Utils.concatUrls(Config.Server.publicUrl, '/share/', this.sharing.sharingKey);
|
this.urlValid = true;
|
||||||
|
this.url = this.sharingService.getUrl(this.sharing);
|
||||||
|
await this.updateActiveSharesList();
|
||||||
}
|
}
|
||||||
|
|
||||||
async get(): Promise<void> {
|
async get(): Promise<void> {
|
||||||
|
this.urlValid = false;
|
||||||
this.url = $localize`loading..`;
|
this.url = $localize`loading..`;
|
||||||
this.sharing = await this.sharingService.createSharing(
|
this.sharing = await this.sharingService.createSharing(
|
||||||
this.currentDir,
|
this.currentDir,
|
||||||
this.input.includeSubfolders,
|
this.input.includeSubfolders,
|
||||||
this.calcValidity()
|
this.calcValidity()
|
||||||
);
|
);
|
||||||
this.url = Utils.concatUrls(Config.Server.publicUrl, '/share/', this.sharing.sharingKey);
|
this.url = this.sharingService.getUrl(this.sharing);
|
||||||
|
this.urlValid = true;
|
||||||
|
await this.updateActiveSharesList();
|
||||||
}
|
}
|
||||||
|
|
||||||
async openModal(template: TemplateRef<unknown>): Promise<void> {
|
async openModal(template: TemplateRef<unknown>): Promise<void> {
|
||||||
await this.get();
|
this.url = $localize`Click share to get a link.`;
|
||||||
|
this.urlValid = false;
|
||||||
|
this.sharing = null;
|
||||||
this.input.password = '';
|
this.input.password = '';
|
||||||
if (this.modalRef) {
|
if (this.modalRef) {
|
||||||
this.modalRef.hide();
|
this.modalRef.hide();
|
||||||
}
|
}
|
||||||
this.modalRef = this.modalService.show(template);
|
this.modalRef = this.modalService.show(template);
|
||||||
document.body.style.paddingRight = '0px';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onCopy(): void {
|
onCopy(): void {
|
||||||
this.notification.success($localize`Url has been copied to clipboard`);
|
this.notification.success($localize`Sharing link has been copied to clipboard`);
|
||||||
}
|
}
|
||||||
|
|
||||||
public hideModal(): void {
|
public hideModal(): void {
|
||||||
@ -133,6 +170,16 @@ export class GalleryShareComponent implements OnInit, OnDestroy {
|
|||||||
this.modalRef = null;
|
this.modalRef = null;
|
||||||
this.sharing = null;
|
this.sharing = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async share() {
|
||||||
|
await this.get();
|
||||||
|
if (this.clipboardService.isSupported) {
|
||||||
|
this.clipboardService.copy(this.url);
|
||||||
|
this.onCopy();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,6 +11,9 @@ import {DefaultsJobs} from '../../../../common/entities/job/JobDTO';
|
|||||||
import {StatisticDTO} from '../../../../common/entities/settings/StatisticDTO';
|
import {StatisticDTO} from '../../../../common/entities/settings/StatisticDTO';
|
||||||
import {ScheduledJobsService} from './scheduled-jobs.service';
|
import {ScheduledJobsService} from './scheduled-jobs.service';
|
||||||
import {IWebConfigClassPrivate} from '../../../../../node_modules/typeconfig/src/decorators/class/IWebConfigClass';
|
import {IWebConfigClassPrivate} from '../../../../../node_modules/typeconfig/src/decorators/class/IWebConfigClass';
|
||||||
|
import {SharingDTO} from '../../../../common/entities/SharingDTO';
|
||||||
|
import {Utils} from '../../../../common/Utils';
|
||||||
|
import {Config} from '../../../../common/config/public/Config';
|
||||||
|
|
||||||
|
|
||||||
export enum ConfigStyle {
|
export enum ConfigStyle {
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
import {Injectable} from '@angular/core';
|
|
||||||
import {SharingDTO} from '../../../../../common/entities/SharingDTO';
|
|
||||||
import {NetworkService} from '../../../model/network/network.service';
|
|
||||||
import {SettingsService} from '../settings.service';
|
|
||||||
import {Config} from '../../../../../common/config/public/Config';
|
|
||||||
|
|
||||||
@Injectable({
|
|
||||||
providedIn: 'root'
|
|
||||||
})
|
|
||||||
export class SharingListService {
|
|
||||||
|
|
||||||
constructor(private networkService: NetworkService) {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public getSharingList(): Promise<SharingDTO[]> {
|
|
||||||
if (!Config.Sharing.enabled) {
|
|
||||||
return Promise.resolve([]);
|
|
||||||
}
|
|
||||||
return this.networkService.getJson('/share/list');
|
|
||||||
}
|
|
||||||
|
|
||||||
public deleteSharing(sharing: SharingDTO): Promise<void> {
|
|
||||||
return this.networkService.deleteJson('/share/' + sharing.sharingKey);
|
|
||||||
}
|
|
||||||
}
|
|
@ -20,7 +20,7 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr *ngFor="let share of shares">
|
<tr *ngFor="let share of shares">
|
||||||
<td><a [href]="sharingUrl + share.sharingKey">{{share.sharingKey}}</a></td>
|
<td><a [href]="sharingService.getUrl(share)">{{share.sharingKey}}</a></td>
|
||||||
<td>{{share.path}}</td>
|
<td>{{share.path}}</td>
|
||||||
<td>{{share.creator.name}}</td>
|
<td>{{share.creator.name}}</td>
|
||||||
<td>{{share.expires | date}}</td>
|
<td>{{share.expires | date}}</td>
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import {Component, OnInit} from '@angular/core';
|
import {Component, OnInit} from '@angular/core';
|
||||||
import {SharingDTO} from '../../../../../common/entities/SharingDTO';
|
import {SharingDTO} from '../../../../../common/entities/SharingDTO';
|
||||||
import {SharingListService} from './sharing-list.service';
|
|
||||||
import {SettingsService} from '../settings.service';
|
import {SettingsService} from '../settings.service';
|
||||||
import {Config} from '../../../../../common/config/public/Config';
|
import {ShareService} from '../../gallery/share.service';
|
||||||
import {Utils} from '../../../../../common/Utils';
|
import {AuthenticationService} from '../../../model/network/authentication.service';
|
||||||
|
import {UserRoles} from '../../../../../common/entities/UserDTO';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-settigns-sharings-list',
|
selector: 'app-settigns-sharings-list',
|
||||||
@ -13,10 +13,10 @@ import {Utils} from '../../../../../common/Utils';
|
|||||||
export class SharingsListComponent implements OnInit {
|
export class SharingsListComponent implements OnInit {
|
||||||
|
|
||||||
public shares: SharingDTO[] = [];
|
public shares: SharingDTO[] = [];
|
||||||
public sharingUrl = Utils.concatUrls(Config.Server.publicUrl, '/share') + '/';
|
|
||||||
|
|
||||||
constructor(public sharingList: SharingListService,
|
|
||||||
private settingsService: SettingsService) {
|
constructor(public sharingService: ShareService,
|
||||||
|
public settingsService: SettingsService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -29,13 +29,13 @@ export class SharingsListComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async deleteSharing(sharing: SharingDTO): Promise<void> {
|
async deleteSharing(sharing: SharingDTO): Promise<void> {
|
||||||
await this.sharingList.deleteSharing(sharing);
|
await this.sharingService.deleteSharing(sharing);
|
||||||
await this.getSharingList();
|
await this.getSharingList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getSharingList(): Promise<void> {
|
private async getSharingList(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
this.shares = await this.sharingList.getSharingList();
|
this.shares = await this.sharingService.getSharingList();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.shares = [];
|
this.shares = [];
|
||||||
throw err;
|
throw err;
|
||||||
|
@ -82,7 +82,7 @@ describe('SharingManager', (sqlHelper: DBTestHelper) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const saved = await sm.createSharing(sharing);
|
const saved = await sm.createSharing(sharing);
|
||||||
const found = await sm.findOne({sharingKey: 'testKey'});
|
const found = await sm.findOne('testKey');
|
||||||
|
|
||||||
expect(found.id).to.not.equals(null);
|
expect(found.id).to.not.equals(null);
|
||||||
expect(found.sharingKey).to.equals(sharing.sharingKey);
|
expect(found.sharingKey).to.equals(sharing.sharingKey);
|
||||||
|
Loading…
Reference in New Issue
Block a user