Commit Graph

750 Commits

Author SHA1 Message Date
MingxuanGame
c0575f3274 fix(beatmapset): handle 404 errors and fix qualified sync from add_missing_beatmapsets 2025-10-07 17:40:50 +00:00
MingxuanGame
c76d6163ac fix(sync): cannot qualified beatmapset 2025-10-07 17:05:33 +00:00
MingxuanGame
fa81f837a0 fix(score): don't unpin score 2025-10-07 15:53:04 +00:00
MingxuanGame
64e221c641 perf(beatmapset): optimize beatmap fetching 2025-10-07 15:27:06 +00:00
MingxuanGame
60049a777f feat(auth): support change password 2025-10-07 13:07:14 +00:00
MingxuanGame
95f7c010af fix(trusted-device): no location in response 2025-10-07 12:18:56 +00:00
MingxuanGame
10caa82320 feat(user-preference): add user preference support (#55)
APIs:

- GET `/api/private/user/preferences`: Get current user's preferences.
- PATCH `/api/private/user/preferences`: Modify current user's preferences. (body: Preferences)
- PUT `/api/private/user/preferences`: Overwrite current user's preferences. (body: Preferences)
- DELETE `/api/private/user/preferences`: Reset current user's preferences. (body: list[str])
  - body specifies the content to be reset. If body is empty, reset all preferences.

User:

- `User.g0v0_playmode`: show the special ruleset like `OSURX`, and custom rulesets in the future.

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-06 20:57:17 +08:00
MingxuanGame
febc1d761f feat(user): implement user restrictions
## APIs Restricted for Restricted Users

A restricted user is blocked from performing the following actions, and will typically receive a `403 Forbidden` error:

*   **Chat & Notifications:**
    *   Sending any chat messages (public or private).
    *   Joining or leaving chat channels.
    *   Creating new PM channels.
*   **User Profile & Content:**
    *   Uploading a new avatar.
    *   Uploading a new profile cover image.
    *   Changing their username.
    *   Updating their userpage content.
*   **Scores & Gameplay:**
    *   Submitting scores in multiplayer rooms.
    *   Deleting their own scores (to prevent hiding evidence of cheating).
*   **Beatmaps:**
    *   Rating beatmaps.
    *   Taging beatmaps.
*   **Relationship:**
    *   Adding friends or blocking users.
    *   Removing friends or unblocking users.
*   **Teams:**
    *   Creating, updating, or deleting a team.
    *   Requesting to join a team.
    *   Handling join requests for a team they manage.
    *   Kicking a member from a team they manage.
*   **Multiplayer:**
    *   Creating or deleting multiplayer rooms.
    *   Joining or leaving multiplayer rooms.

## What is Invisible to Normal Users

*   **Leaderboards:**
    *   Beatmap leaderboards.
    *   Multiplayer (playlist) room leaderboards.
*   **User Search/Lists:**
    *   Restricted users will not appear in the results of the `/api/v2/users` endpoint.
    *   They will not appear in the list of a team's members.
*   **Relationship:**
    *   They will not appear in a user's friend list (`/friends`).
*   **Profile & History:**
    *   Attempting to view a restricted user's profile, events, kudosu history, or score history will result in a `404 Not Found` error, effectively making their profile invisible (unless the user viewing the profile is the restricted user themselves).
*   **Chat:**
    *   Normal users cannot start a new PM with a restricted user (they will get a `404 Not Found` error).
*   **Ranking:**
    *   Restricted users are excluded from any rankings.

### How to Restrict a User

Insert into `user_account_history` with `type=restriction`.

```sql
-- length is in seconds
INSERT INTO user_account_history (`description`, `length`, `permanent`, `timestamp`, `type`, `user_id`) VALUE ('some description', 86400, 0, '2025-10-05 01:00:00', 'RESTRICTION', 1);
```

---

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-06 11:10:25 +08:00
MingxuanGame
d19f82df80 chore(config): update example 2025-10-05 03:49:05 +00:00
MingxuanGame
1db34bf5c5 feat(sync): add configuration to control syncing & support sync immediately by API 2025-10-05 03:44:46 +00:00
MingxuanGame
8884f8993c fix(beatmap): refresh current_user in batch_get_beatmaps response 2025-10-04 17:28:42 +00:00
MingxuanGame
bb4d454093 feat(recalculate): add CLI arguments for user and mode filtering in performance recalculation 2025-10-04 12:18:18 +00:00
MingxuanGame
6f522847ec fix(playcount): show the sum of all users' playcount in BeatmapResp/BeatmapsetResp 2025-10-04 10:50:33 +00:00
MingxuanGame
38671cd471 feat(user): implement /users/{user_id}/beatmaps-passed
close #9
2025-10-04 09:52:15 +00:00
MingxuanGame
6f48dd4575 fix(sync): handle 404 errors for missing beatmaps and beatmapsets 2025-10-04 08:58:05 +00:00
MingxuanGame
3f702dc5ec fix(auth): add API version check in login 2025-10-04 08:51:38 +00:00
MingxuanGame
6c23694061 fix(beatmap): refresh current user data in lookup_beatmap function 2025-10-04 08:43:48 +00:00
MingxuanGame
806dd819fb fix(ci): remove copy packages directory 2025-10-04 08:38:52 +00:00
MingxuanGame
96d96ddcd3 chore(merge): merge #53
## Removed

- SignalR server
- `msgpack_lazer_api`
- Unused services

## Changed

- Move once tasks and scheduled tasks into `app.tasks`
- Improve Logs
  - Yellow: Tasks
  - Blue: Services
  - Magenta: Fetcher
  - Dark green: Uvicorn
  - Red: System
  - `#FFC1C1`: Normal
- Redis: use multiple logical databases
  - db0: general cache (`redis_client`)
  - db1: message cache (`redis_message_client`)
  - db2: binary storage (`redis_binary_client`)
  - db3: rate limiting (`redis_rate_limit_client`)
- API: move user page API (`/api/v2/users/{user_id}/page`, `/api/v2/me/validate-bbcode`) into private APIs (`/api/private/user/page`, `/api/private/user/validate-bbcode`)
- Remove `from __future__ import annotations` to avoid `ForwardRef` problems
- Assets Proxy: use decorators to simplify code
- Ruff: add rules
- API Router: use Annotated-style dependency injections.
- Database: rename filenames to easily find the model

## Documents

- CONTRIBUTING.md
- AGENTS.md
- copilot-instructions.md
2025-10-04 16:37:40 +08:00
MingxuanGame
d1d2bd55a0 fix(security): raise RuntimeError for unset jwt_secret_key to enhance server safety 2025-10-04 08:04:23 +00:00
MingxuanGame
1163a93053 refactor(scores): rename models of score to match with filename 2025-10-04 08:01:38 +00:00
MingxuanGame
80ba65c746 docs(dev): add guides for authorization 2025-10-04 07:49:35 +00:00
MingxuanGame
9fe493a12e refactor(cache): remove unused cache management and monitoring endpoints 2025-10-04 07:35:58 +00:00
MingxuanGame
470e8b3c06 fix(beatmapset): update cursor type of SearchBeatmapsetsResp to support string values 2025-10-04 07:35:35 +00:00
MingxuanGame
00f53f0dc0 feat(beatmap): add asset_proxy_response decorator to beatmap lookup endpoints 2025-10-04 07:32:35 +00:00
MingxuanGame
238cb96c12 refactor(settings): remove unused user_cache_concurrent_limit field 2025-10-04 06:58:51 +00:00
MingxuanGame
ca7c74f709 refactor(project): remove useless getattr 2025-10-04 06:43:55 +00:00
MingxuanGame
c6058eb0d8 docs(dev): update contribution guide & agent instructions 2025-10-04 06:10:40 +00:00
MingxuanGame
216d3ab3bf feat(redis): refactor Redis configuration to use multiple logical databases
- Updated default REDIS_URL to remove explicit /0 suffix
- Added dedicated Redis clients:
  - db0: general cache (redis_client)
  - db1: message cache (redis_message_client)
  - db2: binary storage (redis_binary_client)
  - db3: rate limiting (redis_rate_limit_client)
- Updated configuration, Docker files, and main startup lifecycle accordingly
- Replaced `get_redis()` usage in notification server with `redis_message_client`
2025-10-04 05:39:59 +00:00
MingxuanGame
c2bfafc67a refactor(message): replace synchronous Redis client with asynchronous client 2025-10-04 05:26:37 +00:00
MingxuanGame
21da83e4eb refactor(middleware): remove unused setup method 2025-10-04 05:09:31 +00:00
MingxuanGame
238520c577 chore(linter): make ruff happy 2025-10-04 05:01:05 +00:00
MingxuanGame
382c1721df chore(merge): merge branch 'main' into refactor/restruct-project 2025-10-04 04:58:22 +00:00
MingxuanGame
7c18fc5fb6 refactor(userpage): move APIs into g0v0 private API 2025-10-04 04:57:24 +00:00
MingxuanGame
2bfde24b84 fix(log): fix typing & exception logs 2025-10-03 17:27:47 +00:00
MingxuanGame
dfd656f2fb style(project): remove from __future__ import annotations 2025-10-03 17:15:41 +00:00
MingxuanGame
046f894407 refactor(assets_proxy): use decorators to simplify code 2025-10-03 17:12:28 +00:00
MingxuanGame
d490239f46 chore(linter): update ruff rules 2025-10-03 15:46:53 +00:00
MingxuanGame
b10425ad91 refactor(service): remove unused services 2025-10-03 13:40:18 +00:00
MingxuanGame
1e775c9a36 fix(log): don't show traceback in log 2025-10-03 13:25:31 +00:00
MingxuanGame
0d9019c6cc refactor(signalr): remove SignalR server & msgpack_lazer_api
Maybe we can make `msgpack_lazer_api` independent?
2025-10-03 13:20:12 +00:00
MingxuanGame
d23f32f08d refactor(log): refactor the whole project
format: {time:YYYY-MM-DD HH:mm:ss} [{level}] | {name} | {message}
{name} is:
- Uvicorn: log from uvicorn server (#228B22)
- Service: log from class of `app.service` (blue)
- Fetcher: log from fetchers (magenta)
- Task: log from `app.tasks` (#FFD700)
- System: log from `system_logger` (red)
- Normal: log from `log(name)` (#FFC1C1)
- Default: the module name of caller

if you are writing services or tasks, you can just call `logger.`, we will pack it with name `Service` or `Task`
if you want to print fetcher logs, system-related logs, or normal logs, use `logger = (fetcher_logger / system_logger / log)(name)`
2025-10-03 11:53:05 +00:00
MingxuanGame
fce88272b5 refactor(task): move schedulers and startup/shutdown task into tasks directory 2025-10-03 10:15:22 +00:00
MingxuanGame
56fcc84196 fix(beatmapset): don't store genre and language into database 2025-10-03 16:57:56 +08:00
MingxuanGame
afd5018bcd refactor(log): add prefix for fetcher and services 2025-10-03 08:22:41 +00:00
MingxuanGame
346c2557cf refactor(api): use Annotated-style dependency injection 2025-10-03 05:41:31 +00:00
MingxuanGame
e6b60c54bd fix(migrations): add default for refresh_token_expires_at to avoid tokens are cleaned 2025-10-03 12:16:12 +08:00
MingxuanGame
37b4eadf79 refactor(database): rename filename to find the models by table name easily 2025-10-03 03:33:47 +00:00
MingxuanGame
40670c094b feat(auth): support trusted device (#52)
New API to maintain sessions and devices:

- GET /api/private/admin/sessions
- DELETE /api/private/admin/sessions/{session_id}
- GET /api/private/admin/trusted-devices
- DELETE /api/private/admin/trusted-devices/{device_id}

Auth:

web clients request `/oauth/token` and `/api/v2/session/verify` with `X-UUID` header to save the client as trusted device.

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-03 11:26:43 +08:00
MingxuanGame
f34ed53a55 fix(beatmap): fix beatmap.beatmapset is None when it from from_resp 2025-10-02 16:41:40 +00:00