Skip to content

add web #18

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Feb 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)