package de.hsadmin.mods.db; import static javax.persistence.FetchType.EAGER; import static javax.persistence.GenerationType.SEQUENCE; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.DiscriminatorColumn; import javax.persistence.DiscriminatorType; import javax.persistence.Entity; import javax.persistence.EntityManager; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Inheritance; import javax.persistence.InheritanceType; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.NoResultException; import javax.persistence.Query; import javax.persistence.SequenceGenerator; import javax.persistence.Table; import javax.persistence.Transient; import de.hsadmin.core.model.AbstractEntity; import de.hsadmin.core.model.AbstractModuleImpl; import de.hsadmin.core.model.AnnFieldIO; import de.hsadmin.core.model.ReadWriteAccess; import de.hsadmin.mods.pac.Pac; import de.hsadmin.mods.user.UnixUser; @Entity @Table(name = "database_user") @Inheritance(strategy=InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(name="engine", discriminatorType=DiscriminatorType.STRING) @SequenceGenerator(name = "DatabaseUserSeqGen", sequenceName = "dbuser_dbuser_id_seq") public abstract class DatabaseUser extends AbstractEntity implements Serializable { private static final long serialVersionUID = -4840133372566213014L; @Id @GeneratedValue(strategy = SEQUENCE, generator = "DatabaseUserSeqGen") @Column(name = "dbuser_id", columnDefinition = "integer", updatable=false, insertable=false) private long id; @AnnFieldIO(validation="[a-z0-9\\_]*", rw=ReadWriteAccess.WRITEONCE) @Column(name = "name", columnDefinition = "character varying(24)", updatable=false) private String name; @AnnFieldIO(validation="[^']*", rw=ReadWriteAccess.WRITEONLY) @Transient private String password; @AnnFieldIO(validation="[a-zA-Z]*", rw=ReadWriteAccess.WRITEONCE) @Column(name = "engine", columnDefinition = "character varying(12)", updatable=false) protected String instance; @JoinColumn(name = "packet_id", columnDefinition = "integer", updatable=false) @ManyToOne(fetch = EAGER) @AnnFieldIO(validation="[a-z0-9]*", rw=ReadWriteAccess.WRITEONCE) protected Pac pac; protected DatabaseUser() { } protected DatabaseUser(String instance, Pac pac, String name, String password) { this.instance = instance; this.pac = pac; this.name = name; this.password = password; } @Override public void initialize(EntityManager em, UnixUser loginUser) { pac = loginUser.getPac(); // a default useful for the pac admin } public void complete(EntityManager em, UnixUser loginUser) { if (pac == null && name != null && name.length() > 0) { // TODO: it's ugly having this code here, needs refactoring String pacName = name.substring(0, 5); try { // get the entities name (query part from FROM to WHERE) javax.persistence.Entity entityAnnot = Pac.class .getAnnotation(javax.persistence.Entity.class); String queryString = "SELECT obj FROM " + entityAnnot.name() + " obj WHERE " + Pac.createQueryFromStringKey(pacName); // set parameters Query query = em.createQuery(queryString); AbstractModuleImpl.setQueryParameter(query, queryString, "loginUser", loginUser); AbstractModuleImpl.setQueryParameter(query, queryString, "loginUserName", loginUser.getName()); AbstractModuleImpl.setQueryParameter(query, queryString, "loginUserPac", loginUser.getPac()); pac = (Pac) query.getSingleResult(); } catch (NoResultException exc) { throw new SecurityException("packet '" + pacName + "' not found or access denied"); } } } @Override public String createStringKey() { return getName(); } @Override public long id() { return id; } public long getId() { return id; } protected void setId(long id) { this.id = id; } public String getInstance() { return instance; } public void setInstance(String instance) { this.instance = instance; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Pac getPac() { return pac; } public void setPac(Pac pac) { this.pac = pac; } @Override public boolean isNew() { return id == 0; } @Override public DatabaseUser merge(EntityManager em, UnixUser loginUser) { DatabaseUser dbEntity = (DatabaseUser) super.merge(em, loginUser); dbEntity.setPassword(this.getPassword()); return dbEntity; } @Override public String getHiveName() { if (isNew()) return null; else return getPac().getHiveName(); } @Override public UnixUser owningUser(EntityManager em) { return getPac().owningUser(em); } /** * determines whether the given user has full read access on all merged * fields of this entity */ @Override public boolean isReadAllowedFor(UnixUser loginUser) { return loginUser.hasPacAdminRoleFor(getPac()); } /** * determines whether the given user has full write access on all merged * fields of this entity */ @Override public boolean isWriteAllowedFor(UnixUser loginUser) { String pacName = pac.getName(); if (!name.equals(pacName) && !name.startsWith(pacName + "_")) return false; return loginUser.hasPacAdminRoleFor(getPac()); } /** * query restriction for access control */ public static String restriction() { return // all databases of all pacs of customer "obj.pac.customer.name=:loginUserName OR " + // all aliases of packet admin "obj.pac.name=:loginUserName"; } }