Skip to content

Feature/single letters - #49

Open
ghbm-itk wants to merge 30 commits into
developfrom
feature/single-letters
Open

Feature/single letters#49
ghbm-itk wants to merge 30 commits into
developfrom
feature/single-letters

Conversation

@ghbm-itk

@ghbm-itk ghbm-itk commented Jul 29, 2026

Copy link
Copy Markdown
Member

Added

  • API endpoint for sending single letters without a shipment.
  • Admin page for viewing api letters and deactivating api users.
  • Added get_pdf param to get_letter api endpoint to allow not downloading letter files.

Changed

  • Added created_by and post_type to letters db table to support single letters.
  • Made shipment_id nullable in letters db table.
  • Api users can not be deleted if any letters are attached to them.
  • Added indexes to the letters, nemsms messages and registration tasks db tables.

ghbm-itk and others added 27 commits July 27, 2026 13:01
Eight files had been committed with CRLF line endings, which made their
diffs unreviewable (send_post.py showed 896 changed lines with no actual
content change). Renormalized with `git add --renormalize`; this commit
changes line endings only.

Root cause was core.autocrlf=false locally, which commits worktree bytes
verbatim. Now set to `input` globally so CRLF is normalized on commit
while nothing is converted on checkout.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ghbm-itk
ghbm-itk requested a review from jekuaitk July 29, 2026 08:27

@jekuaitk jekuaitk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple suggestions and questions otherwise good!

Comment on lines +15 to +23
def check_bearer_token(credentials: HTTPAuthorizationCredentials = Depends(security_scheme)) -> dict[str, str]:
"""Check the validity of an incoming bearer JWT token."""
try:
payload = jwt.decode(credentials.credentials, config.API_JWT_SECRET, algorithms=["HS256"])
return payload
except jwt.ExpiredSignatureError:
raise HTTPException(401, "Token expired") # pylint: disable=raise-missing-from
except jwt.InvalidTokenError:
raise HTTPException(401, "Invalid token") # pylint: disable=raise-missing-from

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also check whether the api user is active? Seems like a deactivated API-user can keep using an already issued JWT until it expires, that is worst case up to api_token_lifetime_seconds.



@router.get("/letter/{letter_id}", tags=["Letters"])
def get_letter(letter_id: str, get_pdf: bool = True) -> LetterDetail:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like any API-user can fetch any letter (provided they know their id). Is this on purpose?

Comment on lines +301 to +305
for letter in letters:
document_storage.delete_single_letter_doc(letter.id)
session.delete(letter)

session.commit()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to re-order this such that the actual document are only deleted after committing? Perhaps even collecting the letter ids in a list and then deleting them after a single commit?

Suggested change
for letter in letters:
document_storage.delete_single_letter_doc(letter.id)
session.delete(letter)
session.commit()
for letter in letters:
session.delete(letter)
session.commit()
document_storage.delete_single_letter_doc(letter.id)

return tuple(result)


def get_api_user(id: str) -> ApiUser:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this not be

Suggested change
def get_api_user(id: str) -> ApiUser:
def get_api_user(id: str) -> ApiUser | None:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants