Web service initiated
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
from typing import Any, List, Dict, Optional, Union
|
||||
import arrow
|
||||
|
||||
from typing import Any, Dict, Optional, Union
|
||||
from ApiServices.AuthService.events.auth.model import PasswordHistoryViaUser
|
||||
from ApiServices.AuthService.validations.custom.token import (
|
||||
EmployeeTokenObject,
|
||||
OccupantTokenObject,
|
||||
@@ -6,7 +9,7 @@ from ApiServices.AuthService.validations.custom.token import (
|
||||
OccupantToken,
|
||||
UserType,
|
||||
)
|
||||
from ApiServices.TemplateService.config import api_config
|
||||
from ApiServices.AuthService.config import api_config
|
||||
from Schemas import (
|
||||
Users,
|
||||
People,
|
||||
@@ -25,12 +28,14 @@ from Schemas import (
|
||||
Event2Employee,
|
||||
)
|
||||
from Modules.Token.password_module import PasswordModule
|
||||
from Controllers.Redis.database import RedisActions
|
||||
from Schemas.building.build import RelationshipEmployee2Build
|
||||
from Schemas.event.event import Event2Occupant
|
||||
from Controllers.Redis.database import RedisActions
|
||||
from Controllers.Mongo.database import mongo_handler
|
||||
|
||||
TokenDictType = Union[EmployeeTokenObject, OccupantTokenObject]
|
||||
|
||||
|
||||
class RedisHandlers:
|
||||
AUTH_TOKEN: str = "AUTH_TOKEN"
|
||||
|
||||
@@ -63,7 +68,7 @@ class RedisHandlers:
|
||||
result_delete = RedisActions.delete(
|
||||
list_keys=[RedisHandlers.AUTH_TOKEN, "*", str(user.uu_id)]
|
||||
)
|
||||
print('result_delete', result_delete)
|
||||
print("result_delete", result_delete)
|
||||
generated_access_token = PasswordModule.generate_access_token()
|
||||
keys = [RedisHandlers.AUTH_TOKEN, generated_access_token, str(user.uu_id)]
|
||||
RedisActions.set_json(
|
||||
@@ -74,20 +79,27 @@ class RedisHandlers:
|
||||
return generated_access_token
|
||||
|
||||
@classmethod
|
||||
def update_token_at_redis(cls, token: str, add_payload: Union[CompanyToken, OccupantToken]):
|
||||
def update_token_at_redis(
|
||||
cls, token: str, add_payload: Union[CompanyToken, OccupantToken]
|
||||
):
|
||||
if already_token_data := RedisActions.get_json(
|
||||
list_keys=[RedisHandlers.AUTH_TOKEN, token, "*"]
|
||||
).first:
|
||||
already_token = cls.process_redis_object(**already_token_data)
|
||||
if already_token.is_employee:
|
||||
already_token = cls.process_redis_object(already_token_data)
|
||||
if already_token.is_employee and isinstance(add_payload, CompanyToken):
|
||||
already_token.selected_company = add_payload
|
||||
elif already_token.is_occupant:
|
||||
elif already_token.is_occupant and isinstance(add_payload, OccupantToken):
|
||||
already_token.selected_occupant = add_payload
|
||||
result = RedisActions.set_json(
|
||||
list_keys=[RedisHandlers.AUTH_TOKEN, token, str(already_token.user_uu_id)],
|
||||
list_keys=[
|
||||
RedisHandlers.AUTH_TOKEN,
|
||||
token,
|
||||
str(already_token.user_uu_id),
|
||||
],
|
||||
value=already_token.model_dump(),
|
||||
expires={"hours": 1, "minutes": 30},
|
||||
)
|
||||
print("result.first", result.first)
|
||||
return result.first
|
||||
raise ValueError("Something went wrong")
|
||||
|
||||
@@ -118,6 +130,14 @@ class UserHandlers:
|
||||
"""
|
||||
Check if the password is valid.
|
||||
"""
|
||||
print(
|
||||
dict(
|
||||
domain=domain,
|
||||
id_=id_,
|
||||
password=password,
|
||||
password_hashed=password_hashed,
|
||||
)
|
||||
)
|
||||
if PasswordModule.check_password(
|
||||
domain=domain, id_=id_, password=password, password_hashed=password_hashed
|
||||
):
|
||||
@@ -135,10 +155,9 @@ class LoginHandler:
|
||||
def is_employee(email: str):
|
||||
return str(email).split("@")[1] == api_config.ACCESS_EMAIL_EXT
|
||||
|
||||
|
||||
@classmethod
|
||||
def do_employee_login(
|
||||
cls, request: Any, data: Any, extra_dict: Optional[Dict[str, Any]] = None
|
||||
cls, request: Any, data: Any, extra_dict: Optional[Dict[str, Any]] = None
|
||||
):
|
||||
"""
|
||||
Handle employee login.
|
||||
@@ -154,10 +173,10 @@ class LoginHandler:
|
||||
)
|
||||
|
||||
if not user_handler.check_password_valid(
|
||||
domain=data.domain,
|
||||
domain=domain or "",
|
||||
id_=str(found_user.uu_id),
|
||||
password=data.password,
|
||||
password_hashed=found_user.hash_password
|
||||
password_hashed=found_user.hash_password,
|
||||
):
|
||||
raise ValueError("EYS_0005")
|
||||
|
||||
@@ -230,13 +249,27 @@ class LoginHandler:
|
||||
return {
|
||||
"access_token": access_token,
|
||||
"user_type": UserType.employee.name,
|
||||
"user": found_user.get_dict(
|
||||
exclude_list=[
|
||||
Users.hash_password,
|
||||
Users.cryp_uu_id,
|
||||
Users.password_token,
|
||||
Users.created_credentials_token,
|
||||
Users.updated_credentials_token,
|
||||
Users.confirmed_credentials_token,
|
||||
Users.is_confirmed,
|
||||
Users.is_notification_send,
|
||||
Users.is_email_send,
|
||||
Users.remember_me,
|
||||
]
|
||||
),
|
||||
"selection_list": companies_list,
|
||||
}
|
||||
raise ValueError("Something went wrong")
|
||||
|
||||
@classmethod
|
||||
def do_employee_occupant(
|
||||
cls, request: Any, data: Any, extra_dict: Optional[Dict[str, Any]] = None
|
||||
cls, request: Any, data: Any, extra_dict: Optional[Dict[str, Any]] = None
|
||||
):
|
||||
"""
|
||||
Handle occupant login.
|
||||
@@ -254,7 +287,7 @@ class LoginHandler:
|
||||
domain=data.domain,
|
||||
id_=str(found_user.uu_id),
|
||||
password=data.password,
|
||||
password_hashed=found_user.hash_password
|
||||
password_hashed=found_user.hash_password,
|
||||
):
|
||||
raise ValueError("EYS_0005")
|
||||
|
||||
@@ -300,7 +333,9 @@ class LoginHandler:
|
||||
"occupants": [occupant_data],
|
||||
}
|
||||
else:
|
||||
occupants_selection_dict[build_key]["occupants"].append(occupant_data)
|
||||
occupants_selection_dict[build_key]["occupants"].append(
|
||||
occupant_data
|
||||
)
|
||||
|
||||
person = found_user.person
|
||||
model_value = OccupantTokenObject(
|
||||
@@ -344,9 +379,9 @@ class LoginHandler:
|
||||
Returns:
|
||||
SuccessResponse containing authentication token and user info
|
||||
"""
|
||||
language = request.headers("language", "tr")
|
||||
domain = request.headers("domain", None)
|
||||
timezone = request.headers("tz", None) or "GMT+3"
|
||||
language = request.headers.get("language", "tr")
|
||||
domain = request.headers.get("domain", None)
|
||||
timezone = request.headers.get("tz", None) or "GMT+3"
|
||||
|
||||
if cls.is_employee(data.access_key):
|
||||
return cls.do_employee_login(
|
||||
@@ -386,7 +421,9 @@ class LoginHandler:
|
||||
return request.headers.get(api_config.ACCESS_TOKEN_TAG)
|
||||
|
||||
@classmethod
|
||||
def handle_employee_selection(cls, access_token: str, data: Any, token_dict: TokenDictType):
|
||||
def handle_employee_selection(
|
||||
cls, access_token: str, data: Any, token_dict: TokenDictType
|
||||
):
|
||||
with Users.new_session() as db:
|
||||
if data.company_uu_id not in token_dict.companies_uu_id_list:
|
||||
ValueError("EYS_0011")
|
||||
@@ -407,7 +444,9 @@ class LoginHandler:
|
||||
# Get staff IDs
|
||||
staff_ids = [
|
||||
staff.id
|
||||
for staff in Staff.filter_all(Staff.duties_id.in_(duties_ids), db=db).data
|
||||
for staff in Staff.filter_all(
|
||||
Staff.duties_id.in_(duties_ids), db=db
|
||||
).data
|
||||
]
|
||||
|
||||
# Get employee
|
||||
@@ -456,13 +495,12 @@ class LoginHandler:
|
||||
reachable_event_codes=reachable_event_codes,
|
||||
)
|
||||
redis_handler = RedisHandlers()
|
||||
try: # Update Redis
|
||||
return redis_handler.update_token_at_redis(
|
||||
token=access_token, add_payload=company_token
|
||||
)
|
||||
except Exception as e:
|
||||
err = e
|
||||
ValueError("EYS_0008")
|
||||
redis_result = redis_handler.update_token_at_redis(
|
||||
token=access_token, add_payload=company_token
|
||||
)
|
||||
return {
|
||||
"selected_uu_id": data.company_uu_id,
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def handle_occupant_selection(
|
||||
@@ -526,12 +564,12 @@ class LoginHandler:
|
||||
reachable_event_codes=reachable_event_codes,
|
||||
)
|
||||
redis_handler = RedisHandlers()
|
||||
try: # Update Redis
|
||||
return redis_handler.update_token_at_redis(
|
||||
token=access_token, add_payload=occupant_token
|
||||
)
|
||||
except Exception as e:
|
||||
raise ValueError("EYS_0008")
|
||||
redis_handler.update_token_at_redis(
|
||||
token=access_token, add_payload=occupant_token
|
||||
)
|
||||
return {
|
||||
"selected_uu_id": data.company_uu_id,
|
||||
}
|
||||
|
||||
@classmethod # Requires auth context
|
||||
def authentication_select_company_or_occupant_type(cls, request: Any, data: Any):
|
||||
@@ -549,16 +587,119 @@ class LoginHandler:
|
||||
if not access_token:
|
||||
raise ValueError("EYS_0001")
|
||||
|
||||
token_object = RedisHandlers().get_object_from_redis(access_token=access_token)
|
||||
if token_object.is_employee and isinstance(data, CompanyToken):
|
||||
token_object = RedisHandlers.get_object_from_redis(access_token=access_token)
|
||||
if token_object.is_employee:
|
||||
return cls.handle_employee_selection(
|
||||
access_token=access_token, data=data, token_dict=token_object,
|
||||
access_token=access_token,
|
||||
data=data,
|
||||
token_dict=token_object,
|
||||
)
|
||||
elif token_object.is_occupant and isinstance(data, OccupantToken):
|
||||
elif token_object.is_occupant:
|
||||
return cls.handle_occupant_selection(
|
||||
access_token=access_token, data=data, token_dict=token_object,
|
||||
access_token=access_token,
|
||||
data=data,
|
||||
token_dict=token_object,
|
||||
)
|
||||
|
||||
|
||||
class PasswordHandler:
|
||||
|
||||
@staticmethod
|
||||
def create_password(password, password_token=None):
|
||||
with Users.new_session() as db_session:
|
||||
found_user = Users.filter_one(
|
||||
Users.password_token == password_token, db=db_session
|
||||
).data
|
||||
if not found_user:
|
||||
raise ValueError("EYS_0031")
|
||||
|
||||
if found_user.password_token:
|
||||
replace_day = 0
|
||||
try:
|
||||
replace_day = int(
|
||||
str(found_user.password_expires_day or 0)
|
||||
.split(",")[0]
|
||||
.replace(" days", "")
|
||||
)
|
||||
except Exception as e:
|
||||
err = e
|
||||
token_is_expired = arrow.now() >= arrow.get(
|
||||
str(found_user.password_expiry_begins)
|
||||
).shift(days=replace_day)
|
||||
|
||||
if not password_token == found_user.password_token and token_is_expired:
|
||||
raise ValueError("")
|
||||
|
||||
collection_name = f"{found_user.related_company}*Domain"
|
||||
print("collection_name", collection_name)
|
||||
with mongo_handler.collection(collection_name) as mongo_engine:
|
||||
print({"user_uu_id": str(found_user.uu_id)})
|
||||
domain_via_user = mongo_engine.find_one(
|
||||
{"user_uu_id": str(found_user.uu_id)}
|
||||
)
|
||||
print("domain_via_user", domain_via_user)
|
||||
if not domain_via_user:
|
||||
raise ValueError("EYS_0024")
|
||||
domain_via_user = domain_via_user.get("main_domain", None)
|
||||
new_password_dict = {
|
||||
"password": PasswordModule.create_hashed_password(
|
||||
domain=domain_via_user,
|
||||
id_=str(found_user.uu_id),
|
||||
password=password,
|
||||
),
|
||||
"date": str(arrow.now().date()),
|
||||
}
|
||||
history_dict = PasswordHistoryViaUser(
|
||||
user_uu_id=str(found_user.uu_id),
|
||||
password_add=new_password_dict,
|
||||
access_history_detail={"request": "", "ip": ""},
|
||||
)
|
||||
found_user.password_expiry_begins = str(arrow.now())
|
||||
found_user.hash_password = new_password_dict.get("password")
|
||||
found_user.password_token = "" if found_user.password_token else ""
|
||||
|
||||
collection_name = f"{found_user.related_company}*PasswordHistory"
|
||||
with mongo_handler.collection(collection_name) as mongo_engine_sc:
|
||||
password_history_item = mongo_engine_sc.find_one(
|
||||
{"user_uu_id": str(found_user.uu_id)}
|
||||
)
|
||||
if not password_history_item:
|
||||
mongo_engine_sc.insert_one(
|
||||
document={
|
||||
"user_uu_id": str(found_user.uu_id),
|
||||
"password_history": [],
|
||||
}
|
||||
)
|
||||
password_history_item = mongo_engine_sc.find_one(
|
||||
{"user_uu_id": str(found_user.uu_id)}
|
||||
)
|
||||
password_history_list = password_history_item.get(
|
||||
"password_history", []
|
||||
)
|
||||
hashed_password = history_dict.password_add.get("password")
|
||||
for password_in_history in password_history_list:
|
||||
if str(password_in_history.get("password")) == str(
|
||||
hashed_password
|
||||
):
|
||||
raise ValueError("EYS_0032")
|
||||
if len(password_history_list) > 3:
|
||||
password_history_list.pop(0)
|
||||
password_history_list.append(history_dict.password_add)
|
||||
return mongo_engine_sc.update_one(
|
||||
filter={"user_uu_id": str(found_user.uu_id)},
|
||||
update={
|
||||
"$set": {
|
||||
"password_history": password_history_list,
|
||||
"modified_at": arrow.now().timestamp(),
|
||||
"access_history_detail": history_dict.access_history_detail,
|
||||
}
|
||||
},
|
||||
upsert=True,
|
||||
)
|
||||
found_user.save(db=db_session)
|
||||
return found_user
|
||||
|
||||
|
||||
class AuthHandlers:
|
||||
LoginHandler: LoginHandler = LoginHandler()
|
||||
PasswordHandler: PasswordHandler = PasswordHandler()
|
||||
|
||||
19
ApiServices/AuthService/events/auth/model.py
Normal file
19
ApiServices/AuthService/events/auth/model.py
Normal file
@@ -0,0 +1,19 @@
|
||||
from typing import Optional
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class DomainViaUser(BaseModel):
|
||||
user_uu_id: str
|
||||
main_domain: str
|
||||
other_domains_list: Optional[list] = None
|
||||
|
||||
|
||||
class PasswordHistoryViaUser(BaseModel):
|
||||
user_uu_id: str
|
||||
password_add: dict
|
||||
access_history_detail: Optional[dict]
|
||||
|
||||
|
||||
class AccessHistoryViaUser(BaseModel):
|
||||
user_uu_id: str
|
||||
access_history: dict
|
||||
Reference in New Issue
Block a user