Just push
This commit is contained in:
@@ -106,6 +106,12 @@
|
|||||||
<version>6.5.0</version>
|
<version>6.5.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hibernate.validator</groupId>
|
||||||
|
<artifactId>hibernate-validator</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ public class SecurityConfig {
|
|||||||
)
|
)
|
||||||
.authorizeHttpRequests(auth -> auth
|
.authorizeHttpRequests(auth -> auth
|
||||||
.requestMatchers(new AntPathRequestMatcher("/api/auth/**")).permitAll()
|
.requestMatchers(new AntPathRequestMatcher("/api/auth/**")).permitAll()
|
||||||
.requestMatchers(new AntPathRequestMatcher("/h2-console/**")).permitAll()
|
.requestMatchers(new AntPathRequestMatcher("/api/notes/*")).permitAll()
|
||||||
.requestMatchers(new AntPathRequestMatcher("/error")).permitAll()
|
.requestMatchers(new AntPathRequestMatcher("/error")).permitAll()
|
||||||
.anyRequest().authenticated()
|
.anyRequest().authenticated()
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -14,12 +14,14 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.http.HttpEntity;
|
import org.springframework.http.HttpEntity;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
|
@Validated
|
||||||
@RequestMapping("/auth")
|
@RequestMapping("/auth")
|
||||||
public class AuthController {
|
public class AuthController {
|
||||||
|
|
||||||
@@ -38,7 +40,6 @@ public class AuthController {
|
|||||||
return ResponseEntity.ok(response);
|
return ResponseEntity.ok(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@PostMapping("/new-root")
|
@PostMapping("/new-root")
|
||||||
public ResponseEntity<RootResponse> newRoot() {
|
public ResponseEntity<RootResponse> newRoot() {
|
||||||
RootResponse response = authService.registerRoot();
|
RootResponse response = authService.registerRoot();
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
package net.tokishu.note.controller;
|
package net.tokishu.note.controller;
|
||||||
|
|
||||||
|
import jakarta.validation.Valid;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import net.tokishu.note.dto.request.NoteRequest;
|
import net.tokishu.note.dto.request.NoteRequest;
|
||||||
import net.tokishu.note.dto.response.NoteResponse;
|
import net.tokishu.note.dto.response.NoteResponse;
|
||||||
import net.tokishu.note.service.NoteService;
|
import net.tokishu.note.service.NoteService;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -14,6 +16,7 @@ import java.util.UUID;
|
|||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@RestController
|
@RestController
|
||||||
|
@Validated
|
||||||
@RequestMapping("/notes")
|
@RequestMapping("/notes")
|
||||||
public class NotesController {
|
public class NotesController {
|
||||||
|
|
||||||
@@ -24,19 +27,19 @@ public class NotesController {
|
|||||||
return ResponseEntity.ok(noteService.getAll());
|
return ResponseEntity.ok(noteService.getAll());
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/{uuid}")
|
@GetMapping("/{idOrCode}")
|
||||||
public NoteResponse find(@PathVariable UUID uuid){
|
public NoteResponse find(@PathVariable String idOrCode) {
|
||||||
return noteService.find(uuid);
|
return noteService.findByIdOrPublicLink(idOrCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping()
|
@PostMapping()
|
||||||
public ResponseEntity<Map<String, String>> add(@RequestBody NoteRequest note){
|
public ResponseEntity<Map<String, String>> add(@RequestBody @Valid NoteRequest note){
|
||||||
noteService.add(note);
|
noteService.add(note);
|
||||||
return ResponseEntity.status(HttpStatus.CREATED).body(Map.of("message", "Note added"));
|
return ResponseEntity.status(HttpStatus.CREATED).body(Map.of("message", "Note added"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping("/{uuid}")
|
@PutMapping("/{uuid}")
|
||||||
public ResponseEntity<?> update(@PathVariable("uuid") UUID uuid, @RequestBody NoteRequest note){
|
public ResponseEntity<?> update(@PathVariable("uuid") UUID uuid, @RequestBody @Valid NoteRequest note){
|
||||||
noteService.update(uuid, note);
|
noteService.update(uuid, note);
|
||||||
return ResponseEntity.ok(Map.of("message", "Note updated"));
|
return ResponseEntity.ok(Map.of("message", "Note updated"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package net.tokishu.note.dto.request;
|
package net.tokishu.note.dto.request;
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
import jakarta.validation.constraints.Size;
|
import jakarta.validation.constraints.Size;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@@ -13,4 +14,7 @@ public class NoteRequest {
|
|||||||
@NotBlank
|
@NotBlank
|
||||||
@Size(min=1, max=8192)
|
@Size(min=1, max=8192)
|
||||||
private String text;
|
private String text;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private Boolean isPublic;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ public class NoteResponse {
|
|||||||
private UUID uuid;
|
private UUID uuid;
|
||||||
private String name;
|
private String name;
|
||||||
private String text;
|
private String text;
|
||||||
|
private Boolean isPublic;
|
||||||
|
private String publicLink;
|
||||||
private String author;
|
private String author;
|
||||||
private LocalDateTime createdAt;
|
private LocalDateTime createdAt;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import jakarta.servlet.http.HttpServletRequest;
|
|||||||
import net.tokishu.note.dto.response.ApiErrorResponse;
|
import net.tokishu.note.dto.response.ApiErrorResponse;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.http.converter.HttpMessageNotReadableException;
|
import org.springframework.http.converter.HttpMessageNotReadableException;
|
||||||
|
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
import org.springframework.web.server.ResponseStatusException;
|
import org.springframework.web.server.ResponseStatusException;
|
||||||
@@ -12,48 +13,58 @@ import org.springframework.web.servlet.NoHandlerFoundException;
|
|||||||
@ControllerAdvice
|
@ControllerAdvice
|
||||||
public class GlobalExceptionHandler {
|
public class GlobalExceptionHandler {
|
||||||
|
|
||||||
@ExceptionHandler(ResponseStatusException.class)
|
|
||||||
public ResponseEntity<ApiErrorResponse> handle(ResponseStatusException ex) {
|
|
||||||
return ResponseEntity
|
|
||||||
.status(ex.getStatusCode())
|
|
||||||
.body(ApiErrorResponse.builder()
|
|
||||||
.status(ex.getStatusCode().value())
|
|
||||||
.message(ex.getReason() != null ? ex.getReason() : "Unexpected error")
|
|
||||||
.build()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(HttpMessageNotReadableException.class)
|
|
||||||
public ResponseEntity<ApiErrorResponse> handleBadRequest(HttpMessageNotReadableException ex) {
|
|
||||||
return ResponseEntity
|
|
||||||
.badRequest()
|
|
||||||
.body(ApiErrorResponse.builder()
|
|
||||||
.status(400)
|
|
||||||
.message("Invalid request body")
|
|
||||||
.build()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(NoHandlerFoundException.class)
|
|
||||||
public ResponseEntity<ApiErrorResponse> handleNotFound(NoHandlerFoundException ex) {
|
|
||||||
return ResponseEntity
|
|
||||||
.status(404)
|
|
||||||
.body(ApiErrorResponse.builder()
|
|
||||||
.status(404)
|
|
||||||
.message("Endpoint not found")
|
|
||||||
.build()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@ExceptionHandler(Exception.class)
|
@ExceptionHandler(Exception.class)
|
||||||
public ResponseEntity<ApiErrorResponse> handleGeneric(Exception ex) {
|
public ResponseEntity<ApiErrorResponse> handleAll(Exception ex) {
|
||||||
|
if (ex instanceof MethodArgumentNotValidException validationEx) {
|
||||||
|
return handleValidation(validationEx);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (ex.getClass().getSimpleName()) {
|
||||||
|
case "ResponseStatusException" -> {
|
||||||
|
ResponseStatusException rse = (ResponseStatusException) ex;
|
||||||
|
return buildErrorResponse(rse.getStatusCode().value(), rse.getReason());
|
||||||
|
}
|
||||||
|
case "NoHandlerFoundException" -> {
|
||||||
|
return buildErrorResponse(404, "Endpoint not found");
|
||||||
|
}
|
||||||
|
case "HttpMessageNotReadableException" -> {
|
||||||
|
return buildErrorResponse(400, "Invalid request body");
|
||||||
|
}
|
||||||
|
case "HttpRequestMethodNotSupportedException" -> {
|
||||||
|
return buildErrorResponse(405, "Method not allowed");
|
||||||
|
}
|
||||||
|
case "HttpMediaTypeNotSupportedException" -> {
|
||||||
|
return buildErrorResponse(415, "Unsupported media type");
|
||||||
|
}
|
||||||
|
case "HttpMediaTypeNotAcceptableException" -> {
|
||||||
|
return buildErrorResponse(406, "Not acceptable");
|
||||||
|
}
|
||||||
|
case "HttpRequestTimeoutException" -> {
|
||||||
|
return buildErrorResponse(408, "Request timeout");
|
||||||
|
}
|
||||||
|
default -> {
|
||||||
|
return buildErrorResponse(500, "Internal server error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||||
|
public ResponseEntity<ApiErrorResponse> handleValidation(MethodArgumentNotValidException ex) {
|
||||||
|
String message = ex.getBindingResult().getFieldErrors().stream()
|
||||||
|
.map(error -> error.getField() + ": " + error.getDefaultMessage())
|
||||||
|
.findFirst()
|
||||||
|
.orElse("Invalid request");
|
||||||
|
|
||||||
|
return buildErrorResponse(400, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private ResponseEntity<ApiErrorResponse> buildErrorResponse(int status, String message) {
|
||||||
return ResponseEntity
|
return ResponseEntity
|
||||||
.status(500)
|
.status(status)
|
||||||
.body(ApiErrorResponse.builder()
|
.body(ApiErrorResponse.builder()
|
||||||
.status(500)
|
.status(status)
|
||||||
.message("Internal server error")
|
.message(message != null ? message : "Unexpected error")
|
||||||
.build()
|
.build());
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
package net.tokishu.note.model;
|
package net.tokishu.note.model;
|
||||||
|
|
||||||
import jakarta.persistence.*;
|
import jakarta.persistence.*;
|
||||||
|
import jakarta.validation.constraints.Null;
|
||||||
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.hibernate.annotations.ColumnDefault;
|
||||||
import org.hibernate.annotations.CreationTimestamp;
|
import org.hibernate.annotations.CreationTimestamp;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
@@ -15,13 +18,21 @@ public class Note {
|
|||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.UUID)
|
@GeneratedValue(strategy = GenerationType.UUID)
|
||||||
private UUID uuid;
|
private UUID uuid;
|
||||||
|
@Column(length = 128, nullable = false)
|
||||||
private String name;
|
private String name;
|
||||||
|
@Column(length = 8192, nullable = false)
|
||||||
private String text;
|
private String text;
|
||||||
|
|
||||||
@ManyToOne(fetch = FetchType.LAZY)
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
@JoinColumn(name = "author", referencedColumnName = "username")
|
@JoinColumn(name = "author", referencedColumnName = "username")
|
||||||
private User author;
|
private User author;
|
||||||
|
|
||||||
|
@Column(length = 6, nullable = true, updatable = false)
|
||||||
|
private String publicLink;
|
||||||
|
|
||||||
|
@ColumnDefault("false")
|
||||||
|
private Boolean isPublic;
|
||||||
|
|
||||||
@CreationTimestamp
|
@CreationTimestamp
|
||||||
@Column(updatable = false)
|
@Column(updatable = false)
|
||||||
private LocalDateTime createdAt;
|
private LocalDateTime createdAt;
|
||||||
|
|||||||
@@ -4,9 +4,12 @@ import net.tokishu.note.model.Note;
|
|||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public interface NoteRepository extends JpaRepository<Note, UUID> {
|
public interface NoteRepository extends JpaRepository<Note, UUID> {
|
||||||
List<Note> findByAuthorUsername(String username);
|
List<Note> findByAuthorUsername(String username);
|
||||||
List<Note> findByAuthorUsernameOrderByCreatedAtDesc(String username);
|
List<Note> findByAuthorUsernameOrderByCreatedAtDesc(String username);
|
||||||
|
Optional<Note> findByPublicLinkAndIsPublicTrue(String publicLink);
|
||||||
|
boolean existsByPublicLink(String publicLink);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,4 +6,5 @@ import org.springframework.data.jpa.repository.JpaRepository;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public interface UserRepository extends JpaRepository<User, String> {
|
public interface UserRepository extends JpaRepository<User, String> {
|
||||||
|
boolean existsByRole(String role);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import net.tokishu.note.dto.response.RootResponse;
|
|||||||
import net.tokishu.note.model.User;
|
import net.tokishu.note.model.User;
|
||||||
import net.tokishu.note.repo.UserRepository;
|
import net.tokishu.note.repo.UserRepository;
|
||||||
import net.tokishu.note.security.JwtService;
|
import net.tokishu.note.security.JwtService;
|
||||||
import net.tokishu.note.security.PasswordService;
|
import net.tokishu.note.util.PasswordGenerator;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@@ -20,17 +20,15 @@ import org.springframework.web.server.ResponseStatusException;
|
|||||||
public class AuthService {
|
public class AuthService {
|
||||||
|
|
||||||
public final UserRepository userRepository;
|
public final UserRepository userRepository;
|
||||||
public final UserService userService;
|
|
||||||
public final PasswordService passwordService;
|
|
||||||
private final PasswordEncoder passwordEncoder;
|
private final PasswordEncoder passwordEncoder;
|
||||||
private final JwtService jwtService;
|
private final JwtService jwtService;
|
||||||
|
|
||||||
public RootResponse registerRoot() {
|
public RootResponse registerRoot() {
|
||||||
userRepository.findById("root").ifPresent(user -> {
|
if (userRepository.existsByRole("ADMIN")) {
|
||||||
throw new ResponseStatusException(HttpStatus.FORBIDDEN, "Root user already exists");
|
throw new ResponseStatusException(HttpStatus.FORBIDDEN, "Administrator already exists");
|
||||||
});
|
}
|
||||||
|
|
||||||
String rawPassword = passwordService.generate(16);
|
String rawPassword = PasswordGenerator.generate(16);
|
||||||
String hashedPassword = passwordEncoder.encode(rawPassword);
|
String hashedPassword = passwordEncoder.encode(rawPassword);
|
||||||
|
|
||||||
User rootUser = new User();
|
User rootUser = new User();
|
||||||
|
|||||||
@@ -6,9 +6,10 @@ import net.tokishu.note.dto.response.NoteResponse;
|
|||||||
import net.tokishu.note.model.Note;
|
import net.tokishu.note.model.Note;
|
||||||
import net.tokishu.note.model.User;
|
import net.tokishu.note.model.User;
|
||||||
import net.tokishu.note.repo.NoteRepository;
|
import net.tokishu.note.repo.NoteRepository;
|
||||||
import net.tokishu.note.repo.UserRepository;
|
import net.tokishu.note.util.CodeGenerator;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.server.ResponseStatusException;
|
import org.springframework.web.server.ResponseStatusException;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@@ -20,7 +21,6 @@ public class NoteService {
|
|||||||
|
|
||||||
public final NoteRepository noteRepository;
|
public final NoteRepository noteRepository;
|
||||||
public final UserService userService;
|
public final UserService userService;
|
||||||
public final UserRepository userRepository;
|
|
||||||
|
|
||||||
public List<NoteResponse> getAll() {
|
public List<NoteResponse> getAll() {
|
||||||
User currentUser = userService.getCurrentUser();
|
User currentUser = userService.getCurrentUser();
|
||||||
@@ -37,16 +37,29 @@ public class NoteService {
|
|||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public NoteResponse find(UUID uuid) {
|
public NoteResponse findByIdOrPublicLink(String idOrCode) {
|
||||||
Note note = noteRepository.findById(uuid)
|
if (!StringUtils.hasText(idOrCode)) {
|
||||||
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Note not found"));
|
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Invalid identifier or public link");
|
||||||
|
}
|
||||||
|
|
||||||
|
Note note;
|
||||||
|
if (isUuid(idOrCode)) {
|
||||||
|
UUID id = UUID.fromString(idOrCode);
|
||||||
|
note = noteRepository.findById(id)
|
||||||
|
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Note not found"));
|
||||||
|
|
||||||
|
User currentUser = userService.getCurrentUser();
|
||||||
|
checkOwnership(note, currentUser);
|
||||||
|
} else {
|
||||||
|
note = noteRepository.findByPublicLinkAndIsPublicTrue(idOrCode)
|
||||||
|
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Note not found"));
|
||||||
|
}
|
||||||
|
|
||||||
User currentUser = userService.getCurrentUser();
|
|
||||||
checkOwnership(note, currentUser);
|
|
||||||
return toResponse(note);
|
return toResponse(note);
|
||||||
}
|
}
|
||||||
|
|
||||||
public NoteResponse add(NoteRequest data){
|
|
||||||
|
public NoteResponse add(NoteRequest data) {
|
||||||
User author = userService.getCurrentUser();
|
User author = userService.getCurrentUser();
|
||||||
|
|
||||||
Note note = new Note();
|
Note note = new Note();
|
||||||
@@ -54,10 +67,26 @@ public class NoteService {
|
|||||||
note.setText(data.getText());
|
note.setText(data.getText());
|
||||||
note.setAuthor(author);
|
note.setAuthor(author);
|
||||||
|
|
||||||
|
String code;
|
||||||
|
|
||||||
|
int attempts = 0;
|
||||||
|
do {
|
||||||
|
code = CodeGenerator.generateCode();
|
||||||
|
attempts++;
|
||||||
|
if (attempts > 10) {
|
||||||
|
throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Failed to generate unique public link");
|
||||||
|
}
|
||||||
|
} while (noteRepository.existsByPublicLink(code));
|
||||||
|
|
||||||
|
note.setPublicLink(code);
|
||||||
|
|
||||||
|
note.setIsPublic(Boolean.TRUE.equals(data.getIsPublic()));
|
||||||
|
|
||||||
Note saved = noteRepository.save(note);
|
Note saved = noteRepository.save(note);
|
||||||
return toResponse(saved);
|
return toResponse(saved);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public NoteResponse update(UUID uuid, NoteRequest data) {
|
public NoteResponse update(UUID uuid, NoteRequest data) {
|
||||||
Note existing = noteRepository.findById(uuid)
|
Note existing = noteRepository.findById(uuid)
|
||||||
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Note not found"));
|
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Note not found"));
|
||||||
@@ -67,6 +96,7 @@ public class NoteService {
|
|||||||
|
|
||||||
existing.setName(data.getName());
|
existing.setName(data.getName());
|
||||||
existing.setText(data.getText());
|
existing.setText(data.getText());
|
||||||
|
existing.setIsPublic(Boolean.TRUE.equals(data.getIsPublic()));
|
||||||
|
|
||||||
return toResponse(noteRepository.save(existing));
|
return toResponse(noteRepository.save(existing));
|
||||||
}
|
}
|
||||||
@@ -81,7 +111,7 @@ public class NoteService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void checkOwnership(Note note, User user) {
|
private void checkOwnership(Note note, User user) {
|
||||||
if ("ADMIN".equalsIgnoreCase(user.getRole())) {
|
if ("ADMIN".equalsIgnoreCase(user.getRole())) { // TODO: use enum
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,8 +125,19 @@ public class NoteService {
|
|||||||
.uuid(note.getUuid())
|
.uuid(note.getUuid())
|
||||||
.name(note.getName())
|
.name(note.getName())
|
||||||
.text(note.getText())
|
.text(note.getText())
|
||||||
|
.isPublic(note.getIsPublic())
|
||||||
|
.publicLink(note.getPublicLink())
|
||||||
.author(note.getAuthor().getUsername())
|
.author(note.getAuthor().getUsername())
|
||||||
.createdAt(note.getCreatedAt())
|
.createdAt(note.getCreatedAt())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isUuid(String input) {
|
||||||
|
try {
|
||||||
|
UUID.fromString(input);
|
||||||
|
return true;
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package net.tokishu.note.util;
|
||||||
|
|
||||||
|
import lombok.experimental.UtilityClass;
|
||||||
|
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
@UtilityClass
|
||||||
|
public class CodeGenerator {
|
||||||
|
private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||||
|
private static final int LENGTH = 6;
|
||||||
|
private static final Random RANDOM = new SecureRandom();
|
||||||
|
|
||||||
|
public String generateCode() {
|
||||||
|
StringBuilder sb = new StringBuilder(LENGTH);
|
||||||
|
for (int i = 0; i < LENGTH; i++) {
|
||||||
|
sb.append(CHARACTERS.charAt(RANDOM.nextInt(CHARACTERS.length())));
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
-6
@@ -1,13 +1,12 @@
|
|||||||
package net.tokishu.note.security;
|
package net.tokishu.note.util;
|
||||||
|
|
||||||
import org.springframework.stereotype.Service;
|
import lombok.experimental.UtilityClass;
|
||||||
|
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
|
|
||||||
@Service
|
@UtilityClass
|
||||||
public class PasswordService {
|
public class PasswordGenerator {
|
||||||
|
private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789*!$%&@";
|
||||||
private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
||||||
private static final SecureRandom RANDOM = new SecureRandom();
|
private static final SecureRandom RANDOM = new SecureRandom();
|
||||||
|
|
||||||
public String generate(int length) {
|
public String generate(int length) {
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
spring.application.name=notes
|
spring.application.name=notes
|
||||||
spring.mvc.servlet.path=/api
|
spring.mvc.servlet.path=/api
|
||||||
|
|
||||||
?Error
|
# Error
|
||||||
spring.mvc.throw-exception-if-no-handler-found=true
|
spring.mvc.throw-exception-if-no-handler-found=true
|
||||||
spring.web.resources.add-mappings=false
|
spring.web.resources.add-mappings=false
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user