onboarding backend
This commit is contained in:
parent
755ee7b2ea
commit
1bd167d0ec
6
pom.xml
6
pom.xml
@ -86,6 +86,12 @@
|
||||
<version>1.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.flagsmith</groupId>
|
||||
<artifactId>flagsmith-java-client</artifactId>
|
||||
<version>7.2.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Unirest -->
|
||||
<dependency>
|
||||
|
@ -1,6 +1,8 @@
|
||||
package cc.pulseapp.api.controller.v1;
|
||||
|
||||
import cc.pulseapp.api.exception.impl.BadRequestException;
|
||||
import cc.pulseapp.api.model.user.UserDTO;
|
||||
import cc.pulseapp.api.model.user.input.CompleteOnboardingInput;
|
||||
import cc.pulseapp.api.service.UserService;
|
||||
import lombok.NonNull;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -44,4 +46,10 @@ public final class UserController {
|
||||
public ResponseEntity<Map<String, Object>> doesUserExist(@RequestParam @NonNull String email) {
|
||||
return ResponseEntity.ok(Map.of("exists", userService.doesUserExist(email)));
|
||||
}
|
||||
|
||||
@PostMapping("/complete-onboarding") @ResponseBody @NonNull
|
||||
public ResponseEntity<Map<String, Object>> completeOnboarding(CompleteOnboardingInput input) throws BadRequestException {
|
||||
userService.completeOnboarding(input);
|
||||
return ResponseEntity.ok(Map.of("success", true));
|
||||
}
|
||||
}
|
@ -14,5 +14,10 @@ public enum UserFlag {
|
||||
/**
|
||||
* The user completed the onboarding process.
|
||||
*/
|
||||
COMPLETED_ONBOARDING
|
||||
COMPLETED_ONBOARDING,
|
||||
|
||||
/**
|
||||
* The user is an administrator.
|
||||
*/
|
||||
ADMINISTRATOR
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package cc.pulseapp.api.model.user.input;
|
||||
|
||||
import cc.pulseapp.api.model.org.Organization;
|
||||
import cc.pulseapp.api.model.page.StatusPage;
|
||||
import cc.pulseapp.api.model.user.User;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* The input to complete onboarding for a {@link User}.
|
||||
*
|
||||
* @author Braydon
|
||||
*/
|
||||
@AllArgsConstructor @Getter @ToString
|
||||
public final class CompleteOnboardingInput {
|
||||
/**
|
||||
* The name of the {@link Organization} to create.
|
||||
*/
|
||||
private final String organizationName;
|
||||
|
||||
/**
|
||||
* The name of the {@link StatusPage} to create.
|
||||
*/
|
||||
private final String statusPageName;
|
||||
|
||||
/**
|
||||
* Check if this input is valid.
|
||||
*
|
||||
* @return whether this input is valid
|
||||
*/
|
||||
public boolean isValid() {
|
||||
return organizationName != null && (!organizationName.isBlank())
|
||||
&& statusPageName != null && (!statusPageName.isBlank());
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@ import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* Input to login a {@link User}.
|
||||
* The input to login a {@link User}.
|
||||
*
|
||||
* @author Braydon
|
||||
*/
|
||||
|
@ -6,7 +6,7 @@ import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* Input to register a new {@link User}.
|
||||
* The input to register a new {@link User}.
|
||||
*
|
||||
* @author Braydon
|
||||
*/
|
||||
|
@ -0,0 +1,20 @@
|
||||
package cc.pulseapp.api.repository;
|
||||
|
||||
import cc.pulseapp.api.model.org.Organization;
|
||||
import lombok.NonNull;
|
||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||
|
||||
/**
|
||||
* The repository for interacting with {@link Organization}'s.
|
||||
*
|
||||
* @author Braydon
|
||||
*/
|
||||
public interface OrganizationRepository extends MongoRepository<Organization, Long> {
|
||||
/**
|
||||
* Find an organization by its name.
|
||||
*
|
||||
* @param name the name of the org
|
||||
* @return the org with the name
|
||||
*/
|
||||
Organization findByNameIgnoreCase(@NonNull String name);
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
package cc.pulseapp.api.service;
|
||||
|
||||
import cc.pulseapp.api.common.EnvironmentUtils;
|
||||
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.Feature;
|
||||
import cc.pulseapp.api.model.IGenericResponse;
|
||||
import cc.pulseapp.api.model.user.Session;
|
||||
import cc.pulseapp.api.model.user.User;
|
||||
@ -69,6 +69,10 @@ public final class AuthService {
|
||||
*/
|
||||
@NonNull
|
||||
public Session registerUser(@NonNull HttpServletRequest request, UserRegistrationInput input) throws BadRequestException {
|
||||
// Ensure user registration is enabled
|
||||
if (!Feature.USER_REGISTRATION_ENABLED.isEnabled()) {
|
||||
throw new BadRequestException(Error.REGISTRATION_DISABLED);
|
||||
}
|
||||
validateRegistrationInput(input); // Ensure the input is valid
|
||||
|
||||
// Ensure the given email hasn't been used before
|
||||
@ -175,7 +179,7 @@ public final class AuthService {
|
||||
private void validateRegistrationInput(UserRegistrationInput input) throws BadRequestException {
|
||||
// Ensure the input was provided
|
||||
if (input == null || (!input.isValid())) {
|
||||
throw new BadRequestException(Error.MALFORMED_INPUT);
|
||||
throw new BadRequestException(Error.MALFORMED_REGISTRATION_INPUT);
|
||||
}
|
||||
// Ensure the email is valid
|
||||
if (!StringUtils.isValidEmail(input.getEmail())) {
|
||||
@ -207,7 +211,7 @@ public final class AuthService {
|
||||
private void validateLoginInput(UserLoginInput input) throws BadRequestException {
|
||||
// Ensure the input was provided
|
||||
if (input == null || (!input.isValid())) {
|
||||
throw new BadRequestException(Error.MALFORMED_INPUT);
|
||||
throw new BadRequestException(Error.MALFORMED_LOGIN_INPUT);
|
||||
}
|
||||
// Ensure the email is valid
|
||||
if (input.getEmail() != null && (!StringUtils.isValidEmail(input.getEmail()))) {
|
||||
@ -217,8 +221,13 @@ public final class AuthService {
|
||||
captchaService.validateCaptcha(input.getCaptchaResponse());
|
||||
}
|
||||
|
||||
/**
|
||||
* Authentication errors.
|
||||
*/
|
||||
private enum Error implements IGenericResponse {
|
||||
MALFORMED_INPUT,
|
||||
REGISTRATION_DISABLED,
|
||||
MALFORMED_REGISTRATION_INPUT,
|
||||
MALFORMED_LOGIN_INPUT,
|
||||
EMAIL_INVALID,
|
||||
USERNAME_INVALID,
|
||||
USER_NOT_FOUND,
|
||||
|
@ -1,8 +1,12 @@
|
||||
package cc.pulseapp.api.service;
|
||||
|
||||
import cc.pulseapp.api.common.StringUtils;
|
||||
import cc.pulseapp.api.exception.impl.BadRequestException;
|
||||
import cc.pulseapp.api.model.IGenericResponse;
|
||||
import cc.pulseapp.api.model.user.User;
|
||||
import cc.pulseapp.api.model.user.UserDTO;
|
||||
import cc.pulseapp.api.model.user.UserFlag;
|
||||
import cc.pulseapp.api.model.user.input.CompleteOnboardingInput;
|
||||
import cc.pulseapp.api.repository.UserRepository;
|
||||
import lombok.NonNull;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -25,15 +29,22 @@ public final class UserService {
|
||||
*/
|
||||
@NonNull private final SnowflakeService snowflakeService;
|
||||
|
||||
/**
|
||||
* The organization service to use.
|
||||
*/
|
||||
@NonNull private final OrganizationService orgService;
|
||||
|
||||
/**
|
||||
* The user repository to use.
|
||||
*/
|
||||
@NonNull private final UserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
public UserService(@NonNull AuthService authService, @NonNull SnowflakeService snowflakeService, @NonNull UserRepository userRepository) {
|
||||
public UserService(@NonNull AuthService authService, @NonNull SnowflakeService snowflakeService,
|
||||
@NonNull OrganizationService orgService, @NonNull UserRepository userRepository) {
|
||||
this.authService = authService;
|
||||
this.snowflakeService = snowflakeService;
|
||||
this.orgService = orgService;
|
||||
this.userRepository = userRepository;
|
||||
}
|
||||
|
||||
@ -57,4 +68,26 @@ public final class UserService {
|
||||
public boolean doesUserExist(@NonNull String email) {
|
||||
return StringUtils.isValidEmail(email) && userRepository.findByEmailIgnoreCase(email) != null;
|
||||
}
|
||||
|
||||
public void completeOnboarding(CompleteOnboardingInput input) {
|
||||
// Ensure the input was provided
|
||||
if (input == null || (!input.isValid())) {
|
||||
throw new BadRequestException(Error.MALFORMED_ONBOARDING_INPUT);
|
||||
}
|
||||
User user = authService.getAuthenticatedUser();
|
||||
if (user.hasFlag(UserFlag.COMPLETED_ONBOARDING)) { // Already completed
|
||||
throw new BadRequestException(Error.ALREADY_ONBOARDED);
|
||||
}
|
||||
orgService.createOrganization(input.getOrganizationName(), user); // Create the org
|
||||
user.addFlag(UserFlag.COMPLETED_ONBOARDING); // Flag completed onboarding
|
||||
userRepository.save(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* User errors.
|
||||
*/
|
||||
private enum Error implements IGenericResponse {
|
||||
MALFORMED_ONBOARDING_INPUT,
|
||||
ALREADY_ONBOARDED,
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user