NoteController.java
package com.saltynote.service.controller;
import com.google.common.base.Splitter;
import com.saltynote.service.domain.converter.NoteConverter;
import com.saltynote.service.domain.transfer.JwtUser;
import com.saltynote.service.domain.transfer.NoteDto;
import com.saltynote.service.domain.transfer.NoteQuery;
import com.saltynote.service.domain.transfer.ServiceResponse;
import com.saltynote.service.entity.Note;
import com.saltynote.service.exception.WebAppRuntimeException;
import com.saltynote.service.service.NoteService;
import com.saltynote.service.utils.BaseUtils;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Optional;
@RestController
@Slf4j
public class NoteController {
private final NoteService noteService;
private final NoteConverter noteConverter;
public NoteController(NoteService noteService, NoteConverter noteConverter) {
this.noteService = noteService;
this.noteConverter = noteConverter;
}
@GetMapping("/note/{id}")
public ResponseEntity<Note> getNoteById(@PathVariable("id") String id, Authentication auth) {
Optional<Note> note = noteService.getById(id);
checkNoteOwner(note, auth);
return note.map(ResponseEntity::ok).orElseGet(() -> ResponseEntity.notFound().build());
}
@RequestMapping(value = "/note/{id}", method = { RequestMethod.POST, RequestMethod.PUT })
public ResponseEntity<Note> updateNoteById(@PathVariable("id") String id, @RequestBody NoteDto noteDto,
Authentication auth) {
Optional<Note> queryNote = noteService.getById(id);
checkNoteOwner(queryNote, auth);
Note noteTobeUpdate = queryNote.get();
if (StringUtils.isNotBlank(noteDto.getNote())) {
noteTobeUpdate.setNote(noteDto.getNote());
}
noteTobeUpdate.setTags(noteDto.getTags());
if (StringUtils.isNotBlank(noteDto.getHighlightColor())) {
noteTobeUpdate.setHighlightColor(noteDto.getHighlightColor());
}
noteTobeUpdate = noteService.update(noteTobeUpdate);
return ResponseEntity.ok(noteTobeUpdate);
}
@DeleteMapping("/note/{id}")
public ResponseEntity<ServiceResponse> deleteNoteById(@PathVariable("id") String id, Authentication auth) {
Optional<Note> note = noteService.getById(id);
checkNoteOwner(note, auth);
noteService.delete(note.get());
return ResponseEntity.ok(ServiceResponse.ok("Delete Successfully!"));
}
// TODO: this POST is required for chrome extension, as I find the PUT or DELETE
// requests will be
// blocked by Chrome. Further investigation is required from me for this issue.
@PostMapping("/note/{id}/delete")
public ResponseEntity<ServiceResponse> postDeleteNoteById(@PathVariable("id") String id, Authentication auth) {
return deleteNoteById(id, auth);
}
@GetMapping("/notes")
public List<Note> getNotes(Authentication auth, @RequestParam(required = false) String keyword) {
JwtUser user = (JwtUser) auth.getPrincipal();
List<Note> allNotes = noteService.getAllByUserId(user.getId());
if (allNotes == null || allNotes.isEmpty() || StringUtils.isBlank(keyword)) {
return allNotes;
}
Iterable<String> queries = Splitter.on(" ").trimResults().omitEmptyStrings().split(keyword);
return allNotes.stream()
.filter(n -> StringUtils.isNotBlank(n.getNote()) && BaseUtils.containsAllIgnoreCase(n.getNote(), queries)
|| StringUtils.isNotBlank(n.getText()) && BaseUtils.containsAllIgnoreCase(n.getText(), queries))
.toList();
}
@PostMapping("/notes")
public List<Note> getNotesByUrl(Authentication auth, @Valid @RequestBody NoteQuery noteQuery) {
JwtUser user = (JwtUser) auth.getPrincipal();
return noteService.getAllByUserIdAndUrl(user.getId(), noteQuery.getUrl());
}
@PostMapping("/note")
public ResponseEntity<Note> createNote(@Valid @RequestBody NoteDto noteDto, Authentication auth) {
JwtUser user = (JwtUser) auth.getPrincipal();
noteDto.setUserId(user.getId());
Note note = noteConverter.toEntity(noteDto);
note = noteService.create(note);
if (note.getId() != null) {
return ResponseEntity.ok(note);
}
throw new WebAppRuntimeException(HttpStatus.INTERNAL_SERVER_ERROR,
"Failed to save note into database: " + note);
}
private void checkNoteOwner(Optional<Note> note, Authentication auth) {
JwtUser user = (JwtUser) auth.getPrincipal();
if (note.isPresent() && user.getId().equals(note.get().getUserId())) {
return;
}
throw new WebAppRuntimeException(HttpStatus.FORBIDDEN, "Permission Error: You are not the owner of the note.");
}
}