From 62a835718a46830c82594d5b531ab219f411a9c5 Mon Sep 17 00:00:00 2001 From: Isaak Buslovich Date: Fri, 19 Jan 2024 19:46:42 +0100 Subject: [PATCH] intitial --- .idea/.gitignore | 3 ++ .../inspectionProfiles/profiles_settings.xml | 6 +++ .idea/modules.xml | 8 +++ app/__init__.py | 28 ++++++++++ app/auth.py | 53 +++++++++++++++++++ app/main.py | 14 +++++ app/models.py | 16 ++++++ app/routes.py | 25 +++++++++ app/static/styles.css | 43 +++++++++++++++ app/templates/index.html | 15 ++++++ app/templates/login.html | 18 +++++++ app/templates/register.html | 18 +++++++ requirements.txt | 4 ++ run.py | 11 ++++ 14 files changed, 262 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/modules.xml create mode 100644 app/__init__.py create mode 100644 app/auth.py create mode 100644 app/main.py create mode 100644 app/models.py create mode 100644 app/routes.py create mode 100644 app/static/styles.css create mode 100644 app/templates/index.html create mode 100644 app/templates/login.html create mode 100644 app/templates/register.html create mode 100644 requirements.txt create mode 100644 run.py diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..008574a --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/__init__.py b/app/__init__.py new file mode 100644 index 0000000..8213b5a --- /dev/null +++ b/app/__init__.py @@ -0,0 +1,28 @@ +from flask import Flask +from flask_sqlalchemy import SQLAlchemy +from flask_login import LoginManager + +db = SQLAlchemy() + +def create_app(): + app = Flask(__name__) + + app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///users.db' + app.config['SECRET_KEY'] = 'your-secret-key' + + db.init_app(app) + + login_manager = LoginManager() + login_manager.login_view = 'auth.login' + login_manager.init_app(app) + + from .models import User + + @login_manager.user_loader + def load_user(user_id): + return User.query.get(int(user_id)) + + from .auth import auth as auth_blueprint + app.register_blueprint(auth_blueprint) + + return app diff --git a/app/auth.py b/app/auth.py new file mode 100644 index 0000000..fb02670 --- /dev/null +++ b/app/auth.py @@ -0,0 +1,53 @@ +from flask import Blueprint, request, render_template, redirect, url_for, flash +from flask_login import login_user, logout_user, login_required +from .models import User, db +from passlib.hash import argon2 + +auth = Blueprint('auth', __name__) + + +@auth.route('/register', methods=['GET', 'POST']) +def register(): + if request.method == 'POST': + username = request.form.get('username') + password = request.form.get('password') + + # Check if username already exists + existing_user = User.query.filter_by(username=username).first() + if existing_user: + flash('Username already exists.') + return redirect(url_for('auth.register')) + + # Create new user with hashed password + new_user = User(username=username) + new_user.set_password(password) + db.session.add(new_user) + db.session.commit() + + flash('Registration successful.') + return redirect(url_for('auth.login')) + + return render_template('register.html') + + +@auth.route('/login', methods=['GET', 'POST']) +def login(): + if request.method == 'POST': + username = request.form.get('username') + password = request.form.get('password') + + user = User.query.filter_by(username=username).first() + if user and user.check_password(password): + login_user(user) + return redirect(url_for('main.index')) + + flash('Invalid username or password.') + + return render_template('login.html') + + +@auth.route('/logout') +@login_required +def logout(): + logout_user() + return redirect(url_for('main.index')) diff --git a/app/main.py b/app/main.py new file mode 100644 index 0000000..be33de5 --- /dev/null +++ b/app/main.py @@ -0,0 +1,14 @@ +from flask import Blueprint, render_template +import random + +main = Blueprint('main', __name__) + + +@main.route('/') +def index(): + return render_template('index.html') + + +@main.route('/random-number') +def random_number(): + return str(random.randint(1, 100)) diff --git a/app/models.py b/app/models.py new file mode 100644 index 0000000..8f30b2b --- /dev/null +++ b/app/models.py @@ -0,0 +1,16 @@ +from flask_sqlalchemy import SQLAlchemy +from passlib.hash import argon2 + +db = SQLAlchemy() + + +class User(db.Model): + id = db.Column(db.Integer, primary_key=True) + username = db.Column(db.String(80), unique=True, nullable=False) + password_hash = db.Column(db.String(120), nullable=False) + + def set_password(self, password): + self.password_hash = argon2.hash(password) + + def check_password(self, password): + return argon2.verify(password, self.password_hash) diff --git a/app/routes.py b/app/routes.py new file mode 100644 index 0000000..dc3d233 --- /dev/null +++ b/app/routes.py @@ -0,0 +1,25 @@ +from flask import Blueprint, render_template, request, redirect, url_for +from .models import User, db + +auth = Blueprint('auth', __name__) + + +@auth.route('/register', methods=['GET', 'POST']) +def register(): + if request.method == 'POST': + username = request.form['username'] + password = request.form['password'] + + new_user = User(username=username) + new_user.set_password(password) + db.session.add(new_user) + db.session.commit() + + return redirect(url_for('auth.login')) + return render_template('register.html') + + +@auth.route('/login', methods=['GET', 'POST']) +def login(): + # Implement login logic + return render_template('login.html') diff --git a/app/static/styles.css b/app/static/styles.css new file mode 100644 index 0000000..008232d --- /dev/null +++ b/app/static/styles.css @@ -0,0 +1,43 @@ +@import url('https://fonts.googleapis.com/css2?family=Lora:wght@400;700&display=swap'); + +body { + font-family: 'Lora', serif; + background-color: #fbfbfb; + color: #383a42; + display: flex; + justify-content: center; + align-items: center; + height: 100vh; + margin: 0; +} + +.card { + background-color: #fff; + border-radius: 8px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + padding: 20px; + width: 90%; + max-width: 400px; + text-align: center; +} + +button { + background-color: #61afef; + color: #fff; + border: none; + padding: 10px 20px; + border-radius: 5px; + cursor: pointer; + font-size: 16px; + transition: background-color 0.3s; +} + +button:hover { + background-color: #528bca; +} + +@media (max-width: 600px) { + .card { + width: 80%; + } +} diff --git a/app/templates/index.html b/app/templates/index.html new file mode 100644 index 0000000..3c76988 --- /dev/null +++ b/app/templates/index.html @@ -0,0 +1,15 @@ + + + + Flask App + + +

Welcome to the Flask App

+ + + diff --git a/app/templates/login.html b/app/templates/login.html new file mode 100644 index 0000000..b2bca41 --- /dev/null +++ b/app/templates/login.html @@ -0,0 +1,18 @@ + + + + Login + + + +
+

Login

+
+ + + +
+

New user? Register here

+
+ + diff --git a/app/templates/register.html b/app/templates/register.html new file mode 100644 index 0000000..0494457 --- /dev/null +++ b/app/templates/register.html @@ -0,0 +1,18 @@ + + + + Register + + + +
+

Register

+
+ + + +
+

Already have an account? Login here

+
+ + diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..ab66084 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +Flask +Flask-SQLAlchemy +Flask-Login +passlib diff --git a/run.py b/run.py new file mode 100644 index 0000000..24f9987 --- /dev/null +++ b/run.py @@ -0,0 +1,11 @@ +from app import create_app, db +from app.models import User + +app = create_app() + +@app.before_first_request +def create_tables(): + db.create_all() + +if __name__ == '__main__': + app.run(debug=True) # Turn off debug in production