Add production-ready SuperAdmin API features for tenants, SMS, servers, and plugins.

Includes mobile auth, get_user/get_version, SMS wallet parity endpoints, appearance backfill, and related Prisma migrations.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-30 18:19:53 +03:30
co-authored by Cursor
parent ddf36f8470
commit a6b3457779
54 changed files with 3770 additions and 156 deletions
+22 -10
View File
@@ -1,8 +1,8 @@
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { JwtService } from '@nestjs/jwt';
import * as bcrypt from 'bcrypt';
import { PrismaService } from '../prisma/prisma.service';
import { displayName, normalizeMobile } from '../common/mobile.util';
import { LoginDto } from './dto/login.dto';
@Injectable()
@@ -10,26 +10,31 @@ export class AuthService {
constructor(
private readonly prisma: PrismaService,
private readonly jwt: JwtService,
private readonly config: ConfigService,
) {}
async login(dto: LoginDto) {
const mobile = normalizeMobile(dto.mobile);
if (!mobile) {
throw new UnauthorizedException('موبایل یا رمز عبور نادرست است');
}
const user = await this.prisma.user.findUnique({
where: { email: dto.email.toLowerCase() },
where: { mobile },
});
if (!user || !user.isActive) {
throw new UnauthorizedException('ایمیل یا رمز عبور نادرست است');
throw new UnauthorizedException('موبایل یا رمز عبور نادرست است');
}
const ok = await bcrypt.compare(dto.password, user.passwordHash);
if (!ok) {
throw new UnauthorizedException('ایمیل یا رمز عبور نادرست است');
throw new UnauthorizedException('موبایل یا رمز عبور نادرست است');
}
const name = displayName(user.firstName, user.lastName);
const payload = {
sub: user.id,
email: user.email,
mobile: user.mobile,
role: user.role,
};
@@ -37,8 +42,10 @@ export class AuthService {
accessToken: await this.jwt.signAsync(payload),
user: {
id: user.id,
email: user.email,
name: user.name,
mobile: user.mobile,
firstName: user.firstName,
lastName: user.lastName,
name,
role: user.role,
},
};
@@ -49,8 +56,10 @@ export class AuthService {
where: { id: userId },
select: {
id: true,
mobile: true,
firstName: true,
lastName: true,
email: true,
name: true,
role: true,
isActive: true,
createdAt: true,
@@ -61,6 +70,9 @@ export class AuthService {
throw new UnauthorizedException();
}
return user;
return {
...user,
name: displayName(user.firstName, user.lastName),
};
}
}