ldap: add employeeID

apps/api: add /telegram-confirm method
apps/web: show bot link info
This commit is contained in:
vchikalkin 2024-05-28 15:55:37 +03:00
parent 7a913a23f0
commit 6ab9d44430
10 changed files with 67 additions and 6 deletions

View File

@ -35,6 +35,7 @@
"@nestjs/platform-express": "^10.2.7",
"@nestjs/platform-fastify": "^10.2.7",
"@nestjs/swagger": "^7.1.14",
"axios": "^1.5.1",
"bcrypt": "^5.1.1",
"cache-manager": "^5.2.4",
"cache-manager-ioredis": "^2.1.0",

View File

@ -23,6 +23,7 @@ const envSchema = z.object({
.string()
.transform((val) => Number.parseInt(val, 10))
.default('6379'),
TELEGRAM_SERVICE_URL_SEND_MESSAGE: z.string(),
});
export default envSchema;

View File

@ -1,6 +1,7 @@
/* eslint-disable @typescript-eslint/explicit-member-accessibility */
import { Body, Controller, HttpException, HttpStatus, Post, Req, Res } from '@nestjs/common';
import { ApiResponse, ApiTags } from '@nestjs/swagger';
import axios from 'axios';
import { FastifyReply, FastifyRequest } from 'fastify';
import { cookieOptions } from 'src/config/cookie';
import { env } from 'src/config/env';
@ -37,6 +38,19 @@ export class LdapTfaController extends LdapController {
async loginTelegram(@AuthToken() token: string, @Res() reply: FastifyReply) {
const user = await this.ldapService.getUser(token);
await axios.post(env.TELEGRAM_SERVICE_URL_SEND_MESSAGE, {
authId: crypto.randomUUID(),
user,
});
return reply.status(200).send(user);
}
@Post('/telegram-confirm')
@ApiResponse({
status: HttpStatus.OK,
})
async telegramConfirm(@Req() req: FastifyRequest, @Res() reply: FastifyReply) {
return reply.status(200).send('ok');
}
}

View File

@ -18,6 +18,8 @@ export class User {
public position: string;
@ApiResponseProperty()
public username: string;
@ApiResponseProperty()
public employeeID: string;
}
export type LdapUser = {
@ -108,6 +110,7 @@ export async function authenticate(login: string, password?: string) {
title,
mail,
sAMAccountName: username,
employeeID,
}: LdapUser = await ldap.authenticate(options);
const user: User = {
@ -115,6 +118,7 @@ export async function authenticate(login: string, password?: string) {
displayName,
domain: env.LDAP_DOMAIN,
domainName: `${env.LDAP_DOMAIN}\\${username}`,
employeeID,
mail,
position: title,
username,

View File

@ -14,7 +14,7 @@ import { useForm } from 'react-hook-form';
const ERROR_INVALID_CREDENTIALS = 'Неверный логин или пароль';
const ERROR_SERVER = 'Не удалось войти. Повторите попытку позже';
const { APP_BASE_PATH } = publicRuntimeConfig;
const { APP_BASE_PATH, TELEGRAM_BOT_URL } = publicRuntimeConfig;
type FormData = {
readonly login: string;
@ -49,6 +49,11 @@ function BaseForm({ children, onSubmit }: FormProps & PropsWithChildren) {
autoComplete="on"
{...register('password', { required: true })}
/>
{step === 'telegram-login' ? (
<a target="_blank" className="info" href={TELEGRAM_BOT_URL} rel="noreferrer">
Открыть чат с ботом
</a>
) : null}
{error ? <span className="error">{error}</span> : null}
{children}
</form>
@ -111,11 +116,16 @@ export const Form = {
}
function handleTelegramLogin() {
// window.open(TELEGRAM_BOT_URL);
axios
.post<LdapUser>('/login-telegram')
.then((res) => {
// eslint-disable-next-line no-console
console.log('🚀 ~ .then ~ res:', res);
.then(() => {
dispatch({
payload: {
step: 'telegram-login',
},
type: 'set-step',
});
})
.catch(() =>
dispatch({
@ -142,6 +152,23 @@ export const Form = {
);
}
if (step === 'telegram-login') {
return (
<BaseForm onSubmit={() => {}}>
<button disabled type="submit" className={styles['button-telegram']}>
<Image
className={styles['button-telegram-icon']}
src={TelegramIcon}
width={24}
height={22}
alt="Telegram icon"
/>
Ожидаем подтверждения...
</button>
</BaseForm>
);
}
return (
<BaseForm onSubmit={(data) => handleLogin(data)}>
<button className={styles['button-submit']} type="submit">

View File

@ -1,8 +1,9 @@
const { z } = require('zod');
const envSchema = z.object({
APP_DESCRIPTION: z.string(),
APP_BASE_PATH: z.string().optional().default(''),
APP_DESCRIPTION: z.string(),
TELEGRAM_BOT_URL: z.string(),
});
module.exports = envSchema;

View File

@ -5,7 +5,7 @@ import { createContext, useMemo, useReducer } from 'react';
type State = {
error: string | undefined;
step: 'login' | 'telegram';
step: 'login' | 'telegram' | 'telegram-login';
user: LdapUser | undefined;
};

View File

@ -3,3 +3,4 @@
@import './h.css';
@import './error.css';
@import './colors.css';
@import './info.css';

9
apps/web/styles/info.css Normal file
View File

@ -0,0 +1,9 @@
.info {
display: inline-block;
font-family: Montserrat;
font-size: smaller;
font-weight: bold;
text-transform: uppercase;
text-decoration: none;
color: var(--color-primary);
}

3
pnpm-lock.yaml generated
View File

@ -59,6 +59,9 @@ importers:
'@nestjs/swagger':
specifier: ^7.1.14
version: 7.1.16(@fastify/static@6.12.0)(@nestjs/common@10.2.10)(@nestjs/core@10.2.10)(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)
axios:
specifier: ^1.5.1
version: 1.6.2
bcrypt:
specifier: ^5.1.1
version: 5.1.1