001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.bean.openapi3;
018
019import static org.apache.juneau.commons.utils.CollectionUtils.*;
020import static org.apache.juneau.bean.openapi3.OpenApiCopyUtils.*;
021import static org.apache.juneau.commons.utils.CollectionUtils.contains;
022import static org.apache.juneau.commons.utils.Shorts.*;
023import static org.apache.juneau.commons.utils.StringUtils.*;
024import static org.apache.juneau.marshall.internal.ConverterUtils.*;
025
026import java.util.*;
027
028import org.apache.juneau.commons.collections.*;
029
030/**
031 * Defines a security scheme that can be used by the operations.
032 *
033 * <p>
034 * The Security Scheme Object defines a security scheme that can be used by the operations. Supported schemes are
035 * HTTP authentication, an API key (either as a header or as a query parameter), OAuth2's common flows (implicit,
036 * password, client credentials and authorization code) as defined in RFC6749, and OpenID Connect Discovery.
037 *
038 * <h5 class='section'>OpenAPI Specification:</h5>
039 * <p>
040 * The Security Scheme Object is composed of the following fields:
041 * <ul class='spaced-list'>
042 *    <li><c>type</c> (string, REQUIRED) - The type of the security scheme. Values: <js>"apiKey"</js>, <js>"http"</js>, <js>"oauth2"</js>, <js>"openIdConnect"</js>
043 *    <li><c>description</c> (string) - A short description for security scheme (CommonMark syntax may be used)
044 *    <li><c>name</c> (string) - The name of the header, query or cookie parameter to be used (for <js>"apiKey"</js> type)
045 *    <li><c>in</c> (string) - The location of the API key (for <js>"apiKey"</js> type). Values: <js>"query"</js>, <js>"header"</js>, <js>"cookie"</js>
046 *    <li><c>scheme</c> (string) - The name of the HTTP Authorization scheme to be used in the Authorization header (for <js>"http"</js> type)
047 *    <li><c>bearerFormat</c> (string) - A hint to the client to identify how the bearer token is formatted (for <js>"http"</js> type with <js>"bearer"</js> scheme)
048 *    <li><c>flows</c> ({@link OAuthFlows}) - An object containing configuration information for the flow types supported (for <js>"oauth2"</js> type)
049 *    <li><c>openIdConnectUrl</c> (string) - OpenId Connect URL to discover OAuth2 configuration values (for <js>"openIdConnect"</js> type)
050 * </ul>
051 *
052 * <h5 class='section'>Example:</h5>
053 * <p class='bjava'>
054 *    <jc>// Create an API key security scheme</jc>
055 *    SecuritySchemeInfo <jv>scheme</jv> = <jk>new</jk> SecuritySchemeInfo()
056 *       .setType(<js>"apiKey"</js>)
057 *       .setDescription(<js>"API key authentication"</js>)
058 *       .setName(<js>"X-API-Key"</js>)
059 *       .setIn(<js>"header"</js>);
060 * </p>
061 * <p class='bjava'>
062 *    <jc>// Create an OAuth2 security scheme</jc>
063 *    SecuritySchemeInfo <jv>oauthScheme</jv> = <jk>new</jk> SecuritySchemeInfo()
064 *       .setType(<js>"oauth2"</js>)
065 *       .setDescription(<js>"OAuth2 authentication"</js>)
066 *       .setFlows(
067 *          <jk>new</jk> OAuthFlows()
068 *             .setAuthorizationCode(
069 *                <jk>new</jk> OAuthFlow()
070 *                   .setAuthorizationUrl(<js>"https://example.com/oauth/authorize"</js>)
071 *                   .setTokenUrl(<js>"https://example.com/oauth/token"</js>)
072 *                   .setScopes(
073 *                      JsonMap.<jsm>of</jsm>(
074 *                         <js>"read"</js>, <js>"Read access to resources"</js>,
075 *                         <js>"write"</js>, <js>"Write access to resources"</js>
076 *                      )
077 *                   )
078 *             )
079 *       );
080 * </p>
081 *
082 * <h5 class='section'>See Also:</h5><ul>
083 *    <li class='link'><a class="doclink" href="https://spec.openapis.org/oas/v3.0.0#security-scheme-object">OpenAPI Specification &gt; Security Scheme Object</a>
084 *    <li class='link'><a class="doclink" href="https://swagger.io/docs/specification/authentication/">OpenAPI Authentication</a>
085 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauBeanOpenApi3">juneau-bean-openapi-v3</a>
086 * </ul>
087 */
088@SuppressWarnings({
089   "java:S1192" // Duplicated literals (argument/property names) read more clearly inline than as constants
090})
091public class SecuritySchemeInfo extends OpenApiElement {
092
093   private static final String[] VALID_IN = { "query", "header", "cookie" };
094   private static final String[] VALID_TYPES = { "apiKey", "http", "oauth2", "openIdConnect" };
095
096   private String type;
097   private String description;
098   private String name;
099   private String in;
100   private String scheme;
101   private String bearerFormat;
102   private String openIdConnectUrl;
103
104   private OAuthFlow flows;
105
106   /**
107    * Default constructor.
108    */
109   public SecuritySchemeInfo() {}
110
111   /**
112    * Copy constructor.
113    *
114    * @param copyFrom The object to copy.
115    */
116   public SecuritySchemeInfo(SecuritySchemeInfo copyFrom) {
117      super(copyFrom);
118
119      this.name = copyFrom.name;
120      this.in = copyFrom.in;
121      this.description = copyFrom.description;
122      this.type = copyFrom.type;
123      this.scheme = copyFrom.scheme;
124      this.bearerFormat = copyFrom.bearerFormat;
125      this.openIdConnectUrl = copyFrom.openIdConnectUrl;
126      this.flows = copyOf(copyFrom.flows);
127   }
128
129   /**
130    * Make a deep copy of this object.
131    *
132    * @return A deep copy of this object.
133    */
134   public SecuritySchemeInfo copy() {
135      return new SecuritySchemeInfo(this);
136   }
137
138   @Override /* Overridden from SwaggerElement */
139   public <T> T get(String property, Class<T> type) {
140      reqnn("property", property);
141      return switch (property) {
142         case "name" -> toType(getName(), type);
143         case "in" -> toType(getIn(), type);
144         case "description" -> toType(getDescription(), type);
145         case "scheme" -> toType(getScheme(), type);
146         case "flows" -> toType(getFlows(), type);
147         case "bearerFormat" -> toType(getBearerFormat(), type);
148         case "openIdConnectUrl" -> toType(getOpenIdConnectUrl(), type);
149         case "type" -> toType(getType(), type);
150         default -> super.get(property, type);
151      };
152   }
153
154   /**
155    * Bean property getter:  <property>bearerFormat</property>.
156    *
157    * <p>
158    * A hint to the client to identify how the bearer token is formatted.
159    *
160    * @return The property value, or <jk>null</jk> if it is not set.
161    */
162   public String getBearerFormat() { return bearerFormat; }
163
164   /**
165    * Bean property getter:  <property>description</property>.
166    *
167    * <p>
168    * A short description for the security scheme.
169    *
170    * @return The property value, or <jk>null</jk> if it is not set.
171    */
172   public String getDescription() { return description; }
173
174   /**
175    * Bean property getter:  <property>flows</property>.
176    *
177    * <p>
178    * An object containing configuration information for the flow types supported.
179    *
180    * @return The property value, or <jk>null</jk> if it is not set.
181    */
182   public OAuthFlow getFlows() { return flows; }
183
184   /**
185    * Bean property getter:  <property>in</property>.
186    *
187    * <p>
188    * The location of the API key.
189    *
190    * @return The property value, or <jk>null</jk> if it is not set.
191    */
192   public String getIn() { return in; }
193
194   /**
195    * Bean property getter:  <property>name</property>.
196    *
197    * <p>
198    * The name of the header, query or cookie parameter to be used.
199    *
200    * @return The property value, or <jk>null</jk> if it is not set.
201    */
202   public String getName() { return name; }
203
204   /**
205    * Bean property getter:  <property>openIdConnectUrl</property>.
206    *
207    * <p>
208    * OpenId Connect URL to discover OAuth2 configuration values.
209    *
210    * @return The property value, or <jk>null</jk> if it is not set.
211    */
212   public String getOpenIdConnectUrl() { return openIdConnectUrl; }
213
214   /**
215    * Bean property getter:  <property>scheme</property>.
216    *
217    * <p>
218    * The name of the HTTP Authorization scheme to be used in the Authorization header.
219    *
220    * @return The property value, or <jk>null</jk> if it is not set.
221    */
222   public String getScheme() { return scheme; }
223
224   /**
225    * Bean property getter:  <property>type</property>.
226    *
227    * <p>
228    * The type of the security scheme.
229    *
230    * @return The property value, or <jk>null</jk> if it is not set.
231    */
232   public String getType() { return type; }
233
234   @Override /* Overridden from SwaggerElement */
235   public Set<String> keySet() {
236      // @formatter:off
237      var s = stb(String.class)
238         .addIf(nn(bearerFormat), "bearerFormat")
239         .addIf(nn(description), "description")
240         .addIf(nn(flows), "flows")
241         .addIf(nn(in), "in")
242         .addIf(nn(name), "name")
243         .addIf(nn(openIdConnectUrl), "openIdConnectUrl")
244         .addIf(nn(scheme), "scheme")
245         .addIf(nn(type), "type")
246         .build();
247      // @formatter:on
248      return new MultiSet<>(s, super.keySet());
249   }
250
251   @Override /* Overridden from SwaggerElement */
252   public SecuritySchemeInfo set(String property, Object value) {
253      reqnn("property", property);
254      return switch (property) {
255         case "bearerFormat" -> setBearerFormat(s(value));
256         case "description" -> setDescription(s(value));
257         case "flows" -> setFlows(toType(value, OAuthFlow.class));
258         case "in" -> setIn(s(value));
259         case "name" -> setName(s(value));
260         case "openIdConnectUrl" -> setOpenIdConnectUrl(s(value));
261         case "scheme" -> setScheme(s(value));
262         case "type" -> setType(s(value));
263         default -> {
264            super.set(property, value);
265            yield this;
266         }
267      };
268   }
269
270   /**
271    * Bean property setter:  <property>bearerFormat</property>.
272    *
273    * <p>
274    * A hint to the client to identify how the bearer token is formatted.
275    *
276    * @param value The new value for this property.
277    *    <br>Can be <jk>null</jk> to unset the property.
278    * @return This object
279    */
280   public SecuritySchemeInfo setBearerFormat(String value) {
281      bearerFormat = value;
282      return this;
283   }
284
285   /**
286    * Bean property setter:  <property>description</property>.
287    *
288    * <p>
289    * A short description for the security scheme.
290    *
291    * @param value
292    *    The new value for this property.
293    *    <br>Can be <jk>null</jk> to unset the property.
294    * @return This object
295    */
296   public SecuritySchemeInfo setDescription(String value) {
297      description = value;
298      return this;
299   }
300
301   /**
302    * Bean property setter:  <property>flows</property>.
303    *
304    * <p>
305    * An object containing configuration information for the flow types supported.
306    *
307    * @param value
308    *    The new value for this property.
309    *    <br>Can be <jk>null</jk> to unset the property.
310    * @return This object
311    */
312   public SecuritySchemeInfo setFlows(OAuthFlow value) {
313      flows = value;
314      return this;
315   }
316
317   /**
318    * Bean property setter:  <property>in</property>.
319    *
320    * <p>
321    * The location of the API key.
322    *
323    * @param value
324    *    The new value for this property.
325    *    <br>Valid values:
326    *    <ul>
327    *       <li><js>"query"</js>
328    *       <li><js>"header"</js>
329    *       <li><js>"cookie"</js>
330    *    </ul>
331    *    <br>Can be <jk>null</jk> to unset the property.
332    * @return This object
333    */
334   public SecuritySchemeInfo setIn(String value) {
335      if (isStrict() && ! contains(value, VALID_IN))
336         throw rex("Invalid value passed in to setIn(String).  Value='%s', valid values=[%s]", value, toCdl(VALID_IN));
337      in = value;
338      return this;
339   }
340
341   /**
342    * Bean property setter:  <property>name</property>.
343    *
344    * <p>
345    * The name of the header, query or cookie parameter to be used.
346    *
347    * @param value
348    *    The new value for this property.
349    *    <br>Can be <jk>null</jk> to unset the property.
350    * @return This object
351    */
352   public SecuritySchemeInfo setName(String value) {
353      name = value;
354      return this;
355   }
356
357   /**
358    * Bean property setter:  <property>openIdConnectUrl</property>.
359    *
360    * <p>
361    * OpenId Connect URL to discover OAuth2 configuration values.
362    *
363    * @param value The new value for this property.
364    *    <br>Can be <jk>null</jk> to unset the property.
365    * @return This object
366    */
367   public SecuritySchemeInfo setOpenIdConnectUrl(String value) {
368      openIdConnectUrl = value;
369      return this;
370   }
371
372   /**
373    * Bean property setter:  <property>scheme</property>.
374    *
375    * <p>
376    * The name of the HTTP Authorization scheme to be used in the Authorization header.
377    *
378    * @param value
379    *    The new value for this property.
380    *    <br>Can be <jk>null</jk> to unset the property.
381    * @return This object
382    */
383   public SecuritySchemeInfo setScheme(String value) {
384      scheme = value;
385      return this;
386   }
387
388   /**
389    * Bean property setter:  <property>type</property>.
390    *
391    * <p>
392    * The type of the security scheme.
393    *
394    * @param value
395    *    The new value for this property.
396    *    <br>Valid values:
397    *    <ul>
398    *       <li><js>"apiKey"</js>
399    *       <li><js>"http"</js>
400    *       <li><js>"oauth2"</js>
401    *       <li><js>"openIdConnect"</js>
402    *    </ul>
403    *    <br>Can be <jk>null</jk> to unset the property.
404    * @return This object
405    */
406   public SecuritySchemeInfo setType(String value) {
407      if (isStrict() && ! contains(value, VALID_TYPES))
408         throw rex("Invalid value passed in to setType(String).  Value='%s', valid values=[%s]", value, toCdl(VALID_TYPES));
409      type = value;
410      return this;
411   }
412
413   @Override /* Overridden from OpenApiElement */
414   public SecuritySchemeInfo strict(Object value) {
415      super.strict(value);
416      return this;
417   }
418
419   @Override /* Overridden from SwaggerElement */
420   protected SecuritySchemeInfo strict() {
421      super.strict();
422      return this;
423   }
424}