Skip to content

Commit 86b56ea

Browse files
authored
Merge pull request #1104 from objectstack-ai/claude/add-sysuserpreference-object
[WIP] Add SysUserPreference system object to plugin-auth
2 parents 51c5977 + 78ea54c commit 86b56ea

File tree

5 files changed

+89
-2
lines changed

5 files changed

+89
-2
lines changed

packages/plugins/plugin-auth/src/auth-plugin.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
SysUser, SysSession, SysAccount, SysVerification,
88
SysOrganization, SysMember, SysInvitation,
99
SysTeam, SysTeamMember,
10-
SysApiKey, SysTwoFactor,
10+
SysApiKey, SysTwoFactor, SysUserPreference,
1111
} from './objects/index.js';
1212

1313
/**
@@ -107,7 +107,7 @@ export class AuthPlugin implements Plugin {
107107
SysUser, SysSession, SysAccount, SysVerification,
108108
SysOrganization, SysMember, SysInvitation,
109109
SysTeam, SysTeamMember,
110-
SysApiKey, SysTwoFactor,
110+
SysApiKey, SysTwoFactor, SysUserPreference,
111111
],
112112
});
113113

packages/plugins/plugin-auth/src/objects/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export { SysTeamMember } from './sys-team-member.object.js';
2727
// ── Additional Auth Objects ────────────────────────────────────────────────
2828
export { SysApiKey } from './sys-api-key.object.js';
2929
export { SysTwoFactor } from './sys-two-factor.object.js';
30+
export { SysUserPreference } from './sys-user-preference.object.js';
3031

3132
// ── Backward Compatibility (deprecated) ────────────────────────────────────
3233
/** @deprecated Use `SysUser` instead */
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2+
3+
import { ObjectSchema, Field } from '@objectstack/spec/data';
4+
5+
/**
6+
* sys_user_preference — System User Preference Object
7+
*
8+
* Per-user key-value preferences for storing UI state, settings, and personalization.
9+
* Supports the User Preferences layer in the Config Resolution hierarchy
10+
* (Runtime > User Preferences > Tenant > Env).
11+
*
12+
* Common use cases:
13+
* - UI preferences: theme, locale, timezone, sidebar state
14+
* - Feature flags: plugin.ai.auto_save, plugin.dev.debug_mode
15+
* - User-specific settings: default_view, notifications_enabled
16+
*
17+
* @namespace sys
18+
*/
19+
export const SysUserPreference = ObjectSchema.create({
20+
namespace: 'sys',
21+
name: 'user_preference',
22+
label: 'User Preference',
23+
pluralLabel: 'User Preferences',
24+
icon: 'settings',
25+
isSystem: true,
26+
description: 'Per-user key-value preferences (theme, locale, etc.)',
27+
titleFormat: '{key}',
28+
compactLayout: ['user_id', 'key'],
29+
30+
fields: {
31+
id: Field.text({
32+
label: 'Preference ID',
33+
required: true,
34+
readonly: true,
35+
}),
36+
37+
created_at: Field.datetime({
38+
label: 'Created At',
39+
defaultValue: 'NOW()',
40+
readonly: true,
41+
}),
42+
43+
updated_at: Field.datetime({
44+
label: 'Updated At',
45+
defaultValue: 'NOW()',
46+
readonly: true,
47+
}),
48+
49+
user_id: Field.text({
50+
label: 'User ID',
51+
required: true,
52+
maxLength: 255,
53+
description: 'Owner user of this preference',
54+
}),
55+
56+
key: Field.text({
57+
label: 'Key',
58+
required: true,
59+
maxLength: 255,
60+
description: 'Preference key (e.g., theme, locale, plugin.ai.auto_save)',
61+
}),
62+
63+
value: Field.json({
64+
label: 'Value',
65+
description: 'Preference value (any JSON-serializable type)',
66+
}),
67+
},
68+
69+
indexes: [
70+
{ fields: ['user_id', 'key'], unique: true },
71+
{ fields: ['user_id'], unique: false },
72+
],
73+
74+
enable: {
75+
trackHistory: false,
76+
searchable: false,
77+
apiEnabled: true,
78+
apiMethods: ['get', 'list', 'create', 'update', 'delete'],
79+
trash: false,
80+
mru: false,
81+
},
82+
});

packages/spec/src/system/constants/system-names.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ describe('SystemObjectName', () => {
2222
expect(SystemObjectName.TEAM_MEMBER).toBe('sys_team_member');
2323
expect(SystemObjectName.API_KEY).toBe('sys_api_key');
2424
expect(SystemObjectName.TWO_FACTOR).toBe('sys_two_factor');
25+
expect(SystemObjectName.USER_PREFERENCE).toBe('sys_user_preference');
2526
expect(SystemObjectName.ROLE).toBe('sys_role');
2627
expect(SystemObjectName.PERMISSION_SET).toBe('sys_permission_set');
2728
expect(SystemObjectName.AUDIT_LOG).toBe('sys_audit_log');
@@ -54,6 +55,7 @@ describe('SystemObjectName', () => {
5455
expect(keys).toContain('TEAM_MEMBER');
5556
expect(keys).toContain('API_KEY');
5657
expect(keys).toContain('TWO_FACTOR');
58+
expect(keys).toContain('USER_PREFERENCE');
5759
expect(keys).toContain('ROLE');
5860
expect(keys).toContain('PERMISSION_SET');
5961
expect(keys).toContain('AUDIT_LOG');

packages/spec/src/system/constants/system-names.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ export const SystemObjectName = {
4242
API_KEY: 'sys_api_key',
4343
/** Authentication: two-factor authentication credentials */
4444
TWO_FACTOR: 'sys_two_factor',
45+
/** Authentication: user preferences (theme, locale, etc.) */
46+
USER_PREFERENCE: 'sys_user_preference',
4547
/** Security: role definition for RBAC */
4648
ROLE: 'sys_role',
4749
/** Security: permission set grouping */

0 commit comments

Comments
 (0)