"""
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)

[((768, 837), 'flask.Blueprint', 'Blueprint', (['"""admin_bp"""', '__name__'], {'template_folder': '"""../templates/admin"""'}), "('admin_bp', __name__, template_folder='../templates/admin')\n", (777, 837), False, 'from flask import session, flash, Blueprint\n'), ((1506, 1522), 'liberaforms.models.user.User.find', 'User.find', ([], {'id': 'id'}), '(id=id)\n', (1515, 1522), False, 'from liberaforms.models.user import User\n'), ((1658, 1705), 'flask.render_template', 'render_template', (['"""inspect-user.html"""'], {'user': 'user'}), "('inspect-user.html', user=user)\n", (1673, 1705), False, 'from flask import g, request, render_template, redirect\n'), ((1836, 1852), 'liberaforms.models.user.User.find', 'User.find', ([], {'id': 'id'}), '(id=id)\n', (1845, 1852), False, 'from liberaforms.models.user import User\n'), ((2251, 2267), 'liberaforms.models.user.User.find', 'User.find', ([], {'id': 'id'}), '(id=id)\n', (2260, 2267), False, 'from liberaforms.models.user import User\n'), ((2705, 2721), 'liberaforms.models.user.User.find', 'User.find', ([], {'id': 'id'}), '(id=id)\n', (2714, 2721), False, 'from liberaforms.models.user import User\n'), ((3024, 3040), 'liberaforms.models.user.User.find', 'User.find', ([], {'id': 'id'}), '(id=id)\n', (3033, 3040), False, 'from liberaforms.models.user import User\n'), ((3936, 3982), 'flask.render_template', 'render_template', (['"""delete-user.html"""'], {'user': 'user'}), "('delete-user.html', user=user)\n", (3951, 3982), False, 'from flask import g, request, render_template, redirect\n'), ((4086, 4110), 'flask.g.site.write_users_csv', 'g.site.write_users_csv', ([], {}), '()\n', (4108, 4110), False, 'from flask import g, request, render_template, redirect\n'), ((4229, 4289), 'flask.send_file', 'send_file', (['csv_file'], {'mimetype': '"""text/csv"""', 'as_attachment': '(True)'}), "(csv_file, mimetype='text/csv', as_attachment=True)\n", (4238, 4289), False, 'from flask import send_file, after_this_request\n'), ((4617, 4633), 'liberaforms.models.form.Form.find', 'Form.find', ([], {'id': 'id'}), '(id=id)\n', (4626, 4633), False, 'from liberaforms.models.form import Form\n'), ((5176, 5191), 'liberaforms.utils.wtf.NewInvite', 'wtf.NewInvite', ([], {}), '()\n', (5189, 5191), False, 'from liberaforms.utils import wtf\n'), ((5915, 5939), 'liberaforms.models.invite.Invite.default_message', 'Invite.default_message', ([], {}), '()\n', (5937, 5939), False, 'from liberaforms.models.invite import Invite\n'), ((6217, 6235), 'liberaforms.models.invite.Invite.find', 'Invite.find', ([], {'id': 'id'}), '(id=id)\n', (6228, 6235), False, 'from liberaforms.models.invite import Invite\n'), ((7171, 7192), 'liberaforms.models.form.Form.find', 'Form.find', ([], {'id': 'form_id'}), '(id=form_id)\n', (7180, 7192), False, 'from liberaforms.models.form import Form\n'), ((8852, 8907), 'flask.render_template', 'render_template', (['"""change-author.html"""'], {'form': 'queriedForm'}), "('change-author.html', form=queriedForm)\n", (8867, 8907), False, 'from flask import g, request, render_template, redirect\n'), ((2097, 2129), 'json.dumps', 'json.dumps', (["{'blocked': blocked}"], {}), "({'blocked': blocked})\n", (2107, 2129), False, 'import os, json\n'), ((2533, 2564), 'json.dumps', 'json.dumps', (["{'admin': is_admin}"], {}), "({'admin': is_admin})\n", (2543, 2564), False, 'import os, json\n'), ((2855, 2903), 'json.dumps', 'json.dumps', (["{'uploads_enabled': uploads_enabled}"], {}), "({'uploads_enabled': uploads_enabled})\n", (2865, 2903), False, 'import os, json\n'), ((4174, 4193), 'os.remove', 'os.remove', (['csv_file'], {}), '(csv_file)\n', (4183, 4193), False, 'import os, json\n'), ((4831, 4879), 'liberaforms.utils.utils.make_url_for', 'make_url_for', (['"""form_bp.inspect_form"""'], {'form_id': 'id'}), "('form_bp.inspect_form', form_id=id)\n", (4843, 4879), False, 'from liberaforms.utils.utils import make_url_for, JsonResponse\n'), ((5280, 5306), 'liberaforms.utils.utils.create_token', 'utils.create_token', (['Invite'], {}), '(Invite)\n', (5298, 5306), False, 'from liberaforms.utils import utils\n'), ((5349, 5440), 'liberaforms.models.invite.Invite', 'Invite', ([], {'email': 'wtform.email.data', 'message': 'message', 'token': 'token', 'admin': 'wtform.admin.data'}), '(email=wtform.email.data, message=message, token=token, admin=wtform.\n    admin.data)\n', (5355, 5440), False, 'from liberaforms.models.invite import Invite\n'), ((6502, 6539), 'liberaforms.utils.utils.make_url_for', 'make_url_for', (['"""admin_bp.list_invites"""'], {}), "('admin_bp.list_invites')\n", (6514, 6539), False, 'from liberaforms.utils.utils import make_url_for, JsonResponse\n'), ((1073, 1096), 'liberaforms.utils.utils.get_app_version', 'utils.get_app_version', ([], {}), '()\n', (1094, 1096), False, 'from liberaforms.utils import utils\n'), ((1328, 1343), 'liberaforms.models.user.User.find_all', 'User.find_all', ([], {}), '()\n', (1341, 1343), False, 'from liberaforms.models.user import User\n'), ((1381, 1398), 'liberaforms.models.invite.Invite.find_all', 'Invite.find_all', ([], {}), '()\n', (1396, 1398), False, 'from liberaforms.models.invite import Invite\n'), ((1554, 1573), 'flask_babel.gettext', '_', (['"""User not found"""'], {}), "('User not found')\n", (1555, 1573), True, 'from flask_babel import gettext as _\n'), ((1610, 1645), 'liberaforms.utils.utils.make_url_for', 'make_url_for', (['"""admin_bp.list_users"""'], {}), "('admin_bp.list_users')\n", (1622, 1645), False, 'from liberaforms.utils.utils import make_url_for, JsonResponse\n'), ((1898, 1910), 'json.dumps', 'json.dumps', ([], {}), '()\n', (1908, 1910), False, 'import os, json\n'), ((2313, 2325), 'json.dumps', 'json.dumps', ([], {}), '()\n', (2323, 2325), False, 'import os, json\n'), ((2767, 2779), 'json.dumps', 'json.dumps', ([], {}), '()\n', (2777, 2779), False, 'import os, json\n'), ((3072, 3091), 'flask_babel.gettext', '_', (['"""User not found"""'], {}), "('User not found')\n", (3073, 3091), True, 'from flask_babel import gettext as _\n'), ((3128, 3163), 'liberaforms.utils.utils.make_url_for', 'make_url_for', (['"""admin_bp.list_users"""'], {}), "('admin_bp.list_users')\n", (3140, 3163), False, 'from liberaforms.utils.utils import make_url_for, JsonResponse\n'), ((4452, 4467), 'liberaforms.models.form.Form.find_all', 'Form.find_all', ([], {}), '()\n', (4465, 4467), False, 'from liberaforms.models.form import Form\n'), ((4672, 4697), 'flask_babel.gettext', '_', (['"""Can\'t find that form"""'], {}), '("Can\'t find that form")\n', (4673, 4697), True, 'from flask_babel import gettext as _\n'), ((4734, 4766), 'liberaforms.utils.utils.make_url_for', 'make_url_for', (['"""form_bp.my_forms"""'], {}), "('form_bp.my_forms')\n", (4746, 4766), False, 'from liberaforms.utils.utils import make_url_for, JsonResponse\n'), ((5047, 5064), 'liberaforms.models.invite.Invite.find_all', 'Invite.find_all', ([], {}), '()\n', (5062, 5064), False, 'from liberaforms.models.invite import Invite\n'), ((5672, 5728), 'flask_babel.gettext', '_', (["('We have sent an invitation to %s' % new_invite.email)"], {}), "('We have sent an invitation to %s' % new_invite.email)\n", (5673, 5728), True, 'from flask_babel import gettext as _\n'), ((5741, 5769), 'flask.flash', 'flash', (['flash_text', '"""success"""'], {}), "(flash_text, 'success')\n", (5746, 5769), False, 'from flask import session, flash, Blueprint\n'), ((5796, 5827), 'flask.flash', 'flash', (["status['msg']", '"""warning"""'], {}), "(status['msg'], 'warning')\n", (5801, 5827), False, 'from flask import session, flash, Blueprint\n'), ((5852, 5889), 'liberaforms.utils.utils.make_url_for', 'make_url_for', (['"""admin_bp.list_invites"""'], {}), "('admin_bp.list_invites')\n", (5864, 5889), False, 'from liberaforms.utils.utils import make_url_for, JsonResponse\n'), ((6347, 6394), 'flask_babel.gettext', '_', (["('Invitation to %s deleted OK' % invite.email)"], {}), "('Invitation to %s deleted OK' % invite.email)\n", (6348, 6394), True, 'from flask_babel import gettext as _\n'), ((6431, 6471), 'flask_babel.gettext', '_', (['"""Opps! We can\'t find that invitation"""'], {}), '("Opps! We can\'t find that invitation")\n', (6432, 6471), True, 'from flask_babel import gettext as _\n'), ((6735, 6780), 'flask.g.current_user.toggle_new_user_notification', 'g.current_user.toggle_new_user_notification', ([], {}), '()\n', (6778, 6780), False, 'from flask import g, request, render_template, redirect\n'), ((6941, 6986), 'flask.g.current_user.toggle_new_form_notification', 'g.current_user.toggle_new_form_notification', ([], {}), '()\n', (6984, 6986), False, 'from flask import g, request, render_template, redirect\n'), ((7231, 7256), 'flask_babel.gettext', '_', (['"""Can\'t find that form"""'], {}), '("Can\'t find that form")\n', (7232, 7256), True, 'from flask_babel import gettext as _\n'), ((7293, 7325), 'liberaforms.utils.utils.make_url_for', 'make_url_for', (['"""user_bp.my_forms"""'], {}), "('user_bp.my_forms')\n", (7305, 7325), False, 'from liberaforms.utils.utils import make_url_for, JsonResponse\n'), ((7606, 7661), 'flask.render_template', 'render_template', (['"""change-author.html"""'], {'form': 'queriedForm'}), "('change-author.html', form=queriedForm)\n", (7621, 7661), False, 'from flask import g, request, render_template, redirect\n'), ((7735, 7790), 'liberaforms.models.user.User.find', 'User.find', ([], {'username': "request.form['new_author_username']"}), "(username=request.form['new_author_username'])\n", (7744, 7790), False, 'from liberaforms.models.user import User\n'), ((3280, 3308), 'flask_babel.gettext', '_', (['"""Cannot delete root user"""'], {}), "('Cannot delete root user')\n", (3281, 3308), True, 'from flask_babel import gettext as _\n'), ((3349, 3398), 'liberaforms.utils.utils.make_url_for', 'make_url_for', (['"""admin_bp.inspect_user"""'], {'id': 'user.id'}), "('admin_bp.inspect_user', id=user.id)\n", (3361, 3398), False, 'from liberaforms.utils.utils import make_url_for, JsonResponse\n'), ((3459, 3486), 'flask_babel.gettext', '_', (['"""Cannot delete yourself"""'], {}), "('Cannot delete yourself')\n", (3460, 3486), True, 'from flask_babel import gettext as _\n'), ((3527, 3588), 'liberaforms.utils.utils.make_url_for', 'make_url_for', (['"""admin_bp.inspect_user"""'], {'username': 'user.username'}), "('admin_bp.inspect_user', username=user.username)\n", (3539, 3588), False, 'from liberaforms.utils.utils import make_url_for, JsonResponse\n'), ((3734, 3772), 'flask_babel.gettext', '_', (['("Deleted user \'%s\'" % user.username)'], {}), '("Deleted user \'%s\'" % user.username)\n', (3735, 3772), True, 'from flask_babel import gettext as _\n'), ((3815, 3850), 'liberaforms.utils.utils.make_url_for', 'make_url_for', (['"""admin_bp.list_users"""'], {}), "('admin_bp.list_users')\n", (3827, 3850), False, 'from liberaforms.utils.utils import make_url_for, JsonResponse\n'), ((3884, 3912), 'flask_babel.gettext', '_', (['"""Username does not match"""'], {}), "('Username does not match')\n", (3885, 3912), True, 'from flask_babel import gettext as _\n'), ((5565, 5577), 'liberaforms.utils.dispatcher.Dispatcher', 'Dispatcher', ([], {}), '()\n', (5575, 5577), False, 'from liberaforms.utils.dispatcher import Dispatcher\n'), ((7545, 7574), 'flask_babel.gettext', '_', (['"""Current author incorrect"""'], {}), "('Current author incorrect')\n", (7546, 7574), True, 'from flask_babel import gettext as _\n'), ((6071, 6088), 'liberaforms.models.invite.Invite.find_all', 'Invite.find_all', ([], {}), '()\n', (6086, 6088), False, 'from liberaforms.models.invite import Invite\n'), ((8706, 8771), 'flask_babel.gettext', '_', (['("Can\'t find username %s" % request.form[\'new_author_username\'])'], {}), '("Can\'t find username %s" % request.form[\'new_author_username\'])\n', (8707, 8771), True, 'from flask_babel import gettext as _\n'), ((7992, 8070), 'flask_babel.gettext', '_', (["('Changed author from %s to %s' % (old_author.username, new_author.username))"], {}), "('Changed author from %s to %s' % (old_author.username, new_author.username))\n", (7993, 8070), True, 'from flask_babel import gettext as _\n'), ((8506, 8592), 'flask_babel.gettext', '_', (["('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'])\n", (8507, 8592), True, 'from flask_babel import gettext as _\n'), ((8268, 8290), 'flask_babel.gettext', '_', (['"""Changed author OK"""'], {}), "('Changed author OK')\n", (8269, 8290), True, 'from flask_babel import gettext as _\n'), ((8343, 8403), 'liberaforms.utils.utils.make_url_for', 'make_url_for', (['"""form_bp.inspect_form"""'], {'form_id': 'queriedForm.id'}), "('form_bp.inspect_form', form_id=queriedForm.id)\n", (8355, 8403), False, 'from liberaforms.utils.utils import make_url_for, JsonResponse\n')]