parent
23aa5d8cee
commit
0f0f148418
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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
|
Binary file not shown.
@ -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')
|
Binary file not shown.
Binary file not shown.
@ -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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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…
Reference in new issue