feat: add new route for user me and quota
This commit is contained in:
@@ -5,7 +5,7 @@ import { LoginDto } from "./DTO/login.dto";
|
||||
import { RefreshTokenDto } from "./DTO/refresh-token.dto";
|
||||
import { AuthService } from "./services/auth.service";
|
||||
import { AuthGuards } from "../../common/decorators/auth-guard.decorator";
|
||||
import { RefreshTokenRateLimit } from "../../common/decorators/rate-limit.decorator";
|
||||
import { RefreshTokenRateLimit, StrictRateLimit } from "../../common/decorators/rate-limit.decorator";
|
||||
import { UserDec } from "../../common/decorators/user.decorator";
|
||||
|
||||
@ApiTags("Authentication")
|
||||
@@ -13,6 +13,7 @@ import { UserDec } from "../../common/decorators/user.decorator";
|
||||
export class AuthController {
|
||||
constructor(private readonly authService: AuthService) {}
|
||||
|
||||
@StrictRateLimit()
|
||||
@Post("login")
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@ApiOperation({ summary: "Login user" })
|
||||
|
||||
@@ -12,7 +12,7 @@ export class LocalJwtStrategy extends PassportStrategy(Strategy, LOCAL_JWT_STRAT
|
||||
super({
|
||||
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
|
||||
ignoreExpiration: false,
|
||||
secretOrKey: configService.getOrThrow<string>("JWT_SECRET"),
|
||||
secretOrKey: configService.getOrThrow<string>("JWT_SECRET_KEY"),
|
||||
issuer: configService.getOrThrow<string>("JWT_ISSUER"),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
export const SUBSCRIPTIONS = Object.freeze({
|
||||
PROVISIONING_QUEUE_PREFIX: "provisioning",
|
||||
PROVISIONING_QUEUE_PREFIX: "subs",
|
||||
PROVISIONING_QUEUE_NAME: "provisioning",
|
||||
PROVISIONING_JOB_NAME: "business.created",
|
||||
|
||||
|
||||
@@ -132,7 +132,7 @@ export class DomainAutomationService {
|
||||
if (!mailServerUser.success) throw new BadRequestException(MailServerMessage.FAILED_TO_CREATE_ACCOUNT);
|
||||
|
||||
// Check if business has enough quota
|
||||
const remainingQuota = domain.business.remainingQuota || 0;
|
||||
const remainingQuota = Number(domain.business.remainingQuota || 0);
|
||||
if (remainingQuota < QUOTA_CONSTANTS.USER_QUOTA_DEDUCTION) throw new BadRequestException(BusinessMessage.INSUFFICIENT_QUOTA);
|
||||
|
||||
// Create user in local database
|
||||
@@ -152,8 +152,8 @@ export class DomainAutomationService {
|
||||
});
|
||||
|
||||
// Update business quota after successful user creation
|
||||
domain.business.usedQuota = (domain.business.usedQuota || 0) + QUOTA_CONSTANTS.USER_QUOTA_DEDUCTION;
|
||||
domain.business.remainingQuota = (domain.business.quota || 0) - domain.business.usedQuota;
|
||||
domain.business.usedQuota = Number(domain.business.usedQuota || 0) + QUOTA_CONSTANTS.USER_QUOTA_DEDUCTION;
|
||||
domain.business.remainingQuota = Number(domain.business.quota || 0) - Number(domain.business.usedQuota);
|
||||
|
||||
await this.em.persistAndFlush([user, domain.business]);
|
||||
|
||||
|
||||
@@ -216,6 +216,8 @@ export class DomainsService {
|
||||
|
||||
const domain = await this.getDomainById(businessDomain.id, businessId);
|
||||
|
||||
const { dnsRecords } = await this.dnsService.getDomainDnsRecords(domain.id);
|
||||
|
||||
// If domain is already verified, skip verification check and return DNS records directly
|
||||
if (domain.isVerified && domain.status === DomainStatus.VERIFIED) {
|
||||
const { dnsRecords } = await this.dnsService.getDomainDnsRecords(domain.id);
|
||||
@@ -234,7 +236,7 @@ export class DomainsService {
|
||||
};
|
||||
}
|
||||
|
||||
const { dnsRecords, overallStatus, recommendations } = await this.checkDomainVerificationStatus(businessId);
|
||||
const { overallStatus, recommendations } = await this.checkDomainVerificationStatus(businessId);
|
||||
|
||||
return {
|
||||
dnsRecords,
|
||||
@@ -304,7 +306,7 @@ export class DomainsService {
|
||||
}
|
||||
|
||||
return {
|
||||
dnsRecords: verificationStatuses,
|
||||
verificationStatuses,
|
||||
overallStatus: {
|
||||
isVerified,
|
||||
isComplete,
|
||||
|
||||
@@ -29,6 +29,7 @@ export class UserRepository extends EntityRepository<User> {
|
||||
}
|
||||
|
||||
return this.findAndCount(whereClause, {
|
||||
exclude: ["password"],
|
||||
populate: ["domain", "business"],
|
||||
limit,
|
||||
offset: skip,
|
||||
|
||||
@@ -57,9 +57,24 @@ export class UsersService {
|
||||
/*******************************/
|
||||
|
||||
async getMe(userId: string) {
|
||||
const user = await this.userRepository.findOne({ id: userId }, { populate: ["role"] });
|
||||
const user = await this.userRepository.findOne({ id: userId }, { exclude: ["password"], populate: ["role"] });
|
||||
if (!user) throw new BadRequestException(UserMessage.USER_NOT_FOUND);
|
||||
return { user };
|
||||
|
||||
return {
|
||||
user,
|
||||
quota: {
|
||||
total: Number(user.emailQuota),
|
||||
used: Number(user.emailQuotaUsed),
|
||||
remaining: Number(user.emailQuota - user.emailQuotaUsed),
|
||||
totalInMB: Math.round(Number(user.emailQuota) / (1024 * 1024)),
|
||||
totalInGB: Math.round(Number(user.emailQuota) / (1024 * 1024 * 1024)),
|
||||
usedInMB: Math.round(Number(user.emailQuotaUsed) / (1024 * 1024)),
|
||||
usedInGB: Math.round(Number(user.emailQuotaUsed) / (1024 * 1024 * 1024)),
|
||||
remainingInMB: Math.round(Number(user.emailQuota - user.emailQuotaUsed) / (1024 * 1024)),
|
||||
remainingInGB: Math.round(Number(user.emailQuota - user.emailQuotaUsed) / (1024 * 1024 * 1024)),
|
||||
usagePercentage: Math.round((Number(user.emailQuotaUsed) / Number(user.emailQuota)) * 100),
|
||||
},
|
||||
};
|
||||
}
|
||||
/*******************************/
|
||||
|
||||
@@ -77,7 +92,7 @@ export class UsersService {
|
||||
if (!business) throw new BadRequestException(BusinessMessage.NOT_FOUND);
|
||||
|
||||
// Check if business has enough quota
|
||||
const remainingQuota = business.remainingQuota || 0;
|
||||
const remainingQuota = Number(business.remainingQuota || 0);
|
||||
if (remainingQuota < QUOTA_CONSTANTS.USER_QUOTA_DEDUCTION) {
|
||||
throw new BadRequestException("Insufficient quota to create user. Please upgrade your plan.");
|
||||
}
|
||||
@@ -129,8 +144,8 @@ export class UsersService {
|
||||
});
|
||||
|
||||
// Update business quota after successful user creation
|
||||
business.usedQuota = business.usedQuota + QUOTA_CONSTANTS.USER_QUOTA_DEDUCTION;
|
||||
business.remainingQuota = business.quota - business.usedQuota;
|
||||
business.usedQuota = Number(business.usedQuota) + QUOTA_CONSTANTS.USER_QUOTA_DEDUCTION;
|
||||
business.remainingQuota = Number(business.quota) - Number(business.usedQuota);
|
||||
|
||||
await this.em.persistAndFlush([user, business]);
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import { UserListQueryDto } from "./DTO/user-list-query.dto";
|
||||
import { UsersService } from "./services/users.service";
|
||||
import { AuthGuards } from "../../common/decorators/auth-guard.decorator";
|
||||
import { BusinessDec } from "../../common/decorators/business.decorator";
|
||||
import { UserDec } from "../../common/decorators/user.decorator";
|
||||
import { ParamDto } from "../../common/DTO/param.dto";
|
||||
import { BusinessInterceptor } from "../../core/interceptors/business.interceptor";
|
||||
|
||||
@@ -16,6 +17,13 @@ import { BusinessInterceptor } from "../../core/interceptors/business.intercepto
|
||||
export class UsersController {
|
||||
constructor(private readonly usersService: UsersService) {}
|
||||
|
||||
@Get("me")
|
||||
@ApiOperation({ summary: "Get current user" })
|
||||
@ApiResponse({ status: 200, description: "Current user retrieved successfully" })
|
||||
getMe(@UserDec("wildduckUserId") userId: string) {
|
||||
return this.usersService.getMe(userId);
|
||||
}
|
||||
|
||||
@Post()
|
||||
@ApiOperation({ summary: "Create a new email user" })
|
||||
@ApiResponse({ status: 201, description: "Email user created successfully" })
|
||||
|
||||
Reference in New Issue
Block a user