Finished SignUp and SignIn frontend and backend

This commit is contained in:
Donald Zou
2025-06-02 19:23:04 +08:00
parent 4a5de5efd4
commit ecc4cc7670
19 changed files with 725 additions and 158 deletions

View File

@@ -1,14 +1,23 @@
import hashlib
import uuid
import bcrypt
import pyotp
import sqlalchemy as db
from sqlalchemy.orm import DeclarativeBase, Mapped
from sqlalchemy.testing.schema import mapped_column
from .ConnectionString import ConnectionString
from .DashboardClientsTOTP import DashboardClientsTOTP
from .Utilities import ValidatePasswordStrength
from .DashboardLogger import DashboardLogger
class DashboardClients:
def __init__(self):
self.logger = DashboardLogger()
self.engine = db.create_engine(ConnectionString("wgdashboard"))
self.metadata = db.MetaData()
self.DashboardClientsTOTP = DashboardClientsTOTP()
self.dashboardClientsTable = db.Table(
'DashboardClients', self.metadata,
@@ -36,8 +45,6 @@ class DashboardClients:
self.metadata.create_all(self.engine)
self.Clients = []
self.__getClients()
print('hi')
print(self.Clients)
def __getClients(self):
with self.engine.connect() as conn:
@@ -49,10 +56,63 @@ class DashboardClients:
).where(
self.dashboardClientsTable.c.DeletedDate is None)
).mappings().fetchall()
def SignIn(self, Email, Password) -> tuple[bool, str]:
if not all([Email, Password]):
return False, "Please fill in all fields"
with self.engine.connect() as conn:
existingClient = conn.execute(
self.dashboardClientsTable.select().where(
self.dashboardClientsTable.c.Email == Email
)
).mappings().fetchone()
if existingClient:
checkPwd = bcrypt.checkpw(Password.encode("utf-8"), existingClient.get("Password").encode("utf-8"))
if checkPwd:
return True, self.DashboardClientsTOTP.GenerateToken(existingClient.get("ClientID"))
return False, "Email or Password is incorrect"
def SignUp(self, Email, Password, ConfirmPassword) -> tuple[bool, str] or tuple[bool, None]:
try:
if not all([Email, Password, ConfirmPassword]):
return False, "Please fill in all fields"
if Password != ConfirmPassword:
return False, "Passwords does not match"
with self.engine.connect() as conn:
existingClient = conn.execute(
self.dashboardClientsTable.select().where(
self.dashboardClientsTable.c.Email == Email
)
).mappings().fetchone()
if existingClient:
return False, "Email already signed up"
pwStrength, msg = ValidatePasswordStrength(Password)
if not pwStrength:
return pwStrength, msg
with self.engine.begin() as conn:
newClientUUID = str(uuid.uuid4())
totpKey = pyotp.random_base32()
encodePassword = Password.encode('utf-8')
conn.execute(
self.dashboardClientsTable.insert().values({
"ClientID": newClientUUID,
"Email": Email,
"Password": bcrypt.hashpw(encodePassword, bcrypt.gensalt()).decode("utf-8"),
"TotpKey": totpKey
})
)
conn.execute(
self.dashboardClientsInfoTable.insert().values({
"ClientID": newClientUUID
})
)
except Exception as e:
self.logger.log(Status="false", Message=f"Signed up failed, reason: {str(e)}")
return False, "Signed up failed."
def SignUp(self, Email, Password, ConfirmPassword) -> tuple[bool, str]:
pass
return True, None

View File

@@ -0,0 +1,44 @@
import datetime
import hashlib
import uuid
import sqlalchemy as db
from .ConnectionString import ConnectionString
class DashboardClientsTOTP:
def __init__(self):
self.engine = db.create_engine(ConnectionString("wgdashboard"))
self.metadata = db.MetaData()
self.dashboardClientsTOTPTable = db.Table(
'DashboardClientsTOTPTokens', self.metadata,
db.Column("Token", db.String(500), primary_key=True, index=True),
db.Column("ClientID", db.String(500), index=True),
db.Column(
"ExpireTime", (db.DATETIME if 'sqlite:///' in ConnectionString("wgdashboard") else db.TIMESTAMP)
)
)
self.metadata.create_all(self.engine)
def GenerateToken(self, ClientID) -> str:
token = hashlib.sha512(f"{ClientID}_{datetime.datetime.now()}_{uuid.uuid4()}".encode()).hexdigest()
with self.engine.begin() as conn:
conn.execute(
self.dashboardClientsTOTPTable.update().values({
"ExpireTime": datetime.datetime.now()
}).where(
db.and_(self.dashboardClientsTOTPTable.c.ClientID == ClientID, self.dashboardClientsTOTPTable.c.ExpireTime > datetime.datetime.now())
)
)
conn.execute(
self.dashboardClientsTOTPTable.insert().values({
"Token": token,
"ClientID": ClientID,
"ExpireTime": datetime.datetime.now() + datetime.timedelta(minutes=10)
})
)
return token

View File

@@ -8,13 +8,14 @@ from .ConnectionString import ConnectionString
class DashboardLogger:
def __init__(self, DashboardConfig):
def __init__(self):
self.engine = db.create_engine(ConnectionString("wgdashboard_log"))
self.metadata = db.MetaData()
self.dashboardLoggerTable = db.Table('DashboardLog', self.metadata,
db.Column('LogID', db.String(255), nullable=False, primary_key=True),
db.Column('LogDate', (db.DATETIME if DashboardConfig.GetConfig("Database", "type")[1] == 'sqlite' else db.TIMESTAMP),
db.Column('LogDate',
(db.DATETIME if 'sqlite:///' in ConnectionString("wgdashboard") else db.TIMESTAMP),
server_default=db.func.now()),
db.Column('URL', db.String(255)),
db.Column('IP', db.String(255)),