Milin
commited on
Commit
·
33eb1fa
1
Parent(s):
35d4f12
feat(webui): Display logged-in username
Browse files- Add username display in the `SiteHeader` component.
- Update logout button text to include username.
- Add `username` field in auth state.
- Optimize token parsing logic to extract username information.
- pre-commit fix
- env.example +1 -1
- lightrag/api/auth.py +3 -3
- lightrag/api/webui/assets/index-BcBS1RaQ.css +0 -0
- lightrag/api/webui/assets/index-Cq65VeVX.css +0 -0
- lightrag/api/webui/assets/{index-DlScqWrq.js → index-qXLILB5u.js} +0 -0
- lightrag/api/webui/index.html +0 -0
- lightrag_webui/src/features/SiteHeader.tsx +8 -2
- lightrag_webui/src/stores/state.ts +29 -16
env.example
CHANGED
@@ -155,4 +155,4 @@ REDIS_URI=redis://localhost:6379
|
|
155 |
# AUTH_ACCOUNTS='admin:admin123,user1:pass456' # username:password,username:password
|
156 |
# TOKEN_SECRET=Your-Key-For-LightRAG-API-Server # JWT key
|
157 |
# TOKEN_EXPIRE_HOURS=4 # expire duration
|
158 |
-
# WHITELIST_PATHS= # white list
|
|
|
155 |
# AUTH_ACCOUNTS='admin:admin123,user1:pass456' # username:password,username:password
|
156 |
# TOKEN_SECRET=Your-Key-For-LightRAG-API-Server # JWT key
|
157 |
# TOKEN_EXPIRE_HOURS=4 # expire duration
|
158 |
+
# WHITELIST_PATHS= # white list
|
lightrag/api/auth.py
CHANGED
@@ -21,12 +21,12 @@ class AuthHandler:
|
|
21 |
self.algorithm = "HS256"
|
22 |
self.expire_hours = int(os.getenv("TOKEN_EXPIRE_HOURS", 4))
|
23 |
self.guest_expire_hours = int(os.getenv("GUEST_TOKEN_EXPIRE_HOURS", 2))
|
24 |
-
|
25 |
self.accounts = {}
|
26 |
auth_accounts = os.getenv("AUTH_ACCOUNTS")
|
27 |
if auth_accounts:
|
28 |
-
for account in auth_accounts.split(
|
29 |
-
username, password = account.split(
|
30 |
self.accounts[username] = password
|
31 |
|
32 |
def create_token(
|
|
|
21 |
self.algorithm = "HS256"
|
22 |
self.expire_hours = int(os.getenv("TOKEN_EXPIRE_HOURS", 4))
|
23 |
self.guest_expire_hours = int(os.getenv("GUEST_TOKEN_EXPIRE_HOURS", 2))
|
24 |
+
|
25 |
self.accounts = {}
|
26 |
auth_accounts = os.getenv("AUTH_ACCOUNTS")
|
27 |
if auth_accounts:
|
28 |
+
for account in auth_accounts.split(","):
|
29 |
+
username, password = account.split(":", 1)
|
30 |
self.accounts[username] = password
|
31 |
|
32 |
def create_token(
|
lightrag/api/webui/assets/index-BcBS1RaQ.css
ADDED
Binary file (53 kB). View file
|
|
lightrag/api/webui/assets/index-Cq65VeVX.css
DELETED
Binary file (53.1 kB)
|
|
lightrag/api/webui/assets/{index-DlScqWrq.js → index-qXLILB5u.js}
RENAMED
Binary files a/lightrag/api/webui/assets/index-DlScqWrq.js and b/lightrag/api/webui/assets/index-qXLILB5u.js differ
|
|
lightrag/api/webui/index.html
CHANGED
Binary files a/lightrag/api/webui/index.html and b/lightrag/api/webui/index.html differ
|
|
lightrag_webui/src/features/SiteHeader.tsx
CHANGED
@@ -55,7 +55,7 @@ function TabsNavigation() {
|
|
55 |
|
56 |
export default function SiteHeader() {
|
57 |
const { t } = useTranslation()
|
58 |
-
const { isGuestMode, coreVersion, apiVersion } = useAuthStore()
|
59 |
|
60 |
const versionDisplay = (coreVersion && apiVersion)
|
61 |
? `${coreVersion}/${apiVersion}`
|
@@ -96,7 +96,13 @@ export default function SiteHeader() {
|
|
96 |
</Button>
|
97 |
<AppSettings />
|
98 |
{!isGuestMode && (
|
99 |
-
<Button
|
|
|
|
|
|
|
|
|
|
|
|
|
100 |
<LogOutIcon className="size-4" aria-hidden="true" />
|
101 |
</Button>
|
102 |
)}
|
|
|
55 |
|
56 |
export default function SiteHeader() {
|
57 |
const { t } = useTranslation()
|
58 |
+
const { isGuestMode, coreVersion, apiVersion, username } = useAuthStore()
|
59 |
|
60 |
const versionDisplay = (coreVersion && apiVersion)
|
61 |
? `${coreVersion}/${apiVersion}`
|
|
|
96 |
</Button>
|
97 |
<AppSettings />
|
98 |
{!isGuestMode && (
|
99 |
+
<Button
|
100 |
+
variant="ghost"
|
101 |
+
size="icon"
|
102 |
+
side="bottom"
|
103 |
+
tooltip={`${t('header.logout')} (${username})`}
|
104 |
+
onClick={handleLogout}
|
105 |
+
>
|
106 |
<LogOutIcon className="size-4" aria-hidden="true" />
|
107 |
</Button>
|
108 |
)}
|
lightrag_webui/src/stores/state.ts
CHANGED
@@ -21,6 +21,8 @@ interface AuthState {
|
|
21 |
isGuestMode: boolean; // Add guest mode flag
|
22 |
coreVersion: string | null;
|
23 |
apiVersion: string | null;
|
|
|
|
|
24 |
login: (token: string, isGuest?: boolean, coreVersion?: string | null, apiVersion?: string | null) => void;
|
25 |
logout: () => void;
|
26 |
setVersion: (coreVersion: string | null, apiVersion: string | null) => void;
|
@@ -76,36 +78,42 @@ const useBackendState = createSelectors(useBackendStateStoreBase)
|
|
76 |
|
77 |
export { useBackendState }
|
78 |
|
79 |
-
|
80 |
-
const isGuestToken = (token: string): boolean => {
|
81 |
try {
|
82 |
// JWT tokens are in the format: header.payload.signature
|
83 |
const parts = token.split('.');
|
84 |
-
if (parts.length !== 3) return
|
85 |
-
|
86 |
-
// Decode the payload (second part)
|
87 |
const payload = JSON.parse(atob(parts[1]));
|
88 |
-
|
89 |
-
// Check if the token has a role field with value "guest"
|
90 |
-
return payload.role === 'guest';
|
91 |
} catch (e) {
|
92 |
-
console.error('Error parsing token:', e);
|
93 |
-
return
|
94 |
}
|
95 |
};
|
96 |
|
97 |
-
|
98 |
-
const
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
99 |
const token = localStorage.getItem('LIGHTRAG-API-TOKEN');
|
100 |
const coreVersion = localStorage.getItem('LIGHTRAG-CORE-VERSION');
|
101 |
const apiVersion = localStorage.getItem('LIGHTRAG-API-VERSION');
|
|
|
102 |
|
103 |
if (!token) {
|
104 |
return {
|
105 |
isAuthenticated: false,
|
106 |
isGuestMode: false,
|
107 |
coreVersion: coreVersion,
|
108 |
-
apiVersion: apiVersion
|
|
|
109 |
};
|
110 |
}
|
111 |
|
@@ -113,7 +121,8 @@ const initAuthState = (): { isAuthenticated: boolean; isGuestMode: boolean; core
|
|
113 |
isAuthenticated: true,
|
114 |
isGuestMode: isGuestToken(token),
|
115 |
coreVersion: coreVersion,
|
116 |
-
apiVersion: apiVersion
|
|
|
117 |
};
|
118 |
};
|
119 |
|
@@ -126,6 +135,7 @@ export const useAuthStore = create<AuthState>(set => {
|
|
126 |
isGuestMode: initialState.isGuestMode,
|
127 |
coreVersion: initialState.coreVersion,
|
128 |
apiVersion: initialState.apiVersion,
|
|
|
129 |
|
130 |
login: (token, isGuest = false, coreVersion = null, apiVersion = null) => {
|
131 |
localStorage.setItem('LIGHTRAG-API-TOKEN', token);
|
@@ -137,11 +147,13 @@ export const useAuthStore = create<AuthState>(set => {
|
|
137 |
localStorage.setItem('LIGHTRAG-API-VERSION', apiVersion);
|
138 |
}
|
139 |
|
|
|
140 |
set({
|
141 |
isAuthenticated: true,
|
142 |
isGuestMode: isGuest,
|
|
|
143 |
coreVersion: coreVersion,
|
144 |
-
apiVersion: apiVersion
|
145 |
});
|
146 |
},
|
147 |
|
@@ -154,8 +166,9 @@ export const useAuthStore = create<AuthState>(set => {
|
|
154 |
set({
|
155 |
isAuthenticated: false,
|
156 |
isGuestMode: false,
|
|
|
157 |
coreVersion: coreVersion,
|
158 |
-
apiVersion: apiVersion
|
159 |
});
|
160 |
},
|
161 |
|
|
|
21 |
isGuestMode: boolean; // Add guest mode flag
|
22 |
coreVersion: string | null;
|
23 |
apiVersion: string | null;
|
24 |
+
username: string | null; // login username
|
25 |
+
|
26 |
login: (token: string, isGuest?: boolean, coreVersion?: string | null, apiVersion?: string | null) => void;
|
27 |
logout: () => void;
|
28 |
setVersion: (coreVersion: string | null, apiVersion: string | null) => void;
|
|
|
78 |
|
79 |
export { useBackendState }
|
80 |
|
81 |
+
const parseTokenPayload = (token: string): { sub?: string; role?: string } => {
|
|
|
82 |
try {
|
83 |
// JWT tokens are in the format: header.payload.signature
|
84 |
const parts = token.split('.');
|
85 |
+
if (parts.length !== 3) return {};
|
|
|
|
|
86 |
const payload = JSON.parse(atob(parts[1]));
|
87 |
+
return payload;
|
|
|
|
|
88 |
} catch (e) {
|
89 |
+
console.error('Error parsing token payload:', e);
|
90 |
+
return {};
|
91 |
}
|
92 |
};
|
93 |
|
94 |
+
const getUsernameFromToken = (token: string): string | null => {
|
95 |
+
const payload = parseTokenPayload(token);
|
96 |
+
return payload.sub || null;
|
97 |
+
};
|
98 |
+
|
99 |
+
const isGuestToken = (token: string): boolean => {
|
100 |
+
const payload = parseTokenPayload(token);
|
101 |
+
return payload.role === 'guest';
|
102 |
+
};
|
103 |
+
|
104 |
+
const initAuthState = (): { isAuthenticated: boolean; isGuestMode: boolean; coreVersion: string | null; apiVersion: string | null; username: string | null } => {
|
105 |
const token = localStorage.getItem('LIGHTRAG-API-TOKEN');
|
106 |
const coreVersion = localStorage.getItem('LIGHTRAG-CORE-VERSION');
|
107 |
const apiVersion = localStorage.getItem('LIGHTRAG-API-VERSION');
|
108 |
+
const username = token ? getUsernameFromToken(token) : null;
|
109 |
|
110 |
if (!token) {
|
111 |
return {
|
112 |
isAuthenticated: false,
|
113 |
isGuestMode: false,
|
114 |
coreVersion: coreVersion,
|
115 |
+
apiVersion: apiVersion,
|
116 |
+
username: null,
|
117 |
};
|
118 |
}
|
119 |
|
|
|
121 |
isAuthenticated: true,
|
122 |
isGuestMode: isGuestToken(token),
|
123 |
coreVersion: coreVersion,
|
124 |
+
apiVersion: apiVersion,
|
125 |
+
username: username,
|
126 |
};
|
127 |
};
|
128 |
|
|
|
135 |
isGuestMode: initialState.isGuestMode,
|
136 |
coreVersion: initialState.coreVersion,
|
137 |
apiVersion: initialState.apiVersion,
|
138 |
+
username: initialState.username,
|
139 |
|
140 |
login: (token, isGuest = false, coreVersion = null, apiVersion = null) => {
|
141 |
localStorage.setItem('LIGHTRAG-API-TOKEN', token);
|
|
|
147 |
localStorage.setItem('LIGHTRAG-API-VERSION', apiVersion);
|
148 |
}
|
149 |
|
150 |
+
const username = getUsernameFromToken(token);
|
151 |
set({
|
152 |
isAuthenticated: true,
|
153 |
isGuestMode: isGuest,
|
154 |
+
username: username,
|
155 |
coreVersion: coreVersion,
|
156 |
+
apiVersion: apiVersion,
|
157 |
});
|
158 |
},
|
159 |
|
|
|
166 |
set({
|
167 |
isAuthenticated: false,
|
168 |
isGuestMode: false,
|
169 |
+
username: null,
|
170 |
coreVersion: coreVersion,
|
171 |
+
apiVersion: apiVersion,
|
172 |
});
|
173 |
},
|
174 |
|