-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
General REST behavior for jobs (#55)
- Loading branch information
1 parent
2c89a65
commit 99aad7f
Showing
11 changed files
with
254 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,17 @@ | ||
import {Injectable} from "@nestjs/common"; | ||
import {FriendsService} from "./friend.service"; | ||
import {OnEvent} from "@nestjs/event-emitter"; | ||
import {User} from "../user/user.schema"; | ||
import {FriendService} from "./friend.service"; | ||
|
||
@Injectable() | ||
export class FriendsHandler { | ||
export class FriendHandler { | ||
constructor( | ||
private friendsService: FriendsService, | ||
private friendService: FriendService, | ||
) { | ||
} | ||
|
||
@OnEvent('users.*.deleted') | ||
async onUserDeleted(user: User): Promise<void> { | ||
await this.friendsService.deleteMany({$or: [{from: user._id}, {to: user._id}]}); | ||
await this.friendService.deleteMany({$or: [{from: user._id}, {to: user._id}]}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,17 @@ | ||
import {Module} from '@nestjs/common'; | ||
import {MongooseModule} from '@nestjs/mongoose'; | ||
import {Friend, FriendSchema} from "./friend.schema"; | ||
import {FriendsService} from "./friend.service"; | ||
import {FriendsController} from "./friend.controller"; | ||
import {FriendsHandler} from "./friend.handler"; | ||
import {FriendService} from "./friend.service"; | ||
import {FriendHandler} from "./friend.handler"; | ||
import {FriendController} from "./friend.controller"; | ||
|
||
@Module({ | ||
imports: [ | ||
MongooseModule.forFeature([{name: Friend.name, schema: FriendSchema}]), | ||
], | ||
providers: [FriendsService, FriendsHandler], | ||
controllers: [FriendsController], | ||
exports: [FriendsService], | ||
providers: [FriendService, FriendHandler], | ||
controllers: [FriendController], | ||
exports: [FriendService], | ||
}) | ||
export class FriendsModule { | ||
export class FriendModule { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
export enum JobType { | ||
BUILDING = 'building', | ||
DISTRICT = 'district', | ||
UPGRADE = 'upgrade', | ||
TECHNOLOGY = 'technology', | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
import { | ||
Body, | ||
Controller, | ||
Delete, ForbiddenException, | ||
Get, | ||
Param, | ||
Post, | ||
Query, | ||
} from '@nestjs/common'; | ||
import { | ||
ApiCreatedResponse, | ||
ApiForbiddenResponse, | ||
ApiOkResponse, | ||
ApiOperation, | ||
ApiQuery, | ||
ApiTags, | ||
} from '@nestjs/swagger'; | ||
import {Types} from 'mongoose'; | ||
import {NotFound, ObjectIdPipe} from '@mean-stream/nestx'; | ||
import {Validated} from '../util/validated.decorator'; | ||
import {Throttled} from '../util/throttled.decorator'; | ||
import {Auth, AuthUser} from '../auth/auth.decorator'; | ||
import {Job} from './job.schema'; | ||
import {User} from '../user/user.schema'; | ||
import {CreateJobDto} from './job.dto'; | ||
import {JobService} from './job.service'; | ||
import {EmpireService} from "../empire/empire.service"; | ||
import {JobType} from "./job-type.enum"; | ||
|
||
@Controller('games/:game/empires/:empire/jobs') | ||
@ApiTags('Jobs') | ||
@Validated() | ||
@Throttled() | ||
export class JobController { | ||
constructor( | ||
private readonly jobService: JobService, | ||
private readonly empireService: EmpireService, | ||
) { | ||
} | ||
|
||
@Get() | ||
@Auth() | ||
@ApiOperation({description: 'Get the job list with optional filters for system and type.'}) | ||
@ApiOkResponse({type: [Job]}) | ||
@ApiForbiddenResponse({description: 'You can only access jobs for your own empire.'}) | ||
@NotFound() | ||
@ApiQuery({ | ||
name: 'system', | ||
description: 'Filter jobs by system', | ||
required: false, | ||
type: String, | ||
example: '60d6f7eb8b4b8a001d6f7eb1', | ||
}) | ||
@ApiQuery({ | ||
name: 'type', | ||
description: 'Filter jobs by type (`building`, `district`, `upgrade`, `technology`).', | ||
required: false, | ||
enum: JobType, | ||
}) | ||
async getJobs( | ||
@Param('game', ObjectIdPipe) game: Types.ObjectId, | ||
@Param('empire', ObjectIdPipe) empire: Types.ObjectId, | ||
@AuthUser() user: User, | ||
@Query('system', ObjectIdPipe) system?: Types.ObjectId, | ||
@Query('type') type?: string, | ||
): Promise<Job[]> { | ||
const userEmpire = await this.empireService.findOne({game, user: user._id}); | ||
if (!userEmpire || !empire.equals(userEmpire._id)) { | ||
throw new ForbiddenException('You can only access jobs for your own empire.'); | ||
} | ||
// TODO: Return jobs with given filters | ||
return Array.of(new Job()); | ||
} | ||
|
||
@Post() | ||
@Auth() | ||
@ApiOperation({description: 'Create a new job for your empire.'}) | ||
@ApiCreatedResponse({type: Job}) | ||
@ApiForbiddenResponse({description: 'You can only create jobs for your own empire.'}) | ||
@NotFound() | ||
async createJob( | ||
@Param('game', ObjectIdPipe) game: Types.ObjectId, | ||
@Param('empire', ObjectIdPipe) empire: Types.ObjectId, | ||
@AuthUser() user: User, | ||
@Body() createJobDto: CreateJobDto, | ||
): Promise<Job> { | ||
const userEmpire = await this.empireService.findOne({game, user: user._id}); | ||
if (!userEmpire || !empire.equals(userEmpire._id)) { | ||
throw new ForbiddenException('You can only create jobs for your own empire.'); | ||
} | ||
// TODO: Create job | ||
return new Job(); | ||
} | ||
|
||
@Delete(':id') | ||
@Auth() | ||
@ApiOperation({description: 'Delete a job from your empire.'}) | ||
@ApiOkResponse({type: Job}) | ||
@NotFound('Job not found.') | ||
@ApiForbiddenResponse({description: 'You can only delete jobs from your own empire.'}) | ||
async deleteJob( | ||
@Param('game', ObjectIdPipe) game: Types.ObjectId, | ||
@Param('empire', ObjectIdPipe) empire: Types.ObjectId, | ||
@Param('id', ObjectIdPipe) id: Types.ObjectId, | ||
@AuthUser() user: User, | ||
): Promise<Job | null> { | ||
const userEmpire = await this.empireService.findOne({game, user: user._id}); | ||
if (!userEmpire || !empire.equals(userEmpire._id)) { | ||
throw new ForbiddenException('You can only delete jobs for your own empire.'); | ||
} | ||
// TODO: Delete job | ||
return null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import {PickType} from '@nestjs/swagger'; | ||
import {Job} from "./job.schema"; | ||
|
||
export class CreateJobDto extends PickType(Job, ['system', 'type', 'building', 'district', 'technology'] as const) { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import {Module} from '@nestjs/common'; | ||
import {MongooseModule} from '@nestjs/mongoose'; | ||
import {Job, JobSchema} from './job.schema'; | ||
import {JobController} from "./job.controller"; | ||
import {JobService} from "./job.service"; | ||
import {EmpireModule} from "../empire/empire.module"; | ||
|
||
@Module({ | ||
imports: [ | ||
MongooseModule.forFeature([{name: Job.name, schema: JobSchema}]), | ||
EmpireModule, | ||
], | ||
controllers: [JobController], | ||
providers: [JobService], | ||
exports: [JobService], | ||
}) | ||
export class JobModule { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import {Prop, Schema, SchemaFactory} from '@nestjs/mongoose'; | ||
import {Document, Types} from 'mongoose'; | ||
import {BUILDING_NAMES, BuildingName} from "../game-logic/buildings"; | ||
import {DISTRICT_NAMES, DistrictName} from "../game-logic/districts"; | ||
import {RESOURCES_SCHEMA_PROPERTIES, TECHNOLOGY_TAGS, TechnologyTag} from "../game-logic/types"; | ||
import {ResourceName} from "../game-logic/resources"; | ||
import {GLOBAL_SCHEMA_OPTIONS, GlobalSchema} from '../util/schema'; | ||
import {IsEnum, IsIn, IsNumber, IsOptional} from 'class-validator'; | ||
import {ApiProperty, ApiPropertyOptional} from '@nestjs/swagger'; | ||
import {OptionalRef, Ref} from "@mean-stream/nestx"; | ||
import {JobType} from "./job-type.enum"; | ||
|
||
export type JobDocument = Job & Document<Types.ObjectId>; | ||
|
||
@Schema(GLOBAL_SCHEMA_OPTIONS) | ||
export class Job extends GlobalSchema { | ||
@Prop({required: true}) | ||
@ApiProperty({description: 'Current progress of the job'}) | ||
@IsNumber() | ||
progress: number; | ||
|
||
@Prop({required: true}) | ||
@ApiProperty({description: 'Total progress steps required for the job'}) | ||
@IsNumber() | ||
total: number; | ||
|
||
@Ref('Game') | ||
game: Types.ObjectId; | ||
|
||
@Ref('Empire') | ||
empire: Types.ObjectId; | ||
|
||
@OptionalRef('System') | ||
system?: Types.ObjectId; | ||
|
||
@Prop({required: true, type: String, enum: JobType}) | ||
@ApiProperty({enum: JobType, description: 'Type of the job'}) | ||
@IsEnum(JobType) | ||
type: JobType; | ||
|
||
@Prop({type: String}) | ||
@IsOptional() | ||
@ApiPropertyOptional({required: false, description: 'Building name for the job'}) | ||
@IsIn(BUILDING_NAMES) | ||
building?: BuildingName; | ||
|
||
@Prop({type: String}) | ||
@IsOptional() | ||
@ApiPropertyOptional({required: false, description: 'District name for the job'}) | ||
@IsIn(DISTRICT_NAMES) | ||
district?: DistrictName; | ||
|
||
@Prop({type: String}) | ||
@IsOptional() | ||
@ApiPropertyOptional({required: false, description: 'Technology name for the job'}) | ||
@IsIn(TECHNOLOGY_TAGS) | ||
technology?: TechnologyTag; | ||
|
||
@Prop({type: Map, of: Number, default: {}}) | ||
@IsOptional() | ||
@ApiPropertyOptional({ | ||
description: 'Initial cost of resources for the job', | ||
...RESOURCES_SCHEMA_PROPERTIES, | ||
}) | ||
cost?: Record<ResourceName, number>; | ||
} | ||
|
||
export const JobSchema = SchemaFactory.createForClass(Job); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import {Injectable} from "@nestjs/common"; | ||
import {InjectModel} from "@nestjs/mongoose"; | ||
import {Job} from "./job.schema"; | ||
import {Model} from "mongoose"; | ||
import {EventRepository, EventService, MongooseRepository} from "@mean-stream/nestx"; | ||
|
||
@Injectable() | ||
@EventRepository() | ||
export class JobService extends MongooseRepository<Job> { | ||
constructor( | ||
@InjectModel(Job.name) private jobModel: Model<Job>, | ||
private eventEmitter: EventService, | ||
) { | ||
super(jobModel); | ||
} | ||
} |