diff --git a/webinterface/minibase/__init__.py b/webinterface/minibase/__init__.py index c9ac9c9a..d02dfb5a 100644 --- a/webinterface/minibase/__init__.py +++ b/webinterface/minibase/__init__.py @@ -3,23 +3,40 @@ from flask_sqlalchemy import SQLAlchemy from flask_bcrypt import Bcrypt from flask_login import LoginManager from flask_mail import Mail -import os +from minibase.config import Config -app = Flask(__name__) -app.config['SECRET_KEY'] = '5791628bb0b13ce0c676dfde280ba245' -app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db' -db = SQLAlchemy(app) -bcrypt = Bcrypt(app) -login_manager = LoginManager(app) +# (DATABASE) Definition +db = SQLAlchemy() + +# (PASSWORD) Hashign Program to save paswords safely +bcrypt = Bcrypt() + +# (LOGIN) Login manage plugin configuration +login_manager = LoginManager() 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' -app.config['MAIL_PORT']= 465 -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) +# (EMAIL AGENT) Definition +mail = Mail() -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 diff --git a/webinterface/minibase/__pycache__/__init__.cpython-311.pyc b/webinterface/minibase/__pycache__/__init__.cpython-311.pyc index c6ad3d3a..382b7812 100644 Binary files a/webinterface/minibase/__pycache__/__init__.cpython-311.pyc and b/webinterface/minibase/__pycache__/__init__.cpython-311.pyc differ diff --git a/webinterface/minibase/__pycache__/config.cpython-311.pyc b/webinterface/minibase/__pycache__/config.cpython-311.pyc new file mode 100644 index 00000000..0b0980f9 Binary files /dev/null and b/webinterface/minibase/__pycache__/config.cpython-311.pyc differ diff --git a/webinterface/minibase/__pycache__/forms.cpython-311.pyc b/webinterface/minibase/__pycache__/forms.cpython-311.pyc deleted file mode 100644 index 1a341918..00000000 Binary files a/webinterface/minibase/__pycache__/forms.cpython-311.pyc and /dev/null differ diff --git a/webinterface/minibase/__pycache__/models.cpython-311.pyc b/webinterface/minibase/__pycache__/models.cpython-311.pyc index 6f89b6b8..e00fef29 100644 Binary files a/webinterface/minibase/__pycache__/models.cpython-311.pyc and b/webinterface/minibase/__pycache__/models.cpython-311.pyc differ diff --git a/webinterface/minibase/__pycache__/route.cpython-311.pyc b/webinterface/minibase/__pycache__/route.cpython-311.pyc deleted file mode 100644 index d3c9bcad..00000000 Binary files a/webinterface/minibase/__pycache__/route.cpython-311.pyc and /dev/null differ diff --git a/webinterface/minibase/config.py b/webinterface/minibase/config.py new file mode 100644 index 00000000..1d06dc9f --- /dev/null +++ b/webinterface/minibase/config.py @@ -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 diff --git a/webinterface/minibase/main/__init.py__ b/webinterface/minibase/main/__init.py__ new file mode 100644 index 00000000..e69de29b diff --git a/webinterface/minibase/main/__pycache__/routes.cpython-311.pyc b/webinterface/minibase/main/__pycache__/routes.cpython-311.pyc new file mode 100644 index 00000000..6ef2a091 Binary files /dev/null and b/webinterface/minibase/main/__pycache__/routes.cpython-311.pyc differ diff --git a/webinterface/minibase/main/routes.py b/webinterface/minibase/main/routes.py new file mode 100644 index 00000000..33ddd5f5 --- /dev/null +++ b/webinterface/minibase/main/routes.py @@ -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') diff --git a/webinterface/minibase/models.py b/webinterface/minibase/models.py index f1027200..8fc03a9b 100644 --- a/webinterface/minibase/models.py +++ b/webinterface/minibase/models.py @@ -1,7 +1,9 @@ from itsdangerous import TimedJSONWebSignatureSerializer as Serializer from datetime import datetime -from minibase import db, login_manager, app +from minibase import db, login_manager from flask_login import UserMixin +from flask import url_for, current_app + @login_manager.user_loader @@ -17,12 +19,12 @@ class User(db.Model, UserMixin): posts = db.relationship('Post', backref='author', lazy=True) 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') @staticmethod def verify_reset_token(token): - s = Serializer(app.config['SECRET_KEY']) + s = Serializer(current_app.config['SECRET_KEY']) try: user_id = s.loads(token)['user_id'] except: diff --git a/webinterface/minibase/posts/__init.py__ b/webinterface/minibase/posts/__init.py__ new file mode 100644 index 00000000..e69de29b diff --git a/webinterface/minibase/posts/__pycache__/forms.cpython-311.pyc b/webinterface/minibase/posts/__pycache__/forms.cpython-311.pyc new file mode 100644 index 00000000..8277c37b Binary files /dev/null and b/webinterface/minibase/posts/__pycache__/forms.cpython-311.pyc differ diff --git a/webinterface/minibase/posts/__pycache__/routes.cpython-311.pyc b/webinterface/minibase/posts/__pycache__/routes.cpython-311.pyc new file mode 100644 index 00000000..b6ad163e Binary files /dev/null and b/webinterface/minibase/posts/__pycache__/routes.cpython-311.pyc differ diff --git a/webinterface/minibase/posts/forms.py b/webinterface/minibase/posts/forms.py new file mode 100644 index 00000000..e433ce9a --- /dev/null +++ b/webinterface/minibase/posts/forms.py @@ -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') diff --git a/webinterface/minibase/posts/routes.py b/webinterface/minibase/posts/routes.py new file mode 100644 index 00000000..b3ed2eba --- /dev/null +++ b/webinterface/minibase/posts/routes.py @@ -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/") +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//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//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')) diff --git a/webinterface/minibase/route.py b/webinterface/minibase/route.py deleted file mode 100644 index 4d241c02..00000000 --- a/webinterface/minibase/route.py +++ /dev/null @@ -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/") -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//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//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/") -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/", 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) diff --git a/webinterface/minibase/site.db b/webinterface/minibase/site.db index 2cf6104d..026ba317 100644 Binary files a/webinterface/minibase/site.db and b/webinterface/minibase/site.db differ diff --git a/webinterface/minibase/templates/home.html b/webinterface/minibase/templates/home.html index 1b25ca00..fb7d0603 100644 --- a/webinterface/minibase/templates/home.html +++ b/webinterface/minibase/templates/home.html @@ -6,10 +6,10 @@
-

{{ post.title }}

+

{{ post.title }}

{{ post.content }}

@@ -17,9 +17,9 @@ {% for page_num in posts.iter_pages(left_edge=1, right_edge=1, left_current=1, right_current=2) %} {% if page_num %} {% if posts.page == page_num %} - {{ page_num }} + {{ page_num }} {% else %} - {{ page_num }} + {{ page_num }} {% endif %} {% else %} ... diff --git a/webinterface/minibase/templates/layout.html b/webinterface/minibase/templates/layout.html index 7672370d..27afe0ec 100644 --- a/webinterface/minibase/templates/layout.html +++ b/webinterface/minibase/templates/layout.html @@ -17,24 +17,24 @@