All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.venky.swf.db.model.UserImpl Maven / Gradle / Ivy

The newest version!
package com.venky.swf.db.model;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;

import com.venky.cache.Cache;
import com.venky.core.collections.SequenceSet;
import com.venky.core.date.DateUtils;
import com.venky.core.log.SWFLogger;
import com.venky.core.log.TimerStatistics.Timer;
import com.venky.core.string.StringUtil;
import com.venky.core.util.ObjectUtil;
import com.venky.digest.Encryptor;
import com.venky.extension.Registry;
import com.venky.swf.db.Database;
import com.venky.swf.db.annotations.column.pm.PARTICIPANT;
import com.venky.swf.db.model.reflection.ModelReflector;
import com.venky.swf.db.table.ModelImpl;
import com.venky.swf.db.table.Table.ColumnDescriptor;
import com.venky.swf.exceptions.AccessDeniedException;
import com.venky.swf.pm.DataSecurityFilter;
import com.venky.swf.routing.Config;
import com.venky.swf.sql.Conjunction;
import com.venky.swf.sql.Expression;
import com.venky.swf.sql.Operator;
import com.venky.swf.sql.Select;

public class UserImpl extends ModelImpl{
	
	public UserImpl(User user) {
		super(user);
	}
	public void generateApiKey(){
		generateApiKey(true);
	}
	public void generateApiKey(boolean save){
	    User user = getProxy();
		StringBuilder key = new StringBuilder();
		key.append(getProxy().getId()).append(":").append(getProxy().getName()).append(":").append(getProxy().getPassword()).append(":").append(System.currentTimeMillis());
		String encryptedKey = Encryptor.encrypt(key.toString());
		user.setApiKey(encryptedKey);
		user.setApiKeyGeneratedTs(new Timestamp(System.currentTimeMillis()));
		if (save) {
			user.save();
		}
	}
	
	public String getChangePassword(){
		return "";
	}
	
	public void setChangePassword(String password){
		if (!ObjectUtil.isVoid(password)){
			getProxy().setPassword(password);
			getProxy().setPasswordEncrypted(false);
			getProxy().setUpdatedAt(new Timestamp(System.currentTimeMillis()));
		}
	}
	public String getEncryptedPassword(String unencyptedPassword){
		String password = unencyptedPassword;
		if (!ObjectUtil.isVoid(unencyptedPassword) && Config.instance().shouldPasswordsBeEncrypted()){
			User user = getProxy();
			if (user.getReflector().isVoid(user.getCreatedAt())){
				user.setCreatedAt(user.getReflector().getNow());
			}
			long time = user.getCreatedAt().getTime();
			String salt = time + "--" + user.getName() + "--" ;
			password = Encryptor.encrypt(unencyptedPassword + "--" + salt);
		}
		return password;
	}

	public boolean authenticate(String password){
		boolean ret = true;
		try {
			User user = getProxy();
			Registry.instance().callExtensions(User.USER_AUTHENTICATE, user,password);
		}catch (AccessDeniedException ex){
			ret  = false;
		}
		return ret;
	}

	public int getNumMinutesToKeyExpiration(){
        int keyLifeInMinutes = Config.instance().getIntProperty("api.key.expiration.days",30) * 24 * 60;
        User user = getProxy();
	    if (user.getApiKey() != null && user.getApiKeyGeneratedTs() == null){
	        //Backward compatibility dont expire.
            return keyLifeInMinutes;
        }
        if (user.getApiKey() == null){
	        return -1; //Treat as expired.
        }
        int keyLivedMinutes = DateUtils.compareToMinutes(System.currentTimeMillis(),user.getApiKeyGeneratedTs().getTime());
        return keyLifeInMinutes - keyLivedMinutes;
    }
	
	private Cache, SequenceSet> participantExtensionPointsCache = new Cache, SequenceSet>() {
		/**
		 * 
		 */
		private static final long serialVersionUID = -1863284571543640448L;

		@Override
		protected SequenceSet getValue(Class modelClass) {
			SequenceSet extnPoints = new SequenceSet();
			ModelReflector ref = ModelReflector.instance(modelClass);
			for (Class inHierarchy : ref.getClassHierarchies()){
				String extnPoint = User.GET_PARTICIPATION_OPTION + "."+ inHierarchy.getSimpleName();
				extnPoints.add(extnPoint);
			}
			return extnPoints;
		}
	};
	public  SequenceSet getParticipationExtensionPoints(Class modelClass){
		return participantExtensionPointsCache.get(modelClass);
	}
	
	private Cache, Set> relatedTables = new Cache, Set>() {
		private static final long serialVersionUID = 3264144367149148150L;
		@Override
		protected Set getValue(Class modelClass) {
			Set tables = new HashSet();
			load(tables,modelClass);
			return tables;
		}
		private void load(Set tables, Class modelClass){
			if (tables.add(ModelReflector.instance(modelClass).getTableName())){
				for (Method m : ModelReflector.instance(modelClass).getParticipantModelGetters()){ 
					@SuppressWarnings("unchecked")
					Class referredModelClass = (Class)m.getReturnType();
					load(tables,referredModelClass);
				}
			}
		}
	}; 
	private final SWFLogger cat = Config.instance().getLogger(getClass().getName());
	public  Cache>> getParticipationOptions(Class modelClass){
		return getParticipationOptions(modelClass,Database.getTable(modelClass).newRecord());
	}
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public Cache>> getParticipationOptions(Class modelClass, Model model) {
		if (model != null && model.isDirty()){
			//Cannot cache!! possibly from autocomplete. may be the dirtyness is requi
			return _getParticipationOptions(modelClass,model);
		}

		long id = (model == null  || model.getRawRecord().isNewRecord()) ? 0L : model.getId();


		Timer timer = cat.startTimer("getting participating Options for " + modelClass.getSimpleName() + "." + id);


		Set tables = new HashSet(relatedTables.get(modelClass));
		tables.retainAll(Database.getInstance().getCurrentTransaction().getTablesChanged());

		Cache,Cache>>>> baseParticipationOptions = Database.getInstance().getCurrentTransaction().getAttribute(this.getClass().getName() + ".getParticipationOptions" );
		if (baseParticipationOptions == null){
			baseParticipationOptions = new Cache, Cache>>>>() {
				@Override
				protected Cache>>> getValue(Class aModelClass) {
					return new Cache>>>() {
						@Override
						protected Cache>> getValue(Long modelId) {
							Model aModel = null;
							if (ObjectUtil.equals(0L,modelId)){
								aModel = Database.getTable(aModelClass).newRecord();
							}else {
								aModel = Database.getTable(aModelClass).get(modelId);
							}
							return _getParticipationOptions(aModelClass,aModel);
						}
					};
				}

				private static final long serialVersionUID = -5570691940356510299L;

			};
			Database.getInstance().getCurrentTransaction().setAttribute(this.getClass().getName() + ".getParticipationOptions" ,baseParticipationOptions);
		}

		if (!tables.isEmpty()){
			baseParticipationOptions.remove(modelClass);
		}
		timer.stop();
		return baseParticipationOptions.get(modelClass).get(id);
	}
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public Cache>> _getParticipationOptions(Class modelClass, Model model){
        Timer timer = cat.startTimer("_getting participating Options for " + modelClass.getSimpleName() +"/" + (model != null ? model.getId() : "" ));
		try {


			Cache>> mapParticipatingGroupOptions = new Cache>>(){

				/**
				 * 
				 */
				private static final long serialVersionUID = -6588079568930541478L;

				@Override
				protected Map> getValue(String k) {
					return new HashMap>();
				}
				
			};
			User user = getProxy();
			if (user.isAdmin()){
				return mapParticipatingGroupOptions;
			}
			ModelReflector ref = ModelReflector.instance(modelClass);
			for (Method referredModelGetter : ref.getParticipantModelGetters()){
				String referredModelIdFieldName = ref.getReferenceField(referredModelGetter);
				PARTICIPANT participant = ref.getAnnotation(ref.getFieldGetter(referredModelIdFieldName), PARTICIPANT.class);

				Map> mapParticipatingOptions = mapParticipatingGroupOptions.get(participant.value());
				
				
				boolean extnFound = false;
				for (String extnPoint: getParticipationExtensionPoints(modelClass)){
					if (Registry.instance().hasExtensions(extnPoint)){
						Registry.instance().callExtensions(extnPoint, user, model,referredModelIdFieldName, mapParticipatingGroupOptions);
						extnFound = true;
						break;
					}					
				}
				
				if (!extnFound && Registry.instance().hasExtensions(User.GET_PARTICIPATION_OPTION)){
					Registry.instance().callExtensions(User.GET_PARTICIPATION_OPTION, user, modelClass, model, referredModelIdFieldName, mapParticipatingGroupOptions);
					extnFound = true;
				}
				
				if (!extnFound) {
					Class referredModelClass = (Class) referredModelGetter.getReturnType();
					Long rmid = ref.get(model,referredModelIdFieldName);
					Model referredModel = null;
					if (rmid != null){
						referredModel = Database.getTable(referredModelClass).get(rmid);
					}
					Cache>> referredModelParticipatingGroupOptions = null;
					if (referredModel == null){
						referredModelParticipatingGroupOptions = user.getParticipationOptions(referredModelClass);
					}else {
						referredModelParticipatingGroupOptions = user.getParticipationOptions(referredModelClass,referredModel);
					}
		
					ModelReflector referredModelReflector = ModelReflector.instance(referredModelClass);

					if (referredModelParticipatingGroupOptions.size() > 0){
						Set fields = new HashSet();
						for (String g: referredModelParticipatingGroupOptions.keySet()){
							fields.addAll(referredModelParticipatingGroupOptions.get(g).keySet());
						}
						fields.removeAll(DataSecurityFilter.getRedundantParticipationFields(fields, referredModelReflector));
						//This should have been done for partication redundant too. But that is done is getDatasecurity Whereclause.
						
						boolean couldFilterUsingDSW = !DataSecurityFilter.anyFieldIsVirtual(fields,referredModelReflector); 
						
						Select q = new Select().from(referredModelClass);
						Select.ResultFilter filter = null;
						if (couldFilterUsingDSW){
							q.where(getDataSecurityWhereClause(referredModelReflector,referredModelParticipatingGroupOptions));
						}else {
							filter = new Select.AccessibilityFilter(user);
						}
						List referables = q.execute(referredModelClass,filter);
						List ids = DataSecurityFilter.getIds(referables);
						mapParticipatingOptions.put(referredModelIdFieldName,ids);
					}
				}
			}
			
			return mapParticipatingGroupOptions;
		}finally{
			timer.stop();
		}
	}
	
	public boolean isAdmin(){
		return getProxy().getId() == 1;
	}
	

	public Expression getDataSecurityWhereClause(Class modelClass){
		Model dummy = Database.getTable(modelClass).newRecord();
		return getDataSecurityWhereClause(modelClass, dummy);
	}
	
	public Expression getDataSecurityWhereClause(Class modelClass,Model model){
		ModelReflector ref = ModelReflector.instance(modelClass);
		Cache>> participatingOptions = getParticipationOptions(modelClass,model);
		return getDataSecurityWhereClause(ref, participatingOptions);
	}
	public Expression getDataSecurityWhereClause(ModelReflector ref, Cache>> participatingGroupOptions){
		Expression dswMandatory = new Expression(getPool(),Conjunction.AND);
		
		Map optionalWhere = new HashMap();
		for (String participantRoleGroup: participatingGroupOptions.keySet()){
			Expression dswOptional = new Expression(getPool(),Conjunction.OR);
			optionalWhere.put(participantRoleGroup, dswOptional);
			dswMandatory.add(dswOptional);
		}

		for (String participantRoleGroup : participatingGroupOptions.keySet()){
			Map> participatingOptions = participatingGroupOptions.get(participantRoleGroup);
			Iterator fieldNameIterator = participatingOptions.keySet().iterator();
			
			while (fieldNameIterator.hasNext()){
				String key = fieldNameIterator.next();
				List values = participatingOptions.get(key);

				ColumnDescriptor cd = ref.getColumnDescriptor(key);
		    	if (cd.isVirtual()){
		    		continue;
		    	}
				PARTICIPANT participant = ref.getAnnotation(ref.getFieldGetter(key),PARTICIPANT.class);
		    	if (participant.redundant() ){
					continue;
				}
				Expression dsw = optionalWhere.get(participantRoleGroup);

		    	if (values == null){
					dsw.add(new Expression(getPool(),"1",Operator.EQ,1));
					continue;
				}

		    	values = new ArrayList<>(values);

		    	if (values.isEmpty()){
		    		dsw.add(new Expression(getPool(),cd.getName(),Operator.EQ));
		    	}else if (values.size() == 1){
		    		Long value = values.get(0);
		    		if (value == null){
		    			dsw.add(new Expression(getPool(),cd.getName(),Operator.EQ));
		    		}else {
		    			dsw.add(new Expression(getPool(),cd.getName(),Operator.EQ, values.get(0)));
		    		}
		    	}else {
		    		if (values.contains(null)){
		    			values.remove(null);
						dsw.add(Expression.createExpression(getPool(),cd.getName(),Operator.EQ));
					}
					if (!values.isEmpty()){
						dsw.add(Expression.createExpression(getPool(),cd.getName(),Operator.IN, values.toArray()));
					}
		    	}
			}
		}
		return dswMandatory;
	}

	private String firstName = null;
	private String lastName = null;
	private void loadNames(){
		if (firstName != null){
			return ;
		}
		firstName = "";
		lastName = "";
		User user = getProxy();
		if (!ObjectUtil.isVoid(user.getLongName())){
			StringTokenizer tok = new StringTokenizer(user.getLongName());
			if (tok.hasMoreTokens()){
				this.firstName = tok.nextToken();
			}
			if (tok.hasMoreTokens()){
				StringBuilder lastName = new StringBuilder();
				while (tok.hasMoreTokens()) {
					if (lastName.length() >0){
						lastName.append(" ");
					}
					lastName.append(tok.nextToken());
				}
				this.lastName = lastName.toString();
			}
		}
	}
	public String getFirstName(){
		loadNames();
		return firstName;
	}
	public String getLastName(){
		loadNames();
		return lastName;
	}

	BigDecimal lat = null;
	public BigDecimal getCurrentLat(){
		return lat;
	}

	BigDecimal lng = null;
	public BigDecimal getCurrentLng(){
		return lng;
	}

	public void setCurrentLat(BigDecimal lat){
		this.lat = lat;
	}
	public void setCurrentLng(BigDecimal lng){
		this.lng = lng;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy