dev step
Browse files- main.py +28 -26
- modules/model.py +60 -96
- modules/security.py +10 -6
- modules/settings.py +1 -1
- static/js/chatHandler.js +1 -2
- templates/main.html +3 -3
main.py
CHANGED
|
@@ -25,7 +25,7 @@ async def main_page(request: Request, user: User = Depends(User.find_from_cookie
|
|
| 25 |
return RedirectResponse(url='/hold')
|
| 26 |
|
| 27 |
tools = [{"name": k, "desc": v} for k, v in chat_functions.function_user_text.items()]
|
| 28 |
-
token = user.
|
| 29 |
response = templates.TemplateResponse(
|
| 30 |
"main.html", {
|
| 31 |
"request": request,
|
|
@@ -33,7 +33,6 @@ async def main_page(request: Request, user: User = Depends(User.find_from_cookie
|
|
| 33 |
"version": fecha_unix,
|
| 34 |
"tools": tools
|
| 35 |
})
|
| 36 |
-
user.update()
|
| 37 |
return response
|
| 38 |
|
| 39 |
|
|
@@ -49,18 +48,18 @@ async def validate_oauth(request: Request):
|
|
| 49 |
params = dict(request.query_params)
|
| 50 |
fingerprint = params["state"].split("=",1)[1]
|
| 51 |
google_userinfo = oauth.validate_redirect(params) | {"fprint": fingerprint}
|
| 52 |
-
user = model.User.find_or_create(google_userinfo)
|
| 53 |
-
token = user.
|
| 54 |
response = RedirectResponse(url='/')
|
| 55 |
response.set_cookie(key="token", value=token)
|
| 56 |
-
user.
|
| 57 |
return response
|
| 58 |
|
| 59 |
|
| 60 |
########################## API ##########################
|
| 61 |
|
| 62 |
@app.post("/getConfigs")
|
| 63 |
-
async def get_configs(request: Request, user = Depends(model.User.find_from_header)):
|
| 64 |
tokens = user.tokens
|
| 65 |
year, month = datetime.now().strftime("%y-%m").split("-")
|
| 66 |
mes = sum(tokens.get(year, {}).get(month, {"_":0}).values())
|
|
@@ -68,27 +67,24 @@ async def get_configs(request: Request, user = Depends(model.User.find_from_head
|
|
| 68 |
return user.configs.model_dump() | {"tokens": tokens}
|
| 69 |
|
| 70 |
@app.post("/setConfigs")
|
| 71 |
-
async def set_configs(request: Request, configs: model.Configs, user = Depends(User.find_from_header)):
|
| 72 |
user.configs = configs
|
| 73 |
user.update()
|
| 74 |
return {"success":True}
|
| 75 |
|
| 76 |
|
| 77 |
@app.post("/getToken")
|
| 78 |
-
async def get_token(request: Request, data:
|
| 79 |
-
user.session = model.Session(**data)
|
| 80 |
-
data.pop("fingerprint")
|
| 81 |
-
security.validate_signature(**data)
|
| 82 |
-
security.create_jwt_token(data)
|
| 83 |
-
token = user.create_token()
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
fingerprint: str
|
| 87 |
-
public_key: str
|
| 88 |
-
return {"su":True}
|
| 89 |
|
| 90 |
@app.post("/chat")
|
| 91 |
-
async def chat_async(request: Request, body: model.Chat, user = Depends(model.User.find_from_header)):
|
| 92 |
if(len(body.messages) < 1 or body.messages[-1].content==""):
|
| 93 |
log_module.logger.warning(user.gid, "Mensaje RQ", "error, mensajes vacios")
|
| 94 |
raise HTTPException(
|
|
@@ -106,20 +102,26 @@ async def chat_async(request: Request, body: model.Chat, user = Depends(model.Us
|
|
| 106 |
async def privacy_policy(request: Request):
|
| 107 |
return templates.TemplateResponse("PrivacyPolicy.html", {"request": request})
|
| 108 |
|
| 109 |
-
@app.
|
| 110 |
-
async def on_hold(request: Request):
|
| 111 |
redirect_to_login = RedirectResponse(url='/login')
|
| 112 |
|
| 113 |
-
user = model.User.find_from_token(request, "view")
|
| 114 |
-
|
| 115 |
if user.can_use("chat"):
|
| 116 |
return redirect_to_login
|
| 117 |
-
|
| 118 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 119 |
form = await request.form()
|
| 120 |
if message := form["message"].strip():
|
| 121 |
user.update_description(message)
|
| 122 |
-
|
| 123 |
return templates.TemplateResponse(
|
| 124 |
"no_access.html", {
|
| 125 |
"request": request,
|
|
|
|
| 25 |
return RedirectResponse(url='/hold')
|
| 26 |
|
| 27 |
tools = [{"name": k, "desc": v} for k, v in chat_functions.function_user_text.items()]
|
| 28 |
+
token = user.create_shortlived_token()
|
| 29 |
response = templates.TemplateResponse(
|
| 30 |
"main.html", {
|
| 31 |
"request": request,
|
|
|
|
| 33 |
"version": fecha_unix,
|
| 34 |
"tools": tools
|
| 35 |
})
|
|
|
|
| 36 |
return response
|
| 37 |
|
| 38 |
|
|
|
|
| 48 |
params = dict(request.query_params)
|
| 49 |
fingerprint = params["state"].split("=",1)[1]
|
| 50 |
google_userinfo = oauth.validate_redirect(params) | {"fprint": fingerprint}
|
| 51 |
+
user:User = model.User.find_or_create(google_userinfo)
|
| 52 |
+
token = user.create_cookie()
|
| 53 |
response = RedirectResponse(url='/')
|
| 54 |
response.set_cookie(key="token", value=token)
|
| 55 |
+
user.update_user()
|
| 56 |
return response
|
| 57 |
|
| 58 |
|
| 59 |
########################## API ##########################
|
| 60 |
|
| 61 |
@app.post("/getConfigs")
|
| 62 |
+
async def get_configs(request: Request, user ): #= Depends(model.User.find_from_header)):
|
| 63 |
tokens = user.tokens
|
| 64 |
year, month = datetime.now().strftime("%y-%m").split("-")
|
| 65 |
mes = sum(tokens.get(year, {}).get(month, {"_":0}).values())
|
|
|
|
| 67 |
return user.configs.model_dump() | {"tokens": tokens}
|
| 68 |
|
| 69 |
@app.post("/setConfigs")
|
| 70 |
+
async def set_configs(request: Request, configs: model.Configs, user ): # = Depends(User.find_from_header)):
|
| 71 |
user.configs = configs
|
| 72 |
user.update()
|
| 73 |
return {"success":True}
|
| 74 |
|
| 75 |
|
| 76 |
@app.post("/getToken")
|
| 77 |
+
async def get_token(request: Request, data: model.APISession = Depends(model.APISession.validate)):
|
| 78 |
+
# user.session = model.Session(**data)
|
| 79 |
+
# data.pop("fingerprint")
|
| 80 |
+
# security.validate_signature(**data)
|
| 81 |
+
# security.create_jwt_token(data)
|
| 82 |
+
# token = user.create_token()
|
| 83 |
+
pass
|
| 84 |
+
|
|
|
|
|
|
|
|
|
|
| 85 |
|
| 86 |
@app.post("/chat")
|
| 87 |
+
async def chat_async(request: Request, body: model.Chat, user ): # = Depends(model.User.find_from_header)):
|
| 88 |
if(len(body.messages) < 1 or body.messages[-1].content==""):
|
| 89 |
log_module.logger.warning(user.gid, "Mensaje RQ", "error, mensajes vacios")
|
| 90 |
raise HTTPException(
|
|
|
|
| 102 |
async def privacy_policy(request: Request):
|
| 103 |
return templates.TemplateResponse("PrivacyPolicy.html", {"request": request})
|
| 104 |
|
| 105 |
+
@app.get("/hold") #, ["GET", "POST"]
|
| 106 |
+
async def on_hold(request: Request, user: User = Depends(User.find_from_cookie)):
|
| 107 |
redirect_to_login = RedirectResponse(url='/login')
|
| 108 |
|
|
|
|
|
|
|
| 109 |
if user.can_use("chat"):
|
| 110 |
return redirect_to_login
|
| 111 |
+
|
| 112 |
+
return templates.TemplateResponse(
|
| 113 |
+
"no_access.html", {
|
| 114 |
+
"request": request,
|
| 115 |
+
"description": bool(user.description)
|
| 116 |
+
})
|
| 117 |
+
|
| 118 |
+
@app.post("/hold") #, ["GET", "POST"]
|
| 119 |
+
async def on_hold(request: Request, user: User = Depends(User.find_from_cookie)):
|
| 120 |
+
if not user.description:
|
| 121 |
form = await request.form()
|
| 122 |
if message := form["message"].strip():
|
| 123 |
user.update_description(message)
|
| 124 |
+
|
| 125 |
return templates.TemplateResponse(
|
| 126 |
"no_access.html", {
|
| 127 |
"request": request,
|
modules/model.py
CHANGED
|
@@ -1,4 +1,6 @@
|
|
| 1 |
-
import os
|
|
|
|
|
|
|
| 2 |
from pymongo.mongo_client import MongoClient
|
| 3 |
from pymongo.server_api import ServerApi
|
| 4 |
from fastapi import Request
|
|
@@ -60,47 +62,44 @@ class Chat(BaseModel):
|
|
| 60 |
def new_msg(self: Self):
|
| 61 |
return Message(role="", content="")
|
| 62 |
|
| 63 |
-
class
|
| 64 |
gid: str
|
| 65 |
-
|
| 66 |
public_key: str
|
| 67 |
guid: str = str(uuid.uuid4())
|
| 68 |
-
|
| 69 |
-
updated: datetime = datetime.now(tz)
|
| 70 |
-
expire: datetime = datetime.now(tz)+timedelta(days=7)
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
@classmethod
|
| 75 |
-
def remove_expired(cls: Self, gid: str) -> None:
|
| 76 |
-
DB.sess.delete_one({"gid": gid, "expire": {"$lt": datetime.now(tz)}})
|
| 77 |
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
DB.sess.delete_many({"_id": {"$in": ids_a_borrar}})
|
| 86 |
|
| 87 |
@classmethod
|
| 88 |
-
def
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
|
|
|
|
|
|
| 98 |
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
| 104 |
|
| 105 |
|
| 106 |
class User(BaseModel):
|
|
@@ -112,8 +111,8 @@ class User(BaseModel):
|
|
| 112 |
email: str
|
| 113 |
gid: str
|
| 114 |
role: str = "on hold"
|
|
|
|
| 115 |
configs: Configs = Configs()
|
| 116 |
-
session: Session | None = None
|
| 117 |
|
| 118 |
@classmethod
|
| 119 |
def find(cls: Self, gid: str) -> Self | None:
|
|
@@ -124,56 +123,35 @@ class User(BaseModel):
|
|
| 124 |
|
| 125 |
@classmethod
|
| 126 |
def find_or_create(cls: Self, data: dict)-> Self:
|
| 127 |
-
|
|
|
|
|
|
|
| 128 |
found:Self = cls.find(data["gid"])
|
| 129 |
if found:
|
| 130 |
-
found.
|
| 131 |
return found
|
| 132 |
user:Self = cls(**data)
|
| 133 |
-
user.session
|
| 134 |
-
|
| 135 |
-
DB.user.insert_one(user.model_dump(exclude={"session"}))
|
| 136 |
log_module.logger.info(f"User created: {user.gid}")
|
| 137 |
return user
|
| 138 |
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
return
|
| 144 |
-
|
|
|
|
|
|
|
| 145 |
@classmethod
|
| 146 |
def find_from_cookie(cls:Self, request: Request) -> Self:
|
| 147 |
-
|
|
|
|
| 148 |
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
else:
|
| 154 |
-
data:dict = security.token_from_headers(request)
|
| 155 |
-
|
| 156 |
-
userj:dict = DB.user.find_one({"gid":data["gid"]})
|
| 157 |
-
|
| 158 |
-
if gid := userj.get("gid", None):
|
| 159 |
-
sess:Session = Session.find(gid, data["guid"])
|
| 160 |
-
|
| 161 |
-
if not gid or not sess:
|
| 162 |
-
security.raise_307()
|
| 163 |
-
|
| 164 |
-
user:Self = cls(**userj)
|
| 165 |
-
user.session = sess
|
| 166 |
-
return user
|
| 167 |
-
|
| 168 |
-
|
| 169 |
-
def create_token(self: Self) -> str:
|
| 170 |
-
return security.create_jwt_token({
|
| 171 |
-
"gid": self.gid,
|
| 172 |
-
"guid": self.session.guid,
|
| 173 |
-
"fp": self.session.fprint,
|
| 174 |
-
"pubk": self.session.public_key
|
| 175 |
-
})
|
| 176 |
-
|
| 177 |
|
| 178 |
def update_description(self: Self, message: str) -> None:
|
| 179 |
log_module.logger.info(f"Description Updated: {self.gid}")
|
|
@@ -186,25 +164,11 @@ class User(BaseModel):
|
|
| 186 |
def can_use(self: Self, activity: str):
|
| 187 |
return security.can_use(self.role, activity)
|
| 188 |
|
| 189 |
-
def
|
| 190 |
-
count_tokens:int = 0
|
| 191 |
-
if message:
|
| 192 |
-
count_tokens:int = message.tokensOutput+message.tokensPrompt
|
| 193 |
-
year, month, day = datetime.now().strftime("%y-%m-%d").split("-")
|
| 194 |
-
|
| 195 |
-
if year not in self.tokens:
|
| 196 |
-
self.tokens[year] = {}
|
| 197 |
-
|
| 198 |
-
if month not in self.tokens[year]:
|
| 199 |
-
self.tokens[year][month] = {}
|
| 200 |
-
|
| 201 |
-
if day not in self.tokens[year][month] :
|
| 202 |
-
self.tokens[year][month][day] = 0
|
| 203 |
-
|
| 204 |
-
self.tokens[year][month][day] += count_tokens
|
| 205 |
-
|
| 206 |
DB.user.update_one({"gid": self.gid}, {"$set": self.model_dump(exclude={"guid", "session"})})
|
| 207 |
|
| 208 |
-
|
| 209 |
-
|
| 210 |
-
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
from typing_extensions import Unpack
|
| 3 |
+
from pydantic.config import ConfigDict
|
| 4 |
from pymongo.mongo_client import MongoClient
|
| 5 |
from pymongo.server_api import ServerApi
|
| 6 |
from fastapi import Request
|
|
|
|
| 62 |
def new_msg(self: Self):
|
| 63 |
return Message(role="", content="")
|
| 64 |
|
| 65 |
+
class APISession(BaseModel):
|
| 66 |
gid: str
|
| 67 |
+
fprint: str
|
| 68 |
public_key: str
|
| 69 |
guid: str = str(uuid.uuid4())
|
| 70 |
+
challenge: str = str(uuid.uuid4())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
|
| 72 |
+
def __init__(self, **kwargs: dict):
|
| 73 |
+
kwargs["fprint"] = security.sha256(kwargs["fprint"])
|
| 74 |
+
|
| 75 |
+
super(APISession, self).__init__(**kwargs)
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
|
|
|
|
| 79 |
|
| 80 |
@classmethod
|
| 81 |
+
def validate(cls: Self, request: Request, data: dict):
|
| 82 |
+
token_data:dict = security.token_from_headers(request)
|
| 83 |
+
if token_data["step"] != "intermediate":
|
| 84 |
+
security.raise_401()
|
| 85 |
+
token = request.headers.get("Autorization", " ").split(" ",1)[1]
|
| 86 |
+
fprint = security.sha256(data["fingerprint"])
|
| 87 |
+
security.validate_signature(data["public_key"],data["signature"], token)
|
| 88 |
+
if fprint != token_data["fprint"]:
|
| 89 |
+
security.raise_401()
|
| 90 |
+
|
| 91 |
+
new_obj = cls(**data)
|
| 92 |
+
return new_obj
|
| 93 |
|
| 94 |
+
def validate_signature(self: Self, signature:str):
|
| 95 |
+
valid = security.validate_signature(self.public_key, signature, self.challenge)
|
| 96 |
+
if not valid:
|
| 97 |
+
security.raise_401()
|
| 98 |
+
return True
|
| 99 |
+
|
| 100 |
+
def create_token(self: Self):
|
| 101 |
+
self.challenge = str(uuid.uuid4())
|
| 102 |
+
return security.create_jwt_token(self.model_dump())
|
| 103 |
|
| 104 |
|
| 105 |
class User(BaseModel):
|
|
|
|
| 111 |
email: str
|
| 112 |
gid: str
|
| 113 |
role: str = "on hold"
|
| 114 |
+
fprint: str = ""
|
| 115 |
configs: Configs = Configs()
|
|
|
|
| 116 |
|
| 117 |
@classmethod
|
| 118 |
def find(cls: Self, gid: str) -> Self | None:
|
|
|
|
| 123 |
|
| 124 |
@classmethod
|
| 125 |
def find_or_create(cls: Self, data: dict)-> Self:
|
| 126 |
+
if not data.get("fprint", None):
|
| 127 |
+
security.raise_307()
|
| 128 |
+
data["fprint"] = security.sha256(data["fprint"])
|
| 129 |
found:Self = cls.find(data["gid"])
|
| 130 |
if found:
|
| 131 |
+
found.fprint = data["fprint"]
|
| 132 |
return found
|
| 133 |
user:Self = cls(**data)
|
| 134 |
+
DB.user.insert_one(user.model_dump(exclude={"session", "fprint"}))
|
|
|
|
|
|
|
| 135 |
log_module.logger.info(f"User created: {user.gid}")
|
| 136 |
return user
|
| 137 |
|
| 138 |
+
def create_cookie(self: Self) -> str:
|
| 139 |
+
return security.create_jwt_token({"gid": self.gid, "fprint":self.fprint })
|
| 140 |
+
|
| 141 |
+
def create_shortlived_token(self: Self) -> str:
|
| 142 |
+
return security.create_jwt_token({"gid": self.gid, "fprint":self.fprint, "step":"intermediate" }, maxlife=3)
|
| 143 |
+
|
| 144 |
+
|
| 145 |
+
|
| 146 |
@classmethod
|
| 147 |
def find_from_cookie(cls:Self, request: Request) -> Self:
|
| 148 |
+
data:dict = security.token_from_cookie(request)
|
| 149 |
+
user:dict = DB.user.find_one({"gid":data["gid"]})
|
| 150 |
|
| 151 |
+
if (user.get("gid", None)):
|
| 152 |
+
return cls(**user)
|
| 153 |
+
|
| 154 |
+
security.raise_307()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 155 |
|
| 156 |
def update_description(self: Self, message: str) -> None:
|
| 157 |
log_module.logger.info(f"Description Updated: {self.gid}")
|
|
|
|
| 164 |
def can_use(self: Self, activity: str):
|
| 165 |
return security.can_use(self.role, activity)
|
| 166 |
|
| 167 |
+
def update_user(self: Self, message: Message = None) -> None:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 168 |
DB.user.update_one({"gid": self.gid}, {"$set": self.model_dump(exclude={"guid", "session"})})
|
| 169 |
|
| 170 |
+
@staticmethod
|
| 171 |
+
def update_usage(gid:str, message:Message):
|
| 172 |
+
count_tokens:int = message.tokensOutput+message.tokensPrompt
|
| 173 |
+
inc_field = datetime.now().strftime("tokens.%y.%m.%d")
|
| 174 |
+
DB.user.update_one({"gid": gid}, {"$inc":{inc_field: count_tokens}})
|
modules/security.py
CHANGED
|
@@ -19,10 +19,9 @@ for key in settings.USERS:
|
|
| 19 |
|
| 20 |
|
| 21 |
|
| 22 |
-
def create_jwt_token(data):
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
to_encode.update({"exp": expire})
|
| 26 |
encoded_jwt = jwt.encode(to_encode, settings.JWT_SECRET, algorithm=settings.JWT_ALGORITHM)
|
| 27 |
return encoded_jwt
|
| 28 |
|
|
@@ -79,5 +78,10 @@ def validate_signature(public_key: str, signature: str, data:str) -> bool:
|
|
| 79 |
pss.new(public_key).verify(data_, signature)
|
| 80 |
return True
|
| 81 |
except ValueError:
|
| 82 |
-
|
| 83 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
|
| 20 |
|
| 21 |
|
| 22 |
+
def create_jwt_token(data, maxlife=settings.JWT_EXPIRATION_TIME_MINUTES_API):
|
| 23 |
+
expire = datetime.utcnow() + timedelta(minutes=maxlife)
|
| 24 |
+
to_encode = data | {"exp": expire}
|
|
|
|
| 25 |
encoded_jwt = jwt.encode(to_encode, settings.JWT_SECRET, algorithm=settings.JWT_ALGORITHM)
|
| 26 |
return encoded_jwt
|
| 27 |
|
|
|
|
| 78 |
pss.new(public_key).verify(data_, signature)
|
| 79 |
return True
|
| 80 |
except ValueError:
|
| 81 |
+
raise_401()
|
| 82 |
+
|
| 83 |
+
def sha256(data:str|bytes) -> str:
|
| 84 |
+
data_ = data if isinstance(data, bytes) else data.encode()
|
| 85 |
+
return SHA256.new(data_).hexdigest()
|
| 86 |
+
|
| 87 |
+
|
modules/settings.py
CHANGED
|
@@ -22,7 +22,7 @@ USERS = json.loads(str(os.getenv("USER_KEYS")).replace("\n", ""))
|
|
| 22 |
|
| 23 |
JWT_SECRET = USERS["master"]
|
| 24 |
JWT_ALGORITHM = "HS256"
|
| 25 |
-
JWT_EXPIRATION_TIME_MINUTES_API =
|
| 26 |
JWT_EXPIRATION_TIME_MINUTES_VIEW = 7*24*60
|
| 27 |
|
| 28 |
|
|
|
|
| 22 |
|
| 23 |
JWT_SECRET = USERS["master"]
|
| 24 |
JWT_ALGORITHM = "HS256"
|
| 25 |
+
JWT_EXPIRATION_TIME_MINUTES_API = 7*24*60
|
| 26 |
JWT_EXPIRATION_TIME_MINUTES_VIEW = 7*24*60
|
| 27 |
|
| 28 |
|
static/js/chatHandler.js
CHANGED
|
@@ -53,8 +53,7 @@ class ChatGPT{
|
|
| 53 |
let data = {
|
| 54 |
fingerprint: this.fp,
|
| 55 |
public_key: this.pubk,
|
| 56 |
-
signature: this.tokenSigned
|
| 57 |
-
data: this.token
|
| 58 |
}
|
| 59 |
|
| 60 |
$.ajax({
|
|
|
|
| 53 |
let data = {
|
| 54 |
fingerprint: this.fp,
|
| 55 |
public_key: this.pubk,
|
| 56 |
+
signature: this.tokenSigned
|
|
|
|
| 57 |
}
|
| 58 |
|
| 59 |
$.ajax({
|
templates/main.html
CHANGED
|
@@ -173,7 +173,7 @@
|
|
| 173 |
</dialog>
|
| 174 |
|
| 175 |
<script>
|
| 176 |
-
async function
|
| 177 |
let keypair = await window.crypto.subtle.generateKey(
|
| 178 |
{
|
| 179 |
name: "RSA-PSS",
|
|
@@ -202,7 +202,7 @@
|
|
| 202 |
|
| 203 |
let exportKey_u8 = new Uint8Array(exportKey_ba);
|
| 204 |
let exportKey = "-----BEGIN PUBLIC KEY-----\n"+btoa(String.fromCharCode(...exportKey_u8))+"\n-----END PUBLIC KEY-----"
|
| 205 |
-
|
| 206 |
console.log("exportedKey");
|
| 207 |
console.log(exportKey);
|
| 208 |
console.log("sign");
|
|
@@ -217,7 +217,7 @@
|
|
| 217 |
cHand = new ChatGPT("{{ token }}", fp.visitorId, exportKey, sign);
|
| 218 |
|
| 219 |
}
|
| 220 |
-
|
| 221 |
|
| 222 |
|
| 223 |
|
|
|
|
| 173 |
</dialog>
|
| 174 |
|
| 175 |
<script>
|
| 176 |
+
async function start(){
|
| 177 |
let keypair = await window.crypto.subtle.generateKey(
|
| 178 |
{
|
| 179 |
name: "RSA-PSS",
|
|
|
|
| 202 |
|
| 203 |
let exportKey_u8 = new Uint8Array(exportKey_ba);
|
| 204 |
let exportKey = "-----BEGIN PUBLIC KEY-----\n"+btoa(String.fromCharCode(...exportKey_u8))+"\n-----END PUBLIC KEY-----"
|
| 205 |
+
|
| 206 |
console.log("exportedKey");
|
| 207 |
console.log(exportKey);
|
| 208 |
console.log("sign");
|
|
|
|
| 217 |
cHand = new ChatGPT("{{ token }}", fp.visitorId, exportKey, sign);
|
| 218 |
|
| 219 |
}
|
| 220 |
+
start()
|
| 221 |
|
| 222 |
|
| 223 |
|