1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package com.linecorp.centraldogma.server.auth;
17
18 import static com.google.common.base.MoreObjects.firstNonNull;
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static com.linecorp.centraldogma.server.internal.storage.repository.RepositoryCache.validateCacheSpec;
21 import static java.util.Objects.requireNonNull;
22
23 import java.text.ParseException;
24 import java.util.Set;
25 import java.util.function.Function;
26
27 import javax.annotation.Nullable;
28
29 import org.quartz.CronExpression;
30
31 import com.fasterxml.jackson.annotation.JsonCreator;
32 import com.fasterxml.jackson.annotation.JsonProperty;
33 import com.fasterxml.jackson.core.JsonProcessingException;
34 import com.fasterxml.jackson.databind.JsonNode;
35 import com.google.common.base.Ascii;
36 import com.google.common.collect.ImmutableSet;
37
38 import com.linecorp.centraldogma.internal.Jackson;
39
40
41
42
43 public final class AuthConfig {
44
45
46
47 public static final long DEFAULT_SESSION_TIMEOUT_MILLIS = 604800000;
48
49
50
51
52 public static final String DEFAULT_SESSION_CACHE_SPEC =
53
54 "maximumSize=8192,expireAfterWrite=" + (DEFAULT_SESSION_TIMEOUT_MILLIS / 1000) + 's';
55
56
57
58
59 public static final String DEFAULT_SESSION_VALIDATION_SCHEDULE = "0 30 */4 ? * *";
60
61 private final AuthProviderFactory factory;
62
63 private final Set<String> administrators;
64 private final boolean caseSensitiveLoginNames;
65
66 private final String sessionCacheSpec;
67 private final long sessionTimeoutMillis;
68 private final String sessionValidationSchedule;
69
70 @Nullable
71 private final JsonNode properties;
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86 @JsonCreator
87 public AuthConfig(
88 @JsonProperty("factoryClassName") String factoryClassName,
89 @JsonProperty("administrators") @Nullable Set<String> administrators,
90 @JsonProperty("caseSensitiveLoginNames") @Nullable Boolean caseSensitiveLoginNames,
91 @JsonProperty("sessionCacheSpec") @Nullable String sessionCacheSpec,
92 @JsonProperty("sessionTimeoutMillis") @Nullable Long sessionTimeoutMillis,
93 @JsonProperty("sessionValidationSchedule") @Nullable String sessionValidationSchedule,
94 @JsonProperty("properties") @Nullable JsonNode properties) throws Exception {
95 this((AuthProviderFactory) AuthConfig.class
96 .getClassLoader()
97 .loadClass(requireNonNull(factoryClassName, "factoryClassName"))
98 .getDeclaredConstructor().newInstance(),
99 administrators != null ? ImmutableSet.copyOf(administrators) : ImmutableSet.of(),
100 firstNonNull(caseSensitiveLoginNames, false),
101 firstNonNull(sessionCacheSpec, DEFAULT_SESSION_CACHE_SPEC),
102 firstNonNull(sessionTimeoutMillis, DEFAULT_SESSION_TIMEOUT_MILLIS),
103 firstNonNull(sessionValidationSchedule, DEFAULT_SESSION_VALIDATION_SCHEDULE),
104 properties);
105 }
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120 public AuthConfig(AuthProviderFactory factory,
121 Set<String> administrators,
122 boolean caseSensitiveLoginNames,
123 String sessionCacheSpec,
124 long sessionTimeoutMillis,
125 String sessionValidationSchedule,
126 @Nullable JsonNode properties) {
127 this.factory = requireNonNull(factory, "factory");
128 this.administrators = requireNonNull(administrators, "administrators");
129 this.caseSensitiveLoginNames = caseSensitiveLoginNames;
130 this.sessionCacheSpec = validateCacheSpec(requireNonNull(sessionCacheSpec, "sessionCacheSpec"));
131 checkArgument(sessionTimeoutMillis > 0,
132 "sessionTimeoutMillis: %s (expected: > 0)", sessionTimeoutMillis);
133 this.sessionTimeoutMillis = sessionTimeoutMillis;
134 this.sessionValidationSchedule = validateSchedule(
135 requireNonNull(sessionValidationSchedule, "sessionValidationSchedule"));
136 this.properties = properties;
137 }
138
139
140
141
142 public AuthProviderFactory factory() {
143 return factory;
144 }
145
146
147
148
149 @JsonProperty
150 public String factoryClassName() {
151 return factory.getClass().getName();
152 }
153
154
155
156
157 @JsonProperty
158 public Set<String> administrators() {
159 return administrators;
160 }
161
162
163
164
165 @JsonProperty
166 public boolean caseSensitiveLoginNames() {
167 return caseSensitiveLoginNames;
168 }
169
170
171
172
173 @JsonProperty
174 public String sessionCacheSpec() {
175 return sessionCacheSpec;
176 }
177
178
179
180
181 @JsonProperty
182 public long sessionTimeoutMillis() {
183 return sessionTimeoutMillis;
184 }
185
186
187
188
189 @JsonProperty
190 public String sessionValidationSchedule() {
191 return sessionValidationSchedule;
192 }
193
194
195
196
197 @Nullable
198 @JsonProperty
199 public JsonNode properties() {
200 return properties;
201 }
202
203
204
205
206 @Nullable
207 public <T> T properties(Class<T> clazz) throws JsonProcessingException {
208 return properties != null ? Jackson.treeToValue(properties, clazz) : null;
209 }
210
211
212
213
214
215 public Function<String, String> loginNameNormalizer() {
216 return caseSensitiveLoginNames() ? Function.identity() : Ascii::toLowerCase;
217 }
218
219 @Override
220 public String toString() {
221 try {
222 return Jackson.writeValueAsPrettyString(this);
223 } catch (JsonProcessingException e) {
224 throw new IllegalStateException(e);
225 }
226 }
227
228 private static String validateSchedule(String sessionValidationSchedule) {
229 try {
230 CronExpression.validateExpression(sessionValidationSchedule);
231 return sessionValidationSchedule;
232 } catch (ParseException e) {
233 throw new IllegalArgumentException("Invalid session validation schedule", e);
234 }
235 }
236 }