"""
This file is part of LiberaForms.

# SPDX-FileCopyrightText: 2020 LiberaForms.org
# SPDX-License-Identifier: AGPL-3.0-or-later
"""

import os, json
from flask import g, request, render_template, redirect
from flask import session, flash, Blueprint
from flask import send_file, after_this_request
from flask_babel import gettext as _

from liberaforms.models.user import User
from liberaforms.models.form import Form
from liberaforms.models.site import Site
from liberaforms.models.invite import Invite
from liberaforms.utils.wraps import *
from liberaforms.utils import utils
from liberaforms.utils.utils import make_url_for, JsonResponse
from liberaforms.utils.dispatcher import Dispatcher
from liberaforms.utils import wtf

from pprint import pprint

admin_bp = Blueprint('admin_bp', __name__,
                    template_folder='../templates/admin')


@admin_bp.route('/admin', methods=['GET'])
@admin_required
def site_admin():
    return render_template('admin-panel.html',
                            user=g.current_user,
                            app_version=utils.get_app_version(),
                            site=g.site)

""" User management """

@admin_bp.route('/admin/users', methods=['GET'])
@admin_required
def list_users():
    return render_template('list-users.html',
                            users=User.find_all(),
                            invites=Invite.find_all())

@admin_bp.route('/admin/users/<int:id>', methods=['GET'])
@admin_required
def inspect_user(id):
    user=User.find(id=id)
    if not user:
        flash(_("User not found"), 'warning')
        return redirect(make_url_for('admin_bp.list_users'))
    return render_template('inspect-user.html', user=user)


@admin_bp.route('/admin/users/toggle-blocked/<int:id>', methods=['POST'])
@admin_required
def toggle_user_blocked(id):
    user=User.find(id=id)
    if not user:
        return JsonResponse(json.dumps())
    if user.id == g.current_user.id:
        # current_user cannot disable themself
        blocked=user.blocked
    else:
        blocked=user.toggle_blocked()
    return JsonResponse(json.dumps({'blocked':blocked}))


@admin_bp.route('/admin/users/toggle-admin/<int:id>', methods=['POST'])
@admin_required
def toggle_admin(id):
    user=User.find(id=id)
    if not user:
        return JsonResponse(json.dumps())
    if user.username == g.current_user.username:
        # current_user cannot remove their own admin permission
        is_admin=True
    else:
        is_admin=user.toggle_admin()
    return JsonResponse(json.dumps({'admin':is_admin}))

@admin_bp.route('/admin/users/toggle-uploads-enabled/<int:id>', methods=['POST'])
@admin_required
def toggle_uploads_enabled(id):
    user=User.find(id=id)
    if not user:
        return JsonResponse(json.dumps())
    uploads_enabled=user.toggle_uploads_enabled()
    return JsonResponse(json.dumps({'uploads_enabled':uploads_enabled}))

@admin_bp.route('/admin/users/delete/<int:id>', methods=['GET', 'POST'])
@admin_required
def delete_user(id):
    user=User.find(id=id)
    if not user:
        flash(_("User not found"), 'warning')
        return redirect(make_url_for('admin_bp.list_users'))

    if request.method == 'POST' and 'username' in request.form:
        if user.is_root_user():
            flash(_("Cannot delete root user"), 'warning')
            return redirect(make_url_for('admin_bp.inspect_user', id=user.id))
        if user.id == g.current_user.id:
            flash(_("Cannot delete yourself"), 'warning')
            return redirect(make_url_for('admin_bp.inspect_user',
                                         username=user.username))
        if user.username == request.form['username']:
            user.delete_user()
            flash(_("Deleted user '%s'" % (user.username)), 'success')
            return redirect(make_url_for('admin_bp.list_users'))
        else:
            flash(_("Username does not match"), 'warning')
    return render_template('delete-user.html', user=user)


@admin_bp.route('/admin/users/csv', methods=['GET'])
@admin_required
def csv_users():
    csv_file = g.site.write_users_csv()
    @after_this_request
    def remove_file(response):
        os.remove(csv_file)
        return response
    return send_file(csv_file, mimetype="text/csv", as_attachment=True)


""" Form management """

@admin_bp.route('/admin/forms', methods=['GET'])
@admin_required
def list_forms():
    return render_template('list-forms.html', forms=Form.find_all())


@admin_bp.route('/admin/forms/toggle-public/<int:id>', methods=['GET'])
@admin_required
def toggle_form_public_admin_prefs(id):
    queriedForm = Form.find(id=id)
    if not queriedForm:
        flash(_("Can't find that form"), 'warning')
        return redirect(make_url_for('form_bp.my_forms'))
    queriedForm.toggle_admin_form_public()
    return redirect(make_url_for('form_bp.inspect_form', form_id=id))


""" Invitations """

@admin_bp.route('/admin/invites', methods=['GET'])
@admin_required
def list_invites():
    return render_template('list-invites.html', invites=Invite.find_all())


@admin_bp.route('/admin/invites/new', methods=['GET', 'POST'])
@admin_required
def new_invite():
    wtform=wtf.NewInvite()
    if wtform.validate_on_submit():
        message=wtform.message.data
        token = utils.create_token(Invite)
        #pprint(token)
        new_invite=Invite(  email=wtform.email.data,
                            message=message,
                            token=token,
                            admin=wtform.admin.data)
        new_invite.save()
        status = Dispatcher().send_invitation(new_invite)
        if status['email_sent'] == True:
            flash_text = _("We have sent an invitation to %s" % new_invite.email)
            flash(flash_text, 'success')
        else:
            flash(status['msg'], 'warning')
        return redirect(make_url_for('admin_bp.list_invites'))
    wtform.message.data=Invite.default_message()
    return render_template('new-invite.html',
                            wtform=wtform,
                            total_invites=Invite.find_all().count())


@admin_bp.route('/admin/invites/delete/<int:id>', methods=['GET'])
@admin_required
def delete_invite(id):
    invite=Invite.find(id=id)
    if invite:
        invite.delete()
        # i18n: Invitation to dave@example.com deleted OK
        flash(_("Invitation to %s deleted OK" % invite.email), 'success')
    else:
        flash(_("Opps! We can't find that invitation"), 'error')
    return redirect(make_url_for('admin_bp.list_invites'))


""" Personal Admin preferences """

@admin_bp.route('/admin/toggle-newuser-notification', methods=['POST'])
@admin_required
def toggle_newUser_notification():
    return json.dumps({'notify': g.current_user.toggle_new_user_notification()})


@admin_bp.route('/admin/toggle-newform-notification', methods=['POST'])
@admin_required
def toggle_newForm_notification():
    return json.dumps({'notify': g.current_user.toggle_new_form_notification()})


""" ROOT_USERS functions
"""

@admin_bp.route('/admin/forms/change-author/<int:form_id>', methods=['GET', 'POST'])
@rootuser_required
def change_author(form_id):
    queriedForm = Form.find(id=form_id)
    if not queriedForm:
        flash(_("Can't find that form"), 'warning')
        return redirect(make_url_for('user_bp.my_forms'))
    if request.method == 'POST':
        author = queriedForm.author
        if not ('old_author_username' in request.form and \
                request.form['old_author_username']==author.username):
            flash(_("Current author incorrect"), 'warning')
            return render_template('change-author.html', form=queriedForm)
        if 'new_author_username' in request.form:
            new_author=User.find(username=request.form['new_author_username'])
            if new_author:
                if new_author.enabled:
                    old_author=author
                    if queriedForm.change_author(new_author):
                        log_text = _("Changed author from %s to %s" % (
                                                        old_author.username,
                                                        new_author.username))
                        queriedForm.add_log(log_text)
                        flash(_("Changed author OK"), 'success')
                        return redirect(make_url_for('form_bp.inspect_form',
                                                     form_id=queriedForm.id))
                else:
                    flash(_("Cannot use %s. The user is not enabled" % (
                                    request.form['new_author_username']),
                         ), 'warning')
            else:
                flash(_("Can't find username %s" % (
                                request.form['new_author_username'])
                     ), 'warning')
    return render_template('change-author.html', form=queriedForm)

[((26, 11, 27, 57), 'flask.Blueprint', 'Blueprint', (), '', False, 'from flask import session, flash, Blueprint\n'), ((50, 9, 50, 25), 'liberaforms.models.user.User.find', 'User.find', (), '', False, 'from liberaforms.models.user import User\n'), ((54, 11, 54, 58), 'flask.render_template', 'render_template', (), '', False, 'from flask import g, request, render_template, redirect\n'), ((60, 9, 60, 25), 'liberaforms.models.user.User.find', 'User.find', (), '', False, 'from liberaforms.models.user import User\n'), ((74, 9, 74, 25), 'liberaforms.models.user.User.find', 'User.find', (), '', False, 'from liberaforms.models.user import User\n'), ((87, 9, 87, 25), 'liberaforms.models.user.User.find', 'User.find', (), '', False, 'from liberaforms.models.user import User\n'), ((96, 9, 96, 25), 'liberaforms.models.user.User.find', 'User.find', (), '', False, 'from liberaforms.models.user import User\n'), ((115, 11, 115, 57), 'flask.render_template', 'render_template', (), '', False, 'from flask import g, request, render_template, redirect\n'), ((121, 15, 121, 39), 'flask.g.site.write_users_csv', 'g.site.write_users_csv', ({}, {}), '()', False, 'from flask import g, request, render_template, redirect\n'), ((126, 11, 126, 71), 'flask.send_file', 'send_file', (), '', False, 'from flask import send_file, after_this_request\n'), ((140, 18, 140, 34), 'liberaforms.models.form.Form.find', 'Form.find', (), '', False, 'from liberaforms.models.form import Form\n'), ((159, 11, 159, 26), 'liberaforms.utils.wtf.NewInvite', 'wtf.NewInvite', ({}, {}), '()', False, 'from liberaforms.utils import wtf\n'), ((176, 24, 176, 48), 'liberaforms.models.invite.Invite.default_message', 'Invite.default_message', ({}, {}), '()', False, 'from liberaforms.models.invite import Invite\n'), ((185, 11, 185, 29), 'liberaforms.models.invite.Invite.find', 'Invite.find', (), '', False, 'from liberaforms.models.invite import Invite\n'), ((215, 18, 215, 39), 'liberaforms.models.form.Form.find', 'Form.find', (), '', False, 'from liberaforms.models.form import Form\n'), ((246, 11, 246, 66), 'flask.render_template', 'render_template', (), '', False, 'from flask import g, request, render_template, redirect\n'), ((68, 24, 68, 55), 'json.dumps', 'json.dumps', ({(68, 35, 68, 54): "{'blocked': blocked}"}, {}), "({'blocked': blocked})", False, 'import os, json\n'), ((82, 24, 82, 54), 'json.dumps', 'json.dumps', ({(82, 35, 82, 53): "{'admin': is_admin}"}, {}), "({'admin': is_admin})", False, 'import os, json\n'), ((91, 24, 91, 71), 'json.dumps', 'json.dumps', ({(91, 35, 91, 70): "{'uploads_enabled': uploads_enabled}"}, {}), "({'uploads_enabled': uploads_enabled})", False, 'import os, json\n'), ((124, 8, 124, 27), 'os.remove', 'os.remove', ({(124, 18, 124, 26): 'csv_file'}, {}), '(csv_file)', False, 'import os, json\n'), ((145, 20, 145, 68), 'liberaforms.utils.utils.make_url_for', 'make_url_for', (), '', False, 'from liberaforms.utils.utils import make_url_for, JsonResponse\n'), ((162, 16, 162, 42), 'liberaforms.utils.utils.create_token', 'utils.create_token', ({(162, 35, 162, 41): 'Invite'}, {}), '(Invite)', False, 'from liberaforms.utils import utils\n'), ((164, 19, 167, 52), 'liberaforms.models.invite.Invite', 'Invite', (), '', False, 'from liberaforms.models.invite import Invite\n'), ((192, 20, 192, 57), 'liberaforms.utils.utils.make_url_for', 'make_url_for', ({(192, 33, 192, 56): '"""admin_bp.list_invites"""'}, {}), "('admin_bp.list_invites')", False, 'from liberaforms.utils.utils import make_url_for, JsonResponse\n'), ((35, 40, 35, 63), 'liberaforms.utils.utils.get_app_version', 'utils.get_app_version', ({}, {}), '()', False, 'from liberaforms.utils import utils\n'), ((44, 34, 44, 49), 'liberaforms.models.user.User.find_all', 'User.find_all', ({}, {}), '()', False, 'from liberaforms.models.user import User\n'), ((45, 36, 45, 53), 'liberaforms.models.invite.Invite.find_all', 'Invite.find_all', ({}, {}), '()', False, 'from liberaforms.models.invite import Invite\n'), ((52, 14, 52, 33), 'flask_babel.gettext', '_', ({(52, 16, 52, 32): '"""User not found"""'}, {}), "('User not found')", True, 'from flask_babel import gettext as _\n'), ((53, 24, 53, 59), 'liberaforms.utils.utils.make_url_for', 'make_url_for', ({(53, 37, 53, 58): '"""admin_bp.list_users"""'}, {}), "('admin_bp.list_users')", False, 'from liberaforms.utils.utils import make_url_for, JsonResponse\n'), ((62, 28, 62, 40), 'json.dumps', 'json.dumps', ({}, {}), '()', False, 'import os, json\n'), ((76, 28, 76, 40), 'json.dumps', 'json.dumps', ({}, {}), '()', False, 'import os, json\n'), ((89, 28, 89, 40), 'json.dumps', 'json.dumps', ({}, {}), '()', False, 'import os, json\n'), ((98, 14, 98, 33), 'flask_babel.gettext', '_', ({(98, 16, 98, 32): '"""User not found"""'}, {}), "('User not found')", True, 'from flask_babel import gettext as _\n'), ((99, 24, 99, 59), 'liberaforms.utils.utils.make_url_for', 'make_url_for', ({(99, 37, 99, 58): '"""admin_bp.list_users"""'}, {}), "('admin_bp.list_users')", False, 'from liberaforms.utils.utils import make_url_for, JsonResponse\n'), ((134, 52, 134, 67), 'liberaforms.models.form.Form.find_all', 'Form.find_all', ({}, {}), '()', False, 'from liberaforms.models.form import Form\n'), ((142, 14, 142, 39), 'flask_babel.gettext', '_', ({(142, 16, 142, 38): '"""Can\'t find that form"""'}, {}), '("Can\'t find that form")', True, 'from flask_babel import gettext as _\n'), ((143, 24, 143, 56), 'liberaforms.utils.utils.make_url_for', 'make_url_for', ({(143, 37, 143, 55): '"""form_bp.my_forms"""'}, {}), "('form_bp.my_forms')", False, 'from liberaforms.utils.utils import make_url_for, JsonResponse\n'), ((153, 56, 153, 73), 'liberaforms.models.invite.Invite.find_all', 'Invite.find_all', ({}, {}), '()', False, 'from liberaforms.models.invite import Invite\n'), ((171, 25, 171, 81), 'flask_babel.gettext', '_', ({(171, 27, 171, 80): "'We have sent an invitation to %s' % new_invite.email"}, {}), "('We have sent an invitation to %s' % new_invite.email)", True, 'from flask_babel import gettext as _\n'), ((172, 12, 172, 40), 'flask.flash', 'flash', ({(172, 18, 172, 28): 'flash_text', (172, 30, 172, 39): '"""success"""'}, {}), "(flash_text, 'success')", False, 'from flask import session, flash, Blueprint\n'), ((174, 12, 174, 43), 'flask.flash', 'flash', ({(174, 18, 174, 31): "status['msg']", (174, 33, 174, 42): '"""warning"""'}, {}), "(status['msg'], 'warning')", False, 'from flask import session, flash, Blueprint\n'), ((175, 24, 175, 61), 'liberaforms.utils.utils.make_url_for', 'make_url_for', ({(175, 37, 175, 60): '"""admin_bp.list_invites"""'}, {}), "('admin_bp.list_invites')", False, 'from liberaforms.utils.utils import make_url_for, JsonResponse\n'), ((189, 14, 189, 61), 'flask_babel.gettext', '_', ({(189, 16, 189, 60): "('Invitation to %s deleted OK' % invite.email)"}, {}), "('Invitation to %s deleted OK' % invite.email)", True, 'from flask_babel import gettext as _\n'), ((191, 14, 191, 54), 'flask_babel.gettext', '_', ({(191, 16, 191, 53): '"""Opps! We can\'t find that invitation"""'}, {}), '("Opps! We can\'t find that invitation")', True, 'from flask_babel import gettext as _\n'), ((200, 33, 200, 78), 'flask.g.current_user.toggle_new_user_notification', 'g.current_user.toggle_new_user_notification', ({}, {}), '()', False, 'from flask import g, request, render_template, redirect\n'), ((206, 33, 206, 78), 'flask.g.current_user.toggle_new_form_notification', 'g.current_user.toggle_new_form_notification', ({}, {}), '()', False, 'from flask import g, request, render_template, redirect\n'), ((217, 14, 217, 39), 'flask_babel.gettext', '_', ({(217, 16, 217, 38): '"""Can\'t find that form"""'}, {}), '("Can\'t find that form")', True, 'from flask_babel import gettext as _\n'), ((218, 24, 218, 56), 'liberaforms.utils.utils.make_url_for', 'make_url_for', ({(218, 37, 218, 55): '"""user_bp.my_forms"""'}, {}), "('user_bp.my_forms')", False, 'from liberaforms.utils.utils import make_url_for, JsonResponse\n'), ((224, 19, 224, 74), 'flask.render_template', 'render_template', (), '', False, 'from flask import g, request, render_template, redirect\n'), ((226, 23, 226, 78), 'liberaforms.models.user.User.find', 'User.find', (), '', False, 'from liberaforms.models.user import User\n'), ((103, 18, 103, 46), 'flask_babel.gettext', '_', ({(103, 20, 103, 45): '"""Cannot delete root user"""'}, {}), "('Cannot delete root user')", True, 'from flask_babel import gettext as _\n'), ((104, 28, 104, 77), 'liberaforms.utils.utils.make_url_for', 'make_url_for', (), '', False, 'from liberaforms.utils.utils import make_url_for, JsonResponse\n'), ((106, 18, 106, 45), 'flask_babel.gettext', '_', ({(106, 20, 106, 44): '"""Cannot delete yourself"""'}, {}), "('Cannot delete yourself')", True, 'from flask_babel import gettext as _\n'), ((107, 28, 108, 64), 'liberaforms.utils.utils.make_url_for', 'make_url_for', (), '', False, 'from liberaforms.utils.utils import make_url_for, JsonResponse\n'), ((111, 18, 111, 58), 'flask_babel.gettext', '_', ({(111, 20, 111, 57): '("Deleted user \'%s\'" % user.username)'}, {}), '("Deleted user \'%s\'" % user.username)', True, 'from flask_babel import gettext as _\n'), ((112, 28, 112, 63), 'liberaforms.utils.utils.make_url_for', 'make_url_for', ({(112, 41, 112, 62): '"""admin_bp.list_users"""'}, {}), "('admin_bp.list_users')", False, 'from liberaforms.utils.utils import make_url_for, JsonResponse\n'), ((114, 18, 114, 46), 'flask_babel.gettext', '_', ({(114, 20, 114, 45): '"""Username does not match"""'}, {}), "('Username does not match')", True, 'from flask_babel import gettext as _\n'), ((169, 17, 169, 29), 'liberaforms.utils.dispatcher.Dispatcher', 'Dispatcher', ({}, {}), '()', False, 'from liberaforms.utils.dispatcher import Dispatcher\n'), ((223, 18, 223, 47), 'flask_babel.gettext', '_', ({(223, 20, 223, 46): '"""Current author incorrect"""'}, {}), "('Current author incorrect')", True, 'from flask_babel import gettext as _\n'), ((179, 42, 179, 59), 'liberaforms.models.invite.Invite.find_all', 'Invite.find_all', ({}, {}), '()', False, 'from liberaforms.models.invite import Invite\n'), ((243, 22, 245, 22), 'flask_babel.gettext', '_', ({(243, 24, 244, 68): '("Can\'t find username %s" % request.form[\'new_author_username\'])'}, {}), '("Can\'t find username %s" % request.form[\'new_author_username\'])', True, 'from flask_babel import gettext as _\n'), ((231, 35, 233, 77), 'flask_babel.gettext', '_', ({(231, 37, 233, 76): "'Changed author from %s to %s' % (old_author.username, new_author.username)"}, {}), "('Changed author from %s to %s' % (old_author.username, new_author.username))", True, 'from flask_babel import gettext as _\n'), ((239, 26, 241, 26), 'flask_babel.gettext', '_', ({(239, 28, 240, 72): "('Cannot use %s. The user is not enabled' % request.form['new_author_username']\n    )"}, {}), "('Cannot use %s. The user is not enabled' % request.form[\n    'new_author_username'])", True, 'from flask_babel import gettext as _\n'), ((235, 30, 235, 52), 'flask_babel.gettext', '_', ({(235, 32, 235, 51): '"""Changed author OK"""'}, {}), "('Changed author OK')", True, 'from flask_babel import gettext as _\n'), ((236, 40, 237, 76), 'liberaforms.utils.utils.make_url_for', 'make_url_for', (), '', False, 'from liberaforms.utils.utils import make_url_for, JsonResponse\n')]