diff --git a/package-lock.json b/package-lock.json
index 3c274ec..5c55fc1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5,6 +5,7 @@
"packages": {
"": {
"dependencies": {
+ "axios": "^1.9.0",
"marked": "^15.0.7",
"openai": "^4.89.0",
"pinia-plugin-persistedstate": "^4.2.0"
@@ -163,6 +164,17 @@
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
"license": "MIT"
},
+ "node_modules/axios": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmmirror.com/axios/-/axios-1.9.0.tgz",
+ "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==",
+ "license": "MIT",
+ "dependencies": {
+ "follow-redirects": "^1.15.6",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
"node_modules/braces": {
"version": "3.0.3",
"resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.3.tgz",
@@ -444,6 +456,26 @@
"node": ">=8"
}
},
+ "node_modules/follow-redirects": {
+ "version": "1.15.9",
+ "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.9.tgz",
+ "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
"node_modules/form-data": {
"version": "4.0.2",
"resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.2.tgz",
@@ -998,6 +1030,12 @@
"integrity": "sha512-hkT3yDPFbs95mNCy1+7qNKC6Pro+/ibzYxtM2iqEigpf0sVw+bg4Zh9/snjsBcf990vfIsg5+1U7VyiyBb3etg==",
"license": "MIT"
},
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+ "license": "MIT"
+ },
"node_modules/quansync": {
"version": "0.2.10",
"resolved": "https://registry.npmmirror.com/quansync/-/quansync-0.2.10.tgz",
diff --git a/package.json b/package.json
index f83ed9d..652e4a9 100644
--- a/package.json
+++ b/package.json
@@ -1,5 +1,6 @@
{
"dependencies": {
+ "axios": "^1.9.0",
"marked": "^15.0.7",
"openai": "^4.89.0",
"pinia-plugin-persistedstate": "^4.2.0"
diff --git a/src/client.py b/src/client.py
index eece7e9..98f5efb 100644
--- a/src/client.py
+++ b/src/client.py
@@ -36,19 +36,23 @@ def createClientBlueprint(wireguardConfigurations: dict[WireguardConfiguration],
if request.method.lower() == 'options':
return ResponseObject(True)
-
-
- @client.get(prefix)
- def ClientIndex():
- print(wireguardConfigurations.keys())
- return render_template('client.html')
@client.post(f'{prefix}/api/signup')
def ClientAPI_SignUp():
data = request.json
status, msg = DashboardClients.SignUp(**data)
-
-
return ResponseObject(status, msg)
+ @client.post(f'{prefix}/api/signin')
+ def ClientAPI_SignIn():
+ data = request.json
+ status, msg = DashboardClients.SignIn(**data)
+ return ResponseObject(status, msg)
+
+ @client.get(prefix)
+ @login_required
+ def ClientIndex():
+ print(wireguardConfigurations.keys())
+ return render_template('client.html')
+
return client
\ No newline at end of file
diff --git a/src/dashboard.py b/src/dashboard.py
index 36edf79..5d1fb26 100644
--- a/src/dashboard.py
+++ b/src/dashboard.py
@@ -1264,7 +1264,7 @@ WireguardConfigurations: dict[str, WireguardConfiguration] = {}
AllPeerShareLinks: PeerShareLinks = PeerShareLinks(DashboardConfig)
AllPeerJobs: PeerJobs = PeerJobs(DashboardConfig, WireguardConfigurations)
-DashboardLogger: DashboardLogger = DashboardLogger(DashboardConfig)
+DashboardLogger: DashboardLogger = DashboardLogger()
InitWireguardConfigurationsList(startup=True)
diff --git a/src/modules/DashboardClients.py b/src/modules/DashboardClients.py
index 4a66c7b..bbf7c26 100644
--- a/src/modules/DashboardClients.py
+++ b/src/modules/DashboardClients.py
@@ -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
-
-
\ No newline at end of file
+ return True, None
\ No newline at end of file
diff --git a/src/modules/DashboardClientsTOTP.py b/src/modules/DashboardClientsTOTP.py
new file mode 100644
index 0000000..dff96ed
--- /dev/null
+++ b/src/modules/DashboardClientsTOTP.py
@@ -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
+
\ No newline at end of file
diff --git a/src/modules/DashboardLogger.py b/src/modules/DashboardLogger.py
index d7b162c..afa4a02 100644
--- a/src/modules/DashboardLogger.py
+++ b/src/modules/DashboardLogger.py
@@ -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)),
diff --git a/src/static/client/package-lock.json b/src/static/client/package-lock.json
index 8c85ba6..3ef6844 100644
--- a/src/static/client/package-lock.json
+++ b/src/static/client/package-lock.json
@@ -8,6 +8,7 @@
"name": "client",
"version": "0.0.0",
"dependencies": {
+ "axios": "^1.9.0",
"bootstrap": "^5.3.6",
"bootstrap-icons": "^1.13.1",
"dayjs": "^1.11.13",
@@ -1553,6 +1554,23 @@
"integrity": "sha512-c/0fWy3Jw6Z8L9FmTyYfkpM5zklnqqa9+a6dz3DvONRKW2NEbh46BP0FHuLFSWi2TnQEtp91Z6zOWNrU6QiyPg==",
"license": "MIT"
},
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "license": "MIT"
+ },
+ "node_modules/axios": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmmirror.com/axios/-/axios-1.9.0.tgz",
+ "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==",
+ "license": "MIT",
+ "dependencies": {
+ "follow-redirects": "^1.15.6",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
"node_modules/birpc": {
"version": "2.3.0",
"resolved": "https://registry.npmmirror.com/birpc/-/birpc-2.3.0.tgz",
@@ -1646,6 +1664,19 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/call-bind-apply-helpers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/caniuse-lite": {
"version": "1.0.30001720",
"resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001720.tgz",
@@ -1667,6 +1698,18 @@
],
"license": "CC-BY-4.0"
},
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "license": "MIT",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/convert-source-map": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-2.0.0.tgz",
@@ -1777,6 +1820,29 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/dunder-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/electron-to-chromium": {
"version": "1.5.161",
"resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.161.tgz",
@@ -1806,6 +1872,51 @@
"url": "https://github.com/sponsors/antfu"
}
},
+ "node_modules/es-define-property": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz",
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-object-atoms": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+ "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/esbuild": {
"version": "0.25.5",
"resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.25.5.tgz",
@@ -1921,6 +2032,41 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/follow-redirects": {
+ "version": "1.15.9",
+ "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.9.tgz",
+ "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/form-data": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.2.tgz",
+ "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
+ "license": "MIT",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "es-set-tostringtag": "^2.1.0",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/fs-extra": {
"version": "11.3.0",
"resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-11.3.0.tgz",
@@ -1951,6 +2097,15 @@
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/gensync": {
"version": "1.0.0-beta.2",
"resolved": "https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz",
@@ -1961,6 +2116,43 @@
"node": ">=6.9.0"
}
},
+ "node_modules/get-intrinsic": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz",
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/get-stream": {
"version": "9.0.1",
"resolved": "https://registry.npmmirror.com/get-stream/-/get-stream-9.0.1.tgz",
@@ -1988,6 +2180,18 @@
"node": ">=4"
}
},
+ "node_modules/gopd": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz",
@@ -1995,6 +2199,45 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/has-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "license": "MIT",
+ "dependencies": {
+ "has-symbols": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/hookable": {
"version": "5.5.3",
"resolved": "https://registry.npmmirror.com/hookable/-/hookable-5.5.3.tgz",
@@ -2192,6 +2435,36 @@
"@jridgewell/sourcemap-codec": "^1.5.0"
}
},
+ "node_modules/math-intrinsics": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
"node_modules/mitt": {
"version": "3.0.1",
"resolved": "https://registry.npmmirror.com/mitt/-/mitt-3.0.1.tgz",
@@ -2409,6 +2682,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+ "license": "MIT"
+ },
"node_modules/rfdc": {
"version": "1.4.1",
"resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.4.1.tgz",
diff --git a/src/static/client/package.json b/src/static/client/package.json
index 8d11562..19b8c14 100644
--- a/src/static/client/package.json
+++ b/src/static/client/package.json
@@ -9,6 +9,7 @@
"preview": "vite preview"
},
"dependencies": {
+ "axios": "^1.9.0",
"bootstrap": "^5.3.6",
"bootstrap-icons": "^1.13.1",
"dayjs": "^1.11.13",
diff --git a/src/static/client/src/App.vue b/src/static/client/src/App.vue
index 8294dfd..65de3d6 100644
--- a/src/static/client/src/App.vue
+++ b/src/static/client/src/App.vue
@@ -5,13 +5,19 @@ import NotificationList from "@/components/notification/notificationList.vue";
@@ -19,12 +25,12 @@ import NotificationList from "@/components/notification/notificationList.vue";
diff --git a/src/static/client/src/assets/main.css b/src/static/client/src/assets/main.css
index 0d745ed..0e1d730 100644
--- a/src/static/client/src/assets/main.css
+++ b/src/static/client/src/assets/main.css
@@ -56,4 +56,20 @@
::-webkit-scrollbar {
display: none;
+}
+
+.slide-right-enter-active,
+.slide-right-leave-active {
+ transition: all 0.3s cubic-bezier(0.82, 0.58, 0.17, 1);
+}
+.slide-right-enter-from,
+.slide-right-leave-to{
+ opacity: 0;
+}
+
+.slide-right-enter-from{
+ transform: translateX(-20px);
+}
+.slide-right-leave-to{
+ transform: translateX(20px);
}
\ No newline at end of file
diff --git a/src/static/client/src/components/notification/notification.vue b/src/static/client/src/components/notification/notification.vue
index b186457..54a5d5d 100644
--- a/src/static/client/src/components/notification/notification.vue
+++ b/src/static/client/src/components/notification/notification.vue
@@ -16,7 +16,7 @@ const show = () => {
props.notificationData.show = true;
timeout = setTimeout(() => {
dismiss()
- }, 50000)
+ }, 5000)
}
const clearTime = () => clearTimeout(timeout)
const dismiss = () => props.notificationData.show = false;
@@ -57,7 +57,7 @@ onMounted(() => {
\ No newline at end of file
diff --git a/src/static/client/vite.config.js b/src/static/client/vite.config.js
index 604eda8..f6318a2 100644
--- a/src/static/client/vite.config.js
+++ b/src/static/client/vite.config.js
@@ -25,8 +25,7 @@ export default defineConfig({
},
server:{
proxy: {
- '/api': proxy,
- '/fileDownload':proxy
+ '/client': proxy,
},
host: '0.0.0.0'
},