player updates, layout updates, base oidc added
This commit is contained in:
parent
d833ec437d
commit
a4755dd281
|
@ -0,0 +1,40 @@
|
|||
#!/bin/bash
|
||||
|
||||
. CONFIG.sh
|
||||
|
||||
# set -o xtrace ## To debug scripts
|
||||
# set -o errexit ## To exit on error
|
||||
# set -o errunset ## To exit if a variable is referenced but not set
|
||||
|
||||
|
||||
function main() {
|
||||
rm -rf venv/
|
||||
|
||||
clear
|
||||
python -m venv venv/
|
||||
sleep 2
|
||||
source "./venv/bin/activate"
|
||||
|
||||
ANSR="-1"
|
||||
while [[ $ANSR != "0" ]] && [[ $ANSR != "1" ]] && [[ $ANSR != "2" ]]; do
|
||||
clear
|
||||
menu_mesage
|
||||
read -p "--> : " ANSR
|
||||
done
|
||||
case $ANSR in
|
||||
"1" ) pip install -r linux-requirements.txt;;
|
||||
"2" ) pip install -r windows-requirements.txt;;
|
||||
"0" ) exit;;
|
||||
* ) echo "Don't know how you got here but that's a bad sign...";;
|
||||
esac
|
||||
}
|
||||
|
||||
function menu_mesage() {
|
||||
echo "NOTE: Make sure to have Python 3 installed!"
|
||||
echo -e "\nWhat do you want to do?"
|
||||
echo -e "\t1) Generate Linux/Mac supported venv. (Installs Repuirements)"
|
||||
echo -e "\t2) Generate Windows supported venv. (Installs Repuirements)"
|
||||
echo -e "\t0) EXIT"
|
||||
}
|
||||
|
||||
main $@;
|
|
@ -10,6 +10,6 @@ function main() {
|
|||
cd "${SCRIPTPATH}"
|
||||
echo "Working Dir: " $(pwd)
|
||||
source "./venv/bin/activate"
|
||||
gunicorn wsgi:app -b 0.0.0.0:8080 # <module>:<app> IE <file>:<flask app variable>
|
||||
gunicorn wsgi:app -b 0.0.0.0:8080 -p app.pid # <module>:<app> IE <file>:<flask app variable>
|
||||
}
|
||||
main $@;
|
|
@ -9,9 +9,9 @@ function main() {
|
|||
SCRIPTPATH="$( cd "$(dirname "")" >/dev/null 2>&1 ; pwd -P )"
|
||||
cd "${SCRIPTPATH}"
|
||||
echo "Working Dir: " $(pwd)
|
||||
source "./venv/bin/activate"
|
||||
mkdir /tmp/apps
|
||||
./venv/bin/gunicorn \
|
||||
--bind unix:/tmp/apps/webfm.sock wsgi:app
|
||||
gunicorn --bind unix:/tmp/apps/webfm.sock wsgi:app -p app.pid
|
||||
|
||||
}
|
||||
main $@;
|
||||
|
|
|
@ -1,29 +1,58 @@
|
|||
# system import
|
||||
# System import
|
||||
import os, json, secrets
|
||||
from datetime import timedelta
|
||||
|
||||
# Flask imports
|
||||
from flask import Flask, Blueprint
|
||||
# Lib imports
|
||||
from flask import Flask
|
||||
from flask_oidc import OpenIDConnect
|
||||
from flask_login import current_user, login_user, logout_user, LoginManager
|
||||
from flask_bcrypt import Bcrypt
|
||||
|
||||
|
||||
# Apoplication imports
|
||||
|
||||
|
||||
|
||||
# Configs and 'init'
|
||||
app = Flask(__name__)
|
||||
app.config['SQLALCHEMY_DATABASE_URI'] = "sqlite:///static/db/webfm.db"
|
||||
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
||||
app.config['TITLE'] = 'WebFM'
|
||||
APP_NAME = 'WebFM'
|
||||
ROOT_FILE_PTH = os.path.dirname(os.path.realpath(__file__))
|
||||
CONFIG_FILE = ROOT_FILE_PTH + "/config.json"
|
||||
# This path is submitted as the redirect URI in certain code flows.
|
||||
REDIRECT_LINK = "https%3A%2F%2Fwww.webfm.com%2F"
|
||||
|
||||
|
||||
app = Flask(__name__)
|
||||
app.config.update({
|
||||
"TITLE": APP_NAME,
|
||||
'DEBUG': False,
|
||||
'SECRET_KEY': secrets.token_hex(32),
|
||||
'PERMANENT_SESSION_LIFETIME': timedelta(days = 7).total_seconds(),
|
||||
"SQLALCHEMY_DATABASE_URI": "sqlite:///static/db/webfm.db",
|
||||
"SQLALCHEMY_TRACK_MODIFICATIONS": False,
|
||||
"APP_REDIRECT_URI": REDIRECT_LINK,
|
||||
'OIDC_CLIENT_SECRETS': ROOT_FILE_PTH + '/client_secrets.json',
|
||||
'OIDC_ID_TOKEN_COOKIE_SECURE': True, # Only set false in development setups...
|
||||
'OIDC_REQUIRE_VERIFIED_EMAIL': False,
|
||||
'OIDC_USER_INFO_ENABLED': True,
|
||||
'OIDC_VALID_ISSUERS': [
|
||||
'http://www.ssoapps.com/auth/realms/apps',
|
||||
'https://www.ssoapps.com/auth/realms/apps'
|
||||
],
|
||||
'OIDC_TOKEN_TYPE_HINT': 'access_token'
|
||||
})
|
||||
|
||||
|
||||
login_manager = LoginManager(app)
|
||||
bcrypt = Bcrypt(app)
|
||||
oidc = OpenIDConnect(app)
|
||||
def oidc_loggedin():
|
||||
return oidc.user_loggedin
|
||||
app.jinja_env.globals['oidc_loggedin'] = oidc_loggedin
|
||||
app.jinja_env.globals['TITLE'] = APP_NAME
|
||||
|
||||
|
||||
# For csrf and some other stuff...
|
||||
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days = 7)
|
||||
app.config['SECRET_KEY'] = secrets.token_hex(32)
|
||||
login_manager = LoginManager(app)
|
||||
bcrypt = Bcrypt(app)
|
||||
|
||||
# Settings data
|
||||
THIS_FILE_PTH = os.path.dirname(os.path.realpath(__file__))
|
||||
CONFIG_FILE = THIS_FILE_PTH + "/config.json"
|
||||
def retrieveSettings():
|
||||
returnData = []
|
||||
|
||||
|
@ -39,7 +68,7 @@ config = retrieveSettings()
|
|||
|
||||
from .forms import LoginForm, RegisterForm
|
||||
from .models import db, Favorites, Settings, User
|
||||
from webfm import routes
|
||||
|
||||
with app.app_context():
|
||||
db.create_all()
|
||||
db.init_app(app)
|
||||
with app.app_context(): db.create_all()
|
||||
from webfm import routes
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"web": {
|
||||
"auth_uri": "https://www.ssoapps.com/auth/realms/apps/protocol/openid-connect/auth",
|
||||
"client_id": "apps",
|
||||
"issuer": "https://www.ssoapps.com/auth/realms/apps",
|
||||
"client_secret": "[Add your secret key here]",
|
||||
"redirect_uris": [
|
||||
"http://www.webfm.com/home",
|
||||
"https://www.webfm.com/home"
|
||||
],
|
||||
"userinfo_uri": "https://www.ssoapps.com/auth/realms/apps/protocol/openid-connect/userinfo",
|
||||
"token_uri": "https://www.ssoapps.com/auth/realms/apps/protocol/openid-connect/token",
|
||||
"token_introspection_uri": "https://www.ssoapps.com/auth/realms/apps/protocol/openid-connect/token/introspect"
|
||||
}
|
||||
}
|
|
@ -10,7 +10,6 @@ from ...utils import MessageHandler # Get simple message processor
|
|||
|
||||
|
||||
msgHandler = MessageHandler()
|
||||
TITLE = app.config['TITLE']
|
||||
|
||||
@app.route('/login', methods=['GET', 'POST'])
|
||||
def login():
|
||||
|
@ -28,7 +27,7 @@ def login():
|
|||
|
||||
flash("Username or password incorrect! Please try again...", "danger")
|
||||
|
||||
return render_template('login.html', title=TITLE, form=_form)
|
||||
return render_template('login.html', form = _form)
|
||||
|
||||
|
||||
@app.route('/logout', methods=['GET', 'POST'])
|
||||
|
|
|
@ -10,7 +10,6 @@ from ...utils import MessageHandler # Get simple message processor
|
|||
|
||||
|
||||
msgHandler = MessageHandler()
|
||||
TITLE = app.config['TITLE']
|
||||
|
||||
@app.route('/register', methods=['GET', 'POST'])
|
||||
def register():
|
||||
|
@ -27,5 +26,4 @@ def register():
|
|||
return redirect("/login")
|
||||
|
||||
return render_template('register.html',
|
||||
title=TITLE,
|
||||
form=_form)
|
||||
form = _form)
|
||||
|
|
|
@ -22,12 +22,11 @@
|
|||
|
||||
#file-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(18em, 1fr));
|
||||
grid-template-columns: repeat(auto-fit, minmax(14em, 1fr));
|
||||
grid-column-gap: 1em;
|
||||
grid-row-gap: 1em;
|
||||
margin: 5em auto;
|
||||
margin: 2em auto;
|
||||
width: 85%;
|
||||
padding: 2em;
|
||||
overflow-y: auto;
|
||||
max-height: 25em;
|
||||
}
|
||||
|
@ -35,12 +34,33 @@
|
|||
#path { max-width: inherit; }
|
||||
#faves-list > li { width: 100%; }
|
||||
|
||||
#video-container {
|
||||
width: 30em;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#video-viewer {
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
#video-controls {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0.5em;
|
||||
background-color: rgba(0, 0, 0, 0.64);
|
||||
width: inherit;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* CLASSES */
|
||||
.scroller {
|
||||
scrollbar-color: #00000084 #ffffff64;
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: #00000084 #ffffff64;
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
|
||||
.dir-style, .video-style, .file-style {
|
||||
|
|
|
@ -1,3 +1,14 @@
|
|||
#video-container::-webkit-media-controls {
|
||||
display:none !important;
|
||||
}
|
||||
|
||||
#video-container::-webkit-media-controls-enclosure {
|
||||
display:none !important;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.modal-content {
|
||||
background-color: #32383e74;
|
||||
border-color: #f8940674;
|
||||
|
|
|
@ -30,12 +30,7 @@ const doAjax = (actionPath, data, action) => {
|
|||
xhttp.onreadystatechange = function() {
|
||||
if (this.readyState === 4 && this.status === 200) {
|
||||
if (this.responseText != null) { // this.responseXML if getting XML data
|
||||
if (xhttp.responseURL.includes("/register") ||
|
||||
xhttp.responseURL.includes("/login")) {
|
||||
window.location.href = xhttp.responseURL;
|
||||
} else {
|
||||
postAjaxController(JSON.parse(this.responseText), action);
|
||||
}
|
||||
postAjaxController(JSON.parse(this.responseText), action);
|
||||
} else {
|
||||
let type = "danger"
|
||||
let msg = "No content returned. Check the target path.";
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// let eventSource = new EventSource( formatURL("stream") );
|
||||
// eventSource.onmessage = function(e) {
|
||||
// console.log(e.data);
|
||||
// };
|
||||
let fullScreenState = 0;
|
||||
let shouldPlay = null;
|
||||
let clicktapwait = 200;
|
||||
|
||||
|
||||
document.body.onload = (eve) => {
|
||||
|
@ -23,6 +22,100 @@ document.body.onload = (eve) => {
|
|||
}
|
||||
|
||||
|
||||
function togglePlay(video) {
|
||||
shouldPlay = setTimeout(function () {
|
||||
shouldPlay = null;
|
||||
if (video.paused) {
|
||||
video.play();
|
||||
} else {
|
||||
video.pause();
|
||||
}
|
||||
}, 300);
|
||||
}
|
||||
|
||||
function toggleFullscreen(video) {
|
||||
containerElm = document.getElementById("video-container");
|
||||
parentElm = video.parentElement;
|
||||
|
||||
|
||||
if (video.requestFullscreen) {
|
||||
parentElm.requestFullscreen();
|
||||
containerElm.style.display = "block";
|
||||
} else if (video.webkitRequestFullscreen) { /* Safari */
|
||||
parentElm.webkitRequestFullscreen();
|
||||
containerElm.style.display = "block";
|
||||
} else if (video.msRequestFullscreen) { /* IE11 */
|
||||
parentElm.msRequestFullscreen();
|
||||
containerElm.style.display = "block";
|
||||
}
|
||||
|
||||
if (fullScreenState == 2) {
|
||||
if (document.exitFullscreen) {
|
||||
document.exitFullscreen();
|
||||
containerElm.style.display = "contents";
|
||||
} else if (document.webkitExitFullscreen) { /* Safari */
|
||||
document.webkitExitFullscreen();
|
||||
containerElm.style.display = "contents";
|
||||
} else if (document.msExitFullscreen) { /* IE11 */
|
||||
document.msExitFullscreen();
|
||||
containerElm.style.display = "contents";
|
||||
}
|
||||
|
||||
fullScreenState = 0;
|
||||
}
|
||||
|
||||
fullScreenState += 1;
|
||||
}
|
||||
|
||||
$("#video-viewer").on("click", function(eve){
|
||||
const video = eve.target;
|
||||
|
||||
if(!shouldPlay) {
|
||||
shouldPlay = setTimeout( function() {
|
||||
shouldPlay = null;
|
||||
togglePlay(video);
|
||||
}, clicktapwait);
|
||||
} else {
|
||||
clearTimeout(shouldPlay); // Stop single tap callback
|
||||
shouldPlay = null;
|
||||
toggleFullscreen(video);
|
||||
}
|
||||
eve.preventDefault();
|
||||
});
|
||||
|
||||
$("#video-viewer").on("touchend", function(eve){
|
||||
const video = eve.target;
|
||||
|
||||
if(!shouldPlay) {
|
||||
shouldPlay = setTimeout( function() {
|
||||
shouldPlay = null;
|
||||
togglePlay(video);
|
||||
}, clicktapwait);
|
||||
} else {
|
||||
clearTimeout(shouldPlay); // Stop single tap callback
|
||||
shouldPlay = null;
|
||||
toggleFullscreen(video);
|
||||
}
|
||||
eve.preventDefault();
|
||||
});
|
||||
|
||||
$( "#video-viewer" ).bind( "timeupdate", async function(eve) {
|
||||
const video = eve.target;
|
||||
const seekto = document.getElementById("seek-slider");
|
||||
const vt = video.currentTime * (100 / video.duration);
|
||||
seekto.value = vt;
|
||||
});
|
||||
|
||||
$( "#seek-slider" ).bind( "change", async function(eve) {
|
||||
const slider = eve.target;
|
||||
let video = document.getElementById("video-viewer");
|
||||
let seekto = video.duration * (slider.value / 100);
|
||||
video.currentTime = seekto;
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
$( "#search-files-field" ).bind( "keyup", async function(eve) {
|
||||
searchPage();
|
||||
|
|
|
@ -15,4 +15,7 @@ const manageFavorites = (elm) => {
|
|||
|
||||
const loadFave = (id) => {
|
||||
loadFavoriteLink(id);
|
||||
document.getElementById("favorites-modal")
|
||||
.getElementsByClassName("modal-footer")[0]
|
||||
.children[0].click()
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
{% extends "layout.html" %}
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<h1>{{title}}</h1>
|
||||
<p>{{message}}</p>
|
||||
</div>
|
||||
<h1>{{title}}</h1>
|
||||
<p>{{message}}</p>
|
||||
{% endblock content %}
|
||||
|
|
|
@ -2,26 +2,14 @@
|
|||
|
||||
{% block body_header_additional %}
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/base.css')}}">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/overrides.css')}}">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/main.css')}}">
|
||||
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap/bootstrap-table.min.css')}}">
|
||||
{% endblock body_header_additional%}
|
||||
|
||||
<!-- System flashed messages! -->
|
||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||
{% if messages %}
|
||||
<div class=flashes>
|
||||
{% for category, message in messages %}
|
||||
<li class="alert alert-{{ category }}">{{ message }}</li>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
|
||||
|
||||
{% block body_content %}
|
||||
<div class="container-fluid">
|
||||
|
||||
<div class="row sticky-top">
|
||||
<div class="col">
|
||||
<!-- Server messages -->
|
||||
|
@ -48,7 +36,7 @@
|
|||
|
||||
<button title="File viewer..." class="btn btn-secondary btn-sm"
|
||||
data-toggle="modal" data-target="#file-view-modal">🖼</button>
|
||||
{% if isLoggedIn %}
|
||||
{% if current_user.is_authenticated or oidc_loggedin() %}
|
||||
<a href="/logout">
|
||||
<button title="Logout..." class="btn btn-danger btn-sm">
|
||||
Logout
|
||||
|
@ -83,11 +71,10 @@
|
|||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<ul id="file-grid">
|
||||
<ul id="file-grid" class="scroller">
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Favorites modal -->
|
||||
|
@ -132,11 +119,18 @@
|
|||
<div class="row">
|
||||
<div class="col scroller" style="max-height: 30em; overflow: auto;">
|
||||
<!-- For video -->
|
||||
<video id="video-viewer"
|
||||
src=""
|
||||
controls="" style="width: 30em;" autoplay=""
|
||||
poster="{{ url_for('static', filename='imgs/icons/loading.gif')}}">
|
||||
</video>
|
||||
<div id="video-container" style="display: contents;">
|
||||
<video id="video-viewer"
|
||||
src=""
|
||||
autoplay=""
|
||||
loop
|
||||
poster="{{ url_for('static', filename='imgs/icons/loading.gif')}}">
|
||||
</video>
|
||||
<div id="video-controls">
|
||||
<input id="seek-slider" type="range" min="0" max="100" step="1">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- For image -->
|
||||
<img id="image-viewer"
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
{% if title %}
|
||||
<title>{{title}}</title>
|
||||
{% else %}
|
||||
<title>App</title>
|
||||
<title>{{TITLE}}</title>
|
||||
{% endif %}
|
||||
|
||||
{% block header_css %}
|
||||
|
@ -14,6 +14,7 @@
|
|||
<link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap/bootstrap.min.css')}}">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap/bootstrap-datepicker.css')}}">
|
||||
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/overrides.css')}}">
|
||||
{% block header_css_additional %}
|
||||
{% endblock header_css_additional %}
|
||||
{% endblock %}
|
||||
|
@ -26,10 +27,7 @@
|
|||
</head>
|
||||
<body>
|
||||
|
||||
{% block body_header %}
|
||||
{% block body_header_additional %}
|
||||
{% endblock body_header_additional%}
|
||||
{% endblock %}
|
||||
<div class="container-fluid">
|
||||
|
||||
<!-- System flashed messages! -->
|
||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||
|
@ -42,6 +40,11 @@
|
|||
{% endif %}
|
||||
{% endwith %}
|
||||
|
||||
{% block body_header %}
|
||||
{% block body_header_additional %}
|
||||
{% endblock body_header_additional%}
|
||||
{% endblock %}
|
||||
|
||||
{% block body_content %}
|
||||
{% block body_content_additional %}
|
||||
{% endblock body_content_additional%}
|
||||
|
@ -53,6 +56,7 @@
|
|||
{% endblock body_footer_additional%}
|
||||
{% endblock %}
|
||||
|
||||
</div>
|
||||
|
||||
{% block body_scripts %}
|
||||
<!-- For Bootstrap in this exact order... -->
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<div class="col">
|
||||
<!-- <div class="col justify-content-center text-center"> -->
|
||||
<form action="" method="POST">
|
||||
{{ form.hidden_tag() }}
|
||||
<!-- {{ form.hidden_tag() }} -->
|
||||
<fieldset class="form-group">
|
||||
<legend class="border-bottom mb-4">Login</legend>
|
||||
<u>
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
Click==7.0
|
||||
Flask==1.1.1
|
||||
Flask-SQLAlchemy==2.4.1
|
||||
waitress==1.4.3
|
||||
itsdangerous==1.1.0
|
||||
Jinja2==2.10.3
|
||||
MarkupSafe==1.1.1
|
||||
SQLAlchemy==1.3.11
|
||||
Werkzeug==0.16.0
|
Loading…
Reference in New Issue