{% if cookiecutter.cdsdashboards.enabled %}

# ================ CDSDASHBOARDS =====================
c.JupyterHub.allow_named_servers = True
from cdsdashboards.hubextension import cds_extra_handlers
c.JupyterHub.extra_handlers = cds_extra_handlers
from cdsdashboards.app import CDS_TEMPLATE_PATHS
c.JupyterHub.template_paths = CDS_TEMPLATE_PATHS
c.JupyterHub.spawner_class = 'cdsdashboards.hubextension.spawners.variablekube.VariableKubeSpawner'
c.CDSDashboardsConfig.builder_class = 'cdsdashboards.builder.kubebuilder.KubeBuilder'
c.VariableMixin.default_presentation_cmd = ['python3', '-m', 'jhsingle_native_proxy.main']

c.JupyterHub.default_url = '/hub/home'

{% else %}

c.JupyterHub.allow_named_servers = False
c.JupyterHub.spawner_class = 'kubespawner.KubeSpawner'
c.JupyterHub.template_paths = []
c.JupyterHub.extra_handlers = []

{% endif %}

# ==================== THEME =========================
import tornado.web
import qhub_jupyterhub_theme

c.JupyterHub.extra_handlers += [
    (r'/custom/(.*)', tornado.web.StaticFileHandler, {"path": qhub_jupyterhub_theme.STATIC_PATH}),
]

c.JupyterHub.template_paths = [
    qhub_jupyterhub_theme.TEMPLATE_PATH
] + c.JupyterHub.template_paths

c.JupyterHub.template_vars = {
{%- for key, value in cookiecutter.theme.jupyterhub.items() %}
    "{{ key }}": "{{ value | replace('\"', '\\"') }}",
{%- endfor %}
{% if cookiecutter.cdsdashboards.enabled %}
    "cdsdashboards_enabled": True,
    {% if cookiecutter.cdsdashboards.cds_hide_user_named_servers is defined %}
    "cds_hide_user_named_servers": {{ cookiecutter.cdsdashboards.cds_hide_user_named_servers }},
    {% endif %}
    {% if cookiecutter.cdsdashboards.cds_hide_user_dashboard_servers is defined %}
    "cds_hide_user_dashboard_servers": {{ cookiecutter.cdsdashboards.cds_hide_user_dashboard_servers }},
    {% endif %}
{% endif %}
}

# ================= Profiles =====================
QHUB_USER_MAPPING = {{ cookiecutter.security.users }}
QHUB_GROUP_MAPPING = {{ cookiecutter.security.groups }}
QHUB_PROFILES = {{ cookiecutter.profiles.jupyterlab }}


def qhub_generate_nss_files():
    passwd = []
    passwd_format = '{username}:x:{uid}:{gid}:{username}:/home/jovyan:/bin/bash'
    for username, config in QHUB_USER_MAPPING.items():
        uid = config['uid']
        gid = QHUB_GROUP_MAPPING[config['primary_group']]['gid']
        passwd.append(passwd_format.format(username=username, uid=uid, gid=gid))

    group = []
    group_format = '{groupname}:x:{gid}:'
    for groupname, config in QHUB_GROUP_MAPPING.items():
        gid = config['gid']
        group.append(group_format.format(groupname=groupname, gid=gid))

    return '\n'.join(passwd), '\n'.join(group)


def qhub_list_admins(users):
    return [k for k,v in users.items() if v['primary_group'] == 'admin']


def qhub_list_users(users):
    return [k for k,v in users.items() if v['primary_group'] != 'admin']


def qhub_list_user_groups(username):
    user = QHUB_USER_MAPPING[username]
    return set([user['primary_group']] + user.get('secondary_groups', []))


def qhub_configure_profile(username, safe_username, profile):
    user = QHUB_USER_MAPPING[username]
    uid = user['uid']
    primary_gid = QHUB_GROUP_MAPPING[user['primary_group']]['gid']
    secondary_gids = [QHUB_GROUP_MAPPING[_]['gid'] for _ in user.get('secondary_groups', [])]

    profile['kubespawner_override']['environment'] = {
       'LD_PRELOAD': 'libnss_wrapper.so',
       'NSS_WRAPPER_PASSWD': '/tmp/passwd',
       'NSS_WRAPPER_GROUP': '/tmp/group',
       'NB_UMASK': '0002',
       'HOME': '/home/jovyan',
    }

    passwd, group = qhub_generate_nss_files()
    profile['kubespawner_override']['lifecycle_hooks'] = {
        "postStart": {
            "exec": {
                "command": ["/bin/sh", "-c", (
                     "echo '{passwd}' > /tmp/passwd && "
                     "echo '{group}' > /tmp/group && "
                     "ln -sfn /home/shared /home/jovyan/shared"
                ).format(passwd=passwd, group=group)]
            }
        }
    }

    profile['kubespawner_override']['init_containers'] = [
        {
             "name": "init-nfs",
             "image": "busybox:1.31",
             "command": ["sh", "-c", ' && '.join([
                  "mkdir -p /mnt/home/{username}",
                  "chmod 700 /mnt/home/{username}",
                  "chown {uid}:{primary_gid} /mnt/home/{username}",
                  "mkdir -p /mnt/home/shared",
                  "chmod 777 /mnt/home/shared"
             ] + ["mkdir -p /mnt/home/shared/{groupname} && chmod 2770 /mnt/home/shared/{groupname} && chown 0:{gid} /mnt/home/shared/{groupname}".format(groupname=groupname, gid=config['gid']) for groupname, config in QHUB_GROUP_MAPPING.items()]).format(username=safe_username, uid=uid, primary_gid=primary_gid)],
             "securityContext": {"runAsUser": 0},
             "volumeMounts": [{"mountPath": "/mnt", "name": "home"}]
        }
    ]

    profile['kubespawner_override']['uid'] = uid
    profile['kubespawner_override']['gid'] = primary_gid
    profile['kubespawner_override']['supplemental_gids'] = secondary_gids
    profile['kubespawner_override']['fs_gid'] = primary_gid
    return profile

def qhub_list_available_profiles(username):
    import escapism
    import string
    safe_chars = set(string.ascii_lowercase + string.digits)
    safe_username = escapism.escape(username, safe=safe_chars, escape_char='-').lower()

    exclude_keys = {'users', 'groups'}

    groups = qhub_list_user_groups(username)

    available_profiles = []
    for profile in QHUB_PROFILES:
        filtered_profile = qhub_configure_profile(username, safe_username, {k: v for k,v in profile.items() if k not in exclude_keys})

        if 'users' in profile:
            if username in profile['users']:
                available_profiles.append(filtered_profile)
        elif 'groups' in profile:
            if len(groups & set(profile['groups'])) != 0:
                available_profiles.append(filtered_profile)
        else:
            available_profiles.append(filtered_profile)

    return available_profiles


c.JupyterHub.admin_access = True
c.Authenticator.admin_users = qhub_list_admins(QHUB_USER_MAPPING)
c.Authenticator.whitelist = qhub_list_users(QHUB_USER_MAPPING)

async def custom_options_form(self):
     self.profile_list = qhub_list_available_profiles(self.user.name)

     # Let KubeSpawner inspect profile_list and decide what to return
     return self._options_form_default()

c.KubeSpawner.options_form = custom_options_form
c.LocalProcessSpawner.shell_cmd = ['bash', '-l', '-c']

# ==================== AUTHENTICATION ======================
{% if cookiecutter.security.authentication.type == 'password' %}
# =================== PASSWORD BASED =======================
# create passwords via
# >>> bcrypt.hashpw(b'<password>', bcrypt.gensalt())
import bcrypt
from jupyterhub.auth import Authenticator

class QHubPasswordAuthenticator(Authenticator):
    async def authenticate(self, handler, data):
        username, password = data['username'], data['password'].encode('utf-8')
        if username not in QHUB_USER_MAPPING:
            return None

        if 'password' not in QHUB_USER_MAPPING[username]:
            return None

        salted_password = QHUB_USER_MAPPING[username]['password'].encode('utf-8')
        if bcrypt.checkpw(password, salted_password):
            return username
        return None

c.JupyterHub.authenticator_class = QHubPasswordAuthenticator
{% elif cookiecutter.security.authentication.type == 'GitHub' %}
# =================== GITHUB BASED =======================

from oauthenticator.github import GitHubOAuthenticator
c.JupyterHub.authenticator_class = GitHubOAuthenticator
c.GitHubOAuthenticator.client_id = "{{ cookiecutter.security.authentication.config.client_id }}"
c.GitHubOAuthenticator.client_secret = "{{ cookiecutter.security.authentication.config.client_secret }}"
c.GitHubOAuthenticator.oauth_callback_url = "{{ cookiecutter.security.authentication.config.oauth_callback_url }}"

{% elif cookiecutter.security.authentication.type == 'Auth0' %}
# =================== AUTH0 BASED ========================

from oauthenticator.auth0 import Auth0OAuthenticator
c.JupyterHub.authenticator_class = Auth0OAuthenticator
c.Auth0OAuthenticator.client_id = "{{ cookiecutter.security.authentication.config.client_id }}"
c.Auth0OAuthenticator.client_secret = "{{ cookiecutter.security.authentication.config.client_secret }}"
c.Auth0OAuthenticator.oauth_callback_url = "{{ cookiecutter.security.authentication.config.oauth_callback_url }}"
c.Auth0OAuthenticator.scope = {{ cookiecutter.security.authentication.config.scope | jsonify }}
c.Auth0OAuthenticator.auth0_subdomain = "{{ cookiecutter.security.authentication.config.auth0_subdomain }}"
{% elif cookiecutter.security.authentication.type == 'custom'  %}
# =================== CUSTOM AUTHENTICATION BASED ========================

c.JupyterHub.authenticator_class = "{{ cookiecutter.security.authentication.authentication_class }}"
{% for key, value in cookiecutter.security.authentication.config.items() %}
c.{{ cookiecutter.security.authentication.authentication_class.split('.')[-1] }}.{{ key }} = {{ value | pprint }}
{% endfor %}

{% endif %}
