Add admin panel to delete URLs from the browser. Add copyright notice.
This commit is contained in:
parent
332d82e97a
commit
8288b3624e
11 changed files with 445 additions and 75 deletions
83
liteshort.py
83
liteshort.py
|
@ -1,9 +1,10 @@
|
|||
# Copyright (c) 2019 Steven Spangler <132@ikl.sh>
|
||||
# Copyright (c) 2019 Steven Spangler <132@ikl.sh>, Kevin Alberts <kevin@kevinalberts.nl>
|
||||
# This file is part of liteshort by 132ikl
|
||||
# This software is license under the MIT license. It should be included in your copy of this software.
|
||||
# A copy of the MIT license can be obtained at https://mit-license.org/
|
||||
|
||||
from flask import Flask, current_app, flash, g, jsonify, make_response, redirect, render_template, request, send_from_directory, url_for
|
||||
from flask import Flask, current_app, flash, g, jsonify, make_response, redirect, render_template, request, \
|
||||
send_from_directory, url_for, session
|
||||
import bcrypt
|
||||
import os
|
||||
import random
|
||||
|
@ -22,13 +23,14 @@ def load_config():
|
|||
req_options = {'admin_username': 'admin', 'database_name': "urls", 'random_length': 4,
|
||||
'allowed_chars': 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_',
|
||||
'random_gen_timeout': 5, 'site_name': 'liteshort', 'site_domain': None, 'show_github_link': True,
|
||||
'secret_key': None, 'disable_api': False, 'subdomain': '', 'latest': 'l'
|
||||
'secret_key': None, 'disable_api': False, 'subdomain': '', 'latest': 'l', 'admin_links_per_page': 20
|
||||
}
|
||||
|
||||
config_types = {'admin_username': str, 'database_name': str, 'random_length': int,
|
||||
'allowed_chars': str, 'random_gen_timeout': int, 'site_name': str,
|
||||
'site_domain': (str, type(None)), 'show_github_link': bool, 'secret_key': str,
|
||||
'disable_api': bool, 'subdomain': (str, type(None)), 'latest': (str, type(None))
|
||||
'disable_api': bool, 'subdomain': (str, type(None)), 'latest': (str, type(None)),
|
||||
'admin_links_per_page': int
|
||||
}
|
||||
|
||||
for option in req_options.keys():
|
||||
|
@ -128,6 +130,26 @@ def list_shortlinks():
|
|||
return result
|
||||
|
||||
|
||||
def list_shortlinks_page(page, limit=50):
|
||||
assert page >= 1
|
||||
assert type(page) == int
|
||||
assert type(limit) == int
|
||||
start_index = (page - 1) * limit
|
||||
result = query_db('SELECT * FROM urls ORDER BY short LIMIT ? OFFSET ?', (limit, start_index), False, None)
|
||||
result = nested_list_to_dict(result)
|
||||
return result
|
||||
|
||||
|
||||
def get_num_pages(limit=50):
|
||||
assert type(limit) == int
|
||||
result = query_db('SELECT COUNT(*) FROM urls', (), False, None)
|
||||
items = result[0][0]
|
||||
page_count = result[0][0] // limit
|
||||
if page_count * limit < items:
|
||||
page_count += 1
|
||||
return page_count, items
|
||||
|
||||
|
||||
def nested_list_to_dict(l):
|
||||
d = {}
|
||||
for nl in l:
|
||||
|
@ -300,5 +322,58 @@ def main_post():
|
|||
return response(request, None, 'Long URL required')
|
||||
|
||||
|
||||
@app.route('/login', methods=['POST'])
|
||||
def login():
|
||||
if 'admin_hashed_password' not in app.config or app.config['admin_hashed_password'] is None:
|
||||
raise AssertionError("Login is disabled.")
|
||||
|
||||
if authenticate(request.form['username'], request.form['password']):
|
||||
session['logged_in'] = True
|
||||
else:
|
||||
flash('Wrong password!', 'error')
|
||||
return make_response(redirect(url_for('admin')))
|
||||
|
||||
|
||||
@app.route('/logout')
|
||||
def logout():
|
||||
if 'logged_in' in session and session['logged_in']:
|
||||
session['logged_in'] = False
|
||||
return make_response(redirect(url_for('admin')))
|
||||
|
||||
|
||||
@app.route('/delete/<short>')
|
||||
def delete(short):
|
||||
if 'logged_in' in session and session['logged_in']:
|
||||
success = delete_url(short)
|
||||
if success:
|
||||
flash("Link '/{}' deleted.".format(short), "success")
|
||||
else:
|
||||
flash("Failed to delete URL.".format(short), "error")
|
||||
page = request.args.get('page', '1')
|
||||
return make_response(redirect(url_for('admin')+"?page="+page))
|
||||
else:
|
||||
return make_response(redirect(url_for('admin')))
|
||||
|
||||
|
||||
@app.route('/admin')
|
||||
def admin():
|
||||
if 'logged_in' in session and session['logged_in']:
|
||||
page_count, num_items = get_num_pages(app.config['admin_links_per_page'])
|
||||
page = request.args.get('page', '1')
|
||||
try:
|
||||
page = int(page)
|
||||
if page > page_count:
|
||||
return make_response(redirect(url_for('admin')+"?page="+str(page_count)))
|
||||
if page < 1:
|
||||
return make_response(redirect(url_for('admin')+"?page=1"))
|
||||
except ValueError:
|
||||
page = 1
|
||||
|
||||
urls = list_shortlinks_page(page, app.config['admin_links_per_page'])
|
||||
return render_template('admin.html', urls=urls, page=page, page_count=page_count, num_items=num_items)
|
||||
else:
|
||||
return render_template('login.html')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run()
|
||||
|
|
Reference in a new issue