Skip to content

Commit

Permalink
social_login and logout in auditlogs (#1593)
Browse files Browse the repository at this point in the history
* added code for logging logout and sso_login entities in audit logs and added test cases related to the same.

* changed sso_login to social_login
  • Loading branch information
maheshsattala authored Nov 13, 2024
1 parent 997fef9 commit c7fd7a5
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 2 deletions.
17 changes: 16 additions & 1 deletion kairon/api/app/routers/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
from starlette.requests import Request

from kairon.idp.processor import IDPProcessor
from kairon.shared.account.activity_log import UserActivityLogger
from kairon.shared.data.utils import DataUtility
from kairon.shared.organization.processor import OrgProcessor
from kairon.shared.utils import Utility, MailUtility
from kairon.shared.auth import Authentication
from kairon.api.models import Response, IntegrationRequest, RecaptchaVerifiedOAuth2PasswordRequestForm
from kairon.shared.authorization.processor import IntegrationProcessor
from kairon.shared.constants import ADMIN_ACCESS, TESTER_ACCESS
from kairon.shared.constants import ADMIN_ACCESS, TESTER_ACCESS, UserActivityType
from kairon.shared.data.constant import ACCESS_ROLES, TOKEN_TYPE
from kairon.shared.models import User

Expand Down Expand Up @@ -164,13 +165,27 @@ async def sso_callback(
MailUtility.format_and_send_mail, mail_type='password_generated', email=user_details['email'],
first_name=user_details['first_name'], password=user_details['password'].get_secret_value()
)
UserActivityLogger.add_log(a_type=UserActivityType.social_login.value, email=user_details['email'],
data={"username": user_details['email'], "sso_type": sso_type})
return {
"data": {"access_token": access_token, "token_type": "bearer"},
"message": """It is your responsibility to keep the token secret.
If leaked then other may have access to your system.""",
}


@router.post("/logout", response_model=Response)
async def logout(
current_user: User = Depends(Authentication.get_current_user)
):
"""
Invalidate user session and revoke authentication token upon successful logout.
"""
UserActivityLogger.add_log(a_type=UserActivityType.logout.value, account=current_user.account,
email=current_user.email, data={"username": current_user.email})
return Response(message="User Logged out!")


@router.get('/login/idp/{realm_name}')
async def idp_login(
realm_name: str = Path(description="Domain name for your company", examples=["KAIRON"])):
Expand Down
2 changes: 2 additions & 0 deletions kairon/shared/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ class UserActivityType(str, Enum):
delete_asset = "delete_asset"
link_usage = "link_usage"
login = 'login'
social_login = 'social_login'
logout = 'logout'
login_refresh_token = "login_refresh_token"
invalid_login = 'invalid_login'
download = "download"
Expand Down
71 changes: 70 additions & 1 deletion tests/integration_test/services_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1345,6 +1345,38 @@ def test_add_scheduled_broadcast_with_no_language_code(mock_event_server):
assert not actual["data"]


def test_logout():
response = client.post(
"/api/auth/login",
data={"username": "[email protected]", "password": "Welcome@10"},
)
actual = response.json()
assert actual["success"]
assert actual["error_code"] == 0

access_token = actual["data"]["access_token"]
token_type = actual["data"]["token_type"]
response = client.post(
url=f"/api/auth/logout",
headers={"Authorization": token_type + " " + access_token},
)
actual = response.json()
print(actual)
assert actual["success"]
assert actual["message"] == "User Logged out!"
assert not actual["data"]
assert actual["error_code"] == 0

values = list(AuditLogData.objects(user="[email protected]", action='activity', entity='logout').order_by(
"-timestamp"))
audit_log_data = values[0].to_mongo().to_dict()
print(audit_log_data)
assert audit_log_data["action"] == 'activity'
assert audit_log_data['entity'] == 'logout'
assert audit_log_data['user'] == '[email protected]'
assert audit_log_data['data']['username'] == '[email protected]'


@responses.activate
def test_default_values():
response = client.get(
Expand Down Expand Up @@ -21250,8 +21282,18 @@ def test_sso_get_login_token_invalid_type():


def test_sso_get_login_token(monkeypatch):
token = "fgyduhsaifusijfisofwh87eyfhw98yqwhfc8wufchwufehwncj"

async def __mock_verify_and_process(*args, **kwargs):
return True, {}, "fgyduhsaifusijfisofwh87eyfhw98yqwhfc8wufchwufehwncj"
return (
False,
{
"email": "[email protected]",
"first_name": "new",
"password": SecretStr("123456789"),
},
token,
)

monkeypatch.setattr(Authentication, "verify_and_process", __mock_verify_and_process)
response = client.get(
Expand All @@ -21266,6 +21308,15 @@ async def __mock_verify_and_process(*args, **kwargs):
)
assert actual["success"]
assert actual["error_code"] == 0
values = list(AuditLogData.objects(user="[email protected]", action='activity', entity='social_login').order_by(
"-timestamp"))
audit_log_data = values[0].to_mongo().to_dict()
assert audit_log_data['user'] == '[email protected]'
assert audit_log_data["attributes"] == [{'key': 'email', 'value': '[email protected]'}]
assert audit_log_data["action"] == 'activity'
assert audit_log_data['entity'] == 'social_login'
assert audit_log_data['data']['username'] == '[email protected]'
assert audit_log_data['data']['sso_type'] == 'google'

response = client.get(
url=f"/api/auth/login/sso/callback/linkedin?code=123456789",
Expand All @@ -21280,6 +21331,15 @@ async def __mock_verify_and_process(*args, **kwargs):
)
assert actual["success"]
assert actual["error_code"] == 0
values = list(AuditLogData.objects(user="[email protected]", action='activity', entity='social_login').order_by(
"-timestamp"))
audit_log_data = values[0].to_mongo().to_dict()
assert audit_log_data['user'] == '[email protected]'
assert audit_log_data["attributes"] == [{'key': 'email', 'value': '[email protected]'}]
assert audit_log_data["action"] == 'activity'
assert audit_log_data['entity'] == 'social_login'
assert audit_log_data['data']['username'] == '[email protected]'
assert audit_log_data['data']['sso_type'] == 'linkedin'

response = client.get(
url=f"/api/auth/login/sso/callback/facebook?code=123456789",
Expand All @@ -21294,6 +21354,15 @@ async def __mock_verify_and_process(*args, **kwargs):
)
assert actual["success"]
assert actual["error_code"] == 0
values = list(AuditLogData.objects(user="[email protected]", action='activity', entity='social_login').order_by(
"-timestamp"))
audit_log_data = values[0].to_mongo().to_dict()
assert audit_log_data['user'] == '[email protected]'
assert audit_log_data["attributes"] == [{'key': 'email', 'value': '[email protected]'}]
assert audit_log_data["action"] == 'activity'
assert audit_log_data['entity'] == 'social_login'
assert audit_log_data['data']['username'] == '[email protected]'
assert audit_log_data['data']['sso_type'] == 'facebook'


def test_trigger_mail_on_new_signup_with_sso(monkeypatch):
Expand Down

0 comments on commit c7fd7a5

Please sign in to comment.