Add authentication system and admin dashboard
Security Features:
- Added User model with bcrypt password hashing
- Implemented Flask-Login for session management
- Protected all API write operations with @login_required decorator
- Added authentication routes (login/logout)
Admin Dashboard:
- Created comprehensive admin dashboard with statistics
- Profile management interface
- Skills management (add/edit/delete)
- Projects management with full CRUD operations
- Social links management
- Modern responsive UI with Bootstrap 5
New Files:
- models.py: Added User model with bcrypt
- routes/auth.py: Login/logout functionality
- routes/admin.py: Complete admin dashboard with CRUD operations
- templates/auth/login.html: Login page
- templates/admin/base.html: Admin base template
- templates/admin/dashboard.html: Main dashboard
- templates/admin/profile.html: Profile editor
- templates/admin/skills.html: Skills manager
- templates/admin/projects.html: Projects list
- templates/admin/project_form.html: Project editor
- templates/admin/social_links.html: Social links manager
Modified Files:
- app.py: Integrated Flask-Login and bcrypt, registered new blueprints
- requirements.txt: Added Flask-Login, Flask-Bcrypt, bcrypt
- init_db.py: Creates default admin user (admin/admin123)
- routes/api.py: Protected all write operations with authentication
Default Credentials:
- Username: admin
- Password: admin123
- ⚠️ MUST be changed after first login!
Benefits:
- Secure API access with session-based authentication
- User-friendly admin interface for content management
- No need to edit code or database directly
- Bcrypt password hashing for security
- Protected against unauthorized access
This commit is contained in:
@@ -6,9 +6,11 @@
|
||||
"""
|
||||
API Routes for managing portfolio data dynamically
|
||||
Provides REST endpoints for CRUD operations on Profile, Skills, Projects, and Social Links
|
||||
All write operations (POST, PUT, DELETE) require authentication
|
||||
"""
|
||||
|
||||
from flask import Blueprint, jsonify, request
|
||||
from flask_login import login_required
|
||||
from models import db, Profile, Skill, Project, ProjectTag, SocialLink
|
||||
|
||||
route_api = Blueprint('api', __name__, url_prefix='/api')
|
||||
@@ -28,6 +30,7 @@ def get_profile():
|
||||
|
||||
|
||||
@route_api.route('/profile', methods=['PUT'])
|
||||
@login_required
|
||||
def update_profile():
|
||||
"""Update profile information"""
|
||||
profile = Profile.query.first()
|
||||
@@ -58,6 +61,7 @@ def get_skills():
|
||||
|
||||
|
||||
@route_api.route('/skills', methods=['POST'])
|
||||
@login_required
|
||||
def create_skill():
|
||||
"""Create a new skill"""
|
||||
data = request.json
|
||||
@@ -75,6 +79,7 @@ def create_skill():
|
||||
|
||||
|
||||
@route_api.route('/skills/<int:skill_id>', methods=['PUT'])
|
||||
@login_required
|
||||
def update_skill(skill_id):
|
||||
"""Update a skill"""
|
||||
skill = Skill.query.get_or_404(skill_id)
|
||||
@@ -92,6 +97,7 @@ def update_skill(skill_id):
|
||||
|
||||
|
||||
@route_api.route('/skills/<int:skill_id>', methods=['DELETE'])
|
||||
@login_required
|
||||
def delete_skill(skill_id):
|
||||
"""Delete a skill"""
|
||||
skill = Skill.query.get_or_404(skill_id)
|
||||
@@ -112,6 +118,7 @@ def get_projects():
|
||||
|
||||
|
||||
@route_api.route('/projects', methods=['POST'])
|
||||
@login_required
|
||||
def create_project():
|
||||
"""Create a new project"""
|
||||
data = request.json
|
||||
@@ -144,6 +151,7 @@ def create_project():
|
||||
|
||||
|
||||
@route_api.route('/projects/<int:project_id>', methods=['PUT'])
|
||||
@login_required
|
||||
def update_project(project_id):
|
||||
"""Update a project"""
|
||||
project = Project.query.get_or_404(project_id)
|
||||
@@ -177,6 +185,7 @@ def update_project(project_id):
|
||||
|
||||
|
||||
@route_api.route('/projects/<int:project_id>', methods=['DELETE'])
|
||||
@login_required
|
||||
def delete_project(project_id):
|
||||
"""Delete a project"""
|
||||
project = Project.query.get_or_404(project_id)
|
||||
@@ -197,6 +206,7 @@ def get_social_links():
|
||||
|
||||
|
||||
@route_api.route('/social-links', methods=['POST'])
|
||||
@login_required
|
||||
def create_social_link():
|
||||
"""Create a new social link"""
|
||||
data = request.json
|
||||
@@ -214,6 +224,7 @@ def create_social_link():
|
||||
|
||||
|
||||
@route_api.route('/social-links/<int:link_id>', methods=['PUT'])
|
||||
@login_required
|
||||
def update_social_link(link_id):
|
||||
"""Update a social link"""
|
||||
link = SocialLink.query.get_or_404(link_id)
|
||||
@@ -231,6 +242,7 @@ def update_social_link(link_id):
|
||||
|
||||
|
||||
@route_api.route('/social-links/<int:link_id>', methods=['DELETE'])
|
||||
@login_required
|
||||
def delete_social_link(link_id):
|
||||
"""Delete a social link"""
|
||||
link = SocialLink.query.get_or_404(link_id)
|
||||
|
||||
Reference in New Issue
Block a user