From 214c01208ac5c7c53c4da3b1829f3fa8745c1e6e Mon Sep 17 00:00:00 2001 From: Jannis Mattheis Date: Sun, 5 Jul 2026 20:16:02 +0200 Subject: [PATCH 1/2] fix: update client --- client/.openapi-generator/FILES | 4 + .../gotify/client/api/ApplicationApi.java | 17 ++ .../github/gotify/client/api/ClientApi.java | 5 +- .../github/gotify/client/api/MessageApi.java | 5 +- .../gotify/client/model/Application.java | 29 ++- .../github/gotify/client/model/Client.java | 78 ++++++- .../gotify/client/model/ClientParams.java | 32 ++- .../gotify/client/model/CreateMessage.java | 219 ++++++++++++++++++ .../gotify/client/model/CurrentUser.java | 23 +- .../gotify/client/model/ElevateRequest.java | 32 +-- .../gotify/client/model/PluginConf.java | 24 +- .../client/model/RegenerateTokenResponse.java | 98 ++++++++ .../client/model/SecurityUpdateAction.java | 97 ++++++++ .../model/SecurityUpdateActionResponse.java | 98 ++++++++ .../com/github/gotify/client/model/User.java | 24 +- 15 files changed, 738 insertions(+), 47 deletions(-) create mode 100644 client/src/main/java/com/github/gotify/client/model/CreateMessage.java create mode 100644 client/src/main/java/com/github/gotify/client/model/RegenerateTokenResponse.java create mode 100644 client/src/main/java/com/github/gotify/client/model/SecurityUpdateAction.java create mode 100644 client/src/main/java/com/github/gotify/client/model/SecurityUpdateActionResponse.java diff --git a/client/.openapi-generator/FILES b/client/.openapi-generator/FILES index 67595600..afa15ac5 100644 --- a/client/.openapi-generator/FILES +++ b/client/.openapi-generator/FILES @@ -25,6 +25,7 @@ src/main/java/com/github/gotify/client/model/Application.java src/main/java/com/github/gotify/client/model/ApplicationParams.java src/main/java/com/github/gotify/client/model/Client.java src/main/java/com/github/gotify/client/model/ClientParams.java +src/main/java/com/github/gotify/client/model/CreateMessage.java src/main/java/com/github/gotify/client/model/CreateUserExternal.java src/main/java/com/github/gotify/client/model/CurrentUser.java src/main/java/com/github/gotify/client/model/ElevateRequest.java @@ -39,6 +40,9 @@ src/main/java/com/github/gotify/client/model/OIDCExternalTokenResponse.java src/main/java/com/github/gotify/client/model/PagedMessages.java src/main/java/com/github/gotify/client/model/Paging.java src/main/java/com/github/gotify/client/model/PluginConf.java +src/main/java/com/github/gotify/client/model/RegenerateTokenResponse.java +src/main/java/com/github/gotify/client/model/SecurityUpdateAction.java +src/main/java/com/github/gotify/client/model/SecurityUpdateActionResponse.java src/main/java/com/github/gotify/client/model/UpdateUserExternal.java src/main/java/com/github/gotify/client/model/User.java src/main/java/com/github/gotify/client/model/UserPass.java diff --git a/client/src/main/java/com/github/gotify/client/api/ApplicationApi.java b/client/src/main/java/com/github/gotify/client/api/ApplicationApi.java index c93666bd..95597e95 100644 --- a/client/src/main/java/com/github/gotify/client/api/ApplicationApi.java +++ b/client/src/main/java/com/github/gotify/client/api/ApplicationApi.java @@ -13,6 +13,8 @@ import com.github.gotify.client.model.ApplicationParams; import com.github.gotify.client.model.Error; import java.io.File; +import com.github.gotify.client.model.SecurityUpdateAction; +import com.github.gotify.client.model.SecurityUpdateActionResponse; import java.util.ArrayList; import java.util.HashMap; @@ -66,6 +68,21 @@ Call removeAppImage( @retrofit2.http.Path("id") Long id ); + /** + * Perform security updates on an application. + * Requires elevated authentication. + * @param id the application id (required) + * @param body security update action descriptor (required) + * @return Call<SecurityUpdateActionResponse> + */ + @Headers({ + "Content-Type:application/json" + }) + @PUT("application/{id}/security") + Call updateAppSecurity( + @retrofit2.http.Path("id") Long id, @retrofit2.http.Body SecurityUpdateAction body + ); + /** * Update an application. * diff --git a/client/src/main/java/com/github/gotify/client/api/ClientApi.java b/client/src/main/java/com/github/gotify/client/api/ClientApi.java index 658c6893..f5d463f7 100644 --- a/client/src/main/java/com/github/gotify/client/api/ClientApi.java +++ b/client/src/main/java/com/github/gotify/client/api/ClientApi.java @@ -49,15 +49,16 @@ Call deleteClient( /** * Elevate a client session. * Requires elevated authentication. + * @param id the client id (required) * @param body the elevation request (required) * @return Call<Void> */ @Headers({ "Content-Type:application/json" }) - @POST("client:elevate") + @POST("client/{id}/elevate") Call elevateClient( - @retrofit2.http.Body ElevateRequest body + @retrofit2.http.Path("id") Long id, @retrofit2.http.Body ElevateRequest body ); /** diff --git a/client/src/main/java/com/github/gotify/client/api/MessageApi.java b/client/src/main/java/com/github/gotify/client/api/MessageApi.java index 1c2bd33c..51683c13 100644 --- a/client/src/main/java/com/github/gotify/client/api/MessageApi.java +++ b/client/src/main/java/com/github/gotify/client/api/MessageApi.java @@ -9,6 +9,7 @@ import okhttp3.ResponseBody; import okhttp3.MultipartBody; +import com.github.gotify.client.model.CreateMessage; import com.github.gotify.client.model.Error; import com.github.gotify.client.model.Message; import com.github.gotify.client.model.PagedMessages; @@ -22,7 +23,7 @@ public interface MessageApi { /** * Create a message. - * __NOTE__: This API ONLY accepts an application token as authentication. + * __NOTE__: When authenticating with a client token or basic auth, the request body must include \"appid\" referencing an application owned by the authenticated user. When authenticating with an application token, the application is derived from the token and any \"appid\" in the body is ignored. * @param body the message to add (required) * @return Call<Message> */ @@ -31,7 +32,7 @@ public interface MessageApi { }) @POST("message") Call createMessage( - @retrofit2.http.Body Message body + @retrofit2.http.Body CreateMessage body ); /** diff --git a/client/src/main/java/com/github/gotify/client/model/Application.java b/client/src/main/java/com/github/gotify/client/model/Application.java index 8691c167..8c4eb493 100644 --- a/client/src/main/java/com/github/gotify/client/model/Application.java +++ b/client/src/main/java/com/github/gotify/client/model/Application.java @@ -28,6 +28,11 @@ */ @javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", comments = "Generator version: 7.19.0") public class Application { + public static final String SERIALIZED_NAME_CREATED_AT = "createdAt"; + @SerializedName(SERIALIZED_NAME_CREATED_AT) + @javax.annotation.Nonnull + private OffsetDateTime createdAt; + public static final String SERIALIZED_NAME_DEFAULT_PRIORITY = "defaultPriority"; @SerializedName(SERIALIZED_NAME_DEFAULT_PRIORITY) @javax.annotation.Nullable @@ -70,7 +75,7 @@ public class Application { public static final String SERIALIZED_NAME_TOKEN = "token"; @SerializedName(SERIALIZED_NAME_TOKEN) - @javax.annotation.Nonnull + @javax.annotation.Nullable private String token; public Application() { @@ -80,6 +85,7 @@ public Application() { */ public Application( + OffsetDateTime createdAt, Long id, String image, Boolean internal, @@ -87,6 +93,7 @@ public Application( String token ) { this(); + this.createdAt = createdAt; this.id = id; this.image = image; this.internal = internal; @@ -94,6 +101,18 @@ public Application( this.token = token; } + /** + * The date the application was created. + * @return createdAt + */ + @javax.annotation.Nonnull + + public OffsetDateTime getCreatedAt() { + return createdAt; + } + + + public Application defaultPriority(@javax.annotation.Nullable Long defaultPriority) { this.defaultPriority = defaultPriority; @@ -230,7 +249,7 @@ public void setSortKey(@javax.annotation.Nonnull String sortKey) { * The application token. Can be used as `appToken`. See Authentication. * @return token */ - @javax.annotation.Nonnull + @javax.annotation.Nullable public String getToken() { return token; @@ -247,7 +266,8 @@ public boolean equals(Object o) { return false; } Application application = (Application) o; - return Objects.equals(this.defaultPriority, application.defaultPriority) && + return Objects.equals(this.createdAt, application.createdAt) && + Objects.equals(this.defaultPriority, application.defaultPriority) && Objects.equals(this.description, application.description) && Objects.equals(this.id, application.id) && Objects.equals(this.image, application.image) && @@ -260,13 +280,14 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(defaultPriority, description, id, image, internal, lastUsed, name, sortKey, token); + return Objects.hash(createdAt, defaultPriority, description, id, image, internal, lastUsed, name, sortKey, token); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class Application {\n"); + sb.append(" createdAt: ").append(toIndentedString(createdAt)).append("\n"); sb.append(" defaultPriority: ").append(toIndentedString(defaultPriority)).append("\n"); sb.append(" description: ").append(toIndentedString(description)).append("\n"); sb.append(" id: ").append(toIndentedString(id)).append("\n"); diff --git a/client/src/main/java/com/github/gotify/client/model/Client.java b/client/src/main/java/com/github/gotify/client/model/Client.java index b9d7a2fd..4f66397f 100644 --- a/client/src/main/java/com/github/gotify/client/model/Client.java +++ b/client/src/main/java/com/github/gotify/client/model/Client.java @@ -28,11 +28,26 @@ */ @javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", comments = "Generator version: 7.19.0") public class Client { + public static final String SERIALIZED_NAME_CREATED_AT = "createdAt"; + @SerializedName(SERIALIZED_NAME_CREATED_AT) + @javax.annotation.Nonnull + private OffsetDateTime createdAt; + public static final String SERIALIZED_NAME_ELEVATED_UNTIL = "elevatedUntil"; @SerializedName(SERIALIZED_NAME_ELEVATED_UNTIL) @javax.annotation.Nullable private OffsetDateTime elevatedUntil; + public static final String SERIALIZED_NAME_EXPIRES_AFTER_INACTIVITY_SECONDS = "expiresAfterInactivitySeconds"; + @SerializedName(SERIALIZED_NAME_EXPIRES_AFTER_INACTIVITY_SECONDS) + @javax.annotation.Nullable + private Long expiresAfterInactivitySeconds; + + public static final String SERIALIZED_NAME_EXPIRES_AT = "expiresAt"; + @SerializedName(SERIALIZED_NAME_EXPIRES_AT) + @javax.annotation.Nullable + private OffsetDateTime expiresAt; + public static final String SERIALIZED_NAME_ID = "id"; @SerializedName(SERIALIZED_NAME_ID) @javax.annotation.Nonnull @@ -50,7 +65,7 @@ public class Client { public static final String SERIALIZED_NAME_TOKEN = "token"; @SerializedName(SERIALIZED_NAME_TOKEN) - @javax.annotation.Nonnull + @javax.annotation.Nullable private String token; public Client() { @@ -60,18 +75,34 @@ public Client() { */ public Client( + OffsetDateTime createdAt, OffsetDateTime elevatedUntil, + OffsetDateTime expiresAt, Long id, OffsetDateTime lastUsed, String token ) { this(); + this.createdAt = createdAt; this.elevatedUntil = elevatedUntil; + this.expiresAt = expiresAt; this.id = id; this.lastUsed = lastUsed; this.token = token; } + /** + * The date the client was created. + * @return createdAt + */ + @javax.annotation.Nonnull + + public OffsetDateTime getCreatedAt() { + return createdAt; + } + + + /** * The time until which this client's session is elevated. * @return elevatedUntil @@ -84,6 +115,39 @@ public OffsetDateTime getElevatedUntil() { + public Client expiresAfterInactivitySeconds(@javax.annotation.Nullable Long expiresAfterInactivitySeconds) { + + this.expiresAfterInactivitySeconds = expiresAfterInactivitySeconds; + return this; + } + + /** + * The number of seconds of inactivity after which the client is removed. 0 means the client never expires. + * @return expiresAfterInactivitySeconds + */ + @javax.annotation.Nullable + + public Long getExpiresAfterInactivitySeconds() { + return expiresAfterInactivitySeconds; + } + + + public void setExpiresAfterInactivitySeconds(@javax.annotation.Nullable Long expiresAfterInactivitySeconds) { + this.expiresAfterInactivitySeconds = expiresAfterInactivitySeconds; + } + + /** + * The time at which this client will expire due to inactivity, or null if it never expires. + * @return expiresAt + */ + @javax.annotation.Nullable + + public OffsetDateTime getExpiresAt() { + return expiresAt; + } + + + /** * The client id. * @return id @@ -133,7 +197,7 @@ public void setName(@javax.annotation.Nonnull String name) { * The client token. Can be used as `clientToken`. See Authentication. * @return token */ - @javax.annotation.Nonnull + @javax.annotation.Nullable public String getToken() { return token; @@ -150,7 +214,10 @@ public boolean equals(Object o) { return false; } Client client = (Client) o; - return Objects.equals(this.elevatedUntil, client.elevatedUntil) && + return Objects.equals(this.createdAt, client.createdAt) && + Objects.equals(this.elevatedUntil, client.elevatedUntil) && + Objects.equals(this.expiresAfterInactivitySeconds, client.expiresAfterInactivitySeconds) && + Objects.equals(this.expiresAt, client.expiresAt) && Objects.equals(this.id, client.id) && Objects.equals(this.lastUsed, client.lastUsed) && Objects.equals(this.name, client.name) && @@ -159,14 +226,17 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(elevatedUntil, id, lastUsed, name, token); + return Objects.hash(createdAt, elevatedUntil, expiresAfterInactivitySeconds, expiresAt, id, lastUsed, name, token); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class Client {\n"); + sb.append(" createdAt: ").append(toIndentedString(createdAt)).append("\n"); sb.append(" elevatedUntil: ").append(toIndentedString(elevatedUntil)).append("\n"); + sb.append(" expiresAfterInactivitySeconds: ").append(toIndentedString(expiresAfterInactivitySeconds)).append("\n"); + sb.append(" expiresAt: ").append(toIndentedString(expiresAt)).append("\n"); sb.append(" id: ").append(toIndentedString(id)).append("\n"); sb.append(" lastUsed: ").append(toIndentedString(lastUsed)).append("\n"); sb.append(" name: ").append(toIndentedString(name)).append("\n"); diff --git a/client/src/main/java/com/github/gotify/client/model/ClientParams.java b/client/src/main/java/com/github/gotify/client/model/ClientParams.java index b7669da7..a3ef6b7a 100644 --- a/client/src/main/java/com/github/gotify/client/model/ClientParams.java +++ b/client/src/main/java/com/github/gotify/client/model/ClientParams.java @@ -27,6 +27,11 @@ */ @javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", comments = "Generator version: 7.19.0") public class ClientParams { + public static final String SERIALIZED_NAME_EXPIRES_AFTER_INACTIVITY_SECONDS = "expiresAfterInactivitySeconds"; + @SerializedName(SERIALIZED_NAME_EXPIRES_AFTER_INACTIVITY_SECONDS) + @javax.annotation.Nullable + private Long expiresAfterInactivitySeconds; + public static final String SERIALIZED_NAME_NAME = "name"; @SerializedName(SERIALIZED_NAME_NAME) @javax.annotation.Nonnull @@ -35,6 +40,27 @@ public class ClientParams { public ClientParams() { } + public ClientParams expiresAfterInactivitySeconds(@javax.annotation.Nullable Long expiresAfterInactivitySeconds) { + + this.expiresAfterInactivitySeconds = expiresAfterInactivitySeconds; + return this; + } + + /** + * The number of seconds of inactivity after which the client is removed. 0 (or omitted) means the client never expires. + * @return expiresAfterInactivitySeconds + */ + @javax.annotation.Nullable + + public Long getExpiresAfterInactivitySeconds() { + return expiresAfterInactivitySeconds; + } + + + public void setExpiresAfterInactivitySeconds(@javax.annotation.Nullable Long expiresAfterInactivitySeconds) { + this.expiresAfterInactivitySeconds = expiresAfterInactivitySeconds; + } + public ClientParams name(@javax.annotation.Nonnull String name) { this.name = name; @@ -65,18 +91,20 @@ public boolean equals(Object o) { return false; } ClientParams clientParams = (ClientParams) o; - return Objects.equals(this.name, clientParams.name); + return Objects.equals(this.expiresAfterInactivitySeconds, clientParams.expiresAfterInactivitySeconds) && + Objects.equals(this.name, clientParams.name); } @Override public int hashCode() { - return Objects.hash(name); + return Objects.hash(expiresAfterInactivitySeconds, name); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class ClientParams {\n"); + sb.append(" expiresAfterInactivitySeconds: ").append(toIndentedString(expiresAfterInactivitySeconds)).append("\n"); sb.append(" name: ").append(toIndentedString(name)).append("\n"); sb.append("}"); return sb.toString(); diff --git a/client/src/main/java/com/github/gotify/client/model/CreateMessage.java b/client/src/main/java/com/github/gotify/client/model/CreateMessage.java new file mode 100644 index 00000000..e57dfff6 --- /dev/null +++ b/client/src/main/java/com/github/gotify/client/model/CreateMessage.java @@ -0,0 +1,219 @@ +/* + * Gotify REST-API. + * This is the documentation of the Gotify REST-API. # Authentication In Gotify there are two token types: __clientToken__: a client is something that receives message and manages stuff like creating new tokens or delete messages. (f.ex this token should be used for an android app) __appToken__: an application is something that sends messages (f.ex. this token should be used for a shell script) The token can be transmitted in a header named `X-Gotify-Key`, in a query parameter named `token` or through a header named `Authorization` with the value prefixed with `Bearer` (Ex. `Bearer randomtoken`). There is also the possibility to authenticate through basic auth, this should only be used for creating a clientToken. \\--- Found a bug or have some questions? [Create an issue on GitHub](https://github.com/gotify/server/issues) + * + * The version of the OpenAPI document: 2.1.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package com.github.gotify.client.model; + +import java.util.Objects; +import java.util.Arrays; +import com.google.gson.TypeAdapter; +import com.google.gson.annotations.JsonAdapter; +import com.google.gson.annotations.SerializedName; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +/** + * The CreateMessage holds information about a message that will be sent. + */ +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", comments = "Generator version: 7.19.0") +public class CreateMessage { + public static final String SERIALIZED_NAME_APPID = "appid"; + @SerializedName(SERIALIZED_NAME_APPID) + @javax.annotation.Nullable + private Long appid; + + public static final String SERIALIZED_NAME_EXTRAS = "extras"; + @SerializedName(SERIALIZED_NAME_EXTRAS) + @javax.annotation.Nullable + private Map extras = new HashMap<>(); + + public static final String SERIALIZED_NAME_MESSAGE = "message"; + @SerializedName(SERIALIZED_NAME_MESSAGE) + @javax.annotation.Nonnull + private String message; + + public static final String SERIALIZED_NAME_PRIORITY = "priority"; + @SerializedName(SERIALIZED_NAME_PRIORITY) + @javax.annotation.Nullable + private Long priority; + + public static final String SERIALIZED_NAME_TITLE = "title"; + @SerializedName(SERIALIZED_NAME_TITLE) + @javax.annotation.Nullable + private String title; + + public CreateMessage() { + } + + public CreateMessage appid(@javax.annotation.Nullable Long appid) { + + this.appid = appid; + return this; + } + + /** + * The application id that send this message. Always set when returned via the API. + * @return appid + */ + @javax.annotation.Nullable + + public Long getAppid() { + return appid; + } + + + public void setAppid(@javax.annotation.Nullable Long appid) { + this.appid = appid; + } + + public CreateMessage extras(@javax.annotation.Nullable Map extras) { + + this.extras = extras; + return this; + } + + public CreateMessage putExtrasItem(String key, Object extrasItem) { + if (this.extras == null) { + this.extras = new HashMap<>(); + } + this.extras.put(key, extrasItem); + return this; + } + + /** + * The extra data sent along the message. The extra fields are stored in a key-value scheme. Only accepted in CreateMessage requests with application/json content-type. The keys should be in the following format: &lt;top-namespace&gt;::[&lt;sub-namespace&gt;::]&lt;action&gt; These namespaces are reserved and might be used in the official clients: gotify android ios web server client. Do not use them for other purposes. + * @return extras + */ + @javax.annotation.Nullable + + public Map getExtras() { + return extras; + } + + + public void setExtras(@javax.annotation.Nullable Map extras) { + this.extras = extras; + } + + public CreateMessage message(@javax.annotation.Nonnull String message) { + + this.message = message; + return this; + } + + /** + * The message. Markdown (excluding html) is allowed. + * @return message + */ + @javax.annotation.Nonnull + + public String getMessage() { + return message; + } + + + public void setMessage(@javax.annotation.Nonnull String message) { + this.message = message; + } + + public CreateMessage priority(@javax.annotation.Nullable Long priority) { + + this.priority = priority; + return this; + } + + /** + * The priority of the message. If unset, then the default priority of the application will be used. + * @return priority + */ + @javax.annotation.Nullable + + public Long getPriority() { + return priority; + } + + + public void setPriority(@javax.annotation.Nullable Long priority) { + this.priority = priority; + } + + public CreateMessage title(@javax.annotation.Nullable String title) { + + this.title = title; + return this; + } + + /** + * The title of the message. + * @return title + */ + @javax.annotation.Nullable + + public String getTitle() { + return title; + } + + + public void setTitle(@javax.annotation.Nullable String title) { + this.title = title; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + CreateMessage createMessage = (CreateMessage) o; + return Objects.equals(this.appid, createMessage.appid) && + Objects.equals(this.extras, createMessage.extras) && + Objects.equals(this.message, createMessage.message) && + Objects.equals(this.priority, createMessage.priority) && + Objects.equals(this.title, createMessage.title); + } + + @Override + public int hashCode() { + return Objects.hash(appid, extras, message, priority, title); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class CreateMessage {\n"); + sb.append(" appid: ").append(toIndentedString(appid)).append("\n"); + sb.append(" extras: ").append(toIndentedString(extras)).append("\n"); + sb.append(" message: ").append(toIndentedString(message)).append("\n"); + sb.append(" priority: ").append(toIndentedString(priority)).append("\n"); + sb.append(" title: ").append(toIndentedString(title)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + +} + diff --git a/client/src/main/java/com/github/gotify/client/model/CurrentUser.java b/client/src/main/java/com/github/gotify/client/model/CurrentUser.java index ebcb413d..805b5b0a 100644 --- a/client/src/main/java/com/github/gotify/client/model/CurrentUser.java +++ b/client/src/main/java/com/github/gotify/client/model/CurrentUser.java @@ -38,6 +38,11 @@ public class CurrentUser { @javax.annotation.Nullable private Long clientId; + public static final String SERIALIZED_NAME_CREATED_AT = "createdAt"; + @SerializedName(SERIALIZED_NAME_CREATED_AT) + @javax.annotation.Nonnull + private OffsetDateTime createdAt; + public static final String SERIALIZED_NAME_ELEVATED_UNTIL = "elevatedUntil"; @SerializedName(SERIALIZED_NAME_ELEVATED_UNTIL) @javax.annotation.Nullable @@ -61,11 +66,13 @@ public CurrentUser() { public CurrentUser( Long clientId, + OffsetDateTime createdAt, OffsetDateTime elevatedUntil, Long id ) { this(); this.clientId = clientId; + this.createdAt = createdAt; this.elevatedUntil = elevatedUntil; this.id = id; } @@ -103,6 +110,18 @@ public Long getClientId() { + /** + * The date the user was created. + * @return createdAt + */ + @javax.annotation.Nonnull + + public OffsetDateTime getCreatedAt() { + return createdAt; + } + + + /** * The time until which the session is elevated. * @return elevatedUntil @@ -159,6 +178,7 @@ public boolean equals(Object o) { CurrentUser currentUser = (CurrentUser) o; return Objects.equals(this.admin, currentUser.admin) && Objects.equals(this.clientId, currentUser.clientId) && + Objects.equals(this.createdAt, currentUser.createdAt) && Objects.equals(this.elevatedUntil, currentUser.elevatedUntil) && Objects.equals(this.id, currentUser.id) && Objects.equals(this.name, currentUser.name); @@ -166,7 +186,7 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(admin, clientId, elevatedUntil, id, name); + return Objects.hash(admin, clientId, createdAt, elevatedUntil, id, name); } @Override @@ -175,6 +195,7 @@ public String toString() { sb.append("class CurrentUser {\n"); sb.append(" admin: ").append(toIndentedString(admin)).append("\n"); sb.append(" clientId: ").append(toIndentedString(clientId)).append("\n"); + sb.append(" createdAt: ").append(toIndentedString(createdAt)).append("\n"); sb.append(" elevatedUntil: ").append(toIndentedString(elevatedUntil)).append("\n"); sb.append(" id: ").append(toIndentedString(id)).append("\n"); sb.append(" name: ").append(toIndentedString(name)).append("\n"); diff --git a/client/src/main/java/com/github/gotify/client/model/ElevateRequest.java b/client/src/main/java/com/github/gotify/client/model/ElevateRequest.java index f9fdfb51..166708d6 100644 --- a/client/src/main/java/com/github/gotify/client/model/ElevateRequest.java +++ b/client/src/main/java/com/github/gotify/client/model/ElevateRequest.java @@ -32,11 +32,6 @@ public class ElevateRequest { @javax.annotation.Nonnull private Long durationSeconds; - public static final String SERIALIZED_NAME_ID = "id"; - @SerializedName(SERIALIZED_NAME_ID) - @javax.annotation.Nonnull - private Long id; - public ElevateRequest() { } @@ -61,27 +56,6 @@ public void setDurationSeconds(@javax.annotation.Nonnull Long durationSeconds) { this.durationSeconds = durationSeconds; } - public ElevateRequest id(@javax.annotation.Nonnull Long id) { - - this.id = id; - return this; - } - - /** - * The client ID to elevate. - * @return id - */ - @javax.annotation.Nonnull - - public Long getId() { - return id; - } - - - public void setId(@javax.annotation.Nonnull Long id) { - this.id = id; - } - @Override public boolean equals(Object o) { if (this == o) { @@ -91,13 +65,12 @@ public boolean equals(Object o) { return false; } ElevateRequest elevateRequest = (ElevateRequest) o; - return Objects.equals(this.durationSeconds, elevateRequest.durationSeconds) && - Objects.equals(this.id, elevateRequest.id); + return Objects.equals(this.durationSeconds, elevateRequest.durationSeconds); } @Override public int hashCode() { - return Objects.hash(durationSeconds, id); + return Objects.hash(durationSeconds); } @Override @@ -105,7 +78,6 @@ public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class ElevateRequest {\n"); sb.append(" durationSeconds: ").append(toIndentedString(durationSeconds)).append("\n"); - sb.append(" id: ").append(toIndentedString(id)).append("\n"); sb.append("}"); return sb.toString(); } diff --git a/client/src/main/java/com/github/gotify/client/model/PluginConf.java b/client/src/main/java/com/github/gotify/client/model/PluginConf.java index d7424709..0e329192 100644 --- a/client/src/main/java/com/github/gotify/client/model/PluginConf.java +++ b/client/src/main/java/com/github/gotify/client/model/PluginConf.java @@ -21,6 +21,7 @@ import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; import java.io.IOException; +import java.time.OffsetDateTime; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -40,6 +41,11 @@ public class PluginConf { @javax.annotation.Nonnull private List capabilities = new ArrayList<>(); + public static final String SERIALIZED_NAME_CREATED_AT = "createdAt"; + @SerializedName(SERIALIZED_NAME_CREATED_AT) + @javax.annotation.Nonnull + private OffsetDateTime createdAt; + public static final String SERIALIZED_NAME_ENABLED = "enabled"; @SerializedName(SERIALIZED_NAME_ENABLED) @javax.annotation.Nonnull @@ -83,6 +89,7 @@ public PluginConf() { public PluginConf( String author, + OffsetDateTime createdAt, Long id, String license, String modulePath, @@ -91,6 +98,7 @@ public PluginConf( ) { this(); this.author = author; + this.createdAt = createdAt; this.id = id; this.license = license; this.modulePath = modulePath; @@ -139,6 +147,18 @@ public void setCapabilities(@javax.annotation.Nonnull List capabilities) this.capabilities = capabilities; } + /** + * The date the plugin was created. + * @return createdAt + */ + @javax.annotation.Nonnull + + public OffsetDateTime getCreatedAt() { + return createdAt; + } + + + public PluginConf enabled(@javax.annotation.Nonnull Boolean enabled) { this.enabled = enabled; @@ -252,6 +272,7 @@ public boolean equals(Object o) { PluginConf pluginConf = (PluginConf) o; return Objects.equals(this.author, pluginConf.author) && Objects.equals(this.capabilities, pluginConf.capabilities) && + Objects.equals(this.createdAt, pluginConf.createdAt) && Objects.equals(this.enabled, pluginConf.enabled) && Objects.equals(this.id, pluginConf.id) && Objects.equals(this.license, pluginConf.license) && @@ -263,7 +284,7 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(author, capabilities, enabled, id, license, modulePath, name, token, website); + return Objects.hash(author, capabilities, createdAt, enabled, id, license, modulePath, name, token, website); } @Override @@ -272,6 +293,7 @@ public String toString() { sb.append("class PluginConf {\n"); sb.append(" author: ").append(toIndentedString(author)).append("\n"); sb.append(" capabilities: ").append(toIndentedString(capabilities)).append("\n"); + sb.append(" createdAt: ").append(toIndentedString(createdAt)).append("\n"); sb.append(" enabled: ").append(toIndentedString(enabled)).append("\n"); sb.append(" id: ").append(toIndentedString(id)).append("\n"); sb.append(" license: ").append(toIndentedString(license)).append("\n"); diff --git a/client/src/main/java/com/github/gotify/client/model/RegenerateTokenResponse.java b/client/src/main/java/com/github/gotify/client/model/RegenerateTokenResponse.java new file mode 100644 index 00000000..b8d73aef --- /dev/null +++ b/client/src/main/java/com/github/gotify/client/model/RegenerateTokenResponse.java @@ -0,0 +1,98 @@ +/* + * Gotify REST-API. + * This is the documentation of the Gotify REST-API. # Authentication In Gotify there are two token types: __clientToken__: a client is something that receives message and manages stuff like creating new tokens or delete messages. (f.ex this token should be used for an android app) __appToken__: an application is something that sends messages (f.ex. this token should be used for a shell script) The token can be transmitted in a header named `X-Gotify-Key`, in a query parameter named `token` or through a header named `Authorization` with the value prefixed with `Bearer` (Ex. `Bearer randomtoken`). There is also the possibility to authenticate through basic auth, this should only be used for creating a clientToken. \\--- Found a bug or have some questions? [Create an issue on GitHub](https://github.com/gotify/server/issues) + * + * The version of the OpenAPI document: 2.1.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package com.github.gotify.client.model; + +import java.util.Objects; +import java.util.Arrays; +import com.google.gson.TypeAdapter; +import com.google.gson.annotations.JsonAdapter; +import com.google.gson.annotations.SerializedName; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; + +/** + * The RegenerateTokenResponse holds information about the response to the regenerate token action. + */ +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", comments = "Generator version: 7.19.0") +public class RegenerateTokenResponse { + public static final String SERIALIZED_NAME_TOKEN = "token"; + @SerializedName(SERIALIZED_NAME_TOKEN) + @javax.annotation.Nonnull + private String token; + + public RegenerateTokenResponse() { + } + /** + * Constructor with only readonly parameters + */ + + public RegenerateTokenResponse( + String token + ) { + this(); + this.token = token; + } + + /** + * The new token. + * @return token + */ + @javax.annotation.Nonnull + + public String getToken() { + return token; + } + + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + RegenerateTokenResponse regenerateTokenResponse = (RegenerateTokenResponse) o; + return Objects.equals(this.token, regenerateTokenResponse.token); + } + + @Override + public int hashCode() { + return Objects.hash(token); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class RegenerateTokenResponse {\n"); + sb.append(" token: ").append(toIndentedString(token)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + +} + diff --git a/client/src/main/java/com/github/gotify/client/model/SecurityUpdateAction.java b/client/src/main/java/com/github/gotify/client/model/SecurityUpdateAction.java new file mode 100644 index 00000000..9fe0de36 --- /dev/null +++ b/client/src/main/java/com/github/gotify/client/model/SecurityUpdateAction.java @@ -0,0 +1,97 @@ +/* + * Gotify REST-API. + * This is the documentation of the Gotify REST-API. # Authentication In Gotify there are two token types: __clientToken__: a client is something that receives message and manages stuff like creating new tokens or delete messages. (f.ex this token should be used for an android app) __appToken__: an application is something that sends messages (f.ex. this token should be used for a shell script) The token can be transmitted in a header named `X-Gotify-Key`, in a query parameter named `token` or through a header named `Authorization` with the value prefixed with `Bearer` (Ex. `Bearer randomtoken`). There is also the possibility to authenticate through basic auth, this should only be used for creating a clientToken. \\--- Found a bug or have some questions? [Create an issue on GitHub](https://github.com/gotify/server/issues) + * + * The version of the OpenAPI document: 2.1.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package com.github.gotify.client.model; + +import java.util.Objects; +import java.util.Arrays; +import com.google.gson.TypeAdapter; +import com.google.gson.annotations.JsonAdapter; +import com.google.gson.annotations.SerializedName; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; + +/** + * The SecurityUpdateAction describes the details of a requested security update. + */ +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", comments = "Generator version: 7.19.0") +public class SecurityUpdateAction { + public static final String SERIALIZED_NAME_REGENERATE_TOKEN = "regenerateToken"; + @SerializedName(SERIALIZED_NAME_REGENERATE_TOKEN) + @javax.annotation.Nullable + private Boolean regenerateToken; + + public SecurityUpdateAction() { + } + + public SecurityUpdateAction regenerateToken(@javax.annotation.Nullable Boolean regenerateToken) { + + this.regenerateToken = regenerateToken; + return this; + } + + /** + * Whether to regenerate the token. Your client token must be elevated to perform this action. + * @return regenerateToken + */ + @javax.annotation.Nullable + + public Boolean getRegenerateToken() { + return regenerateToken; + } + + + public void setRegenerateToken(@javax.annotation.Nullable Boolean regenerateToken) { + this.regenerateToken = regenerateToken; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + SecurityUpdateAction securityUpdateAction = (SecurityUpdateAction) o; + return Objects.equals(this.regenerateToken, securityUpdateAction.regenerateToken); + } + + @Override + public int hashCode() { + return Objects.hash(regenerateToken); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class SecurityUpdateAction {\n"); + sb.append(" regenerateToken: ").append(toIndentedString(regenerateToken)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + +} + diff --git a/client/src/main/java/com/github/gotify/client/model/SecurityUpdateActionResponse.java b/client/src/main/java/com/github/gotify/client/model/SecurityUpdateActionResponse.java new file mode 100644 index 00000000..b585c8d1 --- /dev/null +++ b/client/src/main/java/com/github/gotify/client/model/SecurityUpdateActionResponse.java @@ -0,0 +1,98 @@ +/* + * Gotify REST-API. + * This is the documentation of the Gotify REST-API. # Authentication In Gotify there are two token types: __clientToken__: a client is something that receives message and manages stuff like creating new tokens or delete messages. (f.ex this token should be used for an android app) __appToken__: an application is something that sends messages (f.ex. this token should be used for a shell script) The token can be transmitted in a header named `X-Gotify-Key`, in a query parameter named `token` or through a header named `Authorization` with the value prefixed with `Bearer` (Ex. `Bearer randomtoken`). There is also the possibility to authenticate through basic auth, this should only be used for creating a clientToken. \\--- Found a bug or have some questions? [Create an issue on GitHub](https://github.com/gotify/server/issues) + * + * The version of the OpenAPI document: 2.1.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package com.github.gotify.client.model; + +import java.util.Objects; +import java.util.Arrays; +import com.github.gotify.client.model.RegenerateTokenResponse; +import com.google.gson.TypeAdapter; +import com.google.gson.annotations.JsonAdapter; +import com.google.gson.annotations.SerializedName; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; + +/** + * The SecurityUpdateActionResponse holds information about the response to a security update request. + */ +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", comments = "Generator version: 7.19.0") +public class SecurityUpdateActionResponse { + public static final String SERIALIZED_NAME_REGENERATE_TOKEN = "regenerateToken"; + @SerializedName(SERIALIZED_NAME_REGENERATE_TOKEN) + @javax.annotation.Nullable + private RegenerateTokenResponse regenerateToken; + + public SecurityUpdateActionResponse() { + } + + public SecurityUpdateActionResponse regenerateToken(@javax.annotation.Nullable RegenerateTokenResponse regenerateToken) { + + this.regenerateToken = regenerateToken; + return this; + } + + /** + * Get regenerateToken + * @return regenerateToken + */ + @javax.annotation.Nullable + + public RegenerateTokenResponse getRegenerateToken() { + return regenerateToken; + } + + + public void setRegenerateToken(@javax.annotation.Nullable RegenerateTokenResponse regenerateToken) { + this.regenerateToken = regenerateToken; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + SecurityUpdateActionResponse securityUpdateActionResponse = (SecurityUpdateActionResponse) o; + return Objects.equals(this.regenerateToken, securityUpdateActionResponse.regenerateToken); + } + + @Override + public int hashCode() { + return Objects.hash(regenerateToken); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class SecurityUpdateActionResponse {\n"); + sb.append(" regenerateToken: ").append(toIndentedString(regenerateToken)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + +} + diff --git a/client/src/main/java/com/github/gotify/client/model/User.java b/client/src/main/java/com/github/gotify/client/model/User.java index b47e14dd..81cbb78c 100644 --- a/client/src/main/java/com/github/gotify/client/model/User.java +++ b/client/src/main/java/com/github/gotify/client/model/User.java @@ -21,6 +21,7 @@ import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; import java.io.IOException; +import java.time.OffsetDateTime; /** * The User holds information about permission and other stuff. @@ -32,6 +33,11 @@ public class User { @javax.annotation.Nonnull private Boolean admin; + public static final String SERIALIZED_NAME_CREATED_AT = "createdAt"; + @SerializedName(SERIALIZED_NAME_CREATED_AT) + @javax.annotation.Nonnull + private OffsetDateTime createdAt; + public static final String SERIALIZED_NAME_ID = "id"; @SerializedName(SERIALIZED_NAME_ID) @javax.annotation.Nonnull @@ -49,9 +55,11 @@ public User() { */ public User( + OffsetDateTime createdAt, Long id ) { this(); + this.createdAt = createdAt; this.id = id; } @@ -76,6 +84,18 @@ public void setAdmin(@javax.annotation.Nonnull Boolean admin) { this.admin = admin; } + /** + * The date the user was created. + * @return createdAt + */ + @javax.annotation.Nonnull + + public OffsetDateTime getCreatedAt() { + return createdAt; + } + + + /** * The user id. * @return id @@ -119,13 +139,14 @@ public boolean equals(Object o) { } User user = (User) o; return Objects.equals(this.admin, user.admin) && + Objects.equals(this.createdAt, user.createdAt) && Objects.equals(this.id, user.id) && Objects.equals(this.name, user.name); } @Override public int hashCode() { - return Objects.hash(admin, id, name); + return Objects.hash(admin, createdAt, id, name); } @Override @@ -133,6 +154,7 @@ public String toString() { StringBuilder sb = new StringBuilder(); sb.append("class User {\n"); sb.append(" admin: ").append(toIndentedString(admin)).append("\n"); + sb.append(" createdAt: ").append(toIndentedString(createdAt)).append("\n"); sb.append(" id: ").append(toIndentedString(id)).append("\n"); sb.append(" name: ").append(toIndentedString(name)).append("\n"); sb.append("}"); From 05c885ef06e5a930bb66c35a285f7e9cb51c31fb Mon Sep 17 00:00:00 2001 From: Jannis Mattheis Date: Sun, 5 Jul 2026 20:28:37 +0200 Subject: [PATCH 2/2] fix: allow pushing messages with client auth --- .../com/github/gotify/sharing/ShareActivity.kt | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/app/src/main/kotlin/com/github/gotify/sharing/ShareActivity.kt b/app/src/main/kotlin/com/github/gotify/sharing/ShareActivity.kt index e7e8c70d..26939c1e 100644 --- a/app/src/main/kotlin/com/github/gotify/sharing/ShareActivity.kt +++ b/app/src/main/kotlin/com/github/gotify/sharing/ShareActivity.kt @@ -16,7 +16,7 @@ import com.github.gotify.api.ApiException import com.github.gotify.api.ClientFactory import com.github.gotify.client.api.MessageApi import com.github.gotify.client.model.Application -import com.github.gotify.client.model.Message +import com.github.gotify.client.model.CreateMessage import com.github.gotify.databinding.ActivityShareBinding import com.github.gotify.messages.provider.ApplicationHolder import kotlinx.coroutines.Dispatchers @@ -107,7 +107,7 @@ internal class ShareActivity : AppCompatActivity() { return } - val message = Message() + val message = CreateMessage() if (titleText.isNotEmpty()) { message.title = titleText } @@ -115,7 +115,7 @@ internal class ShareActivity : AppCompatActivity() { message.priority = priority.toLong() launchCoroutine { - val response = executeMessageCall(appIndex, message) + val response = executeMessageCall(appsHolder.get()[appIndex], message) withContext(Dispatchers.Main) { if (response) { Toast.makeText(this@ShareActivity, "Pushed!", Toast.LENGTH_LONG).show() @@ -131,10 +131,16 @@ internal class ShareActivity : AppCompatActivity() { } } - private fun executeMessageCall(appIndex: Int, message: Message): Boolean { - val pushClient = ClientFactory.clientToken(settings, appsHolder.get()[appIndex].token) + private fun executeMessageCall(app: Application, message: CreateMessage): Boolean { + // In gotify 3.0, tokens aren't returned in the API anymore, but the push api allows setting the appid with client auth. + val client = if (app.token == null) { + message.appid = app.id + ClientFactory.clientToken(settings) + } else { + ClientFactory.clientToken(settings, app.token) + } return try { - val messageApi = pushClient.createService(MessageApi::class.java) + val messageApi = client.createService(MessageApi::class.java) Api.execute(messageApi.createMessage(message)) true } catch (apiException: ApiException) {