first commit
This commit is contained in:
68
app.py
Normal file
68
app.py
Normal file
@@ -0,0 +1,68 @@
|
||||
from flask import Flask, request, Response, render_template, redirect, url_for
|
||||
from sqlalchemy import create_engine, Column, Integer, String, DateTime
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from datetime import datetime
|
||||
import threading
|
||||
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
# SQLAlchemy setup
|
||||
db_uri = 'sqlite:///request_logs.db'
|
||||
engine = create_engine(db_uri)
|
||||
Base = declarative_base()
|
||||
|
||||
class RequestLog(Base):
|
||||
__tablename__ = 'request_logs'
|
||||
id = Column(Integer, primary_key=True)
|
||||
timestamp = Column(DateTime, default=datetime.utcnow)
|
||||
method = Column(String)
|
||||
url = Column(String)
|
||||
root_domain = Column(String)
|
||||
|
||||
Base.metadata.create_all(engine)
|
||||
Session = sessionmaker(bind=engine)
|
||||
HTTP_METHODS = ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'TRACE', 'PATCH']
|
||||
|
||||
@app.route('/', defaults={'path': ''}, methods=HTTP_METHODS)
|
||||
@app.route('/<path:path>', methods=HTTP_METHODS)
|
||||
def catch_all(path):
|
||||
if request.path == '/favicon.ico':
|
||||
return Response(status=200)
|
||||
# Log the request
|
||||
with Session() as session:
|
||||
records = {
|
||||
'method': request.method,
|
||||
'url': request.url,
|
||||
'root_domain': request.host.split(':')[0]
|
||||
}
|
||||
log_entry = RequestLog(**records)
|
||||
session.add(log_entry)
|
||||
session.commit()
|
||||
|
||||
|
||||
return render_template('index.html', records=records)
|
||||
|
||||
|
||||
@app.route('/test/showquery')
|
||||
def show_query():
|
||||
# Retrieve all records from the request_logs table
|
||||
with Session() as session:
|
||||
logs = session.query(RequestLog).all()
|
||||
|
||||
return render_template('records.html', records=logs)
|
||||
|
||||
@app.route('/test/delete_records', methods=['POST'])
|
||||
def delete_records():
|
||||
# Delete all records from the request_logs table
|
||||
with Session() as session:
|
||||
session.query(RequestLog).delete()
|
||||
session.commit()
|
||||
|
||||
# Redirect back to the page displaying the records
|
||||
return redirect(url_for('show_query'))
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(debug=True, host='0.0.0.0', port=443, ssl_context=('ssl/cert.pem', 'ssl/key.pem'))
|
||||
# app.run(debug=True,host="0.0.0.0", port=80)
|
||||
30
docker-compose.yml
Normal file
30
docker-compose.yml
Normal file
@@ -0,0 +1,30 @@
|
||||
version: '3'
|
||||
networks:
|
||||
# Join the container to network you have in use
|
||||
backend:
|
||||
external: true
|
||||
|
||||
services:
|
||||
catchall:
|
||||
container_name: catchall
|
||||
hostname: catchall
|
||||
image: python:3
|
||||
volumes:
|
||||
# Mount your Flask app code into the container to /app
|
||||
- /opt/settings/catch_all:/app
|
||||
working_dir: /app
|
||||
# To start the app, run bellow command:
|
||||
command: ["bash", "-c", "/app/startup.sh"]
|
||||
# if you have any issues, you can run it with command bellow
|
||||
# and test it with docker exec -it catchall bash
|
||||
# here you will be able to run the app.py and fix any errors
|
||||
#command: ["bash", "-c", "echo 'Container is ready'; sleep infinity"]
|
||||
restart: always
|
||||
# if you want, you can use these ports, or just use the ip of container
|
||||
# ports:
|
||||
# - 80:80
|
||||
# - 443:443
|
||||
networks:
|
||||
backend:
|
||||
# for best results, assign static IP and point Adguard to the ip
|
||||
ipv4_address: 10.99.197.231
|
||||
84
generate_cert.sh
Normal file
84
generate_cert.sh
Normal file
@@ -0,0 +1,84 @@
|
||||
#!/bin/bash
|
||||
# CA Authority custom values:
|
||||
CA_NAME="self.certificate" # Use your own domain name
|
||||
CA_COUNTRY_Code="GB"
|
||||
ca_stateOrProvinceName=England
|
||||
ca_localityName="Yorkshire"
|
||||
ca_orgUnitName="IT"
|
||||
ca_comp_Name="Home Industry SelfSigned"
|
||||
|
||||
# your own values for certificate
|
||||
NAME="flower.com" # Use your own domain name
|
||||
COUNTRY_Code="GB"
|
||||
stateOrProvinceName=England
|
||||
localityName="Yorkshire"
|
||||
organizationalUnitName="IT"
|
||||
csr_email="myemail@$NAME"
|
||||
company_Name="Adventures"
|
||||
|
||||
# Also edit Suj Alt names for the certificate down 2x
|
||||
|
||||
# folders
|
||||
cert_dir="ssl"
|
||||
ca_dir='ssl/myca'
|
||||
if [ ! -d "$cert_dir" ]; then
|
||||
mkdir $cert_dir
|
||||
fi
|
||||
|
||||
if [ ! -d "$ca_dir" ]; then
|
||||
mkdir $ca_dir
|
||||
fi
|
||||
|
||||
|
||||
# Check if CA certificate and key files exist
|
||||
if [[ ! -f "$ca_dir/ca-cert.pem" ]] || [[ ! -f "$ca_dir/ca-key.pem" ]]; then
|
||||
echo "CA certificate or key file not found. Creating new CA!!!"
|
||||
# Generate CA-Private Key
|
||||
openssl genrsa 2048 > "$ca_dir/ca-key.pem"
|
||||
# Generate CA certificate
|
||||
openssl req -new -x509 -nodes -days 365000 \
|
||||
-key "$ca_dir/ca-key.pem" \
|
||||
-out "$ca_dir/ca-cert.pem" \
|
||||
-subj "/C=$CA_COUNTRY_Code/ST=$ca_stateOrProvinceName/L=$ca_localityName/O=$ca_comp_Name/OU=$ca_orgUnitName/CN=$CA_NAME"
|
||||
else
|
||||
echo "CA certificate and key file found. Using existing Certificate Authority!"
|
||||
fi
|
||||
|
||||
# Server Key and request
|
||||
# bellow you can set alt_names for hosname and IP you want to use with this cert
|
||||
openssl req -newkey rsa:2048 -nodes -days 365000 \
|
||||
-keyout "$cert_dir/key.pem" \
|
||||
-out "$cert_dir/server-req.pem" \
|
||||
-subj "/C=$COUNTRY_Code/ST=$stateOrProvinceName/L=$localityName/O=$company_Name/OU=$organizationalUnitName/CN=$NAME/emailAddress=$csr_email" \
|
||||
-config <(cat <<-EOF
|
||||
[req]
|
||||
req_extensions = v3_req
|
||||
|
||||
[v3_req]
|
||||
subjectAltName = @alt_names
|
||||
|
||||
[alt_names]
|
||||
DNS.1 = *.${NAME}
|
||||
DNS.2 = piserver.local
|
||||
DNS.3 = localhost
|
||||
IP.1 = 127.0.0.1
|
||||
IP.2 = 10.100.112.254
|
||||
IP.3 = 10.99.197.231
|
||||
EOF
|
||||
)
|
||||
|
||||
# Generate X509 Certificate for the server
|
||||
openssl x509 -req -days 365000 -set_serial 01 \
|
||||
-in "$cert_dir/server-req.pem" \
|
||||
-out "$cert_dir/cert.pem" \
|
||||
-CA "$ca_dir/ca-cert.pem" \
|
||||
-CAkey "$ca_dir/ca-key.pem" \
|
||||
-extfile <(echo "subjectAltName = DNS:*.${NAME}, DNS:piserver.local, DNS:localhost, IP:127.0.0.1, IP:10.100.112.254, IP:10.99.197.231")
|
||||
# Testing certs:
|
||||
openssl verify -CAfile "$ca_dir/ca-cert.pem" \
|
||||
"$ca_dir/ca-cert.pem" \
|
||||
"$cert_dir/cert.pem"
|
||||
|
||||
# To add them to the CA approved list in linux:
|
||||
# sudo cp $ca_dir/ca-cert.pem /usr/local/share/ca-certificates/ca-cert001.crt
|
||||
# sudo update-ca-certificates
|
||||
2
requirements.txt
Normal file
2
requirements.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
Flask
|
||||
SQLAlchemy
|
||||
24
ssl/cert.pem
Normal file
24
ssl/cert.pem
Normal file
@@ -0,0 +1,24 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEEzCCAvugAwIBAgIBATANBgkqhkiG9w0BAQsFADB+MQswCQYDVQQGEwJHQjEQ
|
||||
MA4GA1UECAwHRW5nbGFuZDESMBAGA1UEBwwJWW9ya3NoaXJlMSEwHwYDVQQKDBhI
|
||||
b21lIEluZHVzdHJ5IFNlbGZTaWduZWQxCzAJBgNVBAsMAklUMRkwFwYDVQQDDBBz
|
||||
ZWxmLmNlcnRpZmljYXRlMCAXDTI0MDMyOTEyMzgxM1oYDzMwMjMwNzMxMTIzODEz
|
||||
WjCBjTELMAkGA1UEBhMCR0IxEDAOBgNVBAgMB0VuZ2xhbmQxEjAQBgNVBAcMCVlv
|
||||
cmtzaGlyZTETMBEGA1UECgwKQWR2ZW50dXJlczELMAkGA1UECwwCSVQxEzARBgNV
|
||||
BAMMCmZsb3dlci5jb20xITAfBgkqhkiG9w0BCQEWEm15ZW1haWxAZmxvd2VyLmNv
|
||||
bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbJebhfIl3HAUP4uL4F
|
||||
vaD0vJ84Y2QLqg95qVb+epSHUKbB141i/if945SUzQ82+md9hJKU1Dfmbrq02PsZ
|
||||
OUHE5LXYr5muvxyTlPHgm9I/Oo1QeU8QMC4N/1EcbTFrFCDLeLgDFBE/QFpTnyz1
|
||||
6MWkBdMIVWfHpuG7FExoe9rSYfP9L1F0MuFvbudvGKt7UqUMTi+VE45ILOHjzcns
|
||||
BGzpaaMXLDpG12B48fTUT0042KI185kZ5NPH8ap+WvkCuw4qEkUsUpz84gQ5Ce/H
|
||||
cYZnJBl1OWjFdW/CDZD55vcZS1lCAaq3RIeZWoJUym9p0vQYzQ/7Q4gVwCBLDaPP
|
||||
VQ8CAwEAAaOBiTCBhjBEBgNVHREEPTA7ggwqLmZsb3dlci5jb22CDnBpc2VydmVy
|
||||
LmxvY2Fsgglsb2NhbGhvc3SHBH8AAAGHBApkcP6HBApjxecwHQYDVR0OBBYEFG2M
|
||||
Y1HfovWYY/9iwQhkWS+9gF3AMB8GA1UdIwQYMBaAFB4PFJ2n3XMvMBlNR7/l/Mca
|
||||
pdMZMA0GCSqGSIb3DQEBCwUAA4IBAQBgzQ2ox1w0PkE74xC+OQ18AbyfDh2ZGo/z
|
||||
g6gxOnNQTe39yu1DEkpNbO9vFjzHFdRxLnnraoBhIg8OlDoqoNw8g5WtKtzDh1wp
|
||||
p+6GcKhwRCXVZw506bXnp1elWsjAxLiWO77I7KqlIT34eylAO5bMbnTHKupoeild
|
||||
OrQoDopMXS58NjAiYm3efAl6hwqgwERvAzT39By8ZnoOzTmC9x4TFJGAvbeLx8rv
|
||||
f7xV0diDbcxOswQs/SNAmuR0qsvbrVU0kxvPDLO8MJRp3cFxakfhjkK0kRP+KMfD
|
||||
7/jojqRVvMhbzUeursbrEK+71rGbz7BoWwYAltVX2eTRDhCxRGWR
|
||||
-----END CERTIFICATE-----
|
||||
28
ssl/key.pem
Normal file
28
ssl/key.pem
Normal file
@@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCmyXm4XyJdxwFD
|
||||
+Li+Bb2g9LyfOGNkC6oPealW/nqUh1CmwdeNYv4n/eOUlM0PNvpnfYSSlNQ35m66
|
||||
tNj7GTlBxOS12K+Zrr8ck5Tx4JvSPzqNUHlPEDAuDf9RHG0xaxQgy3i4AxQRP0Ba
|
||||
U58s9ejFpAXTCFVnx6bhuxRMaHva0mHz/S9RdDLhb27nbxire1KlDE4vlROOSCzh
|
||||
483J7ARs6WmjFyw6RtdgePH01E9NONiiNfOZGeTTx/Gqflr5ArsOKhJFLFKc/OIE
|
||||
OQnvx3GGZyQZdTloxXVvwg2Q+eb3GUtZQgGqt0SHmVqCVMpvadL0GM0P+0OIFcAg
|
||||
Sw2jz1UPAgMBAAECggEAM7TjcPbBYzxGVqm9sF98PfGRpnTnT0VUeA66InerTe+z
|
||||
X7dZmYIWlBRgYRhOiEh9keb2WjEcp6XfLy/Q0uurdgnR89RVADqOEhBozSHafPBQ
|
||||
OS45JXs5zJVXUXCUI410RISADOAbcQtgaoBhKSGlg9xJV/bN72oUgQesD9IWj6xH
|
||||
Pi4S6QiawpKbySC9MmwTwvkNRIGntji41ukCPolX9C7SbV8AnG8R/bloLi8xgKJE
|
||||
cci1iL80O+LYrBr3t73gntqgpNII5ADObDQH38JK06fxkiQ+uSgiDNhf0G9M0H3M
|
||||
offBOjfWyOVEGmRIQnxpofnRzzx20bam1USbee2TbQKBgQDqiqRzM/TbTXLaw4ee
|
||||
UP/+UHpsLMQr1ZCsVffVBr1ZATjwuCYOtPJo+qmV8NI3J1eOxo81WTCuT4L0b927
|
||||
ugaZoVSwkMjIgu9cYOPTEVOpD6sMMRZ69w2WriOdExSnvxCy6Ec6Zq6rZj9+Yp4W
|
||||
XR+/7qTtrjgf3wSGnl/slOdPgwKBgQC2C+hSsJu2qvh8R3rcsBuUc3RqLztfSMXt
|
||||
p4YfylASgC+fpC5oepej9Nvaf9YGCAiZdSx+g2MclbTzqo67eUCU6EQcOqINNDur
|
||||
nT3KPayrvikcoBR+dNuBrjp+kX/m9wkA33OIueL5f4w8DUMw8+Vi601OiChA3wiJ
|
||||
T3moL6wChQKBgEd9SvLye0f9K20S/Ft9RQo3bZlba9AQoLBm48vC6iQfA0QcXT1O
|
||||
WjU1ckuJxAmbrEyQqUYRkY0QH1JyZpu58BkT28SV3R2BC4SU49yKA34ckH5+1+NT
|
||||
OokbOy+9iSY4Tta5hjx+3+7Ok7vqQ1V9vRe7nfn0iJbuW2rNC2AJYxgRAoGBAICC
|
||||
AVs17oXRRR29+74D10RBCCHY+6l0nrv38RdJ4qJcuMGRzWzVdWw48mXYrgWN8Dwb
|
||||
2e/o4bMQ/y6u7JjsrCkxmLrwrOpzP9gSZMb6KIUH9M+PNUhbR4TQr9we69Hn+wQR
|
||||
uOYAingjkKPnnNHWqcvdXLIeLYQ1rTn4z2FpXZxdAoGBAOZNc0qA5UEIPLttqhcr
|
||||
lr9p+7PXSTFbGTgXJm/3p5yWfafzb4I4zJwQHexXWlWLf6e03n5RW7mqH+wjOCkG
|
||||
JmV+uNpHHGoDkkxGsm5W2Fj/woFowwjYUnoNNnpbAzKZYdHcMVS2A+scK8/vSlp+
|
||||
Tkt34yovZ0AO2eXtypCTogtK
|
||||
-----END PRIVATE KEY-----
|
||||
23
ssl/myca/ca-cert.pem
Normal file
23
ssl/myca/ca-cert.pem
Normal file
@@ -0,0 +1,23 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIID3zCCAsegAwIBAgIUecB82LW/TlpW9QdDc+2NGPtMK5gwDQYJKoZIhvcNAQEL
|
||||
BQAwfjELMAkGA1UEBhMCR0IxEDAOBgNVBAgMB0VuZ2xhbmQxEjAQBgNVBAcMCVlv
|
||||
cmtzaGlyZTEhMB8GA1UECgwYSG9tZSBJbmR1c3RyeSBTZWxmU2lnbmVkMQswCQYD
|
||||
VQQLDAJJVDEZMBcGA1UEAwwQc2VsZi5jZXJ0aWZpY2F0ZTAgFw0yNDAzMjkxMjM4
|
||||
MTNaGA8zMDIzMDczMTEyMzgxM1owfjELMAkGA1UEBhMCR0IxEDAOBgNVBAgMB0Vu
|
||||
Z2xhbmQxEjAQBgNVBAcMCVlvcmtzaGlyZTEhMB8GA1UECgwYSG9tZSBJbmR1c3Ry
|
||||
eSBTZWxmU2lnbmVkMQswCQYDVQQLDAJJVDEZMBcGA1UEAwwQc2VsZi5jZXJ0aWZp
|
||||
Y2F0ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKdZrhacl+eLbt1J
|
||||
Vxk3wBepfkdgQAtqcfWh/ykmse+ynsOlkhA330oRbWay0KC3hKAsABf7r75PigdW
|
||||
6eOalUvzxAQzBk+hR7Zz3aNrX0h74j1/bi5CfQLy2PwtpS0yxh3uoFeeEUSeZkSj
|
||||
0/lOpH7dCCpnSp6RMCyjgzxm5Gw/lo/sZ+lUQFL05AZeNzqRvX39oZveMqCDDK10
|
||||
ALCXgZAE/C2VTCFJw8GqqZErQcEYgJkdgqiLZ8qvh6M1kJbFQLCwxt3lWDEWe0AF
|
||||
riaMnNDzJWUT+ozhynocHEj/hwfzGXhfjIzVQCFNnzPNfm7TLU28jq+c3RL0omYc
|
||||
gWehgnsCAwEAAaNTMFEwHQYDVR0OBBYEFB4PFJ2n3XMvMBlNR7/l/McapdMZMB8G
|
||||
A1UdIwQYMBaAFB4PFJ2n3XMvMBlNR7/l/McapdMZMA8GA1UdEwEB/wQFMAMBAf8w
|
||||
DQYJKoZIhvcNAQELBQADggEBAIbBn8atU8cIFFgILd0P+zrZX9PdLbx6zM+X+qdA
|
||||
1BGUqiGy/aeS+7/14s2MAMd89DF6H6NnCzwpa7IEc8I6a+eqN4VbsFfBnukgF3eg
|
||||
yzGZ9n5mFafHIAFOvtbsWzvnNwpDzFqgMe3Frdms386/nQe9VoNGoLCgoD0ODSMC
|
||||
tLrCNJYsMkNSBMtHbk3B7UCD5om0lWlLDjD46aTsPjQCgLTkpyamoMGAHvwRG0Rt
|
||||
kLAMKs7gbaHcFwY6hiqKjEHoAGR8Uq1ZOZcPt453HB0VgJy3GBzfr1905NrZ6308
|
||||
amHiktHgD4Qr03WPROlQMjY/C0Xsfep0oRdPMLvhTlnavbI=
|
||||
-----END CERTIFICATE-----
|
||||
28
ssl/myca/ca-key.pem
Normal file
28
ssl/myca/ca-key.pem
Normal file
@@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCnWa4WnJfni27d
|
||||
SVcZN8AXqX5HYEALanH1of8pJrHvsp7DpZIQN99KEW1mstCgt4SgLAAX+6++T4oH
|
||||
VunjmpVL88QEMwZPoUe2c92ja19Ie+I9f24uQn0C8tj8LaUtMsYd7qBXnhFEnmZE
|
||||
o9P5TqR+3QgqZ0qekTAso4M8ZuRsP5aP7GfpVEBS9OQGXjc6kb19/aGb3jKggwyt
|
||||
dACwl4GQBPwtlUwhScPBqqmRK0HBGICZHYKoi2fKr4ejNZCWxUCwsMbd5VgxFntA
|
||||
Ba4mjJzQ8yVlE/qM4cp6HBxI/4cH8xl4X4yM1UAhTZ8zzX5u0y1NvI6vnN0S9KJm
|
||||
HIFnoYJ7AgMBAAECggEAG0xLU9BADdALyeLwZzerM5uSnWKmRSEcQmd7b3iqu8vU
|
||||
5AXPuVTegn7XQVJX1Ro6cxovpbneJVq6IY+xiqP+SIEUmg7CBR6XdmaYt9My8WhB
|
||||
M6uOtdMOAKYhHk71IQClmopV82o1rONzES1GzZBg0CTj88Qc7ZgHVgYSHo82IYX2
|
||||
FckJn+x3eEPd8gbZrol3sJxGFgbS/SCdwuTdQZ64QWK+4847bfArGxvs41mwyLcr
|
||||
Jy4RvGjyoOLajtTCq5FrDd4JTX/JIhqK0yUibx4MrHS5IpYlR53jtKwTJcReEALF
|
||||
zELOcoWnVy2kb5kZaRTQNqvA4rjCf0pY+Xz5Q79oQQKBgQDhi613Y8LXs8El97SW
|
||||
jWQoeXqYoCwV8xfQRXIRkEe+OOniLGi18XKsolfo3DVfkuYdkM9CUtyeZ2KhitHg
|
||||
bAUcrGKEauHAF7xNgnj9Y47gnT5TrCGhpF7kkzy2NkiwTcWei+o3nKq9DlwG+hBq
|
||||
+8/9eyoVs7plocZb8YumAg3WGwKBgQC98mT/TELOPitZFXfpto/IY8gGej/F+ZZd
|
||||
74Yb9Yj5oBJrEUeNnig2mQ1rLZMx/FMZ9lMAtl0klN/0MQoAy9S+earJQ+qaN4yO
|
||||
fkZicwuAayJCGwzeH1RisQV6gvTx8BP5LcFELOq2ffBRl61j/HpjIxcd7z2/LYCt
|
||||
kxFCEE1LIQKBgAm1XnkmJSvtw+GjgPV+DpKjcACD3IHxXdQMOTXCVSQ+BOtEaBl0
|
||||
1C/UKR6P5AhCJX+eTR2YvYBgCOHVPOWBINM0JGV4yFDhdKyNcjHOCEdo3VbysNvp
|
||||
XGBQaiuZuJVGM7x4X1OXfc33gUSXnP9N6Y0KsSwP+XUIeqZYhl9V9UyDAoGBAJuB
|
||||
lPoF3zOmZiq6jr+CPNicCCh1cTyNh3NEI5FERW3IhQuuy9u/PcDlML0sRLPJledN
|
||||
aMrOghbu4yKx+zSHq5Z9WTsJJUo4bBREgS8cbLAoBZYFO1WmZJmfv5J7IDnqiQ+Z
|
||||
S/6an1XkaRkDimqvSytakRRqxyx6/jwciSaC3iTBAoGBAIYPhBZgJEkQRrTnhx1L
|
||||
frj/OaKykb28JOK3MqGtqAPVVOddv/uasF4Tbm1272Q/Q2UTwUAJqZC104tPX1IF
|
||||
eIyAsbA6APPB93S4SRMR/13Bg992g/iTMd7fQ/L9lnPLGgyQfraZnE+qFx1RI2Dn
|
||||
QsHWQkyYUbkK2Gw8ODHP+8pH
|
||||
-----END PRIVATE KEY-----
|
||||
19
ssl/server-req.pem
Normal file
19
ssl/server-req.pem
Normal file
@@ -0,0 +1,19 @@
|
||||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIIDKjCCAhICAQAwgY0xCzAJBgNVBAYTAkdCMRAwDgYDVQQIDAdFbmdsYW5kMRIw
|
||||
EAYDVQQHDAlZb3Jrc2hpcmUxEzARBgNVBAoMCkFkdmVudHVyZXMxCzAJBgNVBAsM
|
||||
AklUMRMwEQYDVQQDDApmbG93ZXIuY29tMSEwHwYJKoZIhvcNAQkBFhJteWVtYWls
|
||||
QGZsb3dlci5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCmyXm4
|
||||
XyJdxwFD+Li+Bb2g9LyfOGNkC6oPealW/nqUh1CmwdeNYv4n/eOUlM0PNvpnfYSS
|
||||
lNQ35m66tNj7GTlBxOS12K+Zrr8ck5Tx4JvSPzqNUHlPEDAuDf9RHG0xaxQgy3i4
|
||||
AxQRP0BaU58s9ejFpAXTCFVnx6bhuxRMaHva0mHz/S9RdDLhb27nbxire1KlDE4v
|
||||
lROOSCzh483J7ARs6WmjFyw6RtdgePH01E9NONiiNfOZGeTTx/Gqflr5ArsOKhJF
|
||||
LFKc/OIEOQnvx3GGZyQZdTloxXVvwg2Q+eb3GUtZQgGqt0SHmVqCVMpvadL0GM0P
|
||||
+0OIFcAgSw2jz1UPAgMBAAGgVzBVBgkqhkiG9w0BCQ4xSDBGMEQGA1UdEQQ9MDuC
|
||||
DCouZmxvd2VyLmNvbYIOcGlzZXJ2ZXIubG9jYWyCCWxvY2FsaG9zdIcEfwAAAYcE
|
||||
CmRw/ocECmPF5zANBgkqhkiG9w0BAQsFAAOCAQEALMbw8nKiGAfoh4szo6+QQfT1
|
||||
0D5V4z+NKQtB5hiQVskcAVVKTIhkI005cfWW1HS11Fro4yrpY3txEgZVv8HVFqhn
|
||||
YF98q6ZLMxn+kP45m7DW1UChR/h/Nr61IZnV5CJDCRBqDm1jN5vawtVgEThXnEYg
|
||||
GAB/tXczH06H2EbBqWp9ED69JPXLvW/z6wAjaO0ghTyPbyMVQy1lVZC06Y0YxdVx
|
||||
1pQp4Y7Ezq9dUrBOVbRnCJ6h8f/DReEkDTYIDQar5k71+gJxLWVqYz2t8aO7McYa
|
||||
BlXXVW0dEJ6KI6SWxJfDOEirIugV4xbI9sCJdiri0cuen+su8LiKiwFZMZ+9DA==
|
||||
-----END CERTIFICATE REQUEST-----
|
||||
11
startup.sh
Normal file
11
startup.sh
Normal file
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
pip install -r requirements.txt
|
||||
#python app.py
|
||||
export FLASK_RUN_EXTRA_FILES="startup.sh"
|
||||
export FLASK_DEBUG=True
|
||||
export FLASK_RUN_HOST="0.0.0.0"
|
||||
export FLASK_RUN_PORT=80
|
||||
|
||||
flask run & python app.py
|
||||
|
||||
#tail -f /dev/null
|
||||
8
static/tables/bootstrap.bundle.min.js
vendored
Normal file
8
static/tables/bootstrap.bundle.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
7
static/tables/bootstrap.min.css
vendored
Normal file
7
static/tables/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
490
static/tables/bootstrap5.css
vendored
Normal file
490
static/tables/bootstrap5.css
vendored
Normal file
@@ -0,0 +1,490 @@
|
||||
/*
|
||||
https://cdn.datatables.net/2.0.3/css/dataTables.bootstrap5.css
|
||||
*/
|
||||
@charset "UTF-8";
|
||||
:root {
|
||||
--dt-row-selected: 13, 110, 253;
|
||||
--dt-row-selected-text: 255, 255, 255;
|
||||
--dt-row-selected-link: 9, 10, 11;
|
||||
--dt-row-stripe: 0, 0, 0;
|
||||
--dt-row-hover: 0, 0, 0;
|
||||
--dt-column-ordering: 0, 0, 0;
|
||||
--dt-html-background: white;
|
||||
}
|
||||
:root.dark {
|
||||
--dt-html-background: rgb(33, 37, 41);
|
||||
}
|
||||
|
||||
table.dataTable td.dt-control {
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
table.dataTable td.dt-control:before {
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
content: "";
|
||||
border-top: 5px solid transparent;
|
||||
border-left: 10px solid rgba(0, 0, 0, 0.5);
|
||||
border-bottom: 5px solid transparent;
|
||||
border-right: 0px solid transparent;
|
||||
}
|
||||
table.dataTable tr.dt-hasChild td.dt-control:before {
|
||||
border-top: 10px solid rgba(0, 0, 0, 0.5);
|
||||
border-left: 5px solid transparent;
|
||||
border-bottom: 0px solid transparent;
|
||||
border-right: 5px solid transparent;
|
||||
}
|
||||
|
||||
html.dark table.dataTable td.dt-control:before,
|
||||
:root[data-bs-theme=dark] table.dataTable td.dt-control:before {
|
||||
border-left-color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
html.dark table.dataTable tr.dt-hasChild td.dt-control:before,
|
||||
:root[data-bs-theme=dark] table.dataTable tr.dt-hasChild td.dt-control:before {
|
||||
border-top-color: rgba(255, 255, 255, 0.5);
|
||||
border-left-color: transparent;
|
||||
}
|
||||
|
||||
div.dt-scroll-body thead tr,
|
||||
div.dt-scroll-body tfoot tr {
|
||||
height: 0;
|
||||
}
|
||||
div.dt-scroll-body thead tr th, div.dt-scroll-body thead tr td,
|
||||
div.dt-scroll-body tfoot tr th,
|
||||
div.dt-scroll-body tfoot tr td {
|
||||
height: 0 !important;
|
||||
padding-top: 0px !important;
|
||||
padding-bottom: 0px !important;
|
||||
border-top-width: 0px !important;
|
||||
border-bottom-width: 0px !important;
|
||||
}
|
||||
div.dt-scroll-body thead tr th div.dt-scroll-sizing, div.dt-scroll-body thead tr td div.dt-scroll-sizing,
|
||||
div.dt-scroll-body tfoot tr th div.dt-scroll-sizing,
|
||||
div.dt-scroll-body tfoot tr td div.dt-scroll-sizing {
|
||||
height: 0 !important;
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
table.dataTable thead > tr > th:active,
|
||||
table.dataTable thead > tr > td:active {
|
||||
outline: none;
|
||||
}
|
||||
table.dataTable thead > tr > th.dt-orderable-asc span.dt-column-order:before, table.dataTable thead > tr > th.dt-ordering-asc span.dt-column-order:before,
|
||||
table.dataTable thead > tr > td.dt-orderable-asc span.dt-column-order:before,
|
||||
table.dataTable thead > tr > td.dt-ordering-asc span.dt-column-order:before {
|
||||
position: absolute;
|
||||
display: block;
|
||||
bottom: 50%;
|
||||
content: "▲";
|
||||
content: "▲"/"";
|
||||
}
|
||||
table.dataTable thead > tr > th.dt-orderable-desc span.dt-column-order:after, table.dataTable thead > tr > th.dt-ordering-desc span.dt-column-order:after,
|
||||
table.dataTable thead > tr > td.dt-orderable-desc span.dt-column-order:after,
|
||||
table.dataTable thead > tr > td.dt-ordering-desc span.dt-column-order:after {
|
||||
position: absolute;
|
||||
display: block;
|
||||
top: 50%;
|
||||
content: "▼";
|
||||
content: "▼"/"";
|
||||
}
|
||||
table.dataTable thead > tr > th.dt-orderable-asc, table.dataTable thead > tr > th.dt-orderable-desc, table.dataTable thead > tr > th.dt-ordering-asc, table.dataTable thead > tr > th.dt-ordering-desc,
|
||||
table.dataTable thead > tr > td.dt-orderable-asc,
|
||||
table.dataTable thead > tr > td.dt-orderable-desc,
|
||||
table.dataTable thead > tr > td.dt-ordering-asc,
|
||||
table.dataTable thead > tr > td.dt-ordering-desc {
|
||||
position: relative;
|
||||
padding-right: 30px;
|
||||
}
|
||||
table.dataTable thead > tr > th.dt-orderable-asc span.dt-column-order, table.dataTable thead > tr > th.dt-orderable-desc span.dt-column-order, table.dataTable thead > tr > th.dt-ordering-asc span.dt-column-order, table.dataTable thead > tr > th.dt-ordering-desc span.dt-column-order,
|
||||
table.dataTable thead > tr > td.dt-orderable-asc span.dt-column-order,
|
||||
table.dataTable thead > tr > td.dt-orderable-desc span.dt-column-order,
|
||||
table.dataTable thead > tr > td.dt-ordering-asc span.dt-column-order,
|
||||
table.dataTable thead > tr > td.dt-ordering-desc span.dt-column-order {
|
||||
position: absolute;
|
||||
right: 12px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 12px;
|
||||
}
|
||||
table.dataTable thead > tr > th.dt-orderable-asc span.dt-column-order:before, table.dataTable thead > tr > th.dt-orderable-asc span.dt-column-order:after, table.dataTable thead > tr > th.dt-orderable-desc span.dt-column-order:before, table.dataTable thead > tr > th.dt-orderable-desc span.dt-column-order:after, table.dataTable thead > tr > th.dt-ordering-asc span.dt-column-order:before, table.dataTable thead > tr > th.dt-ordering-asc span.dt-column-order:after, table.dataTable thead > tr > th.dt-ordering-desc span.dt-column-order:before, table.dataTable thead > tr > th.dt-ordering-desc span.dt-column-order:after,
|
||||
table.dataTable thead > tr > td.dt-orderable-asc span.dt-column-order:before,
|
||||
table.dataTable thead > tr > td.dt-orderable-asc span.dt-column-order:after,
|
||||
table.dataTable thead > tr > td.dt-orderable-desc span.dt-column-order:before,
|
||||
table.dataTable thead > tr > td.dt-orderable-desc span.dt-column-order:after,
|
||||
table.dataTable thead > tr > td.dt-ordering-asc span.dt-column-order:before,
|
||||
table.dataTable thead > tr > td.dt-ordering-asc span.dt-column-order:after,
|
||||
table.dataTable thead > tr > td.dt-ordering-desc span.dt-column-order:before,
|
||||
table.dataTable thead > tr > td.dt-ordering-desc span.dt-column-order:after {
|
||||
left: 0;
|
||||
opacity: 0.125;
|
||||
line-height: 9px;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
table.dataTable thead > tr > th.dt-orderable-asc, table.dataTable thead > tr > th.dt-orderable-desc,
|
||||
table.dataTable thead > tr > td.dt-orderable-asc,
|
||||
table.dataTable thead > tr > td.dt-orderable-desc {
|
||||
cursor: pointer;
|
||||
}
|
||||
table.dataTable thead > tr > th.dt-orderable-asc:hover, table.dataTable thead > tr > th.dt-orderable-desc:hover,
|
||||
table.dataTable thead > tr > td.dt-orderable-asc:hover,
|
||||
table.dataTable thead > tr > td.dt-orderable-desc:hover {
|
||||
outline: 2px solid rgba(0, 0, 0, 0.05);
|
||||
outline-offset: -2px;
|
||||
}
|
||||
table.dataTable thead > tr > th.dt-ordering-asc span.dt-column-order:before, table.dataTable thead > tr > th.dt-ordering-desc span.dt-column-order:after,
|
||||
table.dataTable thead > tr > td.dt-ordering-asc span.dt-column-order:before,
|
||||
table.dataTable thead > tr > td.dt-ordering-desc span.dt-column-order:after {
|
||||
opacity: 0.6;
|
||||
}
|
||||
table.dataTable thead > tr > th.sorting_desc_disabled span.dt-column-order:after, table.dataTable thead > tr > th.sorting_asc_disabled span.dt-column-order:before,
|
||||
table.dataTable thead > tr > td.sorting_desc_disabled span.dt-column-order:after,
|
||||
table.dataTable thead > tr > td.sorting_asc_disabled span.dt-column-order:before {
|
||||
display: none;
|
||||
}
|
||||
table.dataTable thead > tr > th:active,
|
||||
table.dataTable thead > tr > td:active {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
div.dt-scroll-body > table.dataTable > thead > tr > th,
|
||||
div.dt-scroll-body > table.dataTable > thead > tr > td {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
:root.dark table.dataTable thead > tr > th.dt-orderable-asc:hover, :root.dark table.dataTable thead > tr > th.dt-orderable-desc:hover,
|
||||
:root.dark table.dataTable thead > tr > td.dt-orderable-asc:hover,
|
||||
:root.dark table.dataTable thead > tr > td.dt-orderable-desc:hover,
|
||||
:root[data-bs-theme=dark] table.dataTable thead > tr > th.dt-orderable-asc:hover,
|
||||
:root[data-bs-theme=dark] table.dataTable thead > tr > th.dt-orderable-desc:hover,
|
||||
:root[data-bs-theme=dark] table.dataTable thead > tr > td.dt-orderable-asc:hover,
|
||||
:root[data-bs-theme=dark] table.dataTable thead > tr > td.dt-orderable-desc:hover {
|
||||
outline: 2px solid rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
|
||||
div.dt-processing {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 200px;
|
||||
margin-left: -100px;
|
||||
margin-top: -22px;
|
||||
text-align: center;
|
||||
padding: 2px;
|
||||
z-index: 10;
|
||||
}
|
||||
div.dt-processing > div:last-child {
|
||||
position: relative;
|
||||
width: 80px;
|
||||
height: 15px;
|
||||
margin: 1em auto;
|
||||
}
|
||||
div.dt-processing > div:last-child > div {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
border-radius: 50%;
|
||||
background: rgb(13, 110, 253);
|
||||
background: rgb(var(--dt-row-selected));
|
||||
animation-timing-function: cubic-bezier(0, 1, 1, 0);
|
||||
}
|
||||
div.dt-processing > div:last-child > div:nth-child(1) {
|
||||
left: 8px;
|
||||
animation: datatables-loader-1 0.6s infinite;
|
||||
}
|
||||
div.dt-processing > div:last-child > div:nth-child(2) {
|
||||
left: 8px;
|
||||
animation: datatables-loader-2 0.6s infinite;
|
||||
}
|
||||
div.dt-processing > div:last-child > div:nth-child(3) {
|
||||
left: 32px;
|
||||
animation: datatables-loader-2 0.6s infinite;
|
||||
}
|
||||
div.dt-processing > div:last-child > div:nth-child(4) {
|
||||
left: 56px;
|
||||
animation: datatables-loader-3 0.6s infinite;
|
||||
}
|
||||
|
||||
@keyframes datatables-loader-1 {
|
||||
0% {
|
||||
transform: scale(0);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
@keyframes datatables-loader-3 {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
100% {
|
||||
transform: scale(0);
|
||||
}
|
||||
}
|
||||
@keyframes datatables-loader-2 {
|
||||
0% {
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
100% {
|
||||
transform: translate(24px, 0);
|
||||
}
|
||||
}
|
||||
table.dataTable.nowrap th, table.dataTable.nowrap td {
|
||||
white-space: nowrap;
|
||||
}
|
||||
table.dataTable th,
|
||||
table.dataTable td {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
table.dataTable th.dt-left,
|
||||
table.dataTable td.dt-left {
|
||||
text-align: left;
|
||||
}
|
||||
table.dataTable th.dt-center,
|
||||
table.dataTable td.dt-center {
|
||||
text-align: center;
|
||||
}
|
||||
table.dataTable th.dt-right,
|
||||
table.dataTable td.dt-right {
|
||||
text-align: right;
|
||||
}
|
||||
table.dataTable th.dt-justify,
|
||||
table.dataTable td.dt-justify {
|
||||
text-align: justify;
|
||||
}
|
||||
table.dataTable th.dt-nowrap,
|
||||
table.dataTable td.dt-nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
table.dataTable th.dt-empty,
|
||||
table.dataTable td.dt-empty {
|
||||
text-align: center;
|
||||
vertical-align: top;
|
||||
}
|
||||
table.dataTable th.dt-type-numeric, table.dataTable th.dt-type-date,
|
||||
table.dataTable td.dt-type-numeric,
|
||||
table.dataTable td.dt-type-date {
|
||||
text-align: right;
|
||||
}
|
||||
table.dataTable thead th,
|
||||
table.dataTable thead td,
|
||||
table.dataTable tfoot th,
|
||||
table.dataTable tfoot td {
|
||||
text-align: left;
|
||||
}
|
||||
table.dataTable thead th.dt-head-left,
|
||||
table.dataTable thead td.dt-head-left,
|
||||
table.dataTable tfoot th.dt-head-left,
|
||||
table.dataTable tfoot td.dt-head-left {
|
||||
text-align: left;
|
||||
}
|
||||
table.dataTable thead th.dt-head-center,
|
||||
table.dataTable thead td.dt-head-center,
|
||||
table.dataTable tfoot th.dt-head-center,
|
||||
table.dataTable tfoot td.dt-head-center {
|
||||
text-align: center;
|
||||
}
|
||||
table.dataTable thead th.dt-head-right,
|
||||
table.dataTable thead td.dt-head-right,
|
||||
table.dataTable tfoot th.dt-head-right,
|
||||
table.dataTable tfoot td.dt-head-right {
|
||||
text-align: right;
|
||||
}
|
||||
table.dataTable thead th.dt-head-justify,
|
||||
table.dataTable thead td.dt-head-justify,
|
||||
table.dataTable tfoot th.dt-head-justify,
|
||||
table.dataTable tfoot td.dt-head-justify {
|
||||
text-align: justify;
|
||||
}
|
||||
table.dataTable thead th.dt-head-nowrap,
|
||||
table.dataTable thead td.dt-head-nowrap,
|
||||
table.dataTable tfoot th.dt-head-nowrap,
|
||||
table.dataTable tfoot td.dt-head-nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
table.dataTable tbody th.dt-body-left,
|
||||
table.dataTable tbody td.dt-body-left {
|
||||
text-align: left;
|
||||
}
|
||||
table.dataTable tbody th.dt-body-center,
|
||||
table.dataTable tbody td.dt-body-center {
|
||||
text-align: center;
|
||||
}
|
||||
table.dataTable tbody th.dt-body-right,
|
||||
table.dataTable tbody td.dt-body-right {
|
||||
text-align: right;
|
||||
}
|
||||
table.dataTable tbody th.dt-body-justify,
|
||||
table.dataTable tbody td.dt-body-justify {
|
||||
text-align: justify;
|
||||
}
|
||||
table.dataTable tbody th.dt-body-nowrap,
|
||||
table.dataTable tbody td.dt-body-nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/*! Bootstrap 5 integration for DataTables
|
||||
*
|
||||
* ©2020 SpryMedia Ltd, all rights reserved.
|
||||
* License: MIT datatables.net/license/mit
|
||||
*/
|
||||
table.table.dataTable {
|
||||
clear: both;
|
||||
margin-bottom: 0;
|
||||
max-width: none;
|
||||
border-spacing: 0;
|
||||
}
|
||||
table.table.dataTable.table-striped > tbody > tr:nth-of-type(2n+1) > * {
|
||||
box-shadow: none;
|
||||
}
|
||||
table.table.dataTable > :not(caption) > * > * {
|
||||
background-color: transparent;
|
||||
}
|
||||
table.table.dataTable > tbody > tr {
|
||||
background-color: transparent;
|
||||
}
|
||||
table.table.dataTable > tbody > tr.selected > * {
|
||||
box-shadow: inset 0 0 0 9999px rgb(13, 110, 253);
|
||||
box-shadow: inset 0 0 0 9999px rgb(var(--dt-row-selected));
|
||||
color: rgb(255, 255, 255);
|
||||
color: rgb(var(--dt-row-selected-text));
|
||||
}
|
||||
table.table.dataTable > tbody > tr.selected a {
|
||||
color: rgb(9, 10, 11);
|
||||
color: rgb(var(--dt-row-selected-link));
|
||||
}
|
||||
table.table.dataTable.table-striped > tbody > tr:nth-of-type(2n+1) > * {
|
||||
box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-stripe), 0.05);
|
||||
}
|
||||
table.table.dataTable.table-striped > tbody > tr:nth-of-type(2n+1).selected > * {
|
||||
box-shadow: inset 0 0 0 9999px rgba(13, 110, 253, 0.95);
|
||||
box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.95);
|
||||
}
|
||||
table.table.dataTable.table-hover > tbody > tr:hover > * {
|
||||
box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-hover), 0.075);
|
||||
}
|
||||
table.table.dataTable.table-hover > tbody > tr.selected:hover > * {
|
||||
box-shadow: inset 0 0 0 9999px rgba(13, 110, 253, 0.975);
|
||||
box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.975);
|
||||
}
|
||||
|
||||
div.dt-container div.dt-length label {
|
||||
font-weight: normal;
|
||||
text-align: left;
|
||||
white-space: nowrap;
|
||||
}
|
||||
div.dt-container div.dt-length select {
|
||||
width: auto;
|
||||
display: inline-block;
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
div.dt-container div.dt-search {
|
||||
text-align: right;
|
||||
}
|
||||
div.dt-container div.dt-search label {
|
||||
font-weight: normal;
|
||||
white-space: nowrap;
|
||||
text-align: left;
|
||||
}
|
||||
div.dt-container div.dt-search input {
|
||||
margin-left: 0.5em;
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
}
|
||||
div.dt-container div.dt-info {
|
||||
padding-top: 0.85em;
|
||||
}
|
||||
div.dt-container div.dt-paging {
|
||||
margin: 0;
|
||||
}
|
||||
div.dt-container div.dt-paging ul.pagination {
|
||||
margin: 2px 0;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
div.dt-container div.dt-row {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
div.dt-scroll-head table.dataTable {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
div.dt-scroll-body {
|
||||
border-bottom-color: var(--bs-border-color);
|
||||
border-bottom-width: var(--bs-border-width);
|
||||
border-bottom-style: solid;
|
||||
}
|
||||
div.dt-scroll-body > table {
|
||||
border-top: none;
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
div.dt-scroll-body > table > tbody > tr:first-child {
|
||||
border-top-width: 0;
|
||||
}
|
||||
div.dt-scroll-body > table > thead > tr {
|
||||
border-width: 0 !important;
|
||||
}
|
||||
div.dt-scroll-body > table > tbody > tr:last-child > * {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
div.dt-scroll-foot > .dt-scroll-footInner {
|
||||
box-sizing: content-box;
|
||||
}
|
||||
div.dt-scroll-foot > .dt-scroll-footInner > table {
|
||||
margin-top: 0 !important;
|
||||
border-top: none;
|
||||
}
|
||||
div.dt-scroll-foot > .dt-scroll-footInner > table > tfoot > tr:first-child {
|
||||
border-top-width: 0 !important;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
div.dt-container div.dt-length,
|
||||
div.dt-container div.dt-search,
|
||||
div.dt-container div.dt-info,
|
||||
div.dt-container div.dt-paging {
|
||||
text-align: center;
|
||||
}
|
||||
div.dt-container .row {
|
||||
--bs-gutter-y: 0.5rem;
|
||||
}
|
||||
div.dt-container div.dt-paging ul.pagination {
|
||||
justify-content: center !important;
|
||||
}
|
||||
}
|
||||
table.dataTable.table-sm > thead > tr th.dt-orderable-asc, table.dataTable.table-sm > thead > tr th.dt-orderable-desc, table.dataTable.table-sm > thead > tr th.dt-ordering-asc, table.dataTable.table-sm > thead > tr th.dt-ordering-desc,
|
||||
table.dataTable.table-sm > thead > tr td.dt-orderable-asc,
|
||||
table.dataTable.table-sm > thead > tr td.dt-orderable-desc,
|
||||
table.dataTable.table-sm > thead > tr td.dt-ordering-asc,
|
||||
table.dataTable.table-sm > thead > tr td.dt-ordering-desc {
|
||||
padding-right: 20px;
|
||||
}
|
||||
table.dataTable.table-sm > thead > tr th.dt-orderable-asc span.dt-column-order, table.dataTable.table-sm > thead > tr th.dt-orderable-desc span.dt-column-order, table.dataTable.table-sm > thead > tr th.dt-ordering-asc span.dt-column-order, table.dataTable.table-sm > thead > tr th.dt-ordering-desc span.dt-column-order,
|
||||
table.dataTable.table-sm > thead > tr td.dt-orderable-asc span.dt-column-order,
|
||||
table.dataTable.table-sm > thead > tr td.dt-orderable-desc span.dt-column-order,
|
||||
table.dataTable.table-sm > thead > tr td.dt-ordering-asc span.dt-column-order,
|
||||
table.dataTable.table-sm > thead > tr td.dt-ordering-desc span.dt-column-order {
|
||||
right: 5px;
|
||||
}
|
||||
|
||||
div.dt-scroll-head table.table-bordered {
|
||||
border-bottom-width: 0;
|
||||
}
|
||||
|
||||
div.table-responsive > div.dt-container > div.row {
|
||||
margin: 0;
|
||||
}
|
||||
div.table-responsive > div.dt-container > div.row > div[class^=col-]:first-child {
|
||||
padding-left: 0;
|
||||
}
|
||||
div.table-responsive > div.dt-container > div.row > div[class^=col-]:last-child {
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
:root[data-bs-theme=dark] {
|
||||
--dt-row-hover: 255, 255, 255;
|
||||
--dt-row-stripe: 255, 255, 255;
|
||||
--dt-column-ordering: 255, 255, 255;
|
||||
}
|
||||
149
static/tables/dataTables.bootstrap5.js
Normal file
149
static/tables/dataTables.bootstrap5.js
Normal file
@@ -0,0 +1,149 @@
|
||||
/*! DataTables Bootstrap 5 integration
|
||||
* https://cdn.datatables.net/2.0.3/js/dataTables.bootstrap5.js
|
||||
* 2020 SpryMedia Ltd - datatables.net/license
|
||||
*/
|
||||
|
||||
(function( factory ){
|
||||
if ( typeof define === 'function' && define.amd ) {
|
||||
// AMD
|
||||
define( ['jquery', 'datatables.net'], function ( $ ) {
|
||||
return factory( $, window, document );
|
||||
} );
|
||||
}
|
||||
else if ( typeof exports === 'object' ) {
|
||||
// CommonJS
|
||||
var jq = require('jquery');
|
||||
var cjsRequires = function (root, $) {
|
||||
if ( ! $.fn.dataTable ) {
|
||||
require('datatables.net')(root, $);
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof window === 'undefined') {
|
||||
module.exports = function (root, $) {
|
||||
if ( ! root ) {
|
||||
// CommonJS environments without a window global must pass a
|
||||
// root. This will give an error otherwise
|
||||
root = window;
|
||||
}
|
||||
|
||||
if ( ! $ ) {
|
||||
$ = jq( root );
|
||||
}
|
||||
|
||||
cjsRequires( root, $ );
|
||||
return factory( $, root, root.document );
|
||||
};
|
||||
}
|
||||
else {
|
||||
cjsRequires( window, jq );
|
||||
module.exports = factory( jq, window, window.document );
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Browser
|
||||
factory( jQuery, window, document );
|
||||
}
|
||||
}(function( $, window, document ) {
|
||||
'use strict';
|
||||
var DataTable = $.fn.dataTable;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* DataTables integration for Bootstrap 5. This requires Bootstrap 5 and
|
||||
* DataTables 2 or newer.
|
||||
*
|
||||
* This file sets the defaults and adds options to DataTables to style its
|
||||
* controls using Bootstrap. See https://datatables.net/manual/styling/bootstrap
|
||||
* for further information.
|
||||
*/
|
||||
|
||||
/* Set the defaults for DataTables initialisation */
|
||||
$.extend( true, DataTable.defaults, {
|
||||
renderer: 'bootstrap'
|
||||
} );
|
||||
|
||||
|
||||
/* Default class modification */
|
||||
$.extend( true, DataTable.ext.classes, {
|
||||
container: "dt-container dt-bootstrap5",
|
||||
search: {
|
||||
input: "form-control form-control-sm"
|
||||
},
|
||||
length: {
|
||||
select: "form-select form-select-sm"
|
||||
},
|
||||
processing: {
|
||||
container: "dt-processing card"
|
||||
}
|
||||
} );
|
||||
|
||||
|
||||
/* Bootstrap paging button renderer */
|
||||
DataTable.ext.renderer.pagingButton.bootstrap = function (settings, buttonType, content, active, disabled) {
|
||||
var btnClasses = ['dt-paging-button', 'page-item'];
|
||||
|
||||
if (active) {
|
||||
btnClasses.push('active');
|
||||
}
|
||||
|
||||
if (disabled) {
|
||||
btnClasses.push('disabled')
|
||||
}
|
||||
|
||||
var li = $('<li>').addClass(btnClasses.join(' '));
|
||||
var a = $('<a>', {
|
||||
'href': disabled ? null : '#',
|
||||
'class': 'page-link'
|
||||
})
|
||||
.html(content)
|
||||
.appendTo(li);
|
||||
|
||||
return {
|
||||
display: li,
|
||||
clicker: a
|
||||
};
|
||||
};
|
||||
|
||||
DataTable.ext.renderer.pagingContainer.bootstrap = function (settings, buttonEls) {
|
||||
return $('<ul/>').addClass('pagination').append(buttonEls);
|
||||
};
|
||||
|
||||
DataTable.ext.renderer.layout.bootstrap = function ( settings, container, items ) {
|
||||
var row = $( '<div/>', {
|
||||
"class": items.full ?
|
||||
'row mt-2 justify-content-md-center' :
|
||||
'row mt-2 justify-content-between'
|
||||
} )
|
||||
.appendTo( container );
|
||||
|
||||
$.each( items, function (key, val) {
|
||||
var klass;
|
||||
|
||||
// Apply start / end (left / right when ltr) margins
|
||||
if (val.table) {
|
||||
klass = 'col-12';
|
||||
}
|
||||
else if (key === 'start') {
|
||||
klass = 'col-md-auto me-auto';
|
||||
}
|
||||
else if (key === 'end') {
|
||||
klass = 'col-md-auto ms-auto';
|
||||
}
|
||||
else {
|
||||
klass = 'col-md';
|
||||
}
|
||||
|
||||
$( '<div/>', {
|
||||
id: val.id || null,
|
||||
"class": klass + ' ' + (val.className || '')
|
||||
} )
|
||||
.append( val.contents )
|
||||
.appendTo( row );
|
||||
} );
|
||||
};
|
||||
|
||||
|
||||
return DataTable;
|
||||
}));
|
||||
13645
static/tables/dataTables.js
Normal file
13645
static/tables/dataTables.js
Normal file
File diff suppressed because it is too large
Load Diff
10716
static/tables/jquery.js
vendored
Normal file
10716
static/tables/jquery.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
71
templates/index.html
Normal file
71
templates/index.html
Normal file
@@ -0,0 +1,71 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" data-bs-theme="dark" class="fullbody">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='tables/bootstrap.min.css')}}">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='tables/bootstrap5.css')}}">
|
||||
<link rel="shortcut icon" href="#">
|
||||
<title>Blocked Site</title>
|
||||
</head>
|
||||
<style>
|
||||
body, html {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start; /* Align items at the start of the cross axis */
|
||||
}
|
||||
.container {
|
||||
width: 100%;
|
||||
height: 60%; /* adjust height level, 100% is in middle */
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.centered-div {
|
||||
width: auto; /* Set your desired width */
|
||||
height: auto; /* Set your desired height */
|
||||
background-color:rgb(4, 64, 99);
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1); /* Optional: Add shadow for better visual */
|
||||
}
|
||||
.left_align {text-align: left; padding:10px;}
|
||||
.left_ul {padding:10px !important;}
|
||||
.warning {background:red;text-align: center; border-radius: 10px;}
|
||||
.s_table, table, th, td, tr { border: 2px solid;padding: 10px; border-collapse: collapse;}
|
||||
|
||||
</style>
|
||||
<body class="fullbody">
|
||||
<div class="container">
|
||||
<div class="centered-div">
|
||||
|
||||
{% if records %}
|
||||
<h1 class='warning'>
|
||||
<b>Website {{ records.root_domain }} blocked</b>
|
||||
</h1>
|
||||
<div class="container">
|
||||
<table class="left_align s_table">
|
||||
<tr>
|
||||
<th>Method</th>
|
||||
<td>{{records.method}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>URL</th>
|
||||
<td>{{records.url}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<p>
|
||||
<a href="{{ url_for('show_query') }}"> Show History ...</a>
|
||||
</p>
|
||||
|
||||
{% endif %}
|
||||
</div>
|
||||
<p>
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
70
templates/records.html
Normal file
70
templates/records.html
Normal file
@@ -0,0 +1,70 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" data-bs-theme="dark">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='tables/bootstrap.min.css')}}">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='tables/bootstrap5.css')}}">
|
||||
<link rel="shortcut icon" href="#">
|
||||
<script src="{{ url_for('static', filename='tables/jquery.js')}}" type="text/javascript"></script>
|
||||
<script src="{{ url_for('static', filename='tables/dataTables.js')}}" type="text/javascript"></script>
|
||||
<script src="{{ url_for('static', filename='tables/dataTables.bootstrap5.js')}}" type="text/javascript"></script>
|
||||
<script src="{{ url_for('static', filename='tables/bootstrap.bundle.min.js')}}" type="text/javascript"></script>
|
||||
<title>List of blocked sites</title>
|
||||
</head>
|
||||
<style>
|
||||
.out_mid {position: absolute;width: auto; height: auto;top:40%;left: 30%;text-align: center;}
|
||||
</style>
|
||||
<body>
|
||||
{% if records %}
|
||||
<div class="container">
|
||||
<table border="1" id="datatable1" class="table table-striped" style="width:100%">
|
||||
<thead>
|
||||
<tr>
|
||||
{# <th>ID</th> #}
|
||||
<th>Timestamp</th>
|
||||
<th>Method</th>
|
||||
<th>URL</th>
|
||||
<th>Root Domain</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for log in records %}
|
||||
<tr>
|
||||
{# <td>{{log.id}}</td> #}
|
||||
<td>{{log.timestamp.strftime('%d-%m-%Y %H:%M:%S')}}</td>
|
||||
<td>{{log.method}}</td>
|
||||
<td>{{log.url}}</td>
|
||||
<td>{{log.root_domain}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div><br></br>
|
||||
<!-- Add a button to trigger the deletion of records -->
|
||||
<form id="deleteForm" action="{{ url_for('delete_records') }}" method="post">
|
||||
<!-- Button to trigger the confirmation dialog -->
|
||||
<button type="button" class="btn btn-danger" onclick="confirmDelete()">Delete All Records</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="out_mid">
|
||||
<h2> <b>No data recorded yet.</b></h2>
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
<script>
|
||||
new DataTable('#datatable1');
|
||||
// Function to display the confirmation dialog
|
||||
function confirmDelete() {
|
||||
// Show the confirmation dialog
|
||||
if (confirm("Are you sure you want to delete all records?")) {
|
||||
// If user confirms, submit the form
|
||||
document.getElementById("deleteForm").submit();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user