Skip to content

Commit dc0b326

Browse files
committed
Validate format of tags to be max 255 characters and with certain characters
Match up tag validations that came in with the main project here [1]. The multi insertion queries use commas to split tags during batch inserts, so it's important that incoming tags don't have comms of their own. [1] riverqueue/river#351
1 parent e4947c9 commit dc0b326

File tree

2 files changed

+33
-1
lines changed

2 files changed

+33
-1
lines changed

src/riverqueue/client.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from dataclasses import dataclass
22
from datetime import datetime, timezone, timedelta
3+
import re
34
from typing import (
45
Any,
56
Awaitable,
@@ -320,7 +321,7 @@ def _make_insert_params(
320321
queue=insert_opts.queue or args_insert_opts.queue or QUEUE_DEFAULT,
321322
scheduled_at=scheduled_at and scheduled_at.astimezone(timezone.utc),
322323
state="scheduled" if scheduled_at else "available",
323-
tags=insert_opts.tags or args_insert_opts.tags or [],
324+
tags=_validate_tags(insert_opts.tags or args_insert_opts.tags or []),
324325
)
325326

326327
return insert_params, unique_opts
@@ -348,3 +349,14 @@ def _truncate_time(time, interval_seconds) -> datetime:
348349
def _uint64_to_int64(uint64):
349350
# Packs a uint64 then unpacks to int64 to fit within Postgres bigint
350351
return (uint64 + (1 << 63)) % (1 << 64) - (1 << 63)
352+
353+
354+
tag_re = re.compile("\A[\w][\w\-]+[\w]\Z")
355+
356+
357+
def _validate_tags(tags: list[str]) -> list[str]:
358+
for tag in tags:
359+
assert (
360+
len(tag) <= 255 and tag_re.match(tag)
361+
), f"tags should be less than 255 characters in length and match regex {tag_re.pattern}"
362+
return tags

tests/client_test.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,26 @@ def to_json() -> None:
259259
assert "args should return non-nil from `to_json`" == str(ex.value)
260260

261261

262+
def test_tag_validation(client):
263+
client.insert(
264+
SimpleArgs(), insert_opts=InsertOpts(tags=["foo", "bar", "baz", "foo-bar-baz"])
265+
)
266+
267+
with pytest.raises(AssertionError) as ex:
268+
client.insert(SimpleArgs(), insert_opts=InsertOpts(tags=["commas,bad"]))
269+
assert (
270+
"tags should be less than 255 characters in length and match regex \A[\w][\w\-]+[\w]\Z"
271+
== str(ex.value)
272+
)
273+
274+
with pytest.raises(AssertionError) as ex:
275+
client.insert(SimpleArgs(), insert_opts=InsertOpts(tags=["a" * 256]))
276+
assert (
277+
"tags should be less than 255 characters in length and match regex \A[\w][\w\-]+[\w]\Z"
278+
== str(ex.value)
279+
)
280+
281+
262282
def test_check_advisory_lock_prefix_bounds():
263283
Client(mock_driver, advisory_lock_prefix=123)
264284

0 commit comments

Comments
 (0)