diff --git a/src/main/java/io/fusionauth/domain/api/identity/verify/ExistingUserStrategy.java b/src/main/java/io/fusionauth/domain/api/identity/verify/ExistingUserStrategy.java new file mode 100644 index 00000000..c8570548 --- /dev/null +++ b/src/main/java/io/fusionauth/domain/api/identity/verify/ExistingUserStrategy.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025, FusionAuth, All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ +package io.fusionauth.domain.api.identity.verify; + +/** + * Represent the various states/expectations of a user in the context of starting verification + */ +public enum ExistingUserStrategy { + mustExist, + mustNotExist +} diff --git a/src/main/java/io/fusionauth/domain/api/identity/verify/VerifyStartRequest.java b/src/main/java/io/fusionauth/domain/api/identity/verify/VerifyStartRequest.java index 9ee6f0ad..af8c518a 100644 --- a/src/main/java/io/fusionauth/domain/api/identity/verify/VerifyStartRequest.java +++ b/src/main/java/io/fusionauth/domain/api/identity/verify/VerifyStartRequest.java @@ -27,6 +27,12 @@ public class VerifyStartRequest implements Buildable { public UUID applicationId; + /** + * When MustExist (default), loginId/loginIdType must correspond to a user in the tenant. When this is MustNotExist, verification can begin + * without a user, in order to perform verification before user creation. + */ + public ExistingUserStrategy existingUserStrategy = ExistingUserStrategy.mustExist; + public String loginId; public String loginIdType; diff --git a/src/main/java/io/fusionauth/domain/api/user/RegistrationRequest.java b/src/main/java/io/fusionauth/domain/api/user/RegistrationRequest.java index f7e79ae1..c62de6f4 100644 --- a/src/main/java/io/fusionauth/domain/api/user/RegistrationRequest.java +++ b/src/main/java/io/fusionauth/domain/api/user/RegistrationRequest.java @@ -15,6 +15,9 @@ */ package io.fusionauth.domain.api.user; +import java.util.ArrayList; +import java.util.List; + import com.inversoft.json.JacksonConstructor; import io.fusionauth.domain.EventInfo; import io.fusionauth.domain.SendSetPasswordIdentityType; @@ -48,6 +51,8 @@ public class RegistrationRequest extends BaseEventRequest { public User user; + public List verificationIds = new ArrayList<>(); + @JacksonConstructor public RegistrationRequest() { } diff --git a/src/main/java/io/fusionauth/domain/api/user/RegistrationResponse.java b/src/main/java/io/fusionauth/domain/api/user/RegistrationResponse.java index da1a87bb..4fcf58f7 100644 --- a/src/main/java/io/fusionauth/domain/api/user/RegistrationResponse.java +++ b/src/main/java/io/fusionauth/domain/api/user/RegistrationResponse.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2024, FusionAuth, All Rights Reserved + * Copyright (c) 2018-2025, FusionAuth, All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,11 +16,13 @@ package io.fusionauth.domain.api.user; import java.time.ZonedDateTime; +import java.util.List; import java.util.UUID; import com.inversoft.json.JacksonConstructor; import io.fusionauth.domain.User; import io.fusionauth.domain.UserRegistration; +import io.fusionauth.domain.api.UserResponse.VerificationId; /** * Registration API request object. @@ -44,6 +46,8 @@ public class RegistrationResponse { public User user; + public List verificationIds; + @JacksonConstructor public RegistrationResponse() { } diff --git a/src/main/java/io/fusionauth/domain/form/Form.java b/src/main/java/io/fusionauth/domain/form/Form.java index 34c2f926..37ba5b07 100644 --- a/src/main/java/io/fusionauth/domain/form/Form.java +++ b/src/main/java/io/fusionauth/domain/form/Form.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, FusionAuth, All Rights Reserved + * Copyright (c) 2020-2025, FusionAuth, All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -85,9 +85,9 @@ public int hashCode() { public void normalize() { Normalizer.removeEmpty(data); - // Remove any null steps, steps w/out fields, and any null fields in steps + // Remove any null steps, collectData steps w/out fields, and any null fields in steps Normalizer.removeEmpty(steps); - steps.removeIf(step -> step.fields.isEmpty()); + steps.removeIf(step -> step.type == FormStepType.collectData && step.fields.isEmpty()); steps.stream().map(step -> step.fields).forEach(Normalizer::removeEmpty); } diff --git a/src/main/java/io/fusionauth/domain/form/FormStep.java b/src/main/java/io/fusionauth/domain/form/FormStep.java index 527b0d56..1654d311 100644 --- a/src/main/java/io/fusionauth/domain/form/FormStep.java +++ b/src/main/java/io/fusionauth/domain/form/FormStep.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, FusionAuth, All Rights Reserved + * Copyright (c) 2020-2025, FusionAuth, All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,7 @@ import java.util.Objects; import java.util.UUID; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.inversoft.json.JacksonConstructor; import com.inversoft.json.ToString; import io.fusionauth.domain.Buildable; @@ -31,11 +32,14 @@ public class FormStep implements Buildable { public List fields = new ArrayList<>(); + public FormStepType type = FormStepType.collectData; + @JacksonConstructor public FormStep() { } public FormStep(FormStep other) { + type = other.type; fields.addAll(other.fields); } @@ -52,12 +56,12 @@ public boolean equals(Object o) { return false; } FormStep formStep = (FormStep) o; - return Objects.equals(fields, formStep.fields); + return Objects.equals(fields, formStep.fields) && type == formStep.type; } @Override public int hashCode() { - return Objects.hash(fields); + return Objects.hash(fields, type); } @Override diff --git a/src/main/java/io/fusionauth/domain/form/FormStepType.java b/src/main/java/io/fusionauth/domain/form/FormStepType.java new file mode 100644 index 00000000..9acffa24 --- /dev/null +++ b/src/main/java/io/fusionauth/domain/form/FormStepType.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025, FusionAuth, All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ +package io.fusionauth.domain.form; + +/** + * Denotes the type of form step. This is used to configure different behavior on form steps in the registration flow. + */ +public enum FormStepType { + // NOTE: These are ordinal, always add to the end + /** + * Collects data from the user. + */ + collectData, + /** + * Verifies the user's email address before creating the user. + */ + verifyEmail, + /** + * Verifies the user's phone number before creating the user. + */ + verifyPhoneNumber +}