Skip to content

Commit

Permalink
Merge pull request #55 from RobsOnWaves/adding_logs
Browse files Browse the repository at this point in the history
Adding logs
  • Loading branch information
RobsOnWaves authored Jan 14, 2024
2 parents e02c56b + c10a66c commit b6c6832
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 22 deletions.
4 changes: 4 additions & 0 deletions Code/libs/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ class Messages:
language='alias') + "something went wrong for Fay Wray and King Kong"
+ emojize(":musical_note:" + ":lips:", language='alias')}

nok_string_raw = emojize(":no_entry:" + ":musical_note:",language="alias") +\
"something went wrong for Fay Wray and King Kong" + \
emojize(":musical_note:" + ":lips:", language="alias")

__ok_string_user_left_side__ = emojize(":ok_woman:", language='alias') + emojize(":+1:", language='alias') \
+ "user '"

Expand Down
10 changes: 5 additions & 5 deletions Code/libs/mongo_db_handler.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import pymongo
from pymongo import MongoClient
from pymongo import MongoClient, errors
from libs.ged_file_handler import GedFileHandler
from libs.messages import Messages
import pandas as pd
Expand Down Expand Up @@ -210,13 +210,13 @@ def insert_user(self,
status = db.users.insert_one(query)

except errors.DuplicateKeyError as e:
return {'response': "user already exists" + self.__messages__.nok_string}
return {'response': "user already exists" + self.__messages__.nok_string_raw}

except Exception as e:
return {'response': "MongoDB error" + "Exception: " + str(e) + self.__messages__.nok_string}
return {'response': "MongoDB error" + "Exception: " + str(e) + self.__messages__.nok_string_raw}

return self.__messages__.build_ok_user_string(user_name=user_name) if status.acknowledged else \
self.__messages__.nok_string
return {'response': self.__messages__.build_ok_user_string(user_name=user_name) if status.acknowledged else \
self.__messages__.nok_string}

def get_collections(self):

Expand Down
134 changes: 117 additions & 17 deletions Code/public_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from datetime import datetime, timedelta
from typing import Union
from enum import Enum
from fastapi import Depends, FastAPI, HTTPException, status, Form, UploadFile
from fastapi import Depends, FastAPI, HTTPException, status, Form, UploadFile, Request
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from fastapi.responses import FileResponse, RedirectResponse
from jose import JWTError, jwt
Expand All @@ -17,7 +17,10 @@
from fastapi.middleware.cors import CORSMiddleware
import re
from pathlib import Path

import json
import logging
from pythonjsonlogger import jsonlogger
import time

class Roles(str, Enum):
admin = "admin"
Expand All @@ -26,6 +29,19 @@ class Roles(str, Enum):
meps = "meps"


# Configuration du Logger
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

# Créer un gestionnaire de logs qui écrit dans un fichier
logHandler = logging.FileHandler('app_logs.json')

# Utiliser le format JSON pour le gestionnaire de fichier
formatter = jsonlogger.JsonFormatter()
logHandler.setFormatter(formatter)

logger.addHandler(logHandler)

# to get a string like this run:
# openssl rand -hex 32
try:
Expand All @@ -38,6 +54,7 @@ class Roles(str, Enum):
print("Error getting SECRET_KEY")
print(e)


ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
JSON_EXTENSION = ".json"
Expand Down Expand Up @@ -82,6 +99,24 @@ class UserInDB(User):
code at: [GitHub GED-Handler repo](https://github.com/RobsOnWaves/ged-handler))
""", title="GED-Handler")

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

def get_user_id_from_token(token: str):
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
return payload.get("sub") # 'sub' est généralement l'identifiant de l'utilisateur
except jwt.JWTError:
return None

def log_to_json_file(log_data):
log_file_path = 'logz.json'
try:
with open(log_file_path, 'a') as log_file:
json.dump(log_data, log_file)
log_file.write('\n') # Ajoute une nouvelle ligne après chaque log
except Exception as e:
print(f"Error writing to log file: {e}")


def el_parametrizor(mode_debug=False):
if mode_debug:
Expand Down Expand Up @@ -222,6 +257,73 @@ async def get_current_active_user(current_user: User = Depends(get_current_user)
)


async def get_request_body(request: Request):
body = await request.body()

async def app(scope, receive, send):
async def override_receive():
return {"type": "http.request", "body": body}

await request.app(scope, override_receive, send)

# Important: Définir override_receive ici pour qu'elle soit accessible
async def override_receive():
return {"type": "http.request", "body": body}

request._receive = override_receive

return body


def mask_sensitive_data_and_exclude_files(body: str) -> str:
# Masquer les données sensibles
body = re.sub(r'(password=)[^&]*', r'\1[MASKED]', body, flags=re.IGNORECASE)

# Exclure les fichiers uploadés (ajuster selon la structure de la requête)
body = re.sub(r'(upload_file=)[^&]*', '[FILE EXCLUDED]', body, flags=re.IGNORECASE)

return body

@app.middleware("http")
async def log_requests(request: Request, call_next):
start_time = time.time()

# Vérifier le type de contenu
content_type = request.headers.get('content-type')

# Traiter différemment les données binaires
if content_type and ("multipart/form-data" in content_type or "application/octet-stream" in content_type):
body_text = '[Binary Data]'
else:
# Obtenir et nettoyer le corps de la requête pour les types de contenu textuels
body = await get_request_body(request)
body_text = body.decode('utf-8') if body else ''
body_text = mask_sensitive_data_and_exclude_files(body_text)

try:
token = await oauth2_scheme(request)
user_id = get_user_id_from_token(token) if token else "anonymous"
except Exception as e:
user_id = "error_in_token"

# Continuer le traitement de la requête
response = await call_next(request)
process_time = (time.time() - start_time) * 1000
# Logger les informations
logger.info('Request info', extra={
"timestamp": datetime.fromtimestamp(start_time).isoformat(),
"user_id": user_id,
'request_method': request.method,
'request_url': str(request.url),
'response_status': response.status_code,
'process_time_ms': process_time,
'request_body': body_text,
# Autres informations...
})

return response


@app.get("/")
async def docs_redirect():
return RedirectResponse(url='/docs')
Expand Down Expand Up @@ -257,9 +359,8 @@ async def create_user(user_name: str = Form(),
role: Roles = Form(),
current_user: User = Depends(get_current_active_user)):
if current_user.role == "admin":
mongo_handler.insert_user(user_name, full_name, email, get_password_hash(password),
return mongo_handler.insert_user(user_name, full_name, email, get_password_hash(password),
current_user.username, role)
return {'response': 'User created successfully'}
else:
return {'response': 'Access denied'}

Expand All @@ -274,7 +375,7 @@ async def upload_ged_file(file: UploadFile,
return mongo_handler.insert_list_of_ged_objets(collection_name=ged_import_name, ged_handler=ged_handler)

else:
return {'response': messages.denied_entry}
raise HTTPException(status_code=403, detail=messages.denied_entry)


@app.get("/ged_stored_collection_to_json_answer", description="Returns a JSON answer from a stored collection")
Expand All @@ -283,7 +384,7 @@ async def ged_stored_collection_to_json_answer(ged_collection_name: str,
if current_user.role in ['admin', 'user']:
return mongo_handler.from_mongo_to_ged_list_dict(collection_name=ged_collection_name)
else:
return {'response': messages.nok_string}
raise HTTPException(status_code=403, detail=messages.denied_entry)


@app.get("/ged_stored_collection_to_json_file", description="Returns a JSON file from a stored collection")
Expand All @@ -298,7 +399,7 @@ async def ged_stored_collection_to_json_file(ged_collection_name: str,
convert_file.write(jsoned_ged)
return FileResponse(safe_path)
else:
return {'response': messages.nok_string}
raise HTTPException(status_code=403, detail=messages.denied_entry)


@app.post("/ged_file_to_json_answer", description="Returns a converted JSON file from a ged-file"
Expand All @@ -313,7 +414,7 @@ async def ged_collection_to_json_answer(file: UploadFile,
return ged_handler.listed_documents

else:
return {'response': messages.nok_string}
raise HTTPException(status_code=403, detail=messages.denied_entry)


@app.get("/ged_stored_collections", description="Returns a list of all stored collections")
Expand All @@ -323,7 +424,7 @@ async def ged_stored_collections(current_user: User = Depends(get_current_active
return mongo_handler.get_collections()

else:
return {'response': messages.nok_string}
raise HTTPException(status_code=403, detail=messages.denied_entry)


@app.post("/ged_file_to_json_file", description="Returns a converted JSON file from a ged-file"
Expand All @@ -346,7 +447,7 @@ async def ged_collection_to_json_file(file: UploadFile,
return FileResponse(json_file_path)

else:
return {'response': messages.nok_string}
raise HTTPException(status_code=403, detail=messages.denied_entry)


@app.post("/modify_user_password", description="Modify an exiting user password, restricted to admin privileges")
Expand All @@ -361,7 +462,7 @@ async def modify_user_password(
hashed_password=get_password_hash(password))}

else:
return {'response': messages.nok_string}
raise HTTPException(status_code=403, detail=messages.denied_entry)


@app.post("/gold_file_converter", description="Returns an Excel with the estimated value in euros")
Expand All @@ -384,7 +485,7 @@ async def gold_file_converter(file: UploadFile, price_per_kg: int,

return FileResponse(full_safe_path)
else:
return {'response': messages.nok_string}
raise HTTPException(status_code=403, detail=messages.denied_entry)


@app.post("/meps_file",
Expand All @@ -397,12 +498,12 @@ async def load_meps_file(file: UploadFile, current_user: User = Depends(get_curr
await meps_handler.load_csv_file(upload_file=file, answer=answer)

if not answer['success']:
return {'response': messages.nok_string}
raise HTTPException(status_code=403, detail=messages.denied_entry)
else:
mongo_handler.from_df_to_mongo_meps(df=answer['df'], collection_name="meps_meetings")
return {'response': messages.build_ok_action_string(user_name=current_user.username)}
else:
return {'response': messages.denied_entry}
raise HTTPException(status_code=403, detail=messages.denied_entry)


@app.get("/meps_file",
Expand All @@ -413,10 +514,9 @@ async def get_meps_file(current_user: User = Depends(get_current_active_user)):
if mongo_handler.from_mongo_to_xlsx_meps():
return FileResponse('meps_fichier.xlsx')
else:
return {'response': messages.nok_string}
raise HTTPException(status_code=403, detail=messages.denied_entry)
else:
return {'response': messages.denied_entry}

raise HTTPException(status_code=403, detail=messages.denied_entry)

@app.post("/logout")
async def logout():
Expand Down

0 comments on commit b6c6832

Please sign in to comment.