From b8547d9245809033044cabe47c775ba63fb42a4e Mon Sep 17 00:00:00 2001 From: tan-qingliu Date: Thu, 29 May 2025 22:03:04 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=87=AD=E6=8D=AE=E6=8E=88?= =?UTF-8?q?=E6=9D=83=E5=8D=8A=E6=A8=A1=E6=80=81=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: tan-qingliu --- .../MainAbility/CertPickerUiExtAbility.ets | 10 + .../src/main/ets/model/CertMangerModel.ets | 8 +- .../src/main/ets/pages/RequestAuthSheet.ets | 279 ++++++++++++++++++ .../ets/presenter/CmAppCredAuthPresenter.ets | 11 +- .../resources/base/profile/main_pages.json | 3 +- 5 files changed, 308 insertions(+), 3 deletions(-) create mode 100755 certmanager/src/main/ets/pages/RequestAuthSheet.ets diff --git a/certmanager/src/main/ets/MainAbility/CertPickerUiExtAbility.ets b/certmanager/src/main/ets/MainAbility/CertPickerUiExtAbility.ets index e6dc8d7..a543707 100755 --- a/certmanager/src/main/ets/MainAbility/CertPickerUiExtAbility.ets +++ b/certmanager/src/main/ets/MainAbility/CertPickerUiExtAbility.ets @@ -20,6 +20,7 @@ import UIExtensionAbility from '@ohos.app.ability.UIExtensionAbility'; import { BusinessError } from '@ohos.base'; const PAGE_CA_INSTALL = 5; +const PAGE_REQUEST_AUTHORIZE = 6; const TAG = 'CertPickerUiExtAbility'; export default class CertPickerUiExtAbility extends UIExtensionAbility { @@ -46,6 +47,8 @@ export default class CertPickerUiExtAbility extends UIExtensionAbility { try { if (this.isStartToInstall(want.parameters)) { session.loadContent('pages/CertificateInstallPage', storage); + } else if (this.isStartToAuthorize(want.parameters)) { + session.loadContent('pages/RequestAuthSheet', storage); } else { session.loadContent('pages/picker/CertManagerSheetFa', storage); let pwdStore = new PwdStore(); @@ -72,6 +75,13 @@ export default class CertPickerUiExtAbility extends UIExtensionAbility { } return parameters['pageType'] === PAGE_CA_INSTALL; } + + private isStartToAuthorize(parameters: Record | undefined): boolean { + if (parameters === undefined) { + return false; + } + return parameters['pageType'] === PAGE_REQUEST_AUTHORIZE; + } onSessionDestroy(): void { // Main window is destroyed, release UI related resources GlobalContext.getContext().clearSession(); diff --git a/certmanager/src/main/ets/model/CertMangerModel.ets b/certmanager/src/main/ets/model/CertMangerModel.ets index f5500fc..23f4852 100755 --- a/certmanager/src/main/ets/model/CertMangerModel.ets +++ b/certmanager/src/main/ets/model/CertMangerModel.ets @@ -48,6 +48,12 @@ export enum CMModelOptType { CM_MODEL_OPT_USER_CA_P7B = 6, } +export enum DialogErrorCode { + DIALOG_ERROR_INTERNAL = -1000, + DIALOG_OPERATION_CANCELS = -1001, + DIALOG_ERROR_PARAM_INVALID = -1010, +} + export enum CertManagerStore { /* credential certificate store for end entity certificates. */ CERT_MANAGER_CREDENTIAL_STORE = 0, @@ -496,7 +502,7 @@ export class CertMangerModel { try { let result = await CertManager.getAllPublicCertificates(); let credList: CredentialAbstractVo[] = []; - if (result.credentialList !== undefined) { + if (result && result.credentialList !== undefined) { for (let i = 0; i < result.credentialList.length; i++) { credList.push(new CredentialAbstractVo(String(result.credentialList[i].type), String(result.credentialList[i].alias), String(result.credentialList[i].keyUri))); diff --git a/certmanager/src/main/ets/pages/RequestAuthSheet.ets b/certmanager/src/main/ets/pages/RequestAuthSheet.ets new file mode 100755 index 0000000..70387a1 --- /dev/null +++ b/certmanager/src/main/ets/pages/RequestAuthSheet.ets @@ -0,0 +1,279 @@ +/** + * Copyright (c) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { WidthPercent } from '../common/util/ConfigData'; +import CmAppCredAuthPresenter from '../presenter/CmAppCredAuthPresenter'; +import { common, UIExtensionContentSession } from '@kit.AbilityKit'; +import { CMModelErrorCode, DialogErrorCode } from '../model/CertMangerModel'; +import { CredentialAbstractVo } from '../model/CertManagerVo/CredentialAbstractVo'; +import { LengthUnit } from '@kit.ArkUI'; +import hilog from '@ohos.hilog' + +const DOMAIN = 0x0000; +const TAG = 'RequestAuthSheet'; +function hilogInfo(message: string): void { + hilog.info(DOMAIN, TAG, message); +} +function hilogError(message: string): void { + hilog.error(DOMAIN, TAG, message); +} + +let storage = LocalStorage.getShared(); + +@Entry(storage) +@Component +struct RequestAuthSheet { + private session: UIExtensionContentSession = + storage?.get('session') as UIExtensionContentSession; + private want : Want = storage?.get('want') as Want; + private resultCode: number = -1; + private appUid: string = ''; + @State private selectUri: string = '' + @State private mAppCredAuthPresenter: CmAppCredAuthPresenter = CmAppCredAuthPresenter.getInstance(); + @State private isDisplaySheet: boolean = true; + @State private bottomRectHeight: Length = 0; + @State private buttonHeight: Length = 40; + @State private isExtraLargeFontMode: boolean = false; + @State private isAuthBtnOverflow: boolean = false; + @State private hoverItemUri: string = ''; + @State private listPadding: Resource = $r('sys.float.padding_level4'); + + aboutToAppear() { + let parameters = this.want.parameters; + if (parameters === undefined || parameters === null) { + hilogError(`parameters is undefinde`); + return; + } + let callerBundleName: string = parameters['bundleName'] as string; + if (callerBundleName == null || callerBundleName.length === 0) { + hilogError(`bundleName is empty`); + return; + } + hilogInfo(`USER_CERD_GRANT_APP ${callerBundleName}`); + this.appUid = parameters['appUid'].toString(); + if (this.appUid != null && this.appUid.length > 0) { + this.mAppCredAuthPresenter.updateAppNameFromUid(this.appUid); + this.mAppCredAuthPresenter.updateAppCredList((code: CMModelErrorCode) => { + if (code === CMModelErrorCode.CM_MODEL_ERROR_EXCEPTION) { + this.session.terminateSelfWithResult({resultCode: DialogErrorCode.DIALOG_ERROR_INTERNAL}); + } + }) + } else { + hilogError(`request auth appear failed`); + this.session.terminateSelfWithResult({resultCode: DialogErrorCode.DIALOG_ERROR_PARAM_INVALID}); + } + } + + private requestAuth() { + hilogInfo(`USER_CERD_GRANT_APP_SEL_CONFIRM authorize`); + if (this.appUid != null && this.appUid.length > 0 && this.selectUri != null && this.selectUri.length > 0) { + this.mAppCredAuthPresenter.sheetRequestAuthorize(this.selectUri, this.appUid, + (errCode: CMModelErrorCode, data: string) => { + if (errCode === CMModelErrorCode.CM_MODEL_ERROR_SUCCESS) { + this.session?.sendData({ 'uri': data }); + } else { + this.resultCode = DialogErrorCode.DIALOG_ERROR_INTERNAL; + this.isDisplaySheet = false; + } + }); + } else { + this.session.terminateSelfWithResult({resultCode: DialogErrorCode.DIALOG_ERROR_PARAM_INVALID}); + } + } + + @Builder + private buildSheetTitle() { + Row() { + Text($r('app.string.pickCredToAuth')) + .fontWeight(FontWeight.Bold) + .fontSize($r('sys.float.ohos_id_text_size_headline8')) + .fontColor($r('sys.color.font_primary')) + .textOverflow({ overflow: TextOverflow.Ellipsis}) + .maxLines(1) + .maxFontScale(1) + } + .width(WidthPercent.WH_100_100) + .constraintSize({ + minHeight: $r('app.float.wh_value_56') + }) + .justifyContent(FlexAlign.Start) + } + + @Builder + private buildOptBtn() { + Column() { + Button() { + Text($r('app.string.requestAuthFinish')) + .fontWeight(FontWeight.Medium) + .fontSize($r('sys.float.Body_L')) + .fontColor($r('sys.color.font_emphasize')) + .maxLines(1) + .textOverflow({ overflow: TextOverflow.Ellipsis}) + } + .buttonStyle(ButtonStyleMode.NORMAL) + .type(ButtonType.ROUNDED_RECTANGLE) + .width('100%') + .constraintSize({ + minHeight: $r('app.float.wh_value_40') + }) + .onClick(() => { + this.requestAuth(); + }) + } + .width('100%') + .margin({ + top: $r('app.float.wh_value_16'), + bottom: $r('app.float.wh_value_16'), + }) + .justifyContent(FlexAlign.SpaceBetween) + } + + @Builder + private buildSheetContent() { + Column() { + Scroll() { + Column() { + Column() { + Text($r('app.string.requestAuthMsg', this.mAppCredAuthPresenter.appName)) + .fontSize($r('sys.float.ohos_id_text_size_body1')) + .fontColor($r('sys.color.ohos_id_color_text_primary')) + .fontWeight(FontWeight.Regular) + .alignSelf(ItemAlign.Start) + } + .width('100%') + .padding({ left: 12, right: 12 }) + .margin({ top: 8, bottom: 8 }) + + List() { + ForEach(this.mAppCredAuthPresenter.credList, (item: CredentialAbstractVo) => { + ListItem() { + Column() { + Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) { + Column() { + Text(item.alias) + .fontSize($r('app.float.font_18')) + .fontColor($r('sys.color.ohos_id_color_text_primary')) + .fontWeight(FontWeight.Medium) + .textAlign(TextAlign.Start); + } + .alignItems(HorizontalAlign.Start) + .padding({ top: this.listPadding, bottom: this.listPadding }) + + Row() { + Blank().width(8) + Radio({ value: item.alias, group: 'appCredGroup' }) + .height(24) + .width(24) + .checked(this.selectUri === item.keyUri) + .onChange((value: boolean) => { + if (value && this.selectUri !== item.keyUri) { + this.selectUri = item.keyUri; + } + }) + } + } + .width(WidthPercent.WH_100_100) + } + } + .constraintSize({ + minHeight: 48 + }) + .onClick(() => { + if (this.selectUri !== item.keyUri) { + this.selectUri = item.keyUri; + } + }) + .padding({ left: 8, right: 8 }) + .borderRadius(16) + .stateStyles({ + normal: { + .backgroundColor(this.hoverItemUri === item.keyUri ? $r('sys.color.interactive_hover') : + Color.Transparent) + }, + pressed: { + .backgroundColor($r('sys.color.interactive_pressed')) + } + }) + .onHover((isHover: boolean) => { + if (isHover) { + this.hoverItemUri = item.keyUri; + } else { + this.hoverItemUri = ''; + } + }) + .focusBox({ + margin: { + value: -2, + unit: LengthUnit.VP + } + }) + }, (item: CredentialAbstractVo) => JSON.stringify(item) ) + } + .divider({ + strokeWidth: '1px', + color: $r('sys.color.ohos_id_color_list_separator'), + startMargin: 8, + endMargin: 8 + }) + .padding({ + top: 4, + bottom: 4, + left: 4, + right: 4 + }) + .borderRadius(10) + .backgroundColor($r('sys.color.ohos_id_color_list_card_bg')) + .scrollBar(BarState.Off) + .nestedScroll({ + scrollForward: NestedScrollMode.PARENT_FIRST, + scrollBackward: NestedScrollMode.SELF_FIRST, + }) + .visibility(this.mAppCredAuthPresenter.credList.length > 0 ? Visibility.Visible : Visibility.None) + } + .width('100%') + } + .scrollable(ScrollDirection.Vertical) + .scrollBar(BarState.Auto) + .align(Alignment.Top) + .width('100%') + .height(`calc(100% - ${this.buttonHeight}vp)`) + + Column() { + this.buildOptBtn() + } + .width('100%') + .onAreaChange((oldValue: Area, newValue: Area) => { + this.buttonHeight = newValue.height; + }) + } + .padding({ left: 16, right: 16, bottom: this.bottomRectHeight }) + .height('100%') + .justifyContent(FlexAlign.SpaceBetween) + } + + build() { + Column() { + Column() { + } + .bindSheet(this.isDisplaySheet, this.buildSheetContent, { + height: '100%', + title: this.buildSheetTitle, + showClose: true, + onDisappear: () => { + this.session.terminateSelfWithResult({resultCode: this.resultCode}); + } + }) + } + } +} \ No newline at end of file diff --git a/certmanager/src/main/ets/presenter/CmAppCredAuthPresenter.ets b/certmanager/src/main/ets/presenter/CmAppCredAuthPresenter.ets index 28e4e01..d21dfaf 100755 --- a/certmanager/src/main/ets/presenter/CmAppCredAuthPresenter.ets +++ b/certmanager/src/main/ets/presenter/CmAppCredAuthPresenter.ets @@ -63,7 +63,7 @@ export default class CmAppCredAuthPresenter { } } - updateAppCredList(): void { + updateAppCredList(callback?: Function): void { certManagerModel.getCertOrCredList(CMModelOptType.CM_MODEL_OPT_APP_CRED, (errCode: CMModelErrorCode, credList: Array) => { if (errCode === CMModelErrorCode.CM_MODEL_ERROR_SUCCESS) { @@ -72,9 +72,18 @@ export default class CmAppCredAuthPresenter { } else { console.error('updateAppCredList failed'); } + callback?.(errCode); }); } + sheetRequestAuthorize(uri: string, appUid: string, callback: Function): void { + if (appUid == null || appUid.length === 0 || uri == null || uri.length === 0) { + callback(CMModelErrorCode.CM_MODEL_ERROR_FAILED); + return; + } + certManagerModel.setAppAuth(CMModelOptType.CM_MODEL_OPT_APP_CRED, uri, appUid, true, callback); + } + requestAuthorize(uri: string, appUid: string): void { let want = GlobalContext.getContext().getAbilityWant(); certManagerModel.setAppAuth(CMModelOptType.CM_MODEL_OPT_APP_CRED, uri, appUid, diff --git a/certmanager/src/main/resources/base/profile/main_pages.json b/certmanager/src/main/resources/base/profile/main_pages.json index cd3ba33..b371dce 100755 --- a/certmanager/src/main/resources/base/profile/main_pages.json +++ b/certmanager/src/main/resources/base/profile/main_pages.json @@ -7,6 +7,7 @@ "pages/requestAuth", "pages/certInstallFromStorage", "pages/CertificateInstallPage", - "pages/picker/CertManagerSheetFa" + "pages/picker/CertManagerSheetFa", + "pages/RequestAuthSheet" ] } -- Gitee