diff --git a/web/__pycache__/initCMD.cpython-311.pyc b/web/__pycache__/initCMD.cpython-311.pyc new file mode 100644 index 00000000..4c9ea31c Binary files /dev/null and b/web/__pycache__/initCMD.cpython-311.pyc differ diff --git a/web/initCMD.py b/web/initCMD.py new file mode 100644 index 00000000..f18f038a --- /dev/null +++ b/web/initCMD.py @@ -0,0 +1,7 @@ +from minibase.app import db, create_app, bcrypt +from minibase.blueprints.user.models import Users, User_Roles +from minibase.blueprints.geography.models import Countries + +app = create_app() +app.app_context().push() + diff --git a/web/instance/test.db b/web/instance/test.db index 4359c194..aa84c875 100644 Binary files a/web/instance/test.db and b/web/instance/test.db differ diff --git a/web/minibase/__pycache__/app.cpython-311.pyc b/web/minibase/__pycache__/app.cpython-311.pyc index 54c41c69..62a77416 100644 Binary files a/web/minibase/__pycache__/app.cpython-311.pyc and b/web/minibase/__pycache__/app.cpython-311.pyc differ diff --git a/web/minibase/__pycache__/theme.cpython-311.pyc b/web/minibase/__pycache__/theme.cpython-311.pyc index 743f63b2..b4fcfef9 100644 Binary files a/web/minibase/__pycache__/theme.cpython-311.pyc and b/web/minibase/__pycache__/theme.cpython-311.pyc differ diff --git a/web/minibase/app.py b/web/minibase/app.py index 46174c19..235c0f6b 100644 --- a/web/minibase/app.py +++ b/web/minibase/app.py @@ -38,8 +38,11 @@ def create_app(): # import and register all blueprints. from minibase.blueprints.main.routes import main from minibase.blueprints.user.routes import user + from minibase.blueprints.errors.routes import errors app.register_blueprint(main, url_prefix='/') app.register_blueprint(user, url_prefix='/user') - + app.register_blueprint(errors, url_prefix='/errors') + + return app diff --git a/web/minibase/blueprints/database/__init__.py b/web/minibase/blueprints/database/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/web/minibase/blueprints/database/__pycache__/__init__.cpython-311.pyc b/web/minibase/blueprints/database/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 00000000..0a3380d4 Binary files /dev/null and b/web/minibase/blueprints/database/__pycache__/__init__.cpython-311.pyc differ diff --git a/web/minibase/blueprints/database/__pycache__/utils.cpython-311.pyc b/web/minibase/blueprints/database/__pycache__/utils.cpython-311.pyc new file mode 100644 index 00000000..bd71cb44 Binary files /dev/null and b/web/minibase/blueprints/database/__pycache__/utils.cpython-311.pyc differ diff --git a/web/minibase/blueprints/database/utils.py b/web/minibase/blueprints/database/utils.py new file mode 100644 index 00000000..b044bed4 --- /dev/null +++ b/web/minibase/blueprints/database/utils.py @@ -0,0 +1,32 @@ +from minibase.app import db + + +class table_printable: + def __init__(self, table, link_for_item, item_to_be_linked): + self.titles = table.__table__.columns.keys() + self.lines = table.query.all() + self.link_for_item = link_for_item + self.item_to_be_linked = item_to_be_linked + self.paginate = 0 + +# https://www.youtube.com/watch?v=PSWf2TjTGNY&list=PL-osiE80TeTs4UjLw5MM6OjgkjFeUxCYH&index=9 +class table_printable_paginate: + def __init__(self, table, current_page, per_page, link_for_item, item_to_be_linked): + self.titles = table.__table__.columns.keys() + self.lines = table.query.paginate(page=current_page, per_page=per_page) + self.link_for_item = link_for_item + self.item_to_be_linked = item_to_be_linked + self.paginate = 1 + + +def dbAdd(dbClass): + db.session.add(dbClass) + + +def dbCommit(): + db.session.commit() + + +def dbAddAndCommit(dbClass): + db.session.add(dbClass) + db.session.commit() diff --git a/web/minibase/blueprints/errors/__init__.py b/web/minibase/blueprints/errors/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/web/minibase/blueprints/errors/__pycache__/__init__.cpython-311.pyc b/web/minibase/blueprints/errors/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 00000000..d8833b52 Binary files /dev/null and b/web/minibase/blueprints/errors/__pycache__/__init__.cpython-311.pyc differ diff --git a/web/minibase/blueprints/errors/__pycache__/routes.cpython-311.pyc b/web/minibase/blueprints/errors/__pycache__/routes.cpython-311.pyc new file mode 100644 index 00000000..1d319e99 Binary files /dev/null and b/web/minibase/blueprints/errors/__pycache__/routes.cpython-311.pyc differ diff --git a/web/minibase/blueprints/errors/routes.py b/web/minibase/blueprints/errors/routes.py new file mode 100644 index 00000000..194650ce --- /dev/null +++ b/web/minibase/blueprints/errors/routes.py @@ -0,0 +1,8 @@ +from flask import Blueprint, render_template +import minibase.theme as theme + +errors = Blueprint('errors', __name__, template_folder='templates') + +@errors.app_errorhandler(403) +def error_403(error): + return render_template('errors/403.html', theme=theme), 403 diff --git a/web/minibase/blueprints/errors/templates/errors/403.html b/web/minibase/blueprints/errors/templates/errors/403.html new file mode 100644 index 00000000..4f85b3da --- /dev/null +++ b/web/minibase/blueprints/errors/templates/errors/403.html @@ -0,0 +1,9 @@ +{% extends "base.html" %} + +{% block content %} +
+

Your dont have permission to do that (403)

+

PLease Check your account and try again

+
+ +{% endblock content %} diff --git a/web/minibase/blueprints/main/__pycache__/routes.cpython-311.pyc b/web/minibase/blueprints/main/__pycache__/routes.cpython-311.pyc index a9405ad9..fab30cb1 100644 Binary files a/web/minibase/blueprints/main/__pycache__/routes.cpython-311.pyc and b/web/minibase/blueprints/main/__pycache__/routes.cpython-311.pyc differ diff --git a/web/minibase/blueprints/main/routes.py b/web/minibase/blueprints/main/routes.py index 240d99f8..6d04cc22 100644 --- a/web/minibase/blueprints/main/routes.py +++ b/web/minibase/blueprints/main/routes.py @@ -1,10 +1,11 @@ -from flask import Flask, url_for, render_template, Blueprint -from flask_login import current_user +from flask import render_template, Blueprint, request +from flask_login import login_user, current_user, logout_user, login_required from flask_wtf import FlaskForm -from wtforms import StringField, PasswordField +from wtforms import StringField import minibase.theme as theme from minibase.blueprints.user.models import Users, User_Roles -from sqlalchemy import inspect +from minibase.blueprints.geography.models import Countries +import minibase.blueprints.database.utils as dbUtils main = Blueprint('main', __name__, template_folder='templates') @@ -15,9 +16,5 @@ class LoginForm(FlaskForm): @main.route('/', methods=['GET', 'POST']) def index(): - titles = User_Roles.__table__.columns.keys() - items = User_Roles.query.all() - item_link = "/user/link/" - return render_template('/main/index.html', theme=theme, table=items, titles=titles, item_link=item_link) - - + info = dir(current_user) + return render_template('/main/index.html', info=info, theme=theme) diff --git a/web/minibase/blueprints/main/templates/main/index.html b/web/minibase/blueprints/main/templates/main/index.html index 18511b15..f81097c3 100644 --- a/web/minibase/blueprints/main/templates/main/index.html +++ b/web/minibase/blueprints/main/templates/main/index.html @@ -4,5 +4,5 @@ {% block content %}

Hompage of Minibase

-{% include 'table.html' %} -{% endblock %} +{{ info }} +{% endblock %} diff --git a/web/minibase/blueprints/user/__pycache__/forms.cpython-311.pyc b/web/minibase/blueprints/user/__pycache__/forms.cpython-311.pyc index 046a5eb2..0dbd8cd6 100644 Binary files a/web/minibase/blueprints/user/__pycache__/forms.cpython-311.pyc and b/web/minibase/blueprints/user/__pycache__/forms.cpython-311.pyc differ diff --git a/web/minibase/blueprints/user/__pycache__/models.cpython-311.pyc b/web/minibase/blueprints/user/__pycache__/models.cpython-311.pyc index fe627340..dad7cd5f 100644 Binary files a/web/minibase/blueprints/user/__pycache__/models.cpython-311.pyc and b/web/minibase/blueprints/user/__pycache__/models.cpython-311.pyc differ diff --git a/web/minibase/blueprints/user/__pycache__/routes.cpython-311.pyc b/web/minibase/blueprints/user/__pycache__/routes.cpython-311.pyc index 145bc9b6..0d67d268 100644 Binary files a/web/minibase/blueprints/user/__pycache__/routes.cpython-311.pyc and b/web/minibase/blueprints/user/__pycache__/routes.cpython-311.pyc differ diff --git a/web/minibase/blueprints/user/__pycache__/utils.cpython-311.pyc b/web/minibase/blueprints/user/__pycache__/utils.cpython-311.pyc index 5eb6b0cc..8dc70db0 100644 Binary files a/web/minibase/blueprints/user/__pycache__/utils.cpython-311.pyc and b/web/minibase/blueprints/user/__pycache__/utils.cpython-311.pyc differ diff --git a/web/minibase/blueprints/user/forms.py b/web/minibase/blueprints/user/forms.py index 08586163..6bc8bd46 100644 --- a/web/minibase/blueprints/user/forms.py +++ b/web/minibase/blueprints/user/forms.py @@ -1,6 +1,6 @@ from flask_wtf import FlaskForm from flask_wtf.file import FileField, FileAllowed -from wtforms import StringField, PasswordField, SubmitField, BooleanField +from wtforms import StringField, PasswordField, SubmitField, BooleanField, URLField from wtforms.validators import DataRequired, Length, Email, EqualTo, ValidationError from flask_login import current_user from minibase.blueprints.user.models import Users @@ -71,3 +71,11 @@ class resetPasswordForm(FlaskForm): # Defines the form class to be used for pas password = PasswordField('Password', validators=[DataRequired()]) password_confirm = PasswordField('Confirm Password', validators=[DataRequired(), EqualTo('password')]) submit = SubmitField('Reset Password') + + +class updateRoleForm(FlaskForm): + id = StringField('ID', render_kw={'disabled':''}) + role = StringField('Role', validators=[DataRequired(), Length(min=4, max=20)]) + description = StringField('Description', validators=[DataRequired(), Length(min=4, max=200)]) + submit = SubmitField() + diff --git a/web/minibase/blueprints/user/models.py b/web/minibase/blueprints/user/models.py index 7c2743ee..e62f9138 100644 --- a/web/minibase/blueprints/user/models.py +++ b/web/minibase/blueprints/user/models.py @@ -1,14 +1,15 @@ from flask import current_app from itsdangerous import URLSafeTimedSerializer as Serializer -from datetime import datetime -from minibase.app import db, login_manager, bcrypt +from minibase.app import db, login_manager from flask_login import UserMixin - + + # The Default User Loading proccess @login_manager.user_loader def load_user(user_id): return Users.query.get(int(user_id)) + class Users(db.Model, UserMixin): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) @@ -16,9 +17,9 @@ class Users(db.Model, UserMixin): email_account = db.Column(db.String(120), unique=True, nullable=False) email_comm = db.Column(db.String(120), unique=False, nullable=False) role = db.Column(db.String(120), unique=False, nullable=False, default='user') - image_file = db.Column(db.String(20), nullable=False, default='default.jpg') + image_file = db.Column(db.String(20), nullable=False, default='def_avatar.png') password = db.Column(db.String(60), nullable=False) - role_id = db.Column(db.Integer, db.ForeignKey('user_roles.id'), nullable=False) + role_id = db.Column(db.Integer, db.ForeignKey('user_roles.id'), nullable=False, default=2) role = db.relationship('User_Roles', backref=db.backref('users', lazy=True)) def get_reset_token(self, expires_sec=1800): diff --git a/web/minibase/blueprints/user/routes.py b/web/minibase/blueprints/user/routes.py index e8fc7fda..edd56d80 100644 --- a/web/minibase/blueprints/user/routes.py +++ b/web/minibase/blueprints/user/routes.py @@ -2,8 +2,10 @@ 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.app import db, bcrypt import minibase.theme as theme -from minibase.blueprints.user.models import Users -from minibase.blueprints.user.forms import registrationForm, loginForm, updateAccountForm, resetPasswordForm, requestResetForm +from minibase.blueprints.user.models import Users, User_Roles +import minibase.blueprints.database.utils as dbUtils +import minibase.blueprints.user.utils as UserUtils +from minibase.blueprints.user.forms import registrationForm, loginForm, updateAccountForm, resetPasswordForm, requestResetForm, updateRoleForm from minibase.blueprints.user.utils import save_picture, send_reset_email # Declaring a blueprint @@ -18,9 +20,7 @@ def register(): form = registrationForm() if form.validate_on_submit(): hashed_pw = bcrypt.generate_password_hash(form.password.data).decode('utf-8') - user = Users(username=form.username.data, email_account=form.email.data, email_comm=form.email.data, password=hashed_pw) - db.session.add(user) - db.session.commit() + dbUtils.dbAddAndCommit(Users(username=form.username.data, email_account=form.email.data, email_comm=form.email.data, password=hashed_pw)) flash(f'{"Your account has been created you can now log in!"}', 'success') return redirect(url_for('user.login')) @@ -36,7 +36,7 @@ def login(): form = loginForm() if form.validate_on_submit(): - user = Users.query.filter_by(email_account=form.email.data).first() + user = UserUtils.dbGetMailFirst(form.email.data) 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') @@ -86,7 +86,7 @@ def reset_request(): return redirect(url_for('main.index')) form = requestResetForm() if form.validate_on_submit(): - user = Users.query.filter_by(email_account=form.email.data).first() + user = UserUtils.dbGetMailFirst(form.email.data) send_reset_email(user) flash('An Email has been sent with instruction to reset your password', 'warning') return render_template('user/reset_request.html', @@ -112,3 +112,42 @@ def reset_token(token): return render_template('user/reset_token.html', theme=theme, form=form) + + +@user.route("/roles", methods=['GET', 'POST']) +@login_required +def roles(): + page=request.args.get('page', 1, type=int) + table=dbUtils.table_printable_paginate(User_Roles, page, 20, 'role/edit/', 'id') + return(render_template('view.html', theme=theme, table=table, title="User Roles")) + + +class bottons: + def __init__(self, name, link): + self.name = name + self.link = link + + +@user.route("/role/edit/", methods=['GET', 'POST']) +@login_required +def updateRole(id): + if current_user.role.id == 1: + extraButton=[] + extraButton.append(bottons('Back To Roles', url_for('user.roles'))) + role = UserUtils.queryRoleById(id) + form = updateRoleForm() + if form.validate_on_submit(): + role.title = form.role.data + role.description = form.description.data + dbUtils.dbCommit() + flash('The role has been updated', 'success') + return redirect(url_for('user.updateRole', id=role.id)) + elif request.method == 'GET': + form.id.data = role.id + form.role.data = role.name + form.description.data = role.description + return(render_template('edit.html', theme=theme, form=form, title=current_user.role.name, extraButtons=extraButton)) + else: + flash('You have no permission to do that', 'danger') + return redirect(url_for('main.index')) + diff --git a/web/minibase/blueprints/user/templates/user/account.html b/web/minibase/blueprints/user/templates/user/account.html index bfb3e62a..dfb4711c 100644 --- a/web/minibase/blueprints/user/templates/user/account.html +++ b/web/minibase/blueprints/user/templates/user/account.html @@ -1,20 +1,26 @@ {% extends "base.html" %} {% block content %} -
+
+
+ + +
+
{% include 'form.html' %}
+
{% include 'form.html' %} diff --git a/web/minibase/blueprints/user/utils.py b/web/minibase/blueprints/user/utils.py index 483469c9..1a5178e3 100644 --- a/web/minibase/blueprints/user/utils.py +++ b/web/minibase/blueprints/user/utils.py @@ -4,7 +4,10 @@ from PIL import Image from flask import url_for, current_app from flask_mail import Message from minibase.app import mail +from minibase.blueprints.user.models import Users, User_Roles +def dbGetMailFirst(mail): + return Users.query.filter_by(email_account=mail).first() def save_picture(form_picture): random_hex = secrets.token_hex(8) @@ -28,3 +31,7 @@ def send_reset_email(user): If you didn't make this request, then simply ingnore this email and no chancges will be made. ''' mail.send(msg) + + +def queryRoleById(id): + return User_Roles.query.get_or_404(id) diff --git a/web/minibase/static/pics/def_avatar.png b/web/minibase/static/pics/def_avatar.png new file mode 100644 index 00000000..0a672f49 Binary files /dev/null and b/web/minibase/static/pics/def_avatar.png differ diff --git a/web/minibase/templates/base.html b/web/minibase/templates/base.html index 775e73fa..a04fae2e 100644 --- a/web/minibase/templates/base.html +++ b/web/minibase/templates/base.html @@ -13,7 +13,6 @@ {% include 'navbar.html' %} -
@@ -33,5 +32,8 @@ {% block content %}{% endblock %}
+ + + {% block scripts %}{% endblock %} diff --git a/web/minibase/templates/edit.html b/web/minibase/templates/edit.html new file mode 100644 index 00000000..3a510e8c --- /dev/null +++ b/web/minibase/templates/edit.html @@ -0,0 +1,22 @@ +{% extends "base.html" %} +{% block title %}{{ title }}{% endblock %} +{% block content %} +
+

{{ title }}

+
+
+ {% include 'form.html' %} + {% if extraButtons %} +
+
+
+
+ {% for button in extraButtons %} +
  • {{ button.name }} + {% endfor %} +
    +
  • + {% endif %} +
    + +{% endblock content %} diff --git a/web/minibase/templates/form.html b/web/minibase/templates/form.html index 9f18deaf..57920858 100644 --- a/web/minibase/templates/form.html +++ b/web/minibase/templates/form.html @@ -29,8 +29,9 @@ {% endif %} {% endfor %} -
    +

    {{ form.submit(class=theme.form.submit_class, style=theme.form.submit_style) }} +
    diff --git a/web/minibase/templates/pagination.html b/web/minibase/templates/pagination.html new file mode 100644 index 00000000..c5424d86 --- /dev/null +++ b/web/minibase/templates/pagination.html @@ -0,0 +1,14 @@ +
    diff --git a/web/minibase/templates/table.html b/web/minibase/templates/table.html index 1b50899e..e9418c0a 100644 --- a/web/minibase/templates/table.html +++ b/web/minibase/templates/table.html @@ -1,25 +1,59 @@ -
    - +
    +
    {{ info }} - {% for title in titles %} + {% for title in table.titles %} {% endfor %} - {% for item in table %} - - {% for title in titles %} - {% if title == 'id' %} - - {% else %} - - {% endif %} + {% if table.paginate == 1 %} + {% for line in table.lines.items %} + + {% for title in table.titles %} + {% if title == table.item_to_be_linked %} + + {% else %} + + {% endif %} + {% endfor %} + {% endfor %} - - {% endfor %} + {% else %} + {% for line in table.lines %} + + {% for title in table.titles %} + {% if title == table.item_to_be_linked %} + + {% else %} + + {% endif %} + {% endfor %} + + {% endfor %} + {% endif %}
    {{ title }}
    {{ item|attr(title) }}{{ item|attr(title) }}
    {{ line|attr(title) }}{{ line|attr(title) }}
    {{ line|attr(title) }}{{ line|attr(title) }}
    + {% if table.paginate == 1 %} + {% if table.lines.pages < 2 %} + {% else %} + {% include 'pagination.html' %} + {% endif %} + {% endif %}
    +{% block scripts %} + +{% endblock %} diff --git a/web/minibase/templates/view.html b/web/minibase/templates/view.html new file mode 100644 index 00000000..9f8f2c09 --- /dev/null +++ b/web/minibase/templates/view.html @@ -0,0 +1,10 @@ +{% extends "base.html" %} +{% block title %}{{ title }}{% endblock %} +{% block content %} +
    +

    {{ title }}

    +
    +
    + {% include 'table.html' %} +
    +{% endblock content %} diff --git a/web/minibase/theme.py b/web/minibase/theme.py index 93c9ebff..b5dd0e73 100644 --- a/web/minibase/theme.py +++ b/web/minibase/theme.py @@ -12,7 +12,7 @@ class maineTheme: div_style = "background-color:" + yellow class form: - div_style = "background-color:" + black + div_style = "background-color:" + black + "; " +" width:98%;" div_class = "container rounded p-4 py-4" div_error_class = "invalid-feedback" input_label_class = "col-form-label" @@ -20,7 +20,7 @@ class form: check_label_class = "form-check-label" check_label_style = input_label_style check_class = "form-check-input" - submit_class = "btn btn-outline-info" + submit_class = "btn btn-outline-info mb-2 mt-2" submit_style = "" input_error_class = "form-control form-control-lg is-invalid" input_class = "form-control form-control-lg"