Repository navigation
feat(supportedVersions): role-targeted expiration messages #3371
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
Changes from 1 commit
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,59 @@ | ||
| import { dispatch } from '../../store'; | ||
| import { WEBVIEW_USER_ROLES_CHANGED } from '../../ui/actions'; | ||
| import type { Server } from '../common'; | ||
| import { getServerUrl } from './urls'; | ||
|
|
||
| const dispatchUserRoles = (userRoles: Server['userRoles']): void => { | ||
| dispatch({ | ||
| type: WEBVIEW_USER_ROLES_CHANGED, | ||
| payload: { | ||
| url: getServerUrl(), | ||
| userRoles, | ||
| }, | ||
| }); | ||
| }; | ||
|
|
||
| const buildMeEndpoint = (serverUrl: string): string => | ||
| `${serverUrl.replace(/\/$/, '')}/api/v1/me`; | ||
|
|
||
| /** | ||
| * Reads the logged-in user's roles from the workspace REST API and stores them | ||
| * on the server state. Roles are used to decide which supportedVersions | ||
| * messages a user is allowed to see (see Message.roles). Any failure leaves | ||
| * roles unset, which makes role-targeted messages fall back to being shown to | ||
| * everyone — the pre-existing behavior. | ||
| */ | ||
| export const updateUserRoles = async (): Promise<void> => { | ||
| try { | ||
| const serverUrl = getServerUrl(); | ||
| if (!serverUrl) return; | ||
|
|
||
| const authToken = localStorage.getItem('Meteor.loginToken'); | ||
| const userId = localStorage.getItem('Meteor.userId'); | ||
| if (!authToken || !userId) return; | ||
|
|
||
| const response = await fetch(buildMeEndpoint(serverUrl), { | ||
| headers: { | ||
| 'X-Auth-Token': authToken, | ||
| 'X-User-Id': userId, | ||
| }, | ||
| }); | ||
| if (!response.ok) return; | ||
|
|
||
| const data = await response.json(); | ||
| const roles: unknown = data?.roles; | ||
| if (!Array.isArray(roles)) return; | ||
|
|
||
| const userRoles = roles.filter( | ||
| (role): role is string => typeof role === 'string' | ||
| ); | ||
| dispatchUserRoles(userRoles); | ||
|
Comment on lines
+46
to
+76
Contributor
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. 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win Prevent stale roles from being persisted across failed or outdated fetches.
💡 Suggested fix export const updateUserRoles = async (): Promise<void> => {
try {
const serverUrl = getServerUrl();
- if (!serverUrl) return;
+ if (!serverUrl) {
+ dispatchUserRoles(undefined);
+ return;
+ }
const authToken = localStorage.getItem('Meteor.loginToken');
const userId = localStorage.getItem('Meteor.userId');
- if (!authToken || !userId) return;
+ if (!authToken || !userId) {
+ dispatchUserRoles(undefined);
+ return;
+ }
+
+ // Avoid reusing stale roles while refresh is in flight.
+ dispatchUserRoles(undefined);
const response = await fetch(buildMeEndpoint(serverUrl), {
headers: {
'X-Auth-Token': authToken,
'X-User-Id': userId,
},
});
if (!response.ok) return;
const data = await response.json();
const roles: unknown = data?.roles;
if (!Array.isArray(roles)) return;
const userRoles = roles.filter(
(role): role is string => typeof role === 'string'
);
+
+ // Drop stale responses if auth context changed while awaiting network/JSON.
+ if (
+ localStorage.getItem('Meteor.loginToken') !== authToken ||
+ localStorage.getItem('Meteor.userId') !== userId
+ ) {
+ return;
+ }
+
dispatchUserRoles(userRoles);
} catch {🤖 Prompt for AI Agents |
||
| } catch { | ||
| // Network/parse errors are non-fatal: leave roles unset so role-targeted | ||
| // messages default to visible. | ||
| } | ||
| }; | ||
|
|
||
| export const clearUserRoles = (): void => { | ||
| dispatchUserRoles(undefined); | ||
| }; | ||
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.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Fix the fallback-behavior comment to match actual role filtering.
The comment says unset roles make role-targeted messages visible to everyone, but runtime filtering (
src/servers/supportedVersions/main.ts,messageMatchesUserRoles) hides targeted messages whenuserRolesis unknown. This mismatch can lead to incorrect follow-up changes.🤖 Prompt for AI Agents