summaryrefslogtreecommitdiff
path: root/Filer.py
diff options
context:
space:
mode:
Diffstat (limited to 'Filer.py')
-rwxr-xr-xFiler.py68
1 files changed, 42 insertions, 26 deletions
diff --git a/Filer.py b/Filer.py
index ddafd08..bcd6165 100755
--- a/Filer.py
+++ b/Filer.py
@@ -1,10 +1,12 @@
1#!venv/bin/python 1#!venv/bin/python
2 2
3import os
4import hashlib 3import hashlib
5import base64 4import base64
6import time 5import time
6from os import unlink, path, getenv, listdir, mkdir, urandom
7from shutil import rmtree 7from shutil import rmtree
8from threading import Thread
9from random import randint
8 10
9from flask import Flask, render_template, jsonify, request, redirect, send_from_directory 11from flask import Flask, render_template, jsonify, request, redirect, send_from_directory
10from flask_dropzone import Dropzone 12from flask_dropzone import Dropzone
@@ -29,8 +31,8 @@ app.config['DROPZONE_DEFAULT_MESSAGE'] = 'Ziehe die Dateien hier hin, um sie hoc
29 31
30dropzone = Dropzone(app) 32dropzone = Dropzone(app)
31 33
32basedir = os.getenv('FILER_BASEDIR', './Daten') 34basedir = getenv('FILER_BASEDIR', './Daten')
33filettl = int(os.getenv('FILER_FILETTL', 10)) 35filettl = int(getenv('FILER_FILETTL', 10))
34 36
35#### ADMIN FACING DIRECTORY LISTS #### 37#### ADMIN FACING DIRECTORY LISTS ####
36#### 38####
@@ -38,19 +40,19 @@ filettl = int(os.getenv('FILER_FILETTL', 10))
38@app.route("/admin", methods=['GET']) 40@app.route("/admin", methods=['GET'])
39def admin(): 41def admin():
40 url_root = request.url_root.replace('http://', 'https://', 1) 42 url_root = request.url_root.replace('http://', 'https://', 1)
41 users = os.listdir(os.path.join(basedir, 'Mandanten')) 43 users = listdir(path.join(basedir, 'Mandanten'))
42 return render_template('admin.html', users = users, tree = make_tree(basedir, 'Public'), url_root = url_root) 44 return render_template('admin.html', users = users, tree = make_tree(basedir, 'Public'), url_root = url_root)
43 45
44@app.route("/admin/Dokumente/<user>", methods=['GET']) 46@app.route("/admin/Dokumente/<user>", methods=['GET'])
45def admin_dokumente(user): 47def admin_dokumente(user):
46 return render_template('mandant.html', admin = 'admin/', user = user, tree = make_tree(basedir, os.path.join('Dokumente', user))) 48 return render_template('mandant.html', admin = 'admin/', user = user, tree = make_tree(basedir, path.join('Dokumente', user)))
47 49
48@app.route("/admin/del-user/<user>", methods=['POST']) 50@app.route("/admin/del-user/<user>", methods=['POST'])
49def admin_deluser(user): 51def admin_deluser(user):
50 method = request.form.get('_method', 'POST') 52 method = request.form.get('_method', 'POST')
51 if method == 'DELETE': 53 if method == 'DELETE':
52 rmtree(os.path.join(basedir, 'Dokumente', secure_filename(user))) 54 rmtree(path.join(basedir, 'Dokumente', secure_filename(user)))
53 os.unlink(os.path.join(basedir, 'Mandanten', secure_filename(user))) 55 unlink(path.join(basedir, 'Mandanten', secure_filename(user)))
54 return redirect('/admin') 56 return redirect('/admin')
55 57
56@app.route("/admin/new-user", methods=['POST']) 58@app.route("/admin/new-user", methods=['POST'])
@@ -61,7 +63,7 @@ def admin_newuser():
61 return "Username or password missing", 400 63 return "Username or password missing", 400
62 directory = secure_filename(user) 64 directory = secure_filename(user)
63 65
64 salt = os.urandom(4) 66 salt = urandom(4)
65 sha = hashlib.sha1(password.encode('utf-8')) 67 sha = hashlib.sha1(password.encode('utf-8'))
66 sha.update(salt) 68 sha.update(salt)
67 69
@@ -69,9 +71,9 @@ def admin_newuser():
69 tagged_digest_salt = '{{SSHA}}{}'.format(digest_salt_b64.decode('ascii')) 71 tagged_digest_salt = '{{SSHA}}{}'.format(digest_salt_b64.decode('ascii'))
70 72
71 try: 73 try:
72 if not os.path.exists(os.path.join(basedir, 'Dokumente', directory)): 74 if not path.exists(path.join(basedir, 'Dokumente', directory)):
73 os.mkdir(os.path.join(basedir, 'Dokumente', directory)) 75 mkdir(path.join(basedir, 'Dokumente', directory))
74 with open(os.path.join(basedir, 'Mandanten', directory), 'w+', encoding='utf-8') as htpasswd: 76 with open(path.join(basedir, 'Mandanten', directory), 'w+', encoding='utf-8') as htpasswd:
75 htpasswd.write("{}:{}\n".format(user, tagged_digest_salt)) 77 htpasswd.write("{}:{}\n".format(user, tagged_digest_salt))
76 except OSError as error: 78 except OSError as error:
77 return "Couldn't create user scope", 500 79 return "Couldn't create user scope", 500
@@ -82,7 +84,7 @@ def admin_newuser():
82#### 84####
83@app.route("/Dokumente/<user>", methods=['GET']) 85@app.route("/Dokumente/<user>", methods=['GET'])
84def mandant(user): 86def mandant(user):
85 return render_template('mandant.html', admin = '', user = user, tree = make_tree(basedir, os.path.join('Dokumente', user))) 87 return render_template('mandant.html', admin = '', user = user, tree = make_tree(basedir, path.join('Dokumente', user)))
86 88
87#### UPLOAD FILE ROUTES #### 89#### UPLOAD FILE ROUTES ####
88#### 90####
@@ -94,7 +96,7 @@ def upload_mandant(user):
94 if key.startswith('file'): 96 if key.startswith('file'):
95 username = secure_filename(user) 97 username = secure_filename(user)
96 filename = secure_filename(f.filename) 98 filename = secure_filename(f.filename)
97 f.save(os.path.join(basedir, 'Dokumente', username, filename)) 99 f.save(path.join(basedir, 'Dokumente', username, filename))
98 return 'upload template' 100 return 'upload template'
99 101
100@app.route('/admin', methods=['POST']) 102@app.route('/admin', methods=['POST'])
@@ -102,7 +104,7 @@ def upload_admin():
102 for key, f in request.files.items(): 104 for key, f in request.files.items():
103 if key.startswith('file'): 105 if key.startswith('file'):
104 filename = secure_filename(f.filename) 106 filename = secure_filename(f.filename)
105 f.save(os.path.join(basedir, 'Public', filename)) 107 f.save(path.join(basedir, 'Public', filename))
106 return 'upload template' 108 return 'upload template'
107 109
108#### DELETE FILE ROUTES #### 110#### DELETE FILE ROUTES ####
@@ -112,21 +114,21 @@ def upload_admin():
112def delete_file_mandant(user, filename): 114def delete_file_mandant(user, filename):
113 method = request.form.get('_method', 'POST') 115 method = request.form.get('_method', 'POST')
114 if method == 'DELETE': 116 if method == 'DELETE':
115 os.unlink(os.path.join(basedir, 'Dokumente', secure_filename(user), secure_filename(filename))) 117 unlink(path.join(basedir, 'Dokumente', secure_filename(user), secure_filename(filename)))
116 return redirect('/Dokumente/'+user) 118 return redirect('/Dokumente/'+user)
117 119
118@app.route('/admin/Dokumente/<user>/<path:filename>', methods=['POST']) 120@app.route('/admin/Dokumente/<user>/<path:filename>', methods=['POST'])
119def delete_file_mandant_admin(user, filename): 121def delete_file_mandant_admin(user, filename):
120 method = request.form.get('_method', 'POST') 122 method = request.form.get('_method', 'POST')
121 if method == 'DELETE': 123 if method == 'DELETE':
122 os.unlink(os.path.join(basedir, 'Dokumente', secure_filename(user), secure_filename(filename))) 124 unlink(path.join(basedir, 'Dokumente', secure_filename(user), secure_filename(filename)))
123 return redirect('/admin/Dokumente/'+user) 125 return redirect('/admin/Dokumente/'+user)
124 126
125@app.route('/admin/Public/<path:filename>', methods=['POST']) 127@app.route('/admin/Public/<path:filename>', methods=['POST'])
126def delete_file_admin(filename): 128def delete_file_admin(filename):
127 method = request.form.get('_method', 'POST') 129 method = request.form.get('_method', 'POST')
128 if method == 'DELETE': 130 if method == 'DELETE':
129 os.unlink(os.path.join(basedir, 'Public', secure_filename(filename))) 131 unlink(path.join(basedir, 'Public', secure_filename(filename)))
130 return redirect('/admin') 132 return redirect('/admin')
131 133
132#### SERVE FILES RULES #### 134#### SERVE FILES RULES ####
@@ -135,31 +137,45 @@ def delete_file_admin(filename):
135@app.route('/admin/Dokumente/<user>/<path:filename>', methods=['GET']) 137@app.route('/admin/Dokumente/<user>/<path:filename>', methods=['GET'])
136@app.route('/Dokumente/<user>/<path:filename>', methods=['GET']) 138@app.route('/Dokumente/<user>/<path:filename>', methods=['GET'])
137def custom_static(user, filename): 139def custom_static(user, filename):
138 return send_from_directory(os.path.join(basedir, 'Dokumente'), os.path.join(user, filename)) 140 return send_from_directory(path.join(basedir, 'Dokumente'), path.join(user, filename))
139 141
140@app.route('/Public/<path:filename>') 142@app.route('/Public/<path:filename>')
141def custom_static_public(filename): 143def custom_static_public(filename):
142 return send_from_directory(os.path.join(basedir, 'Public'), filename) 144 return send_from_directory(path.join(basedir, 'Public'), filename)
143 145
144def make_tree(rel, path): 146def make_tree(rel, pathname):
145 tree = dict(name=path, download=os.path.basename(path), children=[]) 147 tree = dict(name=pathname, download=path.basename(pathname), children=[])
146 try: lst = os.listdir(os.path.join(rel,path)) 148 try: lst = listdir(path.join(rel,pathname))
147 except OSError: 149 except OSError:
148 pass #ignore errors 150 pass #ignore errors
149 else: 151 else:
150 for name in lst: 152 for name in lst:
151 fn = os.path.join(path, name) 153 fn = path.join(pathname, name)
152 if os.path.isdir(os.path.join(rel,fn)): 154 if path.isdir(path.join(rel,fn)):
153 tree['children'].append(make_tree(rel, fn)) 155 tree['children'].append(make_tree(rel, fn))
154 else: 156 else:
155 ttl = filettl - int((time.time() - os.path.getmtime(os.path.join(rel,fn))) / (24*3600)) 157 ttl = filettl - int((time.time() - path.getmtime(path.join(rel,fn))) / (24*3600))
156 tree['children'].append(dict(name=fn, download=name, ttl = ttl)) 158 if ttl < 0:
159 unlink(path.join(rel,fn))
160 else:
161 tree['children'].append(dict(name=fn, download=name, ttl = ttl))
157 return tree 162 return tree
158 163
164def cleaner_thread():
165 while True:
166 make_tree(basedir, 'Dokumente')
167 # sleep for 6h plus jitter
168 time.sleep(21600 + randint(1, 1800))
169
170thread = Thread(target=cleaner_thread, args=())
171thread.daemon = True
172thread.start()
173
159if __name__ == "__main__": 174if __name__ == "__main__":
160 parser = ArgumentParser(description="Filer") 175 parser = ArgumentParser(description="Filer")
161 parser.add_argument("-H", "--host", help="Hostname of the Flask app " + "[default %s]" % "127.0.0.1", default="127.0.0.1") 176 parser.add_argument("-H", "--host", help="Hostname of the Flask app " + "[default %s]" % "127.0.0.1", default="127.0.0.1")
162 parser.add_argument("-P", "--port", help="Port for the Flask app " + "[default %s]" % "5000", default="5000") 177 parser.add_argument("-P", "--port", help="Port for the Flask app " + "[default %s]" % "5000", default="5000")
178
163 args = parser.parse_args() 179 args = parser.parse_args()
164 180
165 app.run(host=args.host, port=int(args.port)) 181 app.run(host=args.host, port=int(args.port))