Commit a0a786d6 authored by arun.uday's avatar arun.uday

AssetManager-V1.0- Not reviewed

> Updated the logger file
>  updated the change and reset password api
> deleted the conf file
> Updated source path
parent 3fdc6a3e
......@@ -9,9 +9,6 @@ SERVICE_PORT=8671
PROJECT_NAME=AssetManager
BASE_PATH=scripts/
SUB_PATH=log/
ENCODING_TYPE=utf-8
KEY_ENCRYPTION=kliLensKLiLensKL
SECRET_KEY=09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7
......@@ -24,3 +21,8 @@ HTML_LINK=scripts/utils/link_email.html
RESET_ENDPOINT=http://localhost:8671/asset_manager_api/v1/login/reset?token
CLIENT_ID=1060631831358-a21djaa3hm165a8976fnmo1lerujs5p6.apps.googleusercontent.com
LOG_PATH=log
LOG_LEVEL=INFO
BACKUP_COUNT=100
MAX_BYTES=5
......@@ -38,5 +38,5 @@ if __name__ == "__main__":
# starting the app
uvicorn.run("main:app", host=arguments["bind"], port=int(arguments["port"]))
except Exception as e:
logger.exception(e)
logger.exception(f'Services Failed with error {e}')
[project_name]
PROJECT_NAME = AssetManager
2023-04-04 20:12:33 - INFO - [MainThread:<module>(): 37] - App Starting at 0.0.0.0:8671
2023-04-04 20:08:30 - INFO - [MainThread:<module>(): 37] - App Starting at 0.0.0.0:8671
2023-04-04 20:07:39 - INFO - [MainThread:<module>(): 37] - App Starting at 0.0.0.0:8671
2023-04-04 20:06:55 - INFO - [MainThread:<module>(): 37] - App Starting at 0.0.0.0:8671
2023-04-04 20:06:23 - INFO - [MainThread:<module>(): 37] - App Starting at 0.0.0.0:8671
2023-04-04 20:06:10 - INFO - [MainThread:<module>(): 37] - App Starting at 0.0.0.0:8671
......@@ -14,8 +14,10 @@ class _Services(BaseSettings):
CORS_ALLOW_CREDENTIALS: bool = True
CORS_ALLOW_METHODS: list[str] = ["GET", "POST", "DELETE", "PUT"]
CORS_ALLOW_HEADERS: list[str] = ["*"]
LOG_LEVEL: Literal["INFO", "DEBUG", "ERROR", "QTRACE"] = "INFO"
ENABLE_FILE_LOGGING: bool = False
LOG_LEVEL: str
BACKUP_COUNT: int
MAX_BYTES: int
ENABLE_FILE_LOGGING: bool = True
EMAIL_SENDER: str
EMAIL_SMTP: str
EMAIL_PORT: int
......@@ -32,13 +34,8 @@ class _Databases(BaseSettings):
REDIS_LOGIN_DB: int
class _BasePathConf(BaseSettings):
BASE_PATH: str = "scripts/"
class _PathConf:
BASE_PATH: pathlib.Path = pathlib.Path(_BasePathConf().BASE_PATH)
LOG_PATH: pathlib.Path = BASE_PATH / "log/"
class _PathConf(BaseSettings):
LOG_PATH: str
class _Secrets(BaseSettings):
......
......@@ -4,7 +4,7 @@ from datetime import timedelta, datetime
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from jwt.exceptions import ExpiredSignatureError
from jwt.exceptions import ExpiredSignatureError, DecodeError
from google.oauth2 import id_token
from google.auth.transport import requests
......@@ -32,15 +32,20 @@ class LoginHandlers:
self.pass_decrypt = EncryptDecryptPassword()
self.login_type = ""
def normal_login(self, user_data, request):
def general_login(self, user_data, request):
self.login_type = "general_login"
# decrypting the password from the UI
decrypted_password = self.pass_decrypt.password_decrypt(user_data.password)
# validating the received inputs empty or not
# password decrypted form - token "password"
try:
responses = self.obj_login_handler.user_data_validation(
user_data.email,
decrypted_password.split("\"")[1])
except AttributeError:
return JSONResponse(content=DefaultFailureResponse(status="failed",
message=ErrorMessages.ERROR_INVALID_PASSWORD).dict(),
status_code=status.HTTP_200_OK)
# Account is not registered
if responses is not None:
return JSONResponse(content=DefaultFailureResponse(status="failed",
......@@ -190,8 +195,14 @@ class LoginHandlers:
user_id_token = reset_data.user_id
user_id = user_id_token.encode('utf-8')
# Verify and decode the JWT token
try:
try:
decoded_token = jwt.decode(user_id)
except DecodeError:
return JSONResponse(
content=DefaultFailureResponse(status="failed",
message=ErrorMessages.ERROR_INVALID_TOKEN).dict(),
status_code=status.HTTP_200_OK)
db_user_data = obj_mongo_user.fetch_one_user_details({"email": decoded_token['email']})
# if the user is not available
if not db_user_data:
......
......@@ -40,7 +40,7 @@ class NormalLogin:
self.db_user_data = MongoUser().fetch_one_user_details({"email": email})
# if the user is not available
if not self.db_user_data:
return False, ErrorMessages.ERROR_UNAUTHORIZED_USER_LOGIN
return False, ErrorMessages.ERROR_ACCOUNT_DOESNT_EXIST
# if the user is not registered through normal login
if self.db_user_data["login_type"] != login_type:
return False, ErrorMessages.ERROR_ACCESS_DENIED
......
import datetime
import uuid
from passlib.context import CryptContext
from scripts.database.mongo.mongo_db import MongoUser
from scripts.database.redis.redis_conn import login_db
from scripts.errors import ErrorMessages
......@@ -22,9 +24,11 @@ obj_stage = MongoStageCreator()
class UserManagement:
def __init__(self):
self.method = "register"
self.pass_decrypt = EncryptDecryptPassword()
self.pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
# for normal registration using email and password
def normal_register(self, user_data):
def general_register(self, user_data):
try:
response, message = UserDataValidations.register_data_validation(user_data, 'general', self.method)
if not response:
......@@ -33,7 +37,7 @@ class UserManagement:
message=message["message"]).dict(),
status_code=status.HTTP_200_OK)
# fetching the data based on the username
db_user_data = obj_mongo_user.fetch_one_user_details(user_data.email)
db_user_data = obj_mongo_user.fetch_one_user_details({"email": user_data.email})
# if the user is not available
if db_user_data:
return JSONResponse(
......@@ -46,8 +50,14 @@ class UserManagement:
created_at = datetime.datetime.now()
updated_at = datetime.datetime.now()
reg_time = {"created_at": created_at, "updated_at": updated_at}
encrypted = EncryptDecryptPassword().password_encrypt(user_data.password)
if encrypted is None:
return JSONResponse(
content=DefaultFailureResponse(status="failed",
message=ErrorMessages.ERROR_INVALID_PASSWORD).dict(),
status_code=status.HTTP_200_OK)
# storing the user data in dict, encrypting the password
user_data_dict = {key: (EncryptDecryptPassword().password_encrypt(value)
user_data_dict = {key: (encrypted
if key == "password" else value) for key, value in user_data if key != 'action'}
# adding the registration time to the user data
user_data_reg = user_data_dict | reg_time
......@@ -127,8 +137,14 @@ class UserManagement:
status_code=status.HTTP_404_NOT_FOUND)
# creating the filter data
filter_data_updated = {"user_id": update_data.user_id}
encrypted = EncryptDecryptPassword().password_encrypt(update_data.password)
if encrypted is None:
return JSONResponse(
content=DefaultFailureResponse(status="failed",
message=ErrorMessages.ERROR_INVALID_PASSWORD).dict(),
status_code=status.HTTP_200_OK)
# encrypting the password
update_data_removed = {key: (EncryptDecryptPassword().password_encrypt(value)
update_data_removed = {key: (encrypted
if key == "password" else value) for key, value in update_data if
key != 'action' and value is not None}
# validating the data
......@@ -222,8 +238,7 @@ class UserManagement:
logger.exception(e)
# user change password
@staticmethod
def reset_password(reset_data):
def reset_password(self, reset_data):
db_user_data = obj_mongo_user.fetch_one_user_details({"user_id": reset_data.user_id})
# if the user is not available
if db_user_data is None:
......@@ -231,7 +246,19 @@ class UserManagement:
content=DefaultFailureResponse(status="failed",
message=ErrorMessages.ERROR_USER_ID_DOESNT_EXIST).dict(),
status_code=status.HTTP_404_NOT_FOUND)
response = EncryptDecryptPassword().password_encrypt(reset_data.password)
try:
decrypted_password = self.pass_decrypt.password_decrypt(reset_data.new_password)
except TypeError:
return JSONResponse(
content=DefaultFailureResponse(status="failed",
message=ErrorMessages.ERROR_INVALID_PASSWORD).dict(),
status_code=status.HTTP_200_OK)
if not self.pwd_context.verify(decrypted_password.split("\"")[1], db_user_data["password"]):
return JSONResponse(
content=DefaultFailureResponse(status="failed",
message=ErrorMessages.ERROR_PASSWORD_MISMATCH).dict(),
status_code=status.HTTP_200_OK)
response = EncryptDecryptPassword().password_encrypt(reset_data.new_password)
if not response:
return JSONResponse(
content=DefaultFailureResponse(status="failed",
......@@ -244,10 +271,9 @@ class UserManagement:
message=ErrorMessages.ERROR_IN_UPDATING).dict(),
status_code=status.HTTP_200_OK)
return JSONResponse(
content=DefaultSuccessResponse(status="success", message="Updated Successfully").dict(),
content=DefaultSuccessResponse(status="success", message="Password Changed Successfully").dict(),
status_code=status.HTTP_200_OK)
# user logout
@staticmethod
def logout_user(user_id, request):
......
......@@ -4,6 +4,7 @@ class ErrorMessages:
# Authorization Errors
ERROR_AUTH_FAILED = "Authentication Failed. Please verify token"
ERROR_INVALID_LOGIN = "Your are not authorized to view this website."
ERROR_ACCOUNT_DOESNT_EXIST = "Account Does Not Exist"
ERROR_UNAUTHORIZED_USER_LOGIN = "Account is not available"
ERROR_UNAUTHORIZED_ACCESS = "Your are not authorized to view this page"
ERROR_ACCESS_DENIED = "Access Denied!"
......@@ -26,3 +27,4 @@ class ErrorMessages:
ERROR_INVALID_USER_ROLE = "Invalid User Role"
ERROR_USER_ID_DOESNT_EXIST = "User Id doesn't exist"
ERROR_USER_ID = "User Id Not Required"
ERROR_INVALID_TOKEN = "Invalid Token"
This source diff could not be displayed because it is too large. You can view the blob instead.
import logging
import os
from logging.handlers import RotatingFileHandler
import pathlib
from logging import StreamHandler
from logging.handlers import RotatingFileHandler, SocketHandler
from scripts.config import Services, PathConf
def get_logger():
def read_configuration():
return {
"name": Services.PROJECT_NAME,
"handlers": [
{"type": "RotatingFileHandler", "max_bytes": Services.MAX_BYTES, "back_up_count": Services.BACKUP_COUNT},
{"type": "StreamHandler", "name": Services.PROJECT_NAME},
],
}
def init_logger():
logging_config = read_configuration()
"""
Creates a rotating log
"""
__logger__ = logging.getLogger('')
# setting the logger level
__logger__ = logging.getLogger(Services.PROJECT_NAME)
__logger__.setLevel(Services.LOG_LEVEL)
# creating the format for the log
log_formatter = "%(asctime)s - %(levelname)-6s - [%(threadName)5s:%(funcName)5s(): %(lineno)s] - %(message)s"
time_format = "%Y-%m-%d %H:%M:%S"
# getting the path for the logger
file_path = PathConf.LOG_PATH
# setting the format
formatter = logging.Formatter(log_formatter, time_format)
# creating the folder if not exist
if not os.path.exists(file_path):
os.makedirs(file_path)
# joining the path
log_file = os.path.join(f"{file_path}/{Services.PROJECT_NAME}log.log")
# creating rotating file handler with max byte as 1
temp_handler = RotatingFileHandler(log_file, maxBytes=1)
# setting the formatter
for each_handler in logging_config["handlers"]:
if (
each_handler["type"] in ["RotatingFileHandler"]
and Services.ENABLE_FILE_LOGGING
):
pathlib.Path(PathConf.LOG_PATH).mkdir(parents=True, exist_ok=True)
log_file = pathlib.Path(PathConf.LOG_PATH, f"{Services.PROJECT_NAME}.log")
temp_handler = RotatingFileHandler(
log_file,
maxBytes=each_handler["max_bytes"],
backupCount=each_handler["back_up_count"],
)
temp_handler.setFormatter(formatter)
elif each_handler["type"] in ["SocketHandler"]:
temp_handler = SocketHandler(each_handler["host"], each_handler["port"])
elif each_handler["type"] in ["StreamHandler"]:
temp_handler = StreamHandler()
temp_handler.setFormatter(formatter)
# setting the handler
else:
temp_handler = None
__logger__.addHandler(temp_handler)
return __logger__
logger = get_logger()
logger = init_logger()
......@@ -39,7 +39,8 @@ class UsersFilter(BaseModel):
class ResetPassword(BaseModel):
user_id: str
password: str
old_password: Optional[str] = None
new_password: str
class UserIDValidation(BaseModel):
......
......@@ -22,14 +22,14 @@ obj_dashboard_handler = DashboardManagement()
# login API
@router.post(ApiEndPoints.asset_manager_submit)
async def login_default(
async def login_default_api(
user_data: LoginRequest,
request: Request,
):
try:
# mapper for login types
login_mapper = {
"general_login": obj_login_handler.normal_login,
"general_login": obj_login_handler.general_login,
"google": obj_login_handler.google_login,
"microsoft": obj_login_handler.microsoft_login
}
......@@ -103,7 +103,7 @@ async def reset_password(
# User Management API
@router.post(ApiEndPoints.asset_manager_user_table_actions)
async def user_register(
async def user_management(
user_data: UserActions,
request: MetaInfoSchema = Depends(auth)
):
......@@ -116,7 +116,7 @@ async def user_register(
status_code=status.HTTP_200_OK)
# mapper for registration types
register_mapper = {
"general_login": obj_user_handler.normal_register,
"general_login": obj_user_handler.general_register,
"google": obj_user_handler.google_register,
"microsoft": obj_user_handler.microsoft_register
}
......@@ -144,7 +144,7 @@ async def user_register(
# View users API Header
@router.post(ApiEndPoints.asset_manager_user_header)
async def user_register(
async def user_view_header(
request: MetaInfoSchema = Depends(auth)
):
try:
......@@ -172,7 +172,7 @@ async def user_register(
# View users API
@router.post(ApiEndPoints.asset_manager_user_view)
async def user_register_view(
async def user_view_data(
request: MetaInfoSchema = Depends(auth)
):
try:
......@@ -197,15 +197,15 @@ async def user_register_view(
status_code=status.HTTP_200_OK)
# API for reset password
# API for change password
@router.post(ApiEndPoints.asset_manager_user_reset)
async def user_reset_password(
async def user_change_password(
reset_data: ResetPassword,
request: MetaInfoSchema = Depends(auth)
):
try:
# authorize the user
response = AuthorizeAccess().login_authorize(reset_data, request)
response = AuthorizeAccess().login_authorize(request, reset_data)
if not response:
return JSONResponse(
content=DefaultFailureResponse(status="failed",
......@@ -218,7 +218,7 @@ async def user_reset_password(
detail=ErrorMessages.ERROR_IN_FETCHING)
return response
except Exception as e:
logger.exception(e)
logger.exception(f"From user change password - {e}")
return JSONResponse(
content=DefaultFailureResponse(status="failed",
message=ErrorMessages.OP_FAILED).dict(),
......@@ -227,10 +227,16 @@ async def user_reset_password(
# download Button Dashboard
@router.post(ApiEndPoints.asset_manager_dashboard_download)
async def dashboard_download(
async def dashboard_download_files(
request: MetaInfoSchema = Depends(auth)
):
try:
response = AuthorizeAccess().login_authorize(request, None)
if not response:
return JSONResponse(
content=DefaultFailureResponse(status="failed",
message=ErrorMessages.ERROR_UNAUTHORIZED_ACCESS).dict(),
status_code=status.HTTP_200_OK)
# getting the data for the download dashboard
response = obj_dashboard_handler.download_header()
if not response:
......
from typing import Optional
from scripts.database.mongo.mongo_db import MongoUser
from scripts.schemas.project_schema import ResetPassword
obj_mongo_user = MongoUser()
......@@ -17,7 +20,11 @@ class AuthorizeAccess:
return False
@staticmethod
def login_authorize(reset_data, request):
def login_authorize(request, reset_data: Optional[ResetPassword] = None):
if reset_data is not None:
if reset_data.user_id != request.user_id:
return False
return True
if request.user_id:
return True
return False
......@@ -43,5 +43,7 @@ class EncryptDecryptPassword:
# decrypting the UI password
decrypted_password = self.password_decrypt(password)
# hashing the decrypted password
if decrypted_password is None:
return None
hashed_password = self.pwd_context.hash(decrypted_password.split("\"")[1])
return hashed_password
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