Skip to content

Commit f4092ec

Browse files
Migrations and Seeders Added, Auth Templates and Backend UI Added
1 parent 7550878 commit f4092ec

22 files changed

+363
-45
lines changed

.gitignore

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,10 @@ venv
22
virtualenv
33
.env
44
storage/public/*
5-
.vscode
5+
.vscode
6+
.idea
7+
.DS_Store
8+
redis.conf
9+
redis-data
10+
*.log
11+
.pytest_cache

app/__init__.py

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ def factory(config=DevelopmentConfig) -> Flask:
2727
'CACHE_TYPE': 'RedisCache',
2828
'CACHE_REDIS_HOST': config.REDIS_HOST,
2929
}
30-
cache.init_app(app, config=cache_config)
30+
# Enable to use Redis as cache backend
31+
# cache.init_app(app, config=cache_config)
3132

3233
# initialize mail
3334
mail.init_app(app)
@@ -57,7 +58,7 @@ def factory(config=DevelopmentConfig) -> Flask:
5758

5859

5960
def register_login_manager(app):
60-
login_manager.login_view = 'auth.login_page'
61+
login_manager.login_view = 'auth.login'
6162
login_manager.init_app(app)
6263
login_manager.session_protection = 'strong'
6364
login_manager.login_message = 'Please login to access this page.'
@@ -91,7 +92,7 @@ def register_logging(app) -> None:
9192
app.logger.removeHandler(default_handler)
9293

9394
# Create a file handler object
94-
file_handler = RotatingFileHandler('flaskapp.log', maxBytes=16384, backupCount=20)
95+
file_handler = RotatingFileHandler('storage/logs/flaskapp.log', maxBytes=16384, backupCount=20)
9596

9697
# Set the logging level of the file handler object so that it logs INFO and up
9798
file_handler.setLevel(logging.INFO)
@@ -110,39 +111,44 @@ def register_error_handlers(app) -> None:
110111
# 400 - Bad Request
111112
@app.errorhandler(400)
112113
def bad_request(e):
113-
return render_template('errors/400.html', context={
114+
data = {
114115
"title": 400,
115116
"message": "Bad Request"
116-
}), 400
117+
}
118+
return render_template('errors/400.html', **data), 400
117119

118120
# 403 - Forbidden
119121
@app.errorhandler(403)
120122
def forbidden(e):
121-
return render_template('errors/403.html', context={
123+
data = {
122124
"title": 403,
123125
"message": "Forbidden"
124-
}), 403
126+
}
127+
return render_template('errors/403.html', **data), 403
125128

126129
# 404 - Page Not Found
127130
@app.errorhandler(404)
128131
def page_not_found(e):
129-
return render_template('errors/404.html', context={
132+
data = {
130133
"title": 404,
131134
"message": "Page not found"
132-
}), 404
135+
}
136+
return render_template('errors/404.html', **data), 404
133137

134138
# 405 - Method Not Allowed
135139
@app.errorhandler(405)
136140
def method_not_allowed(e):
137-
return render_template('errors/405.html', context={
141+
data = {
138142
"title": 405,
139143
"message": "Method Not Allowed"
140-
}), 405
144+
}
145+
return render_template('errors/405.html', **data), 405
141146

142147
# 500 - Internal Server Error
143148
@app.errorhandler(500)
144149
def server_error(e):
145-
return render_template('errors/500.html', context={
150+
data = {
146151
"title": 500,
147152
"message": "Internal Server Error"
148-
}), 500
153+
}
154+
return render_template('errors/500.html', **data), 500

app/controllers/AuthController.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
from app.models.User import User
22
from app.forms import ForgotPasswordForm, LoginForm
33
from flask import render_template, redirect, request
4-
from flask_login import login_user, logout_user, login_required, current_user
4+
from flask_login import login_user, logout_user, login_required
55

66

77
class AuthController():
88

99
@staticmethod
1010
def login():
11+
"""
12+
Login page
13+
"""
1114
form = LoginForm()
1215
if request.method == 'GET':
1316
return render_template('pages/auth/login.html', title='Login', form=form)
@@ -24,7 +27,7 @@ def login():
2427
login_user(user)
2528
return redirect('/home')
2629

27-
return render_template('pages/auth/login.html', title='Login', form=form, message="User not found!")
30+
return render_template('pages/auth/login.html', title='Login', form=form, message="Invalid credentials!")
2831

2932
def register():
3033
"""
@@ -56,8 +59,21 @@ def logout():
5659

5760
@login_required
5861
def profile():
59-
return render_template('pages/auth/profile.html', title='Profile', user=current_user)
62+
data = {
63+
'title': 'Profile',
64+
}
65+
return render_template('pages/auth/profile.html', **data)
6066

6167
@login_required
6268
def home():
63-
return render_template('pages/auth/home.html', title='Home', user=current_user)
69+
data = {
70+
'title': 'Home',
71+
}
72+
return render_template('pages/auth/home.html', **data)
73+
74+
@login_required
75+
def settings():
76+
data = {
77+
'title': 'Settings',
78+
}
79+
return render_template('pages/auth/settings.html', **data)

app/controllers/WelcomeController.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,24 @@ class WelcomeController():
66

77
@staticmethod
88
def index():
9-
return render_template("pages/index.html")
9+
data = {
10+
'title': 'Home Page',
11+
}
12+
return render_template("pages/index.html", **data)
1013

1114
@staticmethod
1215
def about():
13-
return render_template("pages/about.html")
16+
data = {
17+
'title': 'About Page',
18+
}
19+
return render_template("pages/about.html", **data)
1420

1521
@staticmethod
1622
def contact():
17-
return render_template("pages/contact.html")
23+
data = {
24+
'title': 'Contact Page',
25+
}
26+
return render_template("pages/contact.html", **data)
1827

1928
@staticmethod
2029
def file_upload():

app/models/User.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
from app import db
22
from flask_login import UserMixin
3+
from werkzeug.security import check_password_hash
34

45

56
class User(db.Model, UserMixin):
67

7-
__fillable__ = ['name', 'email']
8+
__fillable__ = ['name', 'email', 'password', 'email_verified_at']
89

910
def check_password(self, password):
10-
return True
11+
return check_password_hash(self.password, password)
1112

1213
def send_password_reset_email(self):
1314
from app.jobs.MailJob import send_mail_job
1415
message_data = {
1516
'subject': 'Reset Password',
1617
'body': 'This email was sent asynchronously using Celery.',
1718
'recipients': self.email,
18-
1919
}
2020
send_mail_job.apply_async(args=[message_data])
2121

app/views/layouts/base.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
<body>
1414
{% block content %}
1515
{% endblock %}
16+
<script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.x.x/dist/alpine.min.js" defer></script>
1617
</body>
1718

1819
</html>

app/views/layouts/dashboard.html

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="UTF-8">
6+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
7+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
8+
<title>{{ title }}</title>
9+
<link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">
10+
11+
</head>
12+
13+
<body>
14+
<div class="min-h-screen flex flex-col flex-auto flex-shrink-0 antialiased relative bg-gray-50 text-gray-800">
15+
{% include 'partials/navbar.html' %}
16+
{% include 'partials/sidebar.html' %}
17+
<main class="flex flex-col w-full min-h-screen flex-1 overflow-hidden pl-64">
18+
<div class="content min-h-full">
19+
{% block content %}
20+
{% endblock %}
21+
</div>
22+
</main>
23+
</div>
24+
<script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.x.x/dist/alpine.min.js" defer></script>
25+
</body>
26+
27+
</html>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{% macro with_errors(field) %}
2+
<div class="form_field">
3+
{% if field.errors %}
4+
{% set label_class = 'text-red-600 font-semibold text-sm text-gray-600 pb-1 block' %}
5+
{% set input_class = 'ring-2 ring-red-600 text-red focus:outline-none focus:ring-2 focus:ring-red-600
6+
focus:border-transparent text-red-600' +
7+
kwargs.pop('class',
8+
'') %}
9+
{{ field.label(class=label_class, **kwargs) }}
10+
{{ field(class=input_class, **kwargs) }}
11+
{% else %}
12+
{{ field.label(class="font-semibold text-sm text-gray-600 pb-1 block") }}
13+
{{ field(**kwargs) }}
14+
{% endif %}
15+
</div>
16+
{% endmacro %}

app/views/pages/auth/home.html

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
{% extends "layouts/base.html" %}
1+
{% extends "layouts/dashboard.html" %}
22

33
{% block content %}
44

5-
<div class="min-h-screen bg-gray-100 flex flex-col justify-center sm:py-12">
5+
<div class="min-h-screen flex flex-col justify-center sm:py-12">
66
<div class="p-10 xs:p-0 mx-auto md:w-full md:max-w-md">
7-
<h1 class="font-bold text-center text-2xl">Welcome, {{ user.name }}!</h1>
8-
<a href="/logout" class="font-bold block text-xs text-center underline cursor-pointer">Logout</a>
7+
<h1 class="font-bold text-center text-2xl">Welcome, {{ current_user.name }}!</h1>
8+
<span class="font-bold block text-xs text-center underline cursor-pointer">A basic template that you
9+
can customize as per your need.</span>
910
</div>
1011
</div>
1112

app/views/pages/auth/login.html

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{% extends "layouts/base.html" %}
2-
2+
{% import "macros/form_input_validation.html" as form_input %}
33
{% block content %}
44

55
<div class="min-h-screen bg-gray-100 flex flex-col justify-center sm:py-12">
@@ -10,12 +10,18 @@ <h1 class="font-bold text-center text-2xl mb-5">Your Logo</h1>
1010
<form class="w-full" method="POST" action="/login">
1111
{{ form.csrf_token }}
1212

13-
{{ form.email.label(class_="font-semibold text-sm text-gray-600 pb-1 block") }}
14-
{{ form.email(class_="border rounded-lg px-3 py-2 mt-1 mb-5 text-sm w-full", autofocus="") }}
13+
{{ form_input.with_errors(form.email, class="border rounded px-3 py-2 mt-1 mb-5 text-sm w-full",
14+
autofocus="") }}
1515

16-
{{ form.password.label(class_="font-semibold text-sm text-gray-600 pb-1 block") }}
17-
{{ form.password(class_="border rounded-lg px-3 py-2 mt-1 mb-5 text-sm w-full", autofocus="") }}
16+
{{ form_input.with_errors(form.password, class="border rounded px-3 py-2 mt-1 mb-5 text-sm w-full",
17+
autofocus="") }}
1818

19+
{% if message %}
20+
<div class="text-red-600 text-xs mb-3 text-center">
21+
<strong class="font-bold">Whoops!</strong>
22+
<span class="block sm:inline">{{ message }}</span>
23+
</div>
24+
{% endif %}
1925
<button type="submit"
2026
class="transition duration-200 bg-blue-500 hover:bg-blue-600 focus:bg-blue-700 focus:shadow-sm focus:ring-4 focus:ring-blue-500 focus:ring-opacity-50 text-white w-full py-2.5 rounded-lg text-sm shadow-sm hover:shadow-md font-semibold text-center inline-block">
2127
<span class="inline-block mr-2">Login</span>

0 commit comments

Comments
 (0)