Skip to content

Commit

Permalink
Merge pull request #1 from Oneloutre/dev
Browse files Browse the repository at this point in the history
Now working auth method !
  • Loading branch information
Oneloutre authored Apr 23, 2024
2 parents acf05a8 + 7a5efb9 commit 8ace604
Show file tree
Hide file tree
Showing 11 changed files with 322 additions and 7 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<div align='center'>

![banner](Assets/BannerNginxPM2.png)
![banner](static/Assets/BannerNginxPM2.png)
<h1>NginxPM2</h1>
<p>A simple, but yet efficient, way of managing all your Nginx Proxy Manager instances !</p>

Expand Down
73 changes: 67 additions & 6 deletions app.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,73 @@
from flask import Flask
import flask
from routes.auth.login import *
from routes.auth.register import *
import os
from flask_jwt_extended import jwt_required, JWTManager, unset_jwt_cookies, get_jwt_identity, get_jwt
from datetime import timedelta, datetime, timezone

app = Flask(__name__)
APP = flask.Flask(__name__)
jwt = JWTManager(APP)

APP.config['JWT_TOKEN_LOCATION'] = ['cookies']
APP.config['JWT_SECRET_KEY'] = 'your-secret-key'
APP.config['JWT_ACCESS_TOKEN_EXPIRES'] = timedelta(days=1)

@app.route('/')
def hello_world():
return 'Hello World!'

@APP.route('/login', methods=['POST', 'GET'])
def login():
if os.path.exists('user_files/admin/admin.json'):
return log_in()
else:
return redirect(url_for('register'), code=301)


@APP.route('/register', methods=['GET', 'POST'])
def register():
if os.path.exists('user_files/admin/admin.json'):
return 'You are already registered'
return redirect(url_for('index'), code=301)
else:
return register_user()


@APP.route('/', methods=['GET', 'POST'])
@jwt_required()
def index():
return render_template('index.html', code=200)


@APP.route('/logout', methods=['POST'])
def logout():
resp = flask.make_response(flask.redirect(flask.url_for('login')))
unset_jwt_cookies(resp)
return resp


@jwt.unauthorized_loader
def my_invalid_token_callback(expired_token):
print("unauthorized_loader", expired_token)
return redirect(url_for('login'))


@APP.errorhandler(401)
def unauthorized_error(error):
return redirect(url_for('login'))


@APP.after_request
def refresh_expiring_jwts(response):
try:
exp_timestamp = get_jwt()["exp"]
now = datetime.now(timezone.utc)
target_timestamp = datetime.timestamp(now + timedelta(minutes=30))
if target_timestamp > exp_timestamp:
access_token = create_access_token(identity=get_jwt_identity())
set_access_cookies(response, access_token)
return response
except (RuntimeError, KeyError):
return response


if __name__ == '__main__':
app.run()
APP.debug=False
APP.run()
31 changes: 31 additions & 0 deletions routes/auth/login.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from flask import render_template, request, redirect, url_for, make_response, jsonify
import json, bcrypt
from flask_jwt_extended import create_access_token, set_access_cookies


def log_in():
error = None
if request.method == 'POST':
username = request.form['username']
password = request.form['password']

encrypted_username, encrypted_email, encrypted_password = load_encrypted_creds('user_files/admin/admin.json')

if (bcrypt.checkpw(username.encode('utf8'), encrypted_username) or bcrypt.checkpw(username.encode('utf8'), encrypted_email)) and bcrypt.checkpw(password.encode('utf8'), encrypted_password):
access_token = create_access_token(identity=username)
response = make_response(redirect(url_for('index')))
set_access_cookies(response, access_token)
return response
else:
error = 'Invalid Credentials. Please try again.'
return render_template('login/login.html', error=error)
return render_template('login/login.html', error=error)


def load_encrypted_creds(file):
loaded_json = json.load(open(file))
username = loaded_json["username"].encode('utf8')
email = loaded_json["email"].encode('utf8')
password = loaded_json["password"].encode('utf8')
return username, email, password

53 changes: 53 additions & 0 deletions routes/auth/register.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
from flask import render_template, request, redirect, url_for
import bcrypt, hashlib, requests


def register_user():
error = None
if request.method == 'POST':
username = request.form['username']
email = request.form['email'].lower()
password = request.form['password']
confirm_password = request.form['confirm_password']
if isFormEmpty(request.form):
error = 'Please fill all the fields'
return render_template('register/register.html', error=error)

if password != confirm_password:
error = 'Passwords do not match'
else:
crypted_username, crypted_email, crypted_password = crypt_data(username, email, password)
get_gravatar_icon(email)
with open('user_files/admin/admin.json', 'w') as file:
file.write('{\n "username": "' + crypted_username.decode('utf-8') + '",\n "email": "' + crypted_email.decode('utf-8') + '",\n "password": "' + crypted_password.decode('utf-8') + '"\n}')
return redirect(url_for('login'))
return render_template('register/register.html', error=error)


def isFormEmpty(form):
for key in form:
if form[key] == "":
return True
return False


def crypt_data(username, email, password):
crypted_username = bcrypt.hashpw(username.encode('utf-8'), bcrypt.gensalt())
crypted_email = bcrypt.hashpw(email.encode('utf-8'), bcrypt.gensalt())
crypted_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
return crypted_username, crypted_email, crypted_password

def get_gravatar_icon(email):
code = hashlib.md5(email.strip().encode('utf8')).hexdigest()
mail_url = f"https://www.gravatar.com/avatar/{code}?size=2048"
img_data = requests.get(mail_url)
if img_data.status_code == 200:
with open('user_files/admin/admin_avatar.png', 'wb') as f:
f.write(img_data.content)

else:
img_data = requests.get("http://www.gravatar.com/avatar/?d=mp").content
with open('user_files/admin/admin_avatar.png', 'wb') as f:
f.write(img_data)


File renamed without changes
File renamed without changes
27 changes: 27 additions & 0 deletions static/login/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
body {
background-color: #1e2124;
color: #ffffff;
margin-top: 50px;
}

.container {
background-color: #282b30;
border-radius: 5px;
padding: 20px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
max-width: 400px;
margin: auto;
}

.dark-container {
color: #333333;
}

.banner img {
max-width: 100%;
height: auto;
max-height: 150px;
}
.error {
color: red;
}
28 changes: 28 additions & 0 deletions static/register/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
body {
background-color: #1e2124;
color: #ffffff;
margin-top: 50px;
}
.container {
background-color: #282b30;
border-radius: 5px;
padding: 20px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
max-width: 400px;
margin: auto;
}

.banner img {
max-width: 100%;
height: auto;
max-height: 150px;
}

.dark-container {
color: #333333;
}


.error {
color: red;
}
43 changes: 43 additions & 0 deletions templates/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Page d'accueil</title>
<!-- Ajouter Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KyZXEAg3QhqLMpG8r+Knujsl5+zr/2+AzmbPFEY1pck9Oi7qOB7w5BzWRwKtk81U" crossorigin="anonymous">
<style>
/* Styles personnalisés ici */
</style>
</head>
<body>
<div class="container">
<h1 class="mt-5">Bienvenue sur notre site</h1>
<p>Ceci est une page d'accueil simple.</p>
<!-- Bouton de déconnexion -->
<button id="btnLogout" class="btn btn-danger mt-3">Déconnexion</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js" integrity="sha384-QFhL/tFfQaTZYZF/Q2vRTJPnC/tfG4S7ZcK/GK8fSYyZOd4yi7ujF0pDc5cW4kE1" crossorigin="anonymous"></script>
<script>
// Ajoutez votre code JavaScript personnalisé ici
document.getElementById("btnLogout").addEventListener("click", function() {
// Redirection vers la route de déconnexion
fetch('/logout', {
method: 'POST',
credentials: 'same-origin'
})
.then(response => {
if (response.ok) {
// Si la déconnexion réussit, redirigez l'utilisateur vers la page de connexion
window.location.href = '/login'; // Remplacez '/login' par l'URL de votre page de connexion
} else {
console.error('Erreur lors de la déconnexion');
}
})
.catch(error => {
console.error('Erreur lors de la déconnexion :', error);
});
});
</script>
</body>
</html>
33 changes: 33 additions & 0 deletions templates/login/login.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login Page</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
<link href="static/login/style.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="banner">
<img src="static/Assets/BannerNginxPM2.png" alt="Bannière">
</div>
<h2 class="text-center">Login</h2>
<br>
<form action="" method="post">
<div class="form-group">
<input type="text" class="form-control bg-dark text-white" placeholder="Username or email" name="username" value="{{ request.form.username }}">
</div>
<div class="form-group">
<input type="password" class="form-control bg-dark text-white" placeholder="Password" name="password" value="{{ request.form.password }}">
</div>
<button type="submit" class="btn btn-primary btn-block">Login</button>
</form>
{% if error %}
<p class="error"><strong>Error:</strong> {{ error }}</p>
{% endif %}
<hr>
<p class="text-center">Not registered yet ? <a href="{{ url_for('register') }}">Register here</a></p>
</div>
</body>
</html>
39 changes: 39 additions & 0 deletions templates/register/register.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Register Page</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
<link href="static/register/style.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="banner">
<img src="static/Assets/BannerNginxPM2.png" alt="Bannière">
</div>
<h2 class="text-center">Register</h2>
<br>
<form action="" method="post">
<div class="form-group">
<input type="text" class="form-control bg-dark text-white" placeholder="Username" name="username" value="{{ request.form.username }}">
</div>
<div class="form-group">
<input type="email" class="form-control bg-dark text-white" placeholder="Email" name="email" value="{{ request.form.email }}">
</div>
<div class="form-group">
<input type="password" class="form-control bg-dark text-white" placeholder="Password" name="password" value="{{ request.form.password }}">
</div>
<div class="form-group">
<input type="password" class="form-control bg-dark text-white" placeholder="Confirm Password" name="confirm_password" value="{{ request.form.confirm_password }}">
</div>
<button type="submit" class="btn btn-primary btn-block">Register</button>
</form>
{% if error %}
<p class="error"><strong>Error:</strong> {{ error }}</p>
{% endif %}
<hr>
<p class="text-center">Already have an account ? <a href="{{ url_for('login') }}">Login here</a></p>
</div>
</body>
</html>

0 comments on commit 8ace604

Please sign in to comment.