Skip to content

Commit 4ce121c

Browse files
author
FusionAuth Automation
committed
sync from monorepo f925969b3a30
1 parent 1ea6852 commit 4ce121c

17 files changed

Lines changed: 386 additions & 22 deletions

src/main/java/io/fusionauth/client/json/MessageTemplateJacksonHelper.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020-2024, FusionAuth, All Rights Reserved
2+
* Copyright (c) 2020-2026, FusionAuth, All Rights Reserved
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
2525
import io.fusionauth.domain.message.MessageTemplate;
2626
import io.fusionauth.domain.message.MessageType;
2727
import io.fusionauth.domain.message.sms.SMSMessageTemplate;
28+
import io.fusionauth.domain.message.voice.VoiceMessageTemplate;
2829

2930
/**
3031
* @author Mikey Sleevi
@@ -49,10 +50,11 @@ public static MessageType extractType(DeserializationContext ctxt, JsonParser p,
4950
}
5051

5152
public static MessageTemplate newMessageTemplate(MessageType type) {
52-
//noinspection SwitchStatementWithTooFewBranches
5353
switch (type) {
5454
case SMS:
5555
return new SMSMessageTemplate();
56+
case Voice:
57+
return new VoiceMessageTemplate();
5658
default:
5759
throw new IllegalStateException("Unexpected type [" + type + "]. This is a FusionAuth bug, someone forgot to add a case statement for a new type.");
5860
}

src/main/java/io/fusionauth/client/json/PreviewMessageTemplateRequestDeserializer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public PreviewMessageTemplateRequest deserialize(JsonParser p, DeserializationCo
5252
req.messageTemplate = MessageTemplateJacksonHelper.newMessageTemplate(mType);
5353
}
5454

55-
if (req.locale == null) {
55+
if (req.locale == null && !lNode.isMissingNode() && !lNode.isNull()) {
5656
req.locale = new Locale(lNode.asText());
5757
}
5858

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright (c) 2026-2026, FusionAuth, All Rights Reserved
3+
*/
4+
package io.fusionauth.client.json;
5+
6+
import java.io.IOException;
7+
import java.util.Arrays;
8+
import java.util.stream.Collectors;
9+
10+
import com.fasterxml.jackson.core.JsonParser;
11+
import com.fasterxml.jackson.databind.DeserializationContext;
12+
import com.fasterxml.jackson.databind.JsonNode;
13+
import com.fasterxml.jackson.databind.ObjectMapper;
14+
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
15+
import com.inversoft.error.Errors;
16+
import io.fusionauth.domain.api.PreviewMessageTemplateResponse;
17+
import io.fusionauth.domain.message.Message;
18+
import io.fusionauth.domain.message.MessageType;
19+
import io.fusionauth.domain.message.sms.SMSMessage;
20+
import io.fusionauth.domain.message.voice.VoiceMessage;
21+
22+
/**
23+
* @author Daniel King
24+
*/
25+
public class PreviewMessageTemplateResponseDeserializer extends StdDeserializer<PreviewMessageTemplateResponse> {
26+
public PreviewMessageTemplateResponseDeserializer() {
27+
super(PreviewMessageTemplateResponse.class);
28+
}
29+
30+
private static MessageType extractType(DeserializationContext ctxt, JsonParser p, JsonNode messageNode) throws IOException {
31+
JsonNode node = messageNode.at("/type");
32+
MessageType type = MessageType.safeValueOf(node.asText());
33+
if (type == null) {
34+
String sorted = Arrays.stream(MessageType.values()).map(Enum::name).sorted().collect(Collectors.joining(", "));
35+
return (MessageType) ctxt.handleUnexpectedToken(Message.class, node.asToken(), p,
36+
"Expected the type field to be one of [" + sorted + "], but found [" + node.asText() + "]");
37+
}
38+
39+
return type;
40+
}
41+
42+
@Override
43+
public PreviewMessageTemplateResponse deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
44+
return deserialize(p, ctxt, new PreviewMessageTemplateResponse());
45+
}
46+
47+
@Override
48+
public PreviewMessageTemplateResponse deserialize(JsonParser p, DeserializationContext ctxt, PreviewMessageTemplateResponse response)
49+
throws IOException {
50+
JsonNode node = p.getCodec().readTree(p);
51+
52+
JsonNode errorsNode = node.at("/errors");
53+
if (!errorsNode.isMissingNode()) {
54+
response.errors = p.getCodec().treeToValue(errorsNode, Errors.class);
55+
}
56+
57+
JsonNode messageNode = node.at("/previewMessage");
58+
MessageType messageType = extractType(ctxt, p, messageNode);
59+
if (messageType == MessageType.Voice) {
60+
response.previewMessage = new VoiceMessage();
61+
} else {
62+
SMSMessage message = new SMSMessage();
63+
response.message = message;
64+
response.previewMessage = message;
65+
}
66+
((ObjectMapper) p.getCodec()).readerForUpdating(response.previewMessage).readValue(messageNode);
67+
68+
return response;
69+
}
70+
}

src/main/java/io/fusionauth/domain/ApplicationMultiFactorConfiguration.java

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021-2022, FusionAuth, All Rights Reserved
2+
* Copyright (c) 2021-2026, FusionAuth, All Rights Reserved
33
*/
44
package io.fusionauth.domain;
55

@@ -21,6 +21,8 @@ public class ApplicationMultiFactorConfiguration {
2121

2222
public ApplicationMultiFactorTrustPolicy trustPolicy;
2323

24+
public MultiFactorVoiceTemplate voice = new MultiFactorVoiceTemplate();
25+
2426
@JacksonConstructor
2527
public ApplicationMultiFactorConfiguration() {
2628
}
@@ -30,6 +32,7 @@ public ApplicationMultiFactorConfiguration(ApplicationMultiFactorConfiguration o
3032
this.loginPolicy = other.loginPolicy;
3133
this.sms = new MultiFactorSMSTemplate(other.sms);
3234
this.trustPolicy = other.trustPolicy;
35+
this.voice = new MultiFactorVoiceTemplate(other.voice);
3336
}
3437

3538
@Override
@@ -44,12 +47,13 @@ public boolean equals(Object o) {
4447
return Objects.equals(email, that.email) &&
4548
loginPolicy == that.loginPolicy &&
4649
Objects.equals(sms, that.sms) &&
47-
trustPolicy == that.trustPolicy;
50+
trustPolicy == that.trustPolicy &&
51+
Objects.equals(voice, that.voice);
4852
}
4953

5054
@Override
5155
public int hashCode() {
52-
return Objects.hash(email, loginPolicy, sms, trustPolicy);
56+
return Objects.hash(email, loginPolicy, sms, trustPolicy, voice);
5357
}
5458

5559
@Override
@@ -114,4 +118,33 @@ public int hashCode() {
114118
return Objects.hash(templateId);
115119
}
116120
}
121+
122+
public static class MultiFactorVoiceTemplate {
123+
public UUID templateId;
124+
125+
@JacksonConstructor
126+
public MultiFactorVoiceTemplate() {
127+
}
128+
129+
public MultiFactorVoiceTemplate(MultiFactorVoiceTemplate other) {
130+
this.templateId = other.templateId;
131+
}
132+
133+
@Override
134+
public boolean equals(Object o) {
135+
if (this == o) {
136+
return true;
137+
}
138+
if (o == null || getClass() != o.getClass()) {
139+
return false;
140+
}
141+
MultiFactorVoiceTemplate that = (MultiFactorVoiceTemplate) o;
142+
return Objects.equals(templateId, that.templateId);
143+
}
144+
145+
@Override
146+
public int hashCode() {
147+
return Objects.hash(templateId);
148+
}
149+
}
117150
}

src/main/java/io/fusionauth/domain/TenantMultiFactorConfiguration.java

Lines changed: 61 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
/*
2-
* Copyright (c) 2021-2022, FusionAuth, All Rights Reserved
2+
* Copyright (c) 2021-2026, FusionAuth, All Rights Reserved
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing,
11+
* software distributed under the License is distributed on an
12+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13+
* either express or implied. See the License for the specific
14+
* language governing permissions and limitations under the License.
315
*/
416
package io.fusionauth.domain;
517

@@ -23,6 +35,8 @@ public class TenantMultiFactorConfiguration implements Buildable<TenantMultiFact
2335

2436
public MultiFactorSMSMethod sms = new MultiFactorSMSMethod();
2537

38+
public MultiFactorVoiceMethod voice = new MultiFactorVoiceMethod();
39+
2640
@JacksonConstructor
2741
public TenantMultiFactorConfiguration() {
2842
}
@@ -32,16 +46,15 @@ public TenantMultiFactorConfiguration(TenantMultiFactorConfiguration other) {
3246
this.email = new MultiFactorEmailMethod(other.email);
3347
this.loginPolicy = other.loginPolicy;
3448
this.sms = new MultiFactorSMSMethod(other.sms);
49+
this.voice = new MultiFactorVoiceMethod(other.voice);
3550
}
3651

3752
/**
38-
* Returns true if at least one Multi-Factor method is enabled.
39-
*
4053
* @return true if at least one Multi-Factor method is enabled
4154
*/
4255
@JsonIgnore
4356
public boolean anyEnabled() {
44-
return authenticator.enabled || sms.enabled || email.enabled;
57+
return authenticator.enabled || sms.enabled || email.enabled || voice.enabled;
4558
}
4659

4760
@Override
@@ -56,12 +69,13 @@ public boolean equals(Object o) {
5669
return Objects.equals(authenticator, that.authenticator) &&
5770
Objects.equals(email, that.email) &&
5871
loginPolicy == that.loginPolicy &&
59-
Objects.equals(sms, that.sms);
72+
Objects.equals(sms, that.sms) &&
73+
Objects.equals(voice, that.voice);
6074
}
6175

6276
@Override
6377
public int hashCode() {
64-
return Objects.hash(authenticator, email, loginPolicy, sms);
78+
return Objects.hash(authenticator, email, loginPolicy, sms, voice);
6579
}
6680

6781
@Override
@@ -191,4 +205,45 @@ public String toString() {
191205
return ToString.toString(this);
192206
}
193207
}
208+
209+
public static class MultiFactorVoiceMethod extends Enableable implements Buildable<MultiFactorVoiceMethod> {
210+
public UUID messengerId;
211+
212+
public UUID templateId;
213+
214+
@JacksonConstructor
215+
public MultiFactorVoiceMethod() {
216+
}
217+
218+
public MultiFactorVoiceMethod(MultiFactorVoiceMethod other) {
219+
this.enabled = other.enabled;
220+
this.messengerId = other.messengerId;
221+
this.templateId = other.templateId;
222+
}
223+
224+
@Override
225+
public boolean equals(Object o) {
226+
if (this == o) {
227+
return true;
228+
}
229+
if (o == null || getClass() != o.getClass()) {
230+
return false;
231+
}
232+
if (!super.equals(o)) {
233+
return false;
234+
}
235+
MultiFactorVoiceMethod that = (MultiFactorVoiceMethod) o;
236+
return Objects.equals(messengerId, that.messengerId) && Objects.equals(templateId, that.templateId);
237+
}
238+
239+
@Override
240+
public int hashCode() {
241+
return Objects.hash(super.hashCode(), messengerId, templateId);
242+
}
243+
244+
@Override
245+
public String toString() {
246+
return ToString.toString(this);
247+
}
248+
}
194249
}

src/main/java/io/fusionauth/domain/TwoFactorMethod.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,20 @@
2424
* @author Daniel DeGroff
2525
*/
2626
public class TwoFactorMethod implements Buildable<TwoFactorMethod> {
27+
28+
/**
29+
* Method which authenticates using a code generated client-side using TOTP.
30+
*/
2731
public static final String Authenticator = "authenticator";
2832

33+
/**
34+
* Method which authenticates using a code sent via email.
35+
*/
2936
public static final String Email = "email";
3037

38+
/**
39+
* Method which authenticates using a code sent to a phone via SMS or voice.
40+
*/
3141
public static final String SMS = "sms";
3242

3343
public AuthenticatorConfiguration authenticator;

src/main/java/io/fusionauth/domain/api/PreviewMessageTemplateResponse.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, FusionAuth, All Rights Reserved
2+
* Copyright (c) 2020-2026, FusionAuth, All Rights Reserved
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -15,14 +15,24 @@
1515
*/
1616
package io.fusionauth.domain.api;
1717

18+
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
1819
import com.inversoft.error.Errors;
20+
import io.fusionauth.client.json.PreviewMessageTemplateResponseDeserializer;
21+
import io.fusionauth.domain.message.Message;
1922
import io.fusionauth.domain.message.sms.SMSMessage;
2023

2124
/**
2225
* @author Michael Sleevi
2326
*/
27+
@JsonDeserialize(using = PreviewMessageTemplateResponseDeserializer.class)
2428
public class PreviewMessageTemplateResponse {
2529
public Errors errors;
2630

31+
/**
32+
* @deprecated value will be null if the requested template is of type {@code VoiceMessageTemplate}. Use {@code previewMessage} instead
33+
*/
34+
@Deprecated
2735
public SMSMessage message;
36+
37+
public Message previewMessage;
2838
}

src/main/java/io/fusionauth/domain/api/TwoFactorRequest.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
/*
2-
* Copyright (c) 2018-2022, FusionAuth, All Rights Reserved
2+
* Copyright (c) 2018-2026, FusionAuth, All Rights Reserved
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing,
11+
* software distributed under the License is distributed on an
12+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13+
* either express or implied. See the License for the specific
14+
* language governing permissions and limitations under the License.
315
*/
416
package io.fusionauth.domain.api;
517

src/main/java/io/fusionauth/domain/api/twoFactor/TwoFactorSendRequest.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018-2023, FusionAuth, All Rights Reserved
2+
* Copyright (c) 2018-2026, FusionAuth, All Rights Reserved
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
1919

2020
import com.inversoft.json.JacksonConstructor;
2121
import io.fusionauth.domain.Buildable;
22+
import io.fusionauth.domain.message.MessageType;
2223

2324
/**
2425
* @author Daniel DeGroff
@@ -28,6 +29,8 @@ public class TwoFactorSendRequest implements Buildable<TwoFactorSendRequest> {
2829

2930
public String email;
3031

32+
public MessageType messageType;
33+
3134
public String method;
3235

3336
public String methodId;

0 commit comments

Comments
 (0)