본문 바로가기
프로그래밍/nodejs

adminJS 기초 - Features / 특징 (공식 사이트 번역)

by 한코코 2022. 11. 15.

Features (특징)

이 섹션에는 AdminJS 기능을 사용하는 방법에 대한 자세한 지침이 포함되어 있습니다.

  • Upload
  • Logger
  • Import & Export
  • Password
  • Writing your own features

 


특징 - Upload (업로드)

업로드 기능은 파일을 구성하고 파일에 대한 정보를 데이터베이스에 보관하는 데 도움이 됩니다.
파일에 대해 다른 저장소를 사용할 가능성이 있습니다.
  • local filesystem
  • AWS S3
  • Google Cloud Storage
     

업로드 기능을 설치하려면 다음을 실행하십시오.

$ yarn add @adminjs/upload
업로드 기능의 주요 개념은 업로드된 파일을 외부 소스로 보내는 것입니다. 데이터베이스는 파일이 저장된 경로 및 폴더 이름에 대한 정보를 유지합니다.
 
이 기능은 다음 용어를 사용합니다.
  • key : 저장된 파일의 경로입니다
  • bucket : 컨테이너의 이름입니다
먼저 파일에 대한 정보를 저장할 데이터베이스 테이블을 만들어야 합니다.
아래는 entity에 대한 서면 인터페이스입니다. 파일과 연결된 다른 데이터를 저장하기 위해 자신의 필드를 자유롭게 추가하십시오.
interface IFile {
  id: number;
  s3Key: string;
  bucket: string;
  mime: string;
  comment: string | null;
}

 

다음으로 파일을 저장할 위치를 결정하고 AdminJS에 대한 리소스 항목을 준비해야 합니다.

 

Local Filesystem

로컬 서버에 bucket 폴더가 설정되어 있어야 하며 웹 브라우저에서 baseUrl 경로를 통해 엑세스 할 수 있어야 합니다.

app.use(express.static(path.join(__dirname, '../public')));
import uploadFeature from '@adminjs/upload';
import { File } from './models/file';

const localProvider = {
  bucket: 'public/files',
  opts: {
    baseUrl: '/files',
  },
};

export const files = {
  resource: File,
  options: {
    properties: {
      s3Key: {
        type: 'string',
      },
      bucket: {
        type: 'string',
      },
      mime: {
        type: 'string',
      },
      comment: {
        type: 'textarea',
        isSortable: false,
      },
    },
  },
  features: [
    uploadFeature({
      provider: { local: localProvider },
      validation: { mimeTypes: ['image/png', 'application/pdf', 'audio/mpeg'] },
    }),
  ],
};

 

AWS S3

import uploadFeature from '@adminjs/upload';
import { File } from './models/file';

const AWScredentials = {
  accessKeyId: 'AWS_ACCESS_KEY_ID',
  secretAccessKey: 'AWS_SECRET_ACCESS_KEY',
  region: 'AWS_REGION',
  bucket: 'AWS_BUCKET',
};

export const files = {
  resource: File,
  options: {
    properties: {
      s3Key: {
        type: 'string',
      },
      bucket: {
        type: 'string',
      },
      mime: {
        type: 'string',
      },
      comment: {
        type: 'textarea',
        isSortable: false,
      },
    },
  },
  features: [
    uploadFeature({
      provider: { aws: AWScredentials },
      validation: { mimeTypes: ['application/pdf'] },
    }),
  ],
};

 

Google Cloud Storage

import uploadFeature from '@adminjs/upload';
import { File } from './models/file';

const GCScredentials = {
  serviceAccount: 'SERVICE_ACCOUNT',
  bucket: 'GCP_STORAGE_BUCKET',
  expires: 0,
};

export const files = {
  resource: File,
  options: {
    properties: {
      s3Key: {
        type: 'string',
      },
      bucket: {
        type: 'string',
      },
      mime: {
        type: 'string',
      },
      comment: {
        type: 'textarea',
        isSortable: false,
      },
    },
  },
  features: [
    uploadFeature({
      provider: { gpc: GCScredentials },
      validation: { mimeTypes: ['image/png'] },
    }),
  ],
};

 

그런 다음 AdminJS 옵션 구성에 파일 리소스를 추가합니다.

import { files } from './resources/files';

const adminJsOptions = {
  resources: [
     //...
     files
  ],
  //...
}

 

단일 데이터베이스 항목으로 여러 파일을 처리하려면 구성 파일을 수정해야 합니다.

Entity

import { BaseEntity, Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';

@Entity({ name: 'files' })
export class File extends BaseEntity {
  @PrimaryGeneratedColumn()
  public id: number;

  @Column({ name: 's3_key', nullable: true, type: 'jsonb' })
  public s3Key: string;

  @Column({ nullable: true, type: 'jsonb' })
  public bucket: string;

  @Column({ nullable: true, type: 'jsonb' })
  public mime: string;

  @Column({ nullable: true, type: 'text' })
  public comment: string;

  @CreateDateColumn({ name: 'created_at' })
  public createdAt: Date;

  @UpdateDateColumn({ name: 'updated_at' })
  public updatedAt: Date;
}

 

Resource

import uploadFeature from '@adminjs/upload';
import { File } from './models/file';

const localProvider = {
  bucket: 'public/files',
  baseUrl: '/files',
};

export const files = {
  resource: File,
  options: {
    properties: {
      s3Key: {
        type: 'string',
        isArray: true,
      },
      bucket: {
        type: 'string',
        isArray: true,
      },
      mime: {
        type: 'string',
        isArray: true,
      },
      comment: {
        type: 'textarea',
        isSortable: false,
      },
    },
  },
  features: [
    uploadFeature({
      provider: { local: localProvider },
      multiple: true,
      validation: { mimeTypes: ['image/png', 'application/pdf', 'audio/mpeg'] },
    }),
  ],
};

 

 

 

 


특징 - Logger (로거)

AdminJS에는 기본 기능을 확장하는 추가 플러그인이 있습니다. 그 중 하나가 로거입니다.
로거의 목적은 선택된 리소스(예: 테이블)를 추적하는 것입니다. 리소스에서 수행되는 모든 작업(신규, 편집, 삭제 또는 대량 삭제)은 특수 객체에 등록되고 데이터베이스에 지속됩니다. 변경 사항에 대한 정보가 모니터링되므로 테이블의 모든 필드에서 변경 사항을 검사하고 비교할 수 있습니다.
설치는 매우 간단합니다. 먼저 @adminjs/logger패키지 를 설치해야 합니다.
$ yarn add @adminjs/logger

 

어댑터 섹션 에 설명된 대로 모든 데이터베이스와 ORM 패키지를 사용할 수 있습니다 .

그런 다음 변경 사항을 추적할 위치인 로그 entity를 정의해야 합니다. 아래에서 예를 찾을 수 있습니다.

// TypeORM
import { BaseEntity, Column, Entity, PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn } from 'typeorm';

export interface ILog {
  id: number;
  action: string;
  resource: string;
  userId: string | null;
  recordId: number;
  recordTitle: string | null;
  difference: Record<string, unknown> | null;
  createdAt: Date;
  updatedAt?: Date;
}

@Entity({ name: 'logs' })
export class Log extends BaseEntity implements ILog {
  @PrimaryGeneratedColumn()
  public id: number;

  @CreateDateColumn({ name: 'created_at' })
  public createdAt: Date;

  @UpdateDateColumn({ name: 'updated_at' })
  public updatedAt?: Date;

  @Column({ name: 'record_id', type: 'integer', nullable: false })
  public recordId: number;

  @Column({ name: 'record_title', type: 'text', nullable: true, default: '' })
  public recordTitle: string | null;

  @Column({ name: 'difference', type: 'jsonb', nullable: true, default: {} })
  public difference: Record<string, unknown> | null;

  @Column({ name: 'action', type: 'varchar', length: 128, nullable: false })
  public action: string;

  @Column({ name: 'resource', type: 'varchar', length: 128, nullable: false })
  public resource: string;

  @Column({ name: 'user_id', type: 'varchar', nullable: false })
  public userId: string;
}

EntityLog는 userId가 변경한 사용자에 대한 참조를 보유하므로 엔티티 사용자와 관련됩니다.

 

한 가지 언급할 것이 있습니다. 해당 변경을 위해서는 사용자 ID가 필요하기 때문에 이 기능을 사용하기 전에 인증을 활성화해야 합니다. 로거가 작동하도록 하려면 리소스 구성에 추가 속성을 추가하세요. 아래에서 이러한 구성의 간단한 예를 찾을 수 있습니다.

import loggerFeature from '@adminjs/logger';
import ResourceModel from './resource.entity';

export default {
  resource: ResourceModel,
  features: [
    loggerFeature({
      propertiesMapping: {
        user: 'userId',
      },
      userIdAttribute: 'id',
    }),
  ],
};

AdminJS 패널에 로그 자원이 나타나게 하려면 먼저 정의해야 합니다.

 

@adminjs/logger는 대부분의 작업을 수행하는 createLoggerResource 함수를 내보냅니다. 구성 인수를 사용하여 사용자 정의할 수 있습니다.

import { createLoggerResource } from '@adminjs/logger';
import Log from './logs.entity';

const config = {
    resource: Log,
    featureOptions: {
        propertiesMapping: {
            recordTitle: 'title' //field to store logged record's title
        },
        userIdAttribute: 'id', //primary key currently logged user
        resourceOptions: {
            navigation: {
                name: 'SectionName',
                icon: 'iconName'
            }
        }
    }
}

export default createLoggerResource(config)

 

 

 

 


특징 - Import & Export

AdminJS는 이 사용 사례를 해결하는 "@adminjs/import-export"라는 기능을 제공합니다. csv, json 또는 xml 파일을 활용할 수 있습니다.

설치하려면 이 패키지를 프로젝트에 추가하십시오.

$ yarn add @adminjs/import-export

그런 다음 AdminJS 구성의 리소스 항목에 한 줄(features)을 추가 합니다.

import importExportFeature from '@adminjs/import-export';

...

{
  resource: Entity,
  features: [
    importExportFeature(),
  ],
}
그런 다음 리소스 보기의 오른쪽 상단 모서리에 두 개의 버튼(가져오기, 내보내기)이 표시되어야 합니다.
가져온 파일의 필드 이름은 데이터베이스 모델과 동일해야 합니다.
 
 
 

특징 - Password

비밀번호 기능은 레코드를 편집할 때 사용자의 비밀번호를 해시하는 데 사용할 수 있습니다.

$ yarn add @adminjs/passwords

다음 단계는 사용자 리소스에 기능 옵션을 추가하는 것입니다.

import argon2 from 'argon2';
import passwordsFeature from '@adminjs/passwords';
import User from './models/user';

const adminJsOptions = {
  resources: [
    {
      resource: User,
      options: {
        //...your regular options go here'
        properties: { password: { isVisible: false } },
      },
      features: [
        passwordsFeature({
          properties: {
            encryptedPassword: 'password',
            password: 'newPassword'
          }
          hash: argon2.hash,
      })
      ]
    },
  ],
  //...
}

위의 예에서 암호는 암호화된 암호를 보유하는 사용자 속성입니다(보안을 유지하려면 보이지 않게 해야 합니다. passwordsFeature -> 옵션 속성의 newPassword는 입력된 암호를 유지하는 가상 필드이며 저장하기 전에 해시됩니다.

 

 

 


 

특징 - 나만의 기능 쓰기

언급했듯이 이 기능은 ResourceOptions를 반환하는 간단한 함수입니다.

그러나 기능을 연결할 수 있으므로 이전 기능에서 생성된 ResourceOptions도 매개변수로 사용합니다.

 

간단한 기능 구현

const feature = (prevResourceOptions) {
  return {
    ...prevResourceOptions,
    actions: {
      ...prevResourceOptions.actions,
      edit: {
        ...(prevResourceOptions.actions && prevResourceOptions.actions.edit),
        //..
      }
      //..
    }
  }
}

export { feature }

 

보시다시피 위의 예에서 문제가 될 수 있는 이전 옵션 병합을 처리해야 합니다. 다행스럽게도 AdminJS는 이에 대한 도우미 기능을 제공합니다.

 

다음은 buildFeature 함수를 사용할 때 기능이 표시되는 방식입니다.

const { buildFeature } = require('adminjs')

const feature = buildFeature({
  actions: {
    before: myBeforeHook
  }
})

 

댓글