This commit is contained in:
redfast00 2018-09-24 20:57:36 +02:00
commit f2ae768f76
No known key found for this signature in database
GPG key ID: 5946E0E34FD0553C
8 changed files with 259 additions and 0 deletions

113
.gitignore vendored Normal file
View file

@ -0,0 +1,113 @@
venv/
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json

1
app/__init__.py Normal file
View file

@ -0,0 +1 @@
from app.app import app

104
app/app.py Normal file
View file

@ -0,0 +1,104 @@
import json
from functools import wraps
from flask import Flask, request, Response, abort
from flask_sqlalchemy import SQLAlchemy
import requests
import config
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = config.DATABASE_URL
# Supress Flask warning
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
response_setting = "ephemeral"
from app import models
def check_regular(username):
'''Check if a user has the permissions of a regular user.'''
return models.User.query.filter_by(username=username, authorized=True).first() is not None
def check_admin(username):
'''Check if a user is an admin'''
return models.User.query.filter_by(username=username, authorized=True, admin=True).first() is not None
def requires_regular(f):
'''Decorator to require a regular user'''
@wraps(f)
def decorated(*args, **kwargs):
username = request.values.get('user_name')
if not username or not check_regular(username):
return abort(401)
return f(username, *args, **kwargs)
return decorated
def requires_admin(f):
'''Decorator to require an admin user'''
@wraps(f)
def decorated(*args, **kwargs):
username = request.values.get('user_name')
if not username or not check_admin(username):
return abort(401)
return f(username, *args, **kwargs)
return decorated
def requires_token(token_name):
'''Decorator to require a correct Mattermost token'''
def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
expected_token = config.tokens[token_name]
token = request.values.get('token')
print(token, expected_token)
if expected_token != token:
return abort(401)
return f(*args, **kwargs)
return decorated_function
return decorator
def mattermost_response(message):
response_dict = {"response_type": response_setting,
"text": message}
return Response(json.dumps(response_dict), mimetype="application/json")
@app.route('/authorize', methods=['POST'])
@requires_token('authorize')
@requires_admin
def authorize(admin_username):
'''Slash-command to authorize a new user or modify an existing user'''
tokens = request.values.get('text').strip().split()
to_authorize = tokens[0]
as_admin = len(tokens) == 2 and tokens[1] == 'admin'
user = models.User.query.filter_by(username=to_authorize).first()
if not user:
user = models.User(to_authorize)
user.authorized = True
user.admin = as_admin
db.session.add(user)
db.session.commit()
return mattermost_response("Succesfully added '{}' as regular user".format(to_authorize))
def slotmachien_request(username, command):
r = requests.post(config.slotmachien_url, data={
'username': username, 'token': config.slotmachien_token, 'text': command})
return r.text
@app.route('/door', methods=['POST'])
@requires_token('door')
@requires_regular
def door(username):
tokens = request.values.get('text').strip().split()
command = tokens[0].lower()
return mattermost_response(slotmachien_request(username, command))

16
app/models.py Normal file
View file

@ -0,0 +1,16 @@
from .app import db
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String, unique=True, nullable=False)
authorized = db.Column(db.Boolean, default=True)
admin = db.Column(db.Boolean, default=False)
def __repr__(self):
return '<User %r>' % self.username
def __init__(self, username, admin=False):
super()
self.username = username
self.admin = admin

7
config.py Normal file
View file

@ -0,0 +1,7 @@
DATABASE_URL = 'sqlite:////tmp/mattermost.db'
tokens = {
'authorize': '123',
'door': '123'
}
slotmachien_url = 'https://kelder.zeus.ugent.be/slotmachien/slack/'
slotmachien_token = '123'

6
requirements.txt Normal file
View file

@ -0,0 +1,6 @@
click==6.7
Flask==1.0.2
itsdangerous==0.24
Jinja2==2.10
MarkupSafe==1.0
Werkzeug==0.14.1

4
run_dev.py Normal file
View file

@ -0,0 +1,4 @@
#!/usr/bin/env python3
from app import app
app.run(debug=True)

8
setup_database.py Normal file
View file

@ -0,0 +1,8 @@
#!/usr/bin/env python3
from app.app import db, models
db.create_all()
db.session.add(models.User('admin', admin=True))
db.session.commit()