Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
GiRx8 committed Mar 7, 2024
1 parent 712187b commit d6245e2
Show file tree
Hide file tree
Showing 37 changed files with 1,248 additions and 0 deletions.
95 changes: 95 additions & 0 deletions deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#!/bin/bash

# Step 1: Install Gunicorn
echo "Installing Gunicorn..."
pip install gunicorn

# Step 2: Install Nginx
echo "Installing Nginx..."
sudo apt update
sudo apt install -y nginx

# Step 3: Configure Gunicorn
echo "Configuring Gunicorn..."
cat <<EOF | sudo tee /etc/systemd/system/gunicorn.service > /dev/null
[Unit]
Description=Gunicorn instance to serve your Flask application
After=network.target
[Service]
User=steam
Group=steam
WorkingDirectory=/home/app/pals
Environment="PATH=/home/app/pals/venv/bin"
ExecStart=/home/app/pals/venv/bin/gunicorn -w 4 -b 0.0.0.0:5000 main:create_app()
[Install]
WantedBy=multi-user.target
EOF

# Step 4: Configure Nginx
echo "Configuring Nginx..."
cat <<EOF | sudo tee /etc/nginx/sites-available/PalService > /dev/null
server {
listen 80;
server_name 192.168.33.78;
location / {
proxy_pass http://localhost:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /static {
alias /home/app/pals/main/static;
}
location /media {
alias /home/app/pals/main/media;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
EOF

sudo ln -s /etc/nginx/sites-available/PalService /etc/nginx/sites-enabled

# Step 5: Enable and Start Services
echo "Enabling and starting services..."
sudo systemctl enable gunicorn
sudo systemctl start gunicorn
sudo systemctl enable nginx
sudo systemctl start nginx

# Step 6: Configure Firewall
echo "Configuring firewall..."
sudo ufw allow 80
#sudo ufw enable

# Step 7: Add new line to sudoers using visudo
echo "Adding a new line to sudoers..."
echo "steam ALL=(ALL) NOPASSWD: /bin/systemctl start palworld.service, /bin/systemctl stop palworld.service, /bin/systemctl restart palworld.service, /bin/systemctl is-active palworld.service" | sudo tee -a /etc/sudoers

# Step 8: Set up Python virtual environment
echo "Setting up Python virtual environment..."
cd /home/app/pals
python3 -m venv venv
source venv/bin/activate

# Step 9: Install Flask and other dependencies
echo "Installing Flask and dependencies..."
pip install -r requirements.txt

# Step 10: Deactivate virtual environment
deactivate

sudo systemctl restart nginx
sudo systemctl restart gunicorn

echo "Deployment completed!"
26 changes: 26 additions & 0 deletions pals/dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Use an official Python runtime as a parent image
FROM python:3.8-slim

# Set the working directory in the container
WORKDIR /app

# Copy the current directory contents into the container at /app
COPY . .

# Upgrade pip
RUN pip install --upgrade pip

# Install Gunicorn
RUN pip install gunicorn

# Install any needed packages specified in requirements.txt
RUN pip install --no-cache-dir -r requirements.txt

# Make port 5000 available to the world outside this container
EXPOSE 5000

# Run the Flask init-db command during container setup
RUN flask --app main:create_app init-db

# Run the Flask app using Gunicorn
CMD ["gunicorn", "-b", "0.0.0.0:5000", "run:app"]
1 change: 1 addition & 0 deletions pals/logfile.log
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Script is running
34 changes: 34 additions & 0 deletions pals/main/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import os
from flask import Flask
from .configurations.config import Config

def create_app():
app = Flask(__name__, instance_relative_config=True)

app.config.from_object(Config)
# Load the default configuration from config.py
#print(app.config)

if not os.path.exists(Config.INSTANCE_PATH):
os.makedirs(Config.INSTANCE_PATH)

# Register blueprints and extensions
from . import db
db.init_app(app)

from .utils import server_config
app.register_blueprint(server_config.bp)

from . import auth
app.register_blueprint(auth.bp)

from main.routes import bp as main_bp
app.register_blueprint(main_bp)

from .utils.service_control import service_control_bp
app.register_blueprint(service_control_bp)

from .configurations.config import Configs_bp
app.register_blueprint(Configs_bp)

return app
153 changes: 153 additions & 0 deletions pals/main/auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import functools

from functools import wraps
from flask import Blueprint, flash, g, redirect, render_template, request, session, url_for
from werkzeug.security import check_password_hash, generate_password_hash

from main.db import get_db

bp = Blueprint('auth', __name__, url_prefix='/auth')

def get_user_by_id(user_id):
db = get_db()
return db.execute("SELECT * FROM user WHERE id = ?", (user_id,)).fetchone()

def login_required(view):
@wraps(view)
def wrapped_view(*args, **kwargs):
if g.user is None:
return redirect(url_for('auth.login'))

g.user = get_user_by_id(session['user_id'])

return view(*args, **kwargs)

return wrapped_view

def admin_required(view):
@wraps(view)
def wrapped_view(*args, **kwargs):
if g.user is None or not g.user.get('is_admin', False):
return redirect(url_for('auth.login'))
return view(*args, **kwargs)

return wrapped_view

@bp.route('/register', methods=('GET', 'POST'))
@admin_required
def register():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
db = get_db()
error = None

if not username:
error = 'Username is required.'
elif not password:
error = 'Password is required.'

if error is None:
try:
db.execute(
"INSERT INTO user (username, password) VALUES (?, ?)",
(username, generate_password_hash(password)),
)
db.commit()
except db.IntegrityError:
error = f"User {username} is already registered."
else:
return redirect('/')

flash(error)

return render_template('auth/register.html')

@bp.route('/login', methods=('GET', 'POST'))
def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
db = get_db()
error = None
user = db.execute(
'SELECT * FROM user WHERE username = ?', (username,)
).fetchone()

if user is None:
error = 'Incorrect username.'
elif not check_password_hash(user['password'], password):
error = 'Incorrect password.'

if error is None:
session.clear()
session['user_id'] = user['id']
return redirect('/')

flash(error)

return render_template('auth/login.html')

@bp.route('/reset-password', methods=('GET', 'POST'))
@login_required
def reset_password():
if request.method == 'POST':
current_password = request.form['current_password']
new_password = request.form['new_password']
confirm_password = request.form['confirm_password']

db = get_db()
error = None

if not check_password_hash(g.user['password'], current_password):
error = 'Invalid current password.'
elif new_password != confirm_password:
error = 'New password and confirm password do not match.'
else:
db.execute(
"UPDATE user SET password = ? WHERE id = ?",
(generate_password_hash(new_password), g.user['id']),
)
db.commit()

flash('Password reset successfully.')
return redirect('/')

flash(error)

return render_template('auth/reset_password.html')

@bp.before_app_request
def load_logged_in_user():
user_id = session.get('user_id')

if user_id is None:
g.user = None
else:
user_data = get_db().execute(
'SELECT id, username, is_admin FROM user WHERE id = ?', (user_id,)
).fetchone()

if user_data:
g.user = {
'id': user_data['id'],
'username': user_data['username'],
'is_admin': user_data['is_admin'],
}
else:
g.user = None

@bp.route('/logout')
def logout():
session.clear()
return redirect(url_for('auth.login'))

def login_required(view):
@functools.wraps(view)
def wrapped_view(**kwargs):
if g.user is None:
return redirect(url_for('auth.login'))

return view(**kwargs)

return wrapped_view
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
47 changes: 47 additions & 0 deletions pals/main/configurations/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import os
from flask import Blueprint, render_template, redirect, url_for, request, flash
from main.auth import admin_required
from main.db import get_db

Configs_bp = Blueprint('Configs', __name__)


class Config:
DEBUG = True
SECRET_KEY = 'your_secret_key'
BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
INSTANCE_PATH=os.path.join(BASE_DIR, 'instance')
DATABASE=os.path.join(BASE_DIR, INSTANCE_PATH, 'flaskr.sqlite')
SCRIPT_FILE_PATH = os.path.join('/home/steam/Steam/steamapps/common/PalServer')
TEMPLATE_FOLDER = os.path.join(BASE_DIR, 'templates')
STATIC_FOLDER = os.path.join(BASE_DIR, 'static')
####Fix data implementation of path####
#INI_FILE_PATH = os.path.join(BASE_DIR, '../PalWorldSettings.ini')
#INI_FILE_PATH = os.path.join('/home/steam/Steam/steamapps/common/PalServer/Pal/Saved/Config/LinuxServer/PalWorldSettings.ini')

@Configs_bp.route('/update_path/<name>', methods=['GET', 'POST'])
@admin_required
def update_path(name):
db = get_db()

existing_config = db.execute('SELECT * FROM configs WHERE name = ?', (name,)).fetchone()

if existing_config is None:
flash(f'Configuration with name {name} not found', 'error')
return redirect(url_for('main.home')) # Redirect to another page or handle appropriately

if request.method == 'POST':
new_path = request.form.get('new_path')

if not new_path:
flash('Missing new_path parameter', 'error')
return redirect(url_for('Configs.update_path', name=name))

db.execute('UPDATE configs SET path = ? WHERE name = ?', (new_path, name))
db.commit()

flash(f'Path for configuration {name} updated successfully', 'success')

return redirect('/')

return render_template('misc/update_path.html', config_name=name)
Loading

0 comments on commit d6245e2

Please sign in to comment.