/**
 *
 */
package org.jenkinsci.plugins;

import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.GrantedAuthorityImpl;
import org.gitlab.api.models.GitlabGroup;

import hudson.security.GroupDetails;

import java.net.URI;

/**
 * Represent a group from Gitlab as a group in Jenkins terms.
 *
 * The surprising bits here are that:
 * * Gitlab groups exist in a hierarchy while jenkins groups are just a flat namespace
 * * Jenkins groups live in the same namespace as user names
 * * Gitlab users can easily be granted the privilege to create new groups and if the name
 *   of the gitlab group is allowed to become the name of the jenkins group, then a relatively
 *   low-privilege user in gitlab can create a group that clashes with privileged users and groups
 *   in jenkins and elevate jenkins privileges that way.
 *
 * The solution is two-fold:
 * * The gitlab groups must be identified as being gitlab groups to avoid clashing with jenkins user names.
 * * The gitlab group hierarchy must be reflected in the name too, to avoid being able to conflate two groups by name
 *
 */
public class GitLabOAuthGroupDetails extends GroupDetails {

    private final GitlabGroup gitlabGroup;
    static final String ORG_TEAM_SEPARATOR = "*";
    private String authName;

    /**
    * Group based on organization name
    * @param gitlabGroup
    */
    public GitLabOAuthGroupDetails(GitlabGroup gitlabGroup) {
        super();
        this.gitlabGroup = gitlabGroup;
    }

    /* (non-Javadoc)
    * @see hudson.security.GroupDetails#getName()
    */
    @Override
    public String getName() {
        if (gitlabGroup != null) {
            return getAuthName();
        }
        return null;
    }

    /**
     * Construct a globally unique identifier for the group
     *
     * The uri for the group is simply stripped of its redundant parts:
     * * The leading protocol scheme (https://)
     * * The host name
     * * The first /groups/ part
     *
     * This means that in stead of getting the full url:
     * https://gitlab.example.com/groups/administrators/supersecret
     *
     * You'll get a slightly shorter version:
     * /administrators/supersecret
     *
     * @return The shorter, but still unique id of the group
     */
    private synchronized String getAuthName() {
        if (authName == null) {
            final String webUrl = gitlabGroup.getWebUrl();
            authName = shortenGroupUri(webUrl);
        }
        return authName;
    }

    static String shortenGroupUri(String webUrl) {
        return URI.create(webUrl).getPath().replace("/groups", "");
    }

    @Override
    public String getDisplayName() {
        return "Gitlab "+ gitlabGroup.getName()+" ("+getName()+")";
    }

    @Override
    public String toString() {
        return getDisplayName();
    }

    public GrantedAuthority getAuth() {
        return new GrantedAuthorityImpl(getName());
    }
}