/*
 * Copyright 2014-2015 Hewlett-Packard Development Company, L.P.
 * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
 */

package com.hp.autonomy.frontend.abc.authentication;

import com.autonomy.aci.client.services.AciErrorException;
import com.autonomy.aci.client.services.AciServiceException;
import com.autonomy.login.role.Roles;
import com.autonomy.user.admin.UserAdmin;
import com.autonomy.user.admin.dto.UserRoles;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.hp.autonomy.frontend.configuration.AuthenticationConfig;
import com.hp.autonomy.frontend.configuration.CommunityAuthentication;
import com.hp.autonomy.frontend.configuration.ConfigService;
import com.hp.autonomy.frontend.configuration.LoginTypes;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

/**
 * A Spring Security {@link org.springframework.security.authentication.AuthenticationProvider} backed by IDOL community.
 */
public class CommunityAuthenticationProvider implements AuthenticationProvider {
    private final ConfigService<? extends AuthenticationConfig<?>> configService;
    private final UserAdmin userAdmin;
    private final Roles roles;
    private final Set<String> loginPrivileges;
    private final GrantedAuthoritiesMapper authoritiesMapper;

    public CommunityAuthenticationProvider(
            final ConfigService<? extends AuthenticationConfig<?>> configService,
            final UserAdmin userAdmin,
            final Roles roles,
            final Set<String> loginPrivileges,
            final GrantedAuthoritiesMapper authoritiesMapper
    ) {
        this.configService = configService;
        this.userAdmin = userAdmin;
        this.roles = roles;
        this.loginPrivileges = loginPrivileges;
        this.authoritiesMapper = authoritiesMapper;
    }

    @Override
    public Authentication authenticate(final Authentication authentication) throws AuthenticationException {
        final com.hp.autonomy.frontend.configuration.Authentication<?> authenticationConfig = configService.getConfig().getAuthentication();
        final String authenticationMethod = authenticationConfig.getMethod();

        if (!(authenticationConfig instanceof CommunityAuthentication) || LoginTypes.DEFAULT.equals(authenticationMethod)) {
            return null;
        }

        final String username = authentication.getName();
        final String password = authentication.getCredentials().toString();

        try {
            final boolean isAuthenticated = userAdmin.authenticateUser(username, password, authenticationMethod);

            if (!isAuthenticated) {
                throw new BadCredentialsException("Bad credentials");
            }

            final UserRoles userRoles = userAdmin.getUser(username);

            if (!roles.areRolesAuthorized(new HashSet<>(userRoles.getRoles()), loginPrivileges)) {
                throw new BadCredentialsException("Bad credentials");
            }

            final Collection<? extends GrantedAuthority> mappedAuthorities = authoritiesMapper.mapAuthorities(Lists.transform(userRoles.getRoles(), new Function<String, GrantedAuthority>() {
                @Override
                public GrantedAuthority apply(final String role) {
                    return new SimpleGrantedAuthority(role);
                }
            }));

            return new UsernamePasswordAuthenticationToken(username, password, mappedAuthorities);
        } catch (final AciErrorException aciError) {
            // This should not happen
            throw new InternalAuthenticationServiceException("An ACI error occurred while attempting to authenticate", aciError);
        } catch (final AciServiceException serviceError) {
            // This will happen if community is down
            throw new InternalAuthenticationServiceException("An error occurred while contacting community", serviceError);
        }
    }

    @Override
    public boolean supports(final Class<?> authenticationClass) {
        return authenticationClass == UsernamePasswordAuthenticationToken.class;
    }
}

@@ -219,11 +219,21 @@
 end.
-abc
+configuration
 .aut
@@ -370,214 +370,8 @@
 on;%0A
-import com.autonomy.login.role.Roles;%0Aimport com.autonomy.user.admin.UserAdmin;%0Aimport com.autonomy.user.admin.dto.UserRoles;%0Aimport com.google.common.base.Function;%0Aimport com.google.common.collect.Lists;%0A
 impo
@@ -624,16 +624,100 @@
 nTypes;%0A
+import com.hp.autonomy.user.UserService;%0Aimport com.hp.autonomy.user.dto.UserRoles;%0A
 import o
@@ -1381,16 +1381,44 @@
 apper;%0A%0A
+import java.util.ArrayList;%0A
 import j
@@ -1464,16 +1464,39 @@
 ashSet;%0A
+import java.util.List;%0A
 import j
@@ -1825,31 +1825,35 @@
 nal User
-Admin userAdmin
+Service userService
 ;%0A    pr
@@ -2031,36 +2031,32 @@
 ovider(%0A        
-    
 final ConfigServ
@@ -2109,36 +2109,32 @@
 ervice,%0A        
-    
 final UserAdmin 
@@ -2131,35 +2131,37 @@
 User
-Admin userAdmin,%0A  
+Service userService,%0A
         
   fi
@@ -2152,26 +2152,24 @@
 ce,%0A        
-  
 final Roles 
@@ -2171,28 +2171,24 @@
 oles roles,%0A
-    
         fina
@@ -2214,28 +2214,24 @@
 Privileges,%0A
-    
         fina
@@ -2348,25 +2348,29 @@
 user
-Admin = userAdmin
+Service = userService
 ;%0A  
@@ -3203,21 +3203,23 @@
 d = user
-Admin
+Service
 .authent
@@ -3441,13 +3441,15 @@
 user
-Admin
+Service
 .get
@@ -3671,29 +3671,13 @@
 nal 
-Collection%3C? extends 
+List%3C
 Gran
@@ -3690,20 +3690,21 @@
 hority%3E 
-mapp
+grant
 edAuthor
@@ -3715,100 +3715,138 @@
 s = 
-authoritiesMapper.mapAuthorities(Lists.transform(userRoles.getRoles(), new Function%3CString, 
+new ArrayList%3C%3E();%0A%0A            for (final String role : userRoles.getRoles()) %7B%0A                grantedAuthorities.add(new Simple
 Gran
@@ -3861,13 +3861,16 @@
 rity
-%3E() %7B
+(role));
 %0A   
@@ -3882,182 +3882,139 @@
     
-    @Override%0A                public GrantedAuthority apply(final String role) %7B%0A                    return new SimpleGrantedAuthority(role);%0A                %7D%0A            %7D)
+%7D%0A%0A            final Collection%3C? extends GrantedAuthority%3E mappedAuthorities = authoritiesMapper.mapAuthorities(grantedAuthorities
 );%0A%0A

Rename variables. Remove Guava.