mirror of
https://github.com/fuckpiracyshield/api.git
synced 2024-12-22 02:40:48 +01:00
Added sessions support.
This commit is contained in:
parent
183fa3e27a
commit
0fb6d08a7f
9 changed files with 115 additions and 60 deletions
|
@ -23,17 +23,19 @@ class ErrorCode:
|
|||
|
||||
TOKEN_FORMAT_NON_VALID = '1008'
|
||||
|
||||
NON_VALID_PARAMETERS = '1009'
|
||||
TOKEN_EXPIRED = '1009'
|
||||
|
||||
MISSING_PARAMETERS = '1010'
|
||||
NON_VALID_PARAMETERS = '1010'
|
||||
|
||||
TOO_MANY_PARAMETERS = '1011'
|
||||
MISSING_PARAMETERS = '1011'
|
||||
|
||||
MISSING_FILE = '1012'
|
||||
TOO_MANY_PARAMETERS = '1012'
|
||||
|
||||
CHANGE_PASSWORD = '1013'
|
||||
MISSING_FILE = '1013'
|
||||
|
||||
IP_ADDRESS_BLACKLISTED = '1014'
|
||||
CHANGE_PASSWORD = '1014'
|
||||
|
||||
IP_ADDRESS_BLACKLISTED = '1015'
|
||||
|
||||
class ErrorMessage:
|
||||
|
||||
|
@ -63,6 +65,8 @@ class ErrorMessage:
|
|||
|
||||
TOKEN_FORMAT_NON_VALID = 'Token format non valid.'
|
||||
|
||||
TOKEN_EXPIRED = 'This token is expired.'
|
||||
|
||||
# json POST parameters
|
||||
|
||||
NON_VALID_PARAMETERS = 'Expecting JSON data.'
|
||||
|
@ -77,6 +81,6 @@ class ErrorMessage:
|
|||
|
||||
# account settings
|
||||
|
||||
CHANGE_PASSWORD = 'A password change has been activated for your account. You must first authenticate via web app and follow the instructions.'
|
||||
CHANGE_PASSWORD = 'A password change has been activated for your account. You must authenticate via web interface and follow the instructions. You should now discard this tokens pairs.'
|
||||
|
||||
IP_ADDRESS_BLACKLISTED = 'Your IP address is temporary blacklisted.'
|
||||
|
|
|
@ -2,6 +2,8 @@ from .base import BaseHandler
|
|||
|
||||
from piracyshield_component.exception import ApplicationException
|
||||
|
||||
from piracyshield_service.security.blacklist.exists_by_access_token import SecurityBlacklistExistsByAccessTokenService
|
||||
|
||||
from piracyshield_service.authentication.verify_access_token import AuthenticationVerifyAccessTokenService
|
||||
|
||||
from piracyshield_service.permission.service import PermissionService
|
||||
|
@ -28,6 +30,8 @@ class ProtectedHandler(BaseHandler):
|
|||
account_data = {}
|
||||
|
||||
async def prepare(self):
|
||||
self.security_blacklist_exists_by_access_token_service = SecurityBlacklistExistsByAccessTokenService()
|
||||
|
||||
self.authentication_verify_access_token_service = AuthenticationVerifyAccessTokenService()
|
||||
|
||||
await super().prepare()
|
||||
|
@ -52,12 +56,19 @@ class ProtectedHandler(BaseHandler):
|
|||
return False
|
||||
|
||||
# get the token only
|
||||
token = authorization_header[7:]
|
||||
self.current_access_token = authorization_header[7:]
|
||||
|
||||
try:
|
||||
if self.security_blacklist_exists_by_access_token_service.execute(
|
||||
access_token = self.current_access_token
|
||||
) == True:
|
||||
self.error(status_code = 401, error_code = ErrorCode.TOKEN_EXPIRED, message = ErrorMessage.TOKEN_EXPIRED)
|
||||
|
||||
return False
|
||||
|
||||
# set the current account data
|
||||
# TODO: absolutely need to validate the payload.
|
||||
self.account_data = self.authentication_verify_access_token_service.execute(token)
|
||||
self.account_data = self.authentication_verify_access_token_service.execute(self.current_access_token)
|
||||
|
||||
if not self.account_data.get('email'):
|
||||
self.error(status_code = 401, error_code = ErrorCode.TOKEN_FORMAT_NON_VALID, message = ErrorMessage.TOKEN_FORMAT_NON_VALID)
|
||||
|
|
|
@ -15,7 +15,7 @@ class TestReporterCreateTicket:
|
|||
ticket_wait_time = 76
|
||||
|
||||
ticket_parameters = {
|
||||
'dda_id': '2326485749e94573bf5724ff5006f30c',
|
||||
'dda_id': '002ad48ea02a43db9003b4f15f1da9b3',
|
||||
'description': '__MOCK_TICKET__',
|
||||
'forensic_evidence': {
|
||||
'hash': {}
|
||||
|
@ -44,6 +44,8 @@ class TestReporterCreateTicket:
|
|||
|
||||
create_response = authenticated_post_request('/api/v1/ticket/create', self.access_token, self.ticket_parameters)
|
||||
|
||||
print(" RES -> ", create_response.json())
|
||||
|
||||
assert create_response.status_code == 200
|
||||
assert create_response.json()['status'] == 'success'
|
||||
|
||||
|
|
|
@ -4,9 +4,10 @@ import pytest
|
|||
import os
|
||||
import requests
|
||||
|
||||
application_config = Config('api').get('general')
|
||||
application_config = Config('application').get('general')
|
||||
api_config = Config('application').get('api')
|
||||
|
||||
URL = f"http://127.0.0.1:{application_config['port']}"
|
||||
URL = f"{application_config.get('domain')}:{api_config.get('port')}"
|
||||
|
||||
def get_request(endpoint: str):
|
||||
return requests.get(f'{URL}{endpoint}')
|
||||
|
|
41
v1/handlers/account/session/get_all.py
Normal file
41
v1/handlers/account/session/get_all.py
Normal file
|
@ -0,0 +1,41 @@
|
|||
import sys
|
||||
import os
|
||||
|
||||
# I hate python imports
|
||||
current = os.path.dirname(os.path.realpath(__file__))
|
||||
parent = os.path.dirname(current)
|
||||
sys.path.append(parent)
|
||||
|
||||
import tornado
|
||||
|
||||
from ioutils.protected import ProtectedHandler
|
||||
|
||||
from piracyshield_service.permission.service import PermissionService
|
||||
from piracyshield_service.account.session.get_all_by_account_ordered import AccountSessionGetAllByAccountOrderedService
|
||||
|
||||
from piracyshield_component.exception import ApplicationException
|
||||
|
||||
class GetAllSessionAccountHandler(ProtectedHandler):
|
||||
|
||||
"""
|
||||
Handles getting multiple active sessions.
|
||||
"""
|
||||
|
||||
async def get(self):
|
||||
if self.initialize_account() == False:
|
||||
return
|
||||
|
||||
try:
|
||||
account_session_get_all_by_account_ordered_service = AccountSessionGetAllByAccountOrderedService()
|
||||
|
||||
response = await tornado.ioloop.IOLoop.current().run_in_executor(
|
||||
None,
|
||||
account_session_get_all_by_account_ordered_service.execute,
|
||||
self.account_data.get('account_id'),
|
||||
self.current_access_token
|
||||
)
|
||||
|
||||
self.success(data = response)
|
||||
|
||||
except ApplicationException as e:
|
||||
self.error(status_code = 400, error_code = e.code, message = e.message)
|
|
@ -11,8 +11,6 @@ from ioutils.base import BaseHandler
|
|||
from ioutils.errors import ErrorCode, ErrorMessage
|
||||
|
||||
from piracyshield_service.authentication.authenticate import AuthenticationAuthenticateService
|
||||
from piracyshield_service.authentication.generate_access_token import AuthenticationGenerateAccessTokenService
|
||||
from piracyshield_service.authentication.generate_refresh_token import AuthenticationGenerateRefreshTokenService
|
||||
|
||||
from piracyshield_component.exception import ApplicationException
|
||||
|
||||
|
@ -36,14 +34,19 @@ class AuthenticationLoginHandler(BaseHandler):
|
|||
return
|
||||
|
||||
try:
|
||||
authentication_authenticate_service = AuthenticationAuthenticateService()
|
||||
|
||||
access_token, refresh_token = await tornado.ioloop.IOLoop.current().run_in_executor(
|
||||
None,
|
||||
self.process,
|
||||
authentication_authenticate_service.execute,
|
||||
self.request_data.get('email'),
|
||||
self.request_data.get('password'),
|
||||
self.request.remote_ip
|
||||
)
|
||||
|
||||
# store the refresh token in a http-only secure cookie
|
||||
self.set_refresh_cookie(value = refresh_token)
|
||||
|
||||
self.success(data = {
|
||||
'access_token': access_token,
|
||||
'refresh_token': refresh_token
|
||||
|
@ -51,25 +54,3 @@ class AuthenticationLoginHandler(BaseHandler):
|
|||
|
||||
except ApplicationException as e:
|
||||
self.error(status_code = 400, error_code = e.code, message = e.message)
|
||||
|
||||
def process(self, email: str, password: str, ip_address: str) -> tuple:
|
||||
authentication_authenticate_service = AuthenticationAuthenticateService()
|
||||
|
||||
# try to authenticate
|
||||
payload = authentication_authenticate_service.execute(
|
||||
email = email,
|
||||
password = password,
|
||||
ip_address = ip_address
|
||||
)
|
||||
|
||||
authentication_generate_access_token_service = AuthenticationGenerateAccessTokenService()
|
||||
authentication_generate_refresh_token_service = AuthenticationGenerateRefreshTokenService()
|
||||
|
||||
# generate token pairs
|
||||
access_token = authentication_generate_access_token_service.execute(payload)
|
||||
refresh_token = authentication_generate_refresh_token_service.execute(payload)
|
||||
|
||||
# store the refresh_token in a http-only cookie
|
||||
self.set_refresh_cookie(value = refresh_token)
|
||||
|
||||
return access_token, refresh_token
|
||||
|
|
|
@ -7,19 +7,31 @@ sys.path.append(parent)
|
|||
|
||||
from ioutils.protected import ProtectedHandler
|
||||
|
||||
from piracyshield_service.account.session.destroy_current_sessions import AccountSessionDestroyCurrentSessionsService
|
||||
|
||||
from piracyshield_component.exception import ApplicationException
|
||||
|
||||
class AuthenticationLogoutHandler(ProtectedHandler):
|
||||
|
||||
"""
|
||||
Removes the authentication refresh token.
|
||||
The effective logout remains on the access token expiration time, this is why it should be set to a short time.
|
||||
Removes the authentication refresh token and blacklists both the tokens.
|
||||
"""
|
||||
|
||||
def get(self):
|
||||
if self.initialize_account() == False:
|
||||
return
|
||||
|
||||
try:
|
||||
account_session_destroy_current_sessions_service = AccountSessionDestroyCurrentSessionsService()
|
||||
|
||||
account_session_destroy_current_sessions_service.execute(
|
||||
self.account_data.get('account_id'),
|
||||
self.current_access_token
|
||||
)
|
||||
|
||||
self.clear_cookie('refresh_token')
|
||||
|
||||
self.success(data = 'Goodbye!')
|
||||
|
||||
except ApplicationException as e:
|
||||
self.error(status_code = 400, error_code = e.code, message = e.message)
|
||||
|
|
|
@ -10,8 +10,9 @@ import tornado
|
|||
from ioutils.base import BaseHandler
|
||||
from ioutils.errors import ErrorCode, ErrorMessage
|
||||
|
||||
from piracyshield_service.authentication.verify_refresh_token import AuthenticationVerifyRefreshTokenService
|
||||
from piracyshield_service.authentication.generate_access_token import AuthenticationGenerateAccessTokenService
|
||||
from piracyshield_service.security.blacklist.exists_by_refresh_token import SecurityBlacklistExistsByRefreshTokenService
|
||||
|
||||
from piracyshield_service.authentication.refresh_access_token import AuthenticationRefreshAccessTokenService
|
||||
|
||||
from piracyshield_component.exception import ApplicationException
|
||||
|
||||
|
@ -41,10 +42,22 @@ class AuthenticationRefreshHandler(BaseHandler):
|
|||
refresh_token = self.request_data.get('refresh_token')
|
||||
|
||||
try:
|
||||
security_blacklist_exists_by_refresh_token_service = SecurityBlacklistExistsByRefreshTokenService()
|
||||
|
||||
if security_blacklist_exists_by_refresh_token_service.execute(
|
||||
refresh_token = refresh_token
|
||||
) == True:
|
||||
self.error(status_code = 401, error_code = ErrorCode.TOKEN_EXPIRED, message = ErrorMessage.TOKEN_EXPIRED)
|
||||
|
||||
return False
|
||||
|
||||
authentication_refresh_access_token_service = AuthenticationRefreshAccessTokenService()
|
||||
|
||||
access_token = await tornado.ioloop.IOLoop.current().run_in_executor(
|
||||
None,
|
||||
self.process,
|
||||
refresh_token
|
||||
authentication_refresh_access_token_service.execute,
|
||||
refresh_token,
|
||||
self.request.remote_ip
|
||||
)
|
||||
|
||||
# return the access_token
|
||||
|
@ -54,18 +67,3 @@ class AuthenticationRefreshHandler(BaseHandler):
|
|||
|
||||
except ApplicationException as e:
|
||||
self.error(status_code = 400, error_code = e.code, message = e.message)
|
||||
|
||||
def process(self, refresh_token: str) -> str:
|
||||
authentication_verify_refresh_token_service = AuthenticationVerifyRefreshTokenService()
|
||||
|
||||
# verify the token and unwrap the payload
|
||||
payload = authentication_verify_refresh_token_service.execute(
|
||||
token = refresh_token
|
||||
)
|
||||
|
||||
authentication_generate_access_token_service = AuthenticationGenerateAccessTokenService()
|
||||
|
||||
# generate a new access token
|
||||
access_token = authentication_generate_access_token_service.execute(payload)
|
||||
|
||||
return access_token
|
||||
|
|
|
@ -31,6 +31,8 @@ from .handlers.account.provider.set_status import SetStatusActiveProviderAccount
|
|||
from .handlers.account.provider.change_password import ChangePasswordProviderAccountHandler
|
||||
from .handlers.account.provider.remove import RemoveProviderAccountHandler
|
||||
|
||||
from .handlers.account.session.get_all import GetAllSessionAccountHandler
|
||||
|
||||
from .handlers.ticket.create import CreateTicketHandler
|
||||
from .handlers.ticket.get import GetTicketHandler
|
||||
from .handlers.ticket.get_all import GetAllTicketHandler
|
||||
|
@ -139,6 +141,9 @@ class APIv1:
|
|||
(r"/account/provider/change_password", ChangePasswordProviderAccountHandler),
|
||||
(r"/account/provider/remove", RemoveProviderAccountHandler),
|
||||
|
||||
# sessions
|
||||
(r"/account/session/get/all", GetAllSessionAccountHandler),
|
||||
|
||||
# blocking ticket management
|
||||
(r"/ticket/create", CreateTicketHandler),
|
||||
(r"/ticket/get", GetTicketHandler),
|
||||
|
|
Loading…
Reference in a new issue