package com.tesora.dve.sql.schema;
/*
* #%L
* Tesora Inc.
* Database Virtualization Engine
* %%
* Copyright (C) 2011 - 2014 Tesora Inc.
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import com.tesora.dve.common.PEConstants;
import com.tesora.dve.common.catalog.CatalogEntity;
import com.tesora.dve.common.catalog.User;
import com.tesora.dve.exceptions.PEException;
import com.tesora.dve.sql.SchemaException;
import com.tesora.dve.sql.ParserException.Pass;
import com.tesora.dve.sql.schema.cache.SchemaCacheKey;
import com.tesora.dve.sql.schema.cache.SchemaEdge;
import com.tesora.dve.sql.util.Functional;
import com.tesora.dve.sql.util.UnaryFunction;
import com.tesora.dve.worker.UserAuthentication;
public class PEUser extends Persistable<PEUser, User> {
private final UserScope name;
private final boolean root;
private final List<SchemaEdge<PEPriviledge>> priviledges;
private Boolean globalPriviledge = null;
private UserAuthentication authentication;
public PEUser(UserScope n, String pword, boolean adminUser) {
super(getUserKey(n.getUserName(),n.getScope()));
name = n;
authentication = new UserAuthentication(n.getUserName(),pword, adminUser);
root = false;
priviledges = new ArrayList<SchemaEdge<PEPriviledge>>(0);
}
// only used in testing
public PEUser(SchemaContext sc) {
super(getUserKey(PEConstants.ROOT, PEConstants.LOCALHOST));
if (sc.isPersistent())
throw new IllegalStateException("Invalid ctor for PEUser");
name = new UserScope(PEConstants.ROOT, PEConstants.LOCALHOST);
authentication = new UserAuthentication(PEConstants.ROOT, PEConstants.PASSWORD, true);
root = true;
priviledges = new ArrayList<SchemaEdge<PEPriviledge>>(0);
}
public UserScope getUserScope() { return name; }
public UserAuthentication getUserAuthentication() {
return authentication;
}
public String getPassword() {
return authentication.getPassword();
}
public boolean isRoot() { return root; }
public void setPassword(String v) {
authentication = new UserAuthentication(name.getUserName(),v, authentication.isAdminUser());
}
private PEUser(User us, SchemaContext pc) {
super(getUserKey(us.getName(),us.getAccessSpec()));
pc.startLoading(this,us);
authentication = new UserAuthentication(us.getName(), us.getPlaintextPassword(),us.getAdminUser());
name = new UserScope(us.getName(),us.getAccessSpec());
root = us.getAdminUser();
priviledges = new ArrayList<SchemaEdge<PEPriviledge>>();
setPersistent(pc, us, us.getId());
pc.finishedLoading(this, us);
}
public static PEUser load(User us, SchemaContext pc) {
PEUser peu = (PEUser)pc.getLoaded(us,getUserKey(us.getName(),us.getAccessSpec()));
if (peu == null)
peu = new PEUser(us, pc);
return peu;
}
@SuppressWarnings("unchecked")
public Persistable<?,?> resolve(SchemaContext sc, Name dbName) {
for(Iterator<SchemaEdge<PEPriviledge>> iter = priviledges.iterator(); iter.hasNext();) {
SchemaEdge<PEPriviledge> sck = iter.next();
PEPriviledge pep = sck.get(sc);
if (pep == null)
iter.remove();
else {
Persistable<?,?> any = pep.match(dbName);
if (any != null)
return any;
}
}
// not found amongst loaded privs, go back to the catalog
PEPriviledge pep = sc.findPrivilege(this,dbName);
if (pep != null) {
priviledges.add(StructuralUtils.buildEdge(sc,pep, true));
return pep.match(dbName);
}
return null;
}
public boolean hasGlobalPriviledge(SchemaContext sc) {
if (globalPriviledge == null) {
for(Iterator<SchemaEdge<PEPriviledge>> iter = priviledges.iterator(); iter.hasNext();) {
SchemaEdge<PEPriviledge> sck = iter.next();
PEPriviledge pep = sck.get(sc);
if (pep == null)
iter.remove();
else if (pep.isGlobal()) {
globalPriviledge = true;
return true;
}
}
globalPriviledge = sc.getCatalog().findGlobalPrivilege(sc,this);
}
return globalPriviledge.booleanValue();
}
@Override
protected Class<? extends CatalogEntity> getPersistentClass() {
return User.class;
}
@Override
protected User lookup(SchemaContext pc) throws PEException {
List<User> users = pc.getCatalog().findUsers(name.getUserName(),name.getScope());
if (users.size() > 1)
throw new PEException("More than one user matching '" + name.getSQL() + "' found");
if (users.isEmpty())
return null;
return users.get(0);
}
@Override
protected User createEmptyNew(SchemaContext sc) throws PEException {
return new User(name.getUserName(), authentication.getPassword(), name.getScope());
}
@Override
protected void populateNew(SchemaContext pc, User p) throws PEException {
for(SchemaEdge<PEPriviledge> pep : priviledges) {
p.addPriviledge(pep.get(pc).persistTree(pc));
}
}
@Override
protected Persistable<PEUser, User> load(SchemaContext pc, User p) throws PEException {
return new PEUser(p,pc);
}
@Override
protected int getID(User p) {
return p.getId();
}
@Override
public boolean collectDifferences(SchemaContext sc, List<String> messages,
Persistable<PEUser, User> other, boolean first, @SuppressWarnings("rawtypes") Set<Persistable> visited) {
return false;
}
@Override
protected String getDiffTag() {
return null;
}
@Override
protected void updateExisting(SchemaContext pc, User p) throws PEException {
p.setPlaintextPassword(authentication.getPassword());
for(SchemaEdge<PEPriviledge> e : priviledges) {
PEPriviledge pep = e.get(pc);
if (pep.getPersistentID() == null) {
p.addPriviledge(pep.persistTree(pc));
}
}
}
public static SchemaCacheKey<PEUser> getUserKey(String name, String accessSpec) {
return new UserCacheKey(name,accessSpec);
}
public static SchemaCacheKey<PEUser> getUserKey(UserScope scope) {
return new UserCacheKey(scope.getUserName(),scope.getScope());
}
public static SchemaCacheKey<PEUser> getUserKey(User u) {
return new UserCacheKey(u.getName(),u.getAccessSpec());
}
public static class UserCacheKey extends SchemaCacheKey<PEUser> {
/**
*
*/
private static final long serialVersionUID = 1L;
private String name;
private String access;
public UserCacheKey(String name, String access) {
super();
this.name = name;
this.access = access;
}
@Override
public int hashCode() {
return addHash(initHash(PEUser.class,name.hashCode()),access.hashCode());
}
@Override
public String toString() {
return "PEUser:" + name + "@" + access;
}
@Override
public boolean equals(Object o) {
if (o instanceof UserCacheKey) {
UserCacheKey ulk = (UserCacheKey) o;
return this.name.equals(ulk.name) && this.access.equals(ulk.access);
}
return false;
}
@Override
public PEUser load(SchemaContext sc) {
List<User> users = sc.getCatalog().findUsers(name, access);
if (users.isEmpty()) return null;
if (users.size() > 1)
throw new SchemaException(Pass.SECOND,"Multiple users matching '" + name + "@'" + access + "' found");
return PEUser.load(users.get(0), sc);
}
@Override
public Collection<SchemaCacheKey<?>> getCascades(Object obj) {
PEUser user = (PEUser) obj;
return Functional.apply(user.priviledges, new UnaryFunction<SchemaCacheKey<?>,SchemaEdge<PEPriviledge>>() {
@Override
public SchemaCacheKey<?> evaluate(SchemaEdge<PEPriviledge> object) {
return object.getCacheKey();
}
});
}
}
}