summaryrefslogtreecommitdiffstats
path: root/app.py
diff options
context:
space:
mode:
Diffstat (limited to 'app.py')
-rw-r--r--app.py172
1 files changed, 172 insertions, 0 deletions
diff --git a/app.py b/app.py
new file mode 100644
index 0000000..decd9df
--- /dev/null
+++ b/app.py
@@ -0,0 +1,172 @@
+import shutil
+from pathlib import Path
+
+import flask
+import markdown
+from flask_caching import Cache
+from flask_htpasswd import HtPasswdAuth
+from flask_restful import reqparse, Api, Resource
+
+from config import Config
+
+app = flask.Flask(__name__)
+api = Api(app)
+
+# app config
+if app.config["ENV"] == "development":
+ app.config.from_object("config.DevelopConfig")
+else:
+ app.config.from_object(Config)
+
+cache = Cache(app)
+htpasswd = HtPasswdAuth(app)
+htpasswd.users.autosave = True
+parser = reqparse.RequestParser()
+
+messages = {
+ 'OK': {
+ 'status': 200,
+ 'message': 'OK'
+ },
+ 'Created': {
+ 'status': 201,
+ 'message': "User creation succeeded"
+ },
+ 'Unauthorized Request': {
+ 'status': 401,
+ 'message': 'Unauthorized Request',
+ },
+ 'Unprocessable Entity':{
+ 'status': 422,
+ 'message': 'Missing parameter'
+ },
+ 'Conflict': {
+ 'status': 409,
+ 'message': 'Username conflict'
+ },
+ 'InternalServerError': {
+ 'status': 500,
+ 'message': 'Something went wrong, please contact the administrator.'
+ }
+}
+
+
+@app.route('/joplin/')
+@cache.cached(timeout=21600)
+def index():
+ # codehilite css
+ with open(Path(app.root_path).joinpath('./static/hilite.css'), 'r') as hilite_file:
+ css = '<style>{css}</style>'.format(css=hilite_file.read())
+
+ # Open the README file
+ with open(Path(app.root_path).joinpath('./static/Readme.md'), 'r') as markdown_file:
+
+ # Read the content of the file
+ content = markdown_file.read()
+
+ html = ''.join([css, content])
+
+ # render finished HTML
+ return flask.Response(markdown.markdown(html, extensions=["fenced_code", "codehilite"]), status=200)
+
+
+@app.route('/joplin/auth-test')
+@htpasswd.required
+def auth_test(user):
+ return 'Hello {user}'.format(user=user)
+
+
+class NewUser(Resource):
+ """
+ class to create new htpasswd user entry
+ """
+ def post(self, username):
+ parser.add_argument('password')
+ parser.add_argument('invite')
+
+ args = parser.parse_args()
+ password = args['password']
+ invitecode = args['invite']
+ path = app.config['JOPLIN_DIR']
+
+ # break early
+ if invitecode != app.config['INVITE_CODE']:
+ return flask.jsonify(messages['Unauthorized Request'])
+
+ if None in [password, invitecode]:
+ return flask.jsonify(messages['Unprocessable Entity'])
+
+ if username not in htpasswd.users.users():
+ # firstly try to create the folder to break if permissions aren't correct
+ try:
+ Path.mkdir(Path(path).joinpath('./%s' % username), mode=0o750, exist_ok=True)
+
+ except OSError:
+ return flask.jsonify(messages['InternalServerError'])
+ # create user entry
+ htpasswd.users.set_password(username, password)
+
+ return flask.jsonify(messages['Created'])
+ else:
+ return flask.jsonify(messages['Conflict'])
+
+
+class ChangePW(Resource):
+ """
+ class to update a users password
+ """
+ def post(self, username):
+ parser.add_argument('password')
+ parser.add_argument('new_password')
+
+ args = parser.parse_args()
+ password = args['password']
+ new_password = args['new_password']
+
+ if None in [password, new_password]:
+ return flask.jsonify(messages['Unprocessable Entity'])
+
+ # check_password return False if password mismatch and None if no user is found
+ if htpasswd.users.check_password(username, password):
+ htpasswd.users.update(username, new_password)
+
+ return flask.jsonify(messages['OK'])
+ else:
+ return flask.jsonify(messages['Unauthorized Request'])
+
+
+class DelUser(Resource):
+ """
+ class to delete a user
+ """
+ def delete(self, username):
+ parser.add_argument('password')
+
+ args = parser.parse_args()
+ password = args['password']
+
+ if password is None:
+ return flask.jsonify(messages['Unprocessable Entity'])
+
+ # check_password return False if password mismatch and None if no user is found
+ if htpasswd.users.check_password(username, password):
+ htpasswd.users.delete(username)
+
+ try:
+ # remove users files recursively
+ shutil.rmtree(Path(app.config['JOPLIN_DIR']).joinpath('./%s' % username))
+ except FileNotFoundError:
+ pass
+
+ return flask.Response(flask.jsonify([]), status=204)
+ else:
+ return flask.jsonify(messages['Unauthorized Request'])
+
+
+api.add_resource(NewUser, '/joplin/<string:username>/create')
+api.add_resource(ChangePW, '/joplin/<string:username>/changepw')
+api.add_resource(DelUser, '/joplin/<string:username>')
+
+
+if __name__ == '__main__':
+ app.run()