Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HAN-79: Devolver un session token en el login #3

Merged
merged 5 commits into from
Apr 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .env.dist
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
LOGGING_LEVEL=
PORT=
USERS_HOST=
MEASUREMENTS_HOST=
PLANTS_HOST=
PLANTS_HOST=
SOCIAL_HOST=
JWT_SECRET=
HASH_ALGORITHM=
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ RUN pip install -r requirements.txt

EXPOSE 5000

CMD ["gunicorn", "wsgi:app", "-b", "0.0.0.0:5000"]
CMD ["gunicorn", "wsgi:app", "--reload", "-b", "0.0.0.0:5000"]
57 changes: 57 additions & 0 deletions src/apps/social.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import os
import logging

import requests
from flask import make_response


def get_query_params(queryParam) -> str:
if not queryParam:
return ""
return f"?{str(queryParam, 'utf-8')}"


class Social:
def __init__(self):
self.host = os.getenv("SOCIAL_HOST")

def getResponseJson(self, response):
if response.status_code == 503 or not response.text:
return {"message": "social service is currently unavailable,"
" please try again later", "status": 503}
return response.json()

def get(self, url, body, headers, query_params):
url = f"{self.host}{url}{get_query_params(query_params)}"
logging.info(f"SOCIAL | GET | {url}")
response = requests.get(url, json=body, headers=headers)
return make_response(self.getResponseJson(response),
response.status_code)

def post(self, url, body, headers, query_params):
response = requests.post(f"{self.host}{url}"
f"{get_query_params(query_params)}",
json=body,
headers=headers)
logging.info(f"SOCIAL | POST | {url}")
logging.debug(f"BODY: {body}")
return make_response(self.getResponseJson(response),
response.status_code)

def patch(self, url, body, headers, query_params):
response = requests.patch(f"{self.host}{url}"
f"{get_query_params(query_params)}",
json=body,
headers=headers)
logging.info(f"SOCIAL | PATCH | {url}")
logging.debug(f"BODY: {body}")
return make_response(self.getResponseJson(response),
response.status_code)

def delete(self, url, body, headers, query_params):
response = requests.delete(f"{self.host}{url}"
f"{get_query_params(query_params)}",
headers=headers)
logging.info(f"SOCIAL | DELETE | {url}")
return make_response(self.getResponseJson(response),
response.status_code)
48 changes: 46 additions & 2 deletions src/apps/users.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,52 @@
import http.client
import os
import logging
import jwt

import requests
from flask import make_response


TOKEN_FIELD_NAME = "x-access-token"


def get_query_params(queryParam) -> str:
if not queryParam:
return ""
return f"?{str(queryParam, 'utf-8')}"


def _get_token(headers: dict):
keyName = None
for key in headers.keys():
if key.lower() == TOKEN_FIELD_NAME:
keyName = key
if not keyName:
return None
return headers.get(keyName)


def process_header(headers, body: dict) -> (dict, bool):
token = _get_token(headers)
if not token and not (body and "user_id" in body):
return body, False
newBody = body.copy() if body else {}
try:
processToken = jwt.decode(token, key=os.getenv("HASH_SECRET"),
algorithms=[os.getenv("HASH_ALGORITHM"), ])
newBody["user_id"] = processToken.get("id", "")
newBody["email"] = processToken.get("email")
except jwt.ExpiredSignatureError:
return {"message":
"expired token",
"status": http.client.UNAUTHORIZED}, True
except jwt.InvalidTokenError:
return {"message":
"invalid token",
"status": http.client.FORBIDDEN}, True
return newBody, False


class Users:
def __init__(self):
self.host = os.getenv("USERS_HOST")
Expand All @@ -29,14 +65,22 @@ def get(self, url, body, headers, query_params):
response.status_code)

def post(self, url, body, headers, query_params):
# if not (url.startswith("login")):
# body, error = process_header(headers, body)
# if error:
# return make_response(body, body.get("status"))
response = requests.post(f"{self.host}{url}"
f"{get_query_params(query_params)}",
json=body,
headers=headers)
logging.info(f"USERS | POST | {url}")
logging.debug(f"BODY: {body}")
return make_response(self.getResponseJson(response),
response.status_code)
headers = dict(response.headers)
response = make_response(self.getResponseJson(response),
response.status_code)
if headers.get(TOKEN_FIELD_NAME):
response.headers[TOKEN_FIELD_NAME] = headers.get(TOKEN_FIELD_NAME)
return response

def patch(self, url, body, headers, query_params):
response = requests.patch(f"{self.host}{url}"
Expand Down
7 changes: 6 additions & 1 deletion src/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
from src.apps.users import Users
from src.apps.measurements import Measurements
from src.apps.plants import Plants
from src.apps.social import Social


def getExtraData():
if request.is_json:
body = request.json
else:
body = {}
print(f"en get extract data headers: {request.headers}")
headers = dict(request.headers)
if 'Host' in headers:
headers.pop('Host') # Invalid header
Expand All @@ -25,8 +27,11 @@ def getExtraData():
"device-plant": Measurements(),
"plants": Plants(),
"plant-type": Plants(),
"plant-types": Plants(),
"logs": Plants(),
"login": Users()
"login": Users(),
# TODO: Add the new service
"social": Social()
}


Expand Down
Loading