Commit 4aae8cd0 authored by nanahira's avatar nanahira

sha256 and migrate

parent 5cef4cc5
Pipeline #4864 passed with stages
in 4 minutes
......@@ -15,8 +15,8 @@ import { AppPrefixDto } from '../dto/AppPrefix.dto';
export class AdminController {
constructor(private readonly appService: AppService) {}
@Post('migrate')
@ApiOperation({ summary: '迁移', description: '上传一个 apps.json 文件' })
@Post('migrate/apps.json')
@ApiOperation({ summary: '迁移 apps', description: '上传一个 apps.json 文件' })
@UseInterceptors(FileInterceptor('file'))
@ApiConsumes('multipart/form-data')
@ApiBody({
......@@ -24,7 +24,7 @@ export class AdminController {
type: FileUploadDto,
})
@ApiCreatedResponse({ type: BlankReturnMessageDto })
async migrate(@UploadedFile('file') file: Express.Multer.File): Promise<BlankReturnMessageDto> {
async migrateApps(@UploadedFile('file') file: Express.Multer.File): Promise<BlankReturnMessageDto> {
if (!file) {
throw new BlankReturnMessageDto(400, 'no file').toException();
}
......@@ -32,6 +32,13 @@ export class AdminController {
return this.appService.migrateFromAppsJson(apps);
}
@Post('migrate/hash')
@ApiOperation({ summary: '迁移 hash' })
@ApiCreatedResponse({ type: BlankReturnMessageDto })
async migrateHash(@UploadedFile('file') file: Express.Multer.File): Promise<BlankReturnMessageDto> {
return this.appService.migrateHashes();
}
@Put('app/:id')
@ApiOperation({ summary: '创建 app' })
@ApiOkResponse({ type: BlankReturnMessageDto })
......
......@@ -13,6 +13,8 @@ import { Build } from './entities/Build.entity';
import { ConfigService } from '@nestjs/config';
import { Archive, ArchiveType } from './entities/Archive.entity';
import { PackageS3Service } from './package-s3/package-s3.service';
import axios from 'axios';
import { createHash } from 'crypto';
@Injectable()
export class AppService extends ConsoleLogger {
......@@ -309,4 +311,33 @@ export class AppService extends ConsoleLogger {
}
return null;
}
async getHashForMigrate(fullPath: string): Promise<string> {
const url = `${this.packageS3.cdnUrl}/${fullPath}`;
this.log(`Migrating hash: ${url} `);
const { data } = await axios.get<internal.Readable>(url, { responseType: 'stream' });
//data.pipe(hashObject);
const hash = await new Promise<string>((resolve, reject) => {
const hashObject = createHash('sha256');
data.on('data', (data) => hashObject.update(data));
data.on('error', reject);
data.on('end', () => resolve(hashObject.digest('hex')));
});
this.log(`Migrated hash: ${url} => ${hash}`);
return hash;
}
async migrateHashes() {
const archivesToDo = await this.db.getRepository(Archive).find({ where: { hash: IsNull() }, select: ['id', 'hash', 'path'] });
const tmpMap = new Map<string, string>();
for (const archive of archivesToDo) {
if (tmpMap.has(archive.path)) {
archive.hash = tmpMap.get(archive.path);
} else {
archive.hash = await this.getHashForMigrate(archive.archiveFullPath);
tmpMap.set(archive.path, archive.hash);
}
}
await this.db.getRepository(Archive).save(archivesToDo);
return new BlankReturnMessageDto(200, 'success');
}
}
......@@ -21,7 +21,7 @@ export class Archive extends TimeBase {
@Column('varchar', { length: 128 })
path: string;
@Column('varchar', { length: 128, nullable: true })
@Column('varchar', { length: 64, nullable: true })
hash: string;
@Column('int', { unsigned: true })
......
......@@ -201,7 +201,7 @@ export class PackagerService extends ConsoleLogger {
reject(error);
});
});
const hashObject = createHash('sha512');
const hashObject = createHash('sha256');
child.stdout.on('data', (chunk) => {
hashObject.update(chunk);
});
......
......@@ -3,6 +3,7 @@
{{#archives}}
<file name="{{path}}.tar.zst">
<size>{{size}}</size>
<hash type="sha-256">{{hash}}</hash>
<url priority="1">{{&cdnUrl}}/{{path}}.tar.zst</url>
</file>
{{/archives}}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment