Login system pt.2
This commit is contained in:
parent
5989f0d97e
commit
1fcb701083
|
|
@ -4,12 +4,13 @@
|
|||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Launch Starfall",
|
||||
"clientOS": "unix",
|
||||
"console": "integratedTerminal",
|
||||
"name": "Launch Starfall",
|
||||
"preLaunchTask": "install_reqs",
|
||||
"program": "${workspaceFolder}/app.py",
|
||||
"request": "launch",
|
||||
"type": "debugpy",
|
||||
"clientOS": "unix"
|
||||
"type": "debugpy"
|
||||
}
|
||||
],
|
||||
"version": "0.2.0"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"tasks": [
|
||||
{
|
||||
"command": "./.venv/bin/activate",
|
||||
"label": "activate",
|
||||
"type": "shell"
|
||||
},
|
||||
{
|
||||
"args": [
|
||||
"install",
|
||||
"--upgrade",
|
||||
"-r",
|
||||
"requirements.txt"
|
||||
],
|
||||
"command": "./.venv/bin/pip",
|
||||
"label": "install_reqs",
|
||||
"type": "shell"
|
||||
}
|
||||
],
|
||||
"version": "2.0.0"
|
||||
}
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
from typing import Any
|
||||
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from starfall.db import db
|
||||
|
|
@ -9,5 +11,17 @@ class User(db.Model):
|
|||
username: Mapped[str] = mapped_column()
|
||||
password: Mapped[str] = mapped_column()
|
||||
|
||||
def __init__(self, **kwargs) -> None:
|
||||
def __init__(self, **kwargs: Any) -> None:
|
||||
super().__init__(**kwargs)
|
||||
|
||||
def auth(self):
|
||||
return (
|
||||
User.query.filter_by(username=self.username, password=self.password).first()
|
||||
is not None
|
||||
)
|
||||
|
||||
def username_free(self):
|
||||
return User.query.filter_by(username=self.username).first() is None
|
||||
|
||||
def email_free(self):
|
||||
return User.query.filter_by(email=self.email).first() is None
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
from flask_babel import _, lazy_gettext
|
||||
from flask_babel import LazyString, lazy_gettext
|
||||
from flask_wtf import FlaskForm
|
||||
from wtforms import PasswordField, StringField
|
||||
from wtforms.validators import DataRequired
|
||||
|
||||
from starfall.db.schema.users import User
|
||||
from starfall.web.blueprints.base import BaseBlueprint
|
||||
from starfall.web.controllers.base import BaseController
|
||||
|
||||
|
|
@ -36,3 +37,16 @@ class LoginController(BaseController):
|
|||
@classmethod
|
||||
def apply(cls, bp: BaseBlueprint):
|
||||
bp.data["form"] = LoginForm()
|
||||
|
||||
@classmethod
|
||||
def handle_form(cls) -> tuple[str, LazyString | str]:
|
||||
form = LoginForm()
|
||||
if not form.validate_on_submit():
|
||||
return "", ""
|
||||
|
||||
user = User(
|
||||
username=str(form.username.data),
|
||||
password=cls.encrypt_password(str(form.password.data)),
|
||||
)
|
||||
|
||||
return "", ""
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
from flask import request
|
||||
from flask_babel import LazyString, lazy_gettext
|
||||
from flask import flash, request
|
||||
from flask_babel import lazy_gettext
|
||||
from flask_wtf import FlaskForm
|
||||
from wtforms import EmailField, PasswordField, StringField
|
||||
from wtforms.validators import DataRequired
|
||||
from wtforms.fields.simple import PasswordField
|
||||
from wtforms.validators import DataRequired, EqualTo, Length
|
||||
|
||||
from starfall.db import db
|
||||
from starfall.db.schema.users import User
|
||||
|
|
@ -26,12 +27,27 @@ class RegisterForm(FlaskForm):
|
|||
password: PasswordField = PasswordField(
|
||||
label=lazy_gettext("page.register.form.password"), # pyright: ignore[reportArgumentType]
|
||||
render_kw={
|
||||
"autocomplete": "password",
|
||||
"class": "form-control",
|
||||
"placeholder": lazy_gettext("page.register.form.password"),
|
||||
},
|
||||
validators=[
|
||||
DataRequired(message=lazy_gettext("page.register.error.password")), # pyright: ignore[reportArgumentType]
|
||||
Length(8, message=lazy_gettext("page.register.error.password_too_short")), # pyright: ignore[reportArgumentType]
|
||||
],
|
||||
)
|
||||
retype_password: PasswordField = PasswordField(
|
||||
label=lazy_gettext("page.register.form.retype_password"), # pyright: ignore[reportArgumentType]
|
||||
render_kw={
|
||||
"class": "form-control",
|
||||
"placeholder": lazy_gettext("page.register.form.retype_password"),
|
||||
},
|
||||
validators=[
|
||||
DataRequired(message=lazy_gettext("page.register.error.retype_password")), # pyright: ignore[reportArgumentType]
|
||||
Length(8, message=lazy_gettext("page.register.error.password_too_short")), # pyright: ignore[reportArgumentType]
|
||||
EqualTo(
|
||||
"password",
|
||||
message=lazy_gettext("page.register.error.password_not_matching"), # pyright: ignore[reportArgumentType]
|
||||
),
|
||||
],
|
||||
)
|
||||
email: EmailField = EmailField(
|
||||
|
|
@ -51,22 +67,31 @@ class RegisterController(BaseController):
|
|||
@classmethod
|
||||
def apply(cls, bp: BaseBlueprint):
|
||||
if "POST" == request.method:
|
||||
bp.data["status_class"], bp.data["status"] = cls.handle_form()
|
||||
cls.handle_form()
|
||||
bp.data["form"] = RegisterForm()
|
||||
|
||||
@classmethod
|
||||
def handle_form(cls) -> tuple[str | None, LazyString | None]:
|
||||
def handle_form(cls):
|
||||
form = RegisterForm()
|
||||
if not form.validate_on_submit():
|
||||
return None, None
|
||||
return
|
||||
|
||||
try:
|
||||
user = User(
|
||||
username=str(form.username.data),
|
||||
password=cls.encrypt_password(str(form.password.data)),
|
||||
email=str(form.email.data),
|
||||
)
|
||||
try:
|
||||
|
||||
if not user.username_free():
|
||||
flash(lazy_gettext("page.register.status.username_exists"), "danger") # pyright: ignore[reportArgumentType]
|
||||
return
|
||||
|
||||
if not user.email_free():
|
||||
flash(lazy_gettext("page.register.status.email_exists"), "danger") # pyright: ignore[reportArgumentType]
|
||||
return
|
||||
|
||||
db.session.add(user)
|
||||
db.session.commit()
|
||||
except Exception:
|
||||
return "error", lazy_gettext("page.register.status.email_already_exists")
|
||||
return "success", lazy_gettext("page.register.status.success")
|
||||
flash(lazy_gettext("page.register.status.insert_error"), "danger") # pyright: ignore[reportArgumentType]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
{%with messages = get_flashed_messages(with_categories=true)%}
|
||||
{%if messages%}
|
||||
{%for category, message in messages%}
|
||||
{# Categories: danger (Error), success (Success), info (Message) #}
|
||||
<div class="alert alert-{{category}} alert-dismissible" role="alert">
|
||||
{{message}}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="base.label.close"></button>
|
||||
</div>
|
||||
{%endfor%}
|
||||
{%endif%}
|
||||
{%endwith%}
|
||||
|
|
@ -9,9 +9,7 @@
|
|||
<h1 class="text-center text-primary-emphasis">{{_('page.login.title')}}</h1>
|
||||
|
||||
<form class="border border-secondary bg-secondary-subtle rounded p-3" method="POST">
|
||||
{%if bp.data["status"]%}
|
||||
<div class="alert alert-{{bp.data['status_class']}}" role="alert">{{bp.data["status"]}}</div>
|
||||
{%endif%}
|
||||
{%include "components/flash.jinja"%}
|
||||
{{bp.data["form"].hidden_tag() }}
|
||||
{{form.field(bp.data["form"].username)}}
|
||||
{{form.field(bp.data["form"].password)}}
|
||||
|
|
|
|||
|
|
@ -9,12 +9,11 @@
|
|||
<h1 class="text-center text-primary-emphasis">{{_('page.register.title')}}</h1>
|
||||
|
||||
<form class="border border-secondary bg-secondary-subtle rounded p-3" method="POST">
|
||||
{%if bp.data["status"]%}
|
||||
<div class="alert alert-{{bp.data['status_class']}}" role="alert">{{bp.data["status"]}}</div>
|
||||
{%endif%}
|
||||
{%include "components/flash.jinja"%}
|
||||
{{bp.data["form"].hidden_tag() }}
|
||||
{{form.field(input=bp.data["form"].username, id="username", prefix="@")}}
|
||||
{{form.field(input=bp.data["form"].password)}}
|
||||
{{form.field(input=bp.data["form"].retype_password)}}
|
||||
{{form.field(input=bp.data["form"].email)}}
|
||||
<button type="submit" class="my-3 btn btn-primary text-center">{{_('page.register.form.submit')}}</button>
|
||||
</form>
|
||||
|
|
|
|||
Loading…
Reference in New Issue