mirror of
https://github.com/GSA/notifications-api.git
synced 2026-02-01 15:46:07 -05:00
Merge pull request #1386 from GSA/USN-COMPLY-51-Verify_State
Verify state for login.gov
This commit is contained in:
@@ -373,7 +373,7 @@ def add_user_to_service(service_id, user_id):
|
|||||||
service = dao_fetch_service_by_id(service_id)
|
service = dao_fetch_service_by_id(service_id)
|
||||||
user = get_user_by_id(user_id=user_id)
|
user = get_user_by_id(user_id=user_id)
|
||||||
if user in service.users:
|
if user in service.users:
|
||||||
error = "User id: {} already part of service id: {}".format(user_id, service_id)
|
error = f"User id: {user_id} already part of service id: {service_id}"
|
||||||
raise InvalidRequest(error, status_code=400)
|
raise InvalidRequest(error, status_code=400)
|
||||||
|
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import base64
|
import base64
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
from urllib.parse import unquote
|
||||||
|
|
||||||
from flask import Blueprint, current_app, jsonify, request
|
from flask import Blueprint, current_app, jsonify, request
|
||||||
from itsdangerous import BadData, SignatureExpired
|
from itsdangerous import BadData, SignatureExpired
|
||||||
@@ -32,7 +33,7 @@ service_invite = Blueprint("service_invite", __name__)
|
|||||||
register_errors(service_invite)
|
register_errors(service_invite)
|
||||||
|
|
||||||
|
|
||||||
def _create_service_invite(invited_user, nonce):
|
def _create_service_invite(invited_user, nonce, state):
|
||||||
|
|
||||||
template_id = current_app.config["INVITATION_EMAIL_TEMPLATE_ID"]
|
template_id = current_app.config["INVITATION_EMAIL_TEMPLATE_ID"]
|
||||||
|
|
||||||
@@ -52,13 +53,14 @@ def _create_service_invite(invited_user, nonce):
|
|||||||
data["invited_user_id"] = str(invited_user.id)
|
data["invited_user_id"] = str(invited_user.id)
|
||||||
data["invited_user_email"] = invited_user.email_address
|
data["invited_user_email"] = invited_user.email_address
|
||||||
|
|
||||||
|
invite_redis_key = f"invite-data-{unquote(state)}"
|
||||||
|
redis_store.set(invite_redis_key, get_user_data_url_safe(data))
|
||||||
|
|
||||||
url = os.environ["LOGIN_DOT_GOV_REGISTRATION_URL"]
|
url = os.environ["LOGIN_DOT_GOV_REGISTRATION_URL"]
|
||||||
|
|
||||||
url = url.replace("NONCE", nonce) # handed from data sent from admin.
|
url = url.replace("NONCE", nonce) # handed from data sent from admin.
|
||||||
|
|
||||||
user_data_url_safe = get_user_data_url_safe(data)
|
url = url.replace("STATE", state)
|
||||||
|
|
||||||
url = url.replace("STATE", user_data_url_safe)
|
|
||||||
|
|
||||||
personalisation = {
|
personalisation = {
|
||||||
"user_name": invited_user.from_user.name,
|
"user_name": invited_user.from_user.name,
|
||||||
@@ -85,6 +87,8 @@ def _create_service_invite(invited_user, nonce):
|
|||||||
)
|
)
|
||||||
send_notification_to_queue(saved_notification, queue=QueueNames.NOTIFY)
|
send_notification_to_queue(saved_notification, queue=QueueNames.NOTIFY)
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
@service_invite.route("/service/<service_id>/invite", methods=["POST"])
|
@service_invite.route("/service/<service_id>/invite", methods=["POST"])
|
||||||
def create_invited_user(service_id):
|
def create_invited_user(service_id):
|
||||||
@@ -94,13 +98,18 @@ def create_invited_user(service_id):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
current_app.logger.exception("nonce not found in submitted data.")
|
current_app.logger.exception("nonce not found in submitted data.")
|
||||||
raise
|
raise
|
||||||
|
try:
|
||||||
|
state = request_json.pop("state")
|
||||||
|
except KeyError:
|
||||||
|
current_app.logger.exception("state not found in submitted data.")
|
||||||
|
raise
|
||||||
|
|
||||||
invited_user = invited_user_schema.load(request_json)
|
invited_user = invited_user_schema.load(request_json)
|
||||||
save_invited_user(invited_user)
|
save_invited_user(invited_user)
|
||||||
|
|
||||||
_create_service_invite(invited_user, nonce)
|
invite_data = _create_service_invite(invited_user, nonce, state)
|
||||||
|
|
||||||
return jsonify(data=invited_user_schema.dump(invited_user)), 201
|
return jsonify(data=invited_user_schema.dump(invited_user), invite=invite_data), 201
|
||||||
|
|
||||||
|
|
||||||
@service_invite.route("/service/<service_id>/invite/expired", methods=["GET"])
|
@service_invite.route("/service/<service_id>/invite/expired", methods=["GET"])
|
||||||
@@ -148,6 +157,18 @@ def resend_service_invite(service_id, invited_user_id):
|
|||||||
Note:
|
Note:
|
||||||
This ignores the POST data entirely.
|
This ignores the POST data entirely.
|
||||||
"""
|
"""
|
||||||
|
request_json = request.get_json()
|
||||||
|
try:
|
||||||
|
nonce = request_json.pop("nonce")
|
||||||
|
except KeyError:
|
||||||
|
current_app.logger.exception("nonce not found in submitted data.")
|
||||||
|
raise
|
||||||
|
try:
|
||||||
|
state = request_json.pop("state")
|
||||||
|
except KeyError:
|
||||||
|
current_app.logger.exception("state not found in submitted data.")
|
||||||
|
raise
|
||||||
|
|
||||||
fetched = get_expired_invite_by_service_and_id(
|
fetched = get_expired_invite_by_service_and_id(
|
||||||
service_id=service_id,
|
service_id=service_id,
|
||||||
invited_user_id=invited_user_id,
|
invited_user_id=invited_user_id,
|
||||||
@@ -161,9 +182,9 @@ def resend_service_invite(service_id, invited_user_id):
|
|||||||
|
|
||||||
save_invited_user(update_dict)
|
save_invited_user(update_dict)
|
||||||
|
|
||||||
_create_service_invite(fetched, current_app.config["ADMIN_BASE_URL"])
|
invite_data = _create_service_invite(fetched, nonce, state)
|
||||||
|
|
||||||
return jsonify(data=invited_user_schema.dump(fetched)), 200
|
return jsonify(data=invited_user_schema.dump(fetched), invite=invite_data), 200
|
||||||
|
|
||||||
|
|
||||||
def invited_user_url(invited_user_id, invite_link_host=None):
|
def invited_user_url(invited_user_id, invite_link_host=None):
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ def test_create_invited_user(
|
|||||||
auth_type=AuthType.EMAIL,
|
auth_type=AuthType.EMAIL,
|
||||||
folder_permissions=["folder_1", "folder_2", "folder_3"],
|
folder_permissions=["folder_1", "folder_2", "folder_3"],
|
||||||
nonce="FakeNonce",
|
nonce="FakeNonce",
|
||||||
|
state="FakeState",
|
||||||
**extra_args,
|
**extra_args,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -110,6 +111,7 @@ def test_create_invited_user_without_auth_type(
|
|||||||
"permissions": "send_messages,manage_service,manage_api_keys",
|
"permissions": "send_messages,manage_service,manage_api_keys",
|
||||||
"folder_permissions": [],
|
"folder_permissions": [],
|
||||||
"nonce": "FakeNonce",
|
"nonce": "FakeNonce",
|
||||||
|
"state": "FakeState",
|
||||||
}
|
}
|
||||||
|
|
||||||
json_resp = admin_request.post(
|
json_resp = admin_request.post(
|
||||||
@@ -134,6 +136,7 @@ def test_create_invited_user_invalid_email(client, sample_service, mocker, fake_
|
|||||||
"permissions": "send_messages,manage_service,manage_api_keys",
|
"permissions": "send_messages,manage_service,manage_api_keys",
|
||||||
"folder_permissions": [fake_uuid, fake_uuid],
|
"folder_permissions": [fake_uuid, fake_uuid],
|
||||||
"nonce": "FakeNonce",
|
"nonce": "FakeNonce",
|
||||||
|
"state": "FakeState",
|
||||||
}
|
}
|
||||||
|
|
||||||
data = json.dumps(data)
|
data = json.dumps(data)
|
||||||
@@ -235,6 +238,7 @@ def test_resend_expired_invite(
|
|||||||
response = client.post(
|
response = client.post(
|
||||||
url,
|
url,
|
||||||
headers=[("Content-Type", "application/json"), auth_header],
|
headers=[("Content-Type", "application/json"), auth_header],
|
||||||
|
data='{"nonce": "FakeNonce", "state": "FakeState"}',
|
||||||
)
|
)
|
||||||
|
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|||||||
Reference in New Issue
Block a user