55from flask import request
66from flask import url_for
77from pydantic import ValidationError
8+ from werkzeug .exceptions import HTTPException
89from werkzeug .exceptions import PreconditionFailed
910from werkzeug .routing import BaseConverter
1011from werkzeug .routing import ValidationError as RoutingValidationError
@@ -51,13 +52,13 @@ def resource_location(app_record):
5152
5253
5354# -- etag-start --
54- def check_etag (record , if_match ):
55- """Compare the record's ETag against an ``If-Match`` header value .
55+ def check_etag (record ):
56+ """Compare the record's ETag against the ``If-Match`` request header .
5657
5758 :param record: The application record.
58- :param if_match: Raw ``If-Match`` header value, or :data:`None`.
5959 :raises ~werkzeug.exceptions.PreconditionFailed: If the header is present and does not match.
6060 """
61+ if_match = request .headers .get ("If-Match" )
6162 if not if_match :
6263 return
6364 if if_match .strip () == "*" :
@@ -100,11 +101,11 @@ def handle_validation_error(error):
100101 return scim_error .model_dump_json (), scim_error .status
101102
102103
103- @bp .errorhandler (404 )
104- def handle_not_found (error ):
105- """Turn Flask 404 errors into SCIM error responses."""
106- scim_error = Error (status = 404 , detail = str (error .description ))
107- return scim_error .model_dump_json (), HTTPStatus . NOT_FOUND
104+ @bp .errorhandler (HTTPException )
105+ def handle_http_error (error ):
106+ """Turn HTTP errors into SCIM error responses."""
107+ scim_error = Error (status = error . code , detail = str (error .description ))
108+ return scim_error .model_dump_json (), error . code
108109
109110
110111@bp .errorhandler (SCIMException )
@@ -114,13 +115,6 @@ def handle_scim_error(error):
114115 return scim_error .model_dump_json (), scim_error .status
115116
116117
117- @bp .errorhandler (PreconditionFailed )
118- def handle_precondition_failed (error ):
119- """Turn ETag mismatches into SCIM 412 responses."""
120- scim_error = Error (status = 412 , detail = "ETag mismatch" )
121- return scim_error .model_dump_json (), HTTPStatus .PRECONDITION_FAILED
122-
123-
124118# -- error-handlers-end --
125119# -- refinements-end --
126120
@@ -152,7 +146,7 @@ def get_user(app_record):
152146@bp .patch ("/Users/<user:app_record>" )
153147def patch_user (app_record ):
154148 """Apply a SCIM PatchOp to an existing user."""
155- check_etag (app_record , request . headers . get ( "If-Match" ) )
149+ check_etag (app_record )
156150 scim_user = to_scim_user (app_record , resource_location (app_record ))
157151 patch = PatchOp [User ].model_validate (
158152 request .get_json (),
@@ -177,7 +171,7 @@ def patch_user(app_record):
177171@bp .put ("/Users/<user:app_record>" )
178172def replace_user (app_record ):
179173 """Replace an existing user with a full SCIM resource."""
180- check_etag (app_record , request . headers . get ( "If-Match" ) )
174+ check_etag (app_record )
181175 existing_user = to_scim_user (app_record , resource_location (app_record ))
182176 replacement = User .model_validate (
183177 request .get_json (),
@@ -204,7 +198,7 @@ def replace_user(app_record):
204198@bp .delete ("/Users/<user:app_record>" )
205199def delete_user (app_record ):
206200 """Delete an existing user."""
207- check_etag (app_record , request . headers . get ( "If-Match" ) )
201+ check_etag (app_record )
208202 delete_record (app_record ["id" ])
209203 return "" , HTTPStatus .NO_CONTENT
210204
0 commit comments