Commit 24d0cc0c authored by arun.uday's avatar arun.uday

Merge branch '1-arun-uday-asset-manager-v1-0' into 'master'

1 arun uday asset manager v1 0

See merge request !4
parents a8343237 a0a786d6
...@@ -4,12 +4,25 @@ DB_NAME=userDB ...@@ -4,12 +4,25 @@ DB_NAME=userDB
REDIS_URI=redis://127.0.0.1:6379 REDIS_URI=redis://127.0.0.1:6379
REDIS_LOGIN_DB=10 REDIS_LOGIN_DB=10
SERVICE_HOST=127.0.0.1 SERVICE_HOST=0.0.0.0
SERVICE_PORT=8671 SERVICE_PORT=8671
PROJECT_NAME=AssetManager PROJECT_NAME=AssetManager
BASE_PATH=scripts/ ENCODING_TYPE=utf-8
SUB_PATH=log/ KEY_ENCRYPTION=kliLensKLiLensKL
SECRET_KEY=09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7
ENCODING_TYPE=utf-8 EMAIL_SENDER=arun.send.email@gmail.com
\ No newline at end of file EMAIL_SMTP=smtp.gmail.com
EMAIL_PORT=465
EMAIL_PASSWORD=gpphuiweedqukchf
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__": ...@@ -38,5 +38,5 @@ if __name__ == "__main__":
# starting the app # starting the app
uvicorn.run("main:app", host=arguments["bind"], port=int(arguments["port"])) uvicorn.run("main:app", host=arguments["bind"], port=int(arguments["port"]))
except Exception as e: 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
uvicorn==0.21.1 uvicorn==0.21.1
python-dotenv~=1.0.0 python-dotenv~=1.0.0
pydantic~=1.10.6 pydantic==1.10.7
fastapi==0.95.0 fastapi==0.95.0
passlib~=1.7.4 passlib~=1.7.4
pymongo~=4.3.3 pymongo~=4.3.3
...@@ -9,4 +9,7 @@ email-validator~=1.3.1 ...@@ -9,4 +9,7 @@ email-validator~=1.3.1
pycryptodomex~=3.17 pycryptodomex~=3.17
PyJWT~=2.6.0 PyJWT~=2.6.0
validate_email~=1.3 validate_email~=1.3
redis~=4.5.2 redis==4.5.4
\ No newline at end of file google~=3.0.0
google-auth~=2.17.1
requests~=2.28.2
\ No newline at end of file
...@@ -14,8 +14,17 @@ class _Services(BaseSettings): ...@@ -14,8 +14,17 @@ class _Services(BaseSettings):
CORS_ALLOW_CREDENTIALS: bool = True CORS_ALLOW_CREDENTIALS: bool = True
CORS_ALLOW_METHODS: list[str] = ["GET", "POST", "DELETE", "PUT"] CORS_ALLOW_METHODS: list[str] = ["GET", "POST", "DELETE", "PUT"]
CORS_ALLOW_HEADERS: list[str] = ["*"] CORS_ALLOW_HEADERS: list[str] = ["*"]
LOG_LEVEL: Literal["INFO", "DEBUG", "ERROR", "QTRACE"] = "INFO" LOG_LEVEL: str
ENABLE_FILE_LOGGING: bool = False BACKUP_COUNT: int
MAX_BYTES: int
ENABLE_FILE_LOGGING: bool = True
EMAIL_SENDER: str
EMAIL_SMTP: str
EMAIL_PORT: int
EMAIL_PASSWORD: str
HTML_LINK: str
RESET_ENDPOINT: str
DATE_TIME = '%Y-%m-%d %H:%M:%S'
class _Databases(BaseSettings): class _Databases(BaseSettings):
...@@ -25,21 +34,18 @@ class _Databases(BaseSettings): ...@@ -25,21 +34,18 @@ class _Databases(BaseSettings):
REDIS_LOGIN_DB: int REDIS_LOGIN_DB: int
class _BasePathConf(BaseSettings): class _PathConf(BaseSettings):
BASE_PATH: str = "scripts/" LOG_PATH: str
class _PathConf:
BASE_PATH: pathlib.Path = pathlib.Path(_BasePathConf().BASE_PATH)
LOG_PATH: pathlib.Path = BASE_PATH / "log/"
class _Secrets(BaseSettings): class _Secrets(BaseSettings):
ACCESS_TOKEN_EXPIRE_MINUTES = 30 ACCESS_TOKEN_EXPIRE_MINUTES = 480
TOKEN_EXPIRE_TIME = 5
leeway_in_minutes: int = 10 leeway_in_minutes: int = 10
KEY_ENCRYPTION = "kliLensKLiLensKL" KEY_ENCRYPTION: str
CLIENT_ID: str
issuer: str = "iotManager" issuer: str = "iotManager"
SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7" SECRET_KEY: str
ALGORITHM = "HS256" ALGORITHM = "HS256"
......
class ApiEndPoints: class ApiEndPoints:
# Main root
root = "/asset_manager_api"
# version # version
version = "/v1" version = "/v1"
# common # common
submit: str = "/submit" submit: str = "/submit"
add: str = "/add" add: str = "/adduser"
view: str = "/view" view: str = "/table_body"
table_actions: str = "/table_actions"
update: str = "/update" update: str = "/update"
delete: str = "/delete" delete: str = "/delete"
header: str = "/table_header"
download: str = "/download"
search: str = "/search"
forgot: str = "/forgot"
reset: str = "/reset"
logout: str = "/logout"
# login-management # login-management
asset_manager_login: str = "/login" asset_manager_login: str = "/login"
asset_manager_submit: str = asset_manager_login + submit asset_manager_submit: str = asset_manager_login + submit
asset_manager_forgot: str = asset_manager_login + forgot
asset_manager_reset: str = asset_manager_login + reset
# user-management # user-management
asset_manager_user_management: str = "/users" asset_manager_user_management: str = "/users"
asset_manager_user_add: str = asset_manager_user_management + add asset_manager_user_add: str = asset_manager_user_management + add
asset_manager_user_view: str = asset_manager_user_management + view asset_manager_user_view: str = asset_manager_user_management + view
asset_manager_user_header: str = asset_manager_user_management + header
asset_manager_user_table_actions: str = asset_manager_user_management + table_actions
asset_manager_user_update: str = asset_manager_user_management + update asset_manager_user_update: str = asset_manager_user_management + update
asset_manager_user_delete: str = asset_manager_user_management + delete asset_manager_user_delete: str = asset_manager_user_management + delete
asset_manager_user_search: str = asset_manager_user_management + search
asset_manager_user_logout: str = asset_manager_user_management + logout
asset_manager_user_reset: str = asset_manager_user_management + reset
# dashboard-management
asset_manager_dashboard: str = "/dashboard"
asset_manager_dashboard_download_header: str = asset_manager_dashboard + download + header
asset_manager_dashboard_download: str = asset_manager_dashboard + download
class Validations:
email = "user@example.com"
from fastapi.responses import JSONResponse
from fastapi import status
from scripts.logging.logger import logger
from scripts.schemas.default_responses import DefaultResponse
from scripts.utils.response_utils import ResponseData
obj_download_util = ResponseData()
# download header and row data
class DashboardManagement:
def __init__(self):
self.download_files = obj_download_util.download_file_data()
def download_header(self):
try:
# header contents
data = {
"actions": [
{
"class": "fa-download",
"action": "download",
"tooltip": "Download"
}
],
"columnDefs": [
{
"headerName": "File Name",
"field": "file_name",
"key": "file_name",
"flex": 0,
"width": 1010
}],
}
# column urls
column_urls = [{"file_name": key, "file_url": value} for key, value in self.download_files.items()]
data["rowData"] = column_urls
return JSONResponse(
content=DefaultResponse(status="success", message="Fetched Successfully",
data=data).dict(),
status_code=status.HTTP_200_OK)
except Exception as e:
logger.exception(e)
This diff is collapsed.
...@@ -19,37 +19,45 @@ class NormalLogin: ...@@ -19,37 +19,45 @@ class NormalLogin:
self.dt = datetime.now() self.dt = datetime.now()
self.time_dt = datetime.now() self.time_dt = datetime.now()
# user data validation
@staticmethod @staticmethod
def user_data_validation(email, password) -> dict | None: def user_data_validation(email, password) -> dict | None:
try: try:
# checking for valid username # checking for valid username
if email == "" or validate_email(email) is not True: if email == "" or validate_email(email) is not True:
return {"message": ErrorMessages.ERROR_INVALID_EMAIL, "data": email} return ErrorMessages.ERROR_INVALID_EMAIL
# checking for valid password # checking for valid password
if password == "": if password == "":
return {"message": ErrorMessages.ERROR_INVALID_PASSWORD, "data": password} return ErrorMessages.ERROR_INVALID_PASSWORD
return None return None
except Exception as e: except Exception as e:
logger.exception(e) logger.exception(e)
# db validation
def db_data_validation(self, login_type, email): def db_data_validation(self, login_type, email):
try: try:
# fetching the data based on the username # fetching the data based on the username
self.db_user_data = MongoUser().fetch_one_user_details(email) self.db_user_data = MongoUser().fetch_one_user_details({"email": email})
# 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_UNAUTHORIZED_USER_LOGIN, return False, ErrorMessages.ERROR_ACCOUNT_DOESNT_EXIST
"data": {"username": email}}
# if the user is not registered through normal login # if the user is not registered through normal login
if self.db_user_data["login_type"] != login_type: if self.db_user_data["login_type"] != login_type:
return False, {"message": ErrorMessages.ERROR_LOGIN_TYPE_INVALID, return False, ErrorMessages.ERROR_ACCESS_DENIED
"data": {"username": email, "Use Login": self.db_user_data["login_type"]}} try:
response = {"user_id": self.db_user_data["user_id"], "name": self.db_user_data["name"],
"email": email,
"user_role": self.db_user_data["user_role"]}
except KeyError:
response = {"user_id": self.db_user_data["user_id"],
"email": email,
"user_role": self.db_user_data["user_role"]}
# if the user exist # if the user exist
return None, {"message": True} return None, response
except Exception as e: except Exception as e:
logger.exception(e) logger.exception(e)
# matching the password
def db_password_matching(self, login_type, user_data, password): def db_password_matching(self, login_type, user_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
...@@ -59,24 +67,31 @@ class NormalLogin: ...@@ -59,24 +67,31 @@ class NormalLogin:
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, return False, ErrorMessages.ERROR_PASSWORD_MISMATCH
"data": {"username": user_data.email}}
# if the password is correct # if the password is correct
return None, {"username": user_data.email, "role": self.db_user_data["user_role"]} return None, message
except Exception as e: except Exception as e:
logger.exception(e) logger.exception(e)
@staticmethod
def update_pic(obj_mongo_user, info_data):
if not obj_mongo_user.update_user({"email": info_data["email"]},
{"name": info_data["name"], "pic_url": info_data["picture"]}):
return None
return True
# cookie and token creation
@staticmethod @staticmethod
def generate_cookie_tokens(user_data, request): def generate_cookie_tokens(user_data, request):
try: try:
# creating the access token # creating the access token
access_token = create_token( access_token, exp = create_token(
user_id=user_data.email, user_id=user_data["user_id"],
ip=request.ip_address ip=request.client.host
) )
# returning the login token # returning the login token
if access_token: if access_token:
return {"user_id": access_token, "token_type": "bearer"} return access_token, exp
else: else:
return None return None
except Exception as e: except Exception as e:
......
...@@ -6,6 +6,7 @@ collection_name = DatabaseConstants.collection_user_details ...@@ -6,6 +6,7 @@ collection_name = DatabaseConstants.collection_user_details
class UserDetailsKeys: class UserDetailsKeys:
KEY_USER_ID = "user_id"
KEY_NAME = "name" KEY_NAME = "name"
KEY_EMAIL = "email" KEY_EMAIL = "email"
KEY_PASSWORD = "password" KEY_PASSWORD = "password"
...@@ -17,6 +18,7 @@ class UserDetailsKeys: ...@@ -17,6 +18,7 @@ class UserDetailsKeys:
class MongoUser(CollectionBaseClass): class MongoUser(CollectionBaseClass):
key_name = UserDetailsKeys.KEY_NAME key_name = UserDetailsKeys.KEY_NAME
key_user_id = UserDetailsKeys.KEY_USER_ID
key_email = UserDetailsKeys.KEY_EMAIL key_email = UserDetailsKeys.KEY_EMAIL
key_password = UserDetailsKeys.KEY_PASSWORD key_password = UserDetailsKeys.KEY_PASSWORD
key_user_role = UserDetailsKeys.KEY_USER_ROLE key_user_role = UserDetailsKeys.KEY_USER_ROLE
...@@ -28,28 +30,37 @@ class MongoUser(CollectionBaseClass): ...@@ -28,28 +30,37 @@ class MongoUser(CollectionBaseClass):
super().__init__(mongo_client, Databases.DB_NAME, collection_name) super().__init__(mongo_client, Databases.DB_NAME, collection_name)
# fetching the user details based on the email id # fetching the user details based on the email id
def fetch_one_user_details(self, email): def fetch_one_user_details(self, query):
if user := self.find_one(query={self.key_email: email}): if user := self.find_one(query=query):
return user return user
return None return None
def fetch_all_user_details(self): # fetching the user data
if user := self.find(query={}, filter_dict={'_id': 0, def fetch_all_user_details(self, query, filter_data):
"login_type": 0, if user := self.find(query=query, filter_dict=filter_data):
"is_alive": 0,
"password": 0,
"created_at": 0,
"updated_at": 0}):
return user return user
return None return None
# inserting the user
def insert_new_user(self, data): def insert_new_user(self, data):
if user := self.insert_one(data=data): if user := self.insert_one(data=data):
return user return user
return None return None
# updating the login time # updating the login time
def update_user(self, update, query): def update_user(self, query, update):
if user := self.update_one(query=update, data=query): if user := self.update_one(query=query, data=update):
return user
return None
# deleting users
def delete_user(self, query):
if user := self.delete_one(query=query):
return user
return None
# for filtering
def filter_data_aggregate(self, pipeline):
if user := self.aggregate(pipelines=pipeline):
return user return user
return None return None
...@@ -4,14 +4,20 @@ class ErrorMessages: ...@@ -4,14 +4,20 @@ class ErrorMessages:
# Authorization Errors # Authorization Errors
ERROR_AUTH_FAILED = "Authentication Failed. Please verify token" ERROR_AUTH_FAILED = "Authentication Failed. Please verify token"
ERROR_INVALID_LOGIN = "Your are not authorized to view this website." 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_USER_LOGIN = "Account is not available"
ERROR_UNAUTHORIZED_ACCESS = "Your are not authorized to view this page" ERROR_UNAUTHORIZED_ACCESS = "Your are not authorized to view this page"
ERROR_LOGIN_TYPE_INVALID = "Invalid Login Method" ERROR_ACCESS_DENIED = "Access Denied!"
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 = "Please enter the correct password"
ERROR_TOKEN_GENERATION = "Unsuccessful token generation" ERROR_TOKEN_GENERATION = "Unsuccessful token generation"
ERROR_STORING_DATA = "New user registration failed" ERROR_STORING_DATA = "New user registration failed"
ERROR_EMAIL_EXIST = "Email Id exists" ERROR_EMAIL_EXIST = "Email Id exists"
ERROR_IN_FETCHING = "Details cannot be fetched"
ERROR_IN_UPDATING = "Error in Updating"
ERROR_INVALID_REQUEST = "Invalid Request"
ERROR_USER_SESSION = "Not The Users Session"
ERROR_TOKEN_EXPIRED = "Google Token Expired"
# Data Validation # Data Validation
ERROR_INVALID_PASSWORD = "Invalid Password" ERROR_INVALID_PASSWORD = "Invalid Password"
...@@ -19,3 +25,6 @@ class ErrorMessages: ...@@ -19,3 +25,6 @@ class ErrorMessages:
ERROR_INVALID_EMAIL = "Invalid Email Id" ERROR_INVALID_EMAIL = "Invalid Email Id"
ERROR_INVALID_PHONE_NUMBER = "Invalid Phone Number" ERROR_INVALID_PHONE_NUMBER = "Invalid Phone Number"
ERROR_INVALID_USER_ROLE = "Invalid User Role" 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 logging
import os import pathlib
from logging.handlers import RotatingFileHandler from logging import StreamHandler
from logging.handlers import RotatingFileHandler, SocketHandler
from scripts.config import Services, PathConf from scripts.config import Services, PathConf
def get_logger(): def read_configuration():
""" return {
Creates a rotating log "name": Services.PROJECT_NAME,
""" "handlers": [
__logger__ = logging.getLogger('') {"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()
# setting the logger level """
Creates a rotating log
"""
__logger__ = logging.getLogger(Services.PROJECT_NAME)
__logger__.setLevel(Services.LOG_LEVEL) __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" log_formatter = "%(asctime)s - %(levelname)-6s - [%(threadName)5s:%(funcName)5s(): %(lineno)s] - %(message)s"
time_format = "%Y-%m-%d %H:%M:%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) formatter = logging.Formatter(log_formatter, time_format)
for each_handler in logging_config["handlers"]:
# creating the folder if not exist if (
if not os.path.exists(file_path): each_handler["type"] in ["RotatingFileHandler"]
os.makedirs(file_path) and Services.ENABLE_FILE_LOGGING
):
# joining the path pathlib.Path(PathConf.LOG_PATH).mkdir(parents=True, exist_ok=True)
log_file = os.path.join(f"{file_path}/{Services.PROJECT_NAME}log.log") log_file = pathlib.Path(PathConf.LOG_PATH, f"{Services.PROJECT_NAME}.log")
temp_handler = RotatingFileHandler(
# creating rotating file handler with max byte as 1 log_file,
temp_handler = RotatingFileHandler(log_file, maxBytes=1) maxBytes=each_handler["max_bytes"],
backupCount=each_handler["back_up_count"],
# setting the formatter )
temp_handler.setFormatter(formatter) temp_handler.setFormatter(formatter)
elif each_handler["type"] in ["SocketHandler"]:
# setting the handler temp_handler = SocketHandler(each_handler["host"], each_handler["port"])
__logger__.addHandler(temp_handler) elif each_handler["type"] in ["StreamHandler"]:
temp_handler = StreamHandler()
temp_handler.setFormatter(formatter)
else:
temp_handler = None
__logger__.addHandler(temp_handler)
return __logger__ return __logger__
logger = get_logger() logger = init_logger()
...@@ -5,12 +5,17 @@ from pydantic import BaseModel ...@@ -5,12 +5,17 @@ from pydantic import BaseModel
# default responses # default responses
class DefaultResponse(BaseModel): class DefaultResponse(BaseModel):
status: bool = True status: str
message: Optional[str] message: str
data: Optional[Any] data: Optional[Any]
class DefaultSuccessResponse(BaseModel):
status: str
message: str
# default failure responses # default failure responses
class DefaultFailureResponse(DefaultResponse): class DefaultFailureResponse(BaseModel):
status: bool = False status: str
error: Any message: Any
...@@ -5,8 +5,10 @@ from pydantic import BaseModel ...@@ -5,8 +5,10 @@ from pydantic import BaseModel
# model for login request # model for login request
class LoginRequest(BaseModel): class LoginRequest(BaseModel):
email: str login_type: str
password: str email: Optional[str] = None
password: Optional[str] = None
id_token: Optional[str] = None
class RegistrationData(BaseModel): class RegistrationData(BaseModel):
...@@ -16,3 +18,34 @@ class RegistrationData(BaseModel): ...@@ -16,3 +18,34 @@ class RegistrationData(BaseModel):
phone_number: Optional[str] phone_number: Optional[str]
login_type: str login_type: str
user_role: str user_role: str
class UserActions(BaseModel):
action: str
user_id: Optional[str] = None
name: Optional[str] = None
email: Optional[str] = None
password: Optional[str]
phone_number: Optional[str] = None
login_type: Optional[str] = None
user_role: Optional[str] = None
class UsersFilter(BaseModel):
name: Optional[str] = None
email: Optional[str] = None
user_role: Optional[str] = None
class ResetPassword(BaseModel):
user_id: str
old_password: Optional[str] = None
new_password: str
class UserIDValidation(BaseModel):
user_id: str
class EmailValidation(BaseModel):
email: str
from fastapi import APIRouter from fastapi import APIRouter
from scripts.constants.api import ApiEndPoints
from scripts.services import v1 from scripts.services import v1
router = APIRouter() router = APIRouter(prefix=ApiEndPoints.root)
# routing to the V1 router # routing to the V1 router
router.include_router(v1.router) router.include_router(v1.router)
...@@ -3,6 +3,6 @@ from scripts.constants.api import ApiEndPoints ...@@ -3,6 +3,6 @@ from scripts.constants.api import ApiEndPoints
from scripts.services.v1 import iot_manager_services from scripts.services.v1 import iot_manager_services
# creating the api router with version as the prefix # creating the api router with version as the prefix
router = APIRouter() router = APIRouter(prefix=ApiEndPoints.version)
# routing to the service api # routing to the service api
router.include_router(iot_manager_services.router) router.include_router(iot_manager_services.router)
This diff is collapsed.
This diff is collapsed.
...@@ -57,3 +57,6 @@ class MongoStageCreator: ...@@ -57,3 +57,6 @@ class MongoStageCreator:
def sort_stage(self, stage: dict) -> dict: def sort_stage(self, stage: dict) -> dict:
return self.add_stage("$sort", stage) return self.add_stage("$sort", stage)
def regex_stage(self, stage: dict) -> dict:
return self.add_stage("$regex", stage)
...@@ -3,15 +3,8 @@ import re ...@@ -3,15 +3,8 @@ import re
from scripts.logging.logger import logger from scripts.logging.logger import logger
# for data validations
class RegexValidation: class RegexValidation:
@staticmethod
def first_name_validation(first_name):
try:
regex = re.fullmatch('([A-Za-z ]{1,100})', str(first_name))
return regex
except Exception as e:
logger.error(f'An Error While listing the home plans {str(e)}')
@staticmethod @staticmethod
def name_validation(name): def name_validation(name):
try: try:
...@@ -29,10 +22,11 @@ class RegexValidation: ...@@ -29,10 +22,11 @@ class RegexValidation:
logger.error(f'An Error While listing the home plans {str(e)}') logger.error(f'An Error While listing the home plans {str(e)}')
@staticmethod @staticmethod
def email_validation(email): def password_validation(password):
try: try:
regex = r'\b[A-Za-z0-9._%+-]+@([A-Za-z0-9.-]{5,20})+\.[A-Z|a-z]{3}\b' password_regex = r'^(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%^&*()_+={}[\]:;\"\'|,.<>\/?]).{8,15}$'
if re.fullmatch(regex, email): if re.search(password_regex, password):
return regex return False
except Exception as e: except Exception as e:
logger.error(f'An Error While listing the home plans {str(e)}') logger.error(f'An Error While listing the home plans {str(e)}')
\ No newline at end of file
# response data utils
class ResponseData:
@staticmethod
def user_view_header():
header = {
"actions": [
{
"class": "fa-pencil",
"action": "edit",
"tooltip": "Edit"
},
{
"class": "fa-trash",
"action": "delete",
"tooltip": "Delete"
},
], "externalActions": [
{
"type": "button",
"action": "addnew",
"label": "Create User"
}
], "columnDefs": [
{
"headerName": "User Name",
"field": "email",
"key": "email"
},
{
"headerName": "Name",
"field": "name",
"key": "name"
},
{
"headerName": "Role",
"field": "user_role",
"key": "user_role",
"width": 150,
"flex": 0
}
],
}
return header
# download api util
@staticmethod
def download_file_data():
data = {
"SCN101-Manual (Local Config with IoTSetupUI)":
"https://ilens.io/DownloadFiles/SCN_Device_Configuration_Page_Updates_4_7.pdf",
"SCN101 Firmware 4.7 Updates":
"https://ilens.io/DownloadFiles/SCN101Manual.pdf",
"IoTSetupUI":
"https://ilens.io/DownloadFiles/IoTsetupUI-V1.6.zip",
"CP2102 SCN Windows USB Driver":
"https://ilens.io/DownloadFiles/CP2102_Windows.zip",
"SCNFirmwareBurner":
"https://ilens.io/DownloadFiles/flash_download_tool_v3.8.5.zip",
"SCN101A Firmware - V2.7 (Board: 1.4, 1.6 and 4MB Part.) ":
"https://ilens.io/DownloadFiles/SCN101_Firmware_V2_7_B1_6.bin",
"SCN101A Firmware - V2.8 (Board: 1.4, 1.6 and 4MB Part.) ":
"https://ilens.io/DownloadFiles/SCN101_Firmware_V2_8_B1_6.bin",
"SCN101A4G (SCN Relay, 4G, SCN201 and SCN101L) Firmware - V4.5 (16MB Part.) ":
"https://ilens.io/DownloadFiles/SCN101_R_A4G_SCN201_Firmware_V4_5.bin",
"SCN101A4G (SCN Relay, 4G, SCN201 and SCN101L) Firmware - V4.6 (16MB Part.) ":
"https://ilens.io/DownloadFiles/SCN101_R_A4G_SCN201_Firmware_V4_6.bin",
"SCN101A4G (SCN Relay, 4G, SCN201 and SCN101L) Firmware - V4.7 (16MB Part.) ":
"https://ilens.io/DownloadFiles/SCN101_R_A4G_SCN201_Firmware_V4_7.bin",
"P10_LED_Driver_V2.1 (Board 1.1)":
"https://ilens.io/DownloadFiles/P10_LED_Driver_V2.1.bin",
"SCN-LED Reset Firmware (Board 1.1)":
"https://ilens.io/DownloadFiles/SCN-LED_Reset.bin",
"SCN Reset Firmware (Partition: 4MB)":
"https://ilens.io/DownloadFiles/SCN_Reset_4MB_Part.bin",
"SCN Reset Firmware (Partition: 16MB)":
"https://ilens.io/DownloadFiles/SCN_Reset_16MB_Part.bin"
}
return data
from datetime import datetime, timedelta import uuid
from datetime import datetime, timedelta, timezone
from scripts.config import Secrets from scripts.config import Secrets
from scripts.database.mongo.mongo_db import MongoUser from scripts.database.mongo.mongo_db import MongoUser
...@@ -12,15 +13,19 @@ mongo_user = MongoUser() ...@@ -12,15 +13,19 @@ mongo_user = MongoUser()
def create_token( def create_token(
user_id, user_id,
ip, ip,
login_token=None,
age=Secrets.ACCESS_TOKEN_EXPIRE_MINUTES, age=Secrets.ACCESS_TOKEN_EXPIRE_MINUTES,
): ):
""" """
This method is to create a cookie This method is to create a cookie
""" """
uid = login_token
if not uid:
uid = str(uuid.uuid4()).replace("-", "")
# creating the payload # creating the payload
payload = {"ip": ip, "user_id": user_id, "token": Secrets.SECRET_KEY, "age": age} payload = {"ip": ip, "user_id": user_id, "token": Secrets.SECRET_KEY, "uid": uid, "age": age}
# getting the current time # getting the current time
current_time = datetime.now() current_time = datetime.now(timezone.utc)
# generating the expiry time of the token # generating the expiry time of the token
exp = current_time + timedelta(minutes=age) exp = current_time + timedelta(minutes=age)
# creating the dictionary with issuer and expiry time # creating the dictionary with issuer and expiry time
...@@ -28,12 +33,9 @@ def create_token( ...@@ -28,12 +33,9 @@ def create_token(
_payload = payload | _extras _payload = payload | _extras
# encoding the token # encoding the token
new_token = jwt.encode(_payload) new_token = jwt.encode(_payload)
# Add session to redis # Add session to redis
login_db.set(user_id, new_token) login_db.set(uid, new_token)
login_db.expire(user_id, timedelta(minutes=age)) login_db.expire(uid, timedelta(minutes=age))
# Add updated time to mongo db # Add updated time to mongo db
mongo_user.update_user({"email": user_id}, {"updated_at": current_time}) mongo_user.update_user({"user_id": user_id}, {"updated_at": current_time})
return uid, exp
return user_id
from typing import Optional
from scripts.database.mongo.mongo_db import MongoUser from scripts.database.mongo.mongo_db import MongoUser
from scripts.schemas.project_schema import ResetPassword
obj_mongo_user = MongoUser() obj_mongo_user = MongoUser()
class AuthorizeAccess: class AuthorizeAccess:
@staticmethod @staticmethod
# authorize the user
def admin_authorize(request): def admin_authorize(request):
user_data = obj_mongo_user.fetch_one_user_details(request.login_token) try:
if user_data["user_role"] != "super admin": # returning the user details
user_data = obj_mongo_user.fetch_one_user_details({"user_id": request.user_id})
if user_data["user_role"] != "super_admin":
return False
return True
except TypeError:
return False return False
return True
@staticmethod
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
...@@ -4,7 +4,6 @@ from fastapi.security import APIKeyCookie ...@@ -4,7 +4,6 @@ from fastapi.security import APIKeyCookie
from fastapi.security.api_key import APIKeyBase from fastapi.security.api_key import APIKeyBase
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
from scripts.config import Services
from scripts.database.redis.redis_conn import login_db from scripts.database.redis.redis_conn import login_db
from scripts.errors import ErrorMessages from scripts.errors import ErrorMessages
from scripts.logging.logger import logger from scripts.logging.logger import logger
...@@ -50,16 +49,8 @@ class _CookieAuthentication(APIKeyBase): ...@@ -50,16 +49,8 @@ class _CookieAuthentication(APIKeyBase):
login_token = cookies.get(self.cookie_name) or request.headers.get( login_token = cookies.get(self.cookie_name) or request.headers.get(
self.cookie_name self.cookie_name
) )
if not login_token or login_token != Services.PROJECT_NAME: if not login_token:
if not login_token: raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
# if the cookie name is same as the service name
if login_token == Services.PROJECT_NAME:
return MetaInfoSchema(
ip_address=request.client.host, # type: ignore
login_token=cookies.get("login-token"),
)
# getting the token stored in redis based on the cookie value
jwt_token = self.login_redis.get(login_token) jwt_token = self.login_redis.get(login_token)
if not jwt_token: if not jwt_token:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED) raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
...@@ -83,7 +74,6 @@ class _CookieAuthentication(APIKeyBase): ...@@ -83,7 +74,6 @@ class _CookieAuthentication(APIKeyBase):
status_code=status.HTTP_401_UNAUTHORIZED, status_code=status.HTTP_401_UNAUTHORIZED,
detail="Token doesn't have required fields", detail="Token doesn't have required fields",
) )
return MetaInfoSchema( return MetaInfoSchema(
user_id=user_id, user_id=user_id,
ip_address=request.client.host, # type: ignore ip_address=request.client.host, # type: ignore
......
...@@ -6,6 +6,7 @@ from scripts.config import Secrets, Services ...@@ -6,6 +6,7 @@ from scripts.config import Secrets, Services
from scripts.logging.logger import logger from scripts.logging.logger import logger
# utility for the password
class EncryptDecryptPassword: class EncryptDecryptPassword:
def __init__(self): def __init__(self):
self.pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") self.pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
...@@ -37,7 +38,12 @@ class EncryptDecryptPassword: ...@@ -37,7 +38,12 @@ class EncryptDecryptPassword:
except Exception as e: except Exception as e:
logger.exception(e) logger.exception(e)
# encrypting the password
def password_encrypt(self, password): def password_encrypt(self, password):
# decrypting the UI password
decrypted_password = self.password_decrypt(password) decrypted_password = self.password_decrypt(password)
hashed_password = self.pwd_context.hash(decrypted_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 return hashed_password
...@@ -6,9 +6,10 @@ from scripts.errors import ErrorMessages ...@@ -6,9 +6,10 @@ from scripts.errors import ErrorMessages
from scripts.logging.logger import logger from scripts.logging.logger import logger
# user data validations
class UserDataValidations: class UserDataValidations:
@staticmethod @staticmethod
def data_validation(user_data, method, feature): def register_data_validation(user_data, method, feature):
try: try:
if user_data.name == "": if user_data.name == "":
return False, {"message": ErrorMessages.ERROR_INVALID_NAME, return False, {"message": ErrorMessages.ERROR_INVALID_NAME,
...@@ -18,14 +19,27 @@ class UserDataValidations: ...@@ -18,14 +19,27 @@ class UserDataValidations:
user_data.email) is not True: user_data.email) is not True:
return False, {"message": ErrorMessages.ERROR_INVALID_EMAIL, "data": user_data.email} return False, {"message": ErrorMessages.ERROR_INVALID_EMAIL, "data": user_data.email}
# checking for valid password # checking for valid password
if method == 'normal': if method == 'general':
if user_data.password == "" or user_data.password == "string": if user_data.password == "" or user_data.password == "string":
return False, {"message": ErrorMessages.ERROR_INVALID_PASSWORD, "data": user_data.password} return False, {"message": ErrorMessages.ERROR_INVALID_PASSWORD, "data": user_data.password}
# Validate phone number # Validate phone number
if user_data.phone_number == "": if user_data.phone_number == "":
return False, {"message": ErrorMessages.ERROR_INVALID_PHONE_NUMBER, return False, {"message": ErrorMessages.ERROR_INVALID_PHONE_NUMBER,
"data": user_data.phone_number} "data": user_data.phone_number}
if user_data.user_role == "" and method == 'normal' and feature == 'register': if user_data.user_role == "" and method == 'general' and feature == 'register':
return False, {"message": ErrorMessages.ERROR_INVALID_USER_ROLE,
"data": user_data.phone_number}
return True, None
except Exception as e:
logger.exception(e)
@staticmethod
def update_data_validation(user_data):
try:
if user_data.name == "":
return False, {"message": ErrorMessages.ERROR_INVALID_NAME,
"data": user_data.phone_number}
if user_data.user_role == "":
return False, {"message": ErrorMessages.ERROR_INVALID_USER_ROLE, return False, {"message": ErrorMessages.ERROR_INVALID_USER_ROLE,
"data": user_data.phone_number} "data": user_data.phone_number}
return True, None return True, None
......
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