Skip to content

Commit 8beceaf

Browse files
refactor: remove git commit hash from version display and polish admin UI
Drops the commit hash from the /health endpoint and sidebar version display, simplifies the attribute definitions and roles list tables, and adds an admin permissions description to the user form.
1 parent f263c74 commit 8beceaf

10 files changed

Lines changed: 94 additions & 88 deletions

File tree

admin-ui/src/api/version.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@ import axios from 'axios'
22

33
export interface VersionInfo {
44
current: string
5-
commit: string
65
}
76

87
export async function getVersion(): Promise<VersionInfo> {
9-
const { data } = await axios.get<{ version: string; commit: string }>('/health')
10-
return { current: data.version, commit: data.commit }
8+
const { data } = await axios.get<{ version: string }>('/health')
9+
return { current: data.version }
1110
}

admin-ui/src/components/Layout.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,6 @@ describe('Layout', () => {
6060
it('displays current version in sidebar', async () => {
6161
mockGetVersion.mockResolvedValue(makeVersionInfo({ current: '0.13.0' }))
6262
renderWithProviders(<WrappedLayout />, { authenticated: true, routerEntries: ['/'] })
63-
await waitFor(() => expect(screen.getByText('v0.13.0 (abc1234)')).toBeInTheDocument())
63+
await waitFor(() => expect(screen.getByText('v0.13.0')).toBeInTheDocument())
6464
})
6565
})

admin-ui/src/components/Layout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ export function Layout() {
148148
<div className="px-4 py-4 border-t border-gray-700 space-y-2">
149149
<p className="text-xs text-gray-400 truncate">@{user?.username}</p>
150150
{version && (
151-
<p className="text-xs text-gray-500">v{version.current} ({version.commit})</p>
151+
<p className="text-xs text-gray-500">v{version.current}</p>
152152
)}
153153
<div className="flex items-center gap-3">
154154
<button

admin-ui/src/components/UserForm.tsx

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -116,28 +116,35 @@ export function UserForm({ mode, initialValues = {}, onSubmit, onCancel, loading
116116
/>
117117
</Field>
118118

119-
<div className="flex gap-6">
120-
<label className="flex items-center gap-2 text-sm cursor-pointer">
121-
<input
122-
type="checkbox"
123-
checked={isAdmin}
124-
onChange={(e) => setIsAdmin(e.target.checked)}
125-
className="rounded"
126-
/>
127-
Admin
128-
</label>
129-
130-
{mode === 'edit' && (
119+
<div>
120+
<div className="flex gap-6">
131121
<label className="flex items-center gap-2 text-sm cursor-pointer">
132122
<input
133123
type="checkbox"
134-
checked={isActive}
135-
onChange={(e) => setIsActive(e.target.checked)}
124+
checked={isAdmin}
125+
onChange={(e) => setIsAdmin(e.target.checked)}
136126
className="rounded"
137127
/>
138-
Active
128+
Admin
139129
</label>
140-
)}
130+
131+
{mode === 'edit' && (
132+
<label className="flex items-center gap-2 text-sm cursor-pointer">
133+
<input
134+
type="checkbox"
135+
checked={isActive}
136+
onChange={(e) => setIsActive(e.target.checked)}
137+
className="rounded"
138+
/>
139+
Active
140+
</label>
141+
)}
142+
</div>
143+
<p className="text-xs text-gray-500 mt-2">
144+
Admins can manage users, roles, policies, data sources, decision functions, and
145+
attribute definitions, and can view audit logs. Non-admin users can sign in and
146+
query data sources they have access to, but cannot access the admin UI.
147+
</p>
141148
</div>
142149

143150
{(error || localError) && (

admin-ui/src/pages/AttributeDefinitionsPage.tsx

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,22 @@ import {
77
deleteAttributeDefinition,
88
} from '../api/attributeDefinitions'
99
import { CopyableId } from '../components/CopyableId'
10-
import { SUPPORTED_ENTITY_TYPES } from '../types/attributeDefinition'
10+
import {
11+
SUPPORTED_ENTITY_TYPES,
12+
type AttributeDefinition,
13+
} from '../types/attributeDefinition'
1114

12-
const VALUE_TYPE_BADGE: Record<string, string> = {
13-
string: 'bg-blue-100 text-blue-700',
14-
integer: 'bg-purple-100 text-purple-700',
15-
boolean: 'bg-amber-100 text-amber-700',
16-
list: 'bg-green-100 text-green-700',
15+
// Renders a value_type as a type-signature string, e.g.:
16+
// string
17+
// string ∈ {read, write, admin}
18+
// list<string>
19+
// list<string> ∈ {us, eu}
20+
function formatValueType(def: AttributeDefinition): string {
21+
const base = def.value_type === 'list' ? 'list<string>' : def.value_type
22+
if (def.allowed_values && def.allowed_values.length > 0) {
23+
return `${base} ∈ {${def.allowed_values.join(', ')}}`
24+
}
25+
return base
1726
}
1827

1928
export function AttributeDefinitionsPage() {
@@ -147,36 +156,38 @@ export function AttributeDefinitionsPage() {
147156
<table className="w-full text-sm">
148157
<thead className="bg-gray-50 border-b border-gray-200">
149158
<tr>
159+
<th className="text-left px-4 py-3 font-medium text-gray-600 text-xs">Name</th>
150160
<th className="text-left px-4 py-3 font-medium text-gray-600 text-xs">Key</th>
151161
<th className="text-left px-4 py-3 font-medium text-gray-600 text-xs">ID</th>
152-
<th className="text-left px-4 py-3 font-medium text-gray-600 text-xs">Entity</th>
153-
<th className="text-left px-4 py-3 font-medium text-gray-600 text-xs">Display Name</th>
154162
<th className="text-left px-4 py-3 font-medium text-gray-600 text-xs">Type</th>
155-
<th className="text-left px-4 py-3 font-medium text-gray-600 text-xs">Allowed Values</th>
156163
<th className="text-left px-4 py-3 font-medium text-gray-600 text-xs">Default</th>
157164
<th className="px-4 py-3 font-medium text-gray-600 text-xs text-right">Actions</th>
158165
</tr>
159166
</thead>
160167
<tbody className="divide-y divide-gray-100">
161168
{items.map((def) => (
162169
<tr key={def.id} className="hover:bg-gray-50 transition-colors">
163-
<td className="px-4 py-3 font-mono text-sm">{def.key}</td>
164170
<td className="px-4 py-3">
165-
<CopyableId id={def.id} short />
171+
<div className="font-medium text-gray-900">{def.display_name}</div>
172+
{def.description && (
173+
<div
174+
className="text-xs text-gray-500 mt-0.5 truncate max-w-xs"
175+
title={def.description}
176+
>
177+
{def.description}
178+
</div>
179+
)}
166180
</td>
167-
<td className="px-4 py-3 text-gray-500">{def.entity_type}</td>
168-
<td className="px-4 py-3">{def.display_name}</td>
169181
<td className="px-4 py-3">
170-
<span
171-
className={`inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${VALUE_TYPE_BADGE[def.value_type] ?? 'bg-gray-100 text-gray-700'}`}
172-
>
173-
{def.value_type}
174-
</span>
182+
<code className="inline-block font-mono text-xs text-gray-600 bg-gray-100 rounded px-1.5 py-0.5">
183+
{`{${def.entity_type}.${def.key}}`}
184+
</code>
175185
</td>
176-
<td className="px-4 py-3 text-gray-500">
177-
{def.allowed_values
178-
? def.allowed_values.join(', ')
179-
: <span className="text-gray-300">any</span>}
186+
<td className="px-4 py-3">
187+
<CopyableId id={def.id} short />
188+
</td>
189+
<td className="px-4 py-3 font-mono text-xs text-gray-600">
190+
{formatValueType(def)}
180191
</td>
181192
<td className="px-4 py-3 text-gray-500">
182193
{def.default_value != null

admin-ui/src/pages/RolesListPage.tsx

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ export function RolesListPage() {
7878
<tr>
7979
<th className="text-left px-4 py-3 font-medium text-gray-600 text-xs">Name</th>
8080
<th className="text-left px-4 py-3 font-medium text-gray-600 text-xs">ID</th>
81-
<th className="text-left px-4 py-3 font-medium text-gray-600 text-xs">Description</th>
8281
<th className="text-left px-4 py-3 font-medium text-gray-600 text-xs">Status</th>
8382
<th className="text-left px-4 py-3 font-medium text-gray-600 text-xs">Direct Members</th>
8483
<th className="text-left px-4 py-3 font-medium text-gray-600 text-xs">Created</th>
@@ -94,19 +93,18 @@ export function RolesListPage() {
9493
>
9594
<td className="px-4 py-3">
9695
<div className="font-medium text-gray-900">{role.name}</div>
97-
</td>
98-
<td className="px-4 py-3" onClick={(e) => e.stopPropagation()}>
99-
<CopyableId id={role.id} short />
100-
</td>
101-
<td className="px-4 py-3">
102-
{role.description ? (
103-
<div className="text-xs text-gray-500 truncate max-w-xs">
96+
{role.description && (
97+
<div
98+
className="text-xs text-gray-500 mt-0.5 truncate max-w-xs"
99+
title={role.description}
100+
>
104101
{role.description}
105102
</div>
106-
) : (
107-
<span className="text-xs text-gray-300 italic">none</span>
108103
)}
109104
</td>
105+
<td className="px-4 py-3" onClick={(e) => e.stopPropagation()}>
106+
<CopyableId id={role.id} short />
107+
</td>
110108
<td className="px-4 py-3">
111109
<span
112110
className={`inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${

admin-ui/src/pages/UserEditPage.tsx

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -138,25 +138,32 @@ export function UserEditPage() {
138138
/>
139139
</div>
140140

141-
<div className="flex gap-6">
142-
<label className="flex items-center gap-2 text-sm cursor-pointer">
143-
<input
144-
type="checkbox"
145-
checked={isAdmin}
146-
onChange={(e) => setIsAdmin(e.target.checked)}
147-
className="rounded"
148-
/>
149-
Admin
150-
</label>
151-
<label className="flex items-center gap-2 text-sm cursor-pointer">
152-
<input
153-
type="checkbox"
154-
checked={isActive}
155-
onChange={(e) => setIsActive(e.target.checked)}
156-
className="rounded"
157-
/>
158-
Active
159-
</label>
141+
<div>
142+
<div className="flex gap-6">
143+
<label className="flex items-center gap-2 text-sm cursor-pointer">
144+
<input
145+
type="checkbox"
146+
checked={isAdmin}
147+
onChange={(e) => setIsAdmin(e.target.checked)}
148+
className="rounded"
149+
/>
150+
Admin
151+
</label>
152+
<label className="flex items-center gap-2 text-sm cursor-pointer">
153+
<input
154+
type="checkbox"
155+
checked={isActive}
156+
onChange={(e) => setIsActive(e.target.checked)}
157+
className="rounded"
158+
/>
159+
Active
160+
</label>
161+
</div>
162+
<p className="text-xs text-gray-500 mt-2">
163+
Admins can manage users, roles, policies, data sources, decision functions, and
164+
attribute definitions, and can view audit logs. Non-admin users can sign in and
165+
query data sources they have access to, but cannot access the admin UI.
166+
</p>
160167
</div>
161168

162169
{/* Attributes */}

admin-ui/src/test/factories.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,6 @@ export function makePolicy(overrides: Partial<PolicyResponse> = {}): PolicyRespo
187187
export function makeVersionInfo(overrides: Partial<VersionInfo> = {}): VersionInfo {
188188
return {
189189
current: '0.13.0',
190-
commit: 'abc1234',
191190
...overrides,
192191
}
193192
}

proxy/build.rs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,6 @@ const JAVY_VERSION: &str = "8.1.0";
1414

1515
fn main() {
1616
println!("cargo:rerun-if-changed=build.rs");
17-
// Tracks branch switches but not new commits on the same branch during
18-
// local incremental builds. This is acceptable — CI always does a clean
19-
// build where build.rs runs unconditionally.
20-
println!("cargo:rerun-if-changed=../.git/HEAD");
21-
22-
// Capture short commit hash at build time
23-
let commit = Command::new("git")
24-
.args(["rev-parse", "--short", "HEAD"])
25-
.output()
26-
.ok()
27-
.filter(|o| o.status.success())
28-
.map(|o| String::from_utf8_lossy(&o.stdout).trim().to_string())
29-
.unwrap_or_else(|| "unknown".to_string());
30-
println!("cargo:rustc-env=GIT_COMMIT_SHORT={commit}");
3117

3218
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
3319
let javy_bin = out_dir.join("javy");

proxy/src/admin/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,6 @@ pub fn admin_router(state: AdminState) -> Router {
108108
get(|| async {
109109
Json(serde_json::json!({
110110
"version": env!("CARGO_PKG_VERSION"),
111-
"commit": env!("GIT_COMMIT_SHORT"),
112111
}))
113112
}),
114113
)

0 commit comments

Comments
 (0)