update
This commit is contained in:
@@ -9,7 +9,11 @@
|
||||
<template v-if="!licenseDisplayInfo.isPaid">
|
||||
<button class="action-btn" @click="refreshLicenseStatus" :disabled="checking" ref="checkButton">{{ $t('license.button.checkLicense.label') }}</button>
|
||||
<kuc-tooltip :title="$t('license.button.checkLicense.desc')" :container="checkButton"></kuc-tooltip>
|
||||
<button class="action-btn main" @click="purchaseLicense" ref="buyButton">{{ $t('license.button.purchase.label') }}</button>
|
||||
<button class="action-btn main" @click="purchaseLicense" ref="buyButton">{{ $t('license.button.purchase.label') }}
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="open-icon">
|
||||
<path d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</button>
|
||||
<kuc-tooltip :title="$t('license.button.purchase.desc')" :container="buyButton"></kuc-tooltip>
|
||||
</template>
|
||||
<button v-else class="action-btn" @click="hidePaidMsg">{{ $t('license.button.hide') }}</button>
|
||||
@@ -134,9 +138,10 @@ async function refreshLicenseStatus() {
|
||||
}
|
||||
|
||||
function purchaseLicense() {
|
||||
alert(
|
||||
`请联系管理员或访问官方网站购买许可证。\nDomain: ${licenseInfo.value?.domain}\nPlugin: ${licenseInfo.value?.pluginId}`,
|
||||
);
|
||||
const { name, email } = kintone.getLoginUser();
|
||||
const domain = licenseInfo.value?.domain;
|
||||
const pluginId = licenseInfo.value?.pluginId;
|
||||
window.open(`https://alisurvey.alicorns.co.jp/s/Iuc5RxZv?input1761283180784=${domain}&input1761283200616=${pluginId}&input1761283314263=${name}&input1761283275767=${email}`);
|
||||
}
|
||||
|
||||
function hidePaidMsg() {
|
||||
|
||||
@@ -70,14 +70,19 @@
|
||||
border-color: #33691E;
|
||||
}
|
||||
|
||||
.license-status-info .action-btn .open-icon {
|
||||
margin-left: 2px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.notification-link {
|
||||
color: #fff;
|
||||
opacity: 0.8;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.notification-link:hover {
|
||||
opacity: 1;
|
||||
color: #fff;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.text-red {
|
||||
|
||||
@@ -54,7 +54,8 @@ export default {
|
||||
},
|
||||
error: {
|
||||
fetchFailed: 'Remote license check failed: {e}',
|
||||
checkFailed: 'License check failed, plugin disabled: {e}'
|
||||
checkFailed: 'License check failed, plugin disabled: {e}',
|
||||
jwtFailed: 'JWT verification or parsing failed: {e}',
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -42,7 +42,7 @@ export default {
|
||||
},
|
||||
notification: {
|
||||
days: '今日 | 明日 | {count}日後',
|
||||
gotoLink: 'ご利用には<a class="notification-link" href="{link}">「プラグインの設定」</a>をご確認ください。',
|
||||
gotoLink: 'ご利用には「<a class="notification-link" href="{link}">プラグインの設定</a>」をご確認ください。',
|
||||
expired: 'プラグイン「{plugin}」の有効期限が切れました。',
|
||||
warning: 'プラグイン「{plugin}」の試用期間が{days}で終了します。'
|
||||
},
|
||||
@@ -57,7 +57,8 @@ export default {
|
||||
},
|
||||
error: {
|
||||
fetchFailed: 'リモートライセンスチェックに失敗しました: {e}',
|
||||
checkFailed: 'ライセンスチェックに失敗しました。プラグイン機能が無効になりました: {e}'
|
||||
checkFailed: 'ライセンスチェックに失敗しました。プラグイン機能が無効になりました: {e}',
|
||||
jwtFailed: 'JWTの検証または解析に失敗しました: {e}',
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -51,11 +51,11 @@ export class LicenseService {
|
||||
// 验证完整的JWT
|
||||
const result = KJUR.jws.JWS.verifyJWT(savedLicense.jwt, rsaPublicKey.trim(), {alg: ['RS256']});
|
||||
if (!result) {
|
||||
console.warn('JWT signature verification failed');
|
||||
console.warn($t('license.error.jwtFailed', { e : '' }));
|
||||
return false;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('JWT verification or parsing failed:', error);
|
||||
console.warn($t('license.error.jwtFailed', { e : error }));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,24 +1,12 @@
|
||||
// 本地存储加密工具类
|
||||
import { LicenseService } from '@/services/license-service';
|
||||
import type { LicenseInfo, LicenseJWSResult, LicenseSetting, SavedLicense } from '@/types/license';
|
||||
import type { LicenseJWSResult, LicenseSetting, SavedLicense } from '@/types/license';
|
||||
import { KJUR } from 'jsrsasign';
|
||||
|
||||
export class LicenseStorage {
|
||||
private static readonly STORAGE_KEY_PREFIX = 'alicorns_plugin_';
|
||||
private static readonly STORAGE_SETTING_KEY_PREFIX = this.STORAGE_KEY_PREFIX + 'setting_';
|
||||
|
||||
/**
|
||||
* 解码JWT(不验证)
|
||||
*/
|
||||
private static parseJWT(jwt: string) {
|
||||
try {
|
||||
return KJUR.jws.JWS.parse(jwt);
|
||||
} catch (error) {
|
||||
console.error('JWT parsing failed:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成存储key
|
||||
*/
|
||||
@@ -89,7 +77,7 @@ export class LicenseStorage {
|
||||
// decode
|
||||
let decodedJWT: LicenseJWSResult;
|
||||
try {
|
||||
decodedJWT = this.parseJWT(storedJWT) as LicenseJWSResult;
|
||||
decodedJWT = KJUR.jws.JWS.parse(storedJWT) as LicenseJWSResult;
|
||||
if (!decodedJWT) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user