removed unused route

This commit is contained in:
waleed
2026-02-09 16:46:29 -08:00
parent e60e5157de
commit a991801a14
5 changed files with 134 additions and 144 deletions

View File

@@ -1,111 +0,0 @@
import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server'
import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid'
import { validateJiraCloudId, validateJiraIssueKey } from '@/lib/core/security/input-validation'
import { getJiraCloudId } from '@/tools/jira/utils'
export const dynamic = 'force-dynamic'
const logger = createLogger('JiraIssueAPI')
export async function POST(request: NextRequest) {
try {
const auth = await checkSessionOrInternalAuth(request)
if (!auth.success || !auth.userId) {
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
}
const { domain, accessToken, issueId, cloudId: providedCloudId } = await request.json()
if (!domain) {
logger.error('Missing domain in request')
return NextResponse.json({ error: 'Domain is required' }, { status: 400 })
}
if (!accessToken) {
logger.error('Missing access token in request')
return NextResponse.json({ error: 'Access token is required' }, { status: 400 })
}
if (!issueId) {
logger.error('Missing issue ID in request')
return NextResponse.json({ error: 'Issue ID is required' }, { status: 400 })
}
const cloudId = providedCloudId || (await getJiraCloudId(domain, accessToken))
logger.info('Using cloud ID:', cloudId)
const cloudIdValidation = validateJiraCloudId(cloudId, 'cloudId')
if (!cloudIdValidation.isValid) {
return NextResponse.json({ error: cloudIdValidation.error }, { status: 400 })
}
const issueIdValidation = validateJiraIssueKey(issueId, 'issueId')
if (!issueIdValidation.isValid) {
return NextResponse.json({ error: issueIdValidation.error }, { status: 400 })
}
const url = `https://api.atlassian.com/ex/jira/${cloudId}/rest/api/3/issue/${issueId}`
logger.info('Fetching Jira issue from:', url)
const response = await fetch(url, {
method: 'GET',
headers: {
Authorization: `Bearer ${accessToken}`,
Accept: 'application/json',
},
})
if (!response.ok) {
logger.error('Jira API error:', {
status: response.status,
statusText: response.statusText,
})
let errorMessage
try {
const errorData = await response.json()
logger.error('Error details:', errorData)
errorMessage = errorData.message || `Failed to fetch issue (${response.status})`
} catch (_e) {
errorMessage = `Failed to fetch issue: ${response.status} ${response.statusText}`
}
return NextResponse.json({ error: errorMessage }, { status: response.status })
}
const data = await response.json()
logger.info('Successfully fetched issue:', data.key)
const issueInfo: any = {
id: data.key,
name: data.fields.summary,
mimeType: 'jira/issue',
url: `https://${domain}/browse/${data.key}`,
modifiedTime: data.fields.updated,
webViewLink: `https://${domain}/browse/${data.key}`,
status: data.fields.status?.name,
description: data.fields.description,
priority: data.fields.priority?.name,
assignee: data.fields.assignee?.displayName,
reporter: data.fields.reporter?.displayName,
project: {
key: data.fields.project?.key,
name: data.fields.project?.name,
},
}
return NextResponse.json({
issue: issueInfo,
cloudId,
})
} catch (error) {
logger.error('Error processing request:', error)
return NextResponse.json(
{
error: 'Failed to retrieve Jira issue',
details: (error as Error).message,
},
{ status: 500 }
)
}
}

View File

@@ -1,4 +1,5 @@
import { randomUUID } from 'crypto'
import type { ItemCreateParams } from '@1password/sdk'
import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod'
@@ -62,15 +63,13 @@ export async function POST(request: NextRequest) {
}))
: undefined
// Cast to any because toSdkCategory/toSdkFieldType return string literals
// that match SDK enum values but TypeScript can't verify this at compile time
const item = await client.items.create({
vaultId: params.vaultId,
category: toSdkCategory(params.category) as any,
category: toSdkCategory(params.category),
title: params.title || '',
tags: parsedTags,
fields: parsedFields as any,
})
fields: parsedFields,
} as ItemCreateParams)
return NextResponse.json(normalizeSdkItem(item))
}

View File

@@ -1,4 +1,5 @@
import { randomUUID } from 'crypto'
import type { Item } from '@1password/sdk'
import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod'
@@ -79,9 +80,9 @@ export async function POST(request: NextRequest) {
autofillBehavior: 'AnywhereOnWebsite' as const,
}))
: existing.websites,
}
} as Item
const result = await client.items.put(sdkItem as any)
const result = await client.items.put(sdkItem)
return NextResponse.json(normalizeSdkItem(result))
}

View File

@@ -35,11 +35,7 @@ export async function POST(request: NextRequest) {
const body = await request.json()
const params = UpdateItemSchema.parse(body)
const creds = resolveCredentials(params)
const ops = JSON.parse(params.operations) as Array<{
op: string
path: string
value?: unknown
}>
const ops = JSON.parse(params.operations) as JsonPatchOperation[]
logger.info(
`[${requestId}] Updating item ${params.itemId} in vault ${params.vaultId} (${creds.mode} mode)`
@@ -48,7 +44,6 @@ export async function POST(request: NextRequest) {
if (creds.mode === 'service_account') {
const client = await createOnePasswordClient(creds.serviceAccountToken!)
// SDK doesn't support PATCH — fetch, apply patches, then put
const item = await client.items.get(params.vaultId, params.itemId)
for (const op of ops) {
@@ -89,8 +84,15 @@ export async function POST(request: NextRequest) {
}
}
/** Apply a single RFC6902 JSON Patch operation to a mutable SDK Item. */
function applyPatch(item: Record<string, any>, op: { op: string; path: string; value?: unknown }) {
interface JsonPatchOperation {
op: 'add' | 'remove' | 'replace'
path: string
value?: unknown
}
/** Apply a single RFC6902 JSON Patch operation to a mutable object. */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function applyPatch(item: Record<string, any>, op: JsonPatchOperation) {
const segments = op.path.split('/').filter(Boolean)
if (segments.length === 1) {
@@ -103,7 +105,6 @@ function applyPatch(item: Record<string, any>, op: { op: string; path: string; v
return
}
// Navigate to parent of target
let target = item
for (let i = 0; i < segments.length - 1; i++) {
const seg = segments[i]

View File

@@ -1,12 +1,112 @@
import type {
Item,
ItemCategory,
ItemField,
ItemFieldType,
ItemOverview,
ItemSection,
VaultOverview,
Website,
} from '@1password/sdk'
import { createLogger } from '@sim/logger'
const logger = createLogger('OnePasswordRouteUtils')
/** Connect-format field type strings returned by normalization. */
type ConnectFieldType =
| 'STRING'
| 'CONCEALED'
| 'EMAIL'
| 'URL'
| 'OTP'
| 'PHONE'
| 'DATE'
| 'MONTH_YEAR'
| 'MENU'
| 'ADDRESS'
| 'REFERENCE'
| 'SSHKEY'
| 'CREDIT_CARD_NUMBER'
| 'CREDIT_CARD_TYPE'
/** Connect-format category strings returned by normalization. */
type ConnectCategory =
| 'LOGIN'
| 'PASSWORD'
| 'API_CREDENTIAL'
| 'SECURE_NOTE'
| 'SERVER'
| 'DATABASE'
| 'CREDIT_CARD'
| 'IDENTITY'
| 'SSH_KEY'
| 'DOCUMENT'
| 'SOFTWARE_LICENSE'
| 'EMAIL_ACCOUNT'
| 'MEMBERSHIP'
| 'PASSPORT'
| 'REWARD_PROGRAM'
| 'DRIVER_LICENSE'
| 'BANK_ACCOUNT'
| 'MEDICAL_RECORD'
| 'OUTDOOR_LICENSE'
| 'WIRELESS_ROUTER'
| 'SOCIAL_SECURITY_NUMBER'
| 'CUSTOM'
/** Normalized vault shape matching the Connect API response. */
export interface NormalizedVault {
id: string
name: string
description: null
attributeVersion: number
contentVersion: number
items: number
type: string
createdAt: string | null
updatedAt: string | null
}
/** Normalized item overview shape matching the Connect API response. */
export interface NormalizedItemOverview {
id: string
title: string
vault: { id: string }
category: ConnectCategory
urls: Array<{ href: string; label: string | null; primary: boolean }>
favorite: boolean
tags: string[]
version: number
state: string | null
createdAt: string | null
updatedAt: string | null
lastEditedBy: null
}
/** Normalized field shape matching the Connect API response. */
export interface NormalizedField {
id: string
label: string
type: ConnectFieldType
purpose: string
value: string | null
section: { id: string } | null
generate: boolean
recipe: null
entropy: null
}
/** Normalized full item shape matching the Connect API response. */
export interface NormalizedItem extends NormalizedItemOverview {
fields: NormalizedField[]
sections: Array<{ id: string; label: string }>
}
/**
* SDK field type string values → Connect field type mapping.
* Uses string literals instead of enum imports to avoid loading the WASM module at build time.
*/
const SDK_TO_CONNECT_FIELD_TYPE: Record<string, string> = {
const SDK_TO_CONNECT_FIELD_TYPE: Record<string, ConnectFieldType> = {
Text: 'STRING',
Concealed: 'CONCEALED',
Email: 'EMAIL',
@@ -24,7 +124,7 @@ const SDK_TO_CONNECT_FIELD_TYPE: Record<string, string> = {
}
/** SDK category string values → Connect category mapping. */
const SDK_TO_CONNECT_CATEGORY: Record<string, string> = {
const SDK_TO_CONNECT_CATEGORY: Record<string, ConnectCategory> = {
Login: 'LOGIN',
Password: 'PASSWORD',
ApiCredentials: 'API_CREDENTIAL',
@@ -52,7 +152,7 @@ const SDK_TO_CONNECT_CATEGORY: Record<string, string> = {
}
/** Connect category → SDK category string mapping. */
const CONNECT_TO_SDK_CATEGORY: Record<string, string> = {
const CONNECT_TO_SDK_CATEGORY: Record<string, `${ItemCategory}`> = {
LOGIN: 'Login',
PASSWORD: 'Password',
API_CREDENTIAL: 'ApiCredentials',
@@ -77,7 +177,7 @@ const CONNECT_TO_SDK_CATEGORY: Record<string, string> = {
}
/** Connect field type → SDK field type string mapping. */
const CONNECT_TO_SDK_FIELD_TYPE: Record<string, string> = {
const CONNECT_TO_SDK_FIELD_TYPE: Record<string, `${ItemFieldType}`> = {
STRING: 'Text',
CONCEALED: 'Concealed',
EMAIL: 'Email',
@@ -98,10 +198,10 @@ const CONNECT_TO_SDK_FIELD_TYPE: Record<string, string> = {
export type ConnectionMode = 'service_account' | 'connect'
export interface CredentialParams {
connectionMode?: ConnectionMode
serviceAccountToken?: string
serverUrl?: string
apiKey?: string
connectionMode?: ConnectionMode | null
serviceAccountToken?: string | null
serverUrl?: string | null
apiKey?: string | null
}
export interface ResolvedCredentials {
@@ -172,7 +272,7 @@ export async function connectRequest(options: {
}
/** Normalize an SDK VaultOverview to match Connect API vault shape. */
export function normalizeSdkVault(vault: Record<string, any>) {
export function normalizeSdkVault(vault: VaultOverview): NormalizedVault {
return {
id: vault.id,
name: vault.title,
@@ -189,13 +289,13 @@ export function normalizeSdkVault(vault: Record<string, any>) {
}
/** Normalize an SDK ItemOverview to match Connect API item summary shape. */
export function normalizeSdkItemOverview(item: Record<string, any>) {
export function normalizeSdkItemOverview(item: ItemOverview): NormalizedItemOverview {
return {
id: item.id,
title: item.title,
vault: { id: item.vaultId },
category: SDK_TO_CONNECT_CATEGORY[item.category] ?? 'CUSTOM',
urls: (item.websites ?? []).map((w: Record<string, any>) => ({
urls: item.websites.map((w: Website) => ({
href: w.url,
label: w.label ?? null,
primary: false,
@@ -213,13 +313,13 @@ export function normalizeSdkItemOverview(item: Record<string, any>) {
}
/** Normalize a full SDK Item to match Connect API FullItem shape. */
export function normalizeSdkItem(item: Record<string, any>) {
export function normalizeSdkItem(item: Item): NormalizedItem {
return {
id: item.id,
title: item.title,
vault: { id: item.vaultId },
category: SDK_TO_CONNECT_CATEGORY[item.category] ?? 'CUSTOM',
urls: (item.websites ?? []).map((w: Record<string, any>) => ({
urls: item.websites.map((w: Website) => ({
href: w.url,
label: w.label ?? null,
primary: false,
@@ -228,7 +328,7 @@ export function normalizeSdkItem(item: Record<string, any>) {
tags: item.tags ?? [],
version: item.version ?? 0,
state: null,
fields: (item.fields ?? []).map((field: Record<string, any>) => ({
fields: item.fields.map((field: ItemField) => ({
id: field.id,
label: field.title,
type: SDK_TO_CONNECT_FIELD_TYPE[field.fieldType] ?? 'STRING',
@@ -239,7 +339,7 @@ export function normalizeSdkItem(item: Record<string, any>) {
recipe: null,
entropy: null,
})),
sections: (item.sections ?? []).map((section: Record<string, any>) => ({
sections: item.sections.map((section: ItemSection) => ({
id: section.id,
label: section.title,
})),
@@ -252,11 +352,11 @@ export function normalizeSdkItem(item: Record<string, any>) {
}
/** Convert a Connect-style category string to the SDK category string. */
export function toSdkCategory(category: string): string {
export function toSdkCategory(category: string): `${ItemCategory}` {
return CONNECT_TO_SDK_CATEGORY[category] ?? 'Login'
}
/** Convert a Connect-style field type string to the SDK field type string. */
export function toSdkFieldType(type: string): string {
export function toSdkFieldType(type: string): `${ItemFieldType}` {
return CONNECT_TO_SDK_FIELD_TYPE[type] ?? 'Text'
}