@@ -171,10 +171,10 @@ public class AccountOwnedResource<E extends HasAccount, DAO extends AccountOwned | |||
@Operation(security=@SecurityRequirement(name=SEC_API_KEY), | |||
tags={API_TAG_ACCOUNT_OBJECTS}, | |||
summary="Create a new object", | |||
description="Create a new object. If validation errors occur, status "+SC_PRECONDITION_FAILED+" is returned and the response will contain an array of errors. Within each error, the `messageTemplate` field refers to messages that can be localized using the /messages resource", | |||
description="Create a new object. If validation errors occur, status "+SC_INVALID+" is returned and the response will contain an array of errors. Within each error, the `messageTemplate` field refers to messages that can be localized using the /messages resource", | |||
responses={ | |||
@ApiResponse(responseCode=SC_OK, description="the object that was created"), | |||
@ApiResponse(responseCode=SC_PRECONDITION_FAILED, description="validation errors occurred", | |||
@ApiResponse(responseCode=SC_INVALID, description="validation errors occurred", | |||
content={@Content(mediaType=APPLICATION_JSON, examples={ | |||
@ExampleObject(name="validation errors", value="[{\"messageTemplate\": \"some.symbolic.error\", \"message\": \"some default English message\"}]") | |||
})}) | |||
@@ -212,12 +212,12 @@ public class AccountOwnedResource<E extends HasAccount, DAO extends AccountOwned | |||
@Operation(security=@SecurityRequirement(name=SEC_API_KEY), | |||
tags={API_TAG_ACCOUNT_OBJECTS}, | |||
summary="Update an existing object", | |||
description="Update an new object. For many types, the object will be created if it does not exist. If validation errors occur, status "+SC_PRECONDITION_FAILED+" is returned and the response will contain an array of errors. Within each error, the `messageTemplate` field refers to messages that can be localized using the /messages resource", | |||
description="Update an new object. For many types, the object will be created if it does not exist. If validation errors occur, status "+SC_INVALID+" is returned and the response will contain an array of errors. Within each error, the `messageTemplate` field refers to messages that can be localized using the /messages resource", | |||
parameters={@Parameter(name="id", description="the UUID (or name, if allowed) of the object to update")}, | |||
responses={ | |||
@ApiResponse(responseCode=SC_OK, description="the object that was updated"), | |||
@ApiResponse(responseCode=SC_NOT_FOUND, description="no object exists with the given id"), | |||
@ApiResponse(responseCode=SC_PRECONDITION_FAILED, description="validation errors occurred", | |||
@ApiResponse(responseCode=SC_INVALID, description="validation errors occurred", | |||
content={@Content(mediaType=APPLICATION_JSON, examples={ | |||
@ExampleObject(name="validation errors", value="[{\"messageTemplate\": \"some.symbolic.error\", \"message\": \"some default English message\"}]") | |||
})}) | |||
@@ -203,7 +203,7 @@ public class AccountsResource { | |||
responses={ | |||
@ApiResponse(responseCode=SC_OK, description="the Account object that was updated"), | |||
@ApiResponse(responseCode=SC_FORBIDDEN, description="forbidden if caller is not admin and is updating any account Account other than themselves"), | |||
@ApiResponse(responseCode=SC_PRECONDITION_FAILED, description="validation errors occurred") | |||
@ApiResponse(responseCode=SC_INVALID, description="validation errors occurred") | |||
} | |||
) | |||
public Response updateUser(@Context ContainerRequest ctx, | |||
@@ -282,7 +282,7 @@ public class AccountsResource { | |||
responses={ | |||
@ApiResponse(responseCode=SC_OK, description="an AccountPolicy object"), | |||
@ApiResponse(responseCode=SC_FORBIDDEN, description="forbidden if caller is not admin and is accessing any account Account other than themselves"), | |||
@ApiResponse(responseCode=SC_PRECONDITION_FAILED, description="validation errors occurred") | |||
@ApiResponse(responseCode=SC_INVALID, description="validation errors occurred") | |||
} | |||
) | |||
public Response updatePolicy(@Context ContainerRequest ctx, | |||
@@ -312,7 +312,7 @@ public class AccountsResource { | |||
responses={ | |||
@ApiResponse(responseCode=SC_OK, description="the AccountContact object that was created or updated"), | |||
@ApiResponse(responseCode=SC_FORBIDDEN, description="forbidden if caller is not admin and is accessing any account Account other than themselves"), | |||
@ApiResponse(responseCode=SC_PRECONDITION_FAILED, description="validation errors occurred") | |||
@ApiResponse(responseCode=SC_INVALID, description="validation errors occurred") | |||
} | |||
) | |||
public Response setContact(@Context Request req, | |||
@@ -518,7 +518,7 @@ public class AccountsResource { | |||
responses={ | |||
@ApiResponse(responseCode=SC_OK, description="the Account object that was updated"), | |||
@ApiResponse(responseCode=SC_FORBIDDEN, description="forbidden if caller is not admin and is accessing any account Account other than themselves"), | |||
@ApiResponse(responseCode=SC_PRECONDITION_FAILED, description="validation errors occurred") | |||
@ApiResponse(responseCode=SC_INVALID, description="validation errors occurred") | |||
} | |||
) | |||
public Response rootChangePassword(@Context Request req, | |||
@@ -640,7 +640,7 @@ public class AccountsResource { | |||
@ExampleObject(name="mitmproxy is disabled", value="false") | |||
})}), | |||
@ApiResponse(responseCode=SC_FORBIDDEN, description="forbidden if caller is not admin"), | |||
@ApiResponse(responseCode=SC_PRECONDITION_FAILED, description="if mitmproxy not installed") | |||
@ApiResponse(responseCode=SC_INVALID, description="if mitmproxy not installed") | |||
} | |||
) | |||
public Response mitmStatus(@Context ContainerRequest ctx, | |||
@@ -663,7 +663,7 @@ public class AccountsResource { | |||
@ExampleObject(name="mitmproxy is disabled", value="false") | |||
})}), | |||
@ApiResponse(responseCode=SC_FORBIDDEN, description="forbidden if caller is not admin"), | |||
@ApiResponse(responseCode=SC_PRECONDITION_FAILED, description="if mitmproxy is not installed or an error occurred enabling it") | |||
@ApiResponse(responseCode=SC_INVALID, description="if mitmproxy is not installed or an error occurred enabling it") | |||
} | |||
) | |||
public Response mitmOn(@Context ContainerRequest ctx, | |||
@@ -686,7 +686,7 @@ public class AccountsResource { | |||
@ExampleObject(name="mitmproxy is disabled", value="false") | |||
})}), | |||
@ApiResponse(responseCode=SC_FORBIDDEN, description="forbidden if caller is not admin"), | |||
@ApiResponse(responseCode=SC_PRECONDITION_FAILED, description="if mitmproxy is not installed or an error occurred disabling it") | |||
@ApiResponse(responseCode=SC_INVALID, description="if mitmproxy is not installed or an error occurred disabling it") | |||
} | |||
) | |||
public Response mitmOff(@Context ContainerRequest ctx, | |||
@@ -40,6 +40,7 @@ import io.swagger.v3.oas.annotations.Operation; | |||
import io.swagger.v3.oas.annotations.Parameter; | |||
import io.swagger.v3.oas.annotations.media.Content; | |||
import io.swagger.v3.oas.annotations.media.ExampleObject; | |||
import io.swagger.v3.oas.annotations.media.Schema; | |||
import io.swagger.v3.oas.annotations.responses.ApiResponse; | |||
import io.swagger.v3.oas.annotations.security.SecurityRequirement; | |||
import lombok.Cleanup; | |||
@@ -147,7 +148,7 @@ public class AuthResource { | |||
description="Determine if the API is running and ready for login", | |||
responses={ | |||
@ApiResponse(responseCode=SC_OK, description="empty response with status 200 if API is ready"), | |||
@ApiResponse(responseCode=SC_PRECONDITION_FAILED, description="error with status 422 if API is NOT ready") | |||
@ApiResponse(responseCode=SC_INVALID, description="error with status 422 if API is NOT ready") | |||
} | |||
) | |||
public Response getNodeIsReady(@Context ContainerRequest ctx) { | |||
@@ -200,7 +201,7 @@ public class AuthResource { | |||
responses={ | |||
@ApiResponse(responseCode=SC_OK, description="the Account object for the initial admin account, with a new session token"), | |||
@ApiResponse(responseCode=SC_FORBIDDEN, description="forbidden if caller is not admin and activation has already been completed"), | |||
@ApiResponse(responseCode=SC_PRECONDITION_FAILED, description="validation errors occurred: activation has already been completed, or there were errors processing the ActivationRequest object") | |||
@ApiResponse(responseCode=SC_INVALID, description="validation errors occurred: activation has already been completed, or there were errors processing the ActivationRequest object") | |||
} | |||
) | |||
public Response activate(@Context Request req, | |||
@@ -266,7 +267,7 @@ public class AuthResource { | |||
parameters={@Parameter(name="restoreKey", description="the restore key")}, | |||
responses={ | |||
@ApiResponse(responseCode=SC_OK, description="the NotificationReceipt from a successful request to retrieve the backup"), | |||
@ApiResponse(responseCode=SC_PRECONDITION_FAILED, description="validation errors occurred") | |||
@ApiResponse(responseCode=SC_INVALID, description="validation errors occurred") | |||
} | |||
) | |||
public Response restore(@NonNull @Context final Request req, | |||
@@ -299,7 +300,7 @@ public class AuthResource { | |||
parameters={@Parameter(name="restoreKey", description="the restore key")}, | |||
responses={ | |||
@ApiResponse(responseCode=SC_OK, description="upon success a 200 HTTP status with an empty response is returned"), | |||
@ApiResponse(responseCode=SC_PRECONDITION_FAILED, description="validation errors occurred") | |||
@ApiResponse(responseCode=SC_INVALID, description="validation errors occurred") | |||
} | |||
) | |||
@NonNull public Response restoreFromPackage(@NonNull @Context final Request req, | |||
@@ -326,8 +327,8 @@ public class AuthResource { | |||
summary="Register a new Account, starts a new API session.", | |||
description="Register a new Account, starts a new API session.", | |||
responses={ | |||
@ApiResponse(responseCode=SC_OK, description="the Account object that was registered, `token` property holds session token"), | |||
@ApiResponse(responseCode=SC_PRECONDITION_FAILED, description="validation errors occurred") | |||
@ApiResponse(responseCode=SC_OK, description="the Account object that was registered, `token` property holds session token", content=@Content(mediaType=APPLICATION_JSON, schema=@Schema(ref="#/components/schema/Account"))), | |||
@ApiResponse(responseCode=SC_INVALID, description="validation errors occurred") | |||
} | |||
) | |||
public Response register(@Context Request req, | |||
@@ -444,7 +445,7 @@ public class AuthResource { | |||
parameters={@Parameter(name="k", description="for a new Bubble that was launched with the lock enabled, the unlock key is required for the first login")}, | |||
responses={ | |||
@ApiResponse(responseCode=SC_OK, description="the Account object that was logged in"), | |||
@ApiResponse(responseCode=SC_PRECONDITION_FAILED, description="validation errors occurred") | |||
@ApiResponse(responseCode=SC_INVALID, description="validation errors occurred") | |||
} | |||
) | |||
public Response login(@Context Request req, | |||
@@ -525,7 +526,7 @@ public class AuthResource { | |||
parameters={@Parameter(name="session", description="the session token to use for logging in")}, | |||
responses={ | |||
@ApiResponse(responseCode=SC_OK, description="the Account object that was logged in"), | |||
@ApiResponse(responseCode=SC_PRECONDITION_FAILED, description="validation errors occurred") | |||
@ApiResponse(responseCode=SC_INVALID, description="validation errors occurred") | |||
} | |||
) | |||
public Response appLogin(@Context Request req, | |||
@@ -656,7 +657,7 @@ public class AuthResource { | |||
responses={ | |||
@ApiResponse(responseCode=SC_OK, description="the NodeKey that was created"), | |||
@ApiResponse(responseCode=SC_FORBIDDEN, description="forbidden if caller is not admin and is accessing any account Account other than themselves"), | |||
@ApiResponse(responseCode=SC_PRECONDITION_FAILED, description="validation errors occurred") | |||
@ApiResponse(responseCode=SC_INVALID, description="validation errors occurred") | |||
} | |||
) | |||
public Response rekeyNode(@Context Request req, | |||
@@ -701,7 +702,7 @@ public class AuthResource { | |||
description="Send a reset password message", | |||
responses={ | |||
@ApiResponse(responseCode=SC_OK, description="an empty response with HTTP status 200 indicates success"), | |||
@ApiResponse(responseCode=SC_PRECONDITION_FAILED, description="if no email address was supplied in the request body") | |||
@ApiResponse(responseCode=SC_INVALID, description="if no email address was supplied in the request body") | |||
} | |||
) | |||
public Response forgotPassword(@Context Request req, | |||
@@ -737,7 +738,7 @@ public class AuthResource { | |||
@ExampleObject(name="if no login requested, returns an empty response", value=""), | |||
@ExampleObject(name="if login requested, returns an Account object with either a valid session token ('token' property) or additional auth factors required (check 'multifactorAuth' property)") | |||
})}), | |||
@ApiResponse(responseCode=SC_PRECONDITION_FAILED, description="a validation error occurred, for example the token might be invalid") | |||
@ApiResponse(responseCode=SC_INVALID, description="a validation error occurred, for example the token might be invalid") | |||
} | |||
) | |||
public Response approve(@Context Request req, | |||
@@ -786,7 +787,7 @@ public class AuthResource { | |||
@ExampleObject(name="if no login requested, returns an empty response", value=""), | |||
@ExampleObject(name="if login requested, returns an Account object with either a valid session token ('token' property) or additional auth factors required (check 'multifactorAuth' property)") | |||
})}), | |||
@ApiResponse(responseCode=SC_PRECONDITION_FAILED, description="a validation error occurred, for example the token might be invalid") | |||
@ApiResponse(responseCode=SC_INVALID, description="a validation error occurred, for example the token might be invalid") | |||
} | |||
) | |||
public Response authenticator(@Context Request req, | |||
@@ -850,7 +851,7 @@ public class AuthResource { | |||
content={@Content(mediaType=APPLICATION_JSON, examples={ | |||
@ExampleObject(name="returns an empty JSON object", value="{}") | |||
})}), | |||
@ApiResponse(responseCode=SC_PRECONDITION_FAILED, description="a validation error occurred, for example the token might be invalid") | |||
@ApiResponse(responseCode=SC_INVALID, description="a validation error occurred, for example the token might be invalid") | |||
} | |||
) | |||
public Response flushAuthenticatorTokens(@Context Request req, | |||
@@ -870,7 +871,7 @@ public class AuthResource { | |||
content={@Content(mediaType=APPLICATION_JSON, examples={ | |||
@ExampleObject(name="returns the denial AccountMessage") | |||
})}), | |||
@ApiResponse(responseCode=SC_PRECONDITION_FAILED, description="a validation error occurred, for example the token might be invalid") | |||
@ApiResponse(responseCode=SC_INVALID, description="a validation error occurred, for example the token might be invalid") | |||
} | |||
) | |||
public Response deny(@Context Request req, | |||
@@ -957,7 +958,7 @@ public class AuthResource { | |||
parameters={@Parameter(name="all", description="logout of all sessions everywhere")}, | |||
responses={ | |||
@ApiResponse(responseCode=SC_OK, description="HTTP status 200 indicates success"), | |||
@ApiResponse(responseCode=SC_PRECONDITION_FAILED, description="If there is no current session to log out of") | |||
@ApiResponse(responseCode=SC_INVALID, description="If there is no current session to log out of") | |||
} | |||
) | |||
public Response logout(@Context ContainerRequest ctx, | |||
@@ -980,7 +981,7 @@ public class AuthResource { | |||
parameters={@Parameter(name="id", description="UUID or email of user to logout")}, | |||
responses={ | |||
@ApiResponse(responseCode=SC_OK, description="HTTP status 200 indicates success"), | |||
@ApiResponse(responseCode=SC_PRECONDITION_FAILED, description="If there is no current session to log out of") | |||
@ApiResponse(responseCode=SC_INVALID, description="If there is no current session to log out of") | |||
} | |||
) | |||
public Response logoutUserEverywhere(@Context ContainerRequest ctx, | |||
@@ -35,6 +35,9 @@ import bubble.service.cloud.NodeLaunchMonitor; | |||
import bubble.service.upgrade.BubbleJarUpgradeService; | |||
import com.fasterxml.jackson.databind.JsonNode; | |||
import io.swagger.v3.oas.annotations.Operation; | |||
import io.swagger.v3.oas.annotations.media.Content; | |||
import io.swagger.v3.oas.annotations.media.ExampleObject; | |||
import io.swagger.v3.oas.annotations.responses.ApiResponse; | |||
import io.swagger.v3.oas.annotations.security.SecurityRequirement; | |||
import lombok.Cleanup; | |||
import lombok.Getter; | |||
@@ -75,9 +78,12 @@ import static bubble.resources.account.AuthResource.forgotPasswordMessage; | |||
import static java.util.concurrent.TimeUnit.MINUTES; | |||
import static org.cobbzilla.util.daemon.ZillaRuntime.*; | |||
import static org.cobbzilla.util.http.HttpContentTypes.*; | |||
import static org.cobbzilla.util.http.HttpStatusCodes.SC_OK; | |||
import static org.cobbzilla.util.http.HttpStatusCodes.SC_INVALID; | |||
import static org.cobbzilla.util.json.JsonUtil.json; | |||
import static org.cobbzilla.wizard.resources.ResourceUtil.*; | |||
import static org.cobbzilla.wizard.server.RestServerBase.reportError; | |||
import static org.cobbzilla.wizard.server.config.OpenApiConfiguration.API_TAG_UTILITY; | |||
import static org.cobbzilla.wizard.server.config.OpenApiConfiguration.SEC_API_KEY; | |||
@Consumes(APPLICATION_JSON) | |||
@@ -95,7 +101,14 @@ public class MeResource { | |||
@Autowired private AccountMessageDAO messageDAO; | |||
@GET | |||
@Operation(security=@SecurityRequirement(name=SEC_API_KEY)) | |||
@Operation(security=@SecurityRequirement(name=SEC_API_KEY), | |||
tags={API_TAG_ACCOUNT}, | |||
summary="Get account record for current session", | |||
description="Get account record for current session", | |||
responses={ | |||
@ApiResponse(responseCode=SC_OK, description="Account object") | |||
} | |||
) | |||
public Response me(@Context ContainerRequest ctx) { | |||
try { | |||
final Account account = userPrincipal(ctx); | |||
@@ -113,14 +126,28 @@ public class MeResource { | |||
} | |||
@GET @Path(EP_LOCALE) | |||
@Operation(security=@SecurityRequirement(name=SEC_API_KEY)) | |||
@Operation(security=@SecurityRequirement(name=SEC_API_KEY), | |||
tags={API_TAG_ACCOUNT}, | |||
summary="Get the account locale", | |||
description="Get the account locale", | |||
responses={ | |||
@ApiResponse(responseCode=SC_OK, description="Locale string", content=@Content(mediaType=APPLICATION_JSON, examples={@ExampleObject(name="default locale", value="en_US")})) | |||
} | |||
) | |||
public Response getLocale(@Context ContainerRequest ctx) { | |||
final Account account = userPrincipal(ctx); | |||
return ok(account.getLocale()); | |||
} | |||
@POST @Path(EP_LOCALE+"/{locale}") | |||
@Operation(security=@SecurityRequirement(name=SEC_API_KEY)) | |||
@Operation(security=@SecurityRequirement(name=SEC_API_KEY), | |||
tags={API_TAG_ACCOUNT}, | |||
summary="Set the account locale", | |||
description="Set the account locale", | |||
responses={ | |||
@ApiResponse(responseCode=SC_OK, description="updated Account object") | |||
} | |||
) | |||
public Response setLocale(@Context ContainerRequest ctx, | |||
@PathParam("locale") String locale) { | |||
final Account account = userPrincipal(ctx); | |||
@@ -150,10 +177,25 @@ public class MeResource { | |||
} | |||
@GET @Path(EP_ERROR_API) | |||
@Operation(tags={API_TAG_UTILITY}, | |||
summary="Get error API information", | |||
description="Get error API information", | |||
responses={ | |||
@ApiResponse(responseCode=SC_OK, description="a Map of API information") | |||
} | |||
) | |||
public Response errorApi(@Context Request req) { return ok(getErrorApi()); } | |||
@POST @Path(EP_CHANGE_PASSWORD) | |||
@Operation(security=@SecurityRequirement(name=SEC_API_KEY)) | |||
@Operation(security=@SecurityRequirement(name=SEC_API_KEY), | |||
tags={API_TAG_ACCOUNT}, | |||
summary="Request account password change", | |||
description="Request account password change. A message will be sent to the user with a token to approve the change and set a new password. If the password can be changed directly, this returns the updated Account object. If approvals are required for a password change, an Account object will be returned and the `multifactorAuth` property will indicate what auth methods are required to approve the change.", | |||
responses={ | |||
@ApiResponse(responseCode=SC_OK, description="an Account object"), | |||
@ApiResponse(responseCode=SC_INVALID, description="current password was incorrect, or a TOTP token is required") | |||
} | |||
) | |||
public Response changePassword(@Context Request req, | |||
@Context ContainerRequest ctx, | |||
ChangePasswordRequest request) { | |||
@@ -1 +1 @@ | |||
Subproject commit 4c1d7e827aeff02a9dd3dbf76de6127ea9c09c60 | |||
Subproject commit 51119dc923d483f8b97fb0de3b36e3ff893e2ee9 |
@@ -1 +1 @@ | |||
Subproject commit d5c78b814875ca5298a664314591ecb644a23741 | |||
Subproject commit 126e4b4da345a14006998703147f4744c535a0df |