ApiToken.java

  1. /*
  2.  * Copyright 2023 Global Crop Diversity Trust
  3.  *
  4.  * Licensed under the Apache License, Version 2.0 (the "License");
  5.  * you may not use this file except in compliance with the License.
  6.  * You may obtain a copy of the License at
  7.  *
  8.  *   http://www.apache.org/licenses/LICENSE-2.0
  9.  *
  10.  * Unless required by applicable law or agreed to in writing, software
  11.  * distributed under the License is distributed on an "AS IS" BASIS,
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  * See the License for the specific language governing permissions and
  14.  * limitations under the License.
  15.  */
  16. package org.genesys.blocks.tokenauth.model;

  17. import java.time.Instant;

  18. import javax.persistence.Column;
  19. import javax.persistence.Entity;
  20. import javax.persistence.FetchType;
  21. import javax.persistence.Index;
  22. import javax.persistence.JoinColumn;
  23. import javax.persistence.ManyToOne;
  24. import javax.persistence.Table;

  25. import com.fasterxml.jackson.annotation.JsonView;
  26. import org.genesys.blocks.annotations.NotCopyable;
  27. import org.genesys.blocks.model.AuditedVersionedModel;
  28. import org.genesys.blocks.model.Copyable;
  29. import org.genesys.blocks.model.JsonViews;
  30. import org.genesys.blocks.security.model.AclSid;

  31. import lombok.Getter;
  32. import lombok.Setter;

  33. /**
  34.  * {@code ApiToken} supports token-based authentication. Each token is unique in the system and
  35.  * links to one and only one {@link AclSid}.
  36.  */
  37. @Entity
  38. @Table(name = "api_token", indexes = {
  39.     @Index(name = "apitoken_token", columnList = "token", unique = true), // Unique index on token
  40.     @Index(name = "apitoken_sid", columnList = "sid"), // Index on sid
  41.     @Index(name = "apitoken_expires", columnList = "expires DESC"), // Index on expires
  42.     @Index(name = "apitoken_sid_label", columnList = "sid, label", unique = true), // Index on sid and label
  43. })
  44. @Getter
  45. @Setter
  46. public class ApiToken extends AuditedVersionedModel implements Copyable<ApiToken> {

  47.     /** The token */
  48.     @Column(length = 128, unique = true, nullable = false, updatable = false)
  49.     @JsonView({ JsonViews.Internal.class })
  50.     @NotCopyable
  51.     private String token;

  52.     /** Token label helps users identify the purpose of the token */
  53.     @Column(length = 64)
  54.     private String label;

  55.     /** Token expiration date */
  56.     @Column(nullable = true, updatable = true)
  57.     private Instant expires;

  58.     /** Token owner */
  59.     @ManyToOne(fetch = FetchType.EAGER, cascade = {})
  60.     @JoinColumn(name = "sid", updatable = false, nullable = false)
  61.     @NotCopyable
  62.     private AclSid sid;

  63.     @Override
  64.     public boolean canEqual(Object other) {
  65.         return other instanceof ApiToken;
  66.     }

  67.     /**
  68.      * Check if token <b>is not</b> expired.
  69.      * API Token is non-expired when {@code expires} is null or is in the future.
  70.      * Token is expired if {@code expires} if non-null and it is in the past.
  71.      *
  72.      * @return {@code true} if expired.
  73.      */
  74.     public boolean isCredentialsNonExpired() {
  75.         return expires == null || Instant.now().isBefore(expires);
  76.     }
  77. }