Files
dukang/server/dukang-api/src/modules/iam/auth.controller.ts
T
2026-08-04 21:38:49 +08:00

247 lines
8.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { BadRequestException, Body, Controller, Get, Post, Req, UseGuards } from '@nestjs/common';
import type { Request } from 'express';
import { AuthService } from './auth.service';
import {
BindPhoneDto,
BindWechatDto,
BindWechatPhoneDto,
MiniWechatProfileDto,
BootstrapSessionDto,
CheckPartnerPhoneDto,
LoginSmsDto,
LoginWechatDto,
LoginWechatPhoneDto,
RefreshTokenDto,
SendSmsDto,
} from './dto/auth.dto';
import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard';
import { OptionalJwtAuthGuard } from '../../common/guards/optional-jwt-auth.guard';
import { CurrentUser } from '../../common/decorators/current-user.decorator';
import { AuthUser } from '../../common/guards/jwt-auth.guard';
import { ClientApp } from '@dukang/shared-types';
function resolveUserClientApp(req: Request): ClientApp {
const header = String(req.headers['x-client-app'] || '').trim();
if (header === ClientApp.USER_MINI) return ClientApp.USER_MINI;
return ClientApp.USER_H5;
}
@Controller()
export class UserAuthController {
constructor(private readonly authService: AuthService) {}
@Post('auth/session/bootstrap')
bootstrap(@Req() req: Request, @Body() dto: BootstrapSessionDto) {
return this.authService.bootstrapSession(dto.deviceKey, resolveUserClientApp(req));
}
@Post('auth/token/refresh')
refresh(@Req() req: Request, @Body() dto: RefreshTokenDto) {
return this.authService.refreshAccessToken(dto.refreshToken, resolveUserClientApp(req));
}
@Post('auth/sms/send')
@UseGuards(OptionalJwtAuthGuard)
sendSms(@Req() req: Request, @Body() dto: SendSmsDto) {
const guest = (req as Request & { user?: AuthUser }).user;
const guestId = guest?.actorType === 'USER' ? guest.actorId : undefined;
return this.authService.sendSms(dto.phone, dto.scene, {
guestUserId: guestId,
clientApp: resolveUserClientApp(req),
});
}
@Post('auth/login/sms')
@UseGuards(OptionalJwtAuthGuard)
login(@Req() req: Request, @Body() dto: LoginSmsDto) {
const guest = (req as Request & { user?: AuthUser }).user;
const guestId = guest?.actorType === 'USER' ? guest.actorId : undefined;
return this.authService.loginUser(dto.phone, dto.code, resolveUserClientApp(req), guestId);
}
@Post('auth/phone/bind')
@UseGuards(JwtAuthGuard)
bindPhone(@Req() req: Request, @CurrentUser() user: AuthUser, @Body() dto: BindPhoneDto) {
return this.authService.bindPhone(user.actorId, dto.phone, dto.code, resolveUserClientApp(req));
}
@Post('auth/login/wechat')
@UseGuards(OptionalJwtAuthGuard)
wechatLogin(@Req() req: Request, @Body() dto: LoginWechatDto) {
const guest = (req as Request & { user?: AuthUser }).user;
const guestId = guest?.actorType === 'USER' ? guest.actorId : undefined;
const clientApp = resolveUserClientApp(req);
const platform = dto.platform ?? (clientApp === ClientApp.USER_MINI ? 'mini' : 'h5');
return this.authService.loginUserWechat(dto.code, clientApp, platform, guestId);
}
/** 小程序手机号快捷登录(getPhoneNumber */
@Post('auth/login/wechat-phone')
@UseGuards(OptionalJwtAuthGuard)
wechatPhoneLogin(@Req() req: Request, @Body() dto: LoginWechatPhoneDto) {
const guest = (req as Request & { user?: AuthUser }).user;
const guestId = guest?.actorType === 'USER' ? guest.actorId : undefined;
const clientApp = resolveUserClientApp(req);
const platform = dto.platform ?? (clientApp === ClientApp.USER_MINI ? 'mini' : 'h5');
return this.authService.loginUserWechatPhone(
dto.phoneCode,
clientApp,
platform,
guestId,
dto.loginCode,
);
}
@Post('auth/wechat/bind-phone')
bindPhoneLegacy(@Req() req: Request, @Body() dto: BindWechatPhoneDto) {
return this.authService.bindWechatPhone(
dto.wxSessionKey,
dto.phone,
dto.code,
resolveUserClientApp(req),
);
}
@Post('auth/wechat/bind')
@UseGuards(JwtAuthGuard)
bindWechat(@Req() req: Request, @CurrentUser() user: AuthUser, @Body() dto: BindWechatDto) {
const clientApp = resolveUserClientApp(req);
const platform = dto.platform ?? (clientApp === ClientApp.USER_MINI ? 'mini' : 'h5');
return this.authService.bindUserWechat(
user.actorId,
{ code: dto.code, wxSessionKey: dto.wxSessionKey },
clientApp,
platform,
);
}
@Post('auth/wechat/mini-profile')
@UseGuards(JwtAuthGuard)
updateMiniWechatProfile(
@Req() req: Request,
@CurrentUser() user: AuthUser,
@Body() dto: MiniWechatProfileDto,
) {
if (user.actorType !== 'USER') {
throw new BadRequestException('仅用户可更新资料');
}
const clientApp = resolveUserClientApp(req);
if (clientApp !== ClientApp.USER_MINI) {
throw new BadRequestException('仅小程序端可调用');
}
return this.authService.updateMiniWechatProfile(user.actorId, dto);
}
@Get('auth/me')
@UseGuards(JwtAuthGuard)
me(@CurrentUser() user: AuthUser) {
return this.authService.getMe(user.actorType, user.actorId);
}
}
@Controller('shop/auth')
export class ShopAuthController {
constructor(private readonly authService: AuthService) {}
@Post('sms/send')
sendSms(@Body() dto: SendSmsDto) {
return this.authService.sendSms(dto.phone, dto.scene, { clientApp: ClientApp.SHOP_H5 });
}
@Post('login/sms')
login(@Body() dto: LoginSmsDto) {
return this.authService.loginStore(dto.phone, dto.code, ClientApp.SHOP_H5);
}
@Post('login/wechat')
@UseGuards(OptionalJwtAuthGuard)
wechatLogin(@Req() req: Request, @Body() dto: LoginWechatDto) {
const user = (req as Request & { user?: AuthUser }).user;
if (user?.actorType === 'STORE') {
return this.authService.bindStoreWechat(
user.actorId,
dto.code,
ClientApp.SHOP_H5,
dto.platform ?? 'h5',
user.storeId,
);
}
return this.authService.loginStoreWechat(dto.code, ClientApp.SHOP_H5, dto.platform ?? 'h5');
}
@Post('token/refresh')
refresh(@Body() dto: RefreshTokenDto) {
return this.authService.refreshAccessToken(dto.refreshToken, ClientApp.SHOP_H5);
}
@Get('stores')
@UseGuards(JwtAuthGuard)
stores(@CurrentUser() user: AuthUser) {
return this.authService.listShopStores(user.actorId);
}
@Post('select-store')
@UseGuards(JwtAuthGuard)
selectStore(@CurrentUser() user: AuthUser, @Body() body: { storeId: string }) {
if (!body?.storeId) throw new BadRequestException('请选择门店');
return this.authService.selectShopStore(user.actorId, BigInt(body.storeId), ClientApp.SHOP_H5);
}
@Get('me')
@UseGuards(JwtAuthGuard)
me(@CurrentUser() user: AuthUser) {
return this.authService.getShopMe(user);
}
}
@Controller('partner/auth')
export class PartnerAuthController {
constructor(private readonly authService: AuthService) {}
@Post('phone/check')
checkPhone(@Body() dto: CheckPartnerPhoneDto) {
return this.authService.checkPartnerPhone(dto.phone);
}
@Post('sms/send')
sendSms(@Body() dto: SendSmsDto) {
return this.authService.sendSms(dto.phone, dto.scene, { clientApp: ClientApp.PARTNER_H5 });
}
@Post('login/sms')
login(@Body() dto: LoginSmsDto) {
return this.authService.loginPartner(dto.phone, dto.code, ClientApp.PARTNER_H5);
}
@Post('login/wechat')
@UseGuards(OptionalJwtAuthGuard)
wechatLogin(@Req() req: Request, @Body() dto: LoginWechatDto) {
const user = (req as Request & { user?: AuthUser }).user;
if (user?.actorType === 'PARTNER') {
return this.authService.bindPartnerWechat(
user.actorId,
dto.code,
ClientApp.PARTNER_H5,
dto.platform ?? 'h5',
);
}
return this.authService.loginPartnerWechat(dto.code, ClientApp.PARTNER_H5, dto.platform ?? 'h5');
}
@Post('token/refresh')
refresh(@Body() dto: RefreshTokenDto) {
return this.authService.refreshAccessToken(dto.refreshToken, ClientApp.PARTNER_H5);
}
}
@Controller('user')
export class UserProfileController {
constructor(private readonly authService: AuthService) {}
@Get('profile')
@UseGuards(JwtAuthGuard)
profile(@CurrentUser() user: AuthUser) {
return this.authService.getMe(user.actorType, user.actorId);
}
}