package com.atlassian.confluence.user;

import com.atlassian.confluence.security.Permission;
import com.atlassian.confluence.security.PermissionManager;
import com.atlassian.seraph.auth.AuthenticatorException;
import com.atlassian.spring.container.ContainerManager;
import com.atlassian.user.EntityException;
import com.atlassian.user.Group;
import com.atlassian.user.GroupManager;
import com.atlassian.user.User;
import org.apache.log4j.Logger;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * This authenticator adds users to confluence-users when they first log in
 */
public class ConfluenceGroupJoiningAuthenticator extends ConfluenceAuthenticator
{
    private static final Logger log = Logger.getLogger(ConfluenceGroupJoiningAuthenticator.class);

    public boolean login(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, final String username, String password, boolean b) throws AuthenticatorException
    {
        boolean loginSucceeded = super.login(httpServletRequest, httpServletResponse, username, password, b);

        if (loginSucceeded)
            postLogin(getUserAccessor().getUser(username)); // user cannot be null otherwise super.login will return false (see com.atlassian.seraph.auth.DefaultAuthenticator#login())

        return loginSucceeded;
    }

    void postLogin(final User user)
    {
        DefaultTransactionDefinition definition = new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRED);
        TransactionTemplate transactionTemplate = new TransactionTemplate((PlatformTransactionManager) ContainerManager.getComponent("transactionManager"), definition);
        transactionTemplate.execute(new TransactionCallbackWithoutResult()
        {
            protected void doInTransactionWithoutResult(TransactionStatus status)
            {
                final PermissionManager permissionManager = (PermissionManager) ContainerManager.getComponent("permissionManager");
                final GroupManager groupManager = (GroupManager) ContainerManager.getComponent("groupManager");

                if (!permissionManager.hasPermission(user, Permission.VIEW, PermissionManager.TARGET_APPLICATION)) // CONF-13754
                {
                    try
                    {
                        Group confluenceUsers = groupManager.getGroup(UserAccessor.GROUP_CONFLUENCE_USERS);
                        if (!groupManager.hasMembership(confluenceUsers, user))
                            groupManager.addMembership(confluenceUsers, user);
                    }
                    catch (EntityException e)
                    {
                        log.error("Failed to add " + user.getName() + " to confluence-users.", e);
                    }
                }
            }
        });
    }
}
