add custom slugs to orgs
All checks were successful
Deploy API / deploy (ubuntu-latest, 2.44.0) (push) Successful in 43s
All checks were successful
Deploy API / deploy (ubuntu-latest, 2.44.0) (push) Successful in 43s
This commit is contained in:
parent
a929a4ee48
commit
a394ecc0e3
@ -1,6 +1,8 @@
|
|||||||
package cc.pulseapp.api.common;
|
package cc.pulseapp.api.common;
|
||||||
|
|
||||||
import cc.pulseapp.api.model.IGenericResponse;
|
import cc.pulseapp.api.model.IGenericResponse;
|
||||||
|
import cc.pulseapp.api.model.org.Organization;
|
||||||
|
import cc.pulseapp.api.model.user.User;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.experimental.UtilityClass;
|
import lombok.experimental.UtilityClass;
|
||||||
|
|
||||||
@ -17,9 +19,6 @@ public final class StringUtils {
|
|||||||
private static final String SPECIAL_STRING = "!@#$%^&*()_+-=[]{}|;:,.<>?";
|
private static final String SPECIAL_STRING = "!@#$%^&*()_+-=[]{}|;:,.<>?";
|
||||||
private static final SecureRandom RANDOM = new SecureRandom();
|
private static final SecureRandom RANDOM = new SecureRandom();
|
||||||
|
|
||||||
private static final Pattern EMAIL_PATTERN = Pattern.compile("^[A-Za-z0-9+_.-]+@(.+)$");
|
|
||||||
private static final Pattern USERNAME_PATTERN = Pattern.compile("^[a-z0-9_.]*$");
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the given email is valid.
|
* Check if the given email is valid.
|
||||||
*
|
*
|
||||||
@ -27,7 +26,7 @@ public final class StringUtils {
|
|||||||
* @return whether the email is valid
|
* @return whether the email is valid
|
||||||
*/
|
*/
|
||||||
public static boolean isValidEmail(@NonNull String email) {
|
public static boolean isValidEmail(@NonNull String email) {
|
||||||
return !email.isBlank() && EMAIL_PATTERN.matcher(email).matches();
|
return !email.isBlank() && User.EMAIL_PATTERN.matcher(email).matches();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -37,7 +36,17 @@ public final class StringUtils {
|
|||||||
* @return whether the username is valid
|
* @return whether the username is valid
|
||||||
*/
|
*/
|
||||||
public static boolean isValidUsername(@NonNull String username) {
|
public static boolean isValidUsername(@NonNull String username) {
|
||||||
return USERNAME_PATTERN.matcher(username).matches();
|
return User.USERNAME_PATTERN.matcher(username).matches();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the given org slug is valid.
|
||||||
|
*
|
||||||
|
* @param slug the slug to check
|
||||||
|
* @return whether the slug is valid
|
||||||
|
*/
|
||||||
|
public static boolean isValidOrgSlug(@NonNull String slug) {
|
||||||
|
return Organization.SLUG_PATTERN.matcher(slug).matches();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -6,6 +6,8 @@ import org.springframework.data.annotation.Id;
|
|||||||
import org.springframework.data.mongodb.core.index.Indexed;
|
import org.springframework.data.mongodb.core.index.Indexed;
|
||||||
import org.springframework.data.mongodb.core.mapping.Document;
|
import org.springframework.data.mongodb.core.mapping.Document;
|
||||||
|
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An organization owned by a {@link User}.
|
* An organization owned by a {@link User}.
|
||||||
*
|
*
|
||||||
@ -15,6 +17,8 @@ import org.springframework.data.mongodb.core.mapping.Document;
|
|||||||
@EqualsAndHashCode(onlyExplicitlyIncluded = true) @ToString
|
@EqualsAndHashCode(onlyExplicitlyIncluded = true) @ToString
|
||||||
@Document("organizations")
|
@Document("organizations")
|
||||||
public final class Organization {
|
public final class Organization {
|
||||||
|
public static final Pattern SLUG_PATTERN = Pattern.compile("^[a-z0-9]+(?:-[a-z0-9]+)*$");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The snowflake id of this organization.
|
* The snowflake id of this organization.
|
||||||
*/
|
*/
|
||||||
@ -25,6 +29,11 @@ public final class Organization {
|
|||||||
*/
|
*/
|
||||||
@Indexed @NonNull private final String name;
|
@Indexed @NonNull private final String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The slug of this organization.
|
||||||
|
*/
|
||||||
|
@Indexed @NonNull private final String slug;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The snowflake of the {@link User}
|
* The snowflake of the {@link User}
|
||||||
* that owns this organization.
|
* that owns this organization.
|
||||||
|
@ -6,6 +6,7 @@ import org.springframework.data.mongodb.core.index.Indexed;
|
|||||||
import org.springframework.data.mongodb.core.mapping.Document;
|
import org.springframework.data.mongodb.core.mapping.Document;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Braydon
|
* @author Braydon
|
||||||
@ -14,6 +15,9 @@ import java.util.Date;
|
|||||||
@EqualsAndHashCode(onlyExplicitlyIncluded = true) @ToString
|
@EqualsAndHashCode(onlyExplicitlyIncluded = true) @ToString
|
||||||
@Document("users")
|
@Document("users")
|
||||||
public final class User {
|
public final class User {
|
||||||
|
public static final Pattern EMAIL_PATTERN = Pattern.compile("^[A-Za-z0-9+_.-]+@(.+)$");
|
||||||
|
public static final Pattern USERNAME_PATTERN = Pattern.compile("^[a-z0-9_.]*$");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The snowflake id of this user.
|
* The snowflake id of this user.
|
||||||
*/
|
*/
|
||||||
|
@ -19,6 +19,11 @@ public final class CompleteOnboardingInput {
|
|||||||
*/
|
*/
|
||||||
private final String organizationName;
|
private final String organizationName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The slug of the {@link Organization} to create.
|
||||||
|
*/
|
||||||
|
private final String organizationSlug;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the {@link StatusPage} to create.
|
* The name of the {@link StatusPage} to create.
|
||||||
*/
|
*/
|
||||||
@ -31,6 +36,7 @@ public final class CompleteOnboardingInput {
|
|||||||
*/
|
*/
|
||||||
public boolean isValid() {
|
public boolean isValid() {
|
||||||
return organizationName != null && (!organizationName.isBlank())
|
return organizationName != null && (!organizationName.isBlank())
|
||||||
|
&& organizationSlug != null && (!organizationSlug.isBlank())
|
||||||
&& statusPageName != null && (!statusPageName.isBlank());
|
&& statusPageName != null && (!statusPageName.isBlank());
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -36,12 +36,13 @@ public final class OrganizationService {
|
|||||||
* Create a new organization.
|
* Create a new organization.
|
||||||
*
|
*
|
||||||
* @param name the org name
|
* @param name the org name
|
||||||
|
* @param slug the org slug
|
||||||
* @param owner the owner of the org
|
* @param owner the owner of the org
|
||||||
* @return the created org
|
* @return the created org
|
||||||
* @throws BadRequestException if the org creation fails
|
* @throws BadRequestException if the org creation fails
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public Organization createOrganization(@Nonnull String name, @NonNull User owner) throws BadRequestException {
|
public Organization createOrganization(@Nonnull String name, @Nonnull String slug, @NonNull User owner) throws BadRequestException {
|
||||||
// Ensure org creation is enabled
|
// Ensure org creation is enabled
|
||||||
if (!Feature.ORG_CREATION_ENABLED.isEnabled()) {
|
if (!Feature.ORG_CREATION_ENABLED.isEnabled()) {
|
||||||
throw new BadRequestException(Error.ORG_CREATION_DISABLED);
|
throw new BadRequestException(Error.ORG_CREATION_DISABLED);
|
||||||
@ -51,7 +52,7 @@ public final class OrganizationService {
|
|||||||
throw new BadRequestException(Error.ORG_NAME_TAKEN);
|
throw new BadRequestException(Error.ORG_NAME_TAKEN);
|
||||||
}
|
}
|
||||||
// Create the org and return it
|
// Create the org and return it
|
||||||
return orgRepository.save(new Organization(snowflakeService.generateSnowflake(), name, owner.getSnowflake()));
|
return orgRepository.save(new Organization(snowflakeService.generateSnowflake(), name, slug, owner.getSnowflake()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -77,16 +77,27 @@ public final class UserService {
|
|||||||
return StringUtils.isValidEmail(email) && userRepository.findByEmailIgnoreCase(email) != null;
|
return StringUtils.isValidEmail(email) && userRepository.findByEmailIgnoreCase(email) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void completeOnboarding(CompleteOnboardingInput input) {
|
/**
|
||||||
|
* Complete the onboarding
|
||||||
|
* process for a user.
|
||||||
|
*
|
||||||
|
* @param input the input to process
|
||||||
|
* @throws BadRequestException if onboarding fails
|
||||||
|
*/
|
||||||
|
public void completeOnboarding(CompleteOnboardingInput input) throws BadRequestException {
|
||||||
// Ensure the input was provided
|
// Ensure the input was provided
|
||||||
if (input == null || (!input.isValid())) {
|
if (input == null || (!input.isValid())) {
|
||||||
throw new BadRequestException(Error.MALFORMED_ONBOARDING_INPUT);
|
throw new BadRequestException(Error.MALFORMED_ONBOARDING_INPUT);
|
||||||
}
|
}
|
||||||
|
// Ensure the org slug is valid
|
||||||
|
if (!StringUtils.isValidOrgSlug(input.getOrganizationSlug())) {
|
||||||
|
throw new BadRequestException(Error.ORGANIZATION_SLUG_INVALID);
|
||||||
|
}
|
||||||
User user = authService.getAuthenticatedUser();
|
User user = authService.getAuthenticatedUser();
|
||||||
if (user.hasFlag(UserFlag.COMPLETED_ONBOARDING)) { // Already completed
|
if (user.hasFlag(UserFlag.COMPLETED_ONBOARDING)) { // Already completed
|
||||||
throw new BadRequestException(Error.ALREADY_ONBOARDED);
|
throw new BadRequestException(Error.ALREADY_ONBOARDED);
|
||||||
}
|
}
|
||||||
Organization org = orgService.createOrganization(input.getOrganizationName(), user); // Create the org
|
Organization org = orgService.createOrganization(input.getOrganizationName(), input.getOrganizationSlug(), user); // Create the org
|
||||||
statusPageService.createStatusPage(input.getStatusPageName(), org); // Create the status page
|
statusPageService.createStatusPage(input.getStatusPageName(), org); // Create the status page
|
||||||
user.addFlag(UserFlag.COMPLETED_ONBOARDING); // Flag completed onboarding
|
user.addFlag(UserFlag.COMPLETED_ONBOARDING); // Flag completed onboarding
|
||||||
userRepository.save(user);
|
userRepository.save(user);
|
||||||
@ -97,6 +108,7 @@ public final class UserService {
|
|||||||
*/
|
*/
|
||||||
private enum Error implements IGenericResponse {
|
private enum Error implements IGenericResponse {
|
||||||
MALFORMED_ONBOARDING_INPUT,
|
MALFORMED_ONBOARDING_INPUT,
|
||||||
|
ORGANIZATION_SLUG_INVALID,
|
||||||
ALREADY_ONBOARDED,
|
ALREADY_ONBOARDED,
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user