* refactor(logger): improve logger format * chore: improve log format * feat(logger): plugin-logger * feat: allow to download log files, close T-1917 * chore: update yarn.lock * chore: improve log format * fix: add maxsize params * chore: add userId field to request * chore: remove userId from request * chore: change userId in response * chore: change action in response * chore: add database logger * fix: build * fix: test * chore: solve conflicts * fix: escape delimiter in message * refactor: improve create logger api * chore: update app logger options * chore: remove colorize for json * fix: bug of data2tree * fix: test * chore: log * chore: remove GITHUB_ACTION check * fix: bug * chore: change version * fix: transports * fix: mockServer * chore: use new plugin settings api * fix: version * fix: build * feat: support logfmt * fix: build * fix: build * fix: test * chore: update config * fix: test * fix: bug * fix: test * fix: format * chore: update path * fix: build * fix: bug * chore: update comment * fix: allow to custom format * fix: package.json * fix: version * fix: bug
		
			
				
	
	
		
			123 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			123 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import { Context, Next } from '@nocobase/actions';
 | 
						|
import { Registry } from '@nocobase/utils';
 | 
						|
import { Auth, AuthExtend } from './auth';
 | 
						|
import { JwtOptions, JwtService } from './base/jwt-service';
 | 
						|
import { ITokenBlacklistService } from './base/token-blacklist-service';
 | 
						|
 | 
						|
export interface Authenticator {
 | 
						|
  authType: string;
 | 
						|
  options: Record<string, any>;
 | 
						|
  [key: string]: any;
 | 
						|
}
 | 
						|
 | 
						|
export interface Storer {
 | 
						|
  get: (name: string) => Promise<Authenticator>;
 | 
						|
}
 | 
						|
 | 
						|
export type AuthManagerOptions = {
 | 
						|
  authKey: string;
 | 
						|
  default?: string;
 | 
						|
  jwt?: JwtOptions;
 | 
						|
};
 | 
						|
 | 
						|
type AuthConfig = {
 | 
						|
  auth: AuthExtend<Auth>; // The authentication class.
 | 
						|
  title?: string; // The display name of the authentication type.
 | 
						|
};
 | 
						|
 | 
						|
export class AuthManager {
 | 
						|
  jwt: JwtService;
 | 
						|
  protected options: AuthManagerOptions;
 | 
						|
  protected authTypes: Registry<AuthConfig> = new Registry();
 | 
						|
  // authenticators collection manager.
 | 
						|
  protected storer: Storer;
 | 
						|
 | 
						|
  constructor(options: AuthManagerOptions) {
 | 
						|
    this.options = options;
 | 
						|
    this.jwt = new JwtService(options.jwt);
 | 
						|
  }
 | 
						|
 | 
						|
  setStorer(storer: Storer) {
 | 
						|
    this.storer = storer;
 | 
						|
  }
 | 
						|
 | 
						|
  setTokenBlacklistService(service: ITokenBlacklistService) {
 | 
						|
    this.jwt.blacklist = service;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * registerTypes
 | 
						|
   * @description Add a new authenticate type and the corresponding authenticator.
 | 
						|
   * The types will show in the authenticators list of the admin panel.
 | 
						|
   *
 | 
						|
   * @param authType - The type of the authenticator. It is required to be unique.
 | 
						|
   * @param authConfig - Configurations of the kind of authenticator.
 | 
						|
   */
 | 
						|
  registerTypes(authType: string, authConfig: AuthConfig) {
 | 
						|
    this.authTypes.register(authType, authConfig);
 | 
						|
  }
 | 
						|
 | 
						|
  listTypes() {
 | 
						|
    return Array.from(this.authTypes.getEntities()).map(([authType, authConfig]) => ({
 | 
						|
      name: authType,
 | 
						|
      title: authConfig.title,
 | 
						|
    }));
 | 
						|
  }
 | 
						|
 | 
						|
  getAuthConfig(authType: string) {
 | 
						|
    return this.authTypes.get(authType);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * get
 | 
						|
   * @description Get authenticator instance by name.
 | 
						|
   * @param name - The name of the authenticator.
 | 
						|
   * @return authenticator instance.
 | 
						|
   */
 | 
						|
  async get(name: string, ctx: Context) {
 | 
						|
    if (!this.storer) {
 | 
						|
      throw new Error('AuthManager.storer is not set.');
 | 
						|
    }
 | 
						|
    const authenticator = await this.storer.get(name);
 | 
						|
    if (!authenticator) {
 | 
						|
      throw new Error(`Authenticator [${name}] is not found.`);
 | 
						|
    }
 | 
						|
    const { auth } = this.authTypes.get(authenticator.authType);
 | 
						|
    if (!auth) {
 | 
						|
      throw new Error(`AuthType [${name}] is not found.`);
 | 
						|
    }
 | 
						|
    return new auth({ authenticator, options: authenticator.options, ctx });
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * middleware
 | 
						|
   * @description Auth middleware, used to check the authentication status.
 | 
						|
   */
 | 
						|
  middleware() {
 | 
						|
    return async (ctx: Context & { auth: Auth }, next: Next) => {
 | 
						|
      const token = ctx.getBearerToken();
 | 
						|
      if (token && (await ctx.app.authManager.jwt.blacklist.has(token))) {
 | 
						|
        return ctx.throw(401, ctx.t('token is not available'));
 | 
						|
      }
 | 
						|
 | 
						|
      const name = ctx.get(this.options.authKey) || this.options.default;
 | 
						|
      let authenticator: Auth;
 | 
						|
      try {
 | 
						|
        authenticator = await ctx.app.authManager.get(name, ctx);
 | 
						|
        ctx.auth = authenticator;
 | 
						|
      } catch (err) {
 | 
						|
        ctx.auth = {} as Auth;
 | 
						|
        ctx.logger.warn(err.message, { method: 'check', authenticator: name });
 | 
						|
        return next();
 | 
						|
      }
 | 
						|
      if (authenticator) {
 | 
						|
        const user = await ctx.auth.check();
 | 
						|
        if (user) {
 | 
						|
          ctx.auth.user = user;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      await next();
 | 
						|
    };
 | 
						|
  }
 | 
						|
}
 |