/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.sling.jcr.resource.internal;

import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

import javax.jcr.RepositoryException;
import javax.jcr.Session;

import org.apache.jackrabbit.api.JackrabbitSession;
import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.api.security.user.User;
import org.apache.jackrabbit.api.security.user.UserManager;
import org.apache.sling.jcr.api.SlingRepository;
import org.apache.sling.serviceusermapping.ServicePrincipalsValidator;
import org.apache.sling.serviceusermapping.ServiceUserValidator;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.Designate;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Implementation of the {@link org.apache.sling.serviceusermapping.ServiceUserValidator}
 * and {@link org.apache.sling.serviceusermapping.ServicePrincipalsValidator}
 * interfaces that verifies that all registered service users/principals are represented by
 * {@link org.apache.jackrabbit.api.security.user.User#isSystemUser() system users}
 * in the underlying JCR repository.
 *
 * @see org.apache.jackrabbit.api.security.user.User#isSystemUser()
 */
@Designate(ocd = JcrSystemUserValidator.Config.class)
@Component(service = {ServiceUserValidator.class, ServicePrincipalsValidator.class},
           property = {
                   Constants.SERVICE_VENDOR + "=The Apache Software Foundation"
           })
public class JcrSystemUserValidator implements ServiceUserValidator, ServicePrincipalsValidator {

    public static final String VALIDATION_SERVICE_USER = "validation";

    @ObjectClassDefinition(
            name = "Apache Sling JCR System User Validator",
            description = "Enforces the usage of JCR system users for all user mappings being used in the 'Sling Service User Mapper Service'")
    public @interface Config {

        @AttributeDefinition(name = "Allow only JCR System Users",
                description="If set to true, only user IDs bound to JCR system users are allowed in the user mappings of the 'Sling Service User Mapper Service'. Otherwise all users are allowed!")
        boolean allow_only_system_user() default true;
    }
    /**
     * logger instance
     */
    private final Logger log = LoggerFactory.getLogger(JcrSystemUserValidator.class);

    @Reference
    private volatile SlingRepository repository;

    private final Method isSystemUserMethod;

    private final Set<String> validIds = new CopyOnWriteArraySet<>();
    private final Set<String> validPrincipalNames = new CopyOnWriteArraySet<>();

    private boolean allowOnlySystemUsers;

    /*
    * We have to prevent a cycle if we are trying to login ourselves. The main idea is that we set the
    * cycleDetection to true for the current thread before we try to loginService('validation', null).
    * That way, if we are asked if a user is valid and the cycleDetection is true we know we are in a
    * cycle and have to shotcut by allowing the user. This should make it so that we use a service user
    * to valid all service users except our own.
    */
    private final ThreadLocal<Boolean> cycleDetection = new ThreadLocal<Boolean>() {
        @Override
        protected Boolean initialValue() {
            return false;
        }
    };

    public JcrSystemUserValidator() {
        Method m = null;
        try {
            m = User.class.getMethod("isSystemUser");
        } catch (Exception e) {
            log.debug("Exception while accessing isSystemUser method", e);
        }
        isSystemUserMethod = m;
    }

    @Activate
    public void activate(final Config config) {
        allowOnlySystemUsers = config.allow_only_system_user();
    }

    @Override
    public boolean isValid(final String serviceUserId, final String serviceName, final String subServiceName) {
        if (cycleDetection.get()) {
            // We are being asked to valid our own service user - hence, allow.
            return true;
        }
        if (serviceUserId == null) {
            log.debug("The provided service user id is null");
            return false;
        }
        if (!allowOnlySystemUsers) {
            log.debug("There is no enforcement of JCR system users, therefore service user id '{}' is valid", serviceUserId);
            return true;
        }
        if (validIds.contains(serviceUserId)) {
            log.debug("The provided service user id '{}' has been already validated and is a known JCR system user id", serviceUserId);
            return true;
        } else {
            Session session = null;
            try {
                try {
                    /*
                     * We have to prevent a cycle if we are trying to login ourselves
                     */
                    cycleDetection.set(true);
                    try {
                        session = repository.loginService(VALIDATION_SERVICE_USER, null);
                    } finally {
                        cycleDetection.set(false);
                    }
                    if (session instanceof JackrabbitSession) {
                        final UserManager userManager = ((JackrabbitSession) session).getUserManager();
                        final Authorizable authorizable = userManager.getAuthorizable(serviceUserId);
                        if (isValidSystemUser(authorizable)) {
                            validIds.add(serviceUserId);
                            log.debug("The provided service user id {} is a known JCR system user id", serviceUserId);
                            return true;
                        }
                    }
                } catch (final RepositoryException e) {
                    log.warn("Could not get user information", e);
                }
            } finally {
                if (session != null) {
                    session.logout();
                }
            }
            log.warn("The provided service user id '{}' is not a known JCR system user id and therefore not allowed in the Sling Service User Mapper.", serviceUserId);
            return false;
        }
    }

    @Override
    public boolean isValid(Iterable<String> servicePrincipalNames, String serviceName, String subServiceName) {
        if (cycleDetection.get()) {
            // We are being asked to valid our own service user - hence, allow.
            return true;
        }
        if (servicePrincipalNames == null) {
            log.debug("The provided service principal names are null");
            return false;
        }
        if (!allowOnlySystemUsers) {
            log.debug("There is no enforcement of JCR system users, therefore service principal names '{}' are valid", servicePrincipalNames);
            return true;
        }

        Session session = null;
        UserManager userManager = null;
        Set<String> invalid = new HashSet<>();
        try {
            for (final String pName : servicePrincipalNames) {
                if (validPrincipalNames.contains(pName)) {
                    log.debug("The provided service principal name '{}' has been already validated and is a known JCR system user", pName);
                } else {
                    if (session == null) {
                        /*
                         * We have to prevent a cycle if we are trying to login ourselves
                         */
                        cycleDetection.set(true);
                        try {
                            session = repository.loginService(VALIDATION_SERVICE_USER, null);
                        } finally {
                            cycleDetection.set(false);
                        }
                        if (session instanceof JackrabbitSession) {
                            userManager = ((JackrabbitSession) session).getUserManager();
                        } else {
                            log.debug("Unable to validate service user principals, JackrabbitSession expected.");
                            return false;
                        }
                    }

                    Authorizable authorizable = userManager.getAuthorizable(() -> pName);
                    if (isValidSystemUser(authorizable)) {
                        validPrincipalNames.add(pName);
                        log.debug("The provided service principal name {} is a known JCR system user", pName);
                    } else {
                        log.warn("The provided service principal name '{}' is not a known JCR system user id and therefore not allowed in the Sling Service User Mapper.", pName);
                        invalid.add(pName);
                    }
                }
            }
        } catch (final RepositoryException e) {
            log.warn("Could not get user information", e);
        } finally {
            if (session != null) {
                session.logout();
            }
        }
        return invalid.isEmpty();
    }

    private boolean isValidSystemUser(final Authorizable authorizable) {
        if (authorizable == null || authorizable.isGroup()) {
            return false;
        }

        User user = (User) authorizable;
        try {
            if (!user.isDisabled()) {
                if (isSystemUserMethod != null) {
                    try {
                        return (Boolean) isSystemUserMethod.invoke(user);
                    } catch (Exception e) {
                        log.debug("Exception while invoking isSystemUser method", e);
                        return true;
                    }
                } else {
                    return true;
                }
            }
        } catch (RepositoryException e) {
            log.debug("Exception while invoking isDisabled method", e);
        }
        return false;
    }
}