mirror of
https://codeberg.org/Mo8it/AdvLabDB.git
synced 2024-12-20 23:41:20 +00:00
Organize docs and scripts
This commit is contained in:
parent
daf0b6287f
commit
1f89e4aaed
27 changed files with 520 additions and 454 deletions
16
advlabdb/scripts/maintain/root_update.py
Normal file
16
advlabdb/scripts/maintain/root_update.py
Normal file
|
@ -0,0 +1,16 @@
|
|||
from advlabdb.scripts.maintain.shared import show_update_datetime
|
||||
from advlabdb.scripts.terminal_utils import box, run
|
||||
|
||||
|
||||
def main():
|
||||
show_update_datetime()
|
||||
|
||||
box("Update system packages")
|
||||
run("sudo apt update")
|
||||
run("sudo apt upgrade -y")
|
||||
|
||||
run("sudo reboot")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
11
advlabdb/scripts/maintain/shared.py
Normal file
11
advlabdb/scripts/maintain/shared.py
Normal file
|
@ -0,0 +1,11 @@
|
|||
from datetime import datetime
|
||||
|
||||
from advlabdb.scripts.terminal_utils import box, spaced_hl
|
||||
|
||||
|
||||
def show_update_datetime():
|
||||
spaced_hl()
|
||||
|
||||
dt = datetime.now().strftime("%d.%m.%Y %H:%M:%S")
|
||||
|
||||
box(dt, "Update on")
|
20
advlabdb/scripts/maintain/update_docs.py
Normal file
20
advlabdb/scripts/maintain/update_docs.py
Normal file
|
@ -0,0 +1,20 @@
|
|||
# TODO: Port to Python
|
||||
# Needed packages: asciidoctor
|
||||
|
||||
# List of documentation files
|
||||
# DOC_FILE_NAMES=$(fd -d 1 -t f --extension adoc --exclude "README.adoc")
|
||||
#
|
||||
# for doc_file_name in "${DOC_FILE_NAMES[@]}"; do
|
||||
# DOC_FILE_NAME_WITHOUT_EXTENSION=${doc_file_name::-5}
|
||||
# OUTPUT_PATH=../advlabdb/templates/docs/$DOC_FILE_NAME_WITHOUT_EXTENSION.html
|
||||
#
|
||||
# # Convert to html with asciidoctor
|
||||
# asciidoctor -v --backend html5 "$doc_file_name" -o "$OUTPUT_PATH"
|
||||
#
|
||||
# # Add the Jinja raw tag
|
||||
# sed -i "1i {% raw %}" "$OUTPUT_PATH"
|
||||
# echo -e "\n{% endraw %}" >>"$OUTPUT_PATH"
|
||||
#
|
||||
# # Done
|
||||
# echo "Generated $OUTPUT_PATH"
|
||||
# done
|
23
advlabdb/scripts/maintain/user_update.py
Normal file
23
advlabdb/scripts/maintain/user_update.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
from advlabdb.scripts.maintain.shared import show_update_datetime
|
||||
from advlabdb.scripts.setup.shared import LOCAL_BIN, install_latest_pipx, poetry_update
|
||||
from advlabdb.scripts.terminal_utils import box, run
|
||||
|
||||
|
||||
def main():
|
||||
show_update_datetime()
|
||||
|
||||
box("Upgrade pipx")
|
||||
install_latest_pipx()
|
||||
|
||||
box("Upgrade pipx packages")
|
||||
pipx_bin = LOCAL_BIN / "pipx"
|
||||
run(f"{pipx_bin} upgrade-all --include-injected")
|
||||
|
||||
# TODO: Backup
|
||||
|
||||
box("Install latest Poetry packages")
|
||||
poetry_update()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,77 +1,16 @@
|
|||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from email_validator import validate_email
|
||||
from flask_security import hash_password
|
||||
|
||||
from advlabdb import app, db, user_datastore
|
||||
from advlabdb.independent_funs import randomPassword
|
||||
from advlabdb.models import MAX_YEAR, MIN_YEAR, Admin, Semester
|
||||
|
||||
scripts_dir = Path(__file__).parent.absolute() / "scripts"
|
||||
|
||||
sys.path.insert(0, str(scripts_dir))
|
||||
|
||||
from shared import box
|
||||
|
||||
|
||||
def validating_input(
|
||||
prompt,
|
||||
options=None,
|
||||
format_function=lambda ans: ans,
|
||||
check_constraints_function=lambda ans: True,
|
||||
):
|
||||
if options is not None:
|
||||
prompt += " ["
|
||||
|
||||
for opt in options[:-1]:
|
||||
prompt += opt + "/"
|
||||
|
||||
prompt += options[-1] + "]: "
|
||||
|
||||
lowered_options = [opt.lower() for opt in options]
|
||||
|
||||
def adj_check_constraints_function(ans):
|
||||
return ans.lower() in lowered_options and check_constraints_function(ans)
|
||||
|
||||
else:
|
||||
prompt += ": "
|
||||
adj_check_constraints_function = check_constraints_function
|
||||
|
||||
ans = None
|
||||
first_run = True
|
||||
|
||||
while ans is None or not adj_check_constraints_function(ans):
|
||||
if not first_run:
|
||||
print("Invalid input!")
|
||||
else:
|
||||
first_run = False
|
||||
|
||||
ans = input(prompt)
|
||||
try:
|
||||
ans = format_function(ans)
|
||||
except Exception as ex:
|
||||
ans = None
|
||||
|
||||
return ans
|
||||
|
||||
|
||||
def confirm(prompt):
|
||||
ans = validating_input(
|
||||
prompt,
|
||||
options=("y", "n"),
|
||||
format_function=lambda ans: ans.lower(),
|
||||
)
|
||||
|
||||
if ans == "y":
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
from advlabdb.scripts.terminal_utils import box, confirm, validating_input
|
||||
|
||||
|
||||
def main():
|
||||
print("This script should only be used to initialize the database after setting up a server")
|
||||
print("The old database will be DELETED and a new database will be created.")
|
||||
|
||||
if not confirm("Are you sure that you want to continue?"):
|
||||
print("Aborted!")
|
||||
return
|
||||
|
@ -137,7 +76,7 @@ def main():
|
|||
|
||||
box(admin_password, "Admin password")
|
||||
|
||||
print("Done! Successfull database initialization.")
|
||||
print("Done database initialization!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
97
advlabdb/scripts/setup/logged_server_setup.py
Normal file
97
advlabdb/scripts/setup/logged_server_setup.py
Normal file
|
@ -0,0 +1,97 @@
|
|||
from pathlib import Path
|
||||
|
||||
from advlabdb.scripts.setup.shared import (
|
||||
LOCAL_BIN,
|
||||
LOGS_DIR,
|
||||
install_latest_pipx,
|
||||
poetry_update,
|
||||
)
|
||||
from advlabdb.scripts.terminal_utils import run, step
|
||||
|
||||
|
||||
def main():
|
||||
file_dir = Path(__file__).parent.absolute()
|
||||
|
||||
step("Update system packages")
|
||||
run("sudo apt update")
|
||||
run("sudo apt dist-upgrade")
|
||||
|
||||
step("Remove unused packages")
|
||||
run("sudo apt autoremove")
|
||||
|
||||
step("Install needed system packages")
|
||||
run("sudo apt install python3 python3-pip python3-venv ufw nginx systemd asciidoctor -y")
|
||||
|
||||
step("Install optional system packages")
|
||||
run("sudo apt install htop")
|
||||
|
||||
step("Setup firewall")
|
||||
run("sudo ufw default allow outgoing")
|
||||
run("sudo ufw default deny incoming")
|
||||
run("sudo ufw allow ssh")
|
||||
run("sudo ufw allow http/tcp")
|
||||
run("sudo ufw allow https/tcp")
|
||||
run("sudo ufw enable")
|
||||
run("sudo ufw status")
|
||||
|
||||
step("Enable Gunicorn")
|
||||
gunicorn_service_file = file_dir / "gunicorn.service"
|
||||
run(f"sudo cp -v {gunicorn_service_file} /etc/systemd/system/")
|
||||
run("sudo systemctl enable gunicorn")
|
||||
|
||||
step("Setup Nginx")
|
||||
for dir_appendix in ("available", "enabled"):
|
||||
run(f"sudo rm -v /etc/nginx/sites-{dir_appendix}/default")
|
||||
|
||||
nginx_conf_file = file_dir / "advlabdb.conf"
|
||||
run(f"sudo cp -v {nginx_conf_file} /etc/nginx/sites-available/")
|
||||
run("sudo ln -v -s /etc/nginx/sites-available/advlabdb.conf /etc/nginx/sites-enabled/")
|
||||
run("sudo systemctl enable nginx")
|
||||
|
||||
step("Install pipx")
|
||||
install_latest_pipx()
|
||||
|
||||
pipx_bin = LOCAL_BIN / "pipx"
|
||||
|
||||
step("Install Poetry")
|
||||
run(f"{pipx_bin} install poetry")
|
||||
# Place virtual environments in the root directory of the project
|
||||
# The virtual environment will then be found in /home/admin/advlabdb/.venv
|
||||
poetry_bin = LOCAL_BIN / "poetry"
|
||||
run(f"{poetry_bin} config virtualenvs.in-project true")
|
||||
|
||||
step("Install Certbot")
|
||||
run(f"{pipx_bin} install certbot")
|
||||
run(f"{pipx_bin} inject certbot certbot-nginx")
|
||||
|
||||
step("Setup Certbot")
|
||||
certbot_bin = LOCAL_BIN / "certbot"
|
||||
run(f"sudo {certbot_bin} --nginx")
|
||||
run(
|
||||
f"echo \"0 0,12 * * * root python3 -c 'import random; import time; time.sleep(random.random() * 3600)' && sudo {certbot_bin} renew -q\" | sudo tee -a /etc/crontab"
|
||||
)
|
||||
|
||||
step("Setup update cron jobs")
|
||||
|
||||
user_update_script = file_dir / "user_update.py"
|
||||
user_update_log = LOGS_DIR / "user_update.log"
|
||||
# Every Sunday at 04:00
|
||||
run(f'echo "0 4 * * 0 admin python3 -u {user_update_script} &>> {user_update_log}" | sudo tee -a /etc/crontab')
|
||||
|
||||
root_update_script = file_dir / "root_update.py"
|
||||
root_update_log = LOGS_DIR / "root_update.log"
|
||||
# Every Sunday at 04:15
|
||||
run(f'echo "15 4 * * 0 root python3 -u {root_update_script} &>> {root_update_log}" | sudo tee -a /etc/crontab')
|
||||
|
||||
step("Install latest Poetry packages")
|
||||
poetry_update()
|
||||
|
||||
step("Deactivate the 'root' user")
|
||||
run("sudo passwd -l root")
|
||||
|
||||
step("Reboot")
|
||||
run("sudo reboot")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
20
advlabdb/scripts/setup/server_setup.py
Normal file
20
advlabdb/scripts/setup/server_setup.py
Normal file
|
@ -0,0 +1,20 @@
|
|||
from advlabdb.scripts.setup.logged_server_setup import (
|
||||
__file__ as logged_server_setup_script,
|
||||
)
|
||||
from advlabdb.scripts.setup.shared import LOGS_DIR
|
||||
from advlabdb.scripts.terminal_utils import run
|
||||
|
||||
|
||||
def main():
|
||||
# Create logs directory
|
||||
run(f"sudo mkdir -v -p {LOGS_DIR}")
|
||||
run(f"sudo chown -R admin:admin {LOGS_DIR}")
|
||||
|
||||
log_file = LOGS_DIR / "server_setup.log"
|
||||
|
||||
# Start actual server setup script with logging
|
||||
run(f"python3 -u {logged_server_setup_script} | tee {log_file}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
17
advlabdb/scripts/setup/shared.py
Normal file
17
advlabdb/scripts/setup/shared.py
Normal file
|
@ -0,0 +1,17 @@
|
|||
from pathlib import Path
|
||||
|
||||
from advlabdb import __file__ as advlabdb_init_path # Points to __init__.py
|
||||
from advlabdb.scripts.terminal_utils import run
|
||||
|
||||
LOCAL_BIN = Path("/home/admin/.local/bin/")
|
||||
LOGS_DIR = Path("/var/log/advlabdb")
|
||||
|
||||
|
||||
def install_latest_pipx():
|
||||
run("pip install --user --upgrade pipx")
|
||||
|
||||
|
||||
def poetry_update():
|
||||
poetry_bin = LOCAL_BIN / "poetry"
|
||||
advlabdb_root_dir = Path(advlabdb_init_path).parents[1]
|
||||
run(f"{poetry_bin} update", cwd=advlabdb_root_dir)
|
95
advlabdb/scripts/terminal_utils.py
Normal file
95
advlabdb/scripts/terminal_utils.py
Normal file
|
@ -0,0 +1,95 @@
|
|||
import subprocess
|
||||
from getpass import getpass
|
||||
|
||||
|
||||
def run(command, **kwargs):
|
||||
return subprocess.run(command, shell=True, **kwargs)
|
||||
|
||||
|
||||
def box(message, context=None):
|
||||
text_line = "| "
|
||||
|
||||
if context is not None:
|
||||
text_line += context + ": "
|
||||
|
||||
text_line += message + " |"
|
||||
|
||||
separator = "=" * len(text_line)
|
||||
|
||||
print()
|
||||
print(separator)
|
||||
print(text_line)
|
||||
print(separator)
|
||||
print()
|
||||
|
||||
|
||||
def step(message):
|
||||
continue_message = "-> Press ENTER to continue or Ctrl+C to interrupt the script <-"
|
||||
upper_separator = "_" * len(continue_message)
|
||||
|
||||
print()
|
||||
print(upper_separator)
|
||||
|
||||
box(message, "Next step")
|
||||
|
||||
print(continue_message)
|
||||
getpass("")
|
||||
print()
|
||||
|
||||
|
||||
def spaced_hl():
|
||||
print("\n\n" + "_" * 20 + "\n\n")
|
||||
|
||||
|
||||
def validating_input(
|
||||
prompt,
|
||||
options=None,
|
||||
format_function=lambda ans: ans,
|
||||
check_constraints_function=lambda ans: True,
|
||||
):
|
||||
if options is not None:
|
||||
prompt += " ["
|
||||
|
||||
for opt in options[:-1]:
|
||||
prompt += opt + "/"
|
||||
|
||||
prompt += options[-1] + "]: "
|
||||
|
||||
lowered_options = [opt.lower() for opt in options]
|
||||
|
||||
def adj_check_constraints_function(ans):
|
||||
return ans.lower() in lowered_options and check_constraints_function(ans)
|
||||
|
||||
else:
|
||||
prompt += ": "
|
||||
adj_check_constraints_function = check_constraints_function
|
||||
|
||||
ans = None
|
||||
first_run = True
|
||||
|
||||
while ans is None or not adj_check_constraints_function(ans):
|
||||
if not first_run:
|
||||
print("Invalid input!")
|
||||
else:
|
||||
first_run = False
|
||||
|
||||
ans = input(prompt)
|
||||
try:
|
||||
ans = format_function(ans)
|
||||
except Exception as ex:
|
||||
ans = None
|
||||
|
||||
return ans
|
||||
|
||||
|
||||
def confirm(prompt):
|
||||
ans = validating_input(
|
||||
prompt,
|
||||
options=("y", "n"),
|
||||
format_function=lambda ans: ans.lower(),
|
||||
)
|
||||
|
||||
if ans == "y":
|
||||
return True
|
||||
else:
|
||||
return False
|
150
advlabdb/scripts/test/test_database.py
Normal file
150
advlabdb/scripts/test/test_database.py
Normal file
|
@ -0,0 +1,150 @@
|
|||
from datetime import date
|
||||
|
||||
from flask_security import hash_password
|
||||
|
||||
from advlabdb import app, db, user_datastore
|
||||
from advlabdb.models import *
|
||||
|
||||
|
||||
def main():
|
||||
with app.app_context():
|
||||
with db.session.begin():
|
||||
db.drop_all()
|
||||
db.create_all()
|
||||
|
||||
program1 = Program(label="BS")
|
||||
program2 = Program(label="MS")
|
||||
program3 = Program(label="BE")
|
||||
|
||||
db.session.add(program1)
|
||||
db.session.add(program2)
|
||||
db.session.add(program3)
|
||||
|
||||
sem1 = Semester.customInit(label="SS", year=22)
|
||||
sem2 = Semester.customInit(label="WS", year=22)
|
||||
|
||||
db.session.add(sem1)
|
||||
db.session.add(sem2)
|
||||
|
||||
partKwargs = [
|
||||
{"program": program1, "number": 1},
|
||||
{"program": program1, "number": 2},
|
||||
{"program": program2, "number": 1},
|
||||
{"program": program2, "number": 2},
|
||||
{"program": program3, "number": 1},
|
||||
]
|
||||
for kwargs in partKwargs:
|
||||
db.session.add(Part(semester=sem1, **kwargs))
|
||||
|
||||
sem2.transferPartsFrom(sem1)
|
||||
|
||||
part1 = sem2.parts[0]
|
||||
part2 = sem2.parts[2]
|
||||
|
||||
student1 = Student(student_number=123, first_name="Mo", last_name="Bit", uni_email="m@test.com")
|
||||
student2 = Student(student_number=1232, first_name="Mo2", last_name="Bit", uni_email="m2@test.com")
|
||||
student3 = Student(student_number=1233, first_name="Mo3", last_name="Bit3", uni_email="m3@test.com")
|
||||
|
||||
db.session.add(student1)
|
||||
db.session.add(student2)
|
||||
db.session.add(student3)
|
||||
|
||||
ps1 = PartStudent.customInit(student=student1, part=part1)
|
||||
ps2 = PartStudent.customInit(student=student2, part=part1)
|
||||
ps3 = PartStudent.customInit(student=student3, part=part2)
|
||||
|
||||
db.session.add(ps1)
|
||||
db.session.add(ps2)
|
||||
db.session.add(ps3)
|
||||
|
||||
g1 = Group.customInit(part_students=[ps1, ps2])
|
||||
g2 = Group.customInit(part_students=[ps3])
|
||||
|
||||
db.session.add(g1)
|
||||
db.session.add(g2)
|
||||
|
||||
ex1 = Experiment(
|
||||
number=1,
|
||||
program=program1,
|
||||
title="exp",
|
||||
room="123",
|
||||
building="phy",
|
||||
responsibility="none",
|
||||
duration_in_days=2,
|
||||
)
|
||||
|
||||
ex2 = Experiment(
|
||||
number=1,
|
||||
program=program2,
|
||||
title="exp2",
|
||||
room="123",
|
||||
building="phy",
|
||||
responsibility="none",
|
||||
duration_in_days=2,
|
||||
)
|
||||
|
||||
db.session.add(ex1)
|
||||
db.session.add(ex2)
|
||||
|
||||
sx1 = SemesterExperiment(experiment=ex1, semester=sem2)
|
||||
sx2 = SemesterExperiment(experiment=ex2, semester=sem2)
|
||||
|
||||
db.session.add(sx1)
|
||||
db.session.add(sx2)
|
||||
|
||||
gx1 = GroupExperiment.customInit(semester_experiment=sx1, group=g1)
|
||||
gx2 = GroupExperiment.customInit(semester_experiment=sx2, group=g2)
|
||||
|
||||
db.session.add(gx1)
|
||||
db.session.add(gx2)
|
||||
|
||||
adminRole = user_datastore.create_role(name="admin")
|
||||
assistantRole = user_datastore.create_role(name="assistant")
|
||||
|
||||
admin_user = user_datastore.create_user(
|
||||
email="admin@advlabdb.de",
|
||||
password=hash_password("admin"),
|
||||
roles=[adminRole],
|
||||
first_name="Peter",
|
||||
last_name="Blümler",
|
||||
)
|
||||
|
||||
admin = Admin(user=admin_user)
|
||||
|
||||
db.session.add(admin)
|
||||
|
||||
us1 = user_datastore.create_user(
|
||||
email="test@protonmail.com",
|
||||
password=hash_password("h1"),
|
||||
roles=[assistantRole],
|
||||
first_name="As1",
|
||||
last_name="l",
|
||||
phone_number="012333212",
|
||||
mobile_phone_number="012334123",
|
||||
)
|
||||
us2 = user_datastore.create_user(
|
||||
email="test2@protonmail.com",
|
||||
password=hash_password("h2"),
|
||||
roles=[assistantRole],
|
||||
first_name="As2",
|
||||
last_name="l",
|
||||
)
|
||||
|
||||
as1 = Assistant(user=us1)
|
||||
as2 = Assistant(user=us2)
|
||||
|
||||
as1.semester_experiments.append(sx1)
|
||||
as2.semester_experiments.append(sx2)
|
||||
|
||||
db.session.add(as1)
|
||||
db.session.add(as2)
|
||||
|
||||
ap1 = Appointment.customInit(date=date(2021, 3, 21), special=True, group_experiment=gx1, assistant=as1)
|
||||
ap2 = Appointment.customInit(date=date(2021, 3, 22), special=True, group_experiment=gx2, assistant=as2)
|
||||
|
||||
db.session.add(ap1)
|
||||
db.session.add(ap2)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,23 +0,0 @@
|
|||
#!/usr/bin/bash
|
||||
|
||||
# Needed packages: fd (find alternative), asciidoctor
|
||||
|
||||
# You have to cd into the docs directory where this script is located before running it!
|
||||
|
||||
# List of documentation files
|
||||
DOC_FILE_NAMES=$(fd -d 1 -t f --extension adoc --exclude "README.adoc")
|
||||
|
||||
for doc_file_name in "${DOC_FILE_NAMES[@]}"; do
|
||||
DOC_FILE_NAME_WITHOUT_EXTENSION=${doc_file_name::-5}
|
||||
OUTPUT_PATH=../advlabdb/templates/docs/$DOC_FILE_NAME_WITHOUT_EXTENSION.html
|
||||
|
||||
# Convert to html with asciidoctor
|
||||
asciidoctor -v --backend html5 "$doc_file_name" -o "$OUTPUT_PATH"
|
||||
|
||||
# Add the Jinja raw tag
|
||||
sed -i "1i {% raw %}" "$OUTPUT_PATH"
|
||||
echo -e "\n{% endraw %}" >>"$OUTPUT_PATH"
|
||||
|
||||
# Done
|
||||
echo "Generated $OUTPUT_PATH"
|
||||
done
|
68
docs/user_docs/server_setup.adoc
Normal file
68
docs/user_docs/server_setup.adoc
Normal file
|
@ -0,0 +1,68 @@
|
|||
= Server setup
|
||||
|
||||
== Setup scripts
|
||||
|
||||
`ssh` as `root`:
|
||||
|
||||
[source,bash]
|
||||
----
|
||||
ssh root@SERVER_NAME
|
||||
----
|
||||
|
||||
Run the following (as root):
|
||||
|
||||
[source,bash]
|
||||
----
|
||||
# Install needed packages
|
||||
apt update
|
||||
apt install sudo python3 -y
|
||||
|
||||
# Add a sudo user with the name 'admin'
|
||||
sudo useradd admin
|
||||
sudo usermod -aG sudo admin
|
||||
sudo mkhomedir_helper admin
|
||||
|
||||
# Enter a new password for 'admin'
|
||||
sudo passwd admin
|
||||
|
||||
# Break the SSH connection
|
||||
exit
|
||||
----
|
||||
|
||||
Copy the repository to the server into `/home/admin/advlabdb`.
|
||||
|
||||
`ssh` again with the new user `admin` and password:
|
||||
|
||||
[source,bash]
|
||||
----
|
||||
ssh admin@SERVER_NAME
|
||||
----
|
||||
|
||||
Run the following:
|
||||
|
||||
[source,bash]
|
||||
----
|
||||
# Run server setup script
|
||||
python3 ~/advlabdb/scripts/server_setup.py
|
||||
----
|
||||
|
||||
Change server_name in advlabdb.conf
|
||||
|
||||
== Stop ssh to root
|
||||
// TODO: Add blocking password access
|
||||
|
||||
IMPORTANT: This step is important for security!
|
||||
|
||||
Change
|
||||
|
||||
----
|
||||
PermitRootLogin yes
|
||||
----
|
||||
|
||||
to
|
||||
|
||||
----
|
||||
PermitRootLogin no
|
||||
----
|
||||
|
||||
in the config file `/etc/ssh/sshd_config`
|
|
@ -1,93 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
script_dir = Path(__file__).parent.absolute()
|
||||
|
||||
sys.path.insert(0, str(script_dir))
|
||||
|
||||
from shared import install_latest_pipx, local_bin, poetry_update, run, step
|
||||
|
||||
logs_dir = Path("/var/log/advlabdb/")
|
||||
|
||||
step("Update system packages")
|
||||
run("sudo apt update")
|
||||
run("sudo apt dist-upgrade")
|
||||
|
||||
step("Remove unused packages")
|
||||
run("sudo apt autoremove")
|
||||
|
||||
step("Install needed system packages")
|
||||
run("sudo apt install python3 python3-pip python3-venv ufw nginx systemd -y")
|
||||
|
||||
step("Install optional system packages")
|
||||
run("sudo apt install htop")
|
||||
|
||||
step("Setup firewall")
|
||||
run("sudo ufw default allow outgoing")
|
||||
run("sudo ufw default deny incoming")
|
||||
run("sudo ufw allow ssh")
|
||||
run("sudo ufw allow http/tcp")
|
||||
# TODO: Setup https
|
||||
# run("sudo ufw allow https/tcp")
|
||||
run("sudo ufw enable")
|
||||
run("sudo ufw status")
|
||||
|
||||
step("Enable Gunicorn")
|
||||
gunicorn_service_file = script_dir / "gunicorn.service"
|
||||
run(f"sudo cp -v {gunicorn_service_file} /etc/systemd/system/")
|
||||
run("sudo systemctl enable gunicorn")
|
||||
|
||||
step("Setup Nginx")
|
||||
for dir_appendix in ("available", "enabled"):
|
||||
run(f"sudo rm -v /etc/nginx/sites-{dir_appendix}/default")
|
||||
|
||||
nginx_conf_file = script_dir / "advlabdb.conf"
|
||||
run(f"sudo cp -v {nginx_conf_file} /etc/nginx/sites-available/")
|
||||
run("sudo ln -v -s /etc/nginx/sites-available/advlabdb.conf /etc/nginx/sites-enabled/")
|
||||
run("sudo systemctl enable nginx")
|
||||
|
||||
step("Install pipx")
|
||||
install_latest_pipx()
|
||||
|
||||
pipx_bin = local_bin / "pipx"
|
||||
|
||||
step("Install Poetry")
|
||||
run(f"{pipx_bin} install poetry")
|
||||
# Place virtual environments in the root directory of the project
|
||||
# The virtual environment will then be found in /home/admin/advlabdb/.venv
|
||||
poetry_bin = local_bin / "poetry"
|
||||
run(f"{poetry_bin} config virtualenvs.in-project true")
|
||||
|
||||
step("Install Certbot")
|
||||
run(f"{pipx_bin} install certbot")
|
||||
run(f"{pipx_bin} inject certbot certbot-nginx")
|
||||
|
||||
step("Setup Certbot")
|
||||
certbot_bin = local_bin / "certbot"
|
||||
run(f"sudo {certbot_bin} --nginx")
|
||||
run(
|
||||
f"echo \"0 0,12 * * * root python3 -c 'import random; import time; time.sleep(random.random() * 3600)' && sudo {certbot_bin} renew -q\" | sudo tee -a /etc/crontab"
|
||||
)
|
||||
|
||||
step("Setup update cron jobs")
|
||||
|
||||
user_update_script = script_dir / "user_update.py"
|
||||
user_update_log = logs_dir / "user_update.log"
|
||||
# Every Sunday at 04:00
|
||||
run(f'echo "0 4 * * 0 admin python3 -u {user_update_script} &>> {user_update_log}" | sudo tee -a /etc/crontab')
|
||||
|
||||
root_update_script = script_dir / "root_update.py"
|
||||
root_update_log = logs_dir / "root_update.log"
|
||||
# Every Sunday at 04:15
|
||||
run(f'echo "15 4 * * 0 root python3 -u {root_update_script} &>> {root_update_log}" | sudo tee -a /etc/crontab')
|
||||
|
||||
step("Install latest Poetry packages")
|
||||
poetry_update(script_dir)
|
||||
|
||||
step("Deactivate the 'root' user")
|
||||
run("sudo passwd -l root")
|
||||
|
||||
step("Reboot")
|
||||
run("sudo reboot")
|
|
@ -1,23 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
script_dir = Path(__file__).parent.absolute()
|
||||
|
||||
sys.path.insert(0, str(script_dir))
|
||||
|
||||
from shared import box, run, spaced_hl
|
||||
|
||||
spaced_hl()
|
||||
|
||||
dt = datetime.now().strftime("%d.%m.%Y %H:%M:%S")
|
||||
|
||||
box(dt, "Update on")
|
||||
|
||||
box("Update system packages")
|
||||
run("sudo apt update")
|
||||
run("sudo apt upgrade -y")
|
||||
|
||||
run("sudo reboot")
|
|
@ -1,22 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
script_dir = Path(__file__).parent.absolute()
|
||||
|
||||
sys.path.insert(0, str(script_dir))
|
||||
|
||||
from shared import run
|
||||
|
||||
logs_dir = Path("/var/log/advlabdb/")
|
||||
|
||||
# Create logs directory
|
||||
run(f"sudo mkdir -v -p {logs_dir}")
|
||||
run(f"sudo chown -R admin:admin {logs_dir}")
|
||||
|
||||
logged_server_setup_script = script_dir / "logged_server_setup.py"
|
||||
log_file = logs_dir / "server_setup.log"
|
||||
|
||||
# Start actual server setup script with logging
|
||||
run(f"python3 -u {logged_server_setup_script} | tee {log_file}")
|
|
@ -1,55 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import subprocess
|
||||
from getpass import getpass
|
||||
from pathlib import Path
|
||||
|
||||
local_bin = Path("/home/admin/.local/bin/")
|
||||
|
||||
|
||||
def run(command, **kwargs):
|
||||
return subprocess.run(command, shell=True, **kwargs)
|
||||
|
||||
|
||||
def box(message, context=None):
|
||||
text_line = "| "
|
||||
|
||||
if context is not None:
|
||||
text_line += context + ": "
|
||||
|
||||
text_line += message + " |"
|
||||
|
||||
separator = "=" * len(text_line)
|
||||
|
||||
print()
|
||||
print(separator)
|
||||
print(text_line)
|
||||
print(separator)
|
||||
print()
|
||||
|
||||
|
||||
def step(message):
|
||||
continue_message = "-> Press ENTER to continue or Ctrl+C to interrupt the script <-"
|
||||
upper_separator = "_" * len(continue_message)
|
||||
|
||||
print()
|
||||
print(upper_separator)
|
||||
|
||||
box(message, "Next step")
|
||||
|
||||
print(continue_message)
|
||||
getpass("")
|
||||
print()
|
||||
|
||||
|
||||
def install_latest_pipx():
|
||||
run("pip install --user --upgrade pipx")
|
||||
|
||||
|
||||
def poetry_update(script_dir):
|
||||
poetry_bin = local_bin / "poetry"
|
||||
run(f"{poetry_bin} update", cwd=script_dir / "..")
|
||||
|
||||
|
||||
def spaced_hl():
|
||||
print("\n\n___________________\n\n")
|
|
@ -1,29 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
script_dir = Path(__file__).parent.absolute()
|
||||
|
||||
sys.path.insert(0, str(script_dir))
|
||||
|
||||
from shared import box, install_latest_pipx, local_bin, poetry_update, run, spaced_hl
|
||||
|
||||
spaced_hl()
|
||||
|
||||
dt = datetime.now().strftime("%d.%m.%Y %H:%M:%S")
|
||||
|
||||
box(dt, "Update on")
|
||||
|
||||
box("Upgrade pipx")
|
||||
install_latest_pipx()
|
||||
|
||||
box("Upgrade pipx packages")
|
||||
pipx_bin = local_bin / "pipx"
|
||||
run(f"{pipx_bin} upgrade-all --include-injected")
|
||||
|
||||
# TODO: Backup
|
||||
|
||||
box("Install latest Poetry packages")
|
||||
poetry_update(script_dir)
|
145
testDB.py
145
testDB.py
|
@ -1,145 +0,0 @@
|
|||
from datetime import date
|
||||
|
||||
from flask_security import hash_password
|
||||
|
||||
from advlabdb import app, db, user_datastore
|
||||
from advlabdb.models import *
|
||||
|
||||
with app.app_context():
|
||||
db.drop_all()
|
||||
db.create_all()
|
||||
|
||||
program1 = Program(label="BS")
|
||||
program2 = Program(label="MS")
|
||||
program3 = Program(label="BE")
|
||||
|
||||
db.session.add(program1)
|
||||
db.session.add(program2)
|
||||
db.session.add(program3)
|
||||
|
||||
sem1 = Semester.customInit(label="SS", year=22)
|
||||
sem2 = Semester.customInit(label="WS", year=22)
|
||||
|
||||
db.session.add(sem1)
|
||||
db.session.add(sem2)
|
||||
|
||||
partKwargs = [
|
||||
{"program": program1, "number": 1},
|
||||
{"program": program1, "number": 2},
|
||||
{"program": program2, "number": 1},
|
||||
{"program": program2, "number": 2},
|
||||
{"program": program3, "number": 1},
|
||||
]
|
||||
for kwargs in partKwargs:
|
||||
db.session.add(Part(semester=sem1, **kwargs))
|
||||
|
||||
sem2.transferPartsFrom(sem1)
|
||||
|
||||
part1 = sem2.parts[0]
|
||||
part2 = sem2.parts[2]
|
||||
|
||||
student1 = Student(student_number=123, first_name="Mo", last_name="Bit", uni_email="m@test.com")
|
||||
student2 = Student(student_number=1232, first_name="Mo2", last_name="Bit", uni_email="m2@test.com")
|
||||
student3 = Student(student_number=1233, first_name="Mo3", last_name="Bit3", uni_email="m3@test.com")
|
||||
|
||||
db.session.add(student1)
|
||||
db.session.add(student2)
|
||||
db.session.add(student3)
|
||||
|
||||
ps1 = PartStudent.customInit(student=student1, part=part1)
|
||||
ps2 = PartStudent.customInit(student=student2, part=part1)
|
||||
ps3 = PartStudent.customInit(student=student3, part=part2)
|
||||
|
||||
db.session.add(ps1)
|
||||
db.session.add(ps2)
|
||||
db.session.add(ps3)
|
||||
|
||||
g1 = Group.customInit(part_students=[ps1, ps2])
|
||||
g2 = Group.customInit(part_students=[ps3])
|
||||
|
||||
db.session.add(g1)
|
||||
db.session.add(g2)
|
||||
|
||||
ex1 = Experiment(
|
||||
number=1,
|
||||
program=program1,
|
||||
title="exp",
|
||||
room="123",
|
||||
building="phy",
|
||||
responsibility="none",
|
||||
duration_in_days=2,
|
||||
)
|
||||
|
||||
ex2 = Experiment(
|
||||
number=1,
|
||||
program=program2,
|
||||
title="exp2",
|
||||
room="123",
|
||||
building="phy",
|
||||
responsibility="none",
|
||||
duration_in_days=2,
|
||||
)
|
||||
|
||||
db.session.add(ex1)
|
||||
db.session.add(ex2)
|
||||
|
||||
sx1 = SemesterExperiment(experiment=ex1, semester=sem2)
|
||||
sx2 = SemesterExperiment(experiment=ex2, semester=sem2)
|
||||
|
||||
db.session.add(sx1)
|
||||
db.session.add(sx2)
|
||||
|
||||
gx1 = GroupExperiment.customInit(semester_experiment=sx1, group=g1)
|
||||
gx2 = GroupExperiment.customInit(semester_experiment=sx2, group=g2)
|
||||
|
||||
db.session.add(gx1)
|
||||
db.session.add(gx2)
|
||||
|
||||
adminRole = user_datastore.create_role(name="admin")
|
||||
assistantRole = user_datastore.create_role(name="assistant")
|
||||
|
||||
admin_user = user_datastore.create_user(
|
||||
email="admin@advlabdb.de",
|
||||
password=hash_password("admin"),
|
||||
roles=[adminRole],
|
||||
first_name="Peter",
|
||||
last_name="Blümler",
|
||||
)
|
||||
|
||||
admin = Admin(user=admin_user)
|
||||
|
||||
db.session.add(admin)
|
||||
|
||||
us1 = user_datastore.create_user(
|
||||
email="test@protonmail.com",
|
||||
password=hash_password("h1"),
|
||||
roles=[assistantRole],
|
||||
first_name="As1",
|
||||
last_name="l",
|
||||
phone_number="012333212",
|
||||
mobile_phone_number="012334123",
|
||||
)
|
||||
us2 = user_datastore.create_user(
|
||||
email="test2@protonmail.com",
|
||||
password=hash_password("h2"),
|
||||
roles=[assistantRole],
|
||||
first_name="As2",
|
||||
last_name="l",
|
||||
)
|
||||
|
||||
as1 = Assistant(user=us1)
|
||||
as2 = Assistant(user=us2)
|
||||
|
||||
as1.semester_experiments.append(sx1)
|
||||
as2.semester_experiments.append(sx2)
|
||||
|
||||
db.session.add(as1)
|
||||
db.session.add(as2)
|
||||
|
||||
ap1 = Appointment.customInit(date=date(2021, 3, 21), special=True, group_experiment=gx1, assistant=as1)
|
||||
ap2 = Appointment.customInit(date=date(2021, 3, 22), special=True, group_experiment=gx2, assistant=as2)
|
||||
|
||||
db.session.add(ap1)
|
||||
db.session.add(ap2)
|
||||
|
||||
db.session.commit()
|
Loading…
Reference in a new issue