Spaces:
Runtime error
Runtime error
Hemanth Sai
commited on
Commit
Β·
6774da0
1
Parent(s):
0f7d563
Separated backend from frontend. (#7)
Browse files* Separated the backend and frontend
* Added Dev Container Folder
- .devcontainer/devcontainer.json +33 -0
- frontend/Login.py β Login.py +0 -0
- app.py +0 -1
- backend/__init__.py +0 -49
- backend/core/ConfigEnv.py +0 -32
- backend/core/ExceptionHandlers.py +0 -27
- backend/core/Exceptions.py +0 -45
- backend/core/__init__.py +0 -0
- backend/models/__init__.py +0 -3
- backend/models/auth.py +0 -32
- backend/models/generic.py +0 -14
- backend/models/inference.py +0 -6
- backend/router.py +0 -65
- backend/services/__init__.py +0 -0
- backend/services/auth/__init__.py +0 -2
- backend/services/auth/ops.py +0 -109
- backend/services/auth/utils/JWTBearer.py +0 -75
- backend/services/auth/utils/auth_funcs.py +0 -171
- backend/services/db/__init__.py +0 -0
- backend/services/db/utils/DBQueries.py +0 -61
- backend/utils/DBConnection.py +0 -57
- backend/utils/__init__.py +0 -1
- backend/utils/prompt.txt +0 -11
- backend/utils/scopes.py +0 -3
- frontend/__init__.py +0 -1
- {frontend/pages β pages}/Code.py +0 -0
- vercel.json +0 -4
- frontend/π‘_Home.py β π‘_Home.py +0 -0
.devcontainer/devcontainer.json
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"name": "Python 3",
|
3 |
+
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
|
4 |
+
"image": "mcr.microsoft.com/devcontainers/python:1-3.11-bullseye",
|
5 |
+
"customizations": {
|
6 |
+
"codespaces": {
|
7 |
+
"openFiles": [
|
8 |
+
"README.md",
|
9 |
+
"frontend/π‘_Home.py"
|
10 |
+
]
|
11 |
+
},
|
12 |
+
"vscode": {
|
13 |
+
"settings": {},
|
14 |
+
"extensions": [
|
15 |
+
"ms-python.python",
|
16 |
+
"ms-python.vscode-pylance"
|
17 |
+
]
|
18 |
+
}
|
19 |
+
},
|
20 |
+
"updateContentCommand": "[ -f packages.txt ] && sudo apt update && sudo apt upgrade -y && sudo xargs apt install -y <packages.txt; [ -f requirements.txt ] && pip3 install --user -r requirements.txt; pip3 install --user streamlit; echo 'β
Packages installed and Requirements met'",
|
21 |
+
"postAttachCommand": {
|
22 |
+
"server": "streamlit run frontend/π‘_Home.py --server.enableCORS false --server.enableXsrfProtection false"
|
23 |
+
},
|
24 |
+
"portsAttributes": {
|
25 |
+
"8501": {
|
26 |
+
"label": "Application",
|
27 |
+
"onAutoForward": "openPreview"
|
28 |
+
}
|
29 |
+
},
|
30 |
+
"forwardPorts": [
|
31 |
+
8501
|
32 |
+
]
|
33 |
+
}
|
frontend/Login.py β Login.py
RENAMED
File without changes
|
app.py
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
from backend import app
|
|
|
|
backend/__init__.py
DELETED
@@ -1,49 +0,0 @@
|
|
1 |
-
import mysql.connector
|
2 |
-
from mysql.connector import errorcode
|
3 |
-
|
4 |
-
from fastapi import FastAPI, status
|
5 |
-
from fastapi.exceptions import HTTPException
|
6 |
-
|
7 |
-
from backend.utils import DBConnection
|
8 |
-
from backend.core.ConfigEnv import config
|
9 |
-
|
10 |
-
from langchain.llms import Clarifai
|
11 |
-
from langchain.chains import LLMChain
|
12 |
-
from langchain.prompts import PromptTemplate
|
13 |
-
|
14 |
-
app = FastAPI(title="Techdocs",
|
15 |
-
version="V0.0.1",
|
16 |
-
description="API for automatic code documentation generation!"
|
17 |
-
)
|
18 |
-
|
19 |
-
from backend import router
|
20 |
-
|
21 |
-
try:
|
22 |
-
dbconnection = DBConnection()
|
23 |
-
test_conn = DBConnection.get_client().get_server_info()
|
24 |
-
|
25 |
-
# send prompt wizardcoderLM-70b-instruct-GGUF model
|
26 |
-
with open("backend/utils/prompt.txt",'r') as f:
|
27 |
-
prompt = f.read()
|
28 |
-
|
29 |
-
prompt = PromptTemplate(template=prompt, input_variables=['instruction'])
|
30 |
-
|
31 |
-
llm = Clarifai(
|
32 |
-
pat = config.CLARIFAI_PAT,
|
33 |
-
user_id = config.USER_ID,
|
34 |
-
app_id = config.APP_ID,
|
35 |
-
model_id = config.MODEL_ID,
|
36 |
-
model_version_id=config.MODEL_VERSION_ID,
|
37 |
-
)
|
38 |
-
|
39 |
-
llmchain = LLMChain(
|
40 |
-
prompt=prompt,
|
41 |
-
llm=llm
|
42 |
-
)
|
43 |
-
app.state.llmchain = llmchain
|
44 |
-
|
45 |
-
|
46 |
-
except mysql.connector.Error as err:
|
47 |
-
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(err))
|
48 |
-
|
49 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend/core/ConfigEnv.py
DELETED
@@ -1,32 +0,0 @@
|
|
1 |
-
"""Config class for handling env variables.
|
2 |
-
"""
|
3 |
-
from functools import lru_cache
|
4 |
-
|
5 |
-
from pydantic import BaseSettings
|
6 |
-
|
7 |
-
|
8 |
-
class Settings(BaseSettings):
|
9 |
-
HOSTNAME: str
|
10 |
-
DATABASE: str
|
11 |
-
UID: str
|
12 |
-
PASSWORD: str
|
13 |
-
ALGORITHM:str
|
14 |
-
JWT_SECRET_KEY:str
|
15 |
-
JWT_REFRESH_SECRET_KEY:str
|
16 |
-
# OPENAI_KEY:str
|
17 |
-
APP_ID:str
|
18 |
-
USER_ID:str
|
19 |
-
MODEL_ID:str
|
20 |
-
CLARIFAI_PAT:str
|
21 |
-
MODEL_VERSION_ID:str
|
22 |
-
|
23 |
-
class Config:
|
24 |
-
env_file = ".env"
|
25 |
-
|
26 |
-
|
27 |
-
@lru_cache()
|
28 |
-
def get_settings():
|
29 |
-
return Settings()
|
30 |
-
|
31 |
-
|
32 |
-
config = get_settings()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend/core/ExceptionHandlers.py
DELETED
@@ -1,27 +0,0 @@
|
|
1 |
-
from backend import app
|
2 |
-
from .Exceptions import *
|
3 |
-
|
4 |
-
from fastapi.responses import JSONResponse
|
5 |
-
from fastapi.requests import Request
|
6 |
-
from fastapi import status
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
@app.exception_handler(ExistingUserException)
|
11 |
-
async def handle_existing_user_found(request: Request, exec: ExistingUserException):
|
12 |
-
return JSONResponse(status_code=status.HTTP_226_IM_USED,
|
13 |
-
content=repr(exec)
|
14 |
-
)
|
15 |
-
|
16 |
-
|
17 |
-
@app.exception_handler(InvalidCredentialsException)
|
18 |
-
async def handle_login_failed(request: Request, exec: InvalidCredentialsException):
|
19 |
-
return JSONResponse(status_code=status.HTTP_403_FORBIDDEN,
|
20 |
-
content=repr(exec)
|
21 |
-
)
|
22 |
-
|
23 |
-
@app.exception_handler(InfoNotFoundException)
|
24 |
-
async def handle_info_not_found(request: Request, exec: InfoNotFoundException):
|
25 |
-
return JSONResponse(status_code=status.HTTP_401_UNAUTHORIZED,
|
26 |
-
content=repr(exec)
|
27 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend/core/Exceptions.py
DELETED
@@ -1,45 +0,0 @@
|
|
1 |
-
import json
|
2 |
-
|
3 |
-
from backend.models import GeneralResponse, TokenSchema
|
4 |
-
|
5 |
-
|
6 |
-
class InvalidCredentialsException(Exception):
|
7 |
-
def __init__(self, token_result: GeneralResponse):
|
8 |
-
self.token_result = token_result
|
9 |
-
self.set_statuses()
|
10 |
-
super(InvalidCredentialsException, self).__init__()
|
11 |
-
|
12 |
-
def set_statuses(self):
|
13 |
-
self.token_result.status = 'login_failed'
|
14 |
-
|
15 |
-
def __repr__(self):
|
16 |
-
return json.dumps(self.token_result)
|
17 |
-
|
18 |
-
class ExistingUserException(Exception):
|
19 |
-
def __init__(self, response_result: GeneralResponse):
|
20 |
-
self.response_result = response_result
|
21 |
-
self.set_statuses()
|
22 |
-
super(ExistingUserException, self).__init__()
|
23 |
-
|
24 |
-
def set_statuses(self):
|
25 |
-
self.response_result.status = f'failed'
|
26 |
-
self.response_result.message.append(f'user with this AADHAR Number already has an account')
|
27 |
-
self.response_result.message[0] = 'authenticated'
|
28 |
-
|
29 |
-
def __repr__(self):
|
30 |
-
return json.dumps(self.response_result)
|
31 |
-
|
32 |
-
class InfoNotFoundException(Exception):
|
33 |
-
def __init__(self, response_result: GeneralResponse, message: str):
|
34 |
-
self.response_result = response_result
|
35 |
-
self.message = message
|
36 |
-
self.set_statuses()
|
37 |
-
super(InfoNotFoundException, self).__init__(message)
|
38 |
-
|
39 |
-
def set_statuses(self):
|
40 |
-
self.response_result['status'] = 'abort'
|
41 |
-
self.response_result['message'][0] = 'authenticated'
|
42 |
-
self.response_result['message'].append(self.message)
|
43 |
-
|
44 |
-
def __repr__(self):
|
45 |
-
return json.dumps(self.response_result)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend/core/__init__.py
DELETED
File without changes
|
backend/models/__init__.py
DELETED
@@ -1,3 +0,0 @@
|
|
1 |
-
from .auth import *
|
2 |
-
from .generic import *
|
3 |
-
from .inference import *
|
|
|
|
|
|
|
|
backend/models/auth.py
DELETED
@@ -1,32 +0,0 @@
|
|
1 |
-
from pydantic import BaseModel, Field, EmailStr
|
2 |
-
from typing import Union, List, Tuple
|
3 |
-
|
4 |
-
from .generic import Base
|
5 |
-
|
6 |
-
|
7 |
-
class TokenSchema(Base):
|
8 |
-
access_token: str
|
9 |
-
refresh_token: str
|
10 |
-
|
11 |
-
|
12 |
-
class UserAuth(Base):
|
13 |
-
username: str = Field(..., description="username")
|
14 |
-
password: str = Field(..., min_length=5, max_length=24, description="user password")
|
15 |
-
email: EmailStr
|
16 |
-
|
17 |
-
|
18 |
-
class User(Base):
|
19 |
-
username: str
|
20 |
-
email: EmailStr
|
21 |
-
|
22 |
-
class TokenPayload(Base):
|
23 |
-
sub: str = None
|
24 |
-
exp: int = None
|
25 |
-
|
26 |
-
|
27 |
-
class LoginCreds(Base):
|
28 |
-
username: str
|
29 |
-
password: str
|
30 |
-
|
31 |
-
class APIKey(Base):
|
32 |
-
api_key: str
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend/models/generic.py
DELETED
@@ -1,14 +0,0 @@
|
|
1 |
-
from pydantic import BaseModel
|
2 |
-
from typing import List
|
3 |
-
|
4 |
-
|
5 |
-
class Base(BaseModel):
|
6 |
-
@classmethod
|
7 |
-
def get_instance(cls, **kwargs):
|
8 |
-
return cls(**kwargs)
|
9 |
-
|
10 |
-
|
11 |
-
class GeneralResponse(Base):
|
12 |
-
status:str
|
13 |
-
message: List[str]
|
14 |
-
data:dict
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend/models/inference.py
DELETED
@@ -1,6 +0,0 @@
|
|
1 |
-
from pydantic import BaseModel
|
2 |
-
from typing import List
|
3 |
-
from .generic import Base
|
4 |
-
|
5 |
-
class Inference(Base):
|
6 |
-
docstr:str
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend/router.py
DELETED
@@ -1,65 +0,0 @@
|
|
1 |
-
from fastapi import Request, Depends, UploadFile
|
2 |
-
from fastapi.middleware.cors import CORSMiddleware
|
3 |
-
|
4 |
-
from backend import app
|
5 |
-
from backend.utils import DBConnection
|
6 |
-
from backend.models import *
|
7 |
-
from backend.services.auth import *
|
8 |
-
|
9 |
-
|
10 |
-
app.add_middleware(
|
11 |
-
CORSMiddleware,
|
12 |
-
allow_origins=["*"],
|
13 |
-
allow_credentials=True,
|
14 |
-
allow_methods=["*"],
|
15 |
-
allow_headers=["*"],
|
16 |
-
)
|
17 |
-
|
18 |
-
@app.get("/api/response_check", tags=["Resource Server"])
|
19 |
-
def api_response_check():
|
20 |
-
response_result = GeneralResponse.get_instance(data={},
|
21 |
-
status="not_allowed",
|
22 |
-
message=["Not authenticated"]
|
23 |
-
)
|
24 |
-
|
25 |
-
try:
|
26 |
-
db_msg = ""
|
27 |
-
if DBConnection.is_connected():
|
28 |
-
db_msg = "Connection Successful to db!"
|
29 |
-
else:
|
30 |
-
db_msg = "Connection failed to db"
|
31 |
-
|
32 |
-
response_result.message.append(db_msg)
|
33 |
-
|
34 |
-
except Exception as e:
|
35 |
-
print("Exception :", e)
|
36 |
-
|
37 |
-
return response_result
|
38 |
-
|
39 |
-
@app.post("/auth/signup", summary="Creates new user account", response_model=GeneralResponse, tags=["Auth Server"])
|
40 |
-
async def signup(response: UserAuth):
|
41 |
-
response_result = GeneralResponse.get_instance(data={},
|
42 |
-
status="not_allowed",
|
43 |
-
message=["Not authenticated"]
|
44 |
-
)
|
45 |
-
ops_signup(response_result, response)
|
46 |
-
|
47 |
-
return response_result
|
48 |
-
|
49 |
-
@app.post("/auth/login", summary="Logs in user", response_model=TokenSchema, tags=["Auth Server"])
|
50 |
-
async def login(response:LoginCreds):
|
51 |
-
return ops_login(response)
|
52 |
-
|
53 |
-
@app.put("/auth/regenerate_api_key",summary="Forget Password",response_model=APIKey,tags=["Auth Server"],dependencies=[Depends(JWTBearer())])
|
54 |
-
async def regenerate_api_key(access_token: str = Depends(JWTBearer())):
|
55 |
-
user_sub=Auth.get_user_credentials(access_token)
|
56 |
-
|
57 |
-
return ops_regenerate_api_key(user_sub)
|
58 |
-
|
59 |
-
@app.post("/api/inference", summary="Inference", response_model=Inference, tags=["Resource Server"], dependencies=[Depends(JWTBearer())])
|
60 |
-
async def inference(code_block:str, api_key: str,access_token:str=Depends(JWTBearer())):
|
61 |
-
user_sub=Auth.get_user_credentials(access_token)
|
62 |
-
|
63 |
-
print("after res")
|
64 |
-
|
65 |
-
return ops_inference(code_block,api_key,user_sub)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend/services/__init__.py
DELETED
File without changes
|
backend/services/auth/__init__.py
DELETED
@@ -1,2 +0,0 @@
|
|
1 |
-
from .ops import *
|
2 |
-
from .utils.JWTBearer import *
|
|
|
|
|
|
backend/services/auth/ops.py
DELETED
@@ -1,109 +0,0 @@
|
|
1 |
-
from .utils.auth_funcs import *
|
2 |
-
from .utils.JWTBearer import *
|
3 |
-
from backend.models import *
|
4 |
-
from backend.services.db.utils.DBQueries import DBQueries
|
5 |
-
from backend.core.Exceptions import *
|
6 |
-
from backend import app
|
7 |
-
|
8 |
-
# import openai
|
9 |
-
# from transformers import RobertaTokenizer, T5ForConditionalGeneration
|
10 |
-
|
11 |
-
def ops_signup(response_result: GeneralResponse, data: UserAuth):
|
12 |
-
"""Wrapper method to handle signup process.
|
13 |
-
|
14 |
-
Args:
|
15 |
-
response_result: FrontendResponseModel. A TypedDict to return the
|
16 |
-
response captured from the API to the frontend.
|
17 |
-
data: UserAuth. New user's prospective credentials from the frontend
|
18 |
-
to create their account.
|
19 |
-
|
20 |
-
Raises:
|
21 |
-
ExistingUserException: If account with entered AADHAR Number already exists.
|
22 |
-
"""
|
23 |
-
# querying database to check if user already exist
|
24 |
-
user = DBQueries.fetch_data_from_database('auth', ['username', 'email'], f"username='{data.username}' OR email='{data.email}'")
|
25 |
-
if len(list(user)) != 0:
|
26 |
-
# user with the entered credentials already exists
|
27 |
-
raise ExistingUserException(response_result)
|
28 |
-
|
29 |
-
DBQueries.insert_to_database('auth', (data.username, Auth.get_password_hash(data.password), data.email),
|
30 |
-
['username', 'password', 'email'])
|
31 |
-
|
32 |
-
response_result.status = 'success'
|
33 |
-
response_result.message = [f'User created successfully']
|
34 |
-
|
35 |
-
def ops_login(data:LoginCreds):
|
36 |
-
"""Wrapper method to handle login process.
|
37 |
-
|
38 |
-
Args:
|
39 |
-
data: LoginCreds. User's credentials from the frontend to login to their account.
|
40 |
-
|
41 |
-
Returns:
|
42 |
-
TokenSchema. A Pydantic BaseModel to return the JWT tokens to the frontend.
|
43 |
-
|
44 |
-
Raises:
|
45 |
-
InvalidCredentialsException: If account with entered credentials does not exist.
|
46 |
-
"""
|
47 |
-
# querying database to check if user already exist
|
48 |
-
response_result = GeneralResponse.get_instance(data={},
|
49 |
-
status="not_allowed",
|
50 |
-
message=["Not authenticated"]
|
51 |
-
)
|
52 |
-
user = DBQueries.fetch_data_from_database('auth', ['username', 'password'], f"username='{data.username}'")
|
53 |
-
user = list(user)
|
54 |
-
if len(user) == 0:
|
55 |
-
# user with the entered credentials does not exist
|
56 |
-
raise InvalidCredentialsException(response_result)
|
57 |
-
user = user[0]
|
58 |
-
if not Auth.verify_password(data.password, user[1]) and Auth.verify_username(data.username, user[0]):
|
59 |
-
# password is incorrect
|
60 |
-
raise InvalidCredentialsException(response_result)
|
61 |
-
|
62 |
-
# password is correct
|
63 |
-
return TokenSchema(access_token=Auth.create_access_token(data.username),
|
64 |
-
refresh_token=Auth.create_refresh_token(data.username),
|
65 |
-
)
|
66 |
-
|
67 |
-
def ops_regenerate_api_key(username:str) -> APIKey:
|
68 |
-
|
69 |
-
user_API_entry = DBQueries.fetch_data_from_database('api_key', 'apikey', f"username='{username}'")
|
70 |
-
user_API_entry = list(user_API_entry)
|
71 |
-
apikey = None
|
72 |
-
|
73 |
-
if len(user_API_entry) != 0:
|
74 |
-
apikey = APIKey(api_key=Auth.generate_api_key(username))
|
75 |
-
DBQueries.update_data_in_database('api_key','apikey',f"username='{username}'", apikey.api_key)
|
76 |
-
|
77 |
-
else:
|
78 |
-
apikey = Auth.generate_api_key(username)
|
79 |
-
DBQueries.insert_to_database('api_key', (username, apikey), ['username', 'apikey'])
|
80 |
-
apikey = APIKey(api_key=apikey)
|
81 |
-
|
82 |
-
return apikey
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
def ops_inference(source_code:str,api_key:str,username:str):
|
87 |
-
response_result = GeneralResponse.get_instance(data={},
|
88 |
-
status="not_allowed",
|
89 |
-
message=["Not authenticated"]
|
90 |
-
)
|
91 |
-
|
92 |
-
user=DBQueries.fetch_data_from_database('api_key', ['apikey'], f"username='{username}'")
|
93 |
-
if len(list(user)) == 0:
|
94 |
-
# user with the entered credentials does not exist
|
95 |
-
raise InfoNotFoundException(response_result,"User not found")
|
96 |
-
elif list(user)[0][0]!=api_key:
|
97 |
-
raise InvalidCredentialsException(response_result)
|
98 |
-
|
99 |
-
def generate_docstring(source_code_message: str):
|
100 |
-
|
101 |
-
|
102 |
-
llm_response = app.state.llmchain.run({"instruction": source_code_message})
|
103 |
-
|
104 |
-
docstring = Inference(docstr=llm_response)
|
105 |
-
|
106 |
-
|
107 |
-
return docstring
|
108 |
-
|
109 |
-
return generate_docstring(source_code)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend/services/auth/utils/JWTBearer.py
DELETED
@@ -1,75 +0,0 @@
|
|
1 |
-
"""Custom Authentication & Authorization bearer to authenticate and authorize
|
2 |
-
users based on the following factors:
|
3 |
-
1. username
|
4 |
-
2.password
|
5 |
-
3.email
|
6 |
-
|
7 |
-
This utility class validates generated JWTs and grants scoped access to users
|
8 |
-
according to their roles.
|
9 |
-
"""
|
10 |
-
from backend.core.ConfigEnv import config
|
11 |
-
from backend.models import TokenPayload
|
12 |
-
|
13 |
-
from datetime import datetime
|
14 |
-
|
15 |
-
from fastapi import Request, HTTPException
|
16 |
-
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
17 |
-
from pydantic import ValidationError
|
18 |
-
from jose import jwt
|
19 |
-
|
20 |
-
|
21 |
-
class JWTBearer(HTTPBearer):
|
22 |
-
"""Custom bearer to validate access tokens.
|
23 |
-
|
24 |
-
Args:
|
25 |
-
auto_error: bool = True. Internal param to allow auto error detection.
|
26 |
-
|
27 |
-
Raises:
|
28 |
-
HHTTPException(403): If authentication scheme is not `Bearer`.
|
29 |
-
HTTPException(403): If the access token is invalid or expired.
|
30 |
-
HTTPException(403): If authorization code is invalid.
|
31 |
-
"""
|
32 |
-
def __init__(self, auto_error: bool = True):
|
33 |
-
super(JWTBearer, self).__init__(auto_error=auto_error)
|
34 |
-
|
35 |
-
async def __call__(self, request: Request) -> str:
|
36 |
-
credentials: HTTPAuthorizationCredentials = await super(JWTBearer, self).__call__(request)
|
37 |
-
if credentials:
|
38 |
-
if not credentials.scheme == "Bearer":
|
39 |
-
raise HTTPException(status_code=403, detail="Invalid authentication scheme.")
|
40 |
-
else:
|
41 |
-
is_valid = JWTBearer.token_validation(credentials.credentials)
|
42 |
-
if not is_valid:
|
43 |
-
raise HTTPException(status_code=403, detail="Invalid token or expired token.")
|
44 |
-
return credentials.credentials
|
45 |
-
else:
|
46 |
-
raise HTTPException(status_code=403, detail="Invalid authorization code.")
|
47 |
-
|
48 |
-
@staticmethod
|
49 |
-
def token_validation(token: str) -> bool:
|
50 |
-
"""Decodes JWTs to check their validity by inspecting expiry and
|
51 |
-
authorization code.
|
52 |
-
|
53 |
-
Args:
|
54 |
-
token: str. Authenticated `access_token` of the user.
|
55 |
-
|
56 |
-
Returns:
|
57 |
-
bool value to indicate validity of the access tokens.
|
58 |
-
|
59 |
-
Raises:
|
60 |
-
jwt.JWTError: If decode fails.
|
61 |
-
ValidationError: If JWTs are not in RFC 7519 standard.
|
62 |
-
"""
|
63 |
-
try:
|
64 |
-
payload = jwt.decode(
|
65 |
-
token, config.JWT_SECRET_KEY, algorithms=[config.ALGORITHM]
|
66 |
-
)
|
67 |
-
token_data = TokenPayload(**payload)
|
68 |
-
|
69 |
-
if datetime.fromtimestamp(token_data.exp) < datetime.now():
|
70 |
-
return False
|
71 |
-
|
72 |
-
except(jwt.JWTError, ValidationError):
|
73 |
-
return False
|
74 |
-
|
75 |
-
return True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend/services/auth/utils/auth_funcs.py
DELETED
@@ -1,171 +0,0 @@
|
|
1 |
-
"""Utility class to leverage encryption, verification of entered credentials
|
2 |
-
and generation of JWT access tokens.
|
3 |
-
"""
|
4 |
-
from datetime import datetime, timedelta
|
5 |
-
from typing import Union, Any
|
6 |
-
import secrets
|
7 |
-
|
8 |
-
from jose import jwt
|
9 |
-
from passlib.context import CryptContext
|
10 |
-
from pydantic import ValidationError
|
11 |
-
|
12 |
-
from fastapi.exceptions import HTTPException
|
13 |
-
|
14 |
-
from backend.core.ConfigEnv import config
|
15 |
-
from backend.core.Exceptions import *
|
16 |
-
from backend.models import TokenPayload, TokenSchema
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
ACCESS_TOKEN_EXPIRE_MINUTES = 30 # 30 minutes
|
21 |
-
REFRESH_TOKEN_EXPIRE_MINUTES = 60 * 24 * 3 # 3 days
|
22 |
-
|
23 |
-
|
24 |
-
class Auth:
|
25 |
-
"""Utility class to perform - 1.encryption via `bcrypt` scheme.
|
26 |
-
2.password hashing 3.verification of credentials and generating
|
27 |
-
access tokens.
|
28 |
-
|
29 |
-
Attrs:
|
30 |
-
pwd_context: CryptContext. Helper for hashing & verifying passwords
|
31 |
-
using `bcrypt` algorithm.
|
32 |
-
"""
|
33 |
-
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
@classmethod
|
38 |
-
def get_password_hash(cls,password: str) -> str:
|
39 |
-
"""Encrypts the entered password.
|
40 |
-
|
41 |
-
Args:
|
42 |
-
password: str. Entered password.
|
43 |
-
|
44 |
-
Returns:
|
45 |
-
returns hashed(encrypted) password string.
|
46 |
-
"""
|
47 |
-
return cls.pwd_context.hash(password)
|
48 |
-
|
49 |
-
@classmethod
|
50 |
-
def verify_password(cls, plain_password: str, hashed_password: str) -> bool:
|
51 |
-
"""Validates if the entered password matches the actual password.
|
52 |
-
|
53 |
-
Args:
|
54 |
-
plain_password: str. Entered password by user.
|
55 |
-
hashed_password: str. hashed password from the database.
|
56 |
-
|
57 |
-
Returns:
|
58 |
-
bool value indicating whether the passwords match or not.
|
59 |
-
"""
|
60 |
-
return cls.pwd_context.verify(plain_password, hashed_password)
|
61 |
-
|
62 |
-
@staticmethod
|
63 |
-
def verify_username(entered_username: str, db_username: str) -> bool:
|
64 |
-
"""Validates if the entered username matches the actual username.
|
65 |
-
|
66 |
-
Args:
|
67 |
-
entered_username: str. Entered `username` by user.
|
68 |
-
db_username: str. username from the database.
|
69 |
-
|
70 |
-
Returns:
|
71 |
-
bool value indicating whether the village names match or not.
|
72 |
-
"""
|
73 |
-
return entered_username == db_username
|
74 |
-
|
75 |
-
@staticmethod
|
76 |
-
def create_access_token(subject: Union[str, Any], expires_delta: int = None) -> str:
|
77 |
-
"""Creates JWT access token.
|
78 |
-
|
79 |
-
Args:
|
80 |
-
subject: Union[Any, str]. Hash_key to generate access token from.
|
81 |
-
expires_delta: int = None. Expiry time for the JWT.
|
82 |
-
|
83 |
-
Returns:
|
84 |
-
encoded_jwt: str. Encoded JWT token from the subject of interest.
|
85 |
-
"""
|
86 |
-
if expires_delta is not None:
|
87 |
-
expires_delta = datetime.utcnow() + expires_delta
|
88 |
-
else:
|
89 |
-
expires_delta = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
|
90 |
-
|
91 |
-
to_encode = {"exp": expires_delta, "sub": str(subject)}
|
92 |
-
encoded_jwt = jwt.encode(to_encode, config.JWT_SECRET_KEY, config.ALGORITHM)
|
93 |
-
return encoded_jwt
|
94 |
-
|
95 |
-
@staticmethod
|
96 |
-
def create_refresh_token(subject: Union[str, Any], expires_delta: int = None) -> str:
|
97 |
-
"""Creates JWT refresh access token.
|
98 |
-
|
99 |
-
Args:
|
100 |
-
subject: Union[Any, str]. Hash_key to generate access token from.
|
101 |
-
expires_delta: int = None. Expiry time for the JWT.
|
102 |
-
|
103 |
-
Returns:
|
104 |
-
encoded_jwt: str. Encoded JWT token from the subject of interest.
|
105 |
-
"""
|
106 |
-
if expires_delta is not None:
|
107 |
-
expires_delta = datetime.utcnow() + expires_delta
|
108 |
-
else:
|
109 |
-
expires_delta = datetime.utcnow() + timedelta(minutes=REFRESH_TOKEN_EXPIRE_MINUTES)
|
110 |
-
|
111 |
-
to_encode = {"exp": expires_delta, "sub": str(subject)}
|
112 |
-
encoded_jwt = jwt.encode(to_encode, config.JWT_REFRESH_SECRET_KEY, config.ALGORITHM)
|
113 |
-
return encoded_jwt
|
114 |
-
|
115 |
-
@staticmethod
|
116 |
-
def generate_access_tokens_from_refresh_tokens(token: str) -> TokenSchema:
|
117 |
-
"""Generates a new pair of tokens by implementing rotating
|
118 |
-
refresh_access_tokens.
|
119 |
-
|
120 |
-
Args:
|
121 |
-
token: str. Current valid refresh access token.
|
122 |
-
|
123 |
-
Returns:
|
124 |
-
tokens: TokenSchema. New tokens with new validity.
|
125 |
-
|
126 |
-
Raises:
|
127 |
-
LoginFailedException: If the current refresh access token is
|
128 |
-
invalid.
|
129 |
-
"""
|
130 |
-
tokens = TokenSchema.get_instance(
|
131 |
-
access_token= "",
|
132 |
-
refresh_token= "",
|
133 |
-
)
|
134 |
-
try:
|
135 |
-
payload = jwt.decode(
|
136 |
-
token, config.JWT_REFRESH_SECRET_KEY, algorithms=[config.ALGORITHM]
|
137 |
-
)
|
138 |
-
token_data = TokenPayload(**payload)
|
139 |
-
if datetime.fromtimestamp(token_data.exp)< datetime.now():
|
140 |
-
raise HTTPException(status_code=403, detail="Invalid token or expired token.")
|
141 |
-
except (jwt.JWTError, ValidationError):
|
142 |
-
raise InvalidCredentialsException(tokens)
|
143 |
-
tokens['access_token'] = Auth.create_access_token(token_data.sub)
|
144 |
-
tokens['refresh_token'] = Auth.create_refresh_token(token_data.sub)
|
145 |
-
tokens['status'] = 'login successful'
|
146 |
-
tokens['role'] = token_data.sub.split("_")[1]
|
147 |
-
return tokens
|
148 |
-
|
149 |
-
@classmethod
|
150 |
-
def generate_api_key(cls, username: str):
|
151 |
-
return cls.get_password_hash(username + secrets.token_urlsafe(25 - len(username)))
|
152 |
-
|
153 |
-
@classmethod
|
154 |
-
def get_user_credentials(cls,access_token:str):
|
155 |
-
response_result = GeneralResponse.get_instance(data={},
|
156 |
-
status="not_allowed",
|
157 |
-
message=["Not authenticated"]
|
158 |
-
)
|
159 |
-
try:
|
160 |
-
payload = jwt.decode(
|
161 |
-
access_token, config.JWT_SECRET_KEY, algorithms=[config.ALGORITHM]
|
162 |
-
)
|
163 |
-
token_data = TokenPayload(**payload)
|
164 |
-
return token_data.sub
|
165 |
-
except (jwt.JWTError, ValidationError):
|
166 |
-
raise InvalidCredentialsException(response_result)
|
167 |
-
|
168 |
-
@classmethod
|
169 |
-
def verify_apikey(cls,user_api_key:str,true_api_key:str):
|
170 |
-
return user_api_key == true_api_key
|
171 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend/services/db/__init__.py
DELETED
File without changes
|
backend/services/db/utils/DBQueries.py
DELETED
@@ -1,61 +0,0 @@
|
|
1 |
-
from typing import Union, Tuple, List
|
2 |
-
|
3 |
-
from backend.utils import DBConnection
|
4 |
-
from backend.core.Exceptions import *
|
5 |
-
|
6 |
-
|
7 |
-
class DBQueries:
|
8 |
-
@classmethod
|
9 |
-
def insert_to_database(cls, table_name:str, data:Union[Tuple, List[Tuple]], cols:List[str]=None):
|
10 |
-
con = DBConnection.get_client()
|
11 |
-
cursor = con.cursor()
|
12 |
-
QUERY = ('INSERT INTO {table_name} '
|
13 |
-
f'({",".join(cols)}) '
|
14 |
-
'VALUES '
|
15 |
-
).format(table_name=table_name)
|
16 |
-
print(data)
|
17 |
-
if isinstance(data, list):
|
18 |
-
QUERY+="("+",".join(["%s" for _ in range(len(data[0]))])+")"
|
19 |
-
cursor.executemany(QUERY, data)
|
20 |
-
else:
|
21 |
-
QUERY+="("+",".join(["%s" for _ in range(len(data))])+")"
|
22 |
-
cursor.execute(QUERY, data)
|
23 |
-
con.commit()
|
24 |
-
|
25 |
-
@classmethod
|
26 |
-
def fetch_data_from_database(cls,table_name:str,cols_to_fetch:Union[str, List[str]], where_clause:str=None):
|
27 |
-
con = DBConnection.get_client()
|
28 |
-
cursor = con.cursor()
|
29 |
-
if isinstance(cols_to_fetch, str):
|
30 |
-
cols_to_fetch = [cols_to_fetch]
|
31 |
-
cols_to_fetch = ", ".join(cols_to_fetch)
|
32 |
-
QUERY = ('SELECT {cols} FROM {table_name}').format(cols=cols_to_fetch, table_name=table_name)
|
33 |
-
if where_clause:
|
34 |
-
QUERY = QUERY + " WHERE " + where_clause
|
35 |
-
cursor.execute(QUERY)
|
36 |
-
return cursor.fetchall()
|
37 |
-
|
38 |
-
@classmethod
|
39 |
-
def update_data_in_database(cls, table_name:str, cols_to_update:Union[str, List[str]], where_clause:str=None, new_values:Union[str, List[str]]=None):
|
40 |
-
con = DBConnection.get_client()
|
41 |
-
cursor = con.cursor()
|
42 |
-
if isinstance(cols_to_update, str):
|
43 |
-
cols_to_update = cols_to_update + "=%s"
|
44 |
-
else:
|
45 |
-
cols_to_update = "=%s, ".join(cols_to_update)
|
46 |
-
|
47 |
-
if isinstance(new_values, str):
|
48 |
-
new_values = [new_values]
|
49 |
-
|
50 |
-
QUERY = ('UPDATE {table_name} SET {cols}').format(table_name=table_name, cols=cols_to_update)
|
51 |
-
if where_clause:
|
52 |
-
QUERY = QUERY + " WHERE " + where_clause
|
53 |
-
cursor.execute(QUERY, new_values)
|
54 |
-
con.commit()
|
55 |
-
return True
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend/utils/DBConnection.py
DELETED
@@ -1,57 +0,0 @@
|
|
1 |
-
""" Import Important Packages"""
|
2 |
-
import mysql.connector
|
3 |
-
|
4 |
-
from backend.core.ConfigEnv import config
|
5 |
-
|
6 |
-
|
7 |
-
class DBConnection:
|
8 |
-
"""DBConnection Class. It ensures only one instance of the class is
|
9 |
-
created and it is accessible from everywhere. It is used in the
|
10 |
-
design of logging classes, Configuration classes where we need to have
|
11 |
-
only one instance of the class. There is no need to create multiple
|
12 |
-
instances of each operation across all components of application.
|
13 |
-
|
14 |
-
Raises:
|
15 |
-
Exception: It raises an exception if the client instance is not created.
|
16 |
-
"""
|
17 |
-
__client = None #This is the client variable that is used to connect to the database
|
18 |
-
_flag = False
|
19 |
-
def __init__(self):
|
20 |
-
"""This is the constructor of the class. It is used to create the client
|
21 |
-
variable. It also checks if the client instance is already created.
|
22 |
-
If the client instance is already created, then it does not create a
|
23 |
-
new client instance.
|
24 |
-
"""
|
25 |
-
if DBConnection.__client is not None:
|
26 |
-
raise Exception("This class is a singleton!")
|
27 |
-
else:
|
28 |
-
creds={
|
29 |
-
'host':config.HOSTNAME,
|
30 |
-
'user':config.UID,
|
31 |
-
'password':config.PASSWORD,
|
32 |
-
'database':config.DATABASE
|
33 |
-
}
|
34 |
-
DBConnection.__client = mysql.connector.connect(**creds)
|
35 |
-
DBConnection._flag = True
|
36 |
-
|
37 |
-
@staticmethod # A static method is a method that is called without creating an instance of the class.
|
38 |
-
def get_client():
|
39 |
-
"""The get_client() function is used to get the client instance.
|
40 |
-
|
41 |
-
Returns:
|
42 |
-
DBConnection.__client: It returns the client instance.
|
43 |
-
"""
|
44 |
-
return DBConnection.__client
|
45 |
-
|
46 |
-
@classmethod
|
47 |
-
def is_connected(cls)->bool:
|
48 |
-
"""property to get the database connection flag.
|
49 |
-
Returns:
|
50 |
-
DBConnection._flag: bool. Connection status to the DB.
|
51 |
-
"""
|
52 |
-
return cls._flag
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend/utils/__init__.py
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
from .DBConnection import DBConnection
|
|
|
|
backend/utils/prompt.txt
DELETED
@@ -1,11 +0,0 @@
|
|
1 |
-
You are an AI Coding Assitant and your task is to generate an elaborate, high quality docstring for the query function given by the user. A docstring consists of the following sections:
|
2 |
-
1. Description: Is the description of what the function does.
|
3 |
-
2. Arguments:
|
4 |
-
1. Argument Name: Description of the argument and its type.
|
5 |
-
3. Returns: Description of the return value of the function if any.
|
6 |
-
4. Raises: Description of the errors that can be raised by the function if any.
|
7 |
-
|
8 |
-
Instruction: {instruction}
|
9 |
-
|
10 |
-
Your task is to generate a docstring for the above query.
|
11 |
-
Response:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend/utils/scopes.py
DELETED
@@ -1,3 +0,0 @@
|
|
1 |
-
from typing import Callable
|
2 |
-
|
3 |
-
from backend.models import User
|
|
|
|
|
|
|
|
frontend/__init__.py
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
|
|
|
|
{frontend/pages β pages}/Code.py
RENAMED
File without changes
|
vercel.json
DELETED
@@ -1,4 +0,0 @@
|
|
1 |
-
{
|
2 |
-
"builds": [{ "src": "app.py", "use": "@vercel/python" }],
|
3 |
-
"routes": [{ "src": "/(.*)", "dest": "app.py" }]
|
4 |
-
}
|
|
|
|
|
|
|
|
|
|
frontend/π‘_Home.py β π‘_Home.py
RENAMED
File without changes
|