Added g11-m3-4
This commit is contained in:
289
g11-m3-4/README.md
Normal file
289
g11-m3-4/README.md
Normal file
@@ -0,0 +1,289 @@
|
||||
# Flask Authentication Application
|
||||
|
||||
A complete full-stack web application with user authentication built with Flask and SQLite.
|
||||
|
||||
## 📁 Project Structure
|
||||
flask_app/
|
||||
├── app.py # Main Flask application
|
||||
├── database.py # Database setup and functions
|
||||
├── users.py # User authentication functions
|
||||
├── users.db # SQLite database
|
||||
├── requirements.txt # Python dependencies
|
||||
├── venv/ # Virtual environment
|
||||
└── templates/ # HTML templates
|
||||
├── base.html
|
||||
├── home.html
|
||||
├── login.html
|
||||
└── register.html
|
||||
|
||||
text
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
### 1. Create Project Structure
|
||||
|
||||
```bash
|
||||
cd Desktop
|
||||
mkdir flask_app
|
||||
cd flask_app
|
||||
|
||||
# Create all project files at once
|
||||
cat > app.py << 'PYEOF'
|
||||
from flask import Flask, render_template, request, redirect, url_for, session, flash
|
||||
import database
|
||||
import users
|
||||
|
||||
app = Flask(__name__)
|
||||
app.secret_key = 'your-secret-key-change-this-in-production'
|
||||
|
||||
database.init_db()
|
||||
|
||||
@app.route('/')
|
||||
def home():
|
||||
return render_template('home.html')
|
||||
|
||||
@app.route('/register', methods=['GET', 'POST'])
|
||||
def register():
|
||||
if request.method == 'POST':
|
||||
username = request.form['username']
|
||||
email = request.form['email']
|
||||
password = request.form['password']
|
||||
|
||||
success, message = users.register_user(username, email, password)
|
||||
|
||||
if success:
|
||||
flash('Registration successful! Please login.', 'success')
|
||||
return redirect(url_for('login'))
|
||||
else:
|
||||
flash(message, 'error')
|
||||
|
||||
return render_template('register.html')
|
||||
|
||||
@app.route('/login', methods=['GET', 'POST'])
|
||||
def login():
|
||||
if request.method == 'POST':
|
||||
username = request.form['username']
|
||||
password = request.form['password']
|
||||
|
||||
success, result = users.login_user(username, password)
|
||||
|
||||
if success:
|
||||
session['user_id'] = result['id']
|
||||
session['username'] = result['username']
|
||||
flash('Login successful!', 'success')
|
||||
return redirect(url_for('home'))
|
||||
else:
|
||||
flash(result, 'error')
|
||||
|
||||
return render_template('login.html')
|
||||
|
||||
@app.route('/logout')
|
||||
def logout():
|
||||
session.clear()
|
||||
flash('You have been logged out.', 'success')
|
||||
return redirect(url_for('home'))
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(debug=True)
|
||||
PYEOF
|
||||
|
||||
cat > database.py << 'DBEOF'
|
||||
import sqlite3
|
||||
|
||||
def init_db():
|
||||
conn = sqlite3.connect('users.db')
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute('''
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
username TEXT UNIQUE NOT NULL,
|
||||
email TEXT UNIQUE NOT NULL,
|
||||
password TEXT NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
''')
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
def get_db_connection():
|
||||
conn = sqlite3.connect('users.db')
|
||||
conn.row_factory = sqlite3.Row
|
||||
return conn
|
||||
DBEOF
|
||||
|
||||
cat > users.py << 'UEOF'
|
||||
from werkzeug.security import generate_password_hash, check_password_hash
|
||||
import database
|
||||
|
||||
def register_user(username, email, password):
|
||||
hashed_password = generate_password_hash(password, method='sha256')
|
||||
|
||||
try:
|
||||
conn = database.get_db_connection()
|
||||
conn.execute('INSERT INTO users (username, email, password) VALUES (?, ?, ?)',
|
||||
(username, email, hashed_password))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
return True, None
|
||||
except sqlite3.IntegrityError as e:
|
||||
return False, 'Username or email already exists!'
|
||||
|
||||
def login_user(username, password):
|
||||
conn = database.get_db_connection()
|
||||
user = conn.execute('SELECT * FROM users WHERE username = ?', (username,)).fetchone()
|
||||
conn.close()
|
||||
|
||||
if user and check_password_hash(user['password'], password):
|
||||
return True, user
|
||||
else:
|
||||
return False, 'Invalid username or password!'
|
||||
UEOF
|
||||
|
||||
# Create templates folder
|
||||
mkdir templates
|
||||
|
||||
cat > templates/base.html << 'HTML1EOF'
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% block title %}Flask Auth App{% endblock %}</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; max-width: 500px; margin: 50px auto; padding: 20px; }
|
||||
.alert { padding: 10px; margin: 10px 0; border-radius: 5px; }
|
||||
.success { background: #d4edda; color: #155724; }
|
||||
.error { background: #f8d7da; color: #721c24; }
|
||||
form { display: flex; flex-direction: column; gap: 10px; }
|
||||
input, button { padding: 10px; margin: 5px 0; }
|
||||
.nav { margin-bottom: 20px; }
|
||||
.nav a { margin-right: 15px; text-decoration: none; color: #007bff; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="nav">
|
||||
<a href="{{ url_for('home') }}">Home</a>
|
||||
{% if session.get('user_id') %}
|
||||
<a href="{{ url_for('logout') }}">Logout</a>
|
||||
{% else %}
|
||||
<a href="{{ url_for('login') }}">Login</a>
|
||||
<a href="{{ url_for('register') }}">Register</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||
{% if messages %}
|
||||
{% for category, message in messages %}
|
||||
<div class="alert {{ category }}">{{ message }}</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
|
||||
{% block content %}{% endblock %}
|
||||
</body>
|
||||
</html>
|
||||
HTML1EOF
|
||||
|
||||
cat > templates/home.html << 'HTML2EOF'
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Home{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Welcome to Flask Auth App</h1>
|
||||
{% if session.get('user_id') %}
|
||||
<h2>Hello, {{ session.get('username') }}!</h2>
|
||||
<p>You are logged in.</p>
|
||||
<p>This is your dashboard.</p>
|
||||
{% else %}
|
||||
<p>Please <a href="{{ url_for('login') }}">login</a> or <a href="{{ url_for('register') }}">register</a>.</p>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
HTML2EOF
|
||||
|
||||
cat > templates/register.html << 'HTML3EOF'
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Register{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Register</h2>
|
||||
<form method="POST" action="{{ url_for('register') }}">
|
||||
<input type="text" name="username" placeholder="Username" required>
|
||||
<input type="email" name="email" placeholder="Email" required>
|
||||
<input type="password" name="password" placeholder="Password" required>
|
||||
<button type="submit">Register</button>
|
||||
</form>
|
||||
<p>Already have an account? <a href="{{ url_for('login') }}">Login here</a></p>
|
||||
{% endblock %}
|
||||
HTML3EOF
|
||||
|
||||
cat > templates/login.html << 'HTML4EOF'
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Login{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Login</h2>
|
||||
<form method="POST" action="{{ url_for('login') }}">
|
||||
<input type="text" name="username" placeholder="Username" required>
|
||||
<input type="password" name="password" placeholder="Password" required>
|
||||
<button type="submit">Login</button>
|
||||
</form>
|
||||
<p>Don't have an account? <a href="{{ url_for('register') }}">Register here</a></p>
|
||||
{% endblock %}
|
||||
HTML4EOF
|
||||
2. Create Virtual Environment
|
||||
bash
|
||||
python -m venv venv
|
||||
venv\Scripts\Activate.ps1
|
||||
If you get an error:
|
||||
|
||||
bash
|
||||
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
|
||||
venv\Scripts\Activate.ps1
|
||||
3. Install Dependencies
|
||||
bash
|
||||
pip install flask werkzeug flask-wtf
|
||||
pip freeze > requirements.txt
|
||||
4. Run the Application
|
||||
bash
|
||||
python app.py
|
||||
Visit: http://127.0.0.1:5000
|
||||
|
||||
📋 File Purpose
|
||||
File Purpose Contains
|
||||
app.py Main Flask application Routes, request handling, session management
|
||||
database.py Database operations Connection functions, table creation, SQL queries
|
||||
users.py User authentication Register, login, password hashing functions
|
||||
templates/ HTML templates Base template and page-specific templates
|
||||
requirements.txt Dependencies List of Python packages needed
|
||||
users.db Database file SQLite database with user data
|
||||
🔒 Security Notes
|
||||
This is a learning example, not production-ready
|
||||
|
||||
Passwords are hashed using Werkzeug
|
||||
|
||||
Never store plain text passwords
|
||||
|
||||
Use stronger secret keys in production
|
||||
|
||||
🚀 Next Steps
|
||||
Add password reset functionality
|
||||
|
||||
Implement email verification
|
||||
|
||||
Add user profile pages
|
||||
|
||||
Create a simple blog system
|
||||
|
||||
Deploy to Heroku or Render
|
||||
|
||||
📚 Resources
|
||||
Flask Documentation
|
||||
|
||||
SQLite Documentation
|
||||
|
||||
Jinja2 Template Documentation
|
||||
Reference in New Issue
Block a user