Skip to content

Commit

Permalink
[AdminTL#79] Doc Generator: Add editor admin page
Browse files Browse the repository at this point in the history
- Add button to share document with writting permission to actual user
- Add verification when connect to remote document, to keep the connection
  • Loading branch information
mathben committed Apr 2, 2018
1 parent 5f0dc76 commit 67bcc66
Show file tree
Hide file tree
Showing 10 changed files with 210 additions and 8 deletions.
4 changes: 4 additions & 0 deletions src/web/base_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ class BaseHandler(tornado.web.RequestHandler):
_db = None
_invalid_login = None
_redirect_http_to_https = None
_config = None
_doc_generator_google_drive_spreadsheet = None
_global_arg = {}

def initialize(self, **kwargs):
Expand All @@ -23,6 +25,8 @@ def initialize(self, **kwargs):
self._invalid_login = self.get_argument("invalid",
default="disable_login" if kwargs.get("disable_login") else None)
self._redirect_http_to_https = kwargs.get("redirect_http_to_https")
self._config = kwargs.get("config")
self._doc_generator_google_drive_spreadsheet = kwargs.get("doc_generator_google_drive_spreadsheet")

self._global_arg = {
"debug": self._debug,
Expand Down
69 changes: 69 additions & 0 deletions src/web/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,25 @@ def get(self):
raise tornado.web.Finish()


class AdminEditorHandler(base_handler.BaseHandler):
@tornado.web.asynchronous
@tornado.web.authenticated
def get(self):
if self._global_arg["disable_admin"]:
# Not Found
self.set_status(404)
self.send_error(404)
raise tornado.web.Finish()
if self.is_permission_admin():
self.render('admin/editor.html', **self._global_arg)
else:
print("Insufficient permissions from %s" % self.request.remote_ip, file=sys.stderr)
# Forbidden
self.set_status(403)
self.send_error(403)
raise tornado.web.Finish()


class ProfileHandler(base_handler.BaseHandler):
@tornado.web.asynchronous
@tornado.web.authenticated
Expand Down Expand Up @@ -686,6 +705,56 @@ def get(self):
self.finish()


class EditorCmdInfoHandler(jsonhandler.JsonHandler):
@tornado.web.asynchronous
@tornado.web.authenticated
def get(self):
if not self.is_permission_admin():
print("Insufficient permissions from %s" % self.request.remote_ip, file=sys.stderr)
# Forbidden
self.set_status(403)
self.send_error(403)
raise tornado.web.Finish()

current_user = self.get_current_user()

self._doc_generator_google_drive_spreadsheet.connect()
has_writer_perm = self._doc_generator_google_drive_spreadsheet.has_user_write_permission(
current_user.get("email"))

info = {
"sh_config": self._config.get("manual_google_spreadsheet"),
"sh_has_writer_perm": has_writer_perm
}

self.write(info)
self.finish()


class EditorCmdAddShShareHandler(jsonhandler.JsonHandler):
@tornado.web.asynchronous
@tornado.web.authenticated
def post(self):
if not self.is_permission_admin():
print("Insufficient permissions from %s" % self.request.remote_ip, file=sys.stderr)
# Forbidden
self.set_status(403)
self.send_error(403)
raise tornado.web.Finish()

current_user = self.get_current_user()
self._doc_generator_google_drive_spreadsheet.connect()
status = self._doc_generator_google_drive_spreadsheet.share_document(current_user.get("email"))

if status:
data = {"status": "Document shared."}
else:
data = {"error": "Cannot share the document."}

self.write(data)
self.finish()


class StatSeasonPass(jsonhandler.JsonHandler):
@tornado.web.asynchronous
def get(self):
Expand Down
1 change: 1 addition & 0 deletions src/web/partials/_base.html
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ <h1 class="detect_javascript_enable">
<script src="{{ static_url('resources/js/tl_module/manual_ctrl/manual_ctrl.js') }}"></script>
<script src="{{ static_url('resources/js/tl_module/lore_ctrl/lore_ctrl.js') }}"></script>
<script src="{{ static_url('resources/js/tl_module/profile_ctrl/profile_ctrl.js') }}"></script>
<script src="{{ static_url('resources/js/tl_module/editor_ctrl/editor_ctrl.js') }}"></script>

<script src="{{ static_url('bower_components/qrcode-generator/js/qrcode.js') }}"></script>
<script src="{{ static_url('bower_components/qrcode-generator/js/qrcode_UTF8.js') }}"></script>
Expand Down
5 changes: 4 additions & 1 deletion src/web/partials/admin/_base.html
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
{% if not disable_character %}
<li ng-class="{ active: isActive('/admin/character') }"><a href="/admin/character"><span class="glyphicon glyphicon-knight"></span> Personnage</a></li>
{% end %}
<li ng-class="{ active: isActive('/admin/editor') }"><a href="/admin/editor"><span class="glyphicon glyphicon-edit"></span> Éditeur</a></li>

{% if not disable_custom_css %}
<li class="dropdown">
Expand All @@ -77,7 +78,7 @@
</li>
{% end %}

<li ng-class="{ active: isActive('/') }"><a href="/" style="color:red;"><span class="glyphicon glyphicon-remove-circle"></span> Quitter</a></li>
<li><a href="/" style="color:red;"><span class="glyphicon glyphicon-remove-circle"></span> Quitter</a></li>

{% if not disable_login %}
{% if current_user %}
Expand Down Expand Up @@ -178,6 +179,8 @@ <h1 class="detect_javascript_enable">
<script src="{{ static_url('resources/js/tl_module/page_ctrl/page_ctrl.js') }}"></script>
<script src="{{ static_url('resources/js/tl_module/manual_ctrl/manual_ctrl.js') }}"></script>
<script src="{{ static_url('resources/js/tl_module/lore_ctrl/lore_ctrl.js') }}"></script>
<script src="{{ static_url('resources/js/tl_module/profile_ctrl/profile_ctrl.js') }}"></script>
<script src="{{ static_url('resources/js/tl_module/editor_ctrl/editor_ctrl.js') }}"></script>

<script src="{{ static_url('bower_components/qrcode-generator/js/qrcode.js') }}"></script>
<script src="{{ static_url('bower_components/qrcode-generator/js/qrcode_UTF8.js') }}"></script>
Expand Down
26 changes: 26 additions & 0 deletions src/web/partials/admin/editor.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{% extends "_base.html" %}

{% block content %}

<div ng-controller="editor_ctrl" ng-cloak>
<h1>Gestionnaire de documentation</h1>
<div ng-show="model_editor.is_ctrl_ready">
<h2>Générateur de documentation à partir de Google Drive Spreadsheet</h2>
Cet outil permet d'ouvrir un fichier sur Google Drive Spreadsheet, d'itérer dans le document pour extraire les données, valider le formatage du document et générer la base de donnée du manuel du
joueur. <br/>
<div ng-show="model_editor.info.sh_config && model_editor.info.sh_config.file_key">
Identifiant du document : {{! model_editor.info.sh_config.file_key }}
</div>
<div ng-show="model_editor.info.sh_config && model_editor.info.sh_config.file_name">
Nom du document : {{! model_editor.info.sh_config.file_name }}
</div>
<div ng-show="model_editor.info.sh_config && model_editor.info.sh_config.file_url">
Lien du document : <a href="{{! model_editor.info.sh_config.file_url }}" style="text-decoration: underline">{{! model_editor.info.sh_config.file_url }}</a>
</div>
<div ng-show="!model_editor.info.sh_has_writer_perm">
Vous n'avez pas les permissions d'écriture. <a ng-click="send_writing_sh_permission()" class="btn btn-lg btn-danger" role="button">Recevoir les permissions d'écriture par courriel.</a>
</div>
</div>
</div>

{% end %}
4 changes: 2 additions & 2 deletions src/web/partials/admin/news.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{% extends "_base.html" %}

{% block content %}

Section Admin
<h1>Accueil des administrateurs de Traître-Lame.</h1>
Il n'y a pas de nouvelle à publier.

{% end %}
60 changes: 55 additions & 5 deletions src/web/py_class/doc_generator_google_drive_spreadsheet.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class DocGeneratorGoogleDriveSpreadsheet(object):

def __init__(self, parser):
self._parser = parser
self._is_open = False

# Internal variable
self._use_file_url = False
Expand All @@ -22,14 +23,17 @@ def __init__(self, parser):
self._google_file = None

# Try to open the remote file
self.connect()
self.generate_manual()
self.disconnect()
# self.connect()
# self.generate_manual()
# self.disconnect()

def connect(self):
def connect(self, stop_if_open=True):
"""
Connect to the remote file.
:return: status of success connection."""
if stop_if_open and self._is_open:
return False

# Only connect a document is in config file
file_info_way = self._fetch_config()

Expand Down Expand Up @@ -57,11 +61,57 @@ def connect(self):

if status:
self._file_info_way = file_info_way
self._is_open = True

return status

def disconnect(self):
pass
"""Disconnect the remote file."""
self._is_open = False

def get_permission_document(self):
"""
Get permission of all user.
:return: Formatted list of user with permission
"""
if not self._google_file:
return False

all_info = self._google_file.list_permissions()
lst_info = []
for perm in all_info:
info = {"name": perm.get('name'), "email": perm.get("emailAddress"), "role": perm.get("role"),
"type": perm.get("type")}
lst_info.append(info)
return lst_info

def has_user_write_permission(self, email):
"""
Check if the user from email has writing permission on the document.
:param email: email in string
:return: success or fail
"""
if not self._google_file:
return False

lst_permission = self._google_file.list_permissions()
for perm in lst_permission:
if perm.get("emailAddress") == email and perm.get("role") in ["owner", "writer"]:
return True
return False

def share_document(self, email):
"""
Share a document and send email for invitation.
:param email: email of user.
:return: succeed or failed
"""
if not self._google_file:
return False

msg = self._parser.config.get("msg_email_share_document")
self._google_file.share(email, "user", "writer", notify=True, email_message=msg)
return True

def generate_manual(self):
"""
Expand Down
39 changes: 39 additions & 0 deletions src/web/resources/js/tl_module/editor_ctrl/editor_ctrl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Formulaire de Traitre-Lame
"use strict";

characterApp.controller("editor_ctrl", ["$scope", "$q", "$http", "$window", /*"$timeout",*/ function ($scope, $q, $http, $window) {
$scope.model_editor = {
is_ctrl_ready: false,
info: {}
};

// Get editor info
$scope.update_editor = function (e) {
$http({
method: "get",
url: "/cmd/editor/get_info",
headers: {"Content-Type": "application/json; charset=UTF-8"},
timeout: 5000
}).then(function (response/*, status, headers, config*/) {
$scope.model_editor.info = response.data;
$scope.model_editor.is_ctrl_ready = true;
});

};
$scope.update_editor();

// Send request to receive writer permission
$scope.send_writing_sh_permission = function (e) {
$http({
method: "post",
url: "/cmd/editor/add_sh_share",
headers: {"Content-Type": "application/json; charset=UTF-8"},
timeout: 5000
}).then(function (response/*, status, headers, config*/) {
$scope.model_editor.info.sh_has_writer_perm = true;
}, function errorCallback(response) {
console.error(response);
});
}

}]);
4 changes: 4 additions & 0 deletions src/web/resources/js/tool.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,7 @@ function hashSha256(secret, salt) {
shaObj.update(secret);
return shaObj.getHash('HEX');
}

function isObjEmpty(obj) {
return Object.keys(obj).length === 0;
}
6 changes: 6 additions & 0 deletions src/web/web.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ def main(parse_arg):
"disable_user_character": parse_arg.disable_user_character,
"disable_admin": parse_arg.disable_admin,
"disable_login": parse_arg.disable_login,
"config": parse_arg.config,
"hide_menu_login": parse_arg.hide_menu_login,
"disable_custom_css": parse_arg.disable_custom_css,
"url": url,
Expand Down Expand Up @@ -112,6 +113,7 @@ def main(parse_arg):
tornado.web.url(r"/logout/?", handlers.LogoutHandler, name='logout', kwargs=settings),
tornado.web.url(r"/admin/?", handlers.AdminHandler, name='admin', kwargs=settings),
tornado.web.url(r"/admin/character?", handlers.AdminCharacterHandler, name='admin character', kwargs=settings),
tornado.web.url(r"/admin/editor?", handlers.AdminEditorHandler, name='admin editor', kwargs=settings),
tornado.web.url(r"/profile/?(?P<user_id>[^\/]+)?/?", handlers.ProfileHandler, name='profile', kwargs=settings),
tornado.web.url(r"/character/?", handlers.CharacterHandler, name='character', kwargs=settings),
tornado.web.url(r"/manual/?", handlers.ManualPageHandler, name='manual', kwargs=settings),
Expand All @@ -130,6 +132,10 @@ def main(parse_arg):
name='cmd_profile_add_new_password', kwargs=settings),
tornado.web.url(r"/cmd/profile/get_info/?", handlers.ProfileCmdInfoHandler,
name='cmd_profile_get_info', kwargs=settings),
tornado.web.url(r"/cmd/editor/get_info/?", handlers.EditorCmdInfoHandler,
name='cmd_editor_get_info', kwargs=settings),
tornado.web.url(r"/cmd/editor/add_sh_share/?", handlers.EditorCmdAddShShareHandler,
name='cmd_editor_add_sh_share', kwargs=settings),

# auto ssl
tornado.web.url(r"/.well-known/acme-challenge.*", handlers.AutoSSLHandler, name="auto_ssl")
Expand Down

0 comments on commit 67bcc66

Please sign in to comment.