admin
This commit is contained in:
parent
31f6295833
commit
55b1af9242
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1,5 @@
|
|||||||
|
/images/
|
||||||
|
|
||||||
target/
|
target/
|
||||||
!.mvn/wrapper/maven-wrapper.jar
|
!.mvn/wrapper/maven-wrapper.jar
|
||||||
!**/src/main/**/target/
|
!**/src/main/**/target/
|
||||||
|
|||||||
@ -5,7 +5,7 @@ spring.datasource.driverClassName=org.h2.Driver
|
|||||||
spring.datasource.username=sa
|
spring.datasource.username=sa
|
||||||
spring.datasource.password=password
|
spring.datasource.password=password
|
||||||
#-
|
#-
|
||||||
spring.jpa.hibernate.ddl-auto=create
|
#spring.jpa.hibernate.ddl-auto=create
|
||||||
#-
|
#-
|
||||||
spring.jackson.serialization.indent_output=true
|
spring.jackson.serialization.indent_output=true
|
||||||
#-
|
#-
|
||||||
|
|||||||
10
src/main/angular/src/app/admin.service.ts
Normal file
10
src/main/angular/src/app/admin.service.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import {Injectable} from '@angular/core';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class AdminService {
|
||||||
|
|
||||||
|
password: string = "";
|
||||||
|
|
||||||
|
}
|
||||||
7
src/main/angular/src/app/admin/admin.component.html
Normal file
7
src/main/angular/src/app/admin/admin.component.html
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<input type="password" [(ngModel)]="adminService.password">
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<div class="button buttonGoTo" routerLink="/gallery">
|
||||||
|
Zur Galerie →
|
||||||
|
</div>
|
||||||
4
src/main/angular/src/app/admin/admin.component.less
Normal file
4
src/main/angular/src/app/admin/admin.component.less
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
input {
|
||||||
|
border: 1px solid red;
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
23
src/main/angular/src/app/admin/admin.component.ts
Normal file
23
src/main/angular/src/app/admin/admin.component.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import {Component} from '@angular/core';
|
||||||
|
import {FormsModule} from '@angular/forms';
|
||||||
|
import {AdminService} from '../admin.service';
|
||||||
|
import {RouterLink} from '@angular/router';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-admin',
|
||||||
|
imports: [
|
||||||
|
FormsModule,
|
||||||
|
RouterLink
|
||||||
|
],
|
||||||
|
templateUrl: './admin.component.html',
|
||||||
|
styleUrl: './admin.component.less'
|
||||||
|
})
|
||||||
|
export class AdminComponent {
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
readonly adminService: AdminService,
|
||||||
|
) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,3 +1,5 @@
|
|||||||
|
<div routerLink="admin" class="admin">Admin</div>
|
||||||
|
|
||||||
<div id="title" class="coloredText">
|
<div id="title" class="coloredText">
|
||||||
<div>Isabell⚭Timo</div>
|
<div>Isabell⚭Timo</div>
|
||||||
<div>09. August 2025</div>
|
<div>09. August 2025</div>
|
||||||
|
|||||||
@ -4,3 +4,9 @@
|
|||||||
font-size: 150%;
|
font-size: 150%;
|
||||||
margin-bottom: @space;
|
margin-bottom: @space;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.admin {
|
||||||
|
font-size: 50%;
|
||||||
|
color: gray;
|
||||||
|
margin: calc(@space / 2);
|
||||||
|
}
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { RouterOutlet } from '@angular/router';
|
import {RouterLink, RouterOutlet} from '@angular/router';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
imports: [RouterOutlet],
|
imports: [RouterOutlet, RouterLink],
|
||||||
templateUrl: './app.component.html',
|
templateUrl: './app.component.html',
|
||||||
styleUrl: './app.component.less'
|
styleUrl: './app.component.less'
|
||||||
})
|
})
|
||||||
|
|||||||
@ -2,8 +2,10 @@ import {Routes} from '@angular/router';
|
|||||||
import {UploadComponent} from './upload/upload.component';
|
import {UploadComponent} from './upload/upload.component';
|
||||||
import {GalleryComponent} from './gallery/gallery.component';
|
import {GalleryComponent} from './gallery/gallery.component';
|
||||||
import {PendingChangesGuard} from './upload/pending.guard';
|
import {PendingChangesGuard} from './upload/pending.guard';
|
||||||
|
import {AdminComponent} from './admin/admin.component';
|
||||||
|
|
||||||
export const routes: Routes = [
|
export const routes: Routes = [
|
||||||
|
{path: 'admin', component: AdminComponent},
|
||||||
{path: 'gallery', component: GalleryComponent},
|
{path: 'gallery', component: GalleryComponent},
|
||||||
{path: '', component: UploadComponent, canDeactivate: [PendingChangesGuard]},
|
{path: '', component: UploadComponent, canDeactivate: [PendingChangesGuard]},
|
||||||
{path: '**', redirectTo: ''},
|
{path: '**', redirectTo: ''},
|
||||||
|
|||||||
@ -1,11 +1,16 @@
|
|||||||
import {orNull, validateDate, validateString} from '../validators';
|
import {orNull, validateBoolean, validateDate, validateString} from '../validators';
|
||||||
|
|
||||||
export class Picture {
|
export class Picture {
|
||||||
|
|
||||||
|
static trackBy(_: number, picture: Picture) {
|
||||||
|
return picture.uuid;
|
||||||
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
readonly uuid: string,
|
readonly uuid: string,
|
||||||
readonly originalDate: Date | null,
|
readonly originalDate: Date | null,
|
||||||
readonly uploadDate: Date,
|
readonly uploadDate: Date,
|
||||||
|
readonly visible: boolean,
|
||||||
) {
|
) {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
@ -15,6 +20,7 @@ export class Picture {
|
|||||||
validateString(json.uuid),
|
validateString(json.uuid),
|
||||||
orNull(json.originalDate, validateDate),
|
orNull(json.originalDate, validateDate),
|
||||||
validateDate(json.uploadDate),
|
validateDate(json.uploadDate),
|
||||||
|
validateBoolean(json.visible),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="images" *ngIf="pictures.length > 0">
|
<div id="images" *ngIf="pictures.length > 0">
|
||||||
<img [src]="pictureUrl(picture)" *ngFor="let picture of sorted()" alt="" loading="lazy">
|
<img [src]="pictureUrl(picture)" *ngFor="let picture of sorted(); trackBy: Picture.trackBy" alt="" loading="lazy" (click)="toggleVisible(picture)" [class.hiddenBorder]="!picture.visible">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="noImages" *ngIf="pictures.length === 0">
|
<div class="noImages" *ngIf="pictures.length === 0">
|
||||||
|
|||||||
@ -10,3 +10,8 @@ img {
|
|||||||
.noImages {
|
.noImages {
|
||||||
margin: calc(5 * @space) 0;
|
margin: calc(5 * @space) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hiddenBorder {
|
||||||
|
border: 0.25em solid red;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|||||||
@ -16,6 +16,8 @@ import {PictureService} from './picture.service';
|
|||||||
})
|
})
|
||||||
export class GalleryComponent implements OnInit {
|
export class GalleryComponent implements OnInit {
|
||||||
|
|
||||||
|
protected readonly Picture = Picture;
|
||||||
|
|
||||||
protected pictures: Picture[] = [];
|
protected pictures: Picture[] = [];
|
||||||
|
|
||||||
protected sortByUpload: boolean = true;
|
protected sortByUpload: boolean = true;
|
||||||
@ -27,7 +29,7 @@ export class GalleryComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.pictureService.all(list => this.pictures = list);
|
this.pictureService.all(list => this.update(list));
|
||||||
}
|
}
|
||||||
|
|
||||||
pictureUrl(picture: Picture): string {
|
pictureUrl(picture: Picture): string {
|
||||||
@ -38,4 +40,12 @@ export class GalleryComponent implements OnInit {
|
|||||||
return this.pictures.sort(this.sortByUpload ? Picture.byUploadDateDesc : Picture.byOriginalDateDesc);
|
return this.pictures.sort(this.sortByUpload ? Picture.byUploadDateDesc : Picture.byOriginalDateDesc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleVisible(picture: Picture) {
|
||||||
|
this.pictureService.toggleVisible(picture, list => this.update(list));
|
||||||
|
}
|
||||||
|
|
||||||
|
private update(list: Picture[]) {
|
||||||
|
this.pictures = list;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import {Injectable} from "@angular/core";
|
|||||||
import {HttpClient} from "@angular/common/http";
|
import {HttpClient} from "@angular/common/http";
|
||||||
import {map} from "rxjs";
|
import {map} from "rxjs";
|
||||||
import {Picture} from "./Picture";
|
import {Picture} from "./Picture";
|
||||||
|
import {AdminService} from '../admin.service';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@ -12,12 +13,13 @@ export class PictureService {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
readonly http: HttpClient,
|
readonly http: HttpClient,
|
||||||
|
readonly adminService: AdminService,
|
||||||
) {
|
) {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
all(next: (list: Picture[]) => any): void {
|
all(next: (list: Picture[]) => any): void {
|
||||||
this.http.get<any[]>(this.apiUrl("http", ['Picture', 'all'])).pipe(map(list => list.map(Picture.fromJson))).subscribe(next);
|
this.http.post<any[]>(this.apiUrl("http", ['Picture', 'all']), this.adminService.password).pipe(map(list => list.map(Picture.fromJson))).subscribe(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
upload(file: File, success: () => any, error: () => any): void {
|
upload(file: File, success: () => any, error: () => any): void {
|
||||||
@ -26,7 +28,15 @@ export class PictureService {
|
|||||||
this.http.post(this.apiUrl("http", ['Picture', 'upload']), form).subscribe({next: success, error: error});
|
this.http.post(this.apiUrl("http", ['Picture', 'upload']), form).subscribe({next: success, error: error});
|
||||||
}
|
}
|
||||||
|
|
||||||
apiUrl(protocol: string, path: string[]): string {
|
toggleVisible(picture: Picture, next: (list: Picture[]) => any) {
|
||||||
|
if (!this.adminService.password) {
|
||||||
|
throw new Error("You are not logged in.");
|
||||||
|
}
|
||||||
|
this.http.post<any[]>(this.apiUrl("http", ['Picture', picture.uuid, 'visible', !picture.visible]), this.adminService.password).pipe(map(list => list.map(Picture.fromJson))).subscribe(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
apiUrl(protocol: string, path: any[]): string {
|
||||||
|
// return `${protocol}${this.secure}://${location.hostname}:8084/${path.join('/')}`;
|
||||||
return `${protocol}${this.secure}://${location.hostname}/api/${path.join('/')}`;
|
return `${protocol}${this.secure}://${location.hostname}/api/${path.join('/')}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,13 @@ export function validateString(value: any) {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function validateBoolean(value: any) {
|
||||||
|
if (!(typeof value === 'boolean')) {
|
||||||
|
throw new Error("Not a boolean: " + JSON.stringify(value));
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
export function validateDate(value: any): Date {
|
export function validateDate(value: any): Date {
|
||||||
const date = new Date(Date.parse(validateString(value)));
|
const date = new Date(Date.parse(validateString(value)));
|
||||||
if (!date) {
|
if (!date) {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
@import "config";
|
@import "config";
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-size: 3vh;
|
font-size: 2.8vh;
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
|||||||
@ -1,54 +0,0 @@
|
|||||||
package de.ph87.isabell_und_timo.picture;
|
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import lombok.NonNull;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
import org.springframework.web.server.ResponseStatusException;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
@CrossOrigin
|
|
||||||
@RestController
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
@RequestMapping("PictureAdmin")
|
|
||||||
public class PictureAdminController {
|
|
||||||
|
|
||||||
private final PictureService pictureService;
|
|
||||||
|
|
||||||
private final PictureRepository pictureRepository;
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@GetMapping("visible")
|
|
||||||
public String visible(@NonNull final HttpServletRequest request) {
|
|
||||||
verifyLocal(request);
|
|
||||||
return pictureRepository
|
|
||||||
.findAllDtoByVisibleTrue()
|
|
||||||
.stream()
|
|
||||||
.map(p -> "<a href='/PictureAdmin/%s/visible/false'><img src='/Picture/%s/preview' loading='lazy' alt='%s' style='width: 100%%;'></a>\n".formatted(p.uuid, p.uuid, p.uuid))
|
|
||||||
.collect(Collectors.joining("\n"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// @GetMapping("{uuid}/visible/{visible}")
|
|
||||||
// public void visible(@PathVariable @NonNull final String uuid, @PathVariable final boolean visible, @NonNull final HttpServletRequest request, @NonNull final HttpServletResponse response) throws IOException {
|
|
||||||
// verifyLocal(request);
|
|
||||||
// pictureService.visible(uuid, visible);
|
|
||||||
// response.sendRedirect(request.get);
|
|
||||||
// }
|
|
||||||
|
|
||||||
private static void verifyLocal(final HttpServletRequest request) {
|
|
||||||
if (!request.getRemoteAddr().startsWith("10.") && !request.getRemoteAddr().equals("127.0.0.1")) {
|
|
||||||
throw new ResponseStatusException(HttpStatus.NOT_FOUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -23,6 +23,7 @@ import org.springframework.web.bind.annotation.CrossOrigin;
|
|||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestHeader;
|
import org.springframework.web.bind.annotation.RequestHeader;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
@ -65,22 +66,34 @@ public class PictureController {
|
|||||||
return factory.createMultipartConfig();
|
return factory.createMultipartConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isAdmin(@Nullable final String password) {
|
||||||
|
return password != null && password.equals("IbPAadstIT25!");
|
||||||
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@GetMapping("all")
|
@PostMapping("all")
|
||||||
public List<PictureDto> all() {
|
public List<PictureDto> all(@RequestBody(required = false) final String password) {
|
||||||
|
if (isAdmin(password)) {
|
||||||
|
return pictureRepository.findAllDto();
|
||||||
|
}
|
||||||
return pictureRepository.findAllDtoByVisibleTrue();
|
return pictureRepository.findAllDtoByVisibleTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@PostMapping("{uuid}/visible/{visible}")
|
||||||
|
public List<PictureDto> visible(@PathVariable @NonNull final String uuid, @PathVariable final boolean visible, @RequestBody(required = false) final String password) {
|
||||||
|
if (isAdmin(password)) {
|
||||||
|
pictureService.visible(uuid, visible);
|
||||||
|
}
|
||||||
|
return all(password);
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("{uuid}/preview")
|
@GetMapping("{uuid}/preview")
|
||||||
public void preview(@PathVariable @NonNull final String uuid, @NonNull final HttpServletRequest request, @NonNull final HttpServletResponse response) throws IOException {
|
public void preview(@PathVariable @NonNull final String uuid, @NonNull final HttpServletRequest request, @NonNull final HttpServletResponse response) throws IOException {
|
||||||
final PictureInternal pictureDto = pictureRepository.findDtoByUuid(uuid).orElseThrow(() -> {
|
final PictureInternal pictureDto = pictureRepository.findDtoByUuid(uuid).orElseThrow(() -> {
|
||||||
log.warn("Tried accessing NON-EXISTENT picture: {}", request);
|
log.warn("Tried accessing NON-EXISTENT picture: {}", request);
|
||||||
return new ResponseStatusException(HttpStatus.NOT_FOUND);
|
return new ResponseStatusException(HttpStatus.NOT_FOUND);
|
||||||
});
|
});
|
||||||
if (!pictureDto.visible) {
|
|
||||||
log.warn("Tried accessing INVISIBLE picture: {}", request);
|
|
||||||
throw new ResponseStatusException(HttpStatus.NOT_FOUND);
|
|
||||||
}
|
|
||||||
try (final FileInputStream input = new FileInputStream(pictureDto.getPreviewPath().toFile())) {
|
try (final FileInputStream input = new FileInputStream(pictureDto.getPreviewPath().toFile())) {
|
||||||
response.getOutputStream().write(input.readAllBytes());
|
response.getOutputStream().write(input.readAllBytes());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,10 +18,13 @@ public class PictureDto {
|
|||||||
@NonNull
|
@NonNull
|
||||||
public final ZonedDateTime uploadDate;
|
public final ZonedDateTime uploadDate;
|
||||||
|
|
||||||
|
public final boolean visible;
|
||||||
|
|
||||||
public PictureDto(@NonNull final Picture picture) {
|
public PictureDto(@NonNull final Picture picture) {
|
||||||
this.uuid = picture.getUuid();
|
this.uuid = picture.getUuid();
|
||||||
this.originalDate = picture.getOriginalDate();
|
this.originalDate = picture.getOriginalDate();
|
||||||
this.uploadDate = picture.getUploadDate();
|
this.uploadDate = picture.getUploadDate();
|
||||||
|
this.visible = picture.isVisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,10 @@ import java.util.Optional;
|
|||||||
|
|
||||||
public interface PictureRepository extends ListCrudRepository<Picture, String> {
|
public interface PictureRepository extends ListCrudRepository<Picture, String> {
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Query("select new de.ph87.isabell_und_timo.picture.PictureDto(p) from Picture p")
|
||||||
|
List<PictureDto> findAllDto();
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Query("select new de.ph87.isabell_und_timo.picture.PictureDto(p) from Picture p where p.visible = true")
|
@Query("select new de.ph87.isabell_und_timo.picture.PictureDto(p) from Picture p where p.visible = true")
|
||||||
List<PictureDto> findAllDtoByVisibleTrue();
|
List<PictureDto> findAllDtoByVisibleTrue();
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import jakarta.annotation.Nullable;
|
|||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
@ -19,8 +18,6 @@ public class PictureService {
|
|||||||
|
|
||||||
private final PictureRepository pictureRepository;
|
private final PictureRepository pictureRepository;
|
||||||
|
|
||||||
private final ResourcePatternResolver resourcePatternResolver;
|
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Transactional
|
@Transactional
|
||||||
public PictureInternal create(
|
public PictureInternal create(
|
||||||
@ -41,9 +38,11 @@ public class PictureService {
|
|||||||
return new PictureInternal(picture);
|
return new PictureInternal(picture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
public void visible(final @NonNull String uuid, final boolean visible) {
|
public void visible(final @NonNull String uuid, final boolean visible) {
|
||||||
final Picture picture = pictureRepository.findById(uuid).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
|
final Picture picture = pictureRepository.findById(uuid).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
|
||||||
picture.setVisible(visible);
|
picture.setVisible(visible);
|
||||||
|
log.info("Visible: {}", picture);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user