Skip to content

Commit

Permalink
feat: autenticacao: login e quem sou eu
Browse files Browse the repository at this point in the history
  • Loading branch information
guesant committed Feb 25, 2024
1 parent 4b64807 commit fe82897
Show file tree
Hide file tree
Showing 20 changed files with 413 additions and 31 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export type IAutenticacaoLoginInputDto = {
matriculaSiape: string;
senha: string;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export type IAutenticacaoLoginResultDto = {
access_token: string | null;
token_type: string | null;
id_token: string | null;
refresh_token: string | null;
expires_in: number | null;
expires_at: number | null;
session_state: string | null;
scope: string | null;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './IAutenticacaoLoginInputDto';
export * from './IAutenticacaoLoginResultDto';
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { IUsuarioFindOneResultDto } from '../../usuario';

export type IAutenticacaoQuemSouEuResultDto = {
usuario: IUsuarioFindOneResultDto | null;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './IAutenticacaoQuemSouEuResultDto';
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './autenticacao-login';
export * from './autenticacao-quem-sou-eu';
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './(dtos)';
export * from './usuario';
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
import { Controller, Get } from '@nestjs/common';
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
import { Controller, Get, Post } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import * as Dto from '../(dtos)';
import { IClientAccess } from '../../../domain';
import { ClientAccessHttp } from '../../../infrastructure';
import { ClientAccessHttp, DtoOperationCreate, DtoOperationFindOne, HttpDtoBody } from '../../../infrastructure';
import { AutenticacaoService } from './autenticacao.service';
import { AutenticacaoOperations } from './dtos';

@ApiTags('Autenticação')
@Controller('/autenticacao')
export class AutenticacaoController {
constructor(private readonly autenticacaoService: AutenticacaoService) {}

@Get('/quem-sou-eu')
@ApiBearerAuth()
@DtoOperationFindOne(AutenticacaoOperations.AUTENTICACAO_QUEM_SOU_EU)
quemSouEu(@ClientAccessHttp() clientAccess: IClientAccess) {
return this.autenticacaoService.quemSouEu(clientAccess);
}

@Post('/login')
@DtoOperationCreate(AutenticacaoOperations.AUTENTICACAO_LOGIN)
login(@ClientAccessHttp() clientAccess: IClientAccess, @HttpDtoBody(AutenticacaoOperations.AUTENTICACAO_LOGIN) dto: Dto.IAutenticacaoLoginInputDto) {
return this.autenticacaoService.login(clientAccess, dto);
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { Module } from '@nestjs/common';
import { OpenidConnectModule } from './../../../infrastructure/authentication/idp-external-connect/openid-connect/openid-connect.module';
import { AutenticacaoController } from './autenticacao.controller';
import { AutenticacaoResolver } from './autenticacao.resolver';
import { AutenticacaoService } from './autenticacao.service';
import { UsuarioModule } from './usuario/usuario.module';

@Module({
imports: [UsuarioModule],
imports: [UsuarioModule, OpenidConnectModule],
controllers: [AutenticacaoController],
providers: [AutenticacaoService],
providers: [AutenticacaoService, AutenticacaoResolver],
exports: [],
})
export class AutenticacaoModule {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Resolver } from '@nestjs/graphql';
import { ClientAccessGraphQl, DtoOperationGqlMutation, DtoOperationGqlQuery, GqlDtoInput } from 'infrastructure';
import * as Dto from '../(dtos)';
import { IClientAccess } from '../../../domain';
import { AutenticacaoService } from './autenticacao.service';
import { AutenticacaoOperations } from './dtos';

@Resolver()
export class AutenticacaoResolver {
constructor(
//
private autenticacaoService: AutenticacaoService,
) {}

//

@DtoOperationGqlMutation(AutenticacaoOperations.AUTENTICACAO_LOGIN)
async autenticacaoLogin(
@ClientAccessGraphQl() clientAccess: IClientAccess,
@GqlDtoInput(AutenticacaoOperations.AUTENTICACAO_LOGIN)
dto: Dto.IAutenticacaoLoginInputDto,
) {
return this.autenticacaoService.login(clientAccess, dto);
}

//

@DtoOperationGqlQuery(AutenticacaoOperations.AUTENTICACAO_QUEM_SOU_EU)
async usuarioFindOneById(@ClientAccessGraphQl() clientAccess: IClientAccess) {
return this.autenticacaoService.quemSouEu(clientAccess);
}

//
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,60 @@
import { Injectable } from '@nestjs/common';
import { BadRequestException, ForbiddenException, Injectable, ServiceUnavailableException } from '@nestjs/common';
import { BaseClient } from 'openid-client';
import { IAutenticacaoLoginInputDto, IAutenticacaoLoginResultDto } from '../(dtos)';
import { IClientAccess } from '../../../domain';
import { OpenidConnectService } from '../../../infrastructure/authentication/idp-external-connect/openid-connect/openid-connect.service';
import { UsuarioService } from './usuario/usuario.service';

@Injectable()
export class AutenticacaoService {
quemSouEu(clientAccess: IClientAccess) {
constructor(
private usuarioService: UsuarioService,
private openidConnectService: OpenidConnectService,
) {}

async quemSouEu(clientAccess: IClientAccess) {
const usuario = clientAccess.currentUsuario ? await this.usuarioService.usuarioFindById(clientAccess, { id: clientAccess.currentUsuario.id }) : null;

return {
usuario: clientAccess.currentUsuario,
usuario: usuario,
};
}

async login(clientAccess: IClientAccess, dto: IAutenticacaoLoginInputDto): Promise<IAutenticacaoLoginResultDto> {
if (clientAccess.currentUsuario !== null) {
throw new BadRequestException('Você não pode usar a rota de login caso já esteja logado.');
}

let trustIssuerClient: BaseClient;

try {
trustIssuerClient = await this.openidConnectService.getTrustIssuerClient();
} catch (error) {
throw new ServiceUnavailableException();
}

const { matriculaSiape, senha } = dto;

try {
const tokenset = await trustIssuerClient.grant({
grant_type: 'password',
username: matriculaSiape,
password: senha,
scope: 'openid profile',
});

return {
access_token: tokenset.access_token ?? null,
token_type: tokenset.token_type ?? null,
id_token: tokenset.id_token ?? null,
refresh_token: tokenset.refresh_token ?? null,
expires_in: tokenset.expires_in ?? null,
expires_at: tokenset.expires_at ?? null,
session_state: tokenset.session_state ?? null,
scope: tokenset.scope ?? null,
};
} catch (error) {}

throw new ForbiddenException('Credenciais inválidas.');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { InputType } from '@nestjs/graphql';
import { IAutenticacaoLoginInputDto } from 'application/core-business/(dtos)/autenticacao/(dtos)/autenticacao-login/IAutenticacaoLoginInputDto';
import { DtoProperty, ValidationContractString, createDtoPropertyMap, createValidationContract, getSchemaField } from 'infrastructure';
import * as yup from 'yup';
import { UsuarioDtoProperties, UsuarioDtoValidationContract } from '../usuario/dtos';

// ======================================================

export const AutenticacaoLoginDtoValidationContract = createValidationContract(() => {
const usuarioSchema = UsuarioDtoValidationContract();

return yup.object().shape({
matriculaSiape: getSchemaField(usuarioSchema, 'matriculaSiape'),
senha: ValidationContractString().required().nonNullable().min(1),
});
});

// ======================================================

export const AutenticacaoLoginDtoProperties = createDtoPropertyMap({
LOGIN_MATRICULA_SIAPE: UsuarioDtoProperties.USUARIO_MATRICULA_SIAPE,

LOGIN_SENHA: {
nullable: false,
description: 'Senha.',
//
gql: {
type: () => String,
},
swagger: {
type: 'string',
},
},
});

// ======================================================

@InputType('AutenticacaoLoginInputDto')
export class AutenticacaoLoginInputDto implements IAutenticacaoLoginInputDto {
@DtoProperty(AutenticacaoLoginDtoProperties.LOGIN_MATRICULA_SIAPE)
matriculaSiape!: string;

@DtoProperty(AutenticacaoLoginDtoProperties.LOGIN_SENHA)
senha!: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import { Int, ObjectType } from '@nestjs/graphql';
import { IAutenticacaoLoginResultDto } from 'application/core-business/(dtos)';
import { DtoProperty, createDtoPropertyMap } from 'infrastructure';

// ======================================================

export const AutenticacaoLoginResultDtoProperties = createDtoPropertyMap({
LOGIN_RESULT_ACCESS_TOKEN: {
nullable: true,
description: 'Token de acesso.',
//
gql: {
type: () => String,
},
swagger: {
type: 'string',
},
},

LOGIN_RESULT_TOKEN_TYPE: {
nullable: true,
//
description: 'Tipo de token de acesso.',
//
gql: {
type: () => String,
},
swagger: {
type: 'string',
},
},

LOGIN_RESULT_ID_TOKEN: {
nullable: true,
description: 'ID token.',
//
gql: {
type: () => String,
},
swagger: {
type: 'string',
},
},

LOGIN_RESULT_REFRESH_TOKEN: {
nullable: true,
description: 'Refresh token.',
//
gql: {
type: () => String,
},
swagger: {
type: 'string',
},
},

LOGIN_RESULT_EXPIRES_IN: {
nullable: true,
description: 'Quanto tempo para expirar o token (em segundos).',
//
gql: {
type: () => Int,
},
swagger: {
type: 'integer',
},
},

LOGIN_RESULT_EXPIRES_AT: {
nullable: true,
description: 'Data de expiração (em segundos unix).',
//
gql: {
type: () => Int,
},
swagger: {
type: 'integer',
},
},

LOGIN_RESULT_SESSION_STATE: {
nullable: true,
description: 'Estado da sessão.',
//
gql: {
type: () => String,
},
swagger: {
type: 'string',
},
},

LOGIN_RESULT_SCOPE: {
nullable: true,
description: 'Escopo do token de acesso.',
//
gql: {
type: () => String,
},
swagger: {
type: 'string',
},
},
});

// ======================================================

@ObjectType('AutenticacaoLoginResultDto')
export class AutenticacaoLoginResultDto implements IAutenticacaoLoginResultDto {
@DtoProperty(AutenticacaoLoginResultDtoProperties.LOGIN_RESULT_ACCESS_TOKEN)
access_token!: string | null;

@DtoProperty(AutenticacaoLoginResultDtoProperties.LOGIN_RESULT_TOKEN_TYPE)
token_type!: string | null;

@DtoProperty(AutenticacaoLoginResultDtoProperties.LOGIN_RESULT_ID_TOKEN)
id_token!: string | null;

@DtoProperty(AutenticacaoLoginResultDtoProperties.LOGIN_RESULT_REFRESH_TOKEN)
refresh_token!: string | null;

@DtoProperty(AutenticacaoLoginResultDtoProperties.LOGIN_RESULT_EXPIRES_IN)
expires_in!: number | null;

@DtoProperty(AutenticacaoLoginResultDtoProperties.LOGIN_RESULT_EXPIRES_AT)
expires_at!: number | null;

@DtoProperty(AutenticacaoLoginResultDtoProperties.LOGIN_RESULT_SESSION_STATE)
session_state!: string | null;

@DtoProperty(AutenticacaoLoginResultDtoProperties.LOGIN_RESULT_SCOPE)
scope!: string | null;
}

// ======================================================
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { ObjectType } from '@nestjs/graphql';
import { IUsuarioFindOneResultDto } from 'application/core-business/(dtos)';
import { DtoProperty, createDtoPropertyMap } from 'infrastructure';
import { IAutenticacaoQuemSouEuResultDto } from '../../(dtos)/autenticacao/(dtos)/autenticacao-quem-sou-eu/IAutenticacaoQuemSouEuResultDto';
import { UsuarioDto, UsuarioFindOneResultDto } from '../usuario/dtos';

// ======================================================

export const AutenticacaoQuemSouEuResultDtoProperties = createDtoPropertyMap({
QUEM_SOU_EU_USUARIO_OUTPUT: {
nullable: true,
description: 'Nulo, caso não autenticado, ou um objeto com as informações sobre o usuário.',
//
gql: {
type: () => UsuarioDto,
},
swagger: {
type: UsuarioFindOneResultDto,
},
},
});

// ======================================================

@ObjectType('AutenticacaoQuemSouEuResultDto')
export class AutenticacaoQuemSouEuResultDto implements IAutenticacaoQuemSouEuResultDto {
@DtoProperty(AutenticacaoQuemSouEuResultDtoProperties.QUEM_SOU_EU_USUARIO_OUTPUT)
usuario!: IUsuarioFindOneResultDto | null;
}

// ======================================================
Loading

0 comments on commit fe82897

Please sign in to comment.