Skip to content

Commit

Permalink
Fix minor issues
Browse files Browse the repository at this point in the history
  • Loading branch information
csuvajit committed Mar 7, 2024
1 parent 911e766 commit 05492dc
Show file tree
Hide file tree
Showing 29 changed files with 298 additions and 98 deletions.
6 changes: 3 additions & 3 deletions apps/service-auth/src/auth/auth.controller.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { CurrentUser, JwtAuthGuard, JwtUser } from '@app/auth';
import { CurrentUserExpanded, JwtAuthGuard, JwtUser } from '@app/auth';
import { getAppHealth } from '@app/helper';
import { Body, Controller, Get, Post, UseGuards } from '@nestjs/common';
import { ApiBearerAuth, ApiExcludeEndpoint, ApiTags } from '@nestjs/swagger';
import { AuthService } from './auth.service';
import { LoginInput } from './dto/login.dto';
import { LoginInput } from './dto';

@ApiTags('AUTH')
@Controller('/auth')
Expand All @@ -30,7 +30,7 @@ export class AuthController {
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@Get('/status')
getStatus(@CurrentUser() user: JwtUser) {
getStatus(@CurrentUserExpanded() user: JwtUser) {
return user;
}
}
34 changes: 23 additions & 11 deletions apps/service-auth/src/auth/auth.service.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,42 @@
import { JwtUser } from '@app/auth';
import { Tokens } from '@app/constants';
import { MongoDbService } from '@app/mongodb';
import { RedisClient, RedisService } from '@app/redis';
import { Inject, Injectable } from '@nestjs/common';
import { Collections } from '@app/constants';
import { PortalUsersEntity } from '@app/entities';
import { Inject, Injectable, UnauthorizedException } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { Db } from 'mongodb';
import moment from 'moment';
import { Collection } from 'mongodb';
import { v4 as uuid } from 'uuid';

const jwtVersion = 'v1';

@Injectable()
export class AuthService {
constructor(
@Inject(Tokens.MONGODB) private readonly db: Db,
@Inject(Tokens.REDIS) private readonly redis: RedisClient,
private readonly redisService: RedisService,
private readonly mongoDbService: MongoDbService,
private readonly jwtService: JwtService,
@Inject(Collections.PORTAL_USERS) private portalUsersCollection: Collection<PortalUsersEntity>,
) {}

async login(userId: string) {
const payload = { sub: userId, jti: uuid() } satisfies Partial<JwtUser>;
async login(passKey: string) {
const user = await this.portalUsersCollection.findOne({ passKey });
if (!user) throw new UnauthorizedException();

const payload = {
sub: user.userId,
jti: uuid(),
version: jwtVersion,
roles: user.roles,
} satisfies Partial<JwtUser>;

return {
userId: user.userId,
roles: user.roles,
expiresIn: moment().add(30, 'days').toDate().getTime(),
accessToken: this.jwtService.sign(payload, { expiresIn: '30d' }),
};
}

async validateJwt(jwtUser: JwtUser) {
if (jwtUser.version !== jwtVersion) throw new UnauthorizedException();
return jwtUser;
}
}
1 change: 1 addition & 0 deletions apps/service-auth/src/auth/dto/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './login.dto';
4 changes: 2 additions & 2 deletions apps/service-auth/src/clans/clans.controller.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { JwtAuthGuard } from '@app/auth';
import { JwtAuthGuard, RolesGuard } from '@app/auth';
import { Controller, Get, Param, UseGuards } from '@nestjs/common';
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
import { ClansService } from './clans.service';

@ApiTags('CLANS')
@ApiBearerAuth()
@Controller('/clans')
@UseGuards(JwtAuthGuard)
@UseGuards(JwtAuthGuard, RolesGuard)
export class ClansController {
constructor(private clansService: ClansService) {}

Expand Down
24 changes: 24 additions & 0 deletions apps/service-auth/src/guilds/dto/guild-output.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
export class GuildOutput {
name: string;
guildId: string;
clans: GuildClanOutput[];
categories: ClanCategoryOutput[];
grouped: ClanCategoryGroupOutput[];
}

export class GuildClanOutput {
_id: string;
name: string;
tag: string;
order: number;
}

export class ClanCategoryOutput {
_id: string;
name: string;
order: number;
}

export class ClanCategoryGroupOutput extends ClanCategoryOutput {
clans: GuildClanOutput[];
}
3 changes: 3 additions & 0 deletions apps/service-auth/src/guilds/dto/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './aggregated.dto';
export * from './guild-output.dto';
export * from './reorder-clan-categories.dto';
29 changes: 29 additions & 0 deletions apps/service-auth/src/guilds/dto/reorder-clan-categories.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { ArrayMinSize, IsArray, IsInt, IsNotEmpty, ValidateNested } from 'class-validator';

export class ReorderClanCategoriesInput {
@ValidateNested({ each: true })
@IsArray()
@ArrayMinSize(1)
categories: ReorderCategoriesInput[];
}

export class ReorderCategoriesInput {
@IsNotEmpty()
_id: string;

@IsInt()
order: number;

@ValidateNested({ each: true })
@IsArray()
@ArrayMinSize(1)
clans: ReorderClansInput[];
}

export class ReorderClansInput {
@IsNotEmpty()
_id: string;

@IsInt()
order: number;
}
32 changes: 0 additions & 32 deletions apps/service-auth/src/guilds/dto/update-clan-categories.dto.ts

This file was deleted.

24 changes: 15 additions & 9 deletions apps/service-auth/src/guilds/guilds.controller.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { JwtAuthGuard } from '@app/auth';
import { JwtAuthGuard, Role, Roles, RolesGuard } from '@app/auth';
import { Body, Controller, Get, Param, Put, Query, UseGuards } from '@nestjs/common';
import { ApiBearerAuth, ApiBody, ApiOperation, ApiTags } from '@nestjs/swagger';
import { ReorderCategoriesInput } from './dto/update-clan-categories.dto';
import { ApiBearerAuth, ApiBody, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { GuildOutput, ReorderClanCategoriesInput } from './dto';
import { GuildsService } from './guilds.service';

@ApiTags('GUILDS')
@Controller('/guilds')
@ApiBearerAuth()
@UseGuards(JwtAuthGuard)
@Roles(Role.USER)
@UseGuards(JwtAuthGuard, RolesGuard)
export class GuildsController {
constructor(private guildsService: GuildsService) {}

Expand All @@ -19,14 +20,19 @@ export class GuildsController {

@Get('/:guildId')
@ApiOperation({ summary: '(Internal)' })
getGuild(@Param('guildId') guildId: string) {
@ApiResponse({ type: GuildOutput, status: 200 })
getGuild(@Param('guildId') guildId: string): Promise<GuildOutput> {
return this.guildsService.getGuild(guildId);
}

@Put('/:guildId/reorder-clans')
@Put('/:guildId/clans/reorder')
@ApiOperation({ summary: '(Internal)' })
@ApiBody({ type: ReorderCategoriesInput, isArray: true })
updateClansAndCategories(@Param('guildId') guildId: string, @Body() _: ReorderCategoriesInput[]) {
return this.guildsService.getGuild(guildId);
@ApiResponse({ type: GuildOutput, status: 200 })
@ApiBody({ type: ReorderClanCategoriesInput })
reorderClanCategories(
@Param('guildId') guildId: string,
@Body() input: ReorderClanCategoriesInput,
) {
return this.guildsService.reorderClanCategories(guildId, input);
}
}
83 changes: 70 additions & 13 deletions apps/service-auth/src/guilds/guilds.service.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { Collections } from '@app/constants';
import { DiscordClientService } from '@app/discord-client';
import { ClanStoresEntity } from '@app/entities';
import { BotGuildsEntity } from '@app/entities/bot-guilds.entity';
import { ClanCategoriesEntity } from '@app/entities/clan-categories.entity';
import {
BotGuildsEntity,
ClanCategoriesEntity,
ClanStoresEntity,
SettingsEntity,
} from '@app/entities';
import { Inject, Injectable, NotFoundException } from '@nestjs/common';
import { Collection } from 'mongodb';
import { GuildAggregated } from './dto/aggregated.dto';
import { AnyBulkWriteOperation, Collection, ObjectId } from 'mongodb';
import { GuildAggregated, GuildClanOutput, GuildOutput, ReorderClanCategoriesInput } from './dto';

@Injectable()
export class GuildsService {
Expand All @@ -16,13 +19,15 @@ export class GuildsService {
private clanCategoriesCollection: Collection<ClanCategoriesEntity>,
@Inject(Collections.BOT_GUILDS)
private botGuildsCollection: Collection<BotGuildsEntity>,
@Inject(Collections.SETTINGS)
private settingsCollection: Collection<SettingsEntity>,
) {}

getMembers(guildId: string, q: string) {
return this.discordClientService.listMembers(guildId, q);
}

async getGuild(guildId: string) {
async getGuild(guildId: string): Promise<GuildOutput> {
const [guild] = await this.botGuildsCollection
.aggregate<GuildAggregated>([
{
Expand Down Expand Up @@ -66,13 +71,13 @@ export class GuildsService {
const categoryIds = categories.map((category) => category._id.toHexString());
const categoryMap = Object.fromEntries(categories.map((cat) => [cat._id.toHexString(), cat]));

const clansReduced = clans.reduce<Record<string, any[]>>((prev, curr) => {
const clansReduced = clans.reduce<Record<string, GuildClanOutput[]>>((prev, curr) => {
let categoryId = curr.categoryId?.toHexString() || 'general';
if (!categoryIds.includes(categoryId)) categoryId = 'general';

prev[categoryId] ??= [];
prev[categoryId]!.push({
_id: curr._id,
_id: curr._id.toHexString(),
name: curr.name,
tag: curr.tag,
order: curr.order ?? 0,
Expand All @@ -81,7 +86,7 @@ export class GuildsService {
}, {});

const clansGrouped = Object.entries(clansReduced).map(([categoryId, clans]) => ({
_id: categoryMap[categoryId]?._id || 'general',
_id: categoryMap[categoryId]?._id.toHexString() || 'general',
name: categoryMap[categoryId]?.displayName || 'General',
order: categoryMap[categoryId]?.order || 0,
clans,
Expand All @@ -91,7 +96,7 @@ export class GuildsService {
const category = categoryMap[categoryId];
if (category && !(categoryId in clansReduced)) {
clansGrouped.push({
_id: category._id,
_id: category._id.toHexString(),
name: category.displayName,
order: category.order,
clans: [],
Expand All @@ -104,17 +109,69 @@ export class GuildsService {
name: guild.name,
guildId: guild.guild,
clans: clans.map((clan) => ({
_id: clan._id,
_id: clan._id.toHexString(),
name: clan.name,
tag: clan.tag,
order: clan.order,
order: clan.order ?? 0,
})),
categories: categories.map((category) => ({
_id: category._id,
_id: category._id.toHexString(),
name: category.displayName,
order: category.order,
})),
grouped: clansGrouped,
};
}

async reorderClanCategories(guildId: string, { categories }: ReorderClanCategoriesInput) {
const clanOps: AnyBulkWriteOperation<ClanStoresEntity>[] = [];
const categoryOps: AnyBulkWriteOperation<ClanCategoriesEntity>[] = [];

const clans = categories
.flatMap((cg) => cg.clans.map((clan) => ({ ...clan, categoryId: cg._id })))
.sort((a, b) => {
if (a.categoryId === 'general' && b.categoryId !== 'general') {
return -1; // a comes before b
} else if (a.categoryId !== 'general' && b.categoryId === 'general') {
return 1; // b comes before a
} else {
return 0; // maintain original order if neither or both are 'general'
}
});

clans.forEach((clan, order) => {
clanOps.push({
updateOne: {
filter: { _id: new ObjectId(clan._id), guild: guildId },
update: {
$set: {
order,
categoryId: ObjectId.isValid(clan.categoryId) ? new ObjectId(clan.categoryId) : null,
},
},
},
});
});

categories.forEach((cat, order) => {
if (ObjectId.isValid(cat._id)) {
categoryOps.push({
updateOne: {
filter: { _id: new ObjectId(cat._id), guildId },
update: {
$set: {
order: order,
},
},
},
});
}
});

await this.clanCategoriesCollection.bulkWrite(categoryOps);
await this.clanStoresCollection.bulkWrite(clanOps);
await this.settingsCollection.updateOne({ guildId }, { $set: { clansSortingKey: 'order' } });

return this.getGuild(guildId);
}
}
4 changes: 2 additions & 2 deletions apps/service-auth/src/links/dto/bulk-links.dto.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { ArrayMaxSize, IsNotEmpty, IsString } from 'class-validator';
import { ArrayMaxSize, ArrayMinSize, IsString } from 'class-validator';

export class BulkLinksDto {
@IsString({ each: true })
@IsNotEmpty()
@ArrayMinSize(1)
@ArrayMaxSize(1000)
input: string[];
}
3 changes: 3 additions & 0 deletions apps/service-auth/src/links/dto/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './bulk-links.dto';
export * from './create-links.dto';
export * from './delete-link.dto';
Loading

0 comments on commit 05492dc

Please sign in to comment.