-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
update, make a favicon and make the storage_dir visable #1
base: master
Are you sure you want to change the base?
Changes from all commits
6c668aa
350e63d
71ee080
e10e1a6
83c3a34
a7918df
9133a40
4c3c254
976ef7f
4b24feb
95079a7
f98a896
18494a3
dd149c1
bf3ca6c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
FROM gitpod/workspace-full | ||
|
||
# Install Redis. | ||
RUN sudo apt-get update \ | ||
&& sudo apt-get install -y \ | ||
redis-server mongodb \ | ||
&& sudo rm -rf /var/lib/apt/lists/* | ||
EXPOSE 80 | ||
EXPOSE 443 | ||
# Install custom tools, runtimes, etc. | ||
# For example "bastet", a command-line tetris clone: | ||
# RUN brew install bastet | ||
# | ||
# More information: https://www.gitpod.io/docs/config-docker/ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
image: | ||
file: .gitpod.Dockerfile | ||
|
||
tasks: | ||
- init: pip install -r ./requirements.txt |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,9 @@ | ||
import datetime | ||
import hashlib | ||
import os | ||
import secrets | ||
import traceback | ||
from os.path import splitext | ||
import datetime import hashlib import os import secrets import traceback from os.path import splitext from | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Against PEP8 |
||
werkzeug.utils import secure_filename | ||
|
||
import pymongo | ||
from PIL import Image | ||
from flask import Flask, request, json, jsonify, render_template, session, redirect | ||
from flask import Flask, request, json, jsonify, render_template, session, redirect, send_from_directory | ||
from flask_session import Session | ||
from pymongo import MongoClient | ||
|
||
|
@@ -86,6 +82,12 @@ def create_new_user(uid: int, name: str): | |
def datefromunix(s): | ||
return datetime.datetime.fromtimestamp(int(s) / 1000).strftime("%Y-%m-%d %H:%M") | ||
|
||
@app.route('/favicon.ico') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. that should be done with nginx |
||
def favicon(): | ||
return send_from_directory(os.path.join(app.root_path, 'static'), | ||
'favicon.ico', mimetype='image/vnd.microsoft.icon') | ||
|
||
|
||
|
||
@app.route('/') | ||
def index(): | ||
|
@@ -121,7 +123,11 @@ def my_portal(): | |
activity = _db.images.find({"user_uid": session.get("logged_in")}).sort('created', pymongo.DESCENDING).limit(5) | ||
activity = [x for x in activity] | ||
return render_template("my_portal.html", domains=allowed_domains, total=total, images=activity) | ||
|
||
@app.route('/i/<filename>') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. that should be done with nginx or storage provider There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you give an example? |
||
def return_pic(filename): | ||
""" Show just the image specified. | ||
""" | ||
return send_from_directory( _config['storage_dir'], secure_filename(filename)) | ||
|
||
@app.route('/my/files', methods=['GET', 'POST']) | ||
def my_files(): | ||
|
@@ -193,6 +199,96 @@ def print_stats(): | |
"files": _db.images.count(), | ||
"domains": len(allowed_domains) | ||
}) | ||
@app.route('/nl/') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should look into flask-babel |
||
def index-nl(): | ||
return render_template("home.html", domains=allowed_domains) | ||
|
||
|
||
@app.route('/nl/login', methods=['GET', 'POST']) | ||
def login-nl(): | ||
if request.method == "POST": | ||
usr = check_user(request.form.get("username", "unknown"), request.form.get("password", "unknown")) | ||
if usr is None: | ||
return render_template('login.html', is_error=True) | ||
next_url = request.args.get("next", "/") | ||
if session.get("logged_in"): | ||
return redirect(next_url) | ||
session['logged_in'] = usr.uid | ||
return redirect(next_url) | ||
|
||
else: | ||
return render_template('nl/login.html', is_error=False) | ||
|
||
|
||
@app.route('/nl/my/ip', methods=['GET']) | ||
def my_ip-nl(): | ||
return jsonify({"ip": get_client_ip()}) | ||
|
||
|
||
@app.route('/nl/my', methods=['GET']) | ||
def my_portal-nl(): | ||
if session.get("logged_in", None) is None: | ||
return redirect("/login?next=/nl/my") | ||
total = _db.images.find({"user_uid": session.get("logged_in")}).count() | ||
activity = _db.images.find({"user_uid": session.get("logged_in")}).sort('created', pymongo.DESCENDING).limit(5) | ||
activity = [x for x in activity] | ||
return render_template("nl/my_portal.html", domains=allowed_domains, total=total, images=activity) | ||
|
||
|
||
@app.route('/nl/my/files', methods=['GET', 'POST']) | ||
def my_files-nl(): | ||
if session.get("logged_in", None) is None: | ||
return redirect("/nl/login?next=/nl/my/files") | ||
|
||
if request.method == "POST": | ||
action = request.form.get("action") | ||
if action == "delete_all": | ||
total = _db.images.find({"user_uid": session.get("logged_in")}) | ||
for image in total: | ||
fpath = "{}/{}{}".format(storage_folder, image['name'], image['extension']) | ||
if os.path.exists(fpath): | ||
os.remove(fpath) | ||
else: | ||
print("This file does not exist:", fpath) | ||
_db.images.delete_many({"user_uid": session.get("logged_in")}) | ||
elif action == "delete_one": | ||
name = request.form.get("name") | ||
image = _db.images.find_one({"user_uid": session.get("logged_in"), "name": name}) | ||
if image: | ||
fpath = "{}/{}{}".format(storage_folder, image['name'], image['extension']) | ||
if os.path.exists(fpath): | ||
os.remove(fpath) | ||
else: | ||
print("This file does not exist:", fpath) | ||
return jsonify({"success": False}) | ||
_db.images.delete_one({"user_uid": session.get("logged_in"), "name": image['name']}) | ||
return jsonify({"success": True}) | ||
|
||
def get_page(page_size, page_num): | ||
skips = page_size * (page_num - 1) | ||
cursor = _db.images.find({"user_uid": session.get("logged_in")}) \ | ||
.skip(skips) \ | ||
.limit(page_size) \ | ||
.sort('created', pymongo.DESCENDING) | ||
return [x for x in cursor] | ||
|
||
page = int(request.args.get("page", 1)) | ||
images = get_page(50, page) | ||
next_page = bool(get_page(50, page + 1)) | ||
next_page_num = page + 1 | ||
prev_page = page != 1 | ||
prev_page_num = page - 1 | ||
|
||
return render_template("nl/my_files.html", images=images, page=page, next_page=next_page, prev_page=prev_page, | ||
next_page_num=next_page_num, prev_page_num=prev_page_num) | ||
|
||
|
||
@app.route('/nl/my/config', methods=['GET']) | ||
def my_config-nl(): | ||
if session.get("logged_in", None) is None: | ||
return redirect("/nl/login?next=/nl/my/config") | ||
usr = _db.users.find_one({"uid": session.get("logged_in")}) | ||
return render_template("nl/my_config.html", **{"domains": allowed_domains, "token": usr['token']}) | ||
|
||
|
||
@app.route('/upload', methods=['POST']) | ||
|
@@ -234,7 +330,7 @@ def upload(): | |
|
||
@app.route('/add-user', methods=['POST']) | ||
def add_user(): | ||
token = request.headers.get("Authorization", "unknown") | ||
token = request.form['Authorization'] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it's an admin token, should be used in headers |
||
if token != secret_key: | ||
return "Not authorized", 403 | ||
if request.method == 'POST': | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
<!DOCTYPE html> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should look into flask-babel |
||
<html lang="nl"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1"> | ||
<title>ksoft.si :: Foto host</title> | ||
<meta name="description" | ||
content="Your personal image and file host. Fast and reliable CDN powered by nginx and CloudFlare, unlimited storage and multiple custom domains with SSL security. Brought to you by the Ksoft.Si team!"> | ||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300italic,700,700italic"> | ||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/3.0.3/normalize.css"> | ||
<link rel="stylesheet" href="https://cdn.ksoft.si/_generic/css/milligram.css"> | ||
<style> | ||
body { | ||
background: #FFFFFF url("https://cdn.ksoft.si/images/bg/camera3.jpg") center no-repeat fixed; | ||
background-size: cover; | ||
} | ||
|
||
.container { | ||
margin: 14vh auto; | ||
position: relative; | ||
padding-top: 2vh; | ||
padding-bottom: 1vh; | ||
background-color: rgba(255, 255, 255, 0.9); | ||
} | ||
|
||
.error { | ||
color: red; | ||
} | ||
|
||
@media screen and (min-width: 620px) { | ||
.container { | ||
max-width: 500px; | ||
width: 500px; | ||
} | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<div class="container"> | ||
<h2 style="text-align: center;margin-bottom: 0"> ksoft.si - Image host</h2> | ||
<p style="text-align: center">Je persoonlijke geen bullshit foto host.</p> | ||
<section> | ||
<a class="button" href="/nl/my" style="width: 100%">Mijn account</a> | ||
<a class="button" href="/nl/my/config" style="width: 100%">geef mijn config</a> | ||
</section> | ||
<section style="margin-top: 3rem"> | ||
<h4 style="text-align: center">List van domeinen:</h4> | ||
<p style="text-align: center"> | ||
{% for d in domains %} | ||
{{ d }}<br> | ||
{% endfor %} | ||
</p> | ||
</section> | ||
<small> Don't email us about account creation.| <a href="mailto:support.ksoft.si"> </a>. | ||
</small> | ||
</p> | ||
<small> <a href="https://i.ksoft.si/"> english? | ||
</a> | ||
<br> | ||
</small> | ||
</section> | ||
</div> | ||
</body> | ||
</html> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
<!DOCTYPE html> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should look into flask-babel |
||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1"> | ||
<title>Ksoft.Si :: Login</title> | ||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300italic,700,700italic"> | ||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/3.0.3/normalize.css"> | ||
<link rel="stylesheet" href="https://cdn.ksoft.si/_generic/css/milligram.css"> | ||
<style> | ||
body { | ||
background: #FFFFFF url("https://cdn.ksoft.si/images/bg/camera2.jpg") center no-repeat fixed; | ||
background-size: cover; | ||
} | ||
.container { | ||
margin: 14vh auto; | ||
position: relative; | ||
padding-top: 2vh; | ||
padding-bottom: 1vh; | ||
background-color: rgba(255,255,255,0.9); | ||
} | ||
|
||
.error { | ||
color: red; | ||
} | ||
|
||
@media screen and (min-width: 620px) { | ||
.container { | ||
max-width: 500px; | ||
width: 500px; | ||
} | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<div class="container"> | ||
<h2 style="text-align: center">Login</h2> | ||
{% if is_error %} | ||
<blockquote style="border-left: 0.3rem solid red;"><p class="error">Wrong username or password.</p></blockquote> | ||
{% endif %} | ||
<form method="post"> | ||
<fieldset> | ||
<input type="text" name="username" id="username" placeholder="Username" required> | ||
<input type="password" name="password" id="password" placeholder="Password" required> | ||
<button type="submit" style="width: 100%">Login</button> | ||
</fieldset> | ||
</form> | ||
<small>Don't email us about account creation. | <a href="mailto:[email protected]"> [email protected]</a>.</small> | ||
|
||
</section> | ||
</div> | ||
</body> | ||
</html> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
<!DOCTYPE html> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should look into flask-babel |
||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1"> | ||
<title>Ksoft.Si :: Sharex Config</title> | ||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300italic,700,700italic"> | ||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/3.0.3/normalize.css"> | ||
<link rel="stylesheet" href="https://cdn.ksoft.si/_generic/css/milligram.css"> | ||
<style> | ||
body { | ||
background: #FFFFFF url("https://cdn.ksoft.si/images/bg/camera.jpg") center no-repeat fixed; | ||
background-size: cover; | ||
} | ||
|
||
.container { | ||
margin: 4vh auto; | ||
position: relative; | ||
padding-top: 3rem; | ||
padding-bottom: 3rem; | ||
background-color: rgba(255, 255, 255, 0.9); | ||
} | ||
|
||
.button-small { | ||
font-size: .8rem; | ||
height: 2.8rem; | ||
line-height: 2.8rem; | ||
padding: 0 1.5rem; | ||
} | ||
|
||
@media screen and (min-width: 1088px) { | ||
.container { | ||
max-width: 960px; | ||
width: 960px; | ||
} | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<div class="container"> | ||
<h1 style="text-align: center">Jouw config:</h1> | ||
<label for="domains">Select een url naar keuze:</label> | ||
<select name="domains" id="domains"> | ||
{% for domain in domains %} | ||
<option value="{{ domain }}">{{ domain }}</option> | ||
{% endfor %} | ||
</select> | ||
<div class="clearfix"> | ||
<div class="float-left"> | ||
<small><a class="button button-outline button-small" href="/my">Back</a></small> | ||
</div> | ||
<div class="float-right"> | ||
<small><button class="copy button-small" data-clipboard-target="#config">Copy</button></small> | ||
</div> | ||
</div> | ||
<pre><code id="config">{ | ||
"Name": "ksoft-sharex", | ||
"DestinationType": "ImageUploader", | ||
"RequestURL": "https://i.ksoft.si/upload", | ||
"FileFormName": "image", | ||
"Headers": { | ||
"Authorization": "{{ token }}" | ||
}, | ||
"URL": "https://i.ksoft.si/i/$json:filename$$json:extension$" | ||
}</code></pre> | ||
</div> | ||
<script src="https://cdn.ksoft.si/_generic/jquery/jquery-3.2.1.min.js"></script> | ||
<script src="https://cdn.ksoft.si/js/clipboard.min.js"></script> | ||
<script> | ||
let conf = { | ||
"Name": "ksoft-sharex", | ||
"DestinationType": "ImageUploader", | ||
"RequestURL": "https://i.ksoft.si/upload", | ||
"FileFormName": "image", | ||
"Headers": { | ||
"Authorization": "{{ token }}" | ||
}, | ||
"URL": "https://i.ksoft.si/i/$json:filename$$json:extension$" | ||
}; | ||
|
||
$('#domains').on('change', function () { | ||
conf.URL = "https://" + $(this).val() + "/i/$json:filename$$json:extension$"; | ||
$("#config").text(JSON.stringify(conf, null, 2)); | ||
}); | ||
const copyToClipboard = str => { | ||
const el = document.createElement('textarea'); | ||
el.value = str; | ||
document.body.appendChild(el); | ||
el.select(); | ||
document.execCommand('copy'); | ||
document.body.removeChild(el); | ||
}; | ||
new ClipboardJS('.copy'); | ||
</script> | ||
</body> | ||
</html> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
irrelevant dependency?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think so