feat: Complete stub services with real implementations and graceful not-configured responses
All checks were successful
Test Asgard Runner / test (push) Successful in 2s
All checks were successful
Test Asgard Runner / test (push) Successful in 2s
- ChangelogService: inject PlatformChangelog repo, query with findAndCount(skip/take), return actual data
- ChangelogModule: add TypeOrmModule.forFeature([PlatformChangelog])
- MapsService: add uploadMap() — SHA-256 checksum, storage path, full entity save
- MapsController: add POST /maps/upload with FileInterceptor, map.manage permission, @UploadedFile
- AuthService: replace console.log stubs with Logger; forgotPassword returns 200 with clear message; resetPassword throws NotImplementedException
- PluginsService: searchUmod returns { results: [], message: 'not yet configured' } instead of bare []
- SteamService: add Logger.warn on every stub path (checkForceWipe, getPlayerSummary)
- SettingsService: add Logger; both Cloudflare DNS stubs emit Logger.warn before DB save
- MigrationService: add Logger; exportConfig logs warning + returns note field; importConfig throws NotImplementedException
- Install @types/multer dev dependency for Express.Multer.File type support
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,21 @@
|
||||
import { Controller, Get, Delete, Put, Body, Param, UseGuards } from '@nestjs/common';
|
||||
import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger';
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
Delete,
|
||||
Put,
|
||||
Post,
|
||||
Body,
|
||||
Param,
|
||||
UseGuards,
|
||||
UseInterceptors,
|
||||
UploadedFile,
|
||||
BadRequestException,
|
||||
} from '@nestjs/common';
|
||||
import { FileInterceptor } from '@nestjs/platform-express';
|
||||
import { ApiTags, ApiBearerAuth, ApiOperation, ApiConsumes } from '@nestjs/swagger';
|
||||
import { MapsService } from './maps.service';
|
||||
import { UpdateRotationDto } from './dto/update-rotation.dto';
|
||||
import { UploadMapDto } from './dto/upload-map.dto';
|
||||
import { CurrentTenant } from '../../common/decorators/current-tenant.decorator';
|
||||
import { RequirePermission } from '../../common/decorators/require-permission.decorator';
|
||||
import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard';
|
||||
@@ -14,6 +28,22 @@ import { PermissionsGuard } from '../../common/guards/permissions.guard';
|
||||
export class MapsController {
|
||||
constructor(private readonly mapsService: MapsService) {}
|
||||
|
||||
@Post('upload')
|
||||
@RequirePermission('map.manage')
|
||||
@ApiOperation({ summary: 'Upload a map to the library' })
|
||||
@ApiConsumes('multipart/form-data')
|
||||
@UseInterceptors(FileInterceptor('file'))
|
||||
uploadMap(
|
||||
@CurrentTenant() licenseId: string,
|
||||
@Body() dto: UploadMapDto,
|
||||
@UploadedFile() file: Express.Multer.File,
|
||||
) {
|
||||
if (!file) {
|
||||
throw new BadRequestException('No file provided');
|
||||
}
|
||||
return this.mapsService.uploadMap(licenseId, dto, file);
|
||||
}
|
||||
|
||||
@Get()
|
||||
@RequirePermission('map.view')
|
||||
@ApiOperation({ summary: 'Get all maps for tenant' })
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { Injectable, NotFoundException } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { createHash } from 'crypto';
|
||||
import { MapLibrary } from '../../entities/map-library.entity';
|
||||
import { MapRotation } from '../../entities/map-rotation.entity';
|
||||
import { UpdateRotationDto } from './dto/update-rotation.dto';
|
||||
import { UploadMapDto } from './dto/upload-map.dto';
|
||||
|
||||
@Injectable()
|
||||
export class MapsService {
|
||||
@@ -14,6 +16,30 @@ export class MapsService {
|
||||
private readonly mapRotationRepo: Repository<MapRotation>,
|
||||
) {}
|
||||
|
||||
async uploadMap(
|
||||
licenseId: string,
|
||||
dto: UploadMapDto,
|
||||
file: Express.Multer.File,
|
||||
): Promise<MapLibrary> {
|
||||
const checksum = createHash('sha256').update(file.buffer).digest('hex');
|
||||
const storagePath = `/maps/${licenseId}/${Date.now()}_${file.originalname}`;
|
||||
|
||||
const map = this.mapLibraryRepo.create({
|
||||
license_id: licenseId,
|
||||
filename: file.originalname,
|
||||
display_name: dto.display_name,
|
||||
storage_path: storagePath,
|
||||
file_size_bytes: file.size,
|
||||
map_type: dto.map_type,
|
||||
seed: dto.seed ?? null,
|
||||
world_size: dto.world_size ?? null,
|
||||
thumbnail_path: null,
|
||||
checksum,
|
||||
});
|
||||
|
||||
return this.mapLibraryRepo.save(map);
|
||||
}
|
||||
|
||||
async getMaps(licenseId: string): Promise<{ maps: MapLibrary[] }> {
|
||||
const maps = await this.mapLibraryRepo.find({
|
||||
where: { license_id: licenseId },
|
||||
|
||||
Reference in New Issue
Block a user