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;
|
||||
|
||||
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.experimental.UtilityClass;
|
||||
|
||||
@ -17,9 +19,6 @@ public final class StringUtils {
|
||||
private static final String SPECIAL_STRING = "!@#$%^&*()_+-=[]{}|;:,.<>?";
|
||||
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.
|
||||
*
|
||||
@ -27,7 +26,7 @@ public final class StringUtils {
|
||||
* @return whether the email is valid
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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.mapping.Document;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* An organization owned by a {@link User}.
|
||||
*
|
||||
@ -15,6 +17,8 @@ import org.springframework.data.mongodb.core.mapping.Document;
|
||||
@EqualsAndHashCode(onlyExplicitlyIncluded = true) @ToString
|
||||
@Document("organizations")
|
||||
public final class Organization {
|
||||
public static final Pattern SLUG_PATTERN = Pattern.compile("^[a-z0-9]+(?:-[a-z0-9]+)*$");
|
||||
|
||||
/**
|
||||
* The snowflake id of this organization.
|
||||
*/
|
||||
@ -25,6 +29,11 @@ public final class Organization {
|
||||
*/
|
||||
@Indexed @NonNull private final String name;
|
||||
|
||||
/**
|
||||
* The slug of this organization.
|
||||
*/
|
||||
@Indexed @NonNull private final String slug;
|
||||
|
||||
/**
|
||||
* The snowflake of the {@link User}
|
||||
* 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 java.util.Date;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author Braydon
|
||||
@ -14,6 +15,9 @@ import java.util.Date;
|
||||
@EqualsAndHashCode(onlyExplicitlyIncluded = true) @ToString
|
||||
@Document("users")
|
||||
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.
|
||||
*/
|
||||
|
@ -19,6 +19,11 @@ public final class CompleteOnboardingInput {
|
||||
*/
|
||||
private final String organizationName;
|
||||
|
||||
/**
|
||||
* The slug of the {@link Organization} to create.
|
||||
*/
|
||||
private final String organizationSlug;
|
||||
|
||||
/**
|
||||
* The name of the {@link StatusPage} to create.
|
||||
*/
|
||||
@ -31,6 +36,7 @@ public final class CompleteOnboardingInput {
|
||||
*/
|
||||
public boolean isValid() {
|
||||
return organizationName != null && (!organizationName.isBlank())
|
||||
&& organizationSlug != null && (!organizationSlug.isBlank())
|
||||
&& statusPageName != null && (!statusPageName.isBlank());
|
||||
}
|
||||
}
|
@ -36,12 +36,13 @@ public final class OrganizationService {
|
||||
* Create a new organization.
|
||||
*
|
||||
* @param name the org name
|
||||
* @param slug the org slug
|
||||
* @param owner the owner of the org
|
||||
* @return the created org
|
||||
* @throws BadRequestException if the org creation fails
|
||||
*/
|
||||
@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
|
||||
if (!Feature.ORG_CREATION_ENABLED.isEnabled()) {
|
||||
throw new BadRequestException(Error.ORG_CREATION_DISABLED);
|
||||
@ -51,7 +52,7 @@ public final class OrganizationService {
|
||||
throw new BadRequestException(Error.ORG_NAME_TAKEN);
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
|
||||
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
|
||||
if (input == null || (!input.isValid())) {
|
||||
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();
|
||||
if (user.hasFlag(UserFlag.COMPLETED_ONBOARDING)) { // Already completed
|
||||
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
|
||||
user.addFlag(UserFlag.COMPLETED_ONBOARDING); // Flag completed onboarding
|
||||
userRepository.save(user);
|
||||
@ -97,6 +108,7 @@ public final class UserService {
|
||||
*/
|
||||
private enum Error implements IGenericResponse {
|
||||
MALFORMED_ONBOARDING_INPUT,
|
||||
ORGANIZATION_SLUG_INVALID,
|
||||
ALREADY_ONBOARDED,
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user