在 NGXS 中解码 SSL 并更新状态

问题描述

我正在学习 NGXS 并尝试重构一个显示 SSL 证书信息的材料表,以便于访问。我已经能够从我们的 API 成功获取 CertificateObject,但我不确定如何解码证书和更新状态。

这是我的状态模型:

export interface CertificateStateModel {
  certificate: CertificateObject;
  certificates: Certificate[];
  searchLimitedStateMessage: string;
  emptyCertificateMessage: string;
  searchTerm: any;
}

@State<CertificateStateModel>({
  name: "certificate",defaults: {
    certificate: null,certificates: [],searchLimitedStateMessage: SearchMessages.typetoSearch,emptyCertificateMessage: SearchMessages.typetoSearch,searchTerm: null,},})

这是我获取所有证书的操作:

  @Action(CertificateAction.GetAllCertificates)
  getAllCertificates(
    ctx: StateContext<CertificateStateModel>,action: CertificateAction.GetAllCertificates
  ) {
    ctx.dispatch(new Busy(true));
    return this.svc.getAllCertificates().pipe(
      tap((certificate) => {
        ctx.patchState({
          certificate
        });
        ctx.dispatch(new Busy(true));
        console.log(certificate)
      },(error: any) => {
        ctx.dispatch([
          new displayMessage({type: "error",list: [ "Get All Certificates Error",error.error ]}),new Busy(false)
        ]);
      })
    );
  }

证书对象如下所示:

{
    "id": "12345","name": "accountName","certificates": [
        {
            "publicCertificate": "EncodedCertHere","id": "12345","name": "atest"
        },{
            "publicCertificate": "EncodedCertHere","name": "btest"
        }
    ]
}

我的问题是如何解码证书并将其设置为状态模型上的证书 [] 属性

作为参考,这是我在使用 matTableDataSource 之前解码证书的方式:

 this._integrationAccountService.getCertificates().subscribe(response => {
      this.data = [];
      if (response.certificates) {
          for (let entity of response.certificates) {

            const certPem = atob(entity.publicCertificate)
            const cert = pki.certificateFromPem(certPem)
            const fingerprint = forge.md.sha1.create().update(forge.asn1.toDer(forge.pki.certificatetoAsn1(cert)).getBytes()).digest().toHex();
            const currentDate = new Date();
            const daysToExpire = cert.validity.notAfter.valueOf() - currentDate.valueOf();

              let row: CertificateRow = {
                  name: entity.name,issueDate: cert.validity.notBefore,expiryDate: cert.validity.notAfter,fingerPrint: fingerprint,serialNumber: cert.serialNumber,daysToExpire: daysToExpire / 86400000,}
              this.data.push(row);
          }
      }

      this.dataSource = new MatTableDataSource(this.data);
      this.dataSource.sort = this.sort;
      this.dataSource.paginator = this.paginator;
      this.dataSource.filterPredicate = (data: any,filter:string): boolean=> {
        //"data" here is the value of the "row"
        return data.name.toLowerCase().includes(filter);
      };
    })
  }

能帮我指明正确方向的任何帮助都会很棒。我一直在关注 NGXS 网站上的文档,但所有示例都非常简单,我在杂草中迷失了方向。

解决方法

  1. 只是一个 nit 选择,但尝试使用操作生命周期而不是为微调器/加载器等设置状态...请参阅:https://github.com/ngxs-labs/actions-executing

  2. 我会使用您已经使用的任何代码来解码证书,然后将其设置为您的状态,应该很容易。


function decodeCert(cert: CertificateObject) {
 ... *decoding cert code*
}

////

@Action(CertificateAction.GetAllCertificates)
getAllCertificates(
  ctx: StateContext<CertificateStateModel>,action: CertificateAction.GetAllCertificates
) {
  // ctx.dispatch(new Busy(true)); <-- See Point 1
  return this.svc.getAllCertificates().pipe(
    tap((certificate) => {
      ctx.patchState({
        certificate: decodeCert(certificate),// <-- See Point 2
      });
      // ctx.dispatch(new Busy(true)); <-- See Point 1
      console.log(certificate)
    },(error: any) => {
      ctx.dispatch([
        new DisplayMessage({type: "error",list: [ "Get All Certificates Error",error.error ]}),// new Busy(false) <-- See Point 1
      ]);
    })
  );
}

@Selector([CertificateState])
getCerts(state: CertificateState){
  return ... get your data rows here...
}

材料表非常擅长它的功能,但你必须跳过几个箍才能让它工作。不知道你的观点是什么样的,所以我只是想看看

table-wrapper.ts

@Select(CertificateState.getCerts) data$: Observable<T>;

table-wrapper.html

<app-table data="data$ | async"></app-table>

table.html

<table mat-table [dataSource]="dataSource">
<!-- contents -->
</table>

table.ts

// one way to set the incoming datasource
@Input() public set data(value: T) {
    this.dataSource.data = value;
}

// another way to set the incoming data source
@Input() data: T[];
ngOnChanges(): void {
    this.dataSource.data = this.data;
}