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.common.utils.Utils.*; 020import static org.apache.juneau.internal.CollectionUtils.*; 021import static org.apache.juneau.internal.ConverterUtils.*; 022 023import java.util.*; 024 025import org.apache.juneau.common.utils.*; 026import org.apache.juneau.internal.*; 027 028/** 029 * Configuration details for a supported OAuth Flow. 030 * 031 * <p> 032 * The OAuthFlow Object provides configuration details for a supported OAuth Flow. This object contains the URLs and 033 * scopes needed to configure a specific OAuth 2.0 flow. Different flows require different combinations of URLs and 034 * have different security characteristics. 035 * 036 * <h5 class='section'>OpenAPI Specification:</h5> 037 * <p> 038 * The OAuthFlow Object is composed of the following fields: 039 * <ul class='spaced-list'> 040 * <li><c>authorizationUrl</c> (string) - The authorization URL to be used for this flow. This MUST be in the form of a URL 041 * <li><c>tokenUrl</c> (string) - The token URL to be used for this flow. This MUST be in the form of a URL 042 * <li><c>refreshUrl</c> (string) - The URL to be used for obtaining refresh tokens. This MUST be in the form of a URL 043 * <li><c>scopes</c> (map of strings) - The available scopes for the OAuth2 security scheme. A map between the scope name and a short description for it 044 * </ul> 045 * 046 * <h5 class='section'>Example:</h5> 047 * <p class='bcode'> 048 * <jc>// Construct using SwaggerBuilder.</jc> 049 * OAuthFlow <jv>x</jv> = <jsm>oauthFlow</jsm>() 050 * .setAuthorizationUrl(<js>"https://example.com/oauth/authorize"</js>) 051 * .setTokenUrl(<js>"https://example.com/oauth/token"</js>) 052 * .setScopes(<jsm>map</jsm>(<js>"read"</js>, <js>"Read access"</js>, <js>"write"</js>, <js>"Write access"</js>)); 053 * 054 * <jc>// Serialize using JsonSerializer.</jc> 055 * String <jv>json</jv> = Json.<jsm>from</jsm>(<jv>x</jv>); 056 * 057 * <jc>// Or just use toString() which does the same as above.</jc> 058 * <jv>json</jv> = <jv>x</jv>.toString(); 059 * </p> 060 * <p class='bcode'> 061 * <jc>// Output</jc> 062 * { 063 * <js>"authorizationUrl"</js>: <js>"https://example.com/oauth/authorize"</js>, 064 * <js>"tokenUrl"</js>: <js>"https://example.com/oauth/token"</js>, 065 * <js>"scopes"</js>: { 066 * <js>"read"</js>: <js>"Read access"</js>, 067 * <js>"write"</js>: <js>"Write access"</js> 068 * } 069 * } 070 * </p> 071 * 072 * <h5 class='section'>See Also:</h5><ul> 073 * <li class='link'><a class="doclink" href="https://spec.openapis.org/oas/v3.0.0#oauth-flow-object">OpenAPI Specification > OAuth Flow Object</a> 074 * <li class='link'><a class="doclink" href="https://swagger.io/docs/specification/authentication/oauth2/">OpenAPI OAuth2 Authentication</a> 075 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauBeanOpenApi3">juneau-bean-openapi-v3</a> 076 * </ul> 077 */ 078public class OAuthFlow extends OpenApiElement { 079 080 private String authorizationUrl; 081 private String tokenUrl; 082 private String refreshUrl; 083 private Map<String,String> scopes; 084 085 /** 086 * Default constructor. 087 */ 088 public OAuthFlow() {} 089 090 /** 091 * Copy constructor. 092 * 093 * @param copyFrom The object to copy. 094 */ 095 public OAuthFlow(OAuthFlow copyFrom) { 096 super(copyFrom); 097 098 this.authorizationUrl = copyFrom.authorizationUrl; 099 this.tokenUrl = copyFrom.tokenUrl; 100 this.refreshUrl = copyFrom.refreshUrl; 101 this.scopes = copyOf(copyFrom.scopes); 102 } 103 104 /** 105 * Make a deep copy of this object. 106 * 107 * @return A deep copy of this object. 108 */ 109 public OAuthFlow copy() { 110 return new OAuthFlow(this); 111 } 112 113 /** 114 * Bean property getter: <property>operationRef</property>. 115 * 116 * <p> 117 * The identifying name of the contact person/organization. 118 * 119 * @return The property value, or <jk>null</jk> if it is not set. 120 */ 121 public String getAuthorizationUrl() { 122 return authorizationUrl; 123 } 124 125 /** 126 * Bean property setter: <property>operationRef</property>. 127 * 128 * <p> 129 * The identifying name of the contact person/organization. 130 * 131 * @param value 132 * The new value for this property. 133 * <br>Can be <jk>null</jk> to unset the property. 134 * @return This object 135 */ 136 public OAuthFlow setAuthorizationUrl(String value) { 137 authorizationUrl = value; 138 return this; 139 } 140 141 /** 142 * Bean property getter: <property>description</property>. 143 * 144 * <p> 145 * The URL pointing to the contact information. 146 * 147 * @return The property value, or <jk>null</jk> if it is not set. 148 */ 149 public String getTokenUrl() { 150 return tokenUrl; 151 } 152 153 /** 154 * Bean property setter: <property>description</property>. 155 * @param value 156 * The new value for this property. 157 * <br>Can be <jk>null</jk> to unset the property. 158 * @return This object 159 */ 160 public OAuthFlow setTokenUrl(String value) { 161 tokenUrl = value; 162 return this; 163 } 164 165 /** 166 * Bean property getter: <property>externalValue</property>. 167 * 168 * <p> 169 * The email address of the contact person/organization. 170 * 171 * @return The property value, or <jk>null</jk> if it is not set. 172 */ 173 public String getRefreshUrl() { 174 return refreshUrl; 175 } 176 177 /** 178 * Bean property setter: <property>externalValue</property>. 179 * 180 * <p> 181 * The email address of the contact person/organization. 182 * 183 * @param value 184 * The new value for this property. 185 * <br>MUST be in the format of an email address. 186 * <br>Can be <jk>null</jk> to unset the property. 187 * @return This object 188 */ 189 public OAuthFlow setRefreshUrl(String value) { 190 refreshUrl = value; 191 return this; 192 } 193 194 /** 195 * Bean property getter: <property>examples</property>. 196 * 197 * <p> 198 * An example of the response message. 199 * 200 * @return The property value, or <jk>null</jk> if it is not set. 201 */ 202 public Map<String,String> getScopes() { 203 return scopes; 204 } 205 206 /** 207 * Bean property setter: <property>examples</property>. 208 * 209 * <p> 210 * An example of the response message. 211 * 212 * @param value 213 * The new value for this property. 214 * <br>Keys must be MIME-type strings. 215 * <br>Can be <jk>null</jk> to unset the property. 216 * @return This object 217 */ 218 public OAuthFlow setScopes(Map<String,String> value) { 219 scopes = copyOf(value); 220 return this; 221 } 222 223 /** 224 * Adds a single value to the <property>examples</property> property. 225 * 226 * @param name The mime-type string. Must not be <jk>null</jk>. 227 * @param description The example. Must not be <jk>null</jk>. 228 * @return This object 229 */ 230 public OAuthFlow addScope(String name, String description) { 231 assertArgNotNull("name", name); 232 assertArgNotNull("description", description); 233 scopes = mapBuilder(scopes).sparse().add(name, description).build(); 234 return this; 235 } 236 237 @Override /* Overridden from OpenApiElement */ 238 public <T> T get(String property, Class<T> type) { 239 assertArgNotNull("property", property); 240 return switch (property) { 241 case "refreshUrl" -> toType(getRefreshUrl(), type); 242 case "tokenUrl" -> toType(getTokenUrl(), type); 243 case "authorizationUrl" -> toType(getAuthorizationUrl(), type); 244 case "scopes" -> toType(getScopes(), type); 245 default -> super.get(property, type); 246 }; 247 } 248 249 @Override /* Overridden from OpenApiElement */ 250 public OAuthFlow set(String property, Object value) { 251 assertArgNotNull("property", property); 252 return switch (property) { 253 case "authorizationUrl" -> setAuthorizationUrl(Utils.s(value)); 254 case "refreshUrl" -> setRefreshUrl(Utils.s(value)); 255 case "scopes" -> setScopes(mapBuilder(String.class,String.class).sparse().addAny(value).build()); 256 case "tokenUrl" -> setTokenUrl(Utils.s(value)); 257 default -> { 258 super.set(property, value); 259 yield this; 260 } 261 }; 262 } 263 264 @Override /* Overridden from OpenApiElement */ 265 public Set<String> keySet() { 266 var s = setBuilder(String.class) 267 .addIf(authorizationUrl != null, "authorizationUrl") 268 .addIf(refreshUrl != null, "refreshUrl") 269 .addIf(scopes != null, "scopes") 270 .addIf(tokenUrl != null, "tokenUrl") 271 .build(); 272 return new MultiSet<>(s, super.keySet()); 273 } 274 275 @Override /* Overridden from OpenApiElement */ 276 public OAuthFlow strict() { 277 super.strict(); 278 return this; 279 } 280 281 @Override /* Overridden from OpenApiElement */ 282 public OAuthFlow strict(Object value) { 283 super.strict(value); 284 return this; 285 } 286 287}