Skip to content

Commit

Permalink
last-back&profile-merge
Browse files Browse the repository at this point in the history
  • Loading branch information
Recep BATTAL committed Jul 20, 2024
1 parent 1e2efbb commit 6b83774
Show file tree
Hide file tree
Showing 71 changed files with 1,812 additions and 1,397 deletions.
1 change: 0 additions & 1 deletion apigateway/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,5 @@ RUN pip3 install --upgrade pip

RUN pip3 install -r requirements.txt

EXPOSE 8000

CMD ["python3", "manage.py", "runserver", "0.0.0.0:8000"]
3 changes: 2 additions & 1 deletion apigateway/apigateway/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = os.environ.get('DEBUG')

ALLOWED_HOSTS = ['35.242.209.3', 'localhost', '127.0.0.1', '0.0.0.0', 'apigateway', 'usermanagement', 'authservice', 'gameservice', 'friendservice', 'statusservice', 'gameplayservice']
ALLOWED_HOSTS = ['35.242.209.3', 'localhost', '127.0.0.1', '0.0.0.0', 'apigateway', 'usermanagement', 'authservice', 'gameservice', 'friendservice', 'statusservice', 'gameplayservice', '[::1]']


# Application definition
Expand All @@ -39,6 +39,7 @@
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
]

MIDDLEWARE = [
Expand Down
2 changes: 2 additions & 0 deletions apigateway/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
django
django-core
djangorestframework
django-cors-headers
requests
8 changes: 8 additions & 0 deletions apigateway/src/middleware.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import logging

import requests
from django.conf import settings
from django.http import JsonResponse


class JWTAuthenticationMiddleware:
def __init__(self, get_response):
self.get_response = get_response
Expand All @@ -12,9 +15,14 @@ def __call__(self, request):
return response

def process_view(self, request, view_func, view_args, view_kwargs):
if request.path.startswith('/api'):
request.path = request.path[4:]
if request.path in self.paths_to_exclude:
return None

if request.path.startswith('/user/email_verify'):
return None

token = request.headers.get('Authorization')
if not token:
return JsonResponse({'error': 'Missing token'}, status=401)
Expand Down
20 changes: 19 additions & 1 deletion apigateway/src/views.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import logging

import requests
from django.conf import settings
from django.http import HttpResponseRedirect
Expand All @@ -10,6 +12,9 @@ class APIGatewayView(APIView):

def operations(self, request, path):
headers = dict(request.headers)
if request.path.startswith('/user/email_verify'):
headers['Content-Type'] = 'application/json'
return pass_request_to_destination_service(request, path, headers)
if not (settings.EXCLUDED_ROUTES and request.path in settings.EXCLUDED_ROUTES):
headers['id'] = str(request.user_id)
return pass_request_to_destination_service(request, path, headers)
Expand Down Expand Up @@ -40,13 +45,26 @@ def pass_request_to_destination_service(request, path, headers):
if params:
full_url += f"?{params.urlencode()}"
method = request.method.lower()
response = requests.request(method, full_url, headers=headers, json=request.data)
try:
response = requests.request(method, full_url, headers=headers, json=request.data)
except requests.exceptions.RequestException as e:
logging.error(f"Error in request: {e}")
return Response({'error': 'Internal server error'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

if path.startswith('auth/') and response.status_code == 200 or response.status_code == 207:
json_response = response.json()
if 'redirect_url' in json_response:
return HttpResponseRedirect(json_response['redirect_url'])

if path.startswith('user/email_verify') and response.status_code == 200:
try:
json_response = response.json()
if 'redirect_url' in json_response:
return HttpResponseRedirect(json_response['redirect_url'])
except Exception as e:
logging.error(f"Error in request: {e}")
return Response({'error': 'Internal server error'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

if response.headers.get('content-type') == 'application/json':
return Response(response.json(), status=response.status_code)
return Response(response.content, status=response.status_code)
Expand Down
1 change: 1 addition & 0 deletions authservice/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ RUN pip3 install --upgrade pip

RUN pip3 install -r requirements.txt


CMD [ "python3", "manage.py", "runserver", "0.0.0.0:8001"]
95 changes: 56 additions & 39 deletions authservice/src/views.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import jwt
import uuid
import requests
from datetime import datetime, timedelta, timezone
from rest_framework import viewsets
Expand All @@ -9,26 +10,25 @@
import logging


def generate_access_token(user_id):
def generate_access_token(user_id, jti):
payload = {
'user_id': user_id,
'jti': jti, # unique identifier for the token pair.
'exp': datetime.now(tz=timezone.utc) + timedelta(minutes=1),
'iat': datetime.now(tz=timezone.utc)
}
access_token = jwt.encode(payload, settings.SECRET_KEY, algorithm='HS256')
iat_seconds = payload['iat'].timestamp()
logging.error("------------------------------->>>>>>>>> %s", iat_seconds)
return access_token, iat_seconds
return access_token


def generate_refresh_token(user_id, exp, iat, access_token_iat):
def generate_refresh_token(user_id, exp, iat, jti):
if exp is None:
exp = datetime.now(tz=timezone.utc) + timedelta(days=7)
if iat is None:
iat = datetime.now(tz=timezone.utc)
payload = {
'user_id': user_id,
'acces_token_iat': access_token_iat,
'jti': jti,
'exp': exp,
'iat': iat,
}
Expand All @@ -39,15 +39,37 @@ def generate_refresh_token(user_id, exp, iat, access_token_iat):

class AuthHandler(viewsets.ViewSet):
SECRET_KEY = settings.SECRET_KEY
verification_options = {"require": ["exp", "iat"], "verify_exp": True, "verify_iat": True, "verify_signature": True}
verification_options = {
"require": ["exp", "iat", "jti"],
"verify_exp": True,
"verify_iat": True,
"verify_signature": True
}

def _decode_token(self, token, verify_exp=True):
try:
options = self.verification_options.copy()
options['verify_exp'] = verify_exp
return jwt.decode(token, self.SECRET_KEY, algorithms=['HS256'], options=options), None
except jwt.ExpiredSignatureError as e:
return None, 'Token has expired'
except jwt.InvalidTokenError as e:
return None, 'Invalid token'
except Exception as e:
logging.error("Unexpected error decoding token: %s", str(e))
return None, 'Error decoding token'

def _error_response(self, message, status_code=status.HTTP_400_BAD_REQUEST):
return Response({'error': message}, status=status_code)

def generate_tokens(self, request):
req = GenerateTokenSerializer(data=request.query_params)
if not req.is_valid():
return Response(req.errors, status=400)
user_id = req.validated_data['user_id']
access_token, acss_iat = generate_access_token(user_id)
refresh_token = generate_refresh_token(user_id, None, None, acss_iat)
jti = str(uuid.uuid4())
access_token = generate_access_token(user_id, jti)
refresh_token = generate_refresh_token(user_id, None, None, jti)
return Response({
'access_token': access_token,
'refresh_token': refresh_token
Expand All @@ -71,39 +93,33 @@ def validate_token(self, request):
def refresh_token(self, request):
access_token = request.headers.get('Authorization')
if not access_token:
return Response({'error': 'Token is required'}, status=status.HTTP_400_BAD_REQUEST)
return self._error_response('Access token is required', status.HTTP_401_UNAUTHORIZED)

req = RefreshTokenSerializer(data=request.data)
if not req.is_valid():
return Response(req.errors, status=status.HTTP_400_BAD_REQUEST)

refresh_token = req.validated_data['refresh_token']
decoded_access_token, access_error = self._decode_token(access_token.split(' ')[1], verify_exp=False)
decoded_refresh_token, refresh_error = self._decode_token(refresh_token, verify_exp=True)

try:
decoded_access_token = jwt.decode(access_token.split(' ')[1], self.SECRET_KEY, algorithms=['HS256'], options={'verify_exp': False})
except jwt.ExpiredSignatureError:
try:
accs_iat = decoded_access_token['iat']
refresh_token = refresh_token.split(' ')[1]
decoded_token = jwt.decode(refresh_token, self.SECRET_KEY, algorithms=['HS256'], options=self.verification_options)
refresh_accs_iat = decoded_token['acces_token_iat']
if accs_iat != refresh_accs_iat:
return Response({'error': 'Access token and refresh token do not match'}, status=status.HTTP_400_BAD_REQUEST)
user_id = decoded_token['user_id']
new_access_token, access_iat = generate_access_token(user_id)
new_refresh_token = generate_refresh_token(user_id, decoded_token['exp'], decoded_token['iat'], access_iat)
return Response({
'access_token': new_access_token,
'refresh_token': new_refresh_token
}, status=status.HTTP_200_OK)
except jwt.ExpiredSignatureError:
return Response({'error': 'Token has expired'}, status=status.HTTP_401_UNAUTHORIZED)
except jwt.InvalidTokenError:
return Response({'error': 'Invalid token'}, status=status.HTTP_401_UNAUTHORIZED)
except Exception as e:
return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)
except jwt.InvalidTokenError:
return Response({'error': 'Invalids token'}, status=status.HTTP_401_UNAUTHORIZED)
except Exception as e:
return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)
if access_error:
return self._error_response(access_error, status.HTTP_401_UNAUTHORIZED)
if refresh_error:
return self._error_response(refresh_error, status.HTTP_401_UNAUTHORIZED)

if decoded_access_token['jti'] != decoded_refresh_token['jti']:
return self._error_response('Access token and refresh token do not match')

user_id = decoded_refresh_token['user_id']
jti = str(uuid.uuid4()) # Generate a new jti for the new token pair
new_access_token = generate_access_token(user_id, jti)
new_refresh_token = generate_refresh_token(user_id, None, None, jti)

return Response({
'access_token': new_access_token,
'refresh_token': new_refresh_token
}, status=status.HTTP_200_OK)

def intra_oauth(self, request):
return Response({'url': settings.INTRA_REDIRECT_URL}, status=status.HTTP_200_OK)
Expand All @@ -129,9 +145,10 @@ def intra_oauth_callback(self, request):
return Response(user_creation_response.json(), status=user_creation_response.status_code)

response_data = user_creation_response.json().get('data')
jti = str(uuid.uuid4())
user_id = response_data[0].get('id')
token, access_iat = generate_access_token(user_id)
refresh_token = generate_refresh_token(user_id, None, None, access_iat)
token = generate_access_token(user_id, jti)
refresh_token = generate_refresh_token(user_id, None, None, jti)

# 207 status code is for username already exist.
# Redirect to frontend for update username. Otherwise, redirect to homepage
Expand Down
1 change: 1 addition & 0 deletions bucketservice/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ COPY start.sh /app/start.sh

RUN chmod +x /app/start.sh


ENTRYPOINT ["sh", "./start.sh"]

CMD ["python3", "manage.py", "runserver", "0.0.0.0:8014"]
2 changes: 1 addition & 1 deletion bucketservice/bucketservice/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = os.environ.get('DEBUG')

ALLOWED_HOSTS = []
ALLOWED_HOSTS = ['*']

SERVICE_ROUTES = {
'/auth': 'http://authservice:8001',
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion bucketservice/src/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def create(self, request, *args, **kwargs):
except requests.exceptions.RequestException as e:
return Response({'error': 'Internal server error'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
if response.status_code != 200:
return Response({'error': 'Unauthorized'}, status=status.HTTP_401_UNAUTHORIZED)
return Response({'error': response.json()['error']}, status=status.HTTP_401_UNAUTHORIZED)
serializer = ImageSerializer(data=request.data)
if not serializer.is_valid():
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Expand Down
22 changes: 11 additions & 11 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@ version: '3.8'
services:
frontend:
container_name: frontend
image: nginx
build: ./frontend
depends_on:
- apigateway
- bucketservice
- gameplayservice
- statusservice
volumes:
- ./frontend:/usr/share/nginx/html
- ./frontend/nginx.conf:/etc/nginx/nginx.conf
ports:
- "808:80"
- "443:443"

apigateway:
container_name: apigateway
Expand Down Expand Up @@ -40,6 +45,8 @@ services:
- FRONTEND_URL=${FRONTEND_URL}
volumes:
- ./authservice:/app
ports:
- "8001:8001"

bucketservice:
container_name: bucketservice
Expand Down Expand Up @@ -132,6 +139,8 @@ services:
- EMAIL_HOST_PASSWORD=${MailService_EMAIL_HOST_PASSWORD}
volumes:
- ./mailservice:/app
ports:
- "8005:8005"

statusservice:
container_name: statusservice
Expand Down Expand Up @@ -232,12 +241,3 @@ services:
ports:
- "5435:${BucketService_DB_PORT}"










1 change: 1 addition & 0 deletions friendservice/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ COPY start.sh /app/start.sh

RUN chmod +x /app/start.sh


ENTRYPOINT ["sh", "./start.sh"]

CMD ["python3", "manage.py", "runserver", "0.0.0.0:8012"]
2 changes: 1 addition & 1 deletion friendservice/friendservice/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = os.environ.get('DEBUG')

ALLOWED_HOSTS = []
ALLOWED_HOSTS = ['*']


# Application definition
Expand Down
1 change: 1 addition & 0 deletions friendservice/srcs/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ def get_all_request(self, user_id):
res = Friends.objects.filter(receiver_id=user_id, state=0, deleted_at=None).all().values('sender_id')
except:
return ""
res = res.order_by('-created_at')
return res

def set_state(self, sender_id, receiver_id, state):
Expand Down
2 changes: 2 additions & 0 deletions friendservice/srcs/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from .serializers import FriendsSerializer, FriendReqListSerializer
from .utils import BaseResponse


class IFriendsService(ABC):
@abstractmethod
def add_friend(self, sender_id, receiver_id) -> BaseResponse:
Expand All @@ -30,6 +31,7 @@ def get_requests(self, user_id, page, limit) -> BaseResponse:
def get_friends(self, user_id, page, limit) -> BaseResponse:
pass


class FriendsService(IFriendsService):
def __init__(self, repository: IFriendsRepository):
self.repository = repository
Expand Down
13 changes: 13 additions & 0 deletions frontend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM nginx:alpine

RUN apk update && \
apk add --no-cache openssl


RUN mkdir -p /etc/ssl/private/ && mkdir -p /etc/ssl/certs/ && \
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /etc/ssl/private/nginx.key \
-out /etc/ssl/certs/nginx.crt \
-subj "/C=TR/ST=Kocaeli/L=Kocaeli/O=Ecole42/OU=transcendence/CN=127.0.0.1:443"

CMD ["nginx", "-g", "daemon off;"]
Loading

0 comments on commit 6b83774

Please sign in to comment.