This is an automated email from the ASF dual-hosted git repository.

lahirujayathilake pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airavata-custos.git

commit e9c4e6587157e230fb595d5ed463d0d100daa9ee
Author: lahiruj <[email protected]>
AuthorDate: Fri Oct 10 14:59:29 2025 -0400

    data models for ACCESS AMIE users and accounts
---
 .../custos/amie/model/ClusterAccountEntity.java    | 124 +++++++++++++
 .../apache/custos/amie/model/PersonDnsEntity.java  |  87 ++++++++++
 .../org/apache/custos/amie/model/PersonEntity.java | 192 +++++++++++++++++++++
 .../custos/amie/repo/ClusterAccountRepository.java |  32 ++++
 .../custos/amie/repo/PersonDnsRepository.java      |  27 +++
 .../apache/custos/amie/repo/PersonRepository.java  |  38 ++++
 .../db/migration/V1__initial_migration.sql         |  59 +++++++
 7 files changed, 559 insertions(+)

diff --git 
a/amie-decoder/src/main/java/org/apache/custos/amie/model/ClusterAccountEntity.java
 
b/amie-decoder/src/main/java/org/apache/custos/amie/model/ClusterAccountEntity.java
new file mode 100644
index 000000000..fc45ddf0d
--- /dev/null
+++ 
b/amie-decoder/src/main/java/org/apache/custos/amie/model/ClusterAccountEntity.java
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.custos.amie.model;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.Table;
+import org.hibernate.annotations.CreationTimestamp;
+import org.hibernate.annotations.UpdateTimestamp;
+
+import java.time.Instant;
+
+/**
+ * Maps to the 'cluster_accounts' table. Stores a provisioned username on the 
cluster.
+ */
+@Entity
+@Table(name = "cluster_accounts")
+public class ClusterAccountEntity {
+
+    @Id
+    @Column(name = "id")
+    private String id;
+
+    @ManyToOne(fetch = FetchType.LAZY, optional = false)
+    @JoinColumn(name = "person_id", nullable = false)
+    private PersonEntity person;
+
+    @Column(name = "username", nullable = false, unique = true)
+    private String username;
+
+    @Column(name = "is_active", nullable = false)
+    private boolean isActive = true;
+
+    @CreationTimestamp
+    @Column(name = "created_at", nullable = false, updatable = false)
+    private Instant createdAt;
+
+    @UpdateTimestamp
+    @Column(name = "updated_at", nullable = false)
+    private Instant updatedAt;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public PersonEntity getPerson() {
+        return person;
+    }
+
+    public void setPerson(PersonEntity person) {
+        this.person = person;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public boolean isActive() {
+        return isActive;
+    }
+
+    public void setActive(boolean active) {
+        isActive = active;
+    }
+
+    public Instant getCreatedAt() {
+        return createdAt;
+    }
+
+    public void setCreatedAt(Instant createdAt) {
+        this.createdAt = createdAt;
+    }
+
+    public Instant getUpdatedAt() {
+        return updatedAt;
+    }
+
+    public void setUpdatedAt(Instant updatedAt) {
+        this.updatedAt = updatedAt;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == null || getClass() != o.getClass()) return false;
+
+        ClusterAccountEntity that = (ClusterAccountEntity) o;
+        return id.equals(that.id) && username.equals(that.username);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = id.hashCode();
+        result = 31 * result + username.hashCode();
+        return result;
+    }
+}
diff --git 
a/amie-decoder/src/main/java/org/apache/custos/amie/model/PersonDnsEntity.java 
b/amie-decoder/src/main/java/org/apache/custos/amie/model/PersonDnsEntity.java
new file mode 100644
index 000000000..911d61ba5
--- /dev/null
+++ 
b/amie-decoder/src/main/java/org/apache/custos/amie/model/PersonDnsEntity.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.custos.amie.model;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.Table;
+import jakarta.persistence.UniqueConstraint;
+
+/**
+ * Maps to the 'person_dns' table. Stores a Distinguished Name (DN) for a 
person.
+ */
+@Entity
+@Table(name = "person_dns", uniqueConstraints = {@UniqueConstraint(columnNames 
= {"person_id", "dn"})})
+public class PersonDnsEntity {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    @Column(name = "id")
+    private Long id;
+
+    @ManyToOne(fetch = FetchType.LAZY, optional = false)
+    @JoinColumn(name = "person_id", nullable = false)
+    private PersonEntity person;
+
+    @Column(name = "dn", nullable = false, length = 512)
+    private String dn;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public PersonEntity getPerson() {
+        return person;
+    }
+
+    public void setPerson(PersonEntity person) {
+        this.person = person;
+    }
+
+    public String getDn() {
+        return dn;
+    }
+
+    public void setDn(String dn) {
+        this.dn = dn;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == null || getClass() != o.getClass()) return false;
+
+        PersonDnsEntity that = (PersonDnsEntity) o;
+        return id.equals(that.id);
+    }
+
+    @Override
+    public int hashCode() {
+        return id.hashCode();
+    }
+}
diff --git 
a/amie-decoder/src/main/java/org/apache/custos/amie/model/PersonEntity.java 
b/amie-decoder/src/main/java/org/apache/custos/amie/model/PersonEntity.java
new file mode 100644
index 000000000..1603cfcf9
--- /dev/null
+++ b/amie-decoder/src/main/java/org/apache/custos/amie/model/PersonEntity.java
@@ -0,0 +1,192 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.custos.amie.model;
+
+import jakarta.persistence.CascadeType;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.Id;
+import jakarta.persistence.OneToMany;
+import jakarta.persistence.Table;
+import org.hibernate.annotations.CreationTimestamp;
+import org.hibernate.annotations.UpdateTimestamp;
+
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Maps to the 'persons' table. Stores a unique record for each person 
received from AMIE.
+ */
+@Entity
+@Table(name = "persons")
+public class PersonEntity {
+
+    @Id
+    @Column(name = "id")
+    private String id;
+
+    @Column(name = "access_global_id", nullable = false, unique = true)
+    private String accessGlobalId;
+
+    @Column(name = "first_name", nullable = false)
+    private String firstName;
+
+    @Column(name = "last_name", nullable = false)
+    private String lastName;
+
+    @Column(name = "email", nullable = false)
+    private String email;
+
+    @Column(name = "organization")
+    private String organization;
+
+    @Column(name = "org_code")
+    private String orgCode;
+
+    @Column(name = "nsf_status_code", length = 32)
+    private String nsfStatusCode;
+
+    @CreationTimestamp
+    @Column(name = "created_at", nullable = false, updatable = false)
+    private Instant createdAt;
+
+    @UpdateTimestamp
+    @Column(name = "updated_at", nullable = false)
+    private Instant updatedAt;
+
+    @OneToMany(mappedBy = "person", cascade = CascadeType.ALL, orphanRemoval = 
true, fetch = FetchType.LAZY)
+    private List<PersonDnsEntity> dnsEntries = new ArrayList<>();
+
+    @OneToMany(mappedBy = "person", cascade = CascadeType.ALL, orphanRemoval = 
true, fetch = FetchType.LAZY)
+    private List<ClusterAccountEntity> clusterAccounts = new ArrayList<>();
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getAccessGlobalId() {
+        return accessGlobalId;
+    }
+
+    public void setAccessGlobalId(String accessGlobalId) {
+        this.accessGlobalId = accessGlobalId;
+    }
+
+    public String getFirstName() {
+        return firstName;
+    }
+
+    public void setFirstName(String firstName) {
+        this.firstName = firstName;
+    }
+
+    public String getLastName() {
+        return lastName;
+    }
+
+    public void setLastName(String lastName) {
+        this.lastName = lastName;
+    }
+
+    public String getEmail() {
+        return email;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    public String getOrganization() {
+        return organization;
+    }
+
+    public void setOrganization(String organization) {
+        this.organization = organization;
+    }
+
+    public String getOrgCode() {
+        return orgCode;
+    }
+
+    public void setOrgCode(String orgCode) {
+        this.orgCode = orgCode;
+    }
+
+    public String getNsfStatusCode() {
+        return nsfStatusCode;
+    }
+
+    public void setNsfStatusCode(String nsfStatusCode) {
+        this.nsfStatusCode = nsfStatusCode;
+    }
+
+    public Instant getCreatedAt() {
+        return createdAt;
+    }
+
+    public void setCreatedAt(Instant createdAt) {
+        this.createdAt = createdAt;
+    }
+
+    public Instant getUpdatedAt() {
+        return updatedAt;
+    }
+
+    public void setUpdatedAt(Instant updatedAt) {
+        this.updatedAt = updatedAt;
+    }
+
+    public List<PersonDnsEntity> getDnsEntries() {
+        return dnsEntries;
+    }
+
+    public void setDnsEntries(List<PersonDnsEntity> dnsEntries) {
+        this.dnsEntries = dnsEntries;
+    }
+
+    public List<ClusterAccountEntity> getClusterAccounts() {
+        return clusterAccounts;
+    }
+
+    public void setClusterAccounts(List<ClusterAccountEntity> clusterAccounts) 
{
+        this.clusterAccounts = clusterAccounts;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == null || getClass() != o.getClass()) return false;
+
+        PersonEntity that = (PersonEntity) o;
+        return id.equals(that.id) && 
accessGlobalId.equals(that.accessGlobalId);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = id.hashCode();
+        result = 31 * result + accessGlobalId.hashCode();
+        return result;
+    }
+}
+
diff --git 
a/amie-decoder/src/main/java/org/apache/custos/amie/repo/ClusterAccountRepository.java
 
b/amie-decoder/src/main/java/org/apache/custos/amie/repo/ClusterAccountRepository.java
new file mode 100644
index 000000000..05b8b2aca
--- /dev/null
+++ 
b/amie-decoder/src/main/java/org/apache/custos/amie/repo/ClusterAccountRepository.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.custos.amie.repo;
+
+import org.apache.custos.amie.model.ClusterAccountEntity;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.Optional;
+
+@Repository
+public interface ClusterAccountRepository extends 
JpaRepository<ClusterAccountEntity, String> {
+
+    Optional<ClusterAccountEntity> findByUsername(String username);
+
+}
diff --git 
a/amie-decoder/src/main/java/org/apache/custos/amie/repo/PersonDnsRepository.java
 
b/amie-decoder/src/main/java/org/apache/custos/amie/repo/PersonDnsRepository.java
new file mode 100644
index 000000000..5773bc306
--- /dev/null
+++ 
b/amie-decoder/src/main/java/org/apache/custos/amie/repo/PersonDnsRepository.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.custos.amie.repo;
+
+import org.apache.custos.amie.model.PersonDnsEntity;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface PersonDnsRepository extends JpaRepository<PersonDnsEntity, 
Long> {
+}
diff --git 
a/amie-decoder/src/main/java/org/apache/custos/amie/repo/PersonRepository.java 
b/amie-decoder/src/main/java/org/apache/custos/amie/repo/PersonRepository.java
new file mode 100644
index 000000000..1f8254162
--- /dev/null
+++ 
b/amie-decoder/src/main/java/org/apache/custos/amie/repo/PersonRepository.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.custos.amie.repo;
+
+import org.apache.custos.amie.model.PersonEntity;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.Optional;
+
+@Repository
+public interface PersonRepository extends JpaRepository<PersonEntity, String> {
+
+    /**
+     * Finds a person by their unique AMIE Global ID.
+     *
+     * @param accessGlobalId The UserGlobalID from an AMIE packet.
+     * @return An Optional containing the PersonEntity if found.
+     */
+    Optional<PersonEntity> findByAccessGlobalId(String accessGlobalId);
+
+}
diff --git 
a/amie-decoder/src/main/resources/db/migration/V1__initial_migration.sql 
b/amie-decoder/src/main/resources/db/migration/V1__initial_migration.sql
index 37ba745d6..9929d3236 100644
--- a/amie-decoder/src/main/resources/db/migration/V1__initial_migration.sql
+++ b/amie-decoder/src/main/resources/db/migration/V1__initial_migration.sql
@@ -7,6 +7,63 @@ SET NAMES utf8mb4;
 SET
 time_zone = '+00:00';
 
+-- -----------------------------
+-- TABLE: persons
+-- Stores a unique record for each person received from AMIE.
+-- -----------------------------
+CREATE TABLE persons
+(
+    id               VARCHAR(255) NOT NULL, -- Local user ID - UserPersonID
+    access_global_id VARCHAR(255) NOT NULL, -- UserGlobalID from AMIE
+    first_name       VARCHAR(255) NOT NULL,
+    last_name        VARCHAR(255) NOT NULL,
+    email            VARCHAR(255) NOT NULL,
+    organization     VARCHAR(255) NULL,
+    org_code         VARCHAR(255) NULL,
+    nsf_status_code  VARCHAR(32) NULL,
+    created_at       TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+    updated_at       TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON 
UPDATE CURRENT_TIMESTAMP(6),
+
+    PRIMARY KEY (id),
+    UNIQUE KEY uq_persons_amie_global_id (access_global_id)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+
+-- -----------------------------
+-- TABLE: person_dns
+-- Stores the list of Distinguished Names (DNs) for a person.
+-- -----------------------------
+CREATE TABLE person_dns
+(
+    id        BIGINT       NOT NULL AUTO_INCREMENT,
+    person_id VARCHAR(255) NOT NULL,
+    dn        VARCHAR(512) NOT NULL,
+
+    PRIMARY KEY (id),
+    CONSTRAINT fk_dns_person FOREIGN KEY (person_id) REFERENCES persons (id) 
ON DELETE CASCADE,
+    UNIQUE KEY uq_person_dn (person_id, dn)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+
+-- -----------------------------
+-- TABLE: cluster_accounts
+-- Stores the actual provisioned usernames on the cluster.
+-- -----------------------------
+CREATE TABLE cluster_accounts
+(
+    id         VARCHAR(255) NOT NULL,
+    person_id  VARCHAR(255) NOT NULL,
+    username   VARCHAR(255) NOT NULL,
+    is_active  BOOLEAN      NOT NULL DEFAULT TRUE,
+    created_at TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+    updated_at TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE 
CURRENT_TIMESTAMP(6),
+
+    PRIMARY KEY (id),
+    UNIQUE KEY uq_accounts_username (username),
+    CONSTRAINT fk_accounts_person FOREIGN KEY (person_id) REFERENCES persons 
(id) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+
 -- -----------------------------
 -- TABLE: packets
 -- Stores each unique AMIE packet received from the polling endpoint
@@ -30,6 +87,7 @@ CREATE TABLE packets
     KEY          idx_packets_received_at (received_at)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
 
+
 -- -----------------------------
 -- TABLE: processing_events
 -- Individual processing steps for a given packet
@@ -56,6 +114,7 @@ CREATE TABLE processing_events
     KEY         idx_events_type (type)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
 
+
 -- -----------------------------
 -- TABLE: processing_errors
 -- Processing error logs

Reply via email to