Implemented bluorints for flask

master
key 2 years ago
parent 23aa5d8cee
commit 0f0f148418

@ -3,23 +3,40 @@ from flask_sqlalchemy import SQLAlchemy
from flask_bcrypt import Bcrypt from flask_bcrypt import Bcrypt
from flask_login import LoginManager from flask_login import LoginManager
from flask_mail import Mail from flask_mail import Mail
import os from minibase.config import Config
app = Flask(__name__) # (DATABASE) Definition
app.config['SECRET_KEY'] = '5791628bb0b13ce0c676dfde280ba245' db = SQLAlchemy()
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db'
db = SQLAlchemy(app) # (PASSWORD) Hashign Program to save paswords safely
bcrypt = Bcrypt(app) bcrypt = Bcrypt()
login_manager = LoginManager(app)
# (LOGIN) Login manage plugin configuration
login_manager = LoginManager()
login_manager.login_view = 'login' login_manager.login_view = 'login'
login_manager.login_message_category = 'info' login_manager.login_message_category = 'info' #Boostrap Info Message
app.config['MAIL_SERVER']= 'smtp.googlemail.com' # (EMAIL AGENT) Definition
app.config['MAIL_PORT']= 465 mail = Mail()
app.config['MAIL_USE_TLS']= False
app.config['MAIL_USE_SSL']= True
app.config['MAIL_USERNAME']= 'kerem.yollu@gmail.com'
app.config['MAIL_PASSWORD']= 'eoilsjxjwmnfjbbj'
mail = Mail(app)
from minibase import route def create_minibase(config_class=Config):
# (FLASK) Main Flask Application
app = Flask(__name__)
app.config.from_object(Config)
# (DATABASE) Initialisation
db.init_app(app)
# (PASSWORD) Initialisation
bcrypt.init_app(app)
# (LOGIN) Initialisation
login_manager.init_app(app)
# (EMAIL AGENT) Initialisation
mail.init_app(app)
# (FLASK) Importing adn then registering blueprints
from minibase.users.routes import users
from minibase.posts.routes import posts
from minibase.main.routes import main
app.register_blueprint(users)
app.register_blueprint(posts)
app.register_blueprint(main)
# Retunr The ccreated app
return app

@ -0,0 +1,16 @@
import os
class Config:
# (FLASK) Sectret key wich will be used to secure some requests an connections
SECRET_KEY = os.environ.get('MINIBASE_SECRET_KEY')
# (SQLALCHEMY) COnfiguration
SQLALCHEMY_DATABASE_URI = os.environ.get('MINIBASE_SQLALCHEMY_DATABASE_URI')
# (MAIL AGENT) Configure mail Server to send EMails.
MAIL_SERVER = os.environ.get('MINIBASE_MAIL_SERVER')
MAIL_USERNAME = os.environ.get('MINIBASE_MAIL_USERNAME')
MAIL_PASSWORD = os.environ.get('MINIBASE_MAIL_PASSWORD')
MAIL_PORT = 465
MAIL_USE_TLS = False
MAIL_USE_SSL = True

@ -0,0 +1,21 @@
from flask import render_template, request, Blueprint
from minibase.models import Post
# Declaring a blueprint
main = Blueprint('main', __name__)
#Redirect from / and also /home routes to the /
@main.route("/")
@main.route("/home")
def home():
# (PAGINATION) Defines the page number that we will start with
page = request.args.get('page', 1, type=int)
# (POSTS) Query posts usin SQLAlchemy
posts = Post.query.order_by(Post.date_posted.asc()).paginate(per_page=2)
# (HTML) Renders the template for templates/home.html
return render_template('home.html', posts=posts)
@main.route("/about")
def about():
return render_template('about.html', title='About')

@ -1,7 +1,9 @@
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from datetime import datetime from datetime import datetime
from minibase import db, login_manager, app from minibase import db, login_manager
from flask_login import UserMixin from flask_login import UserMixin
from flask import url_for, current_app
@login_manager.user_loader @login_manager.user_loader
@ -17,12 +19,12 @@ class User(db.Model, UserMixin):
posts = db.relationship('Post', backref='author', lazy=True) posts = db.relationship('Post', backref='author', lazy=True)
def get_reset_token(self, expires_sec=1800): def get_reset_token(self, expires_sec=1800):
s = Serializer(app.config['SECRET_KEY'], expires_sec) s = Serializer(current_app.config['SECRET_KEY'], expires_sec)
return s.dumps({'user_id': self.id}).decode('utf-8') return s.dumps({'user_id': self.id}).decode('utf-8')
@staticmethod @staticmethod
def verify_reset_token(token): def verify_reset_token(token):
s = Serializer(app.config['SECRET_KEY']) s = Serializer(current_app.config['SECRET_KEY'])
try: try:
user_id = s.loads(token)['user_id'] user_id = s.loads(token)['user_id']
except: except:

@ -0,0 +1,10 @@
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, TextAreaField
from wtforms.validators import DataRequired
class postForm(FlaskForm):
title = StringField('Title',
validators=[DataRequired()])
content = TextAreaField('Content',
validators=[DataRequired()])
submit = SubmitField('Post')

@ -0,0 +1,55 @@
from flask import (render_template, url_for, flash,
redirect, request, abort, Blueprint)
from flask_login import current_user, login_required
from minibase import db
from minibase.models import Post
from minibase.posts.forms import postForm
# Declaring a blueprint
posts = Blueprint('posts', __name__)
@posts.route("/post/new", methods=['GET', 'POST'])
@login_required
def new_post():
form = postForm()
if form.validate_on_submit():
post = Post(title=form.title.data, content=form.content.data, author=current_user)
db.session.add(post)
db.session.commit()
flash('Your post has been created', 'success')
return redirect(url_for('main.home'))
return render_template('create_post.html', title='Create Post', legend='Create Post', form=form)
@posts.route("/post/<int:post_id>")
def post(post_id):
post = Post.query.get_or_404(post_id)
return render_template('post.html', title=post.title, post=post)
@posts.route("/post/<int:post_id>/update", methods=['GET', 'POST'])
@login_required
def post_update(post_id):
post = Post.query.get_or_404(post_id)
if post.author != current_user:
abort(403)
form = postForm()
if form.validate_on_submit():
post.title = form.title.data
post.content = form.content.data
db.session.commit()
flash('Your post has been updated', 'success')
return redirect(url_for('posts.post', post_id=post.id))
elif request.method == 'GET':
form.title.data = post.title
form.content.data = post.content
return render_template('create_post.html', title='Update Post', legend='Update Post', form=form)
@posts.route("/post/<int:post_id>/delete", methods=['POST'])
@login_required
def post_delete(post_id):
post = Post.query.get_or_404(post_id)
if post.author != current_user:
abort(403)
db.session.delete(post)
db.session.commit()
flash('Your post has been deleted', 'success')
return redirect(url_for('main.home'))

@ -1,183 +0,0 @@
import os
import secrets
from PIL import Image
from flask import render_template, url_for, flash, redirect, request, abort
from minibase import app, db, bcrypt, mail
from minibase.forms import registrationForm, loginForm, updateAccountForm, postForm, requestResetForm, resetPasswordForm
from minibase.models import User, Post
from flask_login import login_user, current_user, logout_user, login_required
from flask_mail import Message
#Redirect from / and also /home routes to the /
@app.route("/")
@app.route("/home")
def home():
page = request.args.get('page', 1, type=int)
posts = Post.query.order_by(Post.date_posted.asc()).paginate(per_page=2)
return render_template('home.html', posts=posts)
@app.route("/about")
def about():
return render_template('about.html', title='About')
@app.route("/register", methods=['GET', 'POST'])
def register():
if current_user.is_authenticated:
return redirect(url_for('home'))
form = registrationForm()
if form.validate_on_submit():
hashed_pw = bcrypt.generate_password_hash(form.password.data).decode('utf-8')
user = User(username=form.username.data, email=form.email.data, password=hashed_pw)
db.session.add(user)
db.session.commit()
flash(f'Your account has benn created you can now log in!','success')
return redirect(url_for('login'))
return render_template('register.html', title='Register', form=form)
@app.route("/login", methods=['GET', 'POST'])
def login():
if current_user.is_authenticated:
return redirect(url_for('home'))
form = loginForm()
if form.validate_on_submit():
user = User.query.filter_by(email=form.email.data).first()
if user and bcrypt.check_password_hash(user.password, form.password.data):
login_user(user,remember=form.remember.data)
next_page = request.args.get('next')
return redirect(next_page) if next_page else redirect(url_for('home'))
else:
flash('Login unsuccessful. Please chek your Email and Password!','danger')
return render_template('login.html', title='Login', form=form)
@app.route("/logout")
def logout():
logout_user()
return redirect(url_for('home'))
def save_picture(form_picture):
random_hex = secrets.token_hex(8)
_, f_ext =os.path.splitext(form_picture.filename)
picture_fn = random_hex + f_ext
picture_path = os.path.join(app.root_path, 'static/pics', picture_fn)
output_size = (125,125)
i = Image.open(form_picture)
i.thumbnail(output_size)
i.save(picture_path)
return picture_fn
@app.route("/account", methods=['GET', 'POST'])
@login_required
def account():
form = updateAccountForm()
if form.validate_on_submit():
if form.picture.data:
picture_file = save_picture(form.picture.data)
current_user.image_file = picture_file
current_user.username = form.username.data
current_user.email = form.email.data
db.session.commit()
flash('Your account has been updated!', 'success')
return redirect(url_for('account'))
elif request.method == 'GET':
form.username.data = current_user.username
form.email.data = current_user.email
image_file = url_for('static', filename='pics/'+ current_user.image_file)
return render_template('account.html', title='Account', image_file = image_file, form=form)
@app.route("/post/new", methods=['GET', 'POST'])
@login_required
def new_post():
form = postForm()
if form.validate_on_submit():
post = Post(title=form.title.data, content=form.content.data, author=current_user)
db.session.add(post)
db.session.commit()
flash('Your post has been created', 'success')
return redirect(url_for('home'))
return render_template('create_post.html', title='Create Post', legend='Create Post', form=form)
@app.route("/post/<int:post_id>")
def post(post_id):
post = Post.query.get_or_404(post_id)
return render_template('post.html', title=post.title, post=post)
@app.route("/post/<int:post_id>/update", methods=['GET', 'POST'])
@login_required
def post_update(post_id):
post = Post.query.get_or_404(post_id)
if post.author != current_user:
abort(403)
form = postForm()
if form.validate_on_submit():
post.title = form.title.data
post.content = form.content.data
db.session.commit()
flash('Your post has been updated', 'success')
return redirect(url_for('post', post_id=post.id))
elif request.method == 'GET':
form.title.data = post.title
form.content.data = post.content
return render_template('create_post.html', title='Update Post', legend='Update Post', form=form)
@app.route("/post/<int:post_id>/delete", methods=['POST'])
@login_required
def post_delete(post_id):
post = Post.query.get_or_404(post_id)
if post.author != current_user:
abort(403)
db.session.delete(post)
db.session.commit()
flash('Your post has been deleted', 'success')
return redirect(url_for('home'))
@app.route("/user/<string:username>")
def user_posts(username):
user = User.query.filter_by(username=username).first_or_404()
page = request.args.get('page', 1, type=int)
posts = Post.query.filter_by(author=user)\
.order_by(Post.date_posted.asc())\
.paginate(page=page, per_page=2)
return render_template('user_posts.html', posts=posts, user=user)
def send_reset_email(user):
token = user.get_reset_token()
msg = Message('Password Reset Request',
sender='noreply@demo.com',
recipients=[user.email])
msg.body = f'''To reset your password, visit the following link:
{url_for('reset_token', token=token, _external=True)}
If you didn't make this request, then simply ingnore this email and no chancges will be made.
'''
mail.send(msg)
@app.route("/reset_password", methods=['GET', 'POST'])
def reset_request():
if current_user.is_authenticated:
return redirect(url_for('home'))
form = requestResetForm()
if form.validate_on_submit():
user = User.query.filter_by(email=form.email.data).first()
send_reset_email(user)
flash('An Email has benn sent with instruction to reset your password', 'warning')
return render_template('reset_request.html', title='Reset Password', form=form)
@app.route("/reset_password/<token>", methods=['GET', 'POST'])
def reset_token(token):
if current_user.is_authenticated:
return redirect(url_for('home'))
user = User.verify_reset_token(token)
if user is None:
flash('That is an invalid or expired token', 'warning')
return redirect(url_for('reset_request'))
form = resetPasswordForm()
if form.validate_on_submit():
hashed_pw = bcrypt.generate_password_hash(form.password.data).decode('utf-8')
user.password = hashed_pw
db.session.commit()
flash(f'Your password has benn udated','success')
return redirect(url_for('login'))
return render_template('reset_token.html', title='Reset Password', form=form)

Binary file not shown.

@ -6,10 +6,10 @@
<img class="rounded-circle article-img" src="{{ url_for('static', filename='pics/' + post.author.image_file) }}"> <img class="rounded-circle article-img" src="{{ url_for('static', filename='pics/' + post.author.image_file) }}">
<div class="media-body"> <div class="media-body">
<div class="article-metadata"> <div class="article-metadata">
<a class="mr-2" href="{{ url_for('user_posts', username=post.author.username) }} ">{{ post.author.username }}</a> <a class="mr-2" href="{{ url_for('users.user_posts', username=post.author.username) }} ">{{ post.author.username }}</a>
<small class="text-muted">{{ post.date_posted.strftime('%Y-%m-%d') }}</small> <small class="text-muted">{{ post.date_posted.strftime('%Y-%m-%d') }}</small>
</div> </div>
<h2><a class="article-title" href="{{ url_for('post', post_id=post.id) }}">{{ post.title }}</a></h2> <h2><a class="article-title" href="{{ url_for('posts.post', post_id=post.id) }}">{{ post.title }}</a></h2>
<p class="article-content">{{ post.content }}</p> <p class="article-content">{{ post.content }}</p>
</div> </div>
</article> </article>
@ -17,9 +17,9 @@
{% for page_num in posts.iter_pages(left_edge=1, right_edge=1, left_current=1, right_current=2) %} {% for page_num in posts.iter_pages(left_edge=1, right_edge=1, left_current=1, right_current=2) %}
{% if page_num %} {% if page_num %}
{% if posts.page == page_num %} {% if posts.page == page_num %}
<a class="btn btn-info mb-4" href="{{ url_for('home', page=page_num) }}">{{ page_num }}</a> <a class="btn btn-info mb-4" href="{{ url_for('main.home', page=page_num) }}">{{ page_num }}</a>
{% else %} {% else %}
<a class="btn btn-outline-info mb-4" href="{{ url_for('home', page=page_num) }}">{{ page_num }}</a> <a class="btn btn-outline-info mb-4" href="{{ url_for('main.home', page=page_num) }}">{{ page_num }}</a>
{% endif %} {% endif %}
{% else %} {% else %}
... ...

@ -17,24 +17,24 @@
<header class="site-header"> <header class="site-header">
<nav class="navbar navbar-expand-md navbar-dark bg-steel fixed-top"> <nav class="navbar navbar-expand-md navbar-dark bg-steel fixed-top">
<div class="container"> <div class="container">
<a class="navbar-brand mr-4" href="{{ url_for('home') }}">MiniBase</a> <a class="navbar-brand mr-4" href="{{ url_for('main.home') }}">MiniBase</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarToggle" aria-controls="navbarToggle" aria-expanded="false" aria-label="Toggle navigation"> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarToggle" aria-controls="navbarToggle" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span> <span class="navbar-toggler-icon"></span>
</button> </button>
<div class="collapse navbar-collapse" id="navbarToggle"> <div class="collapse navbar-collapse" id="navbarToggle">
<div class="navbar-nav mr-auto"> <div class="navbar-nav mr-auto">
<a class="nav-item nav-link" href="{{ url_for('home') }}">Home</a> <a class="nav-item nav-link" href="{{ url_for('main.home') }}">Home</a>
<a class="nav-item nav-link" href="{{ url_for('about') }}">About</a> <a class="nav-item nav-link" href="{{ url_for('main.about') }}">About</a>
</div> </div>
<!-- Navbar Right Side --> <!-- Navbar Right Side -->
<div class="navbar-nav"> <div class="navbar-nav">
{% if current_user.is_authenticated %} {% if current_user.is_authenticated %}
<a class="nav-item nav-link" href="{{ url_for('new_post') }}">New Post</a> <a class="nav-item nav-link" href="{{ url_for('posts.new_post') }}">New Post</a>
<a class="nav-item nav-link" href="{{ url_for('logout') }}">Logout</a> <a class="nav-item nav-link" href="{{ url_for('users.logout') }}">Logout</a>
<a class="nav-item nav-link" href="{{ url_for('account') }}">Account</a> <a class="nav-item nav-link" href="{{ url_for('users.account') }}">Account</a>
{% else %} {% else %}
<a class="nav-item nav-link" href="{{ url_for('login') }}">Login</a> <a class="nav-item nav-link" href="{{ url_for('users.login') }}">Login</a>
<a class="nav-item nav-link" href="{{ url_for('register') }}">Register</a> <a class="nav-item nav-link" href="{{ url_for('users.register') }}">Register</a>
{% endif %} {% endif %}
</div> </div>
</div> </div>

@ -40,13 +40,13 @@
{{ form.submit(class="btn btn-outline-info") }} {{ form.submit(class="btn btn-outline-info") }}
</div> </div>
<small class="text-muted ml-2"> <small class="text-muted ml-2">
<a href="{{ url_for('reset_request') }}">Forgot Password?</a> <a href="{{ url_for('users.reset_request') }}">Forgot Password?</a>
</small> </small>
</form> </form>
</div> </div>
<div class="border-top pt-3"> <div class="border-top pt-3">
<small class="text-muted"> <small class="text-muted">
Need An Account? <a class="ml-2" href="{{ url_for('register') }}">Sign Up Now</a> Need An Account? <a class="ml-2" href="{{ url_for('users.register') }}">Sign Up Now</a>
</small> </small>
</div> </div>
{% endblock content %} {% endblock content %}

@ -5,11 +5,11 @@
<img class="rounded-circle article-img" src="{{ url_for('static', filename='pics/' + post.author.image_file) }}"> <img class="rounded-circle article-img" src="{{ url_for('static', filename='pics/' + post.author.image_file) }}">
<div class="media-body"> <div class="media-body">
<div class="article-metadata"> <div class="article-metadata">
<a class="mr-2" href="{{ url_for('user_posts', username=post.author.username) }}" >{{ post.author.username }}</a> <a class="mr-2" href="{{ url_for('users.user_posts', username=post.author.username) }}" >{{ post.author.username }}</a>
<small class="text-muted">{{ post.date_posted.strftime('%Y-%m-%d') }}</small> <small class="text-muted">{{ post.date_posted.strftime('%Y-%m-%d') }}</small>
{% if post.author == current_user %} {% if post.author == current_user %}
<div> <div>
<a class="btn btn-secondary btn-sm m-1" href="{{ url_for('post_update', post_id=post.id) }}">Update</a> <a class="btn btn-secondary btn-sm m-1" href="{{ url_for('posts.post_update', post_id=post.id) }}">Update</a>
<button type="button" class="btn btn-danger btn-sm m-1" data-bs-toggle="modal" data-bs-target="#staticBackdrop">Delete</button> <button type="button" class="btn btn-danger btn-sm m-1" data-bs-toggle="modal" data-bs-target="#staticBackdrop">Delete</button>
</div> </div>
{% endif %} {% endif %}
@ -31,7 +31,7 @@
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<form action="{{ url_for('post_delete', post_id=post.id) }}" method="POST"> <form action="{{ url_for('posts.post_delete', post_id=post.id) }}" method="POST">
<input class="btn btn-danger" type="submit" value="Delete"> <input class="btn btn-danger" type="submit" value="Delete">
</div> </div>
</div> </div>

@ -66,7 +66,7 @@
</div> </div>
<div class="border-top pt-3"> <div class="border-top pt-3">
<small class="text-muted"> <small class="text-muted">
Already Have An Account? <a class="ml-2" href="{{ url_for('login') }}">Sign In</a> Already Have An Account? <a class="ml-2" href="{{ url_for('users.login') }}">Sign In</a>
</small> </small>
</div> </div>
{% endblock content %} {% endblock content %}

@ -7,10 +7,10 @@
<img class="rounded-circle article-img" src="{{ url_for('static', filename='pics/' + post.author.image_file) }}"> <img class="rounded-circle article-img" src="{{ url_for('static', filename='pics/' + post.author.image_file) }}">
<div class="media-body"> <div class="media-body">
<div class="article-metadata"> <div class="article-metadata">
<a class="mr-2" href="{{ url_for('user_posts', username=post.author.username) }} ">{{ post.author.username }}</a> <a class="mr-2" href="{{ url_for('users.user_posts', username=post.author.username) }} ">{{ post.author.username }}</a>
<small class="text-muted">{{ post.date_posted.strftime('%Y-%m-%d') }}</small> <small class="text-muted">{{ post.date_posted.strftime('%Y-%m-%d') }}</small>
</div> </div>
<h2><a class="article-title" href="{{ url_for('post', post_id=post.id) }}">{{ post.title }}</a></h2> <h2><a class="article-title" href="{{ url_for('posts.post', post_id=post.id) }}">{{ post.title }}</a></h2>
<p class="article-content">{{ post.content }}</p> <p class="article-content">{{ post.content }}</p>
</div> </div>
</article> </article>
@ -18,9 +18,9 @@
{% for page_num in posts.iter_pages(left_edge=1, right_edge=1, left_current=1, right_current=2) %} {% for page_num in posts.iter_pages(left_edge=1, right_edge=1, left_current=1, right_current=2) %}
{% if page_num %} {% if page_num %}
{% if posts.page == page_num %} {% if posts.page == page_num %}
<a class="btn btn-info mb-4" href="{{ url_for('user_posts', username=user.username, page=page_num) }}">{{ page_num }}</a> <a class="btn btn-info mb-4" href="{{ url_for('users.user_posts', username=user.username, page=page_num) }}">{{ page_num }}</a>
{% else %} {% else %}
<a class="btn btn-outline-info mb-4" href="{{ url_for('user_posts', username=user.username, page=page_num) }}">{{ page_num }}</a> <a class="btn btn-outline-info mb-4" href="{{ url_for('users.user_posts', username=user.username, page=page_num) }}">{{ page_num }}</a>
{% endif %} {% endif %}
{% else %} {% else %}
... ...

@ -1,8 +1,8 @@
from flask_wtf import FlaskForm from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileAllowed from flask_wtf.file import FileField, FileAllowed
from flask_login import current_user from wtforms import StringField, PasswordField, SubmitField, BooleanField
from wtforms import StringField, PasswordField, SubmitField, BooleanField, TextAreaField
from wtforms.validators import DataRequired, Length, Email, EqualTo, ValidationError from wtforms.validators import DataRequired, Length, Email, EqualTo, ValidationError
from flask_login import current_user
from minibase.models import User from minibase.models import User
class registrationForm(FlaskForm): class registrationForm(FlaskForm):
@ -55,13 +55,6 @@ class updateAccountForm(FlaskForm):
if email: if email:
raise ValidationError('That email is taken do you have an acocunt ?') raise ValidationError('That email is taken do you have an acocunt ?')
class postForm(FlaskForm):
title = StringField('Title',
validators=[DataRequired(),Length(min = 3, max = 100)])
content = TextAreaField('Content',
validators=[DataRequired()])
submit = SubmitField('Post')
class requestResetForm(FlaskForm): class requestResetForm(FlaskForm):
email = StringField('Email', email = StringField('Email',
validators=[DataRequired(),Email()]) validators=[DataRequired(),Email()])

@ -0,0 +1,106 @@
from flask import render_template, url_for, flash, redirect, request, Blueprint
from flask_login import login_user, current_user, logout_user, login_required
from minibase import db, bcrypt
from minibase.models import User, Post
from minibase.users.forms import registrationForm, loginForm, updateAccountForm, requestResetForm, resetPasswordForm
from minibase.posts.forms import postForm
from minibase.users.utils import save_picture, send_reset_email
# Declaring a blueprint
users = Blueprint('users', __name__)
#Route is the file that is going to be generated
@users.route("/register", methods=['GET', 'POST'])
def register():
if current_user.is_authenticated:
return redirect(url_for('main.home'))
form = registrationForm()
if form.validate_on_submit():
hashed_pw = bcrypt.generate_password_hash(form.password.data).decode('utf-8')
user = User(username=form.username.data, email=form.email.data, password=hashed_pw)
db.session.add(user)
db.session.commit()
flash(f'Your account has benn created you can now log in!','success')
return redirect(url_for('users.login'))
return render_template('register.html', title='Register', form=form)
@users.route("/login", methods=['GET', 'POST'])
def login():
if current_user.is_authenticated:
return redirect(url_for('main.home'))
form = loginForm()
if form.validate_on_submit():
user = User.query.filter_by(email=form.email.data).first()
if user and bcrypt.check_password_hash(user.password, form.password.data):
login_user(user,remember=form.remember.data)
next_page = request.args.get('next')
return redirect(next_page) if next_page else redirect(url_for('main.home'))
else:
flash('Login unsuccessful. Please chek your Email and Password!','danger')
return render_template('login.html', title='Login', form=form)
@users.route("/logout")
def logout():
logout_user()
return redirect(url_for('main.home'))
@users.route("/account", methods=['GET', 'POST'])
@login_required
def account():
form = updateAccountForm()
if form.validate_on_submit():
if form.picture.data:
picture_file = save_picture(form.picture.data)
current_user.image_file = picture_file
current_user.username = form.username.data
current_user.email = form.email.data
db.session.commit()
flash('Your account has been updated!', 'success')
return redirect(url_for('users.account'))
elif request.method == 'GET':
form.username.data = current_user.username
form.email.data = current_user.email
image_file = url_for('static', filename='pics/'+ current_user.image_file)
return render_template('account.html', title='Account', image_file = image_file, form=form)
@users.route("/user/<string:username>")
def user_posts(username):
user = User.query.filter_by(username=username).first_or_404()
page = request.args.get('page', 1, type=int)
posts = Post.query.filter_by(author=user)\
.order_by(Post.date_posted.asc())\
.paginate(page=page, per_page=2)
return render_template('user_posts.html', posts=posts, user=user)
@users.route("/reset_password", methods=['GET', 'POST'])
def reset_request():
if current_user.is_authenticated:
return redirect(url_for('main.home'))
form = requestResetForm()
if form.validate_on_submit():
user = User.query.filter_by(email=form.email.data).first()
send_reset_email(user)
flash('An Email has benn sent with instruction to reset your password', 'warning')
return render_template('reset_request.html', title='Reset Password', form=form)
@users.route("/reset_password/<token>", methods=['GET', 'POST'])
def reset_token(token):
if current_user.is_authenticated:
return redirect(url_for('main.home'))
user = User.verify_reset_token(token)
if user is None:
flash('That is an invalid or expired token', 'warning')
return redirect(url_for('users.reset_request'))
form = resetPasswordForm()
if form.validate_on_submit():
hashed_pw = bcrypt.generate_password_hash(form.password.data).decode('utf-8')
user.password = hashed_pw
db.session.commit()
flash(f'Your password has benn udated','success')
return redirect(url_for('users.login'))
return render_template('reset_token.html', title='Reset Password', form=form)

@ -0,0 +1,28 @@
import os
import secrets
from PIL import Image
from flask import url_for, current_app
from flask_mail import Message
from minibase import mail
def save_picture(form_picture):
random_hex = secrets.token_hex(8)
_, f_ext =os.path.splitext(form_picture.filename)
picture_fn = random_hex + f_ext
picture_path = os.path.join(current_app.root_path, 'static/pics', picture_fn)
output_size = (125,125)
i = Image.open(form_picture)
i.thumbnail(output_size)
i.save(picture_path)
return picture_fn
def send_reset_email(user):
token = user.get_reset_token()
msg = Message('Password Reset Request',
sender='noreply@demo.com',
recipients=[user.email])
msg.body = f'''To reset your password, visit the following link:
{url_for('reset_token', token=token, _external=True)}
If you didn't make this request, then simply ingnore this email and no chancges will be made.
'''
mail.send(msg)
Loading…
Cancel
Save