mirror of
https://github.com/akuker/RASCSI.git
synced 2024-11-29 16:49:55 +00:00
User authentication in the Web Interface (#483)
* Add flask-login library * Add simplepam lib to requirements * We don't use flask-login after all * User authentication in the web app using simplepam * Allow only users in the sudo group to log in * Tweak string * This way to enforce authenticated state doesn't work here * Open links to github in new tab * Disallow uploads when not authenticated * Check for the rascsi group on the system to enable webapp auth. Allow only users in the rascsi group to authenticate. * Make the AUTH_GROUP a global constant. * Add easyinstall option for web interface auth * Make AUTH_GROUP a constant * More accurate change scope
This commit is contained in:
parent
1ad1242fad
commit
5346d110a9
@ -700,6 +700,21 @@ function notifyBackup {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Creates the group and modifies current user for Web Interface auth
|
||||||
|
function enableWebInterfaceAuth {
|
||||||
|
AUTH_GROUP="rascsi"
|
||||||
|
|
||||||
|
if [ $(getent group "$AUTH_GROUP") ]; then
|
||||||
|
echo "The '$AUTH_GROUP' group already exists."
|
||||||
|
else
|
||||||
|
echo "Creating the '$AUTH_GROUP' group."
|
||||||
|
sudo groupadd "$AUTH_GROUP"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Adding user '$USER' to the '$AUTH_GROUP' group."
|
||||||
|
sudo usermod -a -G "$AUTH_GROUP" "$USER"
|
||||||
|
}
|
||||||
|
|
||||||
# Executes the keyword driven scripts for a particular action in the main menu
|
# Executes the keyword driven scripts for a particular action in the main menu
|
||||||
function runChoice() {
|
function runChoice() {
|
||||||
case $1 in
|
case $1 in
|
||||||
@ -855,6 +870,15 @@ function runChoice() {
|
|||||||
echo "Configuring RaSCSI Web Interface stand-alone - Complete!"
|
echo "Configuring RaSCSI Web Interface stand-alone - Complete!"
|
||||||
echo "Launch the Web Interface with the 'start.sh' script. To use a custom port for the web server: 'start.sh --port=8081"
|
echo "Launch the Web Interface with the 'start.sh' script. To use a custom port for the web server: 'start.sh --port=8081"
|
||||||
;;
|
;;
|
||||||
|
12)
|
||||||
|
echo "Enabling authentication for the RaSCSI Web Interface"
|
||||||
|
echo "This script will make the following changes to your system:"
|
||||||
|
echo "- Modify users and user groups"
|
||||||
|
sudoCheck
|
||||||
|
enableWebInterfaceAuth
|
||||||
|
echo "Enabling authentication for the RaSCSI Web Interface - Complete!"
|
||||||
|
echo "Use the credentials for user '$USER' to log in to the Web Interface."
|
||||||
|
;;
|
||||||
-h|--help|h|help)
|
-h|--help|h|help)
|
||||||
showMenu
|
showMenu
|
||||||
;;
|
;;
|
||||||
@ -868,7 +892,7 @@ function runChoice() {
|
|||||||
function readChoice() {
|
function readChoice() {
|
||||||
choice=-1
|
choice=-1
|
||||||
|
|
||||||
until [ $choice -ge "0" ] && [ $choice -le "11" ]; do
|
until [ $choice -ge "0" ] && [ $choice -le "12" ]; do
|
||||||
echo -n "Enter your choice (0-9) or CTRL-C to exit: "
|
echo -n "Enter your choice (0-9) or CTRL-C to exit: "
|
||||||
read -r choice
|
read -r choice
|
||||||
done
|
done
|
||||||
@ -897,6 +921,7 @@ function showMenu() {
|
|||||||
echo "ADVANCED OPTIONS"
|
echo "ADVANCED OPTIONS"
|
||||||
echo " 10) compile and install RaSCSI stand-alone"
|
echo " 10) compile and install RaSCSI stand-alone"
|
||||||
echo " 11) configure the RaSCSI Web Interface stand-alone"
|
echo " 11) configure the RaSCSI Web Interface stand-alone"
|
||||||
|
echo " 12) enable authentication for the RaSCSI Web Interface"
|
||||||
}
|
}
|
||||||
|
|
||||||
# parse arguments passed to the script
|
# parse arguments passed to the script
|
||||||
@ -919,7 +944,7 @@ while [ "$1" != "" ]; do
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
case $VALUE in
|
case $VALUE in
|
||||||
FULLSPEC | STANDARD | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11)
|
FULLSPEC | STANDARD | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12)
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "ERROR: unknown option \"$VALUE\""
|
echo "ERROR: unknown option \"$VALUE\""
|
||||||
|
@ -3,6 +3,7 @@ Module for methods controlling and getting information about the Pi's Linux syst
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
|
from settings import AUTH_GROUP
|
||||||
|
|
||||||
|
|
||||||
def systemd_service(service, action):
|
def systemd_service(service, action):
|
||||||
@ -115,4 +116,20 @@ def introspect_file(file_path, re_term):
|
|||||||
for line in ifile:
|
for line in ifile:
|
||||||
if match(re_term, line):
|
if match(re_term, line):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def auth_active():
|
||||||
|
"""
|
||||||
|
Inspects if the group defined in AUTH_GROUP exists on the system.
|
||||||
|
If it exists, tell the webapp to enable authentication.
|
||||||
|
Returns a (dict) with (bool) status and (str) msg
|
||||||
|
"""
|
||||||
|
from grp import getgrall
|
||||||
|
groups = [g.gr_name for g in getgrall()]
|
||||||
|
if AUTH_GROUP in groups:
|
||||||
|
return {
|
||||||
|
"status": True,
|
||||||
|
"msg": "You must log in to use this function!",
|
||||||
|
}
|
||||||
|
return {"status": False, "msg": ""}
|
||||||
|
@ -6,3 +6,4 @@ Jinja2==3.0.1
|
|||||||
MarkupSafe==2.0.1
|
MarkupSafe==2.0.1
|
||||||
protobuf==3.17.3
|
protobuf==3.17.3
|
||||||
requests==2.26.0
|
requests==2.26.0
|
||||||
|
simplepam==0.1.5
|
||||||
|
@ -27,3 +27,6 @@ REMOVABLE_DEVICE_TYPES = ("SCCD", "SCRM", "SCMO")
|
|||||||
# The RESERVATIONS list is used to keep track of the reserved ID memos.
|
# The RESERVATIONS list is used to keep track of the reserved ID memos.
|
||||||
# Initialize with a list of 8 empty strings.
|
# Initialize with a list of 8 empty strings.
|
||||||
RESERVATIONS = ["" for x in range(0, 8)]
|
RESERVATIONS = ["" for x in range(0, 8)]
|
||||||
|
|
||||||
|
# The user group that is used for webapp authentication
|
||||||
|
AUTH_GROUP = "rascsi"
|
||||||
|
@ -31,12 +31,27 @@
|
|||||||
<body>
|
<body>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<span style="display: inline-block; width: 100%; color: white; background-color: green; text-align: center; vertical-align: center; font-family: Arial, Helvetica, sans-serif;">Service Running</span>
|
{% if auth_active %}
|
||||||
|
{% if username %}
|
||||||
|
<span style="display: inline-block; width: 100%; color: white; background-color: green; text-align: center; vertical-align: center; font-family: Arial, Helvetica, sans-serif;">Logged in as <em>{{ username }}</em> – <a href="/logout">Log Out</a></span>
|
||||||
|
{% else %}
|
||||||
|
<span style="display: inline-block; width: 100%; color: white; background-color: red; text-align: center; vertical-align: center; font-family: Arial, Helvetica, sans-serif;">
|
||||||
|
<form method="POST" action="/login">
|
||||||
|
<div>Log In to Use Web Interface</div>
|
||||||
|
<input type="text" name="username" placeholder="Username">
|
||||||
|
<input type="password" name="password" placeholder="Password">
|
||||||
|
<input type="submit" value="Login">
|
||||||
|
</form>
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
<span style="display: inline-block; width: 100%; color: white; background-color: green; text-align: center; vertical-align: center; font-family: Arial, Helvetica, sans-serif;">Web Interface Authentication Disabled – See <a href="https://github.com/akuker/RASCSI/wiki/Web-Interface#Security_Notice" target="_blank">Wiki</a> for more information</span>
|
||||||
|
{% endif %}
|
||||||
<table width="100%">
|
<table width="100%">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr style="background-color: black;">
|
<tr style="background-color: black;">
|
||||||
<td style="background-color: black;">
|
<td style="background-color: black;">
|
||||||
<a href="http://github.com/akuker/RASCSI">
|
<a href="http://github.com/akuker/RASCSI" target="_blank">
|
||||||
<h1>RaSCSI - 68kmla Edition</h1>
|
<h1>RaSCSI - 68kmla Edition</h1>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
@ -57,7 +72,7 @@
|
|||||||
{% block content %}{% endblock content %}
|
{% block content %}{% endblock content %}
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
<center><tt>RaSCSI version: <strong>{{ version }} <a href="https://github.com/akuker/RASCSI/commit/{{ running_env['git'] }}">{{ running_env["git"][:7] }}</a></strong></tt></center>
|
<center><tt>RaSCSI version: <strong>{{ version }} <a href="https://github.com/akuker/RASCSI/commit/{{ running_env['git'] }}" target="_blank">{{ running_env["git"][:7] }}</a></strong></tt></center>
|
||||||
<center><tt>Pi environment: {{ running_env["env"] }}</tt></center>
|
<center><tt>Pi environment: {{ running_env["env"] }}</tt></center>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
164
src/web/web.py
164
src/web/web.py
@ -16,6 +16,7 @@ from flask import (
|
|||||||
send_file,
|
send_file,
|
||||||
send_from_directory,
|
send_from_directory,
|
||||||
make_response,
|
make_response,
|
||||||
|
session,
|
||||||
)
|
)
|
||||||
|
|
||||||
from file_cmds import (
|
from file_cmds import (
|
||||||
@ -42,6 +43,7 @@ from pi_cmds import (
|
|||||||
disk_space,
|
disk_space,
|
||||||
get_ip_address,
|
get_ip_address,
|
||||||
introspect_file,
|
introspect_file,
|
||||||
|
auth_active,
|
||||||
)
|
)
|
||||||
from ractl_cmds import (
|
from ractl_cmds import (
|
||||||
attach_image,
|
attach_image,
|
||||||
@ -71,6 +73,7 @@ from settings import (
|
|||||||
DRIVE_PROPERTIES_FILE,
|
DRIVE_PROPERTIES_FILE,
|
||||||
REMOVABLE_DEVICE_TYPES,
|
REMOVABLE_DEVICE_TYPES,
|
||||||
RESERVATIONS,
|
RESERVATIONS,
|
||||||
|
AUTH_GROUP,
|
||||||
)
|
)
|
||||||
|
|
||||||
APP = Flask(__name__)
|
APP = Flask(__name__)
|
||||||
@ -111,6 +114,11 @@ def index():
|
|||||||
[ARCHIVE_FILE_SUFFIX]
|
[ARCHIVE_FILE_SUFFIX]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if "username" in session:
|
||||||
|
username = session["username"]
|
||||||
|
else:
|
||||||
|
username = None
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
"index.html",
|
"index.html",
|
||||||
bridge_configured=is_bridge_setup(),
|
bridge_configured=is_bridge_setup(),
|
||||||
@ -141,6 +149,8 @@ def index():
|
|||||||
cdrom_file_suffix=tuple(server_info["sccd"]),
|
cdrom_file_suffix=tuple(server_info["sccd"]),
|
||||||
removable_file_suffix=tuple(server_info["scrm"]),
|
removable_file_suffix=tuple(server_info["scrm"]),
|
||||||
mo_file_suffix=tuple(server_info["scmo"]),
|
mo_file_suffix=tuple(server_info["scmo"]),
|
||||||
|
username=username,
|
||||||
|
auth_active=auth_active()["status"],
|
||||||
ARCHIVE_FILE_SUFFIX=ARCHIVE_FILE_SUFFIX,
|
ARCHIVE_FILE_SUFFIX=ARCHIVE_FILE_SUFFIX,
|
||||||
PROPERTIES_SUFFIX=PROPERTIES_SUFFIX,
|
PROPERTIES_SUFFIX=PROPERTIES_SUFFIX,
|
||||||
REMOVABLE_DEVICE_TYPES=REMOVABLE_DEVICE_TYPES,
|
REMOVABLE_DEVICE_TYPES=REMOVABLE_DEVICE_TYPES,
|
||||||
@ -192,6 +202,11 @@ def drive_list():
|
|||||||
cd_conf = sorted(cd_conf, key=lambda x: x["name"].lower())
|
cd_conf = sorted(cd_conf, key=lambda x: x["name"].lower())
|
||||||
rm_conf = sorted(rm_conf, key=lambda x: x["name"].lower())
|
rm_conf = sorted(rm_conf, key=lambda x: x["name"].lower())
|
||||||
|
|
||||||
|
if "username" in session:
|
||||||
|
username = session["username"]
|
||||||
|
else:
|
||||||
|
username = None
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
"drives.html",
|
"drives.html",
|
||||||
files=sorted_image_files,
|
files=sorted_image_files,
|
||||||
@ -203,15 +218,46 @@ def drive_list():
|
|||||||
version=server_info["version"],
|
version=server_info["version"],
|
||||||
free_disk=int(disk["free"] / 1024 / 1024),
|
free_disk=int(disk["free"] / 1024 / 1024),
|
||||||
cdrom_file_suffix=tuple(server_info["sccd"]),
|
cdrom_file_suffix=tuple(server_info["sccd"]),
|
||||||
|
username=username,
|
||||||
|
auth_active=auth_active()["status"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@APP.route('/pwa/<path:path>')
|
@APP.route("/login", methods=["POST"])
|
||||||
|
def login():
|
||||||
|
"""
|
||||||
|
Uses simplepam to authenticate against Linux users
|
||||||
|
"""
|
||||||
|
username = request.form["username"]
|
||||||
|
password = request.form["password"]
|
||||||
|
|
||||||
|
from simplepam import authenticate
|
||||||
|
from grp import getgrall
|
||||||
|
|
||||||
|
groups = [g.gr_name for g in getgrall() if username in g.gr_mem]
|
||||||
|
if AUTH_GROUP in groups:
|
||||||
|
if authenticate(str(username), str(password)):
|
||||||
|
session["username"] = request.form["username"]
|
||||||
|
return redirect(url_for("index"))
|
||||||
|
flash(f"You must log in with credentials for a user in the '{AUTH_GROUP}' group!", "error")
|
||||||
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
|
|
||||||
|
@APP.route("/logout")
|
||||||
|
def logout():
|
||||||
|
"""
|
||||||
|
Removes the logged in user from the session
|
||||||
|
"""
|
||||||
|
session.pop("username", None)
|
||||||
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
|
|
||||||
|
@APP.route("/pwa/<path:path>")
|
||||||
def send_pwa_files(path):
|
def send_pwa_files(path):
|
||||||
"""
|
"""
|
||||||
Sets up mobile web resources
|
Sets up mobile web resources
|
||||||
"""
|
"""
|
||||||
return send_from_directory('pwa', path)
|
return send_from_directory("pwa", path)
|
||||||
|
|
||||||
|
|
||||||
@APP.route("/drive/create", methods=["POST"])
|
@APP.route("/drive/create", methods=["POST"])
|
||||||
@ -219,6 +265,11 @@ def drive_create():
|
|||||||
"""
|
"""
|
||||||
Creates the image and properties file pair
|
Creates the image and properties file pair
|
||||||
"""
|
"""
|
||||||
|
auth = auth_active()
|
||||||
|
if auth["status"] and "username" not in session:
|
||||||
|
flash(auth["msg"], "error")
|
||||||
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
vendor = request.form.get("vendor")
|
vendor = request.form.get("vendor")
|
||||||
product = request.form.get("product")
|
product = request.form.get("product")
|
||||||
revision = request.form.get("revision")
|
revision = request.form.get("revision")
|
||||||
@ -257,6 +308,11 @@ def drive_cdrom():
|
|||||||
"""
|
"""
|
||||||
Creates a properties file for a CD-ROM image
|
Creates a properties file for a CD-ROM image
|
||||||
"""
|
"""
|
||||||
|
auth = auth_active()
|
||||||
|
if auth["status"] and "username" not in session:
|
||||||
|
flash(auth["msg"], "error")
|
||||||
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
vendor = request.form.get("vendor")
|
vendor = request.form.get("vendor")
|
||||||
product = request.form.get("product")
|
product = request.form.get("product")
|
||||||
revision = request.form.get("revision")
|
revision = request.form.get("revision")
|
||||||
@ -285,6 +341,11 @@ def config_save():
|
|||||||
"""
|
"""
|
||||||
Saves a config file to disk
|
Saves a config file to disk
|
||||||
"""
|
"""
|
||||||
|
auth = auth_active()
|
||||||
|
if auth["status"] and "username" not in session:
|
||||||
|
flash(auth["msg"], "error")
|
||||||
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
file_name = request.form.get("name") or "default"
|
file_name = request.form.get("name") or "default"
|
||||||
file_name = f"{file_name}.{CONFIG_FILE_SUFFIX}"
|
file_name = f"{file_name}.{CONFIG_FILE_SUFFIX}"
|
||||||
|
|
||||||
@ -302,6 +363,11 @@ def config_load():
|
|||||||
"""
|
"""
|
||||||
Loads a config file from disk
|
Loads a config file from disk
|
||||||
"""
|
"""
|
||||||
|
auth = auth_active()
|
||||||
|
if auth["status"] and "username" not in session:
|
||||||
|
flash(auth["msg"], "error")
|
||||||
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
file_name = request.form.get("name")
|
file_name = request.form.get("name")
|
||||||
|
|
||||||
if "load" in request.form:
|
if "load" in request.form:
|
||||||
@ -354,6 +420,11 @@ def log_level():
|
|||||||
"""
|
"""
|
||||||
Sets RaSCSI backend log level
|
Sets RaSCSI backend log level
|
||||||
"""
|
"""
|
||||||
|
auth = auth_active()
|
||||||
|
if auth["status"] and "username" not in session:
|
||||||
|
flash(auth["msg"], "error")
|
||||||
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
level = request.form.get("level") or "info"
|
level = request.form.get("level") or "info"
|
||||||
|
|
||||||
process = set_log_level(level)
|
process = set_log_level(level)
|
||||||
@ -370,6 +441,11 @@ def daynaport_attach():
|
|||||||
"""
|
"""
|
||||||
Attaches a DaynaPORT ethernet adapter device
|
Attaches a DaynaPORT ethernet adapter device
|
||||||
"""
|
"""
|
||||||
|
auth = auth_active()
|
||||||
|
if auth["status"] and "username" not in session:
|
||||||
|
flash(auth["msg"], "error")
|
||||||
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
scsi_id = request.form.get("scsi_id")
|
scsi_id = request.form.get("scsi_id")
|
||||||
interface = request.form.get("if")
|
interface = request.form.get("if")
|
||||||
ip_addr = request.form.get("ip")
|
ip_addr = request.form.get("ip")
|
||||||
@ -414,6 +490,11 @@ def attach():
|
|||||||
"""
|
"""
|
||||||
Attaches a file image as a device
|
Attaches a file image as a device
|
||||||
"""
|
"""
|
||||||
|
auth = auth_active()
|
||||||
|
if auth["status"] and "username" not in session:
|
||||||
|
flash(auth["msg"], "error")
|
||||||
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
file_name = request.form.get("file_name")
|
file_name = request.form.get("file_name")
|
||||||
file_size = request.form.get("file_size")
|
file_size = request.form.get("file_size")
|
||||||
scsi_id = request.form.get("scsi_id")
|
scsi_id = request.form.get("scsi_id")
|
||||||
@ -466,6 +547,11 @@ def detach_all_devices():
|
|||||||
"""
|
"""
|
||||||
Detaches all currently attached devices
|
Detaches all currently attached devices
|
||||||
"""
|
"""
|
||||||
|
auth = auth_active()
|
||||||
|
if auth["status"] and "username" not in session:
|
||||||
|
flash(auth["msg"], "error")
|
||||||
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
process = detach_all()
|
process = detach_all()
|
||||||
if process["status"]:
|
if process["status"]:
|
||||||
flash("Detached all SCSI devices")
|
flash("Detached all SCSI devices")
|
||||||
@ -480,6 +566,11 @@ def detach():
|
|||||||
"""
|
"""
|
||||||
Detaches a specified device
|
Detaches a specified device
|
||||||
"""
|
"""
|
||||||
|
auth = auth_active()
|
||||||
|
if auth["status"] and "username" not in session:
|
||||||
|
flash(auth["msg"], "error")
|
||||||
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
scsi_id = request.form.get("scsi_id")
|
scsi_id = request.form.get("scsi_id")
|
||||||
unit = request.form.get("unit")
|
unit = request.form.get("unit")
|
||||||
process = detach_by_id(scsi_id, unit)
|
process = detach_by_id(scsi_id, unit)
|
||||||
@ -497,6 +588,11 @@ def eject():
|
|||||||
"""
|
"""
|
||||||
Ejects a specified removable device image, but keeps the device attached
|
Ejects a specified removable device image, but keeps the device attached
|
||||||
"""
|
"""
|
||||||
|
auth = auth_active()
|
||||||
|
if auth["status"] and "username" not in session:
|
||||||
|
flash(auth["msg"], "error")
|
||||||
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
scsi_id = request.form.get("scsi_id")
|
scsi_id = request.form.get("scsi_id")
|
||||||
unit = request.form.get("unit")
|
unit = request.form.get("unit")
|
||||||
|
|
||||||
@ -549,6 +645,11 @@ def reserve_id():
|
|||||||
"""
|
"""
|
||||||
Reserves a SCSI ID and stores the memo for that reservation
|
Reserves a SCSI ID and stores the memo for that reservation
|
||||||
"""
|
"""
|
||||||
|
auth = auth_active()
|
||||||
|
if auth["status"] and "username" not in session:
|
||||||
|
flash(auth["msg"], "error")
|
||||||
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
scsi_id = request.form.get("scsi_id")
|
scsi_id = request.form.get("scsi_id")
|
||||||
memo = request.form.get("memo")
|
memo = request.form.get("memo")
|
||||||
reserved_ids = get_reserved_ids()["ids"]
|
reserved_ids = get_reserved_ids()["ids"]
|
||||||
@ -567,6 +668,11 @@ def unreserve_id():
|
|||||||
"""
|
"""
|
||||||
Removes the reservation of a SCSI ID as well as the memo for the reservation
|
Removes the reservation of a SCSI ID as well as the memo for the reservation
|
||||||
"""
|
"""
|
||||||
|
auth = auth_active()
|
||||||
|
if auth["status"] and "username" not in session:
|
||||||
|
flash(auth["msg"], "error")
|
||||||
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
scsi_id = request.form.get("scsi_id")
|
scsi_id = request.form.get("scsi_id")
|
||||||
reserved_ids = get_reserved_ids()["ids"]
|
reserved_ids = get_reserved_ids()["ids"]
|
||||||
reserved_ids.remove(scsi_id)
|
reserved_ids.remove(scsi_id)
|
||||||
@ -584,6 +690,11 @@ def restart():
|
|||||||
"""
|
"""
|
||||||
Restarts the Pi
|
Restarts the Pi
|
||||||
"""
|
"""
|
||||||
|
auth = auth_active()
|
||||||
|
if auth["status"] and "username" not in session:
|
||||||
|
flash(auth["msg"], "error")
|
||||||
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
detach_all()
|
detach_all()
|
||||||
flash("Safely detached all devices.")
|
flash("Safely detached all devices.")
|
||||||
flash("Rebooting the Pi momentarily...")
|
flash("Rebooting the Pi momentarily...")
|
||||||
@ -596,6 +707,11 @@ def rascsi_restart():
|
|||||||
"""
|
"""
|
||||||
Restarts the RaSCSI backend service
|
Restarts the RaSCSI backend service
|
||||||
"""
|
"""
|
||||||
|
auth = auth_active()
|
||||||
|
if auth["status"] and "username" not in session:
|
||||||
|
flash(auth["msg"], "error")
|
||||||
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
detach_all()
|
detach_all()
|
||||||
flash("Safely detached all devices.")
|
flash("Safely detached all devices.")
|
||||||
flash("Restarting RaSCSI Service...")
|
flash("Restarting RaSCSI Service...")
|
||||||
@ -609,6 +725,11 @@ def shutdown():
|
|||||||
"""
|
"""
|
||||||
Shuts down the Pi
|
Shuts down the Pi
|
||||||
"""
|
"""
|
||||||
|
auth = auth_active()
|
||||||
|
if auth["status"] and "username" not in session:
|
||||||
|
flash(auth["msg"], "error")
|
||||||
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
detach_all()
|
detach_all()
|
||||||
flash("Safely detached all devices.")
|
flash("Safely detached all devices.")
|
||||||
flash("Shutting down the Pi momentarily...")
|
flash("Shutting down the Pi momentarily...")
|
||||||
@ -621,6 +742,11 @@ def download_to_iso():
|
|||||||
"""
|
"""
|
||||||
Downloads a remote file and creates a CD-ROM image formatted with HFS that contains the file
|
Downloads a remote file and creates a CD-ROM image formatted with HFS that contains the file
|
||||||
"""
|
"""
|
||||||
|
auth = auth_active()
|
||||||
|
if auth["status"] and "username" not in session:
|
||||||
|
flash(auth["msg"], "error")
|
||||||
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
scsi_id = request.form.get("scsi_id")
|
scsi_id = request.form.get("scsi_id")
|
||||||
url = request.form.get("url")
|
url = request.form.get("url")
|
||||||
|
|
||||||
@ -647,6 +773,11 @@ def download_img():
|
|||||||
"""
|
"""
|
||||||
Downloads a remote file onto the images dir on the Pi
|
Downloads a remote file onto the images dir on the Pi
|
||||||
"""
|
"""
|
||||||
|
auth = auth_active()
|
||||||
|
if auth["status"] and "username" not in session:
|
||||||
|
flash(auth["msg"], "error")
|
||||||
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
url = request.form.get("url")
|
url = request.form.get("url")
|
||||||
server_info = get_server_info()
|
server_info = get_server_info()
|
||||||
process = download_to_dir(url, server_info["image_dir"])
|
process = download_to_dir(url, server_info["image_dir"])
|
||||||
@ -664,6 +795,11 @@ def download_afp():
|
|||||||
"""
|
"""
|
||||||
Downloads a remote file onto the AFP shared dir on the Pi
|
Downloads a remote file onto the AFP shared dir on the Pi
|
||||||
"""
|
"""
|
||||||
|
auth = auth_active()
|
||||||
|
if auth["status"] and "username" not in session:
|
||||||
|
flash(auth["msg"], "error")
|
||||||
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
url = request.form.get("url")
|
url = request.form.get("url")
|
||||||
process = download_to_dir(url, AFP_DIR)
|
process = download_to_dir(url, AFP_DIR)
|
||||||
if process["status"]:
|
if process["status"]:
|
||||||
@ -681,6 +817,10 @@ def upload_file():
|
|||||||
Uploads a file from the local computer to the images dir on the Pi
|
Uploads a file from the local computer to the images dir on the Pi
|
||||||
Depending on the Dropzone.js JavaScript library
|
Depending on the Dropzone.js JavaScript library
|
||||||
"""
|
"""
|
||||||
|
auth = auth_active()
|
||||||
|
if auth["status"] and "username" not in session:
|
||||||
|
return make_response(auth["msg"], 403)
|
||||||
|
|
||||||
from werkzeug.utils import secure_filename
|
from werkzeug.utils import secure_filename
|
||||||
from os import path
|
from os import path
|
||||||
|
|
||||||
@ -729,6 +869,11 @@ def create_file():
|
|||||||
"""
|
"""
|
||||||
Creates an empty image file in the images dir
|
Creates an empty image file in the images dir
|
||||||
"""
|
"""
|
||||||
|
auth = auth_active()
|
||||||
|
if auth["status"] and "username" not in session:
|
||||||
|
flash(auth["msg"], "error")
|
||||||
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
file_name = request.form.get("file_name")
|
file_name = request.form.get("file_name")
|
||||||
size = (int(request.form.get("size")) * 1024 * 1024)
|
size = (int(request.form.get("size")) * 1024 * 1024)
|
||||||
file_type = request.form.get("type")
|
file_type = request.form.get("type")
|
||||||
@ -750,6 +895,11 @@ def download():
|
|||||||
"""
|
"""
|
||||||
Downloads a file from the Pi to the local computer
|
Downloads a file from the Pi to the local computer
|
||||||
"""
|
"""
|
||||||
|
auth = auth_active()
|
||||||
|
if auth["status"] and "username" not in session:
|
||||||
|
flash(auth["msg"], "error")
|
||||||
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
image = request.form.get("file")
|
image = request.form.get("file")
|
||||||
return send_file(image, as_attachment=True)
|
return send_file(image, as_attachment=True)
|
||||||
|
|
||||||
@ -759,6 +909,11 @@ def delete():
|
|||||||
"""
|
"""
|
||||||
Deletes a specified file in the images dir
|
Deletes a specified file in the images dir
|
||||||
"""
|
"""
|
||||||
|
auth = auth_active()
|
||||||
|
if auth["status"] and "username" not in session:
|
||||||
|
flash(auth["msg"], "error")
|
||||||
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
file_name = request.form.get("image")
|
file_name = request.form.get("image")
|
||||||
|
|
||||||
process = delete_image(file_name)
|
process = delete_image(file_name)
|
||||||
@ -787,6 +942,11 @@ def unzip():
|
|||||||
"""
|
"""
|
||||||
Unzips a specified zip file
|
Unzips a specified zip file
|
||||||
"""
|
"""
|
||||||
|
auth = auth_active()
|
||||||
|
if auth["status"] and "username" not in session:
|
||||||
|
flash(auth["msg"], "error")
|
||||||
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
zip_file = request.form.get("zip_file")
|
zip_file = request.form.get("zip_file")
|
||||||
zip_member = request.form.get("zip_member") or False
|
zip_member = request.form.get("zip_member") or False
|
||||||
zip_members = request.form.get("zip_members") or False
|
zip_members = request.form.get("zip_members") or False
|
||||||
|
Loading…
Reference in New Issue
Block a user