dev step
Browse files- main.py +17 -3
- modules/model.py +11 -3
- modules/security.py +16 -2
- static/js/chatHandler.js +28 -1
- templates/main.html +50 -45
main.py
CHANGED
|
@@ -5,6 +5,7 @@ import os, json
|
|
| 5 |
import time
|
| 6 |
from hashlib import sha256
|
| 7 |
from modules import model, oauth, security, log_module, llm, chat_functions, settings
|
|
|
|
| 8 |
from fastapi.staticfiles import StaticFiles
|
| 9 |
from fastapi.templating import Jinja2Templates
|
| 10 |
from datetime import datetime
|
|
@@ -19,11 +20,11 @@ log_module.log_write("master", "iniciado", "-")
|
|
| 19 |
|
| 20 |
########################## MAIN ##########################
|
| 21 |
@app.get("/", response_class=HTMLResponse)
|
| 22 |
-
async def main_page(request: Request, user = Depends(
|
| 23 |
if not user.can_use("chat"):
|
| 24 |
return RedirectResponse(url='/hold')
|
| 25 |
|
| 26 |
-
tools = [{"name": k, "desc": v} for k, v in chat_functions.function_user_text.items()
|
| 27 |
token = user.create_token()
|
| 28 |
response = templates.TemplateResponse(
|
| 29 |
"main.html", {
|
|
@@ -67,12 +68,25 @@ async def get_configs(request: Request, user = Depends(model.User.find_from_head
|
|
| 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(
|
| 71 |
user.configs = configs
|
| 72 |
user.update()
|
| 73 |
return {"success":True}
|
| 74 |
|
| 75 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
@app.post("/chat")
|
| 77 |
async def chat_async(request: Request, body: model.Chat, user = Depends(model.User.find_from_header)):
|
| 78 |
if(len(body.messages) < 1 or body.messages[-1].content==""):
|
|
|
|
| 5 |
import time
|
| 6 |
from hashlib import sha256
|
| 7 |
from modules import model, oauth, security, log_module, llm, chat_functions, settings
|
| 8 |
+
from modules.model import User
|
| 9 |
from fastapi.staticfiles import StaticFiles
|
| 10 |
from fastapi.templating import Jinja2Templates
|
| 11 |
from datetime import datetime
|
|
|
|
| 20 |
|
| 21 |
########################## MAIN ##########################
|
| 22 |
@app.get("/", response_class=HTMLResponse)
|
| 23 |
+
async def main_page(request: Request, user: User = Depends(User.find_from_cookie)):
|
| 24 |
if not user.can_use("chat"):
|
| 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_token()
|
| 29 |
response = templates.TemplateResponse(
|
| 30 |
"main.html", {
|
|
|
|
| 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: dict, user: User = Depends(User.find_from_header)):
|
| 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 |
+
class Session(BaseModel):
|
| 85 |
+
gid: str
|
| 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==""):
|
modules/model.py
CHANGED
|
@@ -62,11 +62,14 @@ class Chat(BaseModel):
|
|
| 62 |
|
| 63 |
class Session(BaseModel):
|
| 64 |
gid: str
|
| 65 |
-
|
|
|
|
| 66 |
guid: str = str(uuid.uuid4())
|
| 67 |
created: datetime = datetime.now(tz)
|
| 68 |
updated: datetime = datetime.now(tz)
|
| 69 |
expire: datetime = datetime.now(tz)+timedelta(days=7)
|
|
|
|
|
|
|
| 70 |
|
| 71 |
@classmethod
|
| 72 |
def remove_expired(cls: Self, gid: str) -> None:
|
|
@@ -164,8 +167,13 @@ class User(BaseModel):
|
|
| 164 |
|
| 165 |
|
| 166 |
def create_token(self: Self) -> str:
|
| 167 |
-
return security.create_jwt_token({
|
| 168 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 169 |
|
| 170 |
def update_description(self: Self, message: str) -> None:
|
| 171 |
log_module.logger.info(f"Description Updated: {self.gid}")
|
|
|
|
| 62 |
|
| 63 |
class Session(BaseModel):
|
| 64 |
gid: str
|
| 65 |
+
fingerprint: str
|
| 66 |
+
public_key: str
|
| 67 |
guid: str = str(uuid.uuid4())
|
| 68 |
created: datetime = datetime.now(tz)
|
| 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:
|
|
|
|
| 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}")
|
modules/security.py
CHANGED
|
@@ -5,7 +5,10 @@ from fastapi.security import HTTPBasicCredentials
|
|
| 5 |
from fastapi.responses import RedirectResponse
|
| 6 |
from . import log_module, settings
|
| 7 |
from datetime import datetime, timedelta
|
| 8 |
-
|
|
|
|
|
|
|
|
|
|
| 9 |
|
| 10 |
|
| 11 |
for key in settings.USERS:
|
|
@@ -66,4 +69,15 @@ def raise_307():
|
|
| 66 |
status_code=status.HTTP_307_TEMPORARY_REDIRECT,
|
| 67 |
detail="Could not validate access",
|
| 68 |
headers=headers
|
| 69 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
from fastapi.responses import RedirectResponse
|
| 6 |
from . import log_module, settings
|
| 7 |
from datetime import datetime, timedelta
|
| 8 |
+
from Crypto.Signature import pss
|
| 9 |
+
from Crypto.Hash import SHA256
|
| 10 |
+
from Crypto.PublicKey import RSA
|
| 11 |
+
import base64
|
| 12 |
|
| 13 |
|
| 14 |
for key in settings.USERS:
|
|
|
|
| 69 |
status_code=status.HTTP_307_TEMPORARY_REDIRECT,
|
| 70 |
detail="Could not validate access",
|
| 71 |
headers=headers
|
| 72 |
+
)
|
| 73 |
+
|
| 74 |
+
def validate_signature(public_key: str, signature: str, data:str) -> bool:
|
| 75 |
+
public_key = RSA.import_key(public_key)
|
| 76 |
+
signature = base64.b64decode(signature)
|
| 77 |
+
data_ = SHA256.new(data.encode())
|
| 78 |
+
try:
|
| 79 |
+
pss.new(public_key).verify(data_, signature)
|
| 80 |
+
return True
|
| 81 |
+
except ValueError:
|
| 82 |
+
return False
|
| 83 |
+
|
static/js/chatHandler.js
CHANGED
|
@@ -32,9 +32,13 @@ class ChatGPT{
|
|
| 32 |
token = null;
|
| 33 |
windowHandlers = {}
|
| 34 |
|
| 35 |
-
constructor(token){
|
| 36 |
// Token JWT de ejecución
|
| 37 |
this.token = token;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
|
| 39 |
this.cargarConfigs();
|
| 40 |
|
|
@@ -43,6 +47,29 @@ class ChatGPT{
|
|
| 43 |
|
| 44 |
this.cargarChats()
|
| 45 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
}
|
| 47 |
|
| 48 |
cargarEventos(){
|
|
|
|
| 32 |
token = null;
|
| 33 |
windowHandlers = {}
|
| 34 |
|
| 35 |
+
constructor(token, fp, exportKey, tokenSigned){
|
| 36 |
// Token JWT de ejecución
|
| 37 |
this.token = token;
|
| 38 |
+
this.fp = fp
|
| 39 |
+
this.pubk = exportKey
|
| 40 |
+
this.tokenSigned = tokenSigned
|
| 41 |
+
this.obtenerToken()
|
| 42 |
|
| 43 |
this.cargarConfigs();
|
| 44 |
|
|
|
|
| 47 |
|
| 48 |
this.cargarChats()
|
| 49 |
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
obtenerToken(){
|
| 53 |
+
let data = {
|
| 54 |
+
fingerprint: this.fp,
|
| 55 |
+
public_key: this.pubk,
|
| 56 |
+
signature: this.tokenSigned,
|
| 57 |
+
data: this.token
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
$.ajax({
|
| 61 |
+
method: "POST",
|
| 62 |
+
url: "/getToken",
|
| 63 |
+
headers: {
|
| 64 |
+
"Autorization": "Bearer " + this.token,
|
| 65 |
+
'Content-Type': 'application/json',
|
| 66 |
+
},
|
| 67 |
+
data: JSON.stringify(data),
|
| 68 |
+
timeout: 5000,
|
| 69 |
+
dataType: "json"
|
| 70 |
+
})
|
| 71 |
+
|
| 72 |
+
|
| 73 |
}
|
| 74 |
|
| 75 |
cargarEventos(){
|
templates/main.html
CHANGED
|
@@ -173,61 +173,66 @@
|
|
| 173 |
</dialog>
|
| 174 |
|
| 175 |
<script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 176 |
|
|
|
|
|
|
|
| 177 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 178 |
var cHand;
|
| 179 |
let versionLocal = localStorage.getItem("version")
|
| 180 |
let versionRemota = "{{ version }}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 181 |
|
| 182 |
|
| 183 |
$(document).ready(function() {
|
| 184 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 185 |
|
| 186 |
-
|
| 187 |
-
|
| 188 |
-
name: "RSA-PSS",
|
| 189 |
-
modulusLength: 1024,
|
| 190 |
-
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
|
| 191 |
-
hash: {name: "SHA-256"},
|
| 192 |
-
},
|
| 193 |
-
false,
|
| 194 |
-
["sign"]
|
| 195 |
-
)
|
| 196 |
-
|
| 197 |
-
let x2 = x1.then(keypair =>{
|
| 198 |
-
this.keypair = keypair;
|
| 199 |
-
return window.crypto.subtle.exportKey(
|
| 200 |
-
"spki",
|
| 201 |
-
keypair.publicKey
|
| 202 |
-
)})
|
| 203 |
-
|
| 204 |
-
let x3 = x2.then(exportedKey => {
|
| 205 |
-
this.exportedKey = exportedKey;
|
| 206 |
-
let c = window.crypto.subtle.sign(
|
| 207 |
-
{
|
| 208 |
-
name: "RSA-PSS",
|
| 209 |
-
saltLength: 128,
|
| 210 |
-
},
|
| 211 |
-
this.keypair.privateKey,
|
| 212 |
-
new TextEncoder().encode("{{ token }}")
|
| 213 |
-
);
|
| 214 |
-
return c;
|
| 215 |
-
|
| 216 |
-
})
|
| 217 |
-
|
| 218 |
-
x3.catch(e => {
|
| 219 |
-
console.log(e)
|
| 220 |
-
}).finally(y => {
|
| 221 |
-
console.log( y)
|
| 222 |
-
})
|
| 223 |
-
console.log(x1)
|
| 224 |
-
console.log(x2)
|
| 225 |
-
console.log(x3)
|
| 226 |
-
|
| 227 |
-
// .then(sign_ba => {
|
| 228 |
-
// let sign_u8 = new Uint8Array(sign_ba);
|
| 229 |
-
// return btoa(String.fromCharCode(...sign_u8));
|
| 230 |
-
// }).then(sign => {
|
| 231 |
// console.log("exportedKey");
|
| 232 |
// console.log(this.exportedKey);
|
| 233 |
// console.log("sign");
|
|
|
|
| 173 |
</dialog>
|
| 174 |
|
| 175 |
<script>
|
| 176 |
+
async function generatex(){
|
| 177 |
+
let keypair = await window.crypto.subtle.generateKey(
|
| 178 |
+
{
|
| 179 |
+
name: "RSA-PSS",
|
| 180 |
+
modulusLength: 1024,
|
| 181 |
+
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
|
| 182 |
+
hash: {name: "SHA-256"},
|
| 183 |
+
},
|
| 184 |
+
false,
|
| 185 |
+
["sign"]
|
| 186 |
+
)
|
| 187 |
+
let exportKey_ba = await window.crypto.subtle.exportKey(
|
| 188 |
+
"spki",
|
| 189 |
+
keypair.publicKey
|
| 190 |
+
)
|
| 191 |
+
let encoder = new TextEncoder()
|
| 192 |
+
let sign_ba = await window.crypto.subtle.sign(
|
| 193 |
+
{
|
| 194 |
+
name: "RSA-PSS",
|
| 195 |
+
saltLength: 32,
|
| 196 |
+
},
|
| 197 |
+
keypair.privateKey,
|
| 198 |
+
encoder.encode("{{ token }}")
|
| 199 |
+
)
|
| 200 |
+
let sign_u8 = new Uint8Array(sign_ba);
|
| 201 |
+
let sign = btoa(String.fromCharCode(...sign_u8))
|
| 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");
|
| 209 |
+
console.log(sign);
|
| 210 |
+
|
| 211 |
+
const fpPromise = await import('/static/js/fingerprintv4.js').then(FingerprintJS => FingerprintJS.load())
|
| 212 |
+
const fp = await fpPromise.get()
|
| 213 |
+
console.log(fp.visitorId)
|
| 214 |
var cHand;
|
| 215 |
let versionLocal = localStorage.getItem("version")
|
| 216 |
let versionRemota = "{{ version }}"
|
| 217 |
+
cHand = new ChatGPT("{{ token }}", fp.visitorId, exportKey, sign);
|
| 218 |
+
|
| 219 |
+
}
|
| 220 |
+
generatex()
|
| 221 |
+
|
| 222 |
+
|
| 223 |
|
| 224 |
|
| 225 |
$(document).ready(function() {
|
| 226 |
|
| 227 |
+
// let x1 = .then(keypair =>{
|
| 228 |
+
// .then(exportedKey => {
|
| 229 |
+
// return
|
| 230 |
+
// ).then(sign_ba =>
|
| 231 |
+
// })
|
| 232 |
+
// })
|
| 233 |
|
| 234 |
+
// console.log(x1)
|
| 235 |
+
// .then(sign => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 236 |
// console.log("exportedKey");
|
| 237 |
// console.log(this.exportedKey);
|
| 238 |
// console.log("sign");
|