Skip to content
Snippets Groups Projects
Unverified Commit dba520b7 authored by Andresmarevi's avatar Andresmarevi Committed by GitHub
Browse files

Add files via upload

parents
No related branches found
No related tags found
No related merge requests found
version: '3'
services:
flask-app_1:
build: .
ports:
- "3001:8080"
depends_on:
- db
environment:
MONGO_URI: "mongodb://$MONGO_USERNAME:$MONGO_PASSWORD@db:27017/db"
command: ["python", "app.py"]
env_file:
- .env
flask-app_2:
build: .
ports:
- "3002:8080"
depends_on:
- db
environment:
MONGO_URI: "mongodb://$MONGO_USERNAME:$MONGO_PASSWORD@db:27017/db"
command: ["python", "app.py"]
env_file:
- .env
flask-app_3:
build: .
ports:
- "3003:8080"
depends_on:
- db
environment:
MONGO_URI: "mongodb://$MONGO_USERNAME:$MONGO_PASSWORD@db:27017/db"
command: ["python", "app.py"]
env_file:
- .env
db:
image: mongo
ports:
- "27017:27017"
haproxy:
build: ./haproxy
ports:
- "80:80"
depends_on:
- flask-app_1
- flask-app_2
- flask-app_3
# Usa una imagen base adecuada
FROM python:3.11
# Establece el directorio de trabajo dentro del contenedor
WORKDIR /app
# Copia todos los archivos de la aplicación al contenedor
COPY . .
# Instala las dependencias de tu aplicación
RUN pip3 install -r requirements.txt
# Expone el puerto en el que se ejecuta tu aplicación
EXPOSE 8080
# Comando para ejecutar la aplicación
CMD ["python", "app.py"]
app.py 0 → 100644
from flask import Flask, render_template, request, redirect, url_for, flash
from flask_pymongo import PyMongo
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
from bson.objectid import ObjectId
import bcrypt
# Initialize Flask app
app = Flask(__name__)
app.secret_key = 'your_secret_key'
# Initialize MongoDB connection
import os
# Initialize MongoDB connection
app.config['MONGO_URI'] = f"mongodb://{os.environ['MONGO_USERNAME']}:{os.environ['MONGO_PASSWORD']}@db:27017/db"
mongo = PyMongo(app)
# Initialize Flask-Login
login_manager = LoginManager()
login_manager.init_app(app)
# User model
class User(UserMixin):
def __init__(self, username, password):
self.username = username
self.password = password
def get_id(self):
return self.username
@login_manager.user_loader
def load_user(username):
user = mongo.db.users.find_one({'username': username})
if not user:
return None
return User(user['username'], user['password'])
# Routes
# Route to show every toDo in the index page
@app.route('/')
def index():
if current_user.is_authenticated:
todos = mongo.db.todos.find({'user_id': current_user.get_id()})
return render_template('index.html', todos=todos)
else:
return redirect(url_for('login'))
# Route to create a new toDo
@app.route('/add', methods=['POST'])
@login_required
def add_todo():
todo_content = request.form['content']
mongo.db.todos.insert_one({'content': todo_content, 'done': False, 'user_id': current_user.get_id()})
return redirect(url_for('index'))
# Route to mark as done a toDo
@app.route('/done/<string:todo_id>')
@login_required
def mark_done(todo_id):
mongo.db.todos.update_one({'_id': ObjectId(todo_id)}, {'$set': {'done': True}})
return redirect(url_for('index'))
# Route to delete a toDo
@app.route('/delete/<string:todo_id>')
@login_required
def delete_todo(todo_id):
mongo.db.todos.delete_one({'_id': ObjectId(todo_id)})
return redirect(url_for('index'))
# Route to log in
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
user = mongo.db.users.find_one({'username': username})
if user and bcrypt.checkpw(password.encode('utf-8'), user['password']):
user_obj = User(username, user['password'])
login_user(user_obj)
return redirect(url_for('index'))
else:
flash('Invalid username or password', 'error')
return render_template('login.html')
# Route to log out
@app.route('/logout')
@login_required
def logout():
logout_user()
return redirect(url_for('login'))
# Route to register a new user into the db
@app.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
# Check if username already exists
if mongo.db.users.find_one({'username': username}):
flash('Username already exists', 'error')
return redirect(url_for('register'))
# Hash password
hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
# Store user in the database
mongo.db.users.insert_one({'username': username, 'password': hashed_password})
flash('Registration successful. Please log in.', 'success')
return redirect(url_for('login'))
return render_template('register.html')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080)
\ No newline at end of file
FROM haproxy:latest
COPY haproxy.cfg /usr/local/etc/haproxy/haproxy.cfg
global
log stdout format raw local0
defaults
log global
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
frontend http-in
bind *:80
default_backend flask_backend
backend flask_backend
balance roundrobin
option httpchk GET /healthcheck
http-check expect status 200
server flask-app_1 flask-app_1:8080 check inter 2000 rise 2 fall 3
server flask-app_2 flask-app_2:8080 check inter 2000 rise 2 fall 3
server flask-app_3 flask-app_3:8080 check inter 2000 rise 2 fall 3
/* Styles of the index page */
body {
font-family: sans-serif;
margin: 0;
padding: 0;
color: #333;
}
h1 {
font-size: 24px;
margin-top: 20px;
margin-bottom: 20px;
}
header {
color: white;
padding: 20px;
text-align: center;
background: linear-gradient(90deg, #493eea 0%, rgb(251, 249, 249) 100%);
}
main {
display: flex;
flex-direction: column;
align-items: center;
padding: 20px;
}
.add-todo {
margin-bottom: 20px;
}
.add-todo form {
display: flex;
align-items: center;
}
.add-todo input[type="text"] {
padding: 10px 15px;
border: 1px solid #ccc;
border-radius: 4px;
flex-grow: 1;
margin-right: 10px;
}
.add-todo button[type="submit"] {
padding: 10px 15px;
background-color: #9fa5fa;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.todo-list {
width: 80%;
max-width: 600px;
}
.todo-item {
display: flex;
align-items: center;
padding: 10px;
border-bottom: 1px solid #ccc;
background-color: white;
box-shadow: 0 1px 3px rgba(0,0,0,0.12);
}
.todo-item .content {
flex-grow: 1;
}
.todo-item .completed {
text-decoration: line-through;
color: #aaa;
}
.todo-item .actions {
text-align: right;
}
.todo-item .actions a {
margin-left: 10px;
text-decoration: none;
color: #333;
}
.logout {
margin-top: 20px;
text-align: center;
}
.logout a {
color: #f70303;
text-decoration: none;
}
@media (max-width: 768px) {
main {
flex-direction: column;
}
.todo-list {
width: 100%;
}
}
/* Styles of the login page */
body {
font-family: sans-serif;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background-image: linear-gradient(to bottom, #f2f2f2 0%, #a8bcfd 100%);
background-repeat: no-repeat;
background-attachment: fixed;
}
.container {
max-width: 300px;
padding: 30px;
background-color: #ffffff;
border-radius: 15px;
box-shadow: 0 10px 15px rgba(0, 0, 0, 0.2);
}
h1 {
font-size: 28px;
margin-bottom: 15px;
color: #333;
text-align: center;
}
form {
display: flex;
flex-direction: column;
align-items: center;
}
.login-text {
margin-bottom: 20px;
text-align: center;
}
input[type="text"],
input[type="password"] {
width: 100%;
padding: 12px 20px;
margin-bottom: 10px;
border: 1px solid #ccc;
border-radius: 3px;
background-color: #f2f2f2;
}
.buttons {
display: flex;
justify-content: space-between;
margin-top: 20px;
}
button {
padding: 12px 30px;
background-color: #e0e7ff;
color: #333;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.2s ease-in-out;
}
button:hover {
background-color: #b3d0ff;
}
.register-button {
margin-top: 15px;
text-align: center;
}
\ No newline at end of file
/* Styles of the register page */
body {
font-family: sans-serif;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background-image: linear-gradient(to bottom, #f2f2f2 0%, #a8bcfd 100%);
background-repeat: no-repeat;
background-attachment: fixed;
}
.container {
max-width: 300px;
padding: 30px;
background-color: #ffffff;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
}
h1 {
font-size: 28px;
margin-bottom: 15px;
color: #333;
text-align: center;
}
form {
display: flex;
flex-direction: column;
align-items: center;
}
.login-text {
margin-bottom: 20px;
text-align: center;
}
input[type="text"],
input[type="password"] {
width: 100%;
padding: 12px 20px;
margin-bottom: 10px;
border: 1px solid #ccc;
border-radius: 3px;
background-color: #f2f2f2;
}
.buttons {
display: flex;
justify-content: space-between;
margin-top: 20px;
}
button {
padding: 12px 30px;
background-color: #e0e7ff;
color: #333;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.2s ease-in-out;
}
button:hover {
background-color: #b3d0ff;
}
.login-button {
margin-top: 15px;
text-align: center;
}
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="../static/index.css">
<title>ToDos App</title>
</head>
<body>
<header>
<h1>What do I have to do today?</h1> <!--Title-->
</header>
<main>
<section class="add-todo">
<form action="/add" method="POST"> <!--Post method to create new toDo-->
<input type="text" name="content" placeholder="Add a new task" required>
<button type="submit"> Add </button>
</form>
</section>
<section class="todo-list"> <!--List that shows every toDo-->
<ul>
{% for todo in todos %}
<li class="todo-item">
<div class="content">
{% if todo.done %}
<span class="completed">{{ todo.content }} </span> <!--If a toDo is mark as done, the styles changed to appear crossed and in grey-->
{% else %}
{{ todo.content }}
{% endif %}
</div>
<div class="actions">
{% if not todo.done %}
<a href="/done/{{ todo._id }}">Mark as completed</a> <!--Button that calls the mark as done action of a toDo-->
{% endif %}
<a href="/delete/{{ todo._id }}">Delete</a> <!--Button that calls the delete action of a toDo-->
</div>
</li>
{% endfor %}
</ul>
</section>
<section class="logout">
<a href="/logout">Log out</a> <!--Log out button to come back to the log in page-->
</section>
</main>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="../static/login.css">
<title>Login</title>
</head>
<body>
<div class="container">
<h1>Log in</h1> <!--Title-->
{% with messages = get_flashed_messages(with_categories=True) %}
{% if messages %}
{% for category, message in messages %}
{% if category == 'error' %}
<p class="flash error">{{ message }}</p> <!--Show error message in case of invalid log in-->
{% endif %}
{% endfor %}
{% endif %}
{% endwith %}
<form action="/login" method="POST"> <!--POST method to log in-->
<input type="text" name="username" placeholder="Username" required>
<input type="password" name="password" placeholder="Password" required>
<button type="submit">Log in</button> <!--Submit button to log in-->
</form>
<div class="register-button">
<a href="/register">Register</a> <!--Button to access to the register page-->
</div>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="../static/register.css">
<title>Register</title>
</head>
<body>
<div class="container">
<h1>Register</h1> <!--Register title-->
{% with messages = get_flashed_messages(with_categories=True) %}
{% if messages %}
{% for category, message in messages %}
{% if category == 'error' %}
<p class="flash error">{{ message }}</p> <!--Show error message in case of invalid register-->
{% endif %}
{% endfor %}
{% endif %}
{% endwith %}
<form action="/register" method="POST"> <!--Post method to register-->
<input type="text" name="username" placeholder="Username" required>
<input type="password" name="password" placeholder="Password" required>
<button type="submit">Register</button> <!--Submit button to register-->
</form>
<div class="login-button">
<a href="/login">Login</a> <!--Button to access to the login page-->
</div>
</div>
</body>
</html>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment