/@me route
This commit is contained in:
parent
d326767c7c
commit
ba473d1dae
4
pom.xml
4
pom.xml
@ -68,6 +68,10 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Libraries -->
|
||||
<dependency>
|
||||
|
@ -5,6 +5,7 @@ import lombok.SneakyThrows;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
@ -14,7 +15,7 @@ import java.util.Objects;
|
||||
/**
|
||||
* @author Braydon
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@SpringBootApplication(exclude = UserDetailsServiceAutoConfiguration.class)
|
||||
@Log4j2(topic = "PulseApp")
|
||||
public class PulseAPI {
|
||||
@SneakyThrows
|
||||
|
@ -25,7 +25,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
@RequestMapping(value = "/v1/auth", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public final class AuthController {
|
||||
/**
|
||||
* The user service to use.
|
||||
* The auth service to use.
|
||||
*/
|
||||
@NonNull private final AuthService authService;
|
||||
|
||||
|
@ -0,0 +1,43 @@
|
||||
package cc.pulseapp.api.controller.v1;
|
||||
|
||||
import cc.pulseapp.api.model.user.UserDTO;
|
||||
import cc.pulseapp.api.service.UserService;
|
||||
import lombok.NonNull;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* This controller is responsible for
|
||||
* handling user authentication requests.
|
||||
*
|
||||
* @author Braydon
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(value = "/v1/user", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public final class UserController {
|
||||
/**
|
||||
* The user service to use.
|
||||
*/
|
||||
@NonNull private final UserService userService;
|
||||
|
||||
@Autowired
|
||||
public UserController(@NonNull UserService userService) {
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
/**
|
||||
* A GET endpoint to get the
|
||||
* currently authenticated user.
|
||||
*
|
||||
* @return the currently authenticated user
|
||||
*/
|
||||
@PostMapping("/@me") @ResponseBody @NonNull
|
||||
public ResponseEntity<UserDTO> getUser() {
|
||||
return ResponseEntity.ok(userService.getUser());
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package cc.pulseapp.api.exception.impl;
|
||||
|
||||
import cc.pulseapp.api.model.IGenericResponse;
|
||||
import lombok.NonNull;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
/**
|
||||
* This exception is raised
|
||||
* when a resource is not found.
|
||||
*
|
||||
* @author Braydon
|
||||
*/
|
||||
@ResponseStatus(HttpStatus.NOT_FOUND)
|
||||
public final class ResourceNotFoundException extends RuntimeException {
|
||||
public ResourceNotFoundException(@NonNull IGenericResponse error) {
|
||||
super(error.name());
|
||||
}
|
||||
}
|
@ -34,12 +34,12 @@ public final class StatusPage {
|
||||
@NonNull private final String slug;
|
||||
|
||||
/**
|
||||
* The id to the logo of this status page, if any.
|
||||
* The hash to the logo of this status page, if any.
|
||||
*/
|
||||
private final String logo;
|
||||
|
||||
/**
|
||||
* The id to the banner of this status page, if any.
|
||||
* The hash to the banner of this status page, if any.
|
||||
*/
|
||||
private final String banner;
|
||||
|
||||
|
@ -39,6 +39,11 @@ public final class User {
|
||||
*/
|
||||
@NonNull private final String passwordSalt;
|
||||
|
||||
/**
|
||||
* The hash to the avatar of this user, if any.
|
||||
*/
|
||||
private final String avatar;
|
||||
|
||||
/**
|
||||
* The tier of this user.
|
||||
*/
|
||||
@ -47,13 +52,22 @@ public final class User {
|
||||
/**
|
||||
* The flags for this user.
|
||||
*/
|
||||
private final int flags;
|
||||
private int flags;
|
||||
|
||||
/**
|
||||
* The date this user last logged in.
|
||||
*/
|
||||
@NonNull private Date lastLogin;
|
||||
|
||||
/**
|
||||
* Add a flag to this user.
|
||||
*
|
||||
* @param flag the flag to add
|
||||
*/
|
||||
public void addFlag(@NonNull UserFlag flag) {
|
||||
flags |= flag.ordinal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this user has a given flag.
|
||||
*
|
||||
|
@ -5,6 +5,7 @@ import cc.pulseapp.api.common.HashUtils;
|
||||
import cc.pulseapp.api.common.RequestUtils;
|
||||
import cc.pulseapp.api.common.StringUtils;
|
||||
import cc.pulseapp.api.exception.impl.BadRequestException;
|
||||
import cc.pulseapp.api.exception.impl.ResourceNotFoundException;
|
||||
import cc.pulseapp.api.model.IGenericResponse;
|
||||
import cc.pulseapp.api.model.user.Session;
|
||||
import cc.pulseapp.api.model.user.User;
|
||||
@ -17,6 +18,7 @@ import cc.pulseapp.api.repository.UserRepository;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.NonNull;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Base64;
|
||||
@ -81,7 +83,7 @@ public final class AuthService {
|
||||
return generateSession(request, userRepository.save(new User(
|
||||
snowflakeService.generateSnowflake(), input.getEmail(), input.getUsername(),
|
||||
HashUtils.hash(salt, input.getPassword()), Base64.getEncoder().encodeToString(salt),
|
||||
UserTier.FREE, 0, now
|
||||
null, UserTier.FREE, 0, now
|
||||
)));
|
||||
}
|
||||
|
||||
@ -111,6 +113,38 @@ public final class AuthService {
|
||||
return generateSession(request, userRepository.save(user));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the authenticated user.
|
||||
*
|
||||
* @return the authenticated user
|
||||
* @throws ResourceNotFoundException if the user doesn't exist
|
||||
*/
|
||||
@NonNull
|
||||
public User getAuthenticatedUser() throws ResourceNotFoundException {
|
||||
Session session = (Session) SecurityContextHolder.getContext().getAuthentication().getCredentials();
|
||||
return getUserFromSnowflake(session.getUserSnowflake());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a user from a snowflake, if the user exists.
|
||||
*
|
||||
* @param snowflake the snowflake of the user
|
||||
* @return the user from the snowflake
|
||||
* @throws BadRequestException if the snowflake is invalid
|
||||
* @throws ResourceNotFoundException if the user doesn't exist
|
||||
*/
|
||||
@NonNull
|
||||
public User getUserFromSnowflake(long snowflake) {
|
||||
if (snowflake < 1L) {
|
||||
throw new ResourceNotFoundException(Error.USER_NOT_FOUND);
|
||||
}
|
||||
User user = userRepository.findById(snowflake).orElse(null);
|
||||
if (user == null) {
|
||||
throw new ResourceNotFoundException(Error.USER_NOT_FOUND);
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an auth token for a user.
|
||||
*
|
||||
|
34
src/main/java/cc/pulseapp/api/service/UserService.java
Normal file
34
src/main/java/cc/pulseapp/api/service/UserService.java
Normal file
@ -0,0 +1,34 @@
|
||||
package cc.pulseapp.api.service;
|
||||
|
||||
import cc.pulseapp.api.model.user.User;
|
||||
import cc.pulseapp.api.model.user.UserDTO;
|
||||
import lombok.NonNull;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author Braydon
|
||||
*/
|
||||
@Service
|
||||
public final class UserService {
|
||||
@NonNull private final AuthService authService;
|
||||
|
||||
/**
|
||||
* The service to use for snowflake timestamp extraction.
|
||||
*/
|
||||
@NonNull private final SnowflakeService snowflakeService;
|
||||
|
||||
@Autowired
|
||||
public UserService(@NonNull AuthService authService, @NonNull SnowflakeService snowflakeService) {
|
||||
this.authService = authService;
|
||||
this.snowflakeService = snowflakeService;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public UserDTO getUser() {
|
||||
User user = authService.getAuthenticatedUser();
|
||||
return UserDTO.asDTO(user, new Date(snowflakeService.extractCreationTime(user.getSnowflake())));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user