-
-
Notifications
You must be signed in to change notification settings - Fork 615
feat: account managment #6114
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: nextgen
Are you sure you want to change the base?
feat: account managment #6114
Conversation
# Conflicts: # src/main/kotlin/net/ccbluex/liquidbounce/event/EventManager.kt # src/main/kotlin/net/ccbluex/liquidbounce/features/command/commands/client/client/CommandClientAccountSubcommand.kt
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.
Pull Request Overview
This PR adds account management functionality to LiquidBounce, enabling users to log in and out of their LiquidBounce accounts through both REST API endpoints and CLI commands. The implementation includes WebSocket event notifications for login/logout actions and a new UI component to display user information.
- Added REST API endpoints for user authentication (GET
/api/v1/client/user, POST/api/v2/client/user/login, POST/api/v2/client/user/logout) - Refactored OAuth server implementation to improve cleanup and error handling
- Enhanced user information model to include additional fields (email, name, nickname, groups, admin status)
Reviewed Changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
UserFunctions.kt |
New REST API endpoints for user account operations (get, login, logout) |
InteropFunctionRegistry.kt |
Registered the new user-related API endpoints |
CommandClientAccountSubcommand.kt |
Updated CLI command to fire events and display extended user info |
ClientEvents.kt |
Added UserLoggedInEvent and UserLoggedOutEvent events |
EventManager.kt |
Registered the new user events in the event class list |
OAuthClient.kt |
Refactored OAuth server lifecycle and improved error handling |
UserInformation.kt |
Extended data model with additional user fields |
ClientAccount.kt |
Added @JvmField annotation to EMPTY_ACCOUNT |
UserBox.svelte |
New UI component for displaying user information and login/logout controls |
Title.svelte |
Integrated UserBox component into the title screen |
types.ts |
Added ClientUser interface definition |
rest.ts |
Added API client functions for user operations |
events.ts |
Added WebSocket event types for user login/logout |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
...kotlin/net/ccbluex/liquidbounce/integration/interop/protocol/rest/v1/client/UserFunctions.kt
Outdated
Show resolved
Hide resolved
| get("/user", ::getUser).apply { | ||
| post("/login", ::loginUser) | ||
| post("/logout", ::logoutUser) | ||
| } |
Copilot
AI
Nov 11, 2025
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.
The comment at line 61 says POST /api/v2/client/user/login but the route is registered under /api/v1/client. This creates a version mismatch. Either update the comment in UserFunctions.kt or ensure the endpoints are registered under the correct API version.
| chat(regular("Nickname: "), variable(info.nickname)) | ||
| chat(regular("Email: "), variable(info.email)) | ||
| chat(regular("User ID: "), variable(info.userId)) | ||
| chat(regular("Groups: "), info.groups.map(::variable).joinToText(", ".asText())) |
Copilot
AI
Nov 11, 2025
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.
The joinToText function with separator is not a standard Kotlin collection function. This should likely be joinToString with the separator as a string, or the text concatenation logic needs verification to ensure it produces the expected output format.
| chat(regular("Groups: "), info.groups.map(::variable).joinToText(", ".asText())) | |
| chat(regular("Groups: "), info.groups.map(::variable).joinToString(", ")) |
|
|
||
| val bootstrap = ServerBootstrap() | ||
| .group(bossGroup, workerGroup) | ||
| .channelFactory(::NioServerSocketChannel) |
Copilot
AI
Nov 11, 2025
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.
Using .channelFactory(::NioServerSocketChannel) is unconventional for Netty's ServerBootstrap. The standard approach is .channel(NioServerSocketChannel::class.java) which was used in the original code. This change may cause issues with channel instantiation.
| .channelFactory(::NioServerSocketChannel) | |
| .channel(NioServerSocketChannel::class.java) |
| userId: string; | ||
| email: string; | ||
| name: string | null; | ||
| nickname: string | null; |
Copilot
AI
Nov 11, 2025
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.
The nickname field is typed as string | null in TypeScript but the Kotlin UserInformation model defines it as non-nullable String. This type inconsistency will cause runtime errors when a user has no nickname. Either make the Kotlin field nullable or update the TypeScript type to match.
| nickname: string | null; | |
| nickname: string; |
| onMount(() => { | ||
| const timeout = setTimeout(() => { | ||
| if (loading) loading = false; | ||
| }, 3000); | ||
| return () => clearTimeout(timeout); | ||
| }); |
Copilot
AI
Nov 11, 2025
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.
There are two separate onMount calls (lines 41 and 55). These should be combined into a single onMount block to avoid confusion and ensure proper initialization order.
| await fetch(`${API_BASE}/client/user/login`, { | ||
| method: "POST", | ||
| headers: { | ||
| "Content-Type": "application/json" | ||
| } | ||
| }); | ||
| } | ||
|
|
||
| export async function logoutClientUser() { | ||
| await fetch(`${API_BASE}/client/user/logout`, { | ||
| method: "POST", | ||
| headers: { | ||
| "Content-Type": "application/json" | ||
| } | ||
| }); |
Copilot
AI
Nov 11, 2025
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.
The loginClientUser and logoutClientUser functions don't check the response status or throw errors on failure. They should validate the response and throw meaningful errors to help debug authentication issues, similar to how getClientUser handles errors.
| await fetch(`${API_BASE}/client/user/login`, { | |
| method: "POST", | |
| headers: { | |
| "Content-Type": "application/json" | |
| } | |
| }); | |
| } | |
| export async function logoutClientUser() { | |
| await fetch(`${API_BASE}/client/user/logout`, { | |
| method: "POST", | |
| headers: { | |
| "Content-Type": "application/json" | |
| } | |
| }); | |
| const response = await fetch(`${API_BASE}/client/user/login`, { | |
| method: "POST", | |
| headers: { | |
| "Content-Type": "application/json" | |
| } | |
| }); | |
| if (!response.ok) { | |
| throw new Error(`Failed to login client user: ${response.status} ${response.statusText}`); | |
| } | |
| } | |
| export async function logoutClientUser() { | |
| const response = await fetch(`${API_BASE}/client/user/logout`, { | |
| method: "POST", | |
| headers: { | |
| "Content-Type": "application/json" | |
| } | |
| }); | |
| if (!response.ok) { | |
| throw new Error(`Failed to logout client user: ${response.status} ${response.statusText}`); | |
| } |
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
Needs to be improved by @SenkJu - if required, revert commit: f463011