HttpSession.java
/*
* The coLAB project
* Copyright (C) 2021-2023 AlbaSim, MEI, HEIG-VD, HES-SO
*
* Licensed under the MIT License
*/
package ch.colabproject.colab.api.model.user;
import static ch.colabproject.colab.api.model.user.User.USER_SEQUENCE_NAME;
import ch.colabproject.colab.api.model.WithPermission;
import ch.colabproject.colab.api.model.WithWebsocketChannels;
import ch.colabproject.colab.api.model.tools.EntityHelper;
import ch.colabproject.colab.api.security.permissions.Conditions;
import ch.colabproject.colab.api.ws.channel.tool.ChannelsBuilders.AboutAccountChannelsBuilder;
import ch.colabproject.colab.api.ws.channel.tool.ChannelsBuilders.ChannelsBuilder;
import ch.colabproject.colab.api.ws.channel.tool.ChannelsBuilders.ForAdminChannelsBuilder;
import ch.colabproject.colab.generator.model.interfaces.WithId;
import ch.colabproject.colab.generator.model.interfaces.WithJsonDiscriminator;
import java.time.OffsetDateTime;
import javax.json.bind.annotation.JsonbTransient;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Index;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;
/**
* store session related information
*
* @author maxence
*/
@Entity
@Table(
indexes = {
@Index(columnList = "account_id"),
}
)
@NamedQuery(
name = "HttpSession.getOlderThan",
query = "SELECT session FROM HttpSession session WHERE session.lastSeen < :time"
)
public class HttpSession
implements WithId, WithJsonDiscriminator, WithPermission, WithWebsocketChannels {
private static final long serialVersionUID = 1L;
// ---------------------------------------------------------------------------------------------
// fields
// ---------------------------------------------------------------------------------------------
/**
* Not so secret id
*/
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = USER_SEQUENCE_NAME)
private Long id;
/**
* raw secret, never persisted, never serialized to client. This is just a temporary field to
* store the raw value to put in SET-COOKIE
*/
@Size(max = 255)
@JsonbTransient
@Transient
private String rawSessionSecret;
/**
* Session secret id. This value is hashed and is persisted in db.
* <p>
* DO NOT SERIALIZE IN JSON EVER
*/
@JsonbTransient
@NotEmpty
private byte[] sessionSecret;
/**
* Last activity date
*/
private OffsetDateTime lastSeen;
/**
* User Agent who create the session
*/
@Size(max = 255)
private String userAgent;
/**
* A HttpSession belongs to an account
*/
@ManyToOne(optional = false, fetch = FetchType.LAZY)
@JsonbTransient
private Account account;
/**
* id of the account used for authentication
*/
@Transient
private Long accountId;
// ---------------------------------------------------------------------------------------------
// getters and setters
// ---------------------------------------------------------------------------------------------
/**
* @return account id
*/
@Override
public Long getId() {
return id;
}
/**
* set id
*
* @param id id
*/
public void setId(Long id) {
this.id = id;
}
/**
* Get the raw secret. This will almost always return null
*
* @return the raw secret or null
*/
public String getRawSessionSecret() {
return rawSessionSecret;
}
/**
* Set raw secret value
*
* @param rawSessionSecret the raw secret
*/
public void setRawSessionSecret(String rawSessionSecret) {
this.rawSessionSecret = rawSessionSecret;
}
/**
* @return Get the session id
*/
public byte[] getSessionSecret() {
return sessionSecret;
}
/**
* Set session id
*
* @param sessionSecret id of the session
*/
public void setSessionSecret(byte[] sessionSecret) {
this.sessionSecret = sessionSecret;
}
/**
* @return Get last activity date
*/
public OffsetDateTime getLastSeen() {
return lastSeen;
}
/**
* Set last activity date
*
* @param lastSeen lastSeen
*/
public void setLastSeen(OffsetDateTime lastSeen) {
this.lastSeen = lastSeen;
}
/**
* Get the value of userAgent
*
* @return the value of userAgent
*/
public String getUserAgent() {
return userAgent;
}
/**
* Set the value of userAgent
*
* @param userAgent new value of userAgent
*/
public void setUserAgent(String userAgent) {
this.userAgent = userAgent;
}
/**
* Get the account linked to this session. The only case the account may be null is on logout or
* when the session is going to be deleted
*
* @return authenticated account
*/
public Account getAccount() {
return account;
}
/**
* Set the account linked to this HttpSession
*
* @param account authenticated account
*/
public void setAccount(Account account) {
this.account = account;
}
/**
* @return authenticated account, null if not authenticated
*/
public Long getAccountId() {
if (account != null) {
return account.getId();
} else {
return accountId;
}
}
/**
* Set authenticated account id
*
* @param accountId id of the account account
*/
public void setAccountId(Long accountId) {
this.accountId = accountId;
}
// ---------------------------------------------------------------------------------------------
// concerning the whole class
// ---------------------------------------------------------------------------------------------
@Override
public ChannelsBuilder getChannelsBuilder() {
if (this.account != null) {
return new AboutAccountChannelsBuilder(this.account);
} else {
return new ForAdminChannelsBuilder();
}
}
@Override
@JsonbTransient
public Conditions.Condition getReadCondition() {
if (this.account != null) {
// same
return this.account.getReadCondition();
} else {
// not linked to any account, nothing to hide
// This case may only exist when the session is about to be destroyed
return Conditions.alwaysTrue;
}
}
@Override
@JsonbTransient
public Conditions.Condition getUpdateCondition() {
if (this.account != null) {
// same
return this.account.getUpdateCondition();
} else {
// not linked to any account, nothing to hide
// This case may only exist when the session is about to be destroyed
return Conditions.alwaysTrue;
}
}
@Override
@JsonbTransient
public Conditions.Condition getCreateCondition() {
// anyone can create a session
return Conditions.alwaysTrue;
}
@Override
public int hashCode() {
return EntityHelper.hashCode(this);
}
@Override
@SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
public boolean equals(Object obj) {
return EntityHelper.equals(this, obj);
}
@Override
public String toString() {
return "HttpSession{" + "id=" + id + ", account=" + account + ", lastSeen=" + lastSeen
+ '}';
}
}