Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions examples/java/io/mailtrap/examples/general/ApiTokensExample.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
import io.mailtrap.model.ResourceType;
import io.mailtrap.model.request.apitokens.ApiTokenResource;
import io.mailtrap.model.request.apitokens.CreateApiTokenRequest;
import io.mailtrap.model.request.apitokens.ResetApiTokenRequest;
import io.mailtrap.model.request.apitokens.TokenExpiration;

import java.time.OffsetDateTime;
import java.util.List;

public class ApiTokensExample {
Expand All @@ -22,8 +25,13 @@ public static void main(String[] args) {
final var client = MailtrapClientFactory.createMailtrapClient(config);

// The full token value is returned only on creation — store it securely.
// Expiration is optional: omit it for the server default (a 1-year default is being
// rolled out), pass TokenExpiration.never() for a token that never expires, or pass
// TokenExpiration.at(...) for a concrete expiration (must be in the future and no
// more than 5 years ahead, otherwise the API responds with a 422 error).
final var createRequest = new CreateApiTokenRequest(
"My token",
TokenExpiration.at(OffsetDateTime.now().plusMonths(6)),
List.of(new ApiTokenResource(ResourceType.ACCOUNT, ACCOUNT_ID, AccessLevel.VIEWER)));

final var createdToken = client.generalApi().apiTokens()
Expand All @@ -39,8 +47,11 @@ public static void main(String[] args) {
System.out.println(token);

// Reset expires the existing token and returns a new one with the same permissions.
// The new token value is only returned here.
final var resetToken = client.generalApi().apiTokens().resetApiToken(ACCOUNT_ID, tokenId);
// The new token value is only returned here. Without a request body the new token
// gets the server default expiration; the overload with ResetApiTokenRequest sets it
// explicitly (here: a token that never expires).
final var resetToken = client.generalApi().apiTokens()
.resetApiToken(ACCOUNT_ID, tokenId, new ResetApiTokenRequest(TokenExpiration.never()));
System.out.println(resetToken);

client.generalApi().apiTokens().deleteApiToken(ACCOUNT_ID, resetToken.getId());
Expand Down
23 changes: 21 additions & 2 deletions src/main/java/io/mailtrap/api/apitokens/ApiTokens.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.mailtrap.api.apitokens;

import io.mailtrap.model.request.apitokens.CreateApiTokenRequest;
import io.mailtrap.model.request.apitokens.ResetApiTokenRequest;
import io.mailtrap.model.response.apitokens.ApiToken;
import io.mailtrap.model.response.apitokens.ApiTokenWithToken;

Expand All @@ -18,7 +19,10 @@ public interface ApiTokens {

/**
* Create a new API token for the account with the given name and resource permissions.
* The full token value is returned only on creation.
* The full token value is returned only on creation. Without an explicit expiration in the
* request the server assigns its default lifetime (currently 1 year); use
* {@link io.mailtrap.model.request.apitokens.TokenExpiration#never()} for a token that
* never expires.
*
* @param accountId unique account ID
* @param request token name and resource permissions
Expand All @@ -45,12 +49,27 @@ public interface ApiTokens {

/**
* Reset an API token. Expires the requested token and creates a new one with the same
* permissions; the new token value is returned only once.
* permissions; the new token value is returned only once. The new token gets the server
* default lifetime (currently 1 year); use
* {@link #resetApiToken(long, long, ResetApiTokenRequest)} to set the expiration
* explicitly, including a token that never expires.
*
* @param accountId unique account ID
* @param id API token ID
* @return new token, including the full token value
*/
ApiTokenWithToken resetApiToken(long accountId, long id);

/**
* Reset an API token. Expires the requested token and creates a new one with the same
* permissions; the new token value is returned only once. The request can set the new
* token expiration; omit it for the server default.
*
* @param accountId unique account ID
* @param id API token ID
* @param request optional new token expiration
* @return new token, including the full token value
*/
ApiTokenWithToken resetApiToken(long accountId, long id, ResetApiTokenRequest request);

}
11 changes: 11 additions & 0 deletions src/main/java/io/mailtrap/api/apitokens/ApiTokensImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import io.mailtrap.http.RequestData;
import io.mailtrap.model.AbstractModel;
import io.mailtrap.model.request.apitokens.CreateApiTokenRequest;
import io.mailtrap.model.request.apitokens.ResetApiTokenRequest;
import io.mailtrap.model.response.apitokens.ApiToken;
import io.mailtrap.model.response.apitokens.ApiTokenWithToken;

Expand Down Expand Up @@ -64,4 +65,14 @@ public ApiTokenWithToken resetApiToken(final long accountId, final long id) {
ApiTokenWithToken.class
);
}

@Override
public ApiTokenWithToken resetApiToken(final long accountId, final long id, final ResetApiTokenRequest request) {
return httpClient.post(
String.format(apiHost + "/api/accounts/%d/api_tokens/%d/reset", accountId, id),
request,
new RequestData(),
ApiTokenWithToken.class
);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.mailtrap.model.request.apitokens;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.mailtrap.model.AbstractModel;
import lombok.AllArgsConstructor;
import lombok.Getter;
Expand All @@ -16,6 +18,19 @@ public class CreateApiTokenRequest extends AbstractModel {

private String name;

/**
* Optional token expiration as an ISO 8601 date-time. Omit (or leave null) for the server
* default (a 1-year default is being rolled out). Use {@link TokenExpiration#never()} for
* a token that never expires. Past or more-than-5-years-ahead values are rejected with 422.
*/
@JsonProperty("expires_at")
@JsonInclude(JsonInclude.Include.NON_NULL)
private TokenExpiration expiresAt;

private List<ApiTokenResource> resources;

public CreateApiTokenRequest(final String name, final List<ApiTokenResource> resources) {
this(name, null, resources);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package io.mailtrap.model.request.apitokens;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.mailtrap.model.AbstractModel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class ResetApiTokenRequest extends AbstractModel {

/**
* Optional token expiration as an ISO 8601 date-time. Omit (or leave null) for the server
* default (a 1-year default is being rolled out). Use {@link TokenExpiration#never()} for
* a token that never expires. Past or more-than-5-years-ahead values are rejected with 422.
*/
@JsonProperty("expires_at")
@JsonInclude(JsonInclude.Include.NON_NULL)
private TokenExpiration expiresAt;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package io.mailtrap.model.request.apitokens;

import com.fasterxml.jackson.annotation.JsonValue;

import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;

/**
* API token expiration sent as the {@code expires_at} request field.
* Use {@link #at(OffsetDateTime)} for a concrete expiration or {@link #never()} for a token
* that never expires (serialized as JSON {@code null}).
*/
public final class TokenExpiration {

private final String value;

private TokenExpiration(final String value) {
this.value = value;
}

/**
* Token expires at the given moment. Past or more-than-5-years-ahead values are rejected
* by the API with a 422 error.
*
* @param value expiration date-time
* @return expiration serialized as an ISO 8601 date-time string
*/
public static TokenExpiration at(final OffsetDateTime value) {
return new TokenExpiration(DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(value));
}

/**
* Token never expires.
*
* @return expiration serialized as JSON {@code null}
*/
public static TokenExpiration never() {
return new TokenExpiration(null);
}

@JsonValue
public String getValue() {
return value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ public class ApiTokenSpecifier extends Specifier {

private String token;

@JsonProperty("masked_token")
private String maskedToken;

@JsonProperty("expires_at")
private OffsetDateTime expiresAt;

Expand Down
Loading
Loading