package com.intrbiz.bergamot.model; import java.io.Serializable; import java.sql.Timestamp; import java.util.Arrays; import java.util.UUID; import com.intrbiz.bergamot.data.BergamotDB; import com.intrbiz.data.db.compiler.meta.Action; import com.intrbiz.data.db.compiler.meta.SQLColumn; import com.intrbiz.data.db.compiler.meta.SQLForeignKey; import com.intrbiz.data.db.compiler.meta.SQLPrimaryKey; import com.intrbiz.data.db.compiler.meta.SQLTable; import com.intrbiz.data.db.compiler.meta.SQLVersion; import com.intrbiz.util.CounterHOTP.CounterHOTPState; import com.intrbiz.util.HOTP.HOTPSecret; import com.intrbiz.util.HOTP.HOTPState; import com.intrbiz.util.HOTPRegistration; /** * A (counter) HOTP based system which can been configured for the contract */ @SQLTable(schema = BergamotDB.class, name = "hotp_registration", since = @SQLVersion({ 3, 39, 0 })) public class ContactHOTPRegistration implements Serializable, HOTPRegistration { private static final long serialVersionUID = 1L; @SQLColumn(index = 1, name = "id", since = @SQLVersion({ 3, 39, 0 })) @SQLPrimaryKey private UUID id; /** * The contact whom this token represents */ @SQLColumn(index = 2, name = "contact_id", since = @SQLVersion({ 3, 39, 0 })) @SQLForeignKey(references = Contact.class, on = "id", onDelete = Action.CASCADE, onUpdate = Action.RESTRICT, since = @SQLVersion({ 1, 0, 0 })) private UUID contactId; @SQLColumn(index = 3, name = "secret", notNull = true, since = @SQLVersion({ 3, 39, 0 })) private byte[] secret; @SQLColumn(index = 4, name = "counter", notNull = true, since = @SQLVersion({ 3, 39, 0 })) private long counter; /** * When did we register this device */ @SQLColumn(index = 5, name = "created", since = @SQLVersion({ 3, 39, 0 })) private Timestamp created = new Timestamp(System.currentTimeMillis()); /** * When was this last updated */ @SQLColumn(index = 6, name = "updated", since = @SQLVersion({ 3, 39, 0 })) private Timestamp updated = null; /** * Has this device been revoked */ @SQLColumn(index = 7, name = "revoked", since = @SQLVersion({ 3, 39, 0 })) private boolean revoked = false; /** * When was it revoked */ @SQLColumn(index = 8, name = "revoked_at", since = @SQLVersion({ 3, 39, 0 })) private Timestamp revokedAt = null; /** * A name for this method */ @SQLColumn(index = 9, name = "summary", since = @SQLVersion({ 3, 39, 0 })) private String summary; public ContactHOTPRegistration() { super(); } public ContactHOTPRegistration(Contact contact, HOTPSecret secret, String summary) { this.id = Site.randomId(contact.getSiteId()); this.contactId = contact.getId(); this.created = new Timestamp(System.currentTimeMillis()); this.updated = null; this.revoked = false; this.secret = secret.getSecret(); this.counter = 0L; this.summary = summary; } public UUID getContactId() { return contactId; } public void setContactId(UUID contactId) { this.contactId = contactId; } public UUID getId() { return id; } public void setId(UUID id) { this.id = id; } public byte[] getSecret() { return secret; } public void setSecret(byte[] secret) { this.secret = secret; } public String getSummary() { return summary; } public void setSummary(String summary) { this.summary = summary; } public long getCounter() { return counter; } public void setCounter(long counter) { this.counter = counter; } public Timestamp getCreated() { return created; } public void setCreated(Timestamp created) { this.created = created; } public Timestamp getUpdated() { return updated; } public void setUpdated(Timestamp updated) { this.updated = updated; } public boolean isRevoked() { return revoked; } public void setRevoked(boolean revoked) { this.revoked = revoked; } public Timestamp getRevokedAt() { return revokedAt; } public void setRevokedAt(Timestamp revokedAt) { this.revokedAt = revokedAt; } public Contact getContact() { if (this.getContactId() == null) return null; try (BergamotDB db = BergamotDB.connect()) { return db.getContact(this.getContactId()); } } public HOTPSecret toHOTPSecret() { return new HOTPSecret(this.secret); } public CounterHOTPState toHOTPState() { return new CounterHOTPState(this.counter); } public ContactHOTPRegistration revoke() { this.revoked = true; this.revokedAt = new Timestamp(System.currentTimeMillis()); return this; } public ContactHOTPRegistration used(CounterHOTPState newState) { this.counter = newState.getCounter(); this.updated = new Timestamp(System.currentTimeMillis()); return this; } @Override public HOTPSecret getHOTPSecret() { return this.toHOTPSecret(); } @SuppressWarnings("unchecked") @Override public <T extends HOTPState> T getHOTPState() { return (T) this.toHOTPState(); } public String toString() { return "HOTPToken { secret=" + Arrays.toString(this.secret) + ", counter=" + this.counter + "}"; } }