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.internal.ArrayUtils.*; 016import static org.apache.juneau.internal.StringUtils.*; 017import static org.apache.juneau.internal.CollectionUtils.*; 018import static org.apache.juneau.internal.ObjectUtils.*; 019 020import java.util.*; 021 022import org.apache.juneau.*; 023import org.apache.juneau.annotation.*; 024import org.apache.juneau.internal.*; 025import org.apache.juneau.utils.*; 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='bcode w800'> 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 * <ul class='seealso'> 061 * <li class='link'>{@doc juneau-dto.Swagger} 062 * </ul> 063 */ 064@Bean(properties="type,description,name,in,flow,authorizationUrl,tokenUrl,scopes,*") 065public class SecurityScheme extends SwaggerElement { 066 067 private static final String[] VALID_TYPES = {"basic", "apiKey", "oauth2"}; 068 069 private String 070 type, 071 description, 072 name, 073 in, 074 flow, 075 authorizationUrl, 076 tokenUrl; 077 private Map<String,String> scopes; 078 079 /** 080 * Default constructor. 081 */ 082 public SecurityScheme() {} 083 084 /** 085 * Copy constructor. 086 * 087 * @param copyFrom The object to copy. 088 */ 089 public SecurityScheme(SecurityScheme copyFrom) { 090 super(copyFrom); 091 092 this.type = copyFrom.type; 093 this.description = copyFrom.description; 094 this.name = copyFrom.name; 095 this.in = copyFrom.in; 096 this.flow = copyFrom.flow; 097 this.authorizationUrl = copyFrom.authorizationUrl; 098 this.tokenUrl = copyFrom.tokenUrl; 099 100 if (copyFrom.scopes == null) 101 this.scopes = null; 102 else 103 this.scopes = new LinkedHashMap<>(copyFrom.scopes); 104 } 105 106 /** 107 * Make a deep copy of this object. 108 * 109 * @return A deep copy of this object. 110 */ 111 public SecurityScheme copy() { 112 return new SecurityScheme(this); 113 } 114 115 116 @Override /* SwaggerElement */ 117 protected SecurityScheme strict() { 118 super.strict(); 119 return this; 120 } 121 122 /** 123 * Bean property getter: <property>type</property>. 124 * 125 * <p> 126 * The type of the security scheme. 127 * 128 * @return The property value, or <jk>null</jk> if it is not set. 129 */ 130 public String getType() { 131 return type; 132 } 133 134 /** 135 * Bean property setter: <property>type</property>. 136 * 137 * <p> 138 * The type of the security scheme. 139 * 140 * @param value 141 * The new value for this property. 142 * <br>Valid values: 143 * <ul> 144 * <li><js>"basic"</js> 145 * <li><js>"apiKey"</js> 146 * <li><js>"oauth2"</js> 147 * </ul> 148 * <br>Property value is required. 149 * @return This object (for method chaining). 150 */ 151 public SecurityScheme setType(String value) { 152 if (isStrict() && ! contains(value, VALID_TYPES)) 153 throw new FormattedRuntimeException( 154 "Invalid value passed in to setType(String). Value=''{0}'', valid values={1}", 155 value, VALID_TYPES 156 ); 157 type = value; 158 return this; 159 } 160 161 /** 162 * Same as {@link #setType(String)}. 163 * 164 * @param value 165 * The new value for this property. 166 * <br>Non-String values will be converted to String using <c>toString()</c>. 167 * <br>Valid values: 168 * <ul> 169 * <li><js>"basic"</js> 170 * <li><js>"apiKey"</js> 171 * <li><js>"oauth2"</js> 172 * </ul> 173 * <br>Can be <jk>null</jk> to unset the property. 174 * @return This object (for method chaining). 175 */ 176 public SecurityScheme type(Object value) { 177 return setType(stringify(value)); 178 } 179 180 /** 181 * Bean property getter: <property>description</property>. 182 * 183 * <p> 184 * A short description for security scheme. 185 * 186 * @return The property value, or <jk>null</jk> if it is not set. 187 */ 188 public String getDescription() { 189 return description; 190 } 191 192 /** 193 * Bean property setter: <property>description</property>. 194 * 195 * <p> 196 * A short description for security scheme. 197 * 198 * @param value 199 * The new value for this property. 200 * <br>Can be <jk>null</jk> to unset the property. 201 * @return This object (for method chaining). 202 */ 203 public SecurityScheme setDescription(String value) { 204 description = value; 205 return this; 206 } 207 208 /** 209 * Same as {@link #setDescription(String)}. 210 * 211 * @param value 212 * The new value for this property. 213 * <br>Non-String values will be converted to String using <c>toString()</c>. 214 * <br>Can be <jk>null</jk> to unset the property. 215 * @return This object (for method chaining). 216 */ 217 public SecurityScheme description(Object value) { 218 return setDescription(stringify(value)); 219 } 220 221 /** 222 * Bean property getter: <property>name</property>. 223 * 224 * <p> 225 * The name of the header or query parameter to be used. 226 * 227 * @return The property value, or <jk>null</jk> if it is not set. 228 */ 229 public String getName() { 230 return name; 231 } 232 233 /** 234 * Bean property setter: <property>name</property>. 235 * 236 * <p> 237 * The name of the header or query parameter to be used. 238 * 239 * @param value 240 * The new value for this property. 241 * <br>Can be <jk>null</jk> to unset the property. 242 * @return This object (for method chaining). 243 */ 244 public SecurityScheme setName(String value) { 245 name = value; 246 return this; 247 } 248 249 /** 250 * Same as {@link #setName(String)}. 251 * 252 * @param value 253 * The new value for this property. 254 * <br>Non-String values will be converted to String using <c>toString()</c>. 255 * <br>Can be <jk>null</jk> to unset the property. 256 * @return This object (for method chaining). 257 */ 258 public SecurityScheme name(Object value) { 259 return setName(stringify(value)); 260 } 261 262 /** 263 * Bean property getter: <property>in</property>. 264 * 265 * <p> 266 * The location of the API key. 267 * 268 * @return The property value, or <jk>null</jk> if it is not set. 269 */ 270 public String getIn() { 271 return in; 272 } 273 274 /** 275 * Bean property setter: <property>in</property>. 276 * 277 * <p> 278 * The location of the API key. 279 * 280 * @param value 281 * The new value for this property. 282 * <br>Valid values: 283 * <ul> 284 * <li><js>"query"</js> 285 * <li><js>"header"</js> 286 * </ul> 287 * <br>Can be <jk>null</jk> to unset the property. 288 * @return This object (for method chaining). 289 */ 290 public SecurityScheme setIn(String value) { 291 in = value; 292 return this; 293 } 294 295 /** 296 * Same as {@link #setIn(String)}. 297 * 298 * @param value 299 * The new value for this property. 300 * <br>Non-String values will be converted to String using <c>toString()</c>. 301 * <br>Valid values: 302 * <ul> 303 * <li><js>"query"</js> 304 * <li><js>"header"</js> 305 * </ul> 306 * <br>Can be <jk>null</jk> to unset the property. 307 * @return This object (for method chaining). 308 */ 309 public SecurityScheme in(Object value) { 310 return setIn(stringify(value)); 311 } 312 313 /** 314 * Bean property getter: <property>flow</property>. 315 * 316 * <p> 317 * The flow used by the OAuth2 security scheme. 318 * 319 * @return The property value, or <jk>null</jk> if it is not set. 320 */ 321 public String getFlow() { 322 return flow; 323 } 324 325 /** 326 * Bean property setter: <property>flow</property>. 327 * 328 * <p> 329 * The flow used by the OAuth2 security scheme. 330 * 331 * @param value 332 * The new value for this property. 333 * <br>Valid values: 334 * <ul> 335 * <li><js>"implicit"</js> 336 * <li><js>"password"</js> 337 * <li><js>"application"</js> 338 * <li><js>"accessCode"</js> 339 * </ul> 340 * <br>Can be <jk>null</jk> to unset the property. 341 * @return This object (for method chaining). 342 */ 343 public SecurityScheme setFlow(String value) { 344 flow = value; 345 return this; 346 } 347 348 /** 349 * Same as {@link #setFlow(String)}. 350 * 351 * @param value 352 * The new value for this property. 353 * <br>Non-String values will be converted to String using <c>toString()</c>. 354 * <br>Valid values: 355 * <ul> 356 * <li><js>"implicit"</js> 357 * <li><js>"password"</js> 358 * <li><js>"application"</js> 359 * <li><js>"accessCode"</js> 360 * </ul> 361 * <br>Can be <jk>null</jk> to unset the property. 362 * @return This object (for method chaining). 363 */ 364 public SecurityScheme flow(Object value) { 365 return setFlow(stringify(value)); 366 } 367 368 /** 369 * Bean property getter: <property>authorizationUrl</property>. 370 * 371 * <p> 372 * The authorization URL to be used for this flow. 373 * 374 * @return The property value, or <jk>null</jk> if it is not set. 375 */ 376 public String getAuthorizationUrl() { 377 return authorizationUrl; 378 } 379 380 /** 381 * Bean property setter: <property>authorizationUrl</property>. 382 * 383 * <p> 384 * The authorization URL to be used for this flow. 385 * 386 * @param value 387 * The new value for this property. 388 * <br>This SHOULD be in the form of a URL. 389 * <br>Can be <jk>null</jk> to unset the property. 390 * @return This object (for method chaining). 391 */ 392 public SecurityScheme setAuthorizationUrl(String value) { 393 authorizationUrl = value; 394 return this; 395 } 396 397 /** 398 * Same as {@link #setAuthorizationUrl(String)}. 399 * 400 * @param value 401 * The new value for this property. 402 * <br>Non-String values will be converted to String using <c>toString()</c>. 403 * <br>This SHOULD be in the form of a URL. 404 * <br>Can be <jk>null</jk> to unset the property. 405 * @return This object (for method chaining). 406 */ 407 public SecurityScheme authorizationUrl(Object value) { 408 return setAuthorizationUrl(stringify(value)); 409 } 410 411 /** 412 * Bean property getter: <property>tokenUrl</property>. 413 * 414 * <p> 415 * The token URL to be used for this flow. 416 * 417 * @return The property value, or <jk>null</jk> if it is not set. 418 */ 419 public String getTokenUrl() { 420 return tokenUrl; 421 } 422 423 /** 424 * Bean property setter: <property>tokenUrl</property>. 425 * 426 * <p> 427 * The token URL to be used for this flow. 428 * 429 * @param value 430 * The new value for this property. 431 * <br>This SHOULD be in the form of a URL. 432 * <br>Can be <jk>null</jk> to unset the property. 433 * @return This object (for method chaining). 434 */ 435 public SecurityScheme setTokenUrl(String value) { 436 tokenUrl = value; 437 return this; 438 } 439 440 /** 441 * Same as {@link #setTokenUrl(String)}. 442 * 443 * @param value 444 * The new value for this property. 445 * <br>Non-String values will be converted to String using <c>toString()</c>. 446 * <br>This SHOULD be in the form of a URL. 447 * <br>Can be <jk>null</jk> to unset the property. 448 * @return This object (for method chaining). 449 */ 450 public SecurityScheme tokenUrl(Object value) { 451 return setTokenUrl(stringify(value)); 452 } 453 454 /** 455 * Bean property getter: <property>scopes</property>. 456 * 457 * <p> 458 * The available scopes for the OAuth2 security scheme. 459 * 460 * @return The property value, or <jk>null</jk> if it is not set. 461 */ 462 public Map<String,String> getScopes() { 463 return scopes; 464 } 465 466 /** 467 * Bean property setter: <property>scopes</property>. 468 * 469 * <p> 470 * The available scopes for the OAuth2 security scheme. 471 * 472 * @param value 473 * The new value for this property. 474 * <br>Can be <jk>null</jk> to unset the property. 475 * @return This object (for method chaining). 476 */ 477 public SecurityScheme setScopes(Map<String,String> value) { 478 scopes = newMap(value); 479 return this; 480 } 481 482 /** 483 * Adds one or more values to the <property>scopes</property> property. 484 * 485 * @param values 486 * The values to add to this property. 487 * <br>Ignored if <jk>null</jk>. 488 * @return This object (for method chaining). 489 */ 490 public SecurityScheme addScopes(Map<String,String> values) { 491 scopes = addToMap(scopes, values); 492 return this; 493 } 494 495 /** 496 * Adds one or more values to the <property>enum</property> property. 497 * 498 * @param values 499 * The values to add to this property. 500 * <br>Valid types: 501 * <ul> 502 * <li><c>Map<String,{@link HeaderInfo}|String></c> 503 * <li><c>String</c> - JSON object representation of <c>Map<String,{@link HeaderInfo}></c> 504 * <h5 class='figure'>Example:</h5> 505 * <p class='bcode w800'> 506 * scopes(<js>"{name:'value'}"</js>); 507 * </p> 508 * </ul> 509 * <br>Ignored if <jk>null</jk>. 510 * @return This object (for method chaining). 511 */ 512 public SecurityScheme scopes(Object...values) { 513 scopes = addToMap(scopes, values, String.class, String.class); 514 return this; 515 } 516 517 @Override /* SwaggerElement */ 518 public <T> T get(String property, Class<T> type) { 519 if (property == null) 520 return null; 521 switch (property) { 522 case "type": return toType(getType(), type); 523 case "description": return toType(getDescription(), type); 524 case "name": return toType(getName(), type); 525 case "in": return toType(getIn(), type); 526 case "flow": return toType(getFlow(), type); 527 case "authorizationUrl": return toType(getAuthorizationUrl(), type); 528 case "tokenUrl": return toType(getTokenUrl(), type); 529 case "scopes": return toType(getScopes(), type); 530 default: return super.get(property, type); 531 } 532 } 533 534 @Override /* SwaggerElement */ 535 public SecurityScheme set(String property, Object value) { 536 if (property == null) 537 return this; 538 switch (property) { 539 case "type": return type(value); 540 case "description": return description(value); 541 case "name": return name(value); 542 case "in": return in(value); 543 case "flow": return flow(value); 544 case "authorizationUrl": return authorizationUrl(value); 545 case "tokenUrl": return tokenUrl(value); 546 case "scopes": return setScopes(null).scopes(value); 547 default: 548 super.set(property, value); 549 return this; 550 } 551 } 552 553 @Override /* SwaggerElement */ 554 public Set<String> keySet() { 555 ASet<String> s = new ASet<String>() 556 .appendIf(type != null, "type") 557 .appendIf(description != null, "description") 558 .appendIf(name != null, "name") 559 .appendIf(in != null, "in") 560 .appendIf(flow != null, "flow") 561 .appendIf(authorizationUrl != null, "authorizationUrl") 562 .appendIf(tokenUrl != null, "tokenUrl") 563 .appendIf(scopes != null, "scopes"); 564 return new MultiSet<>(s, super.keySet()); 565 } 566}