132 lines
4.1 KiB
Python
132 lines
4.1 KiB
Python
"""
|
|
Webdist Flask backend
|
|
"""
|
|
import json
|
|
import logging
|
|
import subprocess
|
|
import sqlite3
|
|
from datetime import datetime
|
|
from flask import Flask, render_template, request
|
|
|
|
|
|
# Enable logging
|
|
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
|
level=logging.INFO)
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
def create_app(config):
|
|
""" creates and returns the Flask app """
|
|
_app = Flask(__name__)
|
|
_app.config.from_file(config, load=json.load)
|
|
# initialize moment on the app within create_app()
|
|
return _app
|
|
|
|
app = create_app("/etc/webdist/main.json")
|
|
logger.info(app.config)
|
|
|
|
def cursor_row_to_dict(cursor, row):
|
|
""" Converts a sqlite3 cursor row into a dict """
|
|
items = {}
|
|
for idx, key in enumerate(cursor.description):
|
|
if key[0] in ['buildtime']:
|
|
items[key[0]] = datetime.fromtimestamp(row[idx]).isoformat()
|
|
else:
|
|
items[key[0]] = row[idx]
|
|
return items
|
|
|
|
def latest():
|
|
""" Returns a dict of latest packages """
|
|
response = {}
|
|
for repo in app.config['WEBDIST_CONFIG']['repos']:
|
|
response[repo] = []
|
|
repo_sources_db = "file:" + app.config['WEBDIST_CONFIG']['repos'][repo]['path'] + \
|
|
f"{app.config['WEBDIST_CONFIG']['repos'][repo]['dbname']}-sources.db?mode=ro"
|
|
conn = sqlite3.connect(repo_sources_db, uri=True)
|
|
cursor = conn.cursor()
|
|
cursor.execute(
|
|
'SELECT * FROM sources ORDER BY buildtime DESC limit 100')
|
|
for row in cursor:
|
|
response[repo].append(cursor_row_to_dict(cursor, row))
|
|
|
|
return response
|
|
|
|
|
|
def query(querystring):
|
|
""" Performs a query of a package """
|
|
logger.info("Query of %s", querystring)
|
|
|
|
response = {}
|
|
for repo in app.config['WEBDIST_CONFIG']['repos']:
|
|
response[repo] = []
|
|
repo_sources_db = "file:" + app.config['WEBDIST_CONFIG']['repos'][repo]['path'] + \
|
|
f"{app.config['WEBDIST_CONFIG']['repos'][repo]['dbname']}-sources.db?mode=ro"
|
|
conn = sqlite3.connect(repo_sources_db, uri=True)
|
|
cursor = conn.cursor()
|
|
cursor.execute(
|
|
f'SELECT * FROM sources where name like "%%{querystring}%%" '
|
|
'or summary like "%%{querystring}%%" '
|
|
'ORDER BY name="{querystring}" DESC, name like "{qs}%%" DESC, '
|
|
'name like "%%{querystring}%%" DESC limit 10')
|
|
for row in cursor:
|
|
response[repo].append(cursor_row_to_dict(cursor, row))
|
|
|
|
return response
|
|
|
|
|
|
@app.route("/")
|
|
def _search():
|
|
return render_template("index.html")
|
|
|
|
|
|
@app.route("/latest")
|
|
def _latest():
|
|
data = latest()
|
|
return render_template("latest.html", data=data)
|
|
|
|
|
|
@app.route("/button/<name>")
|
|
def _button(name):
|
|
script = app.config['WEBDIST_CONFIG']['buttons'][name]['script']
|
|
output = subprocess.check_output([script])
|
|
return render_template("button.html",output=output.decode())
|
|
|
|
|
|
@app.route("/query/<querystring>")
|
|
def _query(querystring):
|
|
data = query(querystring)
|
|
return render_template("query.html", data=data)
|
|
|
|
|
|
@app.route("/api/v1/config")
|
|
def api_config():
|
|
""" GET config API call """
|
|
logger.info("Origin: %s", request.headers['Origin'])
|
|
return {'result': app.config['WEBDIST_CONFIG'] }
|
|
|
|
|
|
@app.route("/api/v1/latest")
|
|
def api_latest():
|
|
""" Get latest packages API call """
|
|
data = latest()
|
|
return {'result': data }
|
|
|
|
|
|
@app.route("/api/v1/button/<name>")
|
|
def api_button(name):
|
|
""" Call a button associated script """
|
|
script = app.config['WEBDIST_CONFIG']['buttons'][name]['script']
|
|
output = subprocess.check_output([script])
|
|
return {'result': output.decode() }
|
|
|
|
|
|
@app.after_request
|
|
def after_request(response):
|
|
""" Allow API request origins specified in configuration file """
|
|
white_origin = app.config['WEBDIST_CONFIG']['white_origins']
|
|
if request.headers['Origin'] in white_origin:
|
|
response.headers['Access-Control-Allow-Origin'] = request.headers['Origin']
|
|
response.headers['Access-Control-Allow-Methods'] = 'PUT,GET,POST,DELETE'
|
|
response.headers['Access-Control-Allow-Headers'] = 'Content-Type,Authorization'
|
|
return response
|