package org.osiam.addons.administration.config;

import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;

import javax.inject.Inject;

import org.osiam.addons.administration.model.session.GeneralSessionData;
import org.osiam.client.OsiamConnector;
import org.osiam.client.query.Query;
import org.osiam.client.query.QueryBuilder;
import org.osiam.resources.scim.SCIMSearchResult;
import org.osiam.resources.scim.User;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;

/**
 * This class is responsible for decide admin-access.
 */
@Component
public class AdminAccessDecisionManager implements AccessDecisionManager {

	@Inject
	private GeneralSessionData session;

	@Inject
	private OsiamConnector connector;

	@Value("${org.osiam.administration.adminGroups}")
	private String[] adminGroups;

	@Override
	public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) {
		// if there are no access-token in session
		if (session.getAccesstoken() == null) {
			throw new AccessDeniedException("There is no accesstoken in session!");
		}

		checkForAdminGroup();
	}

	private void checkForAdminGroup() {
		if (adminGroups == null || adminGroups.length == 0) {
			return;
		}

		String queryFilter = buildQueryFilter();
		Query query = new QueryBuilder()
							.count(1)
							.filter(queryFilter)
						 .build();

		SCIMSearchResult<User> result = connector.searchUsers(query, session.getAccesstoken());

		if(result.getTotalResults() != 1) {
			throw new AccessDeniedException("The user not a member of an admin group.");
		}
	}

	private String buildQueryFilter() {
		StringBuilder queryString = new StringBuilder();
		queryString.append("userName eq ");
		queryString.append("\"");
		queryString.append(session.getAccesstoken().getUserName());
		queryString.append("\" AND (");

		Iterator<String> groupIterator = Arrays.asList(adminGroups).iterator();
		while (groupIterator.hasNext()) {
			queryString.append("groups.display eq \"");
			queryString.append(groupIterator.next());
			queryString.append("\"");

			if(groupIterator.hasNext()) {
				queryString.append(" OR ");
			}
		}
		queryString.append(")");

		return queryString.toString();
	}

	@Override
	public boolean supports(ConfigAttribute attribute) {
		return true;
	}

	@Override
	public boolean supports(Class<?> clazz) {
		return true;
	}
}

@@ -266,16 +266,73 @@
 nector;%0A
+import org.osiam.client.exception.UnauthorizedException;%0A
 import o
@@ -1466,16 +1466,203 @@
 );%0A%09%09%7D%0A%0A
+%09%09try%7B%0A%09%09%09connector.validateAccessToken(session.getAccesstoken());%0A%09%09%7Dcatch(UnauthorizedException e)%7B%0A%09%09%09throw new AccessDeniedException(%22The current accesstoken is not valid!%22, e);%0A%09%09%7D%0A%0A
 %09%09checkF
@@ -1919,17 +1919,16 @@
 )%0A%09%09%09%09%09%09
- 
 .build()

check the access token vality