Skip to content

Commit

Permalink
add web (#18)
Browse files Browse the repository at this point in the history
* add web

* edit main.css, change footer1-2 to footer-left and footer-right

* Add to the readme, how to test the webserver

* In MariaDB, you cannot name a database "database", slight oversight..

* Forgot to tell the user to "use asmara;" after creating the database..

* 2fa

* remove unused imports

* add pytz

* edit webhook system, add timeout,

* add notes
  • Loading branch information
reggietorres authored Feb 3, 2024
1 parent 0854002 commit 97f8ccd
Show file tree
Hide file tree
Showing 7 changed files with 334 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/.idea
34 changes: 34 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,40 @@ python3 asmara.py -vvvv .config2
to use `.config2` as the selected config file. If the file does not exist, it will be created.
> Note: The config file *must* always come after the flags. Adding a flag after the config file may result in unexpected behavior.
## Web Testing
To test the webserver, install mariadb and do the following commands
```
sudo mariadb
CREATE USER 'username'@'localhost' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON *.* TO 'username'@'localhost';
CREATE DATABASE asmara;
USE asmara;
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50),
password VARCHAR(50)
);
```
then, go in web.py and change line 21 to the information you filled out for your table..

to make a user, do the commands in mariadb
```
USE asmara;
INSERT INTO users (username, password) VALUES ('username', 'password');
```
(NEW & required) 2FA:
Make a discord server, and a webhook, copy the webhook url and put it in web.py

To run the webserver, do the following
```
python3 -m pip install flask flask_sqlalchemy mysqlclient pytz
python3 web.py
```
it should work, you can now go to the ip:port/ and it should redirect to the login page.


## Changelog
DO LATER

Expand Down
17 changes: 17 additions & 0 deletions static/main.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#footer-right {
position: fixed;
bottom: 0;
right: 0;
background-color: rgba(0, 0, 0, 0); /* semi-transparent black */
color: white;
font-size: 12px; /* Adjust this value to your liking */
}

#footer-left {
position: fixed;
bottom: 0;
left: 0;
background-color: rgba(0, 0, 0, 0); /* semi-transparent black */
color: white;
font-size: 12px; /* Adjust this value to your liking */
}
80 changes: 80 additions & 0 deletions templates/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]> <html class="no-js"> <!--<![endif]-->
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="{{ url_for('static', filename='main.css') }}">
<script src="https://cdn.tailwindcss.com"></script>
<script>
var timeoutId;
var logoutTimeout = 10 * 60 * 1000; // 10 minutes in milliseconds
var warningTime = 5 * 1000; // 5 seconds in milliseconds

function resetTimer() {
clearTimeout(timeoutId);
timeoutId = setTimeout(logoutUser, logoutTimeout);
}

function logoutUser() {
if (!confirm("You have been inactive for 10 minutes. Are you still here?")) {
window.location.href = "/logout";
} else {
resetTimer();
// Call the server to extend the session
fetch('/extend_session', { method: 'POST' });
}
}

// Reset the timer on any interaction
window.onload = resetTimer;
window.onmousemove = resetTimer;
window.onmousedown = resetTimer;
window.ontouchstart = resetTimer;
window.onclick = resetTimer;
window.onscroll = resetTimer;
window.onkeypress = resetTimer;

// Start the timer
resetTimer();
</script>
</head>
<body class="bg-gray-800">
<nav class="bg-blue-500 p-2 mb-4">
<div class="container mx-auto flex justify-between items-center">
<div>
<a href="/" class="text-white text-lg font-bold">ASMARA Home</a>
</div>
<div>
<a href="/" class="text-white text-lg font-bold">Encode</a>
</div>
<div>
<a href="/" class="text-white text-lg font-bold">Settings</a>
</div>
<div>
<a href="/logout" class="text-white text-lg font-bold">Logout</a>
</div>
<div>
<p class="text-white text-lg font-bold">Welcome {{ username }}</p>
</div>
</div>
</nav>

<div class="content-center">
<p class="text-white">STATISTICS GO HERE! NEED SOCKET OR SOMETHING</p>
</div>

<!--[if lt IE 7]>
<p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="#">upgrade your browser</a> to improve your experience.</p>
<![endif]-->
<div id="footer-right">Webserver Made with ♡ by Reggie Torres and Anastasia Mayer</div>
<div id="footer-left">Copyright © 2024 MissingTextures Software</div>

</body>
</html>
48 changes: 48 additions & 0 deletions templates/login.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]> <html class="no-js"> <!--<![endif]-->
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="{{ url_for('static', filename='main.css') }}">
</head>
<body>
<div class="min-h-screen flex items-center justify-center bg-gray-800 py-12 px-4 sm:px-6 lg:px-8">
<div class="max-w-md w-full space-y-8">
<div>
<h2 class="mt-6 text-center text-3xl font-extrabold text-white">
Sign in to your ASMARA Encoder
</h2>
</div>
<form class="mt-8 space-y-6" action="/login" method="post">
<input type="hidden" name="remember" value="true">
<div class="rounded-md shadow-sm -space-y-px">
<div>
<label for="username" class="sr-only">Username</label>
<input id="username" name="username" type="text" autocomplete="username" required class="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-t-md focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 focus:z-10 sm:text-sm" placeholder="Username">
</div>
<div>
<label for="password" class="sr-only">Password</label>
<input id="password" name="password" type="password" autocomplete="current-password" required class="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-b-md focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 focus:z-10 sm:text-sm" placeholder="Password">
</div>
</div>

<div>
<button type="submit" class="group relative w-full flex justify-center py-2 px-4 border border-transparent text-lg font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
Sign in
</button>
</div>
</form>
</div>
</div>
<div id="footer-right">Webserver Made with ♡ by Reggie Torres and Anastasia Mayer</div>
<div id="footer-left">Copyright © 2024 MissingTextures Software</div>
</body>
</html>
37 changes: 37 additions & 0 deletions templates/verify_code.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Verify Code</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="{{ url_for('static', filename='main.css') }}">
<script>
// Redirect to the login page after 30 seconds
setTimeout(function() {
window.location.href = '/login';
}, 30000); // 30000 milliseconds = 30 seconds
</script>
</head>
<body>
<div class="min-h-screen flex items-center justify-center bg-gray-800 py-12 px-4 sm:px-6 lg:px-8">
<div class="w-full max-w-xs">
<form class="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4" action="/verify_code" method="post">
<div class="mb-4">
<label class="block text-gray-700 text-sm font-bold mb-2" for="code">
Verification Code
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" id="code" type="text" pattern="\d{6}" inputmode="numeric" placeholder="Enter Code" name="code" required>
</div>
<div class="flex items-center justify-between">
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline" type="submit">
Verify
</button>
</div>
</form>
</div>
</div>
<div id="footer-right">Webserver Made with ♡ by Reggie Torres and Anastasia Mayer</div>
<div id="footer-left">Copyright © 2024 MissingTextures Software</div>
</body>
</html>
117 changes: 117 additions & 0 deletions web.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#Standard Lib
import random
from functools import wraps
from datetime import datetime, timedelta

#Third Party

from flask import Flask, render_template, request, session, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
from pytz import utc
from discord_webhook import DiscordWebhook, DiscordEmbed


#Here we define the webhook
webhook = DiscordWebhook(url="webhook here", username="ASMARA 2FA", avatar_url="https://avatars.githubusercontent.com/u/20572623?v=4")



#Define Flask and COnfiguration
app = Flask(__name__, template_folder='templates')
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://username:password@localhost/asmara' #Change this!
db = SQLAlchemy(app)
app.secret_key = 'your_secret_key' # PLEASE PLEASE GENERATE A EXTREMELY LONG PASSWORD HERE!

#Make Database Model
class users(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(50))
password = db.Column(db.String(50))


#Define the @ you put infront of a route if login is required
def login_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if 'logged_in' not in session:
return redirect(url_for('login'))
return f(*args, **kwargs)
return decorated_function

#index.html route
@app.route('/')
@login_required
def home():
username = session.get('username', '')
return render_template('index.html', username=username)


#login.html route
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form.get('username')
password = request.form.get('password')
user = users.query.filter_by(username=username).first()
if user and user.password == password:
# Generate a six-digit random code
code = str(random.randint(100000, 999999))
# Send this code to a specific channel in your Discord server
send_discord_message(code)
# Store the code and its expiration time in the session
session['code'] = {'value': code, 'expires_at': datetime.now(utc) + timedelta(seconds=30)}
# Store the username in the session
session['username'] = username
return redirect(url_for('verify_code'))
else:
return 'Invalid credentials', 401
else:
return render_template('login.html')

#extend session route, for when you go AFK on index.html
@app.route('/extend_session', methods=['POST'])
def extend_session():
return '', 204

#2FA Route
@app.route('/verify_code', methods=['GET', 'POST'])
def verify_code():
# Check if the code exists in the session
if 'code' not in session:
return '401 Unauthorized, Invalid Code, or you are trying to hack me!', 401

if request.method == 'POST':
entered_code = request.form.get('code')
code_info = session.get('code')
if code_info and entered_code == code_info['value'] and datetime.now(utc) <= code_info['expires_at']:
session['logged_in'] = True
# Clear the session variable holding the verification code
session.pop('code', None)
return redirect(url_for('home'))
else:
# Clear the session variable holding the verification code
session.pop('code', None)
return redirect(url_for('verify_code'))
else:
# Retrieve the flashed message from the session and store it in the template context
return render_template('verify_code.html')


#Logout Route
@app.route('/logout')
def logout():
session.pop('logged_in', None)
return redirect(url_for('login'))


#Discord 2FA Embed
def send_discord_message(content):
embed = DiscordEmbed(title="2FA Code Requested", description="Code: " + str(content) + " If you didn't request this code, its safe to ignore this message..", color="03b2f8")
embed.set_author(name="ASMARA")
embed.set_thumbnail(url="https://cdn.discordapp.com/attachments/907457287864590396/907757517751332914/warning.png")
embed.set_footer(text="Code Invalid After 30 Seconds | ASMARA © 2024 MSNGTXTRS SOFT.")
webhook.add_embed(embed)
webhook.execute()

if __name__ == '__main__':
app.run(debug=True)

0 comments on commit 97f8ccd

Please sign in to comment.