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