Clarify Tahesab self-signed TLS fix with one-click enable.
Health already failed on certificate; search/import need allowInsecureTls on the connection. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -132,9 +132,14 @@ export class TahesabHttpClient {
|
|||||||
|
|
||||||
req.on('error', (err) => {
|
req.on('error', (err) => {
|
||||||
this.logger.error(`Tahesab call failed: ${path}`, err);
|
this.logger.error(`Tahesab call failed: ${path}`, err);
|
||||||
|
const raw = err.message || String(err);
|
||||||
|
const tlsHint =
|
||||||
|
/self-signed|certificate|UNABLE_TO_VERIFY|CERT_/i.test(raw)
|
||||||
|
? ' — در تنظیمات اتصال، گزینه «پذیرش گواهی SSL خودامضا» را فعال کنید.'
|
||||||
|
: '';
|
||||||
reject(
|
reject(
|
||||||
new BadGatewayException(
|
new BadGatewayException(
|
||||||
`اتصال به تهحساب ناموفق بود: ${err.message}`,
|
`اتصال به تهحساب ناموفق بود: ${raw}${tlsHint}`,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -70,6 +70,21 @@ function resetForm() {
|
|||||||
form.enabled = true;
|
form.enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function looksLikePrivateHttps(url: string) {
|
||||||
|
return /^https:\/\/(\d{1,3}\.){3}\d{1,3}(:\d+)?/i.test(url.trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
function isTlsError(text: string | null | undefined) {
|
||||||
|
if (!text) return false;
|
||||||
|
return /self-signed|certificate|UNABLE_TO_VERIFY|CERT_|گواهی/i.test(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onBaseUrlBlur() {
|
||||||
|
if (!editingId.value && looksLikePrivateHttps(form.baseUrl)) {
|
||||||
|
form.allowInsecureTls = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function startEdit(row: TahesabConnectionDto) {
|
function startEdit(row: TahesabConnectionDto) {
|
||||||
editingId.value = row.id;
|
editingId.value = row.id;
|
||||||
form.label = row.label;
|
form.label = row.label;
|
||||||
@@ -162,12 +177,31 @@ async function testConn(id: string) {
|
|||||||
`/integrations/tahesab/connections/${id}/test`,
|
`/integrations/tahesab/connections/${id}/test`,
|
||||||
);
|
);
|
||||||
if (data.ok) ok.value = 'اتصال سالم است.';
|
if (data.ok) ok.value = 'اتصال سالم است.';
|
||||||
else error.value = data.error ?? 'تست اتصال ناموفق بود.';
|
else {
|
||||||
|
error.value = data.error ?? 'تست اتصال ناموفق بود.';
|
||||||
|
if (isTlsError(data.error)) {
|
||||||
|
error.value +=
|
||||||
|
' → دکمه «فعالسازی SSL خودامضا» را بزنید یا در ویرایش اتصال تیک آن را بگذارید.';
|
||||||
|
}
|
||||||
|
}
|
||||||
await load();
|
await load();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error.value = axios.isAxiosError(e)
|
error.value = apiErr(e, 'تست ناموفق');
|
||||||
? String((e.response?.data as { message?: string })?.message ?? 'تست ناموفق')
|
}
|
||||||
: 'تست ناموفق';
|
}
|
||||||
|
|
||||||
|
async function enableInsecureTls(id: string) {
|
||||||
|
error.value = '';
|
||||||
|
ok.value = '';
|
||||||
|
try {
|
||||||
|
await api.patch(`/integrations/tahesab/connections/${id}`, {
|
||||||
|
allowInsecureTls: true,
|
||||||
|
});
|
||||||
|
ok.value = 'پذیرش گواهی خودامضا فعال شد. در حال تست…';
|
||||||
|
await load();
|
||||||
|
await testConn(id);
|
||||||
|
} catch (e) {
|
||||||
|
error.value = apiErr(e, 'فعالسازی ناموفق بود');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -332,6 +366,14 @@ onMounted(load);
|
|||||||
<p v-if="error" class="error">{{ error }}</p>
|
<p v-if="error" class="error">{{ error }}</p>
|
||||||
<p v-if="ok" class="ok">{{ ok }}</p>
|
<p v-if="ok" class="ok">{{ ok }}</p>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="items.some((r) => !r.allowInsecureTls && isTlsError(r.lastError))"
|
||||||
|
class="banner warn"
|
||||||
|
>
|
||||||
|
اتصال شما بهخاطر گواهی SSL خودامضا قطع است. روی همان کارت اتصال،
|
||||||
|
<strong>فعالسازی SSL خودامضا</strong> را بزنید؛ بعد دوباره «نمایش بازه» را امتحان کنید.
|
||||||
|
</div>
|
||||||
|
|
||||||
<div v-if="!loading && items.length" class="list">
|
<div v-if="!loading && items.length" class="list">
|
||||||
<article v-for="row in items" :key="row.id" class="card row">
|
<article v-for="row in items" :key="row.id" class="card row">
|
||||||
<div class="row-main">
|
<div class="row-main">
|
||||||
@@ -341,6 +383,7 @@ onMounted(load);
|
|||||||
DB: {{ row.dbName }} · توکن: {{ row.tokenMasked }}
|
DB: {{ row.dbName }} · توکن: {{ row.tokenMasked }}
|
||||||
<template v-if="row.isDefault"> · پیشفرض</template>
|
<template v-if="row.isDefault"> · پیشفرض</template>
|
||||||
<template v-if="!row.enabled"> · غیرفعال</template>
|
<template v-if="!row.enabled"> · غیرفعال</template>
|
||||||
|
<template v-if="row.allowInsecureTls"> · SSL خودامضا مجاز</template>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
v-if="row.lastHealthAt"
|
v-if="row.lastHealthAt"
|
||||||
@@ -353,6 +396,14 @@ onMounted(load);
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="row-actions">
|
<div class="row-actions">
|
||||||
|
<button
|
||||||
|
v-if="!row.allowInsecureTls && isTlsError(row.lastError)"
|
||||||
|
type="button"
|
||||||
|
class="btn primary"
|
||||||
|
@click="enableInsecureTls(row.id)"
|
||||||
|
>
|
||||||
|
فعالسازی SSL خودامضا
|
||||||
|
</button>
|
||||||
<button type="button" class="btn ghost" @click="startEdit(row)">ویرایش</button>
|
<button type="button" class="btn ghost" @click="startEdit(row)">ویرایش</button>
|
||||||
<button type="button" class="btn ghost" @click="testConn(row.id)">تست</button>
|
<button type="button" class="btn ghost" @click="testConn(row.id)">تست</button>
|
||||||
<button type="button" class="btn danger" @click="removeConn(row.id)">حذف</button>
|
<button type="button" class="btn danger" @click="removeConn(row.id)">حذف</button>
|
||||||
@@ -373,6 +424,7 @@ onMounted(load);
|
|||||||
required
|
required
|
||||||
dir="ltr"
|
dir="ltr"
|
||||||
placeholder="https://api-test.tahesab.ir یا https://IP:8081"
|
placeholder="https://api-test.tahesab.ir یا https://IP:8081"
|
||||||
|
@blur="onBaseUrlBlur"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
@@ -401,9 +453,9 @@ onMounted(load);
|
|||||||
<input v-model="form.enabled" type="checkbox" />
|
<input v-model="form.enabled" type="checkbox" />
|
||||||
فعال
|
فعال
|
||||||
</label>
|
</label>
|
||||||
<label class="check">
|
<label class="check highlight">
|
||||||
<input v-model="form.allowInsecureTls" type="checkbox" />
|
<input v-model="form.allowInsecureTls" type="checkbox" />
|
||||||
پذیرش گواهی SSL خودامضا (فقط شبکه داخلی)
|
پذیرش گواهی SSL خودامضا (برای IP داخلی / https بدون گواهی معتبر — معمولاً لازم است)
|
||||||
</label>
|
</label>
|
||||||
<div class="form-actions">
|
<div class="form-actions">
|
||||||
<button class="btn primary" type="submit" :disabled="saving">
|
<button class="btn primary" type="submit" :disabled="saving">
|
||||||
@@ -638,6 +690,24 @@ select {
|
|||||||
color: #0f172a;
|
color: #0f172a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.check.highlight {
|
||||||
|
padding: 0.65rem 0.75rem;
|
||||||
|
border-radius: 12px;
|
||||||
|
background: #fff7ed;
|
||||||
|
border: 1px solid #fdba74;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #9a3412;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner.warn {
|
||||||
|
padding: 0.85rem 1rem;
|
||||||
|
border-radius: 14px;
|
||||||
|
background: #fff7ed;
|
||||||
|
border: 1px solid #fdba74;
|
||||||
|
color: #9a3412;
|
||||||
|
line-height: 1.7;
|
||||||
|
}
|
||||||
|
|
||||||
.form-actions {
|
.form-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
|
|||||||
Reference in New Issue
Block a user