001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.dto.swagger; 014 015import static org.apache.juneau.common.internal.StringUtils.*; 016import static org.apache.juneau.internal.ArrayUtils.contains; 017import static org.apache.juneau.internal.CollectionUtils.*; 018import static org.apache.juneau.internal.ConverterUtils.*; 019 020import java.util.*; 021 022import org.apache.juneau.*; 023import org.apache.juneau.annotation.*; 024import org.apache.juneau.internal.*; 025import org.apache.juneau.marshaller.*; 026 027/** 028 * Allows the definition of a security scheme that can be used by the operations. 029 * 030 * <p> 031 * Supported schemes are basic authentication, an API key (either as a header or as a query parameter) and OAuth2's 032 * common flows (implicit, password, application and access code). 033 * 034 * <h5 class='section'>Example:</h5> 035 * <p class='bjson'> 036 * <jc>// Basic authentication sample</jc> 037 * { 038 * <js>"type"</js>: <js>"basic"</js> 039 * } 040 * 041 * <jc>// API key sample</jc> 042 * { 043 * <js>"type"</js>: <js>"apiKey"</js>, 044 * <js>"name"</js>: <js>"api_key"</js>, 045 * <js>"in"</js>: <js>"header"</js> 046 * } 047 * 048 * <jc>// Implicit OAuth2 sample</jc> 049 * { 050 * <js>"type"</js>: <js>"oauth2"</js>, 051 * <js>"authorizationUrl"</js>: <js>"http://swagger.io/api/oauth/dialog"</js>, 052 * <js>"flow"</js>: <js>"implicit"</js>, 053 * <js>"scopes"</js>: { 054 * <js>"write:pets"</js>: <js>"modify pets in your account"</js>, 055 * <js>"read:pets"</js>: <js>"read your pets"</js> 056 * } 057 * } 058 * </p> 059 * 060 * <h5 class='section'>See Also:</h5><ul> 061 * <li class='link'><a class="doclink" href="../../../../../index.html#jrs.Swagger">Overview > juneau-rest-server > Swagger</a> 062 * </ul> 063 */ 064@Bean(properties="type,description,name,in,flow,authorizationUrl,tokenUrl,scopes,*") 065@FluentSetters 066public class SecurityScheme extends SwaggerElement { 067 068 private static final String[] VALID_TYPES = {"basic", "apiKey", "oauth2"}; 069 070 private String 071 type, 072 description, 073 name, 074 in, 075 flow, 076 authorizationUrl, 077 tokenUrl; 078 private Map<String,String> scopes; 079 080 /** 081 * Default constructor. 082 */ 083 public SecurityScheme() {} 084 085 /** 086 * Copy constructor. 087 * 088 * @param copyFrom The object to copy. 089 */ 090 public SecurityScheme(SecurityScheme copyFrom) { 091 super(copyFrom); 092 093 this.authorizationUrl = copyFrom.authorizationUrl; 094 this.description = copyFrom.description; 095 this.flow = copyFrom.flow; 096 this.in = copyFrom.in; 097 this.name = copyFrom.name; 098 this.scopes = copyOf(copyFrom.scopes); 099 this.tokenUrl = copyFrom.tokenUrl; 100 this.type = copyFrom.type; 101 } 102 103 /** 104 * Make a deep copy of this object. 105 * 106 * @return A deep copy of this object. 107 */ 108 public SecurityScheme copy() { 109 return new SecurityScheme(this); 110 } 111 112 113 @Override /* SwaggerElement */ 114 protected SecurityScheme strict() { 115 super.strict(); 116 return this; 117 } 118 119 //----------------------------------------------------------------------------------------------------------------- 120 // Properties 121 //----------------------------------------------------------------------------------------------------------------- 122 123 /** 124 * Bean property getter: <property>authorizationUrl</property>. 125 * 126 * <p> 127 * The authorization URL to be used for this flow. 128 * 129 * @return The property value, or <jk>null</jk> if it is not set. 130 */ 131 public String getAuthorizationUrl() { 132 return authorizationUrl; 133 } 134 135 /** 136 * Bean property setter: <property>authorizationUrl</property>. 137 * 138 * <p> 139 * The authorization URL to be used for this flow. 140 * 141 * @param value 142 * The new value for this property. 143 * <br>This SHOULD be in the form of a URL. 144 * <br>Can be <jk>null</jk> to unset the property. 145 * @return This object. 146 */ 147 public SecurityScheme setAuthorizationUrl(String value) { 148 authorizationUrl = value; 149 return this; 150 } 151 152 /** 153 * Bean property getter: <property>description</property>. 154 * 155 * <p> 156 * A short description for security scheme. 157 * 158 * @return The property value, or <jk>null</jk> if it is not set. 159 */ 160 public String getDescription() { 161 return description; 162 } 163 164 /** 165 * Bean property setter: <property>description</property>. 166 * 167 * <p> 168 * A short description for security scheme. 169 * 170 * @param value 171 * The new value for this property. 172 * <br>Can be <jk>null</jk> to unset the property. 173 * @return This object. 174 */ 175 public SecurityScheme setDescription(String value) { 176 description = value; 177 return this; 178 } 179 180 /** 181 * Bean property getter: <property>flow</property>. 182 * 183 * <p> 184 * The flow used by the OAuth2 security scheme. 185 * 186 * @return The property value, or <jk>null</jk> if it is not set. 187 */ 188 public String getFlow() { 189 return flow; 190 } 191 192 /** 193 * Bean property setter: <property>flow</property>. 194 * 195 * <p> 196 * The flow used by the OAuth2 security scheme. 197 * 198 * @param value 199 * The new value for this property. 200 * <br>Valid values: 201 * <ul> 202 * <li><js>"implicit"</js> 203 * <li><js>"password"</js> 204 * <li><js>"application"</js> 205 * <li><js>"accessCode"</js> 206 * </ul> 207 * <br>Can be <jk>null</jk> to unset the property. 208 * @return This object. 209 */ 210 public SecurityScheme setFlow(String value) { 211 flow = value; 212 return this; 213 } 214 215 /** 216 * Bean property getter: <property>in</property>. 217 * 218 * <p> 219 * The location of the API key. 220 * 221 * @return The property value, or <jk>null</jk> if it is not set. 222 */ 223 public String getIn() { 224 return in; 225 } 226 227 /** 228 * Bean property setter: <property>in</property>. 229 * 230 * <p> 231 * The location of the API key. 232 * 233 * @param value 234 * The new value for this property. 235 * <br>Valid values: 236 * <ul> 237 * <li><js>"query"</js> 238 * <li><js>"header"</js> 239 * </ul> 240 * <br>Can be <jk>null</jk> to unset the property. 241 * @return This object. 242 */ 243 public SecurityScheme setIn(String value) { 244 in = value; 245 return this; 246 } 247 248 /** 249 * Bean property getter: <property>name</property>. 250 * 251 * <p> 252 * The name of the header or query parameter to be used. 253 * 254 * @return The property value, or <jk>null</jk> if it is not set. 255 */ 256 public String getName() { 257 return name; 258 } 259 260 /** 261 * Bean property setter: <property>name</property>. 262 * 263 * <p> 264 * The name of the header or query parameter to be used. 265 * 266 * @param value 267 * The new value for this property. 268 * <br>Can be <jk>null</jk> to unset the property. 269 * @return This object. 270 */ 271 public SecurityScheme setName(String value) { 272 name = value; 273 return this; 274 } 275 276 /** 277 * Bean property getter: <property>scopes</property>. 278 * 279 * <p> 280 * The available scopes for the OAuth2 security scheme. 281 * 282 * @return The property value, or <jk>null</jk> if it is not set. 283 */ 284 public Map<String,String> getScopes() { 285 return scopes; 286 } 287 288 /** 289 * Bean property setter: <property>scopes</property>. 290 * 291 * <p> 292 * The available scopes for the OAuth2 security scheme. 293 * 294 * @param value 295 * The new value for this property. 296 * <br>Can be <jk>null</jk> to unset the property. 297 * @return This object. 298 */ 299 public SecurityScheme setScopes(Map<String,String> value) { 300 scopes = copyOf(value); 301 return this; 302 } 303 304 /** 305 * Bean property appender: <property>scopes</property>. 306 * 307 * <p> 308 * The available scopes for the OAuth2 security scheme. 309 * 310 * @param key The scope key. 311 * @param value The scope value. 312 * @return This object. 313 */ 314 public SecurityScheme addScope(String key, String value) { 315 scopes = mapBuilder(scopes).sparse().add(key, value).build(); 316 return this; 317 } 318 319 /** 320 * Bean property getter: <property>tokenUrl</property>. 321 * 322 * <p> 323 * The token URL to be used for this flow. 324 * 325 * @return The property value, or <jk>null</jk> if it is not set. 326 */ 327 public String getTokenUrl() { 328 return tokenUrl; 329 } 330 331 /** 332 * Bean property setter: <property>tokenUrl</property>. 333 * 334 * <p> 335 * The token URL to be used for this flow. 336 * 337 * @param value 338 * The new value for this property. 339 * <br>This SHOULD be in the form of a URL. 340 * <br>Can be <jk>null</jk> to unset the property. 341 * @return This object. 342 */ 343 public SecurityScheme setTokenUrl(String value) { 344 tokenUrl = value; 345 return this; 346 } 347 348 /** 349 * Bean property getter: <property>type</property>. 350 * 351 * <p> 352 * The type of the security scheme. 353 * 354 * @return The property value, or <jk>null</jk> if it is not set. 355 */ 356 public String getType() { 357 return type; 358 } 359 360 /** 361 * Bean property setter: <property>type</property>. 362 * 363 * <p> 364 * The type of the security scheme. 365 * 366 * @param value 367 * The new value for this property. 368 * <br>Valid values: 369 * <ul> 370 * <li><js>"basic"</js> 371 * <li><js>"apiKey"</js> 372 * <li><js>"oauth2"</js> 373 * </ul> 374 * <br>Property value is required. 375 * @return This object. 376 */ 377 public SecurityScheme setType(String value) { 378 if (isStrict() && ! contains(value, VALID_TYPES)) 379 throw new BasicRuntimeException( 380 "Invalid value passed in to setType(String). Value=''{0}'', valid values={1}", 381 value, Json5.of(VALID_TYPES) 382 ); 383 type = value; 384 return this; 385 } 386 387 // <FluentSetters> 388 389 // </FluentSetters> 390 391 @Override /* SwaggerElement */ 392 public <T> T get(String property, Class<T> type) { 393 if (property == null) 394 return null; 395 switch (property) { 396 case "authorizationUrl": return toType(getAuthorizationUrl(), type); 397 case "description": return toType(getDescription(), type); 398 case "flow": return toType(getFlow(), type); 399 case "in": return toType(getIn(), type); 400 case "name": return toType(getName(), type); 401 case "scopes": return toType(getScopes(), type); 402 case "tokenUrl": return toType(getTokenUrl(), type); 403 case "type": return toType(getType(), type); 404 default: return super.get(property, type); 405 } 406 } 407 408 @Override /* SwaggerElement */ 409 public SecurityScheme set(String property, Object value) { 410 if (property == null) 411 return this; 412 switch (property) { 413 case "authorizationUrl": return setAuthorizationUrl(stringify(value)); 414 case "description": return setDescription(stringify(value)); 415 case "flow": return setFlow(stringify(value)); 416 case "in": return setIn(stringify(value)); 417 case "name": return setName(stringify(value)); 418 case "scopes": return setScopes(mapBuilder(String.class,String.class).sparse().addAny(value).build()); 419 case "tokenUrl": return setTokenUrl(stringify(value)); 420 case "type": return setType(stringify(value)); 421 default: 422 super.set(property, value); 423 return this; 424 } 425 } 426 427 @Override /* SwaggerElement */ 428 public Set<String> keySet() { 429 Set<String> s = setBuilder(String.class) 430 .addIf(authorizationUrl != null, "authorizationUrl") 431 .addIf(description != null, "description") 432 .addIf(flow != null, "flow") 433 .addIf(in != null, "in") 434 .addIf(name != null, "name") 435 .addIf(scopes != null, "scopes") 436 .addIf(tokenUrl != null, "tokenUrl") 437 .addIf(type != null, "type") 438 .build(); 439 return new MultiSet<>(s, super.keySet()); 440 } 441}