/////
///// This file is part of Mail-in-a-Box-LDAP which is released under the
///// terms of the GNU Affero General Public License as published by the
///// Free Software Foundation, either version 3 of the License, or (at
///// your option) any later version. See file LICENSE or go to
///// https://github.com/downtownallday/mailinabox-ldap for full license
///// details.
/////

import { AuthenticationError } from './exceptions.js';


export class Me {
    /* 
     * construct with return value from GET /admin/login or undefined
     * if already logged in
     */
    constructor(me) {
        if (me) {
            Object.assign(this, me);
        }
        else {
            var cred = Me.get_api_credentials();
            if (cred) {
                this.user_id = cred.username;
                this.user_email = cred.username;
                this.session_key = cred.session_key;
            }
        }
    }

    is_authenticated() {
        return true && this.user_id;
    }

    get_email() {
        return this.user_email;
    }

    get_user_id() {
        return this.user_id;
    }

    get_authorization() {
        if (! this.user_id || ! this.session_key) return null;
        return 'Basic ' + window.btoa(this.user_id + ':' + this.session_key);
    }

    /*
     * get api credentials from session storage
     *
     * returns: {
     *    username: String,
     *    session_key: String
     * }
     *
     * or null, if no credentials are in session storage
     */
    static get_api_credentials() {
        var cred = null;
        // code is from templates/index.html for "recall saved user
        // credentials"
        if (typeof sessionStorage != 'undefined' && sessionStorage.getItem("miab-cp-credentials"))
            cred = JSON.parse(sessionStorage.getItem("miab-cp-credentials"));
        else if (typeof localStorage != 'undefined' && localStorage.getItem("miab-cp-credentials"))
            cred = JSON.parse(localStorage.getItem("miab-cp-credentials"));
        return cred;
    }
};


/*
 * axios interceptors for authentication
 */

export function init_authentication_interceptors() {

    // requests: attach non-session based auth (admin panel)
    axios.interceptors.request.use(request => {
        var me = new Me();
        var auth = me.get_authorization();
        if (auth && request.headers.authorization === undefined) {
            request.headers.authorization = auth;
        }
        // prevent daemon.py's @authorized_personnel_only from sending
        // 401 responses, which cause the browser to pop up a
        // credentials dialog box
        request.headers['X-Requested-With'] = 'XMLHttpRequest';
        return request;
    });


    // reponses: handle authorization failures by throwing exceptions
    // users should catch AuthenticationError exceptions
    axios.interceptors.response.use(
        response => {
            if (response.data &&
                response.data.status === 'invalid' &&
                response.config.headers.authorization)
            {
                var url = response.config.url;
                if (response.config.baseURL) {
                    var sep = ( response.config.baseURL.substr(-1) != '/' ?
                                '/' : '' );
                    url = response.config.baseURL + sep + url;
                }
            
                if (url == '/admin/login')
                {
                    // non-flask-session/admin login, which always
                    // returns 200, even for failed logins
                    throw new AuthenticationError(
                        null,
                        'not authenticated',
                        response
                    );
                }
            }
            return response;
        },
        
        error => {
            const auth_required_msg = 'Authentication required - you have been logged out of the server';
            if (! error.response) {
                throw error;
            }
            
            if (error.response.status == 403 &&
                error.response.data == 'login_required')
            {
                // flask session login
                throw new AuthenticationError(error, auth_required_msg);
            }
            else if ((error.response.status == 403 ||
                      error.response.status == 401) &&
                     error.response.data &&
                     error.response.data.status == 'error')
            {
                // admin
                throw new AuthenticationError(error, auth_required_msg);
            }
            throw error;
        }
    );
}