hazo_auth 1.6.2 → 1.6.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +179 -2
- package/SETUP_CHECKLIST.md +104 -6
- package/dist/app/api/hazo_auth/me/route.d.ts +30 -1
- package/dist/app/api/hazo_auth/me/route.d.ts.map +1 -1
- package/dist/app/api/hazo_auth/me/route.js +76 -16
- package/dist/app/api/hazo_auth/user_management/permissions/route.d.ts +50 -0
- package/dist/app/api/hazo_auth/user_management/permissions/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/user_management/permissions/route.js +257 -0
- package/dist/app/api/hazo_auth/user_management/roles/route.d.ts +40 -0
- package/dist/app/api/hazo_auth/user_management/roles/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/user_management/roles/route.js +352 -0
- package/dist/app/api/hazo_auth/user_management/users/roles/route.d.ts +37 -0
- package/dist/app/api/hazo_auth/user_management/users/roles/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/user_management/users/roles/route.js +276 -0
- package/dist/app/api/hazo_auth/user_management/users/route.d.ts +39 -0
- package/dist/app/api/hazo_auth/user_management/users/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/user_management/users/route.js +170 -0
- package/dist/cli/generate.d.ts.map +1 -1
- package/dist/cli/generate.js +38 -5
- package/dist/cli/validate.d.ts.map +1 -1
- package/dist/cli/validate.js +14 -0
- package/dist/components/layouts/shared/components/profile_pic_menu.d.ts +6 -2
- package/dist/components/layouts/shared/components/profile_pic_menu.d.ts.map +1 -1
- package/dist/components/layouts/shared/components/profile_pic_menu.js +39 -4
- package/dist/components/layouts/shared/components/profile_pic_menu_wrapper.d.ts +4 -2
- package/dist/components/layouts/shared/components/profile_pic_menu_wrapper.d.ts.map +1 -1
- package/dist/components/layouts/shared/components/profile_pic_menu_wrapper.js +3 -3
- package/dist/components/layouts/shared/components/sidebar_layout_wrapper.d.ts.map +1 -1
- package/dist/components/layouts/shared/components/sidebar_layout_wrapper.js +2 -2
- package/dist/components/layouts/shared/hooks/use_auth_status.d.ts +3 -0
- package/dist/components/layouts/shared/hooks/use_auth_status.d.ts.map +1 -1
- package/dist/components/layouts/shared/hooks/use_auth_status.js +4 -0
- package/dist/server/routes/index.d.ts +4 -0
- package/dist/server/routes/index.d.ts.map +1 -1
- package/dist/server/routes/index.js +5 -0
- package/dist/server/routes/user_management_permissions.d.ts +2 -0
- package/dist/server/routes/user_management_permissions.d.ts.map +1 -0
- package/dist/server/routes/user_management_permissions.js +2 -0
- package/dist/server/routes/user_management_roles.d.ts +2 -0
- package/dist/server/routes/user_management_roles.d.ts.map +1 -0
- package/dist/server/routes/user_management_roles.js +2 -0
- package/dist/server/routes/user_management_users.d.ts +2 -0
- package/dist/server/routes/user_management_users.d.ts.map +1 -0
- package/dist/server/routes/user_management_users.js +2 -0
- package/dist/server/routes/user_management_users_roles.d.ts +2 -0
- package/dist/server/routes/user_management_users_roles.d.ts.map +1 -0
- package/dist/server/routes/user_management_users_roles.js +2 -0
- package/hazo_auth_config.example.ini +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -648,7 +648,52 @@ export default async function LoginPage() {
|
|
|
648
648
|
- `ResetPasswordLayout` - Set new password with token
|
|
649
649
|
- `EmailVerificationLayout` - Verify email address
|
|
650
650
|
- `MySettingsLayout` - User profile and settings
|
|
651
|
-
- `UserManagementLayout` - Admin user/role management
|
|
651
|
+
- `UserManagementLayout` - Admin user/role management (requires user_management API routes)
|
|
652
|
+
|
|
653
|
+
### User Management Component
|
|
654
|
+
|
|
655
|
+
The `UserManagementLayout` component provides a comprehensive admin interface for managing users, roles, and permissions. It requires the user_management API routes to be set up in your project.
|
|
656
|
+
|
|
657
|
+
**Required Permissions:**
|
|
658
|
+
- `admin_user_management` - Access to Users tab
|
|
659
|
+
- `admin_role_management` - Access to Roles tab
|
|
660
|
+
- `admin_permission_management` - Access to Permissions tab
|
|
661
|
+
|
|
662
|
+
**Required API Routes:**
|
|
663
|
+
The `UserManagementLayout` component requires the following API routes to be created in your project:
|
|
664
|
+
|
|
665
|
+
```typescript
|
|
666
|
+
// app/api/hazo_auth/user_management/users/route.ts
|
|
667
|
+
export { GET, PATCH, POST } from "hazo_auth/server/routes";
|
|
668
|
+
|
|
669
|
+
// app/api/hazo_auth/user_management/permissions/route.ts
|
|
670
|
+
export { GET, POST, PUT, DELETE } from "hazo_auth/server/routes";
|
|
671
|
+
|
|
672
|
+
// app/api/hazo_auth/user_management/roles/route.ts
|
|
673
|
+
export { GET, POST, PUT } from "hazo_auth/server/routes";
|
|
674
|
+
|
|
675
|
+
// app/api/hazo_auth/user_management/users/roles/route.ts
|
|
676
|
+
export { GET, POST, PUT } from "hazo_auth/server/routes";
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
**Note:** These routes are automatically created when you run `npx hazo_auth generate-routes`. The routes handle:
|
|
680
|
+
- **Users:** List users, deactivate users, send password reset emails
|
|
681
|
+
- **Permissions:** List permissions (from DB and config), migrate config permissions to DB, create/update/delete permissions
|
|
682
|
+
- **Roles:** List roles with permissions, create roles, update role-permission assignments
|
|
683
|
+
- **User Roles:** Get user roles, assign roles to users, bulk update user role assignments
|
|
684
|
+
|
|
685
|
+
**Example Usage:**
|
|
686
|
+
|
|
687
|
+
```tsx
|
|
688
|
+
// app/hazo_auth/user_management/page.tsx
|
|
689
|
+
import { UserManagementLayout } from "hazo_auth/components/layouts/user_management";
|
|
690
|
+
|
|
691
|
+
export default function UserManagementPage() {
|
|
692
|
+
return <UserManagementLayout />;
|
|
693
|
+
}
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
The component automatically shows/hides tabs based on the user's permissions, so users will only see the tabs they have access to.
|
|
652
697
|
|
|
653
698
|
**Shared Components:**
|
|
654
699
|
- `ProfilePicMenu` / `ProfilePicMenuWrapper` - Navbar profile menu
|
|
@@ -680,6 +725,76 @@ layout_mode = standalone
|
|
|
680
725
|
|
|
681
726
|
The `hazo_auth` package provides a comprehensive authentication and authorization system with role-based access control (RBAC). The main authentication utility is `hazo_get_auth`, which provides user details, permissions, and permission checking with built-in caching and rate limiting.
|
|
682
727
|
|
|
728
|
+
### Client-Side API Endpoint (Recommended)
|
|
729
|
+
|
|
730
|
+
#### `/api/hazo_auth/me` (GET) - Standardized User Info Endpoint
|
|
731
|
+
|
|
732
|
+
**⚠️ IMPORTANT: Use this endpoint for all client-side authentication checks. It always returns the same standardized format with permissions.**
|
|
733
|
+
|
|
734
|
+
This is the **standardized endpoint** that ensures consistent response format across all projects. It always includes permissions and user information in a unified structure.
|
|
735
|
+
|
|
736
|
+
**Endpoint:** `GET /api/hazo_auth/me`
|
|
737
|
+
|
|
738
|
+
**Response Format (Authenticated):**
|
|
739
|
+
```typescript
|
|
740
|
+
{
|
|
741
|
+
authenticated: true,
|
|
742
|
+
// Top-level fields (for backward compatibility)
|
|
743
|
+
user_id: string,
|
|
744
|
+
email: string,
|
|
745
|
+
name: string | null,
|
|
746
|
+
email_verified: boolean,
|
|
747
|
+
last_logon: string | undefined,
|
|
748
|
+
profile_picture_url: string | null,
|
|
749
|
+
profile_source: "upload" | "library" | "gravatar" | "custom" | undefined,
|
|
750
|
+
// Permissions (always included)
|
|
751
|
+
user: {
|
|
752
|
+
id: string,
|
|
753
|
+
email_address: string,
|
|
754
|
+
name: string | null,
|
|
755
|
+
is_active: boolean,
|
|
756
|
+
profile_picture_url: string | null,
|
|
757
|
+
},
|
|
758
|
+
permissions: string[],
|
|
759
|
+
permission_ok: boolean,
|
|
760
|
+
missing_permissions?: string[],
|
|
761
|
+
}
|
|
762
|
+
```
|
|
763
|
+
|
|
764
|
+
**Response Format (Not Authenticated):**
|
|
765
|
+
```typescript
|
|
766
|
+
{
|
|
767
|
+
authenticated: false
|
|
768
|
+
}
|
|
769
|
+
```
|
|
770
|
+
|
|
771
|
+
**Example Usage:**
|
|
772
|
+
|
|
773
|
+
```typescript
|
|
774
|
+
// Client-side (React component)
|
|
775
|
+
const response = await fetch("/api/hazo_auth/me", {
|
|
776
|
+
method: "GET",
|
|
777
|
+
credentials: "include",
|
|
778
|
+
});
|
|
779
|
+
|
|
780
|
+
const data = await response.json();
|
|
781
|
+
|
|
782
|
+
if (data.authenticated) {
|
|
783
|
+
console.log("User:", data.user);
|
|
784
|
+
console.log("Email:", data.email);
|
|
785
|
+
console.log("Permissions:", data.permissions);
|
|
786
|
+
console.log("Permission OK:", data.permission_ok);
|
|
787
|
+
}
|
|
788
|
+
```
|
|
789
|
+
|
|
790
|
+
**Why Use `/api/hazo_auth/me`?**
|
|
791
|
+
- ✅ **Standardized format** - Always returns the same structure
|
|
792
|
+
- ✅ **Always includes permissions** - No need for separate permission checks
|
|
793
|
+
- ✅ **Backward compatible** - Top-level fields work with existing code
|
|
794
|
+
- ✅ **Single source of truth** - Prevents downstream variations
|
|
795
|
+
|
|
796
|
+
**Note:** The `use_auth_status` hook automatically uses this endpoint and includes permissions in its return value.
|
|
797
|
+
|
|
683
798
|
### Server-Side Functions
|
|
684
799
|
|
|
685
800
|
#### `hazo_get_auth` (Recommended)
|
|
@@ -917,13 +1032,22 @@ enable_friendly_error_messages = true
|
|
|
917
1032
|
## Profile Picture Menu Widget
|
|
918
1033
|
|
|
919
1034
|
The Profile Picture Menu is a versatile component for navbar or sidebar that automatically displays:
|
|
920
|
-
- **When authenticated**: User's profile picture with a dropdown menu containing user info, settings link, logout, and custom menu items
|
|
1035
|
+
- **When authenticated**: User's profile picture with a dropdown menu (navbar) or sidebar menu (sidebar) containing user info, settings link, logout, and custom menu items
|
|
921
1036
|
- **When not authenticated**: Sign Up and Sign In buttons (or a single button, configurable)
|
|
922
1037
|
|
|
1038
|
+
### Variants
|
|
1039
|
+
|
|
1040
|
+
The component supports two rendering variants:
|
|
1041
|
+
|
|
1042
|
+
- **`dropdown`** (default): Renders as a clickable avatar that opens a dropdown menu. Use this for navbar/header contexts.
|
|
1043
|
+
- **`sidebar`**: Shows profile picture and name in a sidebar group. Clicking opens a dropdown menu with account actions. Use this inside `SidebarContent` for sidebar navigation.
|
|
1044
|
+
|
|
923
1045
|
### Basic Usage (Recommended)
|
|
924
1046
|
|
|
925
1047
|
Use the `ProfilePicMenuWrapper` component which automatically loads configuration from `hazo_auth_config.ini`:
|
|
926
1048
|
|
|
1049
|
+
#### Dropdown Variant (Navbar/Header)
|
|
1050
|
+
|
|
927
1051
|
```typescript
|
|
928
1052
|
// In your navbar or layout component
|
|
929
1053
|
import { ProfilePicMenuWrapper } from "hazo_auth/components/layouts/shared/components/profile_pic_menu_wrapper";
|
|
@@ -935,12 +1059,65 @@ export function Navbar() {
|
|
|
935
1059
|
<ProfilePicMenuWrapper
|
|
936
1060
|
avatar_size="default" // "sm" | "default" | "lg"
|
|
937
1061
|
className="ml-auto"
|
|
1062
|
+
// variant="dropdown" is the default
|
|
938
1063
|
/>
|
|
939
1064
|
</nav>
|
|
940
1065
|
);
|
|
941
1066
|
}
|
|
942
1067
|
```
|
|
943
1068
|
|
|
1069
|
+
#### Sidebar Variant
|
|
1070
|
+
|
|
1071
|
+
The sidebar variant shows only the profile picture and name. Clicking opens a dropdown menu with account actions:
|
|
1072
|
+
|
|
1073
|
+
```typescript
|
|
1074
|
+
// In your sidebar component
|
|
1075
|
+
import { ProfilePicMenu } from "hazo_auth/components/layouts/shared";
|
|
1076
|
+
import { SidebarContent } from "hazo_auth/components/ui/sidebar";
|
|
1077
|
+
|
|
1078
|
+
export function Sidebar() {
|
|
1079
|
+
return (
|
|
1080
|
+
<SidebarContent>
|
|
1081
|
+
{/* Other sidebar groups */}
|
|
1082
|
+
|
|
1083
|
+
{/* Profile menu as sidebar variant - shows avatar + name, clicking opens dropdown */}
|
|
1084
|
+
<ProfilePicMenu
|
|
1085
|
+
variant="sidebar"
|
|
1086
|
+
avatar_size="sm"
|
|
1087
|
+
sidebar_group_label="Account" // Optional: defaults to "Account"
|
|
1088
|
+
className="mt-auto" // Optional: push to bottom
|
|
1089
|
+
/>
|
|
1090
|
+
</SidebarContent>
|
|
1091
|
+
);
|
|
1092
|
+
}
|
|
1093
|
+
```
|
|
1094
|
+
|
|
1095
|
+
### Direct Usage (Advanced)
|
|
1096
|
+
|
|
1097
|
+
If you need more control, use `ProfilePicMenu` directly:
|
|
1098
|
+
|
|
1099
|
+
```typescript
|
|
1100
|
+
import { ProfilePicMenu } from "hazo_auth/components/layouts/shared";
|
|
1101
|
+
|
|
1102
|
+
// Dropdown variant (navbar)
|
|
1103
|
+
<ProfilePicMenu
|
|
1104
|
+
variant="dropdown"
|
|
1105
|
+
avatar_size="sm"
|
|
1106
|
+
settings_path="/settings"
|
|
1107
|
+
logout_path="/api/logout"
|
|
1108
|
+
/>
|
|
1109
|
+
|
|
1110
|
+
// Sidebar variant
|
|
1111
|
+
<ProfilePicMenu
|
|
1112
|
+
variant="sidebar"
|
|
1113
|
+
avatar_size="sm"
|
|
1114
|
+
sidebar_group_label="My Account"
|
|
1115
|
+
custom_menu_items={[
|
|
1116
|
+
{ type: "link", label: "Dashboard", href: "/dashboard", order: 1, id: "dashboard" }
|
|
1117
|
+
]}
|
|
1118
|
+
/>
|
|
1119
|
+
```
|
|
1120
|
+
|
|
944
1121
|
### Configuration
|
|
945
1122
|
|
|
946
1123
|
```ini
|
package/SETUP_CHECKLIST.md
CHANGED
|
@@ -392,6 +392,41 @@ SELECT table_name FROM information_schema.tables WHERE table_name LIKE 'hazo_%';
|
|
|
392
392
|
|
|
393
393
|
---
|
|
394
394
|
|
|
395
|
+
## Phase 3.1: Configure Default Permissions (Optional)
|
|
396
|
+
|
|
397
|
+
The `hazo_auth_config.ini` file includes default permissions that will be available in the Permissions tab. These defaults are already configured when you run `npx hazo_auth init`.
|
|
398
|
+
|
|
399
|
+
**Default permissions included:**
|
|
400
|
+
- `admin_user_management`
|
|
401
|
+
- `admin_role_management`
|
|
402
|
+
- `admin_permission_management`
|
|
403
|
+
|
|
404
|
+
**To customize permissions:**
|
|
405
|
+
|
|
406
|
+
Edit `hazo_auth_config.ini`:
|
|
407
|
+
```ini
|
|
408
|
+
[hazo_auth__user_management]
|
|
409
|
+
application_permission_list_defaults = admin_user_management,admin_role_management,admin_permission_management
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
**To initialize permissions and create a super user:**
|
|
413
|
+
|
|
414
|
+
After setting up your database and configuring permissions, you can run:
|
|
415
|
+
```bash
|
|
416
|
+
npm run init-users
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
This script will:
|
|
420
|
+
1. Create all permissions from `application_permission_list_defaults`
|
|
421
|
+
2. Create a `default_super_user_role` role with all permissions
|
|
422
|
+
3. Assign the role to the user specified in `default_super_user_email` (configure in `[hazo_auth__initial_setup]` section)
|
|
423
|
+
|
|
424
|
+
**Checklist:**
|
|
425
|
+
- [ ] Default permissions configured in `hazo_auth_config.ini` (already set by default)
|
|
426
|
+
- [ ] `default_super_user_email` configured if you want to use `init-users` script
|
|
427
|
+
|
|
428
|
+
---
|
|
429
|
+
|
|
395
430
|
## Phase 4: API Routes
|
|
396
431
|
|
|
397
432
|
Create API route files in your project. Each file re-exports handlers from hazo_auth.
|
|
@@ -427,8 +462,14 @@ app/api/hazo_auth/
|
|
|
427
462
|
├── library_photos/route.ts
|
|
428
463
|
├── get_auth/route.ts
|
|
429
464
|
├── validate_reset_token/route.ts
|
|
430
|
-
|
|
431
|
-
|
|
465
|
+
├── profile_picture/
|
|
466
|
+
│ └── [filename]/route.ts
|
|
467
|
+
└── user_management/
|
|
468
|
+
├── users/route.ts
|
|
469
|
+
├── permissions/route.ts
|
|
470
|
+
├── roles/route.ts
|
|
471
|
+
└── users/
|
|
472
|
+
└── roles/route.ts
|
|
432
473
|
```
|
|
433
474
|
|
|
434
475
|
**Example route file content:**
|
|
@@ -513,9 +554,34 @@ export { POST } from "hazo_auth/server/routes/validate_reset_token";
|
|
|
513
554
|
export { GET } from "hazo_auth/server/routes/profile_picture_filename";
|
|
514
555
|
```
|
|
515
556
|
|
|
557
|
+
**User Management routes (optional - required if using UserManagementLayout):**
|
|
558
|
+
|
|
559
|
+
`app/api/hazo_auth/user_management/users/route.ts`:
|
|
560
|
+
```typescript
|
|
561
|
+
export { GET, PATCH, POST } from "hazo_auth/server/routes";
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
`app/api/hazo_auth/user_management/permissions/route.ts`:
|
|
565
|
+
```typescript
|
|
566
|
+
export { GET, POST, PUT, DELETE } from "hazo_auth/server/routes";
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
`app/api/hazo_auth/user_management/roles/route.ts`:
|
|
570
|
+
```typescript
|
|
571
|
+
export { GET, POST, PUT } from "hazo_auth/server/routes";
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
`app/api/hazo_auth/user_management/users/roles/route.ts`:
|
|
575
|
+
```typescript
|
|
576
|
+
export { GET, POST, PUT } from "hazo_auth/server/routes";
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
**Note:** The `generate-routes` command automatically creates all user_management routes. These routes are required if you plan to use the `UserManagementLayout` component for managing users, roles, and permissions.
|
|
580
|
+
|
|
516
581
|
**Checklist:**
|
|
517
|
-
- [ ] All 16 API route files created
|
|
518
|
-
- [ ]
|
|
582
|
+
- [ ] All 16 core API route files created
|
|
583
|
+
- [ ] User management routes created (if using UserManagementLayout)
|
|
584
|
+
- [ ] Each file exports the correct HTTP method (POST, GET, PATCH, DELETE, PUT)
|
|
519
585
|
|
|
520
586
|
---
|
|
521
587
|
|
|
@@ -616,19 +682,51 @@ export default function CustomLoginPage() {
|
|
|
616
682
|
|
|
617
683
|
Run these tests to verify your setup is working correctly.
|
|
618
684
|
|
|
619
|
-
### Test 1: API Health Check
|
|
685
|
+
### Test 1: API Health Check - Standardized `/api/hazo_auth/me` Endpoint
|
|
686
|
+
|
|
687
|
+
**⚠️ IMPORTANT: Use `/api/hazo_auth/me` for all client-side authentication checks. It always returns a standardized format with permissions.**
|
|
620
688
|
|
|
621
689
|
```bash
|
|
622
690
|
curl -s http://localhost:3000/api/hazo_auth/me | jq
|
|
623
691
|
```
|
|
624
692
|
|
|
625
|
-
**Expected response:**
|
|
693
|
+
**Expected response (not authenticated):**
|
|
626
694
|
```json
|
|
627
695
|
{
|
|
628
696
|
"authenticated": false
|
|
629
697
|
}
|
|
630
698
|
```
|
|
631
699
|
|
|
700
|
+
**Expected response (authenticated - standardized format):**
|
|
701
|
+
```json
|
|
702
|
+
{
|
|
703
|
+
"authenticated": true,
|
|
704
|
+
"user_id": "28fe0aff-29c7-407e-b92e-bf11a6a3332f",
|
|
705
|
+
"email": "test@example.com",
|
|
706
|
+
"name": "Test User",
|
|
707
|
+
"email_verified": false,
|
|
708
|
+
"last_logon": "2025-01-27T16:18:00.054Z",
|
|
709
|
+
"profile_picture_url": "https://gravatar.com/avatar/...",
|
|
710
|
+
"profile_source": "gravatar",
|
|
711
|
+
"user": {
|
|
712
|
+
"id": "28fe0aff-29c7-407e-b92e-bf11a6a3332f",
|
|
713
|
+
"email_address": "test@example.com",
|
|
714
|
+
"name": "Test User",
|
|
715
|
+
"is_active": true,
|
|
716
|
+
"profile_picture_url": "https://gravatar.com/avatar/..."
|
|
717
|
+
},
|
|
718
|
+
"permissions": [],
|
|
719
|
+
"permission_ok": true
|
|
720
|
+
}
|
|
721
|
+
```
|
|
722
|
+
|
|
723
|
+
**Key Points:**
|
|
724
|
+
- ✅ Always returns the same standardized format
|
|
725
|
+
- ✅ Always includes `permissions` and `permission_ok` fields
|
|
726
|
+
- ✅ Top-level fields (`user_id`, `email`, `name`) for backward compatibility
|
|
727
|
+
- ✅ `user` object contains full user details
|
|
728
|
+
- ✅ Use this endpoint instead of `/api/hazo_auth/get_auth` for client-side code
|
|
729
|
+
|
|
632
730
|
### Test 2: Registration API
|
|
633
731
|
|
|
634
732
|
```bash
|
|
@@ -1,3 +1,32 @@
|
|
|
1
1
|
import { NextRequest, NextResponse } from "next/server";
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* GET /api/hazo_auth/me
|
|
4
|
+
*
|
|
5
|
+
* Standardized endpoint that returns authenticated user information with permissions.
|
|
6
|
+
* Always returns the same format to prevent downstream variations.
|
|
7
|
+
*
|
|
8
|
+
* Response format (authenticated):
|
|
9
|
+
* {
|
|
10
|
+
* authenticated: true,
|
|
11
|
+
* user_id: string,
|
|
12
|
+
* email: string,
|
|
13
|
+
* name: string | null,
|
|
14
|
+
* email_verified: boolean,
|
|
15
|
+
* last_logon: string | undefined,
|
|
16
|
+
* profile_picture_url: string | null,
|
|
17
|
+
* profile_source: "upload" | "library" | "gravatar" | "custom" | undefined,
|
|
18
|
+
* user: { id, email_address, name, is_active, profile_picture_url },
|
|
19
|
+
* permissions: string[],
|
|
20
|
+
* permission_ok: boolean,
|
|
21
|
+
* missing_permissions?: string[],
|
|
22
|
+
* }
|
|
23
|
+
*
|
|
24
|
+
* Response format (not authenticated):
|
|
25
|
+
* {
|
|
26
|
+
* authenticated: false
|
|
27
|
+
* }
|
|
28
|
+
*/
|
|
29
|
+
export declare function GET(request: NextRequest): Promise<NextResponse<{
|
|
30
|
+
authenticated: boolean;
|
|
31
|
+
}>>;
|
|
3
32
|
//# sourceMappingURL=route.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../src/app/api/hazo_auth/me/route.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../src/app/api/hazo_auth/me/route.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AASxD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,GAAG,CAAC,OAAO,EAAE,WAAW;;IA0E7C"}
|
|
@@ -1,33 +1,93 @@
|
|
|
1
|
-
// file_description: API route to get current authenticated user information
|
|
1
|
+
// file_description: API route to get current authenticated user information with permissions
|
|
2
|
+
// This is the standardized endpoint that always returns the same format including permissions
|
|
2
3
|
// section: imports
|
|
3
4
|
import { NextResponse } from "next/server";
|
|
4
|
-
import {
|
|
5
|
+
import { hazo_get_auth } from "../../../../lib/auth/hazo_get_auth.server";
|
|
6
|
+
import { get_hazo_connect_instance } from "../../../../lib/hazo_connect_instance.server";
|
|
7
|
+
import { createCrudService } from "hazo_connect/server";
|
|
8
|
+
import { map_db_source_to_ui } from "../../../../lib/services/profile_picture_source_mapper";
|
|
9
|
+
import { create_app_logger } from "../../../../lib/app_logger";
|
|
10
|
+
import { get_filename, get_line_number } from "../../../../lib/utils/api_route_helpers";
|
|
5
11
|
// section: api_handler
|
|
12
|
+
/**
|
|
13
|
+
* GET /api/hazo_auth/me
|
|
14
|
+
*
|
|
15
|
+
* Standardized endpoint that returns authenticated user information with permissions.
|
|
16
|
+
* Always returns the same format to prevent downstream variations.
|
|
17
|
+
*
|
|
18
|
+
* Response format (authenticated):
|
|
19
|
+
* {
|
|
20
|
+
* authenticated: true,
|
|
21
|
+
* user_id: string,
|
|
22
|
+
* email: string,
|
|
23
|
+
* name: string | null,
|
|
24
|
+
* email_verified: boolean,
|
|
25
|
+
* last_logon: string | undefined,
|
|
26
|
+
* profile_picture_url: string | null,
|
|
27
|
+
* profile_source: "upload" | "library" | "gravatar" | "custom" | undefined,
|
|
28
|
+
* user: { id, email_address, name, is_active, profile_picture_url },
|
|
29
|
+
* permissions: string[],
|
|
30
|
+
* permission_ok: boolean,
|
|
31
|
+
* missing_permissions?: string[],
|
|
32
|
+
* }
|
|
33
|
+
*
|
|
34
|
+
* Response format (not authenticated):
|
|
35
|
+
* {
|
|
36
|
+
* authenticated: false
|
|
37
|
+
* }
|
|
38
|
+
*/
|
|
6
39
|
export async function GET(request) {
|
|
40
|
+
const logger = create_app_logger();
|
|
7
41
|
try {
|
|
8
|
-
// Use
|
|
9
|
-
const
|
|
10
|
-
// If response is provided, it means cookies were cleared (invalid auth)
|
|
11
|
-
if (response) {
|
|
12
|
-
return response;
|
|
13
|
-
}
|
|
42
|
+
// Use hazo_get_auth to get user with permissions
|
|
43
|
+
const auth_result = await hazo_get_auth(request);
|
|
14
44
|
// If not authenticated, return false
|
|
15
45
|
if (!auth_result.authenticated) {
|
|
16
46
|
return NextResponse.json({ authenticated: false }, { status: 200 });
|
|
17
47
|
}
|
|
18
|
-
//
|
|
48
|
+
// Fetch additional user fields from database (email_verified, last_logon, profile_source)
|
|
49
|
+
const hazoConnect = get_hazo_connect_instance();
|
|
50
|
+
const users_service = createCrudService(hazoConnect, "hazo_users");
|
|
51
|
+
const users = await users_service.findBy({ id: auth_result.user.id });
|
|
52
|
+
if (!Array.isArray(users) || users.length === 0) {
|
|
53
|
+
logger.warn("me_endpoint_user_not_found", {
|
|
54
|
+
filename: get_filename(),
|
|
55
|
+
line_number: get_line_number(),
|
|
56
|
+
user_id: auth_result.user.id,
|
|
57
|
+
message: "User found in auth but not in database",
|
|
58
|
+
});
|
|
59
|
+
return NextResponse.json({ authenticated: false }, { status: 200 });
|
|
60
|
+
}
|
|
61
|
+
const user_db = users[0];
|
|
62
|
+
// Map database profile_source to UI representation
|
|
63
|
+
const profile_source_db = user_db.profile_source;
|
|
64
|
+
const profile_source_ui = profile_source_db ? map_db_source_to_ui(profile_source_db) : undefined;
|
|
65
|
+
// Return unified format with all fields
|
|
19
66
|
return NextResponse.json({
|
|
20
67
|
authenticated: true,
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
68
|
+
// Top-level fields for backward compatibility
|
|
69
|
+
user_id: auth_result.user.id,
|
|
70
|
+
email: auth_result.user.email_address,
|
|
71
|
+
name: auth_result.user.name,
|
|
72
|
+
email_verified: user_db.email_verified === true,
|
|
73
|
+
last_logon: user_db.last_logon || undefined,
|
|
74
|
+
profile_picture_url: auth_result.user.profile_picture_url,
|
|
75
|
+
profile_source: profile_source_ui,
|
|
76
|
+
// Permissions and user object (always included)
|
|
77
|
+
user: auth_result.user,
|
|
78
|
+
permissions: auth_result.permissions,
|
|
79
|
+
permission_ok: auth_result.permission_ok,
|
|
80
|
+
missing_permissions: auth_result.missing_permissions,
|
|
28
81
|
}, { status: 200 });
|
|
29
82
|
}
|
|
30
83
|
catch (error) {
|
|
84
|
+
const error_message = error instanceof Error ? error.message : "Unknown error";
|
|
85
|
+
logger.error("me_endpoint_error", {
|
|
86
|
+
filename: get_filename(),
|
|
87
|
+
line_number: get_line_number(),
|
|
88
|
+
error_message,
|
|
89
|
+
error_stack: error instanceof Error ? error.stack : undefined,
|
|
90
|
+
});
|
|
31
91
|
// On error, assume not authenticated
|
|
32
92
|
return NextResponse.json({ authenticated: false }, { status: 200 });
|
|
33
93
|
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { NextRequest, NextResponse } from "next/server";
|
|
2
|
+
export declare const dynamic = "force-dynamic";
|
|
3
|
+
/**
|
|
4
|
+
* GET - Fetch all permissions from database and config
|
|
5
|
+
*/
|
|
6
|
+
export declare function GET(request: NextRequest): Promise<NextResponse<{
|
|
7
|
+
error: string;
|
|
8
|
+
}> | NextResponse<{
|
|
9
|
+
success: boolean;
|
|
10
|
+
db_permissions: {
|
|
11
|
+
id: unknown;
|
|
12
|
+
permission_name: unknown;
|
|
13
|
+
description: {};
|
|
14
|
+
}[];
|
|
15
|
+
config_permissions: string[];
|
|
16
|
+
}>>;
|
|
17
|
+
/**
|
|
18
|
+
* POST - Create new permission or migrate config permissions to database
|
|
19
|
+
*/
|
|
20
|
+
export declare function POST(request: NextRequest): Promise<NextResponse<{
|
|
21
|
+
success: boolean;
|
|
22
|
+
created: string[];
|
|
23
|
+
skipped: string[];
|
|
24
|
+
}> | NextResponse<{
|
|
25
|
+
error: string;
|
|
26
|
+
}> | NextResponse<{
|
|
27
|
+
success: boolean;
|
|
28
|
+
permission: {
|
|
29
|
+
id: number;
|
|
30
|
+
permission_name: string;
|
|
31
|
+
description: any;
|
|
32
|
+
};
|
|
33
|
+
}>>;
|
|
34
|
+
/**
|
|
35
|
+
* PUT - Update permission description
|
|
36
|
+
*/
|
|
37
|
+
export declare function PUT(request: NextRequest): Promise<NextResponse<{
|
|
38
|
+
error: string;
|
|
39
|
+
}> | NextResponse<{
|
|
40
|
+
success: boolean;
|
|
41
|
+
}>>;
|
|
42
|
+
/**
|
|
43
|
+
* DELETE - Delete permission from database
|
|
44
|
+
*/
|
|
45
|
+
export declare function DELETE(request: NextRequest): Promise<NextResponse<{
|
|
46
|
+
error: string;
|
|
47
|
+
}> | NextResponse<{
|
|
48
|
+
success: boolean;
|
|
49
|
+
}>>;
|
|
50
|
+
//# sourceMappingURL=route.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../src/app/api/hazo_auth/user_management/permissions/route.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAQxD,eAAO,MAAM,OAAO,kBAAkB,CAAC;AAGvC;;GAEG;AACH,wBAAsB,GAAG,CAAC,OAAO,EAAE,WAAW;;;;;;;;;;IAgE7C;AAED;;GAEG;AACH,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW;;;;;;;;;;;;;IAyJ9C;AAED;;GAEG;AACH,wBAAsB,GAAG,CAAC,OAAO,EAAE,WAAW;;;;IAkD7C;AAED;;GAEG;AACH,wBAAsB,MAAM,CAAC,OAAO,EAAE,WAAW;;;;IAmEhD"}
|