Skip to content

Commit a393f39

Browse files
committed
fix: update core config and config mapper to load from env
1 parent cc77955 commit a393f39

File tree

4 files changed

+102
-12
lines changed

4 files changed

+102
-12
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright (c) 2025, VRAI Labs and/or its affiliates. All rights reserved.
3+
*
4+
* This software is licensed under the Apache License, Version 2.0 (the
5+
* "License") as published by the Apache Software Foundation.
6+
*
7+
* You may not use this file except in compliance with the License. You may
8+
* obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations
14+
* under the License.
15+
*/
16+
17+
package io.supertokens.storage.postgresql.annotations;
18+
19+
import java.lang.annotation.ElementType;
20+
import java.lang.annotation.Retention;
21+
import java.lang.annotation.RetentionPolicy;
22+
import java.lang.annotation.Target;
23+
24+
@Retention(RetentionPolicy.RUNTIME)
25+
// Make annotation accessible at runtime so that config can be read from env
26+
@Target(ElementType.FIELD) // Annotation can only be applied to fields
27+
public @interface EnvName {
28+
String value(); // String value that provides a env var name for the field
29+
}

src/main/java/io/supertokens/storage/postgresql/config/Config.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ private PostgreSQLConfig loadPostgreSQLConfig(JsonObject configJson) throws IOEx
107107

108108
public static boolean canBeUsed(JsonObject configJson) throws InvalidConfigException {
109109
try {
110-
PostgreSQLConfig config = ConfigMapper.mapConfig(configJson, PostgreSQLConfig.class);
110+
PostgreSQLConfig config = ConfigMapper.mapConfig(configJson, new PostgreSQLConfig());
111111
return config.getConnectionURI() != null || config.getUser() != null || config.getPassword() != null;
112112
} catch (InvalidConfigException e) {
113113
throw e;

src/main/java/io/supertokens/storage/postgresql/config/PostgreSQLConfig.java

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public class PostgreSQLConfig {
4040
@IgnoreForAnnotationCheck
4141
private int postgresql_config_version = -1;
4242

43+
@EnvName("POSTGRESQL_CONNECTION_POOL_SIZE")
4344
@JsonProperty
4445
@ConnectionPoolProperty
4546
@DashboardInfo(
@@ -48,6 +49,7 @@ public class PostgreSQLConfig {
4849
defaultValue = "10", isOptional = true, isEditable = true)
4950
private int postgresql_connection_pool_size = 10;
5051

52+
@EnvName("POSTGRESQL_HOST")
5153
@JsonProperty
5254
@UserPoolProperty
5355
@DashboardInfo(
@@ -56,12 +58,14 @@ public class PostgreSQLConfig {
5658
defaultValue = "\"localhost\"", isOptional = true)
5759
private String postgresql_host = null;
5860

61+
@EnvName("POSTGRESQL_PORT")
5962
@JsonProperty
6063
@UserPoolProperty
6164
@DashboardInfo(description = "Specify the port to use when connecting to PostgreSQL instance.",
6265
defaultValue = "5432", isOptional = true)
6366
private int postgresql_port = -1;
6467

68+
@EnvName("POSTGRESQL_USER")
6569
@JsonProperty
6670
@ConnectionPoolProperty
6771
@DashboardInfo(
@@ -72,19 +76,22 @@ public class PostgreSQLConfig {
7276
defaultValue = "null")
7377
private String postgresql_user = null;
7478

79+
@EnvName("POSTGRESQL_PASSWORD")
7580
@JsonProperty
7681
@ConnectionPoolProperty
7782
@DashboardInfo(
7883
description = "Password for the PostgreSQL user. If you have not set a password make this an empty string.",
7984
defaultValue = "null")
8085
private String postgresql_password = null;
8186

87+
@EnvName("POSTGRESQL_DATABASE_NAME")
8288
@JsonProperty
8389
@UserPoolProperty
8490
@DashboardInfo(description = "The database name to store SuperTokens related data.",
8591
defaultValue = "\"supertokens\"", isOptional = true)
8692
private String postgresql_database_name = null;
8793

94+
@EnvName("POSTGRESQL_TABLE_NAMES_PREFIX")
8895
@JsonProperty
8996
@NotConflictingWithinUserPool
9097
@DashboardInfo(
@@ -93,6 +100,7 @@ public class PostgreSQLConfig {
93100
defaultValue = "\"\"", isOptional = true)
94101
private String postgresql_table_names_prefix = "";
95102

103+
@EnvName("POSTGRESQL_KEY_VALUE_TABLE_NAME")
96104
@JsonProperty
97105
@NotConflictingWithinUserPool
98106
@DashboardInfo(
@@ -101,12 +109,14 @@ public class PostgreSQLConfig {
101109
defaultValue = "\"key_value\"", isOptional = true)
102110
private String postgresql_key_value_table_name = null;
103111

112+
@EnvName("POSTGRESQL_SESSION_INFO_TABLE_NAME")
104113
@JsonProperty
105114
@NotConflictingWithinUserPool
106115
@DashboardInfo(description = "Specify the name of the table that will store the session info for users.",
107116
defaultValue = "\"session_info\"", isOptional = true)
108117
private String postgresql_session_info_table_name = null;
109118

119+
@EnvName("POSTGRESQL_EMAILPASSWORD_USERS_TABLE_NAME")
110120
@JsonProperty
111121
@NotConflictingWithinUserPool
112122
@DashboardInfo(
@@ -115,36 +125,42 @@ public class PostgreSQLConfig {
115125
defaultValue = "\"emailpassword_users\"", isOptional = true)
116126
private String postgresql_emailpassword_users_table_name = null;
117127

128+
@EnvName("POSTGRESQL_EMAILPASSWORD_PSWD_RESET_TOKENS_TABLE_NAME")
118129
@JsonProperty
119130
@NotConflictingWithinUserPool
120131
@DashboardInfo(description = "Specify the name of the table that will store the password reset tokens for users.",
121132
defaultValue = "\"emailpassword_pswd_reset_tokens\"", isOptional = true)
122133
private String postgresql_emailpassword_pswd_reset_tokens_table_name = null;
123134

135+
@EnvName("POSTGRESQL_EMAILVERIFICATION_TOKENS_TABLE_NAME")
124136
@JsonProperty
125137
@NotConflictingWithinUserPool
126138
@DashboardInfo(
127139
description = "Specify the name of the table that will store the email verification tokens for users.",
128140
defaultValue = "\"emailverification_tokens\"", isOptional = true)
129141
private String postgresql_emailverification_tokens_table_name = null;
130142

143+
@EnvName("POSTGRESQL_EMAILVERIFICATION_VERIFIED_EMAILS_TABLE_NAME")
131144
@JsonProperty
132145
@NotConflictingWithinUserPool
133146
@DashboardInfo(description = "Specify the name of the table that will store the verified email addresses.",
134147
defaultValue = "\"emailverification_verified_emails\"", isOptional = true)
135148
private String postgresql_emailverification_verified_emails_table_name = null;
136149

150+
@EnvName("POSTGRESQL_THIRDPARTY_USERS_TABLE_NAME")
137151
@JsonProperty
138152
@NotConflictingWithinUserPool
139153
@DashboardInfo(description = "Specify the name of the table that will store the thirdparty recipe users.",
140154
defaultValue = "\"thirdparty_users\"", isOptional = true)
141155
private String postgresql_thirdparty_users_table_name = null;
142156

157+
@EnvName("POSTGRESQL_TABLE_SCHEMA")
143158
@JsonProperty
144159
@UserPoolProperty
145160
@DashboardInfo(description = "The schema for tables.", defaultValue = "\"public\"", isOptional = true)
146161
private String postgresql_table_schema = "public";
147162

163+
@EnvName("POSTGRESQL_CONNECTION_URI")
148164
@JsonProperty
149165
@IgnoreForAnnotationCheck
150166
@DashboardInfo(
@@ -154,22 +170,26 @@ public class PostgreSQLConfig {
154170
defaultValue = "null", isOptional = true)
155171
private String postgresql_connection_uri = null;
156172

173+
@EnvName("POSTGRESQL_CONNECTION_ATTRIBUTES")
157174
@ConnectionPoolProperty
158175
@DashboardInfo(description = "The connection attributes of the PostgreSQL database.",
159176
defaultValue = "\"allowPublicKeyRetrieval=true\"", isOptional = true)
160177
private String postgresql_connection_attributes = "allowPublicKeyRetrieval=true";
161178

179+
@EnvName("POSTGRESQL_CONNECTION_SCHEME")
162180
@ConnectionPoolProperty
163181
@DashboardInfo(description = "The scheme of the PostgreSQL database.", defaultValue = "\"postgresql\"",
164182
isOptional = true)
165183
private String postgresql_connection_scheme = "postgresql";
166184

185+
@EnvName("POSTGRESQL_IDLE_CONNECTION_TIMEOUT")
167186
@JsonProperty
168187
@ConnectionPoolProperty
169188
@DashboardInfo(description = "Timeout in milliseconds for the idle connections to be closed.",
170189
defaultValue = "60000", isOptional = true, isEditable = true)
171190
private long postgresql_idle_connection_timeout = 60000;
172191

192+
@EnvName("POSTGRESQL_MINIMUM_IDLE_CONNECTIONS")
173193
@JsonProperty
174194
@ConnectionPoolProperty
175195
@DashboardInfo(
@@ -181,6 +201,51 @@ public class PostgreSQLConfig {
181201
@IgnoreForAnnotationCheck
182202
boolean isValidAndNormalised = false;
183203

204+
public PostgreSQLConfig() {
205+
Map<String, String> env = System.getenv();
206+
207+
try {
208+
for (Field field : PostgreSQLConfig.class.getDeclaredFields()) {
209+
if (field.isAnnotationPresent(EnvName.class)) {
210+
String envName = field.getAnnotation(EnvName.class).value();
211+
String stringValue = env.get(envName);
212+
213+
if (stringValue == null || stringValue.isEmpty()) {
214+
continue;
215+
}
216+
217+
if (stringValue.startsWith("\"") && stringValue.endsWith("\"")) {
218+
stringValue = stringValue.substring(1, stringValue.length() - 1);
219+
stringValue = stringValue
220+
.replace("\\n", "\n")
221+
.replace("\\t", "\t")
222+
.replace("\\r", "\r")
223+
.replace("\\\"", "\"")
224+
.replace("\\'", "'")
225+
.replace("\\\\", "\\");
226+
}
227+
228+
field.setAccessible(true);
229+
if (field.getType().equals(String.class)) {
230+
field.set(this, stringValue);
231+
} else if (field.getType().equals(int.class)) {
232+
field.set(this, Integer.parseInt(stringValue));
233+
} else if (field.getType().equals(long.class)) {
234+
field.set(this, Long.parseLong(stringValue));
235+
} else if (field.getType().equals(boolean.class)) {
236+
field.set(this, Boolean.parseBoolean(stringValue));
237+
} else if (field.getType().equals(float.class)) {
238+
field.set(this, Float.parseFloat(stringValue));
239+
} else if (field.getType().equals(double.class)) {
240+
field.set(this, Double.parseDouble(stringValue));
241+
}
242+
}
243+
}
244+
} catch (IllegalAccessException e) {
245+
throw new IllegalStateException(e);
246+
}
247+
}
248+
184249
public static Set<String> getValidFields() {
185250
PostgreSQLConfig config = new PostgreSQLConfig();
186251
JsonObject configObj = new GsonBuilder().serializeNulls().create().toJsonTree(config).getAsJsonObject();

src/main/java/io/supertokens/storage/postgresql/utils/ConfigMapper.java

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,15 @@
2828
import java.util.Map;
2929

3030
public class ConfigMapper {
31-
public static <T> T mapConfig(JsonObject config, Class<T> clazz) throws InvalidConfigException {
32-
try {
33-
T result = clazz.newInstance();
34-
for (Map.Entry<String, JsonElement> entry : config.entrySet()) {
35-
Field field = findField(clazz, entry.getKey());
36-
if (field != null) {
37-
setValue(result, field, entry.getValue());
38-
}
31+
public static <T> T mapConfig(JsonObject config, T object) throws InvalidConfigException {
32+
Class<T> clazz = (Class<T>) object.getClass();
33+
for (Map.Entry<String, JsonElement> entry : config.entrySet()) {
34+
Field field = findField(clazz, entry.getKey());
35+
if (field != null) {
36+
setValue(object, field, entry.getValue());
3937
}
40-
return result;
41-
} catch (InstantiationException | IllegalAccessException e) {
42-
throw new RuntimeException(e);
4338
}
39+
return object;
4440
}
4541

4642
private static <T> Field findField(Class<T> clazz, String key) {

0 commit comments

Comments
 (0)