-
-
Notifications
You must be signed in to change notification settings - Fork 50
Add anonymous URL ownership claim via manage_token #134
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
0f4dd02
ff619e7
a60e3bf
d6a27e9
6414c94
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| """ | ||
| POST /api/v1/claim — claim ownership of an anonymously created URL. | ||
|
|
||
| Transfers a URL from anonymous ownership to the authenticated user, | ||
| consuming and invalidating the one-time manage_token in the process. | ||
| """ | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| from fastapi import APIRouter, Depends, HTTPException, Request | ||
| from pydantic import BaseModel, Field | ||
|
|
||
| from dependencies import CurrentUser, get_url_service, require_auth | ||
| from middleware.rate_limiter import Limits, dynamic_limit, limiter | ||
| from services.url_service import UrlService | ||
|
|
||
| router = APIRouter(tags=["URL Management"]) | ||
|
|
||
| _claim_limit, _claim_key = dynamic_limit(Limits.API_AUTHED, Limits.API_AUTHED) | ||
|
|
||
|
revanthlol marked this conversation as resolved.
|
||
|
|
||
| class ClaimUrlRequest(BaseModel): | ||
| alias: str = Field(..., description="The short alias to claim.") | ||
| manage_token: str = Field(..., description="The one-time token returned at creation.") | ||
|
|
||
|
|
||
| class ClaimUrlResponse(BaseModel): | ||
| success: bool | ||
| message: str | ||
|
|
||
|
|
||
| @router.post( | ||
| "/claim", | ||
| status_code=200, | ||
| operation_id="claimUrl", | ||
| summary="Claim Anonymous URL", | ||
| ) | ||
| @limiter.limit(_claim_limit, key_func=_claim_key) | ||
| async def claim_url( | ||
| request: Request, | ||
| body: ClaimUrlRequest, | ||
| user: CurrentUser = Depends(require_auth), | ||
| url_service: UrlService = Depends(get_url_service), | ||
| ) -> ClaimUrlResponse: | ||
| """ | ||
| Transfer ownership of an anonymously created URL to your account. | ||
|
|
||
| The manage_token is single-use and is invalidated immediately on success. | ||
| Returns 403 if the token is wrong, 409 if already claimed, 404 if not found. | ||
|
revanthlol marked this conversation as resolved.
|
||
| """ | ||
|
Comment on lines
+47
to
+52
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Docstring is inconsistent with actual implementation. The docstring states "Returns 403 if the token is wrong, 409 if already claimed, 404 if not found" but the implementation correctly returns 403 for all failure cases (to avoid oracle attacks). Update the docstring to match the actual behavior. 📝 Proposed fix """
Transfer ownership of an anonymously created URL to your account.
The manage_token is single-use and is invalidated immediately on success.
- Returns 403 if the token is wrong, 409 if already claimed, 404 if not found.
+ Returns 403 if the claim fails (wrong token, already claimed, or URL not found).
"""🤖 Prompt for AI Agents |
||
| claimed = await url_service.claim_url( | ||
| alias=body.alias, | ||
| raw_token=body.manage_token, | ||
| new_owner_id=user.user_id, | ||
| ) | ||
| if not claimed: | ||
| # Don't distinguish between wrong token / already claimed / not found | ||
| # to avoid oracle attacks. | ||
| raise HTTPException( | ||
| status_code=403, | ||
| detail="Invalid token or URL is not claimable.", | ||
| ) | ||
| return ClaimUrlResponse(success=True, message="URL successfully claimed.") | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Claiming should normalize
private_statswhen ownership changes.Anonymous URLs are created with
private_stats=Noneinservices/url_service.py, Line 235-237, andcheck_stats_privacy()treatsNoneas public. This update transfers ownership but leaves that field untouched, so claimed links stay public and violate theUrlV2Docinvariant fromschemas/models/url.py, Line 48.🤖 Prompt for AI Agents