|
18 | 18 | from ....admin.request_context import AdminRequestContext |
19 | 19 | from ....messaging.models.base import BaseModelError |
20 | 20 | from ....messaging.models.openapi import OpenAPISchema |
| 21 | +from ....messaging.models.paginated_query import PaginatedQuerySchema, get_limit_offset |
21 | 22 | from ....messaging.valid import UUID4_EXAMPLE, UUID4_VALIDATE |
22 | 23 | from ....storage.error import StorageError, StorageNotFoundError |
23 | 24 | from ...didcomm_prefix import DIDCommPrefix |
|
26 | 27 | from .message_types import SPEC_URI |
27 | 28 | from .messages.invitation import HSProto, InvitationMessage, InvitationMessageSchema |
28 | 29 | from .models.invitation import InvitationRecordSchema |
29 | | -from .models.oob_record import OobRecordSchema |
| 30 | +from .models.oob_record import OobRecord, OobRecordSchema |
30 | 31 |
|
31 | 32 | LOGGER = logging.getLogger(__name__) |
32 | 33 |
|
@@ -217,6 +218,106 @@ class InvitationRecordMatchInfoSchema(OpenAPISchema): |
217 | 218 | ) |
218 | 219 |
|
219 | 220 |
|
| 221 | +class OobRecordListQueryStringSchema(PaginatedQuerySchema): |
| 222 | + """Parameters and validators for OOB record list request query string.""" |
| 223 | + |
| 224 | + state = fields.Str( |
| 225 | + required=False, |
| 226 | + validate=validate.OneOf( |
| 227 | + OobRecord.get_attributes_by_prefix("STATE_", walk_mro=True) |
| 228 | + ), |
| 229 | + metadata={ |
| 230 | + "description": "OOB record state", |
| 231 | + "example": OobRecord.STATE_INITIAL, |
| 232 | + }, |
| 233 | + ) |
| 234 | + role = fields.Str( |
| 235 | + required=False, |
| 236 | + validate=validate.OneOf( |
| 237 | + OobRecord.get_attributes_by_prefix("ROLE_", walk_mro=False) |
| 238 | + ), |
| 239 | + metadata={ |
| 240 | + "description": "OOB record role", |
| 241 | + "example": OobRecord.ROLE_SENDER, |
| 242 | + }, |
| 243 | + ) |
| 244 | + connection_id = fields.Str( |
| 245 | + required=False, |
| 246 | + validate=UUID4_VALIDATE, |
| 247 | + metadata={ |
| 248 | + "description": "Connection identifier", |
| 249 | + "example": UUID4_EXAMPLE, |
| 250 | + }, |
| 251 | + ) |
| 252 | + invi_msg_id = fields.Str( |
| 253 | + required=False, |
| 254 | + validate=UUID4_VALIDATE, |
| 255 | + metadata={ |
| 256 | + "description": "Invitation message identifier", |
| 257 | + "example": UUID4_EXAMPLE, |
| 258 | + }, |
| 259 | + ) |
| 260 | + |
| 261 | + |
| 262 | +class OobRecordListSchema(OpenAPISchema): |
| 263 | + """Result schema for OOB record list.""" |
| 264 | + |
| 265 | + results = fields.List( |
| 266 | + fields.Nested(OobRecordSchema()), |
| 267 | + required=True, |
| 268 | + metadata={"description": "List of OOB records"}, |
| 269 | + ) |
| 270 | + |
| 271 | + |
| 272 | +@docs( |
| 273 | + tags=["out-of-band"], |
| 274 | + summary="Query OOB records", |
| 275 | +) |
| 276 | +@querystring_schema(OobRecordListQueryStringSchema()) |
| 277 | +@response_schema(OobRecordListSchema(), 200, description="") |
| 278 | +@tenant_authentication |
| 279 | +async def oob_records_list(request: web.BaseRequest): |
| 280 | + """Request handler for searching OOB records. |
| 281 | +
|
| 282 | + Args: |
| 283 | + request: aiohttp request object |
| 284 | +
|
| 285 | + Returns: |
| 286 | + The OOB record list response |
| 287 | +
|
| 288 | + """ |
| 289 | + context: AdminRequestContext = request["context"] |
| 290 | + |
| 291 | + tag_filter = { |
| 292 | + k: request.query[k] |
| 293 | + for k in ("connection_id", "invi_msg_id") |
| 294 | + if request.query.get(k, "") != "" |
| 295 | + } |
| 296 | + post_filter = { |
| 297 | + k: request.query[k] |
| 298 | + for k in ("state", "role") |
| 299 | + if request.query.get(k, "") != "" |
| 300 | + } |
| 301 | + |
| 302 | + limit, offset = get_limit_offset(request) |
| 303 | + |
| 304 | + profile = context.profile |
| 305 | + try: |
| 306 | + async with profile.session() as session: |
| 307 | + records = await OobRecord.query( |
| 308 | + session, |
| 309 | + tag_filter, |
| 310 | + limit=limit, |
| 311 | + offset=offset, |
| 312 | + post_filter_positive=post_filter, |
| 313 | + ) |
| 314 | + results = [record.serialize() for record in records] |
| 315 | + except (StorageError, BaseModelError) as err: |
| 316 | + raise web.HTTPBadRequest(reason=err.roll_up) from err |
| 317 | + |
| 318 | + return web.json_response({"results": results}) |
| 319 | + |
| 320 | + |
220 | 321 | @docs( |
221 | 322 | tags=["out-of-band"], |
222 | 323 | summary="Create a new connection invitation", |
@@ -365,6 +466,11 @@ async def register(app: web.Application): |
365 | 466 | [ |
366 | 467 | web.post("/out-of-band/create-invitation", invitation_create), |
367 | 468 | web.post("/out-of-band/receive-invitation", invitation_receive), |
| 469 | + web.get( |
| 470 | + "/out-of-band/records", |
| 471 | + oob_records_list, |
| 472 | + allow_head=False, |
| 473 | + ), |
368 | 474 | web.delete("/out-of-band/invitations/{invi_msg_id}", invitation_remove), |
369 | 475 | ] |
370 | 476 | ) |
|
0 commit comments