Commit 9fbdd464 authored by arun.uday's avatar arun.uday

AssetManager-V1.0- Yet to be reviewed

Updated the code to include new user login if the user email domain is knowledgelens. Also, added necessary validations to the code.
parent 5a7d4881
...@@ -6,14 +6,33 @@ if __name__ == "__main__": ...@@ -6,14 +6,33 @@ if __name__ == "__main__":
import uvicorn import uvicorn
from scripts.config import PROJECT_NAME, Services from scripts.config import Services
import argparse
from scripts.logging.logger import logger from scripts.logging.logger import logger
# starting the application # starting the application
ap = argparse.ArgumentParser()
if __name__ == "__main__": if __name__ == "__main__":
try: try:
print("Api for " + PROJECT_NAME) ap.add_argument(
# uvicorn run "--port",
uvicorn.run("main:app", port=int(Services.PORT)) "-p",
required=False,
default=Services.PORT,
help="Port to start the application.",
)
ap.add_argument(
"--bind",
"-b",
required=False,
default=Services.HOST,
help="IF to start the application.",
)
arguments = vars(ap.parse_args())
logger.info(f"App Starting at {arguments['bind']}:{arguments['port']}")
uvicorn.run("main:app", host=arguments["bind"], port=int(arguments["port"]))
except Exception as e: except Exception as e:
logger.error(e) logger.exception(e)
[PROJECT_NAME] [PROJECT_DETAILS]
PROJECT_NAME = AssetManager PROJECT_NAME = AssetManager
PROJECT_ID = 1256
[PATH] [PATH]
base_path = scripts/ base_path = scripts/
......
...@@ -15,7 +15,7 @@ if __name__ == "__main__": ...@@ -15,7 +15,7 @@ if __name__ == "__main__":
from fastapi import FastAPI from fastapi import FastAPI
from scripts.services import router from scripts.services import router
from scripts.config import PROJECT_NAME, Services as ServiceConf from scripts.config import Services as ServiceConf
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
from scripts.logging.logger import logger from scripts.logging.logger import logger
...@@ -25,7 +25,7 @@ app.include_router(router) ...@@ -25,7 +25,7 @@ app.include_router(router)
# starting the application # starting the application
if __name__ == "__main__": if __name__ == "__main__":
try: try:
print("Api for " + PROJECT_NAME) print("Api for " + ServiceConf.PROJECT_NAME)
# enabling cors for getting UI data # enabling cors for getting UI data
if ServiceConf.ENABLE_CORS: if ServiceConf.ENABLE_CORS:
app.add_middleware( app.add_middleware(
......
...@@ -5,12 +5,13 @@ from pydantic import BaseSettings, Field ...@@ -5,12 +5,13 @@ from pydantic import BaseSettings, Field
config = configparser.RawConfigParser() config = configparser.RawConfigParser()
config.read("conf/application.conf") config.read("conf/application.conf")
PROJECT_NAME = config.get("PROJECT_NAME", "PROJECT_NAME")
class _Services(BaseSettings): class _Services(BaseSettings):
HOST: str = Field(default="127.0.0.1", env="service_host") HOST: str = Field(default="127.0.0.1", env="service_host")
PORT: int = Field(default=8000, env="service_port") PORT: int = Field(default=8000, env="service_port")
PROJECT_NAME = config.get("PROJECT_DETAILS", "PROJECT_NAME")
PROJECT_ID = config.get("PROJECT_DETAILS", "PROJECT_ID")
# path # path
BASE_PATH = config.get("PATH", 'base_path') BASE_PATH = config.get("PATH", 'base_path')
SUB_PATH = config.get("PATH", "sub_path") SUB_PATH = config.get("PATH", "sub_path")
......
from __future__ import annotations from __future__ import annotations
import base64 import base64
import datetime
from Cryptodome.Cipher import AES from Cryptodome.Cipher import AES
from passlib.context import CryptContext from passlib.context import CryptContext
...@@ -9,27 +10,51 @@ from scripts.config import Services ...@@ -9,27 +10,51 @@ from scripts.config import Services
from scripts.database.mongo.mongo_login import MongoUser from scripts.database.mongo.mongo_login import MongoUser
from scripts.errors import ErrorMessages from scripts.errors import ErrorMessages
from scripts.logging.logger import logger from scripts.logging.logger import logger
from scripts.utils.mongo_default_queries import MongoQueries
class LoginHandlers: class LoginHandlers:
def __init__(self): def __init__(self):
self.mongo_user = MongoUser()
self.mongo_queries = MongoQueries()
self.pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") self.pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
self.db_user_data = None self.db_user_data = None
self.db_user_data = None
self.dt = datetime.datetime.now()
self.time_dt = datetime.datetime.now()
@staticmethod @staticmethod
def un_pad(s): def un_pad(s):
# un_padding the encrypted password
return s[:-ord(s[len(s) - 1:])] return s[:-ord(s[len(s) - 1:])]
def new_user_login(self, login_data, password):
# check the domain of the email the user has entered
if login_data.username.split("@")[-1] == "knowledgelens.com":
# hash the password
hashed_password = self.pwd_context.hash(password)
# Enter the user as a guest user to the db
if self.mongo_user.insert_user(
self.mongo_queries.insert_user_query(
login_data,
Services.PROJECT_ID,
hashed_password,
self.time_dt)):
return True
return False
def password_decrypt(self, password): def password_decrypt(self, password):
try: try:
# encoding the Key # encoding the Key
key = Services.KEY_ENCRYPTION.encode('utf-8') key = Services.KEY_ENCRYPTION.encode('utf-8')
# decoding the received password # decoding the received password
enc = base64.b64decode(password) enc = base64.b64decode(password)
# mode for the decryption
mode = AES.MODE_CBC
# getting the initialization vector # getting the initialization vector
iv = enc[:AES.block_size] iv = enc[:AES.block_size]
# decoding with AES # decoding with AES
cipher = AES.new(key, AES.MODE_CBC, iv) cipher = AES.new(key, mode, iv)
# decoding the password # decoding the password
data = cipher.decrypt(enc[AES.block_size:]) data = cipher.decrypt(enc[AES.block_size:])
if len(data) == 0: if len(data) == 0:
...@@ -53,29 +78,40 @@ class LoginHandlers: ...@@ -53,29 +78,40 @@ class LoginHandlers:
except Exception as e: except Exception as e:
logger.exception(e) logger.exception(e)
def db_data_validation(self, username): def db_data_validation(self, login_data, password):
try: try:
# fetching the data based on the username # fetching the data based on the username
self.db_user_data = MongoUser().fetch_user_details(username) self.db_user_data = MongoUser().fetch_user_details(login_data.username)
# if the user is not available # if the user is not available
if not self.db_user_data: if not self.db_user_data:
return False, {"message": ErrorMessages.ERROR_USER_NOT_REGISTERED, "data": username} # if the domain of the user email is knowledge lens create the user as a guest user
if self.new_user_login(login_data, password):
return True, {"message": "new_user", "username": login_data.username, "role": "guest"}
else:
return False, {"message": ErrorMessages.ERROR_INVALID_USERNAME,
"data": {login_data.username, login_data.password}}
# Check the project id from the request body
if self.db_user_data["project_id"] != Services.PROJECT_ID or Services.PROJECT_ID != login_data.project_id:
return False, {"message": ErrorMessages.ERROR_UNAUTHORIZED_USER_LOGIN, "data": login_data.username}
# if the user exist # if the user exist
return None, {"message": True} return None, {"message": True}
except Exception as e: except Exception as e:
logger.exception(e) logger.exception(e)
def db_password_matching(self, username, password): def db_password_matching(self, login_data, password):
try: try:
# getting the response after checking for the user data in db # getting the response after checking for the user data in db
response, message = self.db_data_validation(username) response, message = self.db_data_validation(login_data, password)
# if the response is false then a error message is send back if response and message["message"] == "new_user":
return None, message
# if the response is false then an error message is send back
if response is not None: if response is not None:
return response, message return response, message
# if the user exists in db then password is matched # if the user exists in db then password is matched
if not self.pwd_context.verify(password, self.db_user_data["password"]): if not self.pwd_context.verify(password, self.db_user_data["password"]):
return False, {"message": ErrorMessages.ERROR_PASSWORD_MISMATCH, "data": {"username": username}} return False, {"message": ErrorMessages.ERROR_PASSWORD_MISMATCH,
"data": {"username": login_data.username}}
# if the password is correct # if the password is correct
return None, {"username": username, "role": self.db_user_data["user_role"]} return None, {"username": login_data.username, "role": self.db_user_data["user_role"]}
except Exception as e: except Exception as e:
logger.exception(e) logger.exception(e)
...@@ -6,5 +6,6 @@ class ErrorMessages: ...@@ -6,5 +6,6 @@ class ErrorMessages:
ERROR_INVALID_LOGIN = "Your are not authorized to view this website." ERROR_INVALID_LOGIN = "Your are not authorized to view this website."
ERROR_INVALID_USERNAME = "Invalid Username" ERROR_INVALID_USERNAME = "Invalid Username"
ERROR_INVALID_PASSWORD = "Invalid Password" ERROR_INVALID_PASSWORD = "Invalid Password"
ERROR_UNAUTHORIZED_USER_LOGIN = "Account is not available"
ERROR_USER_NOT_REGISTERED = "Account is not registered in the portal." ERROR_USER_NOT_REGISTERED = "Account is not registered in the portal."
ERROR_PASSWORD_MISMATCH = "Passwords Authentication Failed. Please enter the correct password" ERROR_PASSWORD_MISMATCH = "Passwords Authentication Failed. Please enter the correct password"
This diff is collapsed.
...@@ -2,7 +2,7 @@ import logging ...@@ -2,7 +2,7 @@ import logging
import os import os
from logging.handlers import RotatingFileHandler from logging.handlers import RotatingFileHandler
from scripts.config import Services, PROJECT_NAME from scripts.config import Services
def get_logger(): def get_logger():
...@@ -29,7 +29,7 @@ def get_logger(): ...@@ -29,7 +29,7 @@ def get_logger():
os.makedirs(file_path) os.makedirs(file_path)
# joining the path # joining the path
log_file = os.path.join(f"{file_path}{PROJECT_NAME}log.log") log_file = os.path.join(f"{file_path}{Services.PROJECT_NAME}log.log")
# creating rotating file handler with max byte as 1 # creating rotating file handler with max byte as 1
temp_handler = RotatingFileHandler(log_file, maxBytes=1) temp_handler = RotatingFileHandler(log_file, maxBytes=1)
......
...@@ -18,15 +18,13 @@ def login_default(login_data: NormalLogin): ...@@ -18,15 +18,13 @@ def login_default(login_data: NormalLogin):
try: try:
# decrypting the password from the UI # decrypting the password from the UI
decrypted_password = obj_login_handler.password_decrypt(login_data.password) decrypted_password = obj_login_handler.password_decrypt(login_data.password)
# validating the received inputs empty or not # validating the received inputs empty or not
response = obj_login_handler.user_data_validation(login_data.username, decrypted_password) response = obj_login_handler.user_data_validation(login_data.username, decrypted_password)
if response is not None: if response is not None:
return JSONResponse(content=DefaultFailureResponse(error=response["message"]).dict(), return JSONResponse(content=DefaultFailureResponse(error=response["message"]).dict(),
status_code=status.HTTP_400_BAD_REQUEST) status_code=status.HTTP_400_BAD_REQUEST)
# checking for the account and password matching # checking for the account and password matching
response, data = obj_login_handler.db_password_matching(login_data.username, decrypted_password) response, data = obj_login_handler.db_password_matching(login_data, decrypted_password)
if response is not None: if response is not None:
return JSONResponse(content=DefaultFailureResponse(error=data).dict(), return JSONResponse(content=DefaultFailureResponse(error=data).dict(),
status_code=status.HTTP_401_UNAUTHORIZED) status_code=status.HTTP_401_UNAUTHORIZED)
......
class MongoQueries:
@staticmethod
def insert_user_query(login_data, project_id, hashed_password, time_dt):
query = {"project_id": project_id, "name": "", "email": login_data.username,
"password": hashed_password,
"user_role": "guest",
"is_alive": True, "created_at": time_dt,
"updated_at": time_dt}
return query
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment