131 lines
2.8 KiB
Markdown
131 lines
2.8 KiB
Markdown
# Quickstart: Global Policy Search
|
|
|
|
**Feature**: 001-global-policy-search
|
|
**Time Estimate**: ~4 hours
|
|
|
|
---
|
|
|
|
## Prerequisites
|
|
|
|
- [x] Node.js 20+
|
|
- [x] PostgreSQL running (Docker: `tenantpilot-db`)
|
|
- [x] Azure AD app registration configured
|
|
- [ ] `POLICY_API_SECRET` environment variable set
|
|
|
|
---
|
|
|
|
## Step 1: Add Environment Variable
|
|
|
|
Add to `.env`:
|
|
|
|
```bash
|
|
# API Secret for n8n ingestion (generate a strong random string)
|
|
POLICY_API_SECRET=your-secure-random-secret-here
|
|
```
|
|
|
|
Generate a secure secret:
|
|
```bash
|
|
openssl rand -base64 32
|
|
```
|
|
|
|
---
|
|
|
|
## Step 2: Create Database Schema
|
|
|
|
Create the policy settings schema file:
|
|
|
|
```bash
|
|
# File: lib/db/schema/policySettings.ts
|
|
```
|
|
|
|
Then push to database:
|
|
|
|
```bash
|
|
npm run db:push
|
|
```
|
|
|
|
---
|
|
|
|
## Step 3: Extend NextAuth Session
|
|
|
|
Update `lib/auth/utils.ts` to include `tenantId` in session from Azure AD `tid` claim.
|
|
|
|
---
|
|
|
|
## Step 4: Create Server Actions
|
|
|
|
Create `lib/actions/policySettings.ts` with:
|
|
- `searchPolicySettings(searchTerm)`
|
|
- `getPolicySettingById(id)`
|
|
- `getRecentPolicySettings(limit)`
|
|
|
|
---
|
|
|
|
## Step 5: Create Ingestion API Route
|
|
|
|
Create `app/api/policy-settings/route.ts`:
|
|
- POST handler with `X-API-SECRET` validation
|
|
- Bulk upsert logic with `onConflictDoUpdate`
|
|
|
|
---
|
|
|
|
## Step 6: Create Search UI
|
|
|
|
1. Create search page: `app/(app)/search/page.tsx`
|
|
2. Create search input component with Shadcn UI
|
|
3. Create results table component
|
|
|
|
---
|
|
|
|
## Step 7: Add Navigation
|
|
|
|
Update `config/nav.ts` to include search page in sidebar.
|
|
|
|
---
|
|
|
|
## Testing the Ingestion API
|
|
|
|
```bash
|
|
curl -X POST http://localhost:3000/api/policy-settings \
|
|
-H "Content-Type: application/json" \
|
|
-H "X-API-SECRET: your-secret-here" \
|
|
-d '{
|
|
"settings": [
|
|
{
|
|
"tenantId": "your-azure-tenant-id",
|
|
"policyName": "Test Policy",
|
|
"policyType": "deviceConfiguration",
|
|
"settingName": "TestSetting",
|
|
"settingValue": "enabled",
|
|
"graphPolicyId": "test-graph-id"
|
|
}
|
|
]
|
|
}'
|
|
```
|
|
|
|
---
|
|
|
|
## File Checklist
|
|
|
|
| File | Purpose | Status |
|
|
|------|---------|--------|
|
|
| `lib/db/schema/policySettings.ts` | Drizzle schema | ⬜ |
|
|
| `lib/validators/policySettings.ts` | Zod validation | ⬜ |
|
|
| `lib/actions/policySettings.ts` | Server Actions | ⬜ |
|
|
| `app/api/policy-settings/route.ts` | Ingestion API | ⬜ |
|
|
| `app/(app)/search/page.tsx` | Search page | ⬜ |
|
|
| `components/search/SearchInput.tsx` | Search input | ⬜ |
|
|
| `components/search/ResultsTable.tsx` | Results display | ⬜ |
|
|
| `lib/auth/utils.ts` | Session with tenantId | ⬜ |
|
|
| `config/nav.ts` | Navigation update | ⬜ |
|
|
| `.env` | POLICY_API_SECRET | ⬜ |
|
|
|
|
---
|
|
|
|
## Verify Setup
|
|
|
|
1. **Database**: `npm run db:push` succeeds
|
|
2. **Auth**: Login shows tenantId in session
|
|
3. **API**: POST to `/api/policy-settings` with secret returns 200
|
|
4. **Search**: Search page shows results after ingestion
|