mirror of
https://github.com/usatiuk/y.git
synced 2025-10-28 18:37:47 +01:00
somewhat documented API
This commit is contained in:
@@ -29,11 +29,9 @@ services:
|
||||
- ymariadb:/var/lib/mysql
|
||||
healthcheck:
|
||||
test: [ "CMD", "healthcheck.sh", "--connect", "--innodb_initialized" ]
|
||||
start_period: 30s
|
||||
start_interval: 10s
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
retries: 10
|
||||
|
||||
volumes:
|
||||
ymariadb:
|
||||
@@ -1,19 +1,10 @@
|
||||
package com.usatiuk.tjv.y.server;
|
||||
|
||||
import com.usatiuk.tjv.y.server.dto.ErrorTo;
|
||||
import io.swagger.v3.core.converter.AnnotatedType;
|
||||
import io.swagger.v3.core.converter.ModelConverters;
|
||||
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
|
||||
import io.swagger.v3.oas.annotations.enums.SecuritySchemeType;
|
||||
import io.swagger.v3.oas.annotations.info.Info;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityScheme;
|
||||
import io.swagger.v3.oas.models.media.Content;
|
||||
import io.swagger.v3.oas.models.media.MediaType;
|
||||
import io.swagger.v3.oas.models.media.Schema;
|
||||
import io.swagger.v3.oas.models.responses.ApiResponse;
|
||||
import org.springdoc.core.customizers.OpenApiCustomizer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@@ -25,24 +16,4 @@ import org.springframework.context.annotation.Configuration;
|
||||
scheme = "bearer"
|
||||
)
|
||||
public class OpenAPIConfiguration {
|
||||
private ApiResponse createApiResponse(String message, Schema schema) {
|
||||
MediaType mediaType = new MediaType();
|
||||
mediaType.schema(schema);
|
||||
return new ApiResponse().description(message)
|
||||
.content(new Content().addMediaType(org.springframework.http.MediaType.APPLICATION_JSON_VALUE, mediaType));
|
||||
}
|
||||
|
||||
@Bean
|
||||
public OpenApiCustomizer customizer() {
|
||||
return openApi -> {
|
||||
Schema errorResponseSchema = ModelConverters.getInstance()
|
||||
.resolveAsResolvedSchema(new AnnotatedType(ErrorTo.class)).schema;
|
||||
openApi.getPaths().values().forEach(pathItem -> pathItem.readOperations().forEach(operation -> {
|
||||
var apiResponses = operation.getResponses();
|
||||
apiResponses.addApiResponse("500", createApiResponse("Server Error", errorResponseSchema));
|
||||
}));
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,11 @@ import com.usatiuk.tjv.y.server.service.exceptions.NotFoundException;
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
import jakarta.validation.ConstraintViolation;
|
||||
import jakarta.validation.ConstraintViolationException;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.orm.jpa.JpaObjectRetrievalFailureException;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
@@ -43,6 +45,13 @@ public class ApiExceptionHandler extends ResponseEntityExceptionHandler {
|
||||
}
|
||||
}
|
||||
|
||||
@ExceptionHandler(DataIntegrityViolationException.class)
|
||||
protected ResponseEntity<Object> handleDataIntegrityViolationException(DataIntegrityViolationException ex, WebRequest request) {
|
||||
return handleExceptionInternal(ex,
|
||||
new ErrorTo(List.of("Something is wrong with your request"), HttpStatus.BAD_REQUEST.value()),
|
||||
new HttpHeaders(), HttpStatus.BAD_REQUEST, request);
|
||||
}
|
||||
|
||||
@ExceptionHandler(AuthenticationException.class)
|
||||
protected ResponseEntity<Object> handleAuthenticationException(AuthenticationException ex, WebRequest request) {
|
||||
return handleExceptionInternal(ex,
|
||||
@@ -92,6 +101,12 @@ public class ApiExceptionHandler extends ResponseEntityExceptionHandler {
|
||||
new HttpHeaders(), HttpStatus.NOT_FOUND, request);
|
||||
}
|
||||
|
||||
@ExceptionHandler(JpaObjectRetrievalFailureException.class)
|
||||
protected ResponseEntity<Object> handleEJpaObjectRetrievalFailureException(JpaObjectRetrievalFailureException ex, WebRequest request) {
|
||||
return handleExceptionInternal(ex,
|
||||
new ErrorTo(List.of(ex.getMessage()), HttpStatus.NOT_FOUND.value()),
|
||||
new HttpHeaders(), HttpStatus.NOT_FOUND, request);
|
||||
}
|
||||
|
||||
@ExceptionHandler(ResponseStatusException.class)
|
||||
protected ResponseEntity<Object> handleResponseStatusException(ResponseStatusException ex, WebRequest request) {
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package com.usatiuk.tjv.y.server.controller;
|
||||
|
||||
import com.usatiuk.tjv.y.server.controller.annotations.*;
|
||||
import com.usatiuk.tjv.y.server.dto.ChatCreateTo;
|
||||
import com.usatiuk.tjv.y.server.dto.ChatTo;
|
||||
import com.usatiuk.tjv.y.server.dto.PersonTo;
|
||||
import com.usatiuk.tjv.y.server.service.ChatService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.core.Authentication;
|
||||
@@ -11,6 +14,7 @@ import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
|
||||
@RestController
|
||||
@RequestMapping(value = "/chat", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public class ChatController {
|
||||
@@ -21,32 +25,61 @@ public class ChatController {
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@Operation(summary = "Create a new chat, members must be at least the creator and someone else")
|
||||
@ApiUnauthorizedResponse
|
||||
@ApiBadRequestResponse
|
||||
@ChatToResponse
|
||||
public ChatTo create(Authentication authentication, @RequestBody ChatCreateTo chatCreateTo) {
|
||||
return chatService.create(authentication, chatCreateTo);
|
||||
}
|
||||
|
||||
@GetMapping(path = "/by-id/{id}")
|
||||
@Operation(summary = "Get a chat by id, should be its member")
|
||||
@ApiUnauthorizedResponse
|
||||
@ApiNotFoundResponse
|
||||
@ApiForbiddenResponse
|
||||
@ChatToResponse
|
||||
public ChatTo get(@PathVariable Long id) {
|
||||
return chatService.getById(id);
|
||||
}
|
||||
|
||||
@DeleteMapping(path = "/by-id/{id}")
|
||||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
@Operation(summary = "Delete a chat by id, should be its creator")
|
||||
@ApiUnauthorizedResponse
|
||||
@ApiNotFoundResponse
|
||||
@ApiForbiddenResponse
|
||||
@ApiResponse
|
||||
public void delete(@PathVariable Long id) {
|
||||
chatService.deleteById(id);
|
||||
}
|
||||
|
||||
@PatchMapping(path = "/by-id/{id}")
|
||||
@Operation(summary = "Update a chat by id, should be its creator, members must be at least the creator and someone else")
|
||||
@ApiUnauthorizedResponse
|
||||
@ApiNotFoundResponse
|
||||
@ApiForbiddenResponse
|
||||
@ApiBadRequestResponse
|
||||
@ChatToResponse
|
||||
public ChatTo update(Authentication authentication, @PathVariable Long id, @RequestBody ChatCreateTo chatCreateTo) {
|
||||
return chatService.update(authentication, id, chatCreateTo);
|
||||
}
|
||||
|
||||
@GetMapping(path = "/my")
|
||||
@ApiUnauthorizedResponse
|
||||
@ChatToArrResponse
|
||||
@Operation(summary = "Get chats token holder is member of")
|
||||
public Collection<ChatTo> getMy(Authentication authentication) {
|
||||
return chatService.getMy(authentication);
|
||||
}
|
||||
|
||||
@GetMapping(path = "/by-id/{id}/members")
|
||||
@ApiUnauthorizedResponse
|
||||
@ApiNotFoundResponse
|
||||
@ApiForbiddenResponse
|
||||
@ApiBadRequestResponse
|
||||
@PersonToArrResponse
|
||||
@Operation(summary = "Get members of chat by id, should be its member")
|
||||
public Collection<PersonTo> getMembers(@PathVariable Long id) {
|
||||
return chatService.getMembers(id);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package com.usatiuk.tjv.y.server.controller;
|
||||
|
||||
import com.usatiuk.tjv.y.server.controller.annotations.*;
|
||||
import com.usatiuk.tjv.y.server.dto.MessageCreateTo;
|
||||
import com.usatiuk.tjv.y.server.dto.MessageTo;
|
||||
import com.usatiuk.tjv.y.server.service.MessageService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.core.Authentication;
|
||||
@@ -20,27 +22,52 @@ public class MessageController {
|
||||
}
|
||||
|
||||
@GetMapping(path = "/by-chat/{chatTd}")
|
||||
public Collection<MessageTo> get(Authentication authentication, @PathVariable Long chatTd) {
|
||||
@Operation(summary = "Get messages in a chat, must be its member")
|
||||
@ApiUnauthorizedResponse
|
||||
@ApiForbiddenResponse
|
||||
@ApiNotFoundResponse
|
||||
@MessageToArrResponse
|
||||
public Collection<MessageTo> get(@PathVariable Long chatTd) {
|
||||
return messageService.getByChat(chatTd);
|
||||
}
|
||||
|
||||
@PostMapping(path = "/by-chat/{chatId}")
|
||||
@Operation(summary = "Add a message to a chat, must be its member")
|
||||
@ApiUnauthorizedResponse
|
||||
@ApiForbiddenResponse
|
||||
@ApiNotFoundResponse
|
||||
@MessageToResponse
|
||||
@ApiBadRequestResponse
|
||||
public MessageTo post(Authentication authentication, @PathVariable Long chatId, @RequestBody MessageCreateTo messageCreateTo) {
|
||||
return messageService.addToChat(authentication, chatId, messageCreateTo);
|
||||
}
|
||||
|
||||
@PatchMapping(path = "/by-id/{id}")
|
||||
@Operation(summary = "Change contents of a message, must be its author")
|
||||
@ApiUnauthorizedResponse
|
||||
@ApiForbiddenResponse
|
||||
@ApiNotFoundResponse
|
||||
@MessageToResponse
|
||||
@ApiBadRequestResponse
|
||||
public MessageTo update(@PathVariable long id, @RequestBody MessageCreateTo messageCreateTo) {
|
||||
return messageService.update(id, messageCreateTo);
|
||||
}
|
||||
|
||||
@DeleteMapping(path = "/by-id/{id}")
|
||||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
@Operation(summary = "Delete a message, must be its author")
|
||||
@ApiUnauthorizedResponse
|
||||
@ApiForbiddenResponse
|
||||
@ApiNotFoundResponse
|
||||
public void delete(@PathVariable long id) {
|
||||
messageService.delete(id);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@Operation(summary = "Get all messages, must be admin")
|
||||
@ApiUnauthorizedResponse
|
||||
@ApiForbiddenResponse
|
||||
@MessageToArrResponse
|
||||
public Collection<MessageTo> getAll() {
|
||||
return messageService.readAll();
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package com.usatiuk.tjv.y.server.controller;
|
||||
|
||||
import com.usatiuk.tjv.y.server.controller.annotations.*;
|
||||
import com.usatiuk.tjv.y.server.dto.PersonCreateTo;
|
||||
import com.usatiuk.tjv.y.server.dto.PersonTo;
|
||||
import com.usatiuk.tjv.y.server.service.PersonService;
|
||||
import com.usatiuk.tjv.y.server.service.exceptions.ConflictException;
|
||||
import com.usatiuk.tjv.y.server.service.exceptions.NotFoundException;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirements;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
@@ -24,84 +24,134 @@ public class PersonController {
|
||||
|
||||
@PostMapping
|
||||
@SecurityRequirements(value = {})
|
||||
public PersonTo signup(@RequestBody PersonCreateTo signupRequest) throws ConflictException {
|
||||
@Operation(summary = "Create a user, user created if there are no admins becomes an admin")
|
||||
@PersonToResponse
|
||||
@ApiBadRequestResponse
|
||||
public PersonTo signup(@RequestBody PersonCreateTo signupRequest) {
|
||||
return personService.signup(signupRequest);
|
||||
}
|
||||
|
||||
@GetMapping(path = "/by-username/{username}")
|
||||
public PersonTo getByUsername(@PathVariable String username) throws NotFoundException {
|
||||
@Operation(summary = "Get a user by username")
|
||||
@PersonToResponse
|
||||
@ApiNotFoundResponse
|
||||
@ApiUnauthorizedResponse
|
||||
public PersonTo getByUsername(@PathVariable String username) {
|
||||
return personService.readByUsername(username);
|
||||
}
|
||||
|
||||
@GetMapping(path = "/by-uuid/{uuid}")
|
||||
public PersonTo getByUuid(@PathVariable String uuid) throws NotFoundException {
|
||||
@Operation(summary = "Get a user by uuid")
|
||||
@PersonToResponse
|
||||
@ApiNotFoundResponse
|
||||
@ApiUnauthorizedResponse
|
||||
public PersonTo getByUuid(@PathVariable String uuid) {
|
||||
return personService.readByUuid(uuid);
|
||||
}
|
||||
|
||||
@GetMapping(path = "/self")
|
||||
public PersonTo getSelf(Authentication authentication) throws NotFoundException {
|
||||
@Operation(summary = "Get self")
|
||||
@PersonToResponse
|
||||
@ApiUnauthorizedResponse
|
||||
public PersonTo getSelf(Authentication authentication) {
|
||||
return personService.readSelf(authentication);
|
||||
}
|
||||
|
||||
@PatchMapping(path = "/self")
|
||||
@Operation(summary = "Update self")
|
||||
@PersonToResponse
|
||||
@ApiUnauthorizedResponse
|
||||
@ApiBadRequestResponse
|
||||
public PersonTo update(Authentication authentication, @RequestBody PersonCreateTo personCreateTo) {
|
||||
return personService.update(authentication, personCreateTo);
|
||||
}
|
||||
|
||||
@DeleteMapping(path = "/self")
|
||||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
@Operation(summary = "Delete self")
|
||||
@ApiUnauthorizedResponse
|
||||
public void delete(Authentication authentication) {
|
||||
personService.deleteSelf(authentication);
|
||||
}
|
||||
|
||||
@DeleteMapping(path = "/by-uuid/{uuid}")
|
||||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
public void deleteByUuid(@PathVariable String uuid) throws NotFoundException {
|
||||
@Operation(summary = "Delete a user by uuid, must be admin")
|
||||
@ApiUnauthorizedResponse
|
||||
@ApiNotFoundResponse
|
||||
@ApiForbiddenResponse
|
||||
public void deleteByUuid(@PathVariable String uuid) {
|
||||
personService.deleteByUuid(uuid);
|
||||
}
|
||||
|
||||
|
||||
@GetMapping
|
||||
public Collection<PersonTo> getAll() throws NotFoundException {
|
||||
@Operation(summary = "Get all users")
|
||||
@ApiUnauthorizedResponse
|
||||
@PersonToArrResponse
|
||||
public Collection<PersonTo> getAll() {
|
||||
return personService.readAll();
|
||||
}
|
||||
|
||||
@GetMapping(path = "/followers")
|
||||
public Collection<PersonTo> getFollowers(Authentication authentication) throws NotFoundException {
|
||||
@Operation(summary = "Get your followers")
|
||||
@ApiUnauthorizedResponse
|
||||
@PersonToArrResponse
|
||||
public Collection<PersonTo> getFollowers(Authentication authentication) {
|
||||
return personService.getFollowers(authentication);
|
||||
}
|
||||
|
||||
@GetMapping(path = "/following")
|
||||
public Collection<PersonTo> getFollowing(Authentication authentication) throws NotFoundException {
|
||||
@Operation(summary = "Get who you are following")
|
||||
@ApiUnauthorizedResponse
|
||||
@PersonToArrResponse
|
||||
public Collection<PersonTo> getFollowing(Authentication authentication) {
|
||||
return personService.getFollowing(authentication);
|
||||
}
|
||||
|
||||
@GetMapping(path = "/admins")
|
||||
@Operation(summary = "Get a list of admins")
|
||||
@ApiUnauthorizedResponse
|
||||
@PersonToArrResponse
|
||||
public Collection<PersonTo> getAdmins() {
|
||||
return personService.getAdmins();
|
||||
}
|
||||
|
||||
@PutMapping(path = "/admins/{uuid}")
|
||||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
public void addAdmin(@PathVariable String uuid) throws NotFoundException {
|
||||
@Operation(summary = "Add an admin, must be admin self")
|
||||
@ApiUnauthorizedResponse
|
||||
@ApiForbiddenResponse
|
||||
@ApiNotFoundResponse
|
||||
public void addAdmin(@PathVariable String uuid) {
|
||||
personService.addAdmin(uuid);
|
||||
}
|
||||
|
||||
@DeleteMapping(path = "/admins/{uuid}")
|
||||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
public void deleteAdmin(@PathVariable String uuid) throws NotFoundException {
|
||||
@Operation(summary = "Remove an admin, must be admin self")
|
||||
@ApiUnauthorizedResponse
|
||||
@ApiForbiddenResponse
|
||||
@ApiNotFoundResponse
|
||||
public void deleteAdmin(@PathVariable String uuid) {
|
||||
personService.removeAdmin(uuid);
|
||||
}
|
||||
|
||||
@PutMapping(path = "/following/{uuid}")
|
||||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
public void addFollowing(Authentication authentication, @PathVariable String uuid) throws NotFoundException {
|
||||
@Operation(summary = "Follow someone")
|
||||
@ApiUnauthorizedResponse
|
||||
@ApiNotFoundResponse
|
||||
public void addFollowing(Authentication authentication, @PathVariable String uuid) {
|
||||
personService.addFollower(authentication, uuid);
|
||||
}
|
||||
|
||||
@DeleteMapping(path = "/following/{uuid}")
|
||||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
public void deleteFollowing(Authentication authentication, @PathVariable String uuid) throws NotFoundException {
|
||||
@Operation(summary = "Unfollow someone")
|
||||
@ApiUnauthorizedResponse
|
||||
@ApiNotFoundResponse
|
||||
public void deleteFollowing(Authentication authentication, @PathVariable String uuid) {
|
||||
personService.removeFollower(authentication, uuid);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package com.usatiuk.tjv.y.server.controller;
|
||||
|
||||
import com.usatiuk.tjv.y.server.controller.annotations.*;
|
||||
import com.usatiuk.tjv.y.server.dto.PostCreateTo;
|
||||
import com.usatiuk.tjv.y.server.dto.PostTo;
|
||||
import com.usatiuk.tjv.y.server.dto.converters.PostMapper;
|
||||
import com.usatiuk.tjv.y.server.service.PostService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
@@ -22,42 +24,73 @@ public class PostController {
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@Operation(summary = "Create a post")
|
||||
@PostToResponse
|
||||
@ApiUnauthorizedResponse
|
||||
@ApiBadRequestResponse
|
||||
public PostTo createPost(Authentication authentication, @RequestBody PostCreateTo postCreateTo) {
|
||||
return postService.createPost(authentication, postCreateTo);
|
||||
}
|
||||
|
||||
@GetMapping(path = "/by-author-uuid/{uuid}")
|
||||
@Operation(summary = "Read all posts by some author by their uuid")
|
||||
@PostToArrResponse
|
||||
@ApiNotFoundResponse
|
||||
@ApiUnauthorizedResponse
|
||||
public Collection<PostTo> readAllByAuthorUuid(@PathVariable String uuid) {
|
||||
return postService.readByAuthorId(uuid);
|
||||
}
|
||||
|
||||
@GetMapping(path = "/by-author-username/{username}")
|
||||
@Operation(summary = "Read all posts by some author by their username")
|
||||
@PostToArrResponse
|
||||
@ApiNotFoundResponse
|
||||
@ApiUnauthorizedResponse
|
||||
public Collection<PostTo> readAllByAuthorUsername(@PathVariable String username) {
|
||||
return postService.readByAuthorUsername(username);
|
||||
}
|
||||
|
||||
@GetMapping(path = "/by-following")
|
||||
@Operation(summary = "Read all posts by authors you're following")
|
||||
@PostToArrResponse
|
||||
@ApiUnauthorizedResponse
|
||||
public Collection<PostTo> readAllByFollowees(Authentication authentication) {
|
||||
return postService.readByPersonFollowees(authentication);
|
||||
}
|
||||
|
||||
@GetMapping(path = "/{id}")
|
||||
@Operation(summary = "Read a post by id")
|
||||
@PostToResponse
|
||||
@ApiUnauthorizedResponse
|
||||
@ApiNotFoundResponse
|
||||
public PostTo get(@PathVariable long id) {
|
||||
return postService.readById(id);
|
||||
}
|
||||
|
||||
@PatchMapping(path = "/{id}")
|
||||
@Operation(summary = "Update a post, must be its author")
|
||||
@PostToResponse
|
||||
@ApiUnauthorizedResponse
|
||||
@ApiBadRequestResponse
|
||||
@ApiForbiddenResponse
|
||||
public PostTo update(@PathVariable long id, @RequestBody PostCreateTo postCreateTo) {
|
||||
return postService.updatePost(id, postCreateTo);
|
||||
}
|
||||
|
||||
@DeleteMapping(path = "/{id}")
|
||||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
@Operation(summary = "Delete a post, must be its author")
|
||||
@ApiUnauthorizedResponse
|
||||
@ApiForbiddenResponse
|
||||
public void delete(@PathVariable long id) {
|
||||
postService.deletePost(id);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@Operation(summary = "Get all posts, must be admin")
|
||||
@ApiUnauthorizedResponse
|
||||
@ApiForbiddenResponse
|
||||
@PostToArrResponse
|
||||
public Collection<PostTo> getAll() {
|
||||
return postService.readAll();
|
||||
}
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
package com.usatiuk.tjv.y.server.controller;
|
||||
|
||||
import com.usatiuk.tjv.y.server.controller.annotations.ApiUnauthorizedResponse;
|
||||
import com.usatiuk.tjv.y.server.dto.TokenRequestTo;
|
||||
import com.usatiuk.tjv.y.server.dto.TokenResponseTo;
|
||||
import com.usatiuk.tjv.y.server.service.LoginTokenService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirements;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@@ -21,6 +26,15 @@ public class TokenController {
|
||||
|
||||
@PostMapping
|
||||
@SecurityRequirements(value = {})
|
||||
@Operation(summary = "Get a token (login)")
|
||||
@ApiUnauthorizedResponse
|
||||
@ApiResponse(
|
||||
responseCode = "200",
|
||||
description = "Returns a token",
|
||||
content = @Content(
|
||||
mediaType = "application/json",
|
||||
schema = @Schema(implementation = TokenResponseTo.class)
|
||||
))
|
||||
public TokenResponseTo request(@RequestBody TokenRequestTo tokenRequestTo) {
|
||||
return loginTokenService.login(tokenRequestTo);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.usatiuk.tjv.y.server.controller.annotations;
|
||||
|
||||
import com.usatiuk.tjv.y.server.dto.ErrorTo;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@ApiResponse(
|
||||
responseCode = "400",
|
||||
description = "Bad request - input is invalid, details are in the error response",
|
||||
content = @Content(
|
||||
mediaType = "application/json",
|
||||
schema = @Schema(implementation = ErrorTo.class)
|
||||
))
|
||||
public @interface ApiBadRequestResponse {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.usatiuk.tjv.y.server.controller.annotations;
|
||||
|
||||
import com.usatiuk.tjv.y.server.dto.ErrorTo;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@ApiResponse(
|
||||
responseCode = "409",
|
||||
description = "Conflict - creating/updating what is requested would conflict with existing data",
|
||||
content = @Content(
|
||||
mediaType = "application/json",
|
||||
schema = @Schema(implementation = ErrorTo.class)
|
||||
))
|
||||
public @interface ApiConflictResponse {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.usatiuk.tjv.y.server.controller.annotations;
|
||||
|
||||
import com.usatiuk.tjv.y.server.dto.ErrorTo;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@ApiResponse(
|
||||
responseCode = "403",
|
||||
description = "Forbidden - the token holder doesn't have the rights for this action",
|
||||
content = @Content(
|
||||
mediaType = "application/json",
|
||||
schema = @Schema(implementation = ErrorTo.class)
|
||||
))
|
||||
public @interface ApiForbiddenResponse {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.usatiuk.tjv.y.server.controller.annotations;
|
||||
|
||||
import com.usatiuk.tjv.y.server.dto.ErrorTo;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@ApiResponse(
|
||||
responseCode = "404",
|
||||
description = "Not found - one of the resources mentioned in the request doesn't exist",
|
||||
content = @Content(
|
||||
mediaType = "application/json",
|
||||
schema = @Schema(implementation = ErrorTo.class)
|
||||
))
|
||||
public @interface ApiNotFoundResponse {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.usatiuk.tjv.y.server.controller.annotations;
|
||||
|
||||
import com.usatiuk.tjv.y.server.dto.ErrorTo;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@ApiResponse(
|
||||
responseCode = "401",
|
||||
description = "Unauthorized - requires a valid auth token",
|
||||
content = @Content(
|
||||
mediaType = "application/json",
|
||||
schema = @Schema(implementation = ErrorTo.class)
|
||||
))
|
||||
public @interface ApiUnauthorizedResponse {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.usatiuk.tjv.y.server.controller.annotations;
|
||||
|
||||
import com.usatiuk.tjv.y.server.dto.ChatTo;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@ApiResponse(
|
||||
responseCode = "200",
|
||||
content = @Content(
|
||||
mediaType = "application/json",
|
||||
schema = @Schema(implementation = ChatTo[].class)
|
||||
))
|
||||
public @interface ChatToArrResponse {
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.usatiuk.tjv.y.server.controller.annotations;
|
||||
|
||||
import com.usatiuk.tjv.y.server.dto.ChatTo;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@ApiResponse(
|
||||
responseCode = "200",
|
||||
content = @Content(
|
||||
mediaType = "application/json",
|
||||
schema = @Schema(implementation = ChatTo.class)
|
||||
))
|
||||
public @interface ChatToResponse {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.usatiuk.tjv.y.server.controller.annotations;
|
||||
|
||||
import com.usatiuk.tjv.y.server.dto.MessageTo;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@ApiResponse(
|
||||
responseCode = "200",
|
||||
content = @Content(
|
||||
mediaType = "application/json",
|
||||
schema = @Schema(implementation = MessageTo[].class)
|
||||
))
|
||||
public @interface MessageToArrResponse {
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.usatiuk.tjv.y.server.controller.annotations;
|
||||
|
||||
import com.usatiuk.tjv.y.server.dto.MessageTo;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@ApiResponse(
|
||||
responseCode = "200",
|
||||
content = @Content(
|
||||
mediaType = "application/json",
|
||||
schema = @Schema(implementation = MessageTo.class)
|
||||
))
|
||||
public @interface MessageToResponse {
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.usatiuk.tjv.y.server.controller.annotations;
|
||||
|
||||
import com.usatiuk.tjv.y.server.dto.PersonTo;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@ApiResponse(
|
||||
responseCode = "200",
|
||||
content = @Content(
|
||||
mediaType = "application/json",
|
||||
schema = @Schema(implementation = PersonTo[].class)
|
||||
))
|
||||
public @interface PersonToArrResponse {
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.usatiuk.tjv.y.server.controller.annotations;
|
||||
|
||||
import com.usatiuk.tjv.y.server.dto.PersonTo;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@ApiResponse(
|
||||
responseCode = "200",
|
||||
content = @Content(
|
||||
mediaType = "application/json",
|
||||
schema = @Schema(implementation = PersonTo.class)
|
||||
))
|
||||
public @interface PersonToResponse {
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.usatiuk.tjv.y.server.controller.annotations;
|
||||
|
||||
import com.usatiuk.tjv.y.server.dto.PostTo;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@ApiResponse(
|
||||
responseCode = "200",
|
||||
content = @Content(
|
||||
mediaType = "application/json",
|
||||
schema = @Schema(implementation = PostTo[].class)
|
||||
))
|
||||
public @interface PostToArrResponse {
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.usatiuk.tjv.y.server.controller.annotations;
|
||||
|
||||
import com.usatiuk.tjv.y.server.entity.Post;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@ApiResponse(
|
||||
responseCode = "200",
|
||||
content = @Content(
|
||||
mediaType = "application/json",
|
||||
schema = @Schema(implementation = Post.class)
|
||||
))
|
||||
public @interface PostToResponse {
|
||||
}
|
||||
@@ -1,4 +1,8 @@
|
||||
package com.usatiuk.tjv.y.server.dto;
|
||||
|
||||
public record ChatCreateTo(String name, String[] memberUuids) {
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
public record ChatCreateTo(@NotBlank String name,
|
||||
@NotBlank @Size(min = 2) String[] memberUuids) {
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
package com.usatiuk.tjv.y.server.dto;
|
||||
|
||||
public record MessageCreateTo(String contents) {
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
public record MessageCreateTo(@NotBlank String contents) {
|
||||
}
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
package com.usatiuk.tjv.y.server.dto;
|
||||
|
||||
public record PersonCreateTo(String username, String fullName, String password) {
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
public record PersonCreateTo(@NotBlank @Size(max = 100) String username, @NotBlank @Size(max = 100) String fullName,
|
||||
@NotBlank String password) {
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
package com.usatiuk.tjv.y.server.dto;
|
||||
|
||||
public record PostCreateTo(String text) {
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
public record PostCreateTo(@NotBlank String text) {
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
package com.usatiuk.tjv.y.server.dto;
|
||||
|
||||
public record TokenRequestTo(String username, String password) {
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
public record TokenRequestTo(@NotBlank String username, @NotBlank String password) {
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ public interface ChatService {
|
||||
|
||||
@PreAuthorize("@chatService.isMemberOf(authentication.principal.username, #id)")
|
||||
ChatTo getById(Long id);
|
||||
@PreAuthorize("@chatService.isMemberOf(authentication.principal.username, #id)")
|
||||
@PreAuthorize("@chatService.isCreatorOf(authentication.principal.username, #id)")
|
||||
void deleteById(Long id);
|
||||
|
||||
@PreAuthorize("@chatService.isMemberOf(authentication.principal.username, #id)")
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
@Profile("prod")
|
||||
// A bit of a mess, but even then it seems to be the simplest way to serve a single page application...
|
||||
public class WebConfig implements WebMvcConfigurer {
|
||||
private final AppResourceResolver appResourceResolver;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user