diff --git a/README.md b/README.md index 2501071..8da413d 100644 --- a/README.md +++ b/README.md @@ -63,12 +63,12 @@ To configure it. Run `PiGallery2` first to create `config.json` file, then edit * supporting several core CPU * supporting hardware acceleration ([sharp](https://github.com/lovell/sharp) and [gm](https://github.com/aheckmann/gm) as optional and JS-based [Jimp](https://github.com/oliver-moran/jimp) as fallback) * Custom lightbox for full screen photo viewing - * keyboard support for navigation - `In progress` + * keyboard support for navigation * showing low-res thumbnail while full image loads * Information panel for showing **Exif info** - `In progress` * Client side caching (directories and search results) * Rendering **photos** with GPS coordinates **on google map** - * .gpx file support - `In progress` + * .gpx file support - `future plan` * **Two modes: SQL database and no-database mode** * both modes supports * user management @@ -77,11 +77,11 @@ To configure it. Run `PiGallery2` first to create `config.json` file, then edit * faster directory listing * searching * instant search, auto complete - * sharing - `In progress` + * sharing * setting link expiration time * Nice design - `In progress` * responsive design (phone, tablet desktop support) * Setup page - `In progress` - * **Markdown based blogging support** - `In progress` + * **Markdown based blogging support** - `future plan` * you can write some note in the blog.md for every directory * bug free :) - `In progress` diff --git a/USERRIGHTS.md b/USERRIGHTS.md new file mode 100644 index 0000000..b773700 --- /dev/null +++ b/USERRIGHTS.md @@ -0,0 +1,7 @@ +# User rights + + * Limited Guest - list dir + * Guest - +search + * User - +share + * Admin - +settings + * Developer - +see errors diff --git a/backend/middlewares/GalleryMWs.ts b/backend/middlewares/GalleryMWs.ts index 70070a8..8e5431e 100644 --- a/backend/middlewares/GalleryMWs.ts +++ b/backend/middlewares/GalleryMWs.ts @@ -10,7 +10,7 @@ import {PhotoDTO} from "../../common/entities/PhotoDTO"; import {ProjectPath} from "../ProjectPath"; import {Logger} from "../Logger"; import {Config} from "../../common/config/private/Config"; -import {UserUtil} from "../../common/entities/UserDTO"; +import {UserDTO} from "../../common/entities/UserDTO"; const LOG_TAG = "[GalleryMWs]"; @@ -32,7 +32,7 @@ export class GalleryMWs { req.session.user.permissions.length > 0 && req.session.user.permissions[0] != "/") { directory.directories = directory.directories.filter(d => - UserUtil.isDirectoryAvailable(d, req.session.user.permissions)); + UserDTO.isDirectoryAvailable(d, req.session.user.permissions)); } req.resultPipe = new ContentWrapper(directory, null); return next(); diff --git a/backend/middlewares/user/AuthenticationMWs.ts b/backend/middlewares/user/AuthenticationMWs.ts index 05b6e4b..36f024f 100644 --- a/backend/middlewares/user/AuthenticationMWs.ts +++ b/backend/middlewares/user/AuthenticationMWs.ts @@ -1,7 +1,7 @@ /// import {NextFunction, Request, Response} from "express"; import {Error, ErrorCodes} from "../../../common/entities/Error"; -import {UserDTO, UserRoles, UserUtil} from "../../../common/entities/UserDTO"; +import {UserDTO, UserRoles} from "../../../common/entities/UserDTO"; import {ObjectManagerRepository} from "../../model/ObjectManagerRepository"; import {Config} from "../../../common/config/private/Config"; @@ -9,12 +9,15 @@ export class AuthenticationMWs { private static async getSharingUser(req: Request) { if (Config.Client.Sharing.enabled === true && - Config.Client.Sharing.passwordProtected === false && (!!req.query.sk || !!req.params.sharingKey)) { const sharing = await ObjectManagerRepository.getInstance().SharingManager.findOne({ sharingKey: req.query.sk || req.params.sharingKey, }); - if (!sharing) { + if (!sharing || sharing.expires < Date.now()) { + return null; + } + + if (Config.Client.Sharing.passwordProtected === true && sharing.password) { return null; } @@ -22,7 +25,7 @@ export class AuthenticationMWs { if (sharing.includeSubfolders == true) { path += "*"; } - return {name: "Guest", role: UserRoles.Guest, permissions: [path]}; + return {name: "Guest", role: UserRoles.LimitedGuest, permissions: [path]}; } return null; @@ -67,7 +70,7 @@ export class AuthenticationMWs { } const directoryName = req.params.directory || "/"; - if (UserUtil.isPathAvailable(directoryName, req.session.user.permissions) == true) { + if (UserDTO.isPathAvailable(directoryName, req.session.user.permissions) == true) { return next(); } @@ -117,6 +120,42 @@ export class AuthenticationMWs { } + + public static async shareLogin(req: Request, res: Response, next: NextFunction) { + + if (Config.Client.Sharing.enabled === false) { + return next(); + } + //not enough parameter + if ((!req.query.sk && !req.params.sharingKey)) { + return next(new Error(ErrorCodes.INPUT_ERROR)); + } + + try { + const password = (req.body ? req.body.password : null) || null; + + const sharing = await ObjectManagerRepository.getInstance().SharingManager.findOne({ + sharingKey: req.query.sk || req.params.sharingKey, + }); + if (!sharing || sharing.expires < Date.now() || + (Config.Client.Sharing.passwordProtected === true && sharing.password !== password)) { + return next(new Error(ErrorCodes.CREDENTIAL_NOT_FOUND)); + } + + let path = sharing.path; + if (sharing.includeSubfolders == true) { + path += "*"; + } + + req.session.user = {name: "Guest", role: UserRoles.LimitedGuest, permissions: [path]}; + return next(); + + } catch (err) { + return next(new Error(ErrorCodes.GENERAL_ERROR)); + } + + } + public static logout(req: Request, res: Response, next: NextFunction) { delete req.session.user; return next(); diff --git a/backend/model/memory/UserManager.ts b/backend/model/memory/UserManager.ts index 2545fae..9a9f8c8 100644 --- a/backend/model/memory/UserManager.ts +++ b/backend/model/memory/UserManager.ts @@ -34,7 +34,7 @@ export class UserManager implements IUserManager { this.createUser({name: "developer", password: "developer", role: UserRoles.Developer}); this.createUser({name: "admin", password: "admin", role: UserRoles.Admin}); this.createUser({name: "user", password: "user", role: UserRoles.User}); - this.createUser({name: "guest", password: "guest", role: UserRoles.Guest}); + this.createUser({name: "guest", password: "guest", role: UserRoles.LimitedGuest}); } diff --git a/backend/routes/GalleryRouter.ts b/backend/routes/GalleryRouter.ts index ceb3d90..14f2ea4 100644 --- a/backend/routes/GalleryRouter.ts +++ b/backend/routes/GalleryRouter.ts @@ -2,6 +2,7 @@ import {AuthenticationMWs} from "../middlewares/user/AuthenticationMWs"; import {GalleryMWs} from "../middlewares/GalleryMWs"; import {RenderingMWs} from "../middlewares/RenderingMWs"; import {ThumbnailGeneratorMWs} from "../middlewares/thumbnail/ThumbnailGeneratorMWs"; +import {UserRoles} from "../../common/entities/UserDTO"; export class GalleryRouter { public static route(app: any) { @@ -31,6 +32,7 @@ export class GalleryRouter { private static addGetImage(app) { app.get(["/api/gallery/content/:imagePath(*\.(jpg|bmp|png|gif|jpeg))"], AuthenticationMWs.authenticate, + //TODO: authorize path GalleryMWs.loadImage, RenderingMWs.renderFile ); @@ -39,6 +41,7 @@ export class GalleryRouter { private static addGetImageThumbnail(app) { app.get("/api/gallery/content/:imagePath(*\.(jpg|bmp|png|gif|jpeg))/thumbnail/:size?", AuthenticationMWs.authenticate, + //TODO: authorize path GalleryMWs.loadImage, ThumbnailGeneratorMWs.generateThumbnail, RenderingMWs.renderFile @@ -48,6 +51,7 @@ export class GalleryRouter { private static addGetImageIcon(app) { app.get("/api/gallery/content/:imagePath(*\.(jpg|bmp|png|gif|jpeg))/icon", AuthenticationMWs.authenticate, + //TODO: authorize path GalleryMWs.loadImage, ThumbnailGeneratorMWs.generateIcon, RenderingMWs.renderFile @@ -57,6 +61,7 @@ export class GalleryRouter { private static addSearch(app) { app.get("/api/search/:text", AuthenticationMWs.authenticate, + AuthenticationMWs.authorise(UserRoles.Guest), GalleryMWs.search, ThumbnailGeneratorMWs.addThumbnailInformation, GalleryMWs.removeCyclicDirectoryReferences, @@ -67,6 +72,7 @@ export class GalleryRouter { private static addInstantSearch(app) { app.get("/api/instant-search/:text", AuthenticationMWs.authenticate, + AuthenticationMWs.authorise(UserRoles.Guest), GalleryMWs.instantSearch, ThumbnailGeneratorMWs.addThumbnailInformation, GalleryMWs.removeCyclicDirectoryReferences, @@ -77,6 +83,7 @@ export class GalleryRouter { private static addAutoComplete(app) { app.get("/api/autocomplete/:text", AuthenticationMWs.authenticate, + AuthenticationMWs.authorise(UserRoles.Guest), GalleryMWs.autocomplete, RenderingMWs.renderResult ); diff --git a/backend/routes/SharingRouter.ts b/backend/routes/SharingRouter.ts index 1993c31..2a81447 100644 --- a/backend/routes/SharingRouter.ts +++ b/backend/routes/SharingRouter.ts @@ -6,15 +6,24 @@ import {SharingMWs} from "../middlewares/SharingMWs"; export class SharingRouter { public static route(app: any) { + this.addShareLogin(app); this.addGetSharing(app); this.addCreateSharing(app); this.addUpdateSharing(app); } + private static addShareLogin(app) { + app.post("/api/share/login", + AuthenticationMWs.inverseAuthenticate, + AuthenticationMWs.shareLogin, + RenderingMWs.renderSessionUser + ); + }; + private static addGetSharing(app) { app.get("/api/share/:sharingKey", AuthenticationMWs.authenticate, - AuthenticationMWs.authorise(UserRoles.Guest), + AuthenticationMWs.authorise(UserRoles.LimitedGuest), SharingMWs.getSharing, RenderingMWs.renderSharing ); diff --git a/common/config/public/Config.ts b/common/config/public/Config.ts index 453b5d4..1e3c245 100644 --- a/common/config/public/Config.ts +++ b/common/config/public/Config.ts @@ -8,7 +8,13 @@ declare module ServerInject { export let Config = new PublicConfigClass(); + if (typeof ServerInject !== "undefined" && typeof ServerInject.ConfigInject !== "undefined") { WebConfigLoader.loadFrontendConfig(Config.Client, ServerInject.ConfigInject); } + +if (Config.Client.publicUrl == "") { + Config.Client.publicUrl = location.origin; +} + diff --git a/common/config/public/ConfigClass.ts b/common/config/public/ConfigClass.ts index 6ddb6bc..a6c37cb 100644 --- a/common/config/public/ConfigClass.ts +++ b/common/config/public/ConfigClass.ts @@ -21,6 +21,7 @@ export interface ClientConfig { enableOnScrollThumbnailPrioritising: boolean; authenticationRequired: boolean; googleApiKey: string; + publicUrl: string; } /** @@ -46,7 +47,8 @@ export class PublicConfigClass { enableOnScrollRendering: true, enableOnScrollThumbnailPrioritising: true, authenticationRequired: true, - googleApiKey: "" + googleApiKey: "", + publicUrl: "" }; } diff --git a/common/entities/DirectoryDTO.ts b/common/entities/DirectoryDTO.ts index f095db6..fc58f09 100644 --- a/common/entities/DirectoryDTO.ts +++ b/common/entities/DirectoryDTO.ts @@ -10,8 +10,8 @@ export interface DirectoryDTO { photos: Array; } -export module DirectoryUtil { - export const addReferences = (dir: DirectoryDTO) => { +export module DirectoryDTO { + export const addReferences = (dir: DirectoryDTO): void => { dir.photos.forEach((photo: PhotoDTO) => { photo.directory = dir; }); diff --git a/common/entities/UserDTO.ts b/common/entities/UserDTO.ts index 4003661..f50eb75 100644 --- a/common/entities/UserDTO.ts +++ b/common/entities/UserDTO.ts @@ -1,8 +1,8 @@ import {DirectoryDTO} from "./DirectoryDTO"; import {Utils} from "../Utils"; export enum UserRoles{ - Guest = 0, - TrustedGuest = 1, + LimitedGuest = 0, + Guest = 1, User = 2, Admin = 3, Developer = 4, @@ -17,7 +17,7 @@ export interface UserDTO { permissions: string[]; //user can only see these permissions. if ends with *, its recursive } -export module UserUtil { +export module UserDTO { export const isPathAvailable = (path: string, permissions: string[]): boolean => { if (permissions == null || permissions.length == 0 || permissions[0] == "/") { diff --git a/frontend/app/app.component.ts b/frontend/app/app.component.ts index 61b8ce2..008663d 100644 --- a/frontend/app/app.component.ts +++ b/frontend/app/app.component.ts @@ -5,6 +5,7 @@ import {Router} from "@angular/router"; import {Config} from "../../common/config/public/Config"; import {Title} from "@angular/platform-browser"; import {NotificationService} from "./model/notification.service"; +import {ShareService} from "./gallery/share.service"; @Component({ @@ -16,23 +17,23 @@ export class AppComponent implements OnInit { constructor(private _router: Router, private _authenticationService: AuthenticationService, + private _shareService: ShareService, private _title: Title, vcr: ViewContainerRef, notificatin: NotificationService) { notificatin.setRootViewContainerRef(vcr); } - ngOnInit() { + async ngOnInit() { this._title.setTitle(Config.Client.applicationTitle); + await this._shareService.wait(); this._authenticationService.user.subscribe((user: UserDTO) => { - if (user != null) { - if (this._router.isActive('login', true)) { - console.log("routing"); - this._router.navigate(["gallery", ""]); + if (this._authenticationService.isAuthenticated()) { + if (this.isLoginPage()) { + return this.toGallery(); } } else { - if (!this._router.isActive('login', true)) { - console.log("routing"); - this._router.navigate(["login"]); + if (!this.isLoginPage()) { + return this.toLogin(); } } @@ -41,5 +42,23 @@ export class AppComponent implements OnInit { } + private isLoginPage() { + return this._router.isActive('login', true) || this._router.isActive('shareLogin', false); + } + private toLogin() { + if (this._shareService.isSharing()) { + return this._router.navigate(["shareLogin"], {queryParams: {sk: this._shareService.getSharingKey()}}); + } else { + return this._router.navigate(["login"]); + } + } + + private toGallery() { + if (this._shareService.isSharing()) { + return this._router.navigate(["share", this._shareService.getSharingKey()]); + } else { + return this._router.navigate(["gallery", ""]); + } + } } diff --git a/frontend/app/app.module.ts b/frontend/app/app.module.ts index fcfed53..84ef485 100644 --- a/frontend/app/app.module.ts +++ b/frontend/app/app.module.ts @@ -42,6 +42,9 @@ import {ToastModule} from "ng2-toastr/ng2-toastr"; import {BrowserAnimationsModule} from "@angular/platform-browser/animations"; import {NotificationService} from "./model/notification.service"; +import {ClipboardModule} from "ngx-clipboard"; +import {NavigationService} from "./model/navigation.service"; + @Injectable() export class GoogleMapsConfig { apiKey: string; @@ -58,6 +61,7 @@ export class GoogleMapsConfig { HttpModule, BrowserAnimationsModule, appRoutes, + ClipboardModule, ToastModule.forRoot(), ModalModule.forRoot(), AgmCoreModule.forRoot(), @@ -98,6 +102,7 @@ export class GoogleMapsConfig { ThumbnailManagerService, NotificationService, FullScreenService, + NavigationService, OverlayService], bootstrap: [AppComponent] diff --git a/frontend/app/gallery/cache.gallery.service.ts b/frontend/app/gallery/cache.gallery.service.ts index ffeff81..fb4705f 100644 --- a/frontend/app/gallery/cache.gallery.service.ts +++ b/frontend/app/gallery/cache.gallery.service.ts @@ -1,6 +1,6 @@ import {Injectable} from "@angular/core"; import {PhotoDTO} from "../../../common/entities/PhotoDTO"; -import {DirectoryDTO, DirectoryUtil} from "../../../common/entities/DirectoryDTO"; +import {DirectoryDTO} from "../../../common/entities/DirectoryDTO"; import {Utils} from "../../../common/Utils"; import {Config} from "../../../common/config/public/Config"; @@ -16,7 +16,7 @@ export class GalleryCacheService { if (value != null) { let directory: DirectoryDTO = JSON.parse(value); - DirectoryUtil.addReferences(directory); + DirectoryDTO.addReferences(directory); return directory; } return null; diff --git a/frontend/app/gallery/gallery.component.html b/frontend/app/gallery/gallery.component.html index 15dba22..4469858 100644 --- a/frontend/app/gallery/gallery.component.html +++ b/frontend/app/gallery/gallery.component.html @@ -2,6 +2,12 @@ + +
  • + +
  • diff --git a/frontend/app/gallery/gallery.component.ts b/frontend/app/gallery/gallery.component.ts index 72c378c..2f6d8dd 100644 --- a/frontend/app/gallery/gallery.component.ts +++ b/frontend/app/gallery/gallery.component.ts @@ -9,6 +9,9 @@ import {Config} from "../../../common/config/public/Config"; import {DirectoryDTO} from "../../../common/entities/DirectoryDTO"; import {SearchResultDTO} from "../../../common/entities/SearchResult"; import {ShareService} from "./share.service"; +import {NavigationService} from "../model/navigation.service"; +import {UserRoles} from "../../../common/entities/UserDTO"; +import {Observable} from "rxjs/Rx"; @Component({ selector: 'gallery', @@ -20,42 +23,61 @@ export class GalleryComponent implements OnInit, OnDestroy { @ViewChild(GallerySearchComponent) search: GallerySearchComponent; @ViewChild(GalleryGridComponent) grid: GalleryGridComponent; - public showSearchBar: boolean = true; - public showShare: boolean = true; + public showSearchBar: boolean = false; + public showShare: boolean = false; public directories: DirectoryDTO[] = []; public isPhotoWithLocation = false; + private $counter; private subscription = { content: null, - route: null + route: null, + timer: null }; + public countDown = null; constructor(public _galleryService: GalleryService, private _authService: AuthenticationService, private _router: Router, private shareService: ShareService, - private _route: ActivatedRoute) { + private _route: ActivatedRoute, + private _navigation: NavigationService) { - this.showSearchBar = Config.Client.Search.searchEnabled; - this.showShare = Config.Client.Sharing.enabled; } - - ngOnInit() { - if (!this._authService.isAuthenticated() && - (!this.shareService.isSharing() || - (this.shareService.isSharing() && Config.Client.Sharing.passwordProtected == true)) - ) { - if (this.shareService.isSharing()) { - this._router.navigate(['shareLogin']); - } else { - this._router.navigate(['login']); - } + updateTimer(t: number) { + if (this.shareService.sharing.value == null) { return; } + t = Math.floor((this.shareService.sharing.value.expires - Date.now()) / 1000); + this.countDown = {}; + this.countDown.day = Math.floor(t / 86400); + t -= this.countDown.day * 86400; + this.countDown.hour = Math.floor(t / 3600) % 24; + t -= this.countDown.hour * 3600; + this.countDown.minute = Math.floor(t / 60) % 60; + t -= this.countDown.minute * 60; + this.countDown.second = t % 60; + } + + async ngOnInit() { + await this.shareService.wait(); + if (!this._authService.isAuthenticated() && + (!this.shareService.isSharing() || + (this.shareService.isSharing() && Config.Client.Sharing.passwordProtected == true))) { + + return this._navigation.toLogin(); + } + this.showSearchBar = Config.Client.Search.searchEnabled && this._authService.isAuthorized(UserRoles.Guest); + this.showShare = Config.Client.Sharing.enabled && this._authService.isAuthorized(UserRoles.User); this.subscription.content = this._galleryService.content.subscribe(this.onContentChange); this.subscription.route = this._route.params.subscribe(this.onRoute); + if (this.shareService.isSharing()) { + this.$counter = Observable.interval(1000); + this.subscription.timer = this.$counter.subscribe((x) => this.updateTimer(x)); + } + } ngOnDestroy() { @@ -109,7 +131,7 @@ export class GalleryComponent implements OnInit, OnDestroy { } if (params['sharingKey'] && params['sharingKey'] != "") { - const sharing = await this._galleryService.getSharing(this.shareService.getSharingKey()); + const sharing = await this.shareService.getSharing(); this._router.navigate(['/gallery', sharing.path], {queryParams: {sk: this.shareService.getSharingKey()}}); return; } diff --git a/frontend/app/gallery/gallery.service.ts b/frontend/app/gallery/gallery.service.ts index dd239fd..8740252 100644 --- a/frontend/app/gallery/gallery.service.ts +++ b/frontend/app/gallery/gallery.service.ts @@ -1,7 +1,7 @@ import {Injectable} from "@angular/core"; import {NetworkService} from "../model/network/network.service"; import {ContentWrapper} from "../../../common/entities/ConentWrapper"; -import {DirectoryDTO, DirectoryUtil} from "../../../common/entities/DirectoryDTO"; +import {DirectoryDTO} from "../../../common/entities/DirectoryDTO"; import {SearchTypes} from "../../../common/entities/AutoCompleteItem"; import {GalleryCacheService} from "./cache.gallery.service"; import {BehaviorSubject} from "rxjs/BehaviorSubject"; @@ -53,7 +53,7 @@ export class GalleryService { } - DirectoryUtil.addReferences(cw.directory); + DirectoryDTO.addReferences(cw.directory); this.lastDirectory = cw.directory; diff --git a/frontend/app/gallery/navigator/navigator.gallery.component.ts b/frontend/app/gallery/navigator/navigator.gallery.component.ts index e60bd71..0a5ba02 100644 --- a/frontend/app/gallery/navigator/navigator.gallery.component.ts +++ b/frontend/app/gallery/navigator/navigator.gallery.component.ts @@ -1,7 +1,7 @@ import {Component, Input, OnChanges} from "@angular/core"; import {DirectoryDTO} from "../../../../common/entities/DirectoryDTO"; import {RouterLink} from "@angular/router"; -import {UserUtil} from "../../../../common/entities/UserDTO"; +import {UserDTO} from "../../../../common/entities/UserDTO"; import {AuthenticationService} from "../../model/network/authentication.service"; import {ShareService} from "../share.service"; @@ -49,7 +49,7 @@ export class GalleryNavigatorComponent implements OnChanges { if (dirs.length == 0) { arr.push({name: "Images", route: null}); } else { - arr.push({name: "Images", route: UserUtil.isPathAvailable("/", user.permissions) ? "/" : null}); + arr.push({name: "Images", route: UserDTO.isPathAvailable("/", user.permissions) ? "/" : null}); } @@ -59,7 +59,7 @@ export class GalleryNavigatorComponent implements OnChanges { if (dirs.length - 1 == index) { arr.push({name: name, route: null}); } else { - arr.push({name: name, route: UserUtil.isPathAvailable(route, user.permissions) ? route : null}); + arr.push({name: name, route: UserDTO.isPathAvailable(route, user.permissions) ? route : null}); } }); diff --git a/frontend/app/gallery/share.service.ts b/frontend/app/gallery/share.service.ts index 3d4e728..b81f290 100644 --- a/frontend/app/gallery/share.service.ts +++ b/frontend/app/gallery/share.service.ts @@ -2,10 +2,12 @@ import {Injectable} from "@angular/core"; import {NetworkService} from "../model/network/network.service"; import {CreateSharingDTO, SharingDTO} from "../../../common/entities/SharingDTO"; import {Router, RoutesRecognized} from "@angular/router"; +import {BehaviorSubject} from "rxjs/BehaviorSubject"; @Injectable() export class ShareService { + public sharing: BehaviorSubject; param = null; queryParam = null; sharingKey = null; @@ -15,7 +17,7 @@ export class ShareService { constructor(private _networkService: NetworkService, private router: Router) { - + this.sharing = new BehaviorSubject(null); this.ReadyPR = new Promise((resolve) => { if (this.inited == true) { return resolve(); @@ -27,7 +29,11 @@ export class ShareService { if (val instanceof RoutesRecognized) { this.param = val.state.root.firstChild.params["sharingKey"] || null; this.queryParam = val.state.root.firstChild.queryParams["sk"] || null; - this.sharingKey = this.param || this.queryParam; + const changed = this.sharingKey != this.param || this.queryParam; + if (changed) { + this.sharingKey = this.param || this.queryParam; + this.getSharing(); + } if (this.resolve) { this.resolve(); this.inited = true; @@ -43,7 +49,7 @@ export class ShareService { return this.ReadyPR; } - public getSharing(dir: string, includeSubfolders: boolean, valid: number): Promise { + public createSharing(dir: string, includeSubfolders: boolean, valid: number): Promise { return this._networkService.postJson("/share/" + dir, { createSharing: { includeSubfolders: includeSubfolders, @@ -70,4 +76,10 @@ export class ShareService { return this.sharingKey != null; } + + public async getSharing(): Promise { + const sharing = await this._networkService.getJson("/share/" + this.getSharingKey()); + this.sharing.next(sharing); + return sharing; + } } diff --git a/frontend/app/gallery/share/share.gallery.component.css b/frontend/app/gallery/share/share.gallery.component.css index c599d4e..1a1f01c 100644 --- a/frontend/app/gallery/share/share.gallery.component.css +++ b/frontend/app/gallery/share/share.gallery.component.css @@ -2,7 +2,11 @@ z-index: 9999; } -button { - padding-left: 0; - padding-right: 0; +.full-width { + width: 100%; +} + +.row { + padding-top: 1px; + padding-bottom: 1px; } diff --git a/frontend/app/gallery/share/share.gallery.component.html b/frontend/app/gallery/share/share.gallery.component.html index 8ce14af..b617610 100644 --- a/frontend/app/gallery/share/share.gallery.component.html +++ b/frontend/app/gallery/share/share.gallery.component.html @@ -1,70 +1,98 @@ - -