1
0
mirror of https://github.com/immich-app/immich.git synced 2024-12-26 10:50:29 +02:00

fix(server): more asset upload validation and docs (#1720)

* fix(server): more asset upload validation and docs

* remove unused DTO

* changed Object.keys() to Object.values()

* apply patch to openapi generator for web

* revert CreateAssetDto assetType enum

* resolve merge conflict

* Revert "resolve merge conflict"

This reverts commit 0e00805187.
This commit is contained in:
Michel Heusschen 2023-02-12 06:54:07 +01:00 committed by GitHub
parent 72c947cbaf
commit 05630776a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 578 additions and 28 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -16,6 +16,7 @@ import {
UploadedFiles, UploadedFiles,
Patch, Patch,
StreamableFile, StreamableFile,
ParseFilePipe,
} from '@nestjs/common'; } from '@nestjs/common';
import { Authenticated } from '../../decorators/authenticated.decorator'; import { Authenticated } from '../../decorators/authenticated.decorator';
import { AssetService } from './asset.service'; import { AssetService } from './asset.service';
@ -31,7 +32,6 @@ import { CuratedObjectsResponseDto } from './response-dto/curated-objects-respon
import { CuratedLocationsResponseDto } from './response-dto/curated-locations-response.dto'; import { CuratedLocationsResponseDto } from './response-dto/curated-locations-response.dto';
import { AssetResponseDto, ImmichReadStream } from '@app/domain'; import { AssetResponseDto, ImmichReadStream } from '@app/domain';
import { CheckDuplicateAssetResponseDto } from './response-dto/check-duplicate-asset-response.dto'; import { CheckDuplicateAssetResponseDto } from './response-dto/check-duplicate-asset-response.dto';
import { AssetFileUploadDto } from './dto/asset-file-upload.dto';
import { CreateAssetDto, mapToUploadFile } from './dto/create-asset.dto'; import { CreateAssetDto, mapToUploadFile } from './dto/create-asset.dto';
import { AssetFileUploadResponseDto } from './response-dto/asset-file-upload-response.dto'; import { AssetFileUploadResponseDto } from './response-dto/asset-file-upload-response.dto';
import { DeleteAssetResponseDto } from './response-dto/delete-asset-response.dto'; import { DeleteAssetResponseDto } from './response-dto/delete-asset-response.dto';
@ -55,6 +55,7 @@ import { SharedLinkResponseDto } from '@app/domain';
import { UpdateAssetsToSharedLinkDto } from './dto/add-assets-to-shared-link.dto'; import { UpdateAssetsToSharedLinkDto } from './dto/add-assets-to-shared-link.dto';
import { AssetSearchDto } from './dto/asset-search.dto'; import { AssetSearchDto } from './dto/asset-search.dto';
import { assetUploadOption, ImmichFile } from '../../config/asset-upload.config'; import { assetUploadOption, ImmichFile } from '../../config/asset-upload.config';
import FileNotEmptyValidator from '../validation/file-not-empty-validator';
function asStreamableFile({ stream, type, length }: ImmichReadStream) { function asStreamableFile({ stream, type, length }: ImmichReadStream) {
return new StreamableFile(stream, { type, length }); return new StreamableFile(stream, { type, length });
@ -80,12 +81,13 @@ export class AssetController {
@ApiConsumes('multipart/form-data') @ApiConsumes('multipart/form-data')
@ApiBody({ @ApiBody({
description: 'Asset Upload Information', description: 'Asset Upload Information',
type: AssetFileUploadDto, type: CreateAssetDto,
}) })
async uploadFile( async uploadFile(
@GetAuthUser() authUser: AuthUserDto, @GetAuthUser() authUser: AuthUserDto,
@UploadedFiles() files: { assetData: ImmichFile[]; livePhotoData?: ImmichFile[] }, @UploadedFiles(new ParseFilePipe({ validators: [new FileNotEmptyValidator(['assetData'])] }))
@Body(ValidationPipe) dto: CreateAssetDto, files: { assetData: ImmichFile[]; livePhotoData?: ImmichFile[] },
@Body(new ValidationPipe()) dto: CreateAssetDto,
@Response({ passthrough: true }) res: Res, @Response({ passthrough: true }) res: Res,
): Promise<AssetFileUploadResponseDto> { ): Promise<AssetFileUploadResponseDto> {
const file = mapToUploadFile(files.assetData[0]); const file = mapToUploadFile(files.assetData[0]);

View File

@ -1,8 +0,0 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty } from 'class-validator';
export class AssetFileUploadDto {
@IsNotEmpty()
@ApiProperty({ type: 'string', format: 'binary' })
assetData!: any;
}

View File

@ -1,6 +1,6 @@
import { AssetType } from '@app/infra'; import { AssetType } from '@app/infra';
import { ApiProperty } from '@nestjs/swagger'; import { ApiProperty } from '@nestjs/swagger';
import { IsBoolean, IsNotEmpty, IsOptional } from 'class-validator'; import { IsBoolean, IsEnum, IsNotEmpty, IsOptional } from 'class-validator';
import { ImmichFile } from '../../../config/asset-upload.config'; import { ImmichFile } from '../../../config/asset-upload.config';
export class CreateAssetDto { export class CreateAssetDto {
@ -11,6 +11,7 @@ export class CreateAssetDto {
deviceId!: string; deviceId!: string;
@IsNotEmpty() @IsNotEmpty()
@IsEnum(AssetType)
@ApiProperty({ enumName: 'AssetTypeEnum', enum: AssetType }) @ApiProperty({ enumName: 'AssetTypeEnum', enum: AssetType })
assetType!: AssetType; assetType!: AssetType;
@ -32,6 +33,14 @@ export class CreateAssetDto {
@IsOptional() @IsOptional()
duration?: string; duration?: string;
// The properties below are added to correctly generate the API docs
// and client SDKs. Validation should be handled in the controller.
@ApiProperty({ type: 'string', format: 'binary' })
assetData!: any;
@ApiProperty({ type: 'string', format: 'binary' })
livePhotoData?: any;
} }
export interface UploadFile { export interface UploadFile {

View File

@ -0,0 +1,25 @@
import { FileValidator, Injectable } from '@nestjs/common';
@Injectable()
export default class FileNotEmptyValidator extends FileValidator {
requiredFields: string[];
constructor(requiredFields: string[]) {
super({});
this.requiredFields = requiredFields;
}
isValid(files?: any): boolean {
if (!files) {
return false;
}
return this.requiredFields.every((field) => {
return files[field];
});
}
buildErrorMessage(): string {
return `Field(s) ${this.requiredFields.join(', ')} should not be empty`;
}
}

View File

@ -2,11 +2,11 @@
function mobile { function mobile {
rm -rf ../mobile/openapi rm -rf ../mobile/openapi
cd ./openapi-generator/templates/serialization/native cd ./openapi-generator/templates/mobile/serialization/native
wget -O native_class.mustache https://raw.githubusercontent.com/OpenAPITools/openapi-generator/master/modules/openapi-generator/src/main/resources/dart2/serialization/native/native_class.mustache wget -O native_class.mustache https://raw.githubusercontent.com/OpenAPITools/openapi-generator/master/modules/openapi-generator/src/main/resources/dart2/serialization/native/native_class.mustache
patch -u native_class.mustache <native_class.mustache.patch patch -u native_class.mustache <native_class.mustache.patch
cd ../../../.. cd ../../../../..
npx openapi-generator-cli generate -g dart -i ./immich-openapi-specs.json -o ../mobile/openapi -t ./openapi-generator/templates npx openapi-generator-cli generate -g dart -i ./immich-openapi-specs.json -o ../mobile/openapi -t ./openapi-generator/templates/mobile
# Post generate patches # Post generate patches
patch --no-backup-if-mismatch -u ../mobile/openapi/lib/api_client.dart <./openapi-generator/patch/api_client.dart.patch patch --no-backup-if-mismatch -u ../mobile/openapi/lib/api_client.dart <./openapi-generator/patch/api_client.dart.patch
@ -15,7 +15,11 @@ function mobile {
function web { function web {
rm -rf ../web/src/api/open-api rm -rf ../web/src/api/open-api
npx openapi-generator-cli generate -g typescript-axios -i ./immich-openapi-specs.json -o ../web/src/api/open-api cd ./openapi-generator/templates/web
wget -O apiInner.mustache https://raw.githubusercontent.com/OpenAPITools/openapi-generator/v6.0.1/modules/openapi-generator/src/main/resources/typescript-axios/apiInner.mustache
patch -u apiInner.mustache < apiInner.mustache.patch
cd ../../..
npx openapi-generator-cli generate -g typescript-axios -i ./immich-openapi-specs.json -o ../web/src/api/open-api -t ./openapi-generator/templates/web
} }
if [[ $1 == 'mobile' ]]; then if [[ $1 == 'mobile' ]]; then

View File

@ -1077,7 +1077,7 @@
"content": { "content": {
"multipart/form-data": { "multipart/form-data": {
"schema": { "schema": {
"$ref": "#/components/schemas/AssetFileUploadDto" "$ref": "#/components/schemas/CreateAssetDto"
} }
} }
} }
@ -3758,16 +3758,54 @@
"profileImagePath" "profileImagePath"
] ]
}, },
"AssetFileUploadDto": { "CreateAssetDto": {
"type": "object", "type": "object",
"properties": { "properties": {
"assetType": {
"$ref": "#/components/schemas/AssetTypeEnum"
},
"assetData": { "assetData": {
"type": "string", "type": "string",
"format": "binary" "format": "binary"
},
"livePhotoData": {
"type": "string",
"format": "binary"
},
"deviceAssetId": {
"type": "string"
},
"deviceId": {
"type": "string"
},
"createdAt": {
"type": "string"
},
"modifiedAt": {
"type": "string"
},
"isFavorite": {
"type": "boolean"
},
"isVisible": {
"type": "boolean"
},
"fileExtension": {
"type": "string"
},
"duration": {
"type": "string"
} }
}, },
"required": [ "required": [
"assetData" "assetType",
"assetData",
"deviceAssetId",
"deviceId",
"createdAt",
"modifiedAt",
"isFavorite",
"fileExtension"
] ]
}, },
"AssetFileUploadResponseDto": { "AssetFileUploadResponseDto": {

View File

@ -0,0 +1,372 @@
{{#withSeparateModelsAndApi}}
/* tslint:disable */
/* eslint-disable */
{{>licenseInfo}}
import globalAxios, { AxiosPromise, AxiosInstance, AxiosRequestConfig } from 'axios';
import { Configuration } from '{{apiRelativeToRoot}}configuration';
{{#withNodeImports}}
// URLSearchParams not necessarily used
// @ts-ignore
import { URL, URLSearchParams } from 'url';
{{#multipartFormData}}
import FormData from 'form-data'
{{/multipartFormData}}
{{/withNodeImports}}
// Some imports not used depending on template conditions
// @ts-ignore
import { DUMMY_BASE_URL, assertParamExists, setApiKeyToObject, setBasicAuthToObject, setBearerAuthToObject, setOAuthToObject, setSearchParams, serializeDataIfNeeded, toPathString, createRequestFunction } from '{{apiRelativeToRoot}}common';
// @ts-ignore
import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from '{{apiRelativeToRoot}}base';
{{#imports}}
// @ts-ignore
import { {{classname}} } from '{{apiRelativeToRoot}}{{tsModelPackage}}';
{{/imports}}
{{/withSeparateModelsAndApi}}
{{^withSeparateModelsAndApi}}
{{/withSeparateModelsAndApi}}
{{#operations}}
/**
* {{classname}} - axios parameter creator{{#description}}
* {{&description}}{{/description}}
* @export
*/
export const {{classname}}AxiosParamCreator = function (configuration?: Configuration) {
return {
{{#operation}}
/**
* {{&notes}}
{{#summary}}
* @summary {{&summary}}
{{/summary}}
{{#allParams}}
* @param {{=<% %>=}}{<%&dataType%>}<%={{ }}=%> {{^required}}[{{/required}}{{paramName}}{{^required}}]{{/required}} {{description}}
{{/allParams}}
* @param {*} [options] Override http request option.{{#isDeprecated}}
* @deprecated{{/isDeprecated}}
* @throws {RequiredError}
*/
{{nickname}}: async ({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/allParams}}options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
{{#allParams}}
{{#required}}
// verify required parameter '{{paramName}}' is not null or undefined
assertParamExists('{{nickname}}', '{{paramName}}', {{paramName}})
{{/required}}
{{/allParams}}
const localVarPath = `{{{path}}}`{{#pathParams}}
.replace(`{${"{{baseName}}"}}`, encodeURIComponent(String({{paramName}}))){{/pathParams}};
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions = { method: '{{httpMethod}}', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;{{#vendorExtensions}}{{#hasFormParams}}
const localVarFormParams = new {{^multipartFormData}}URLSearchParams(){{/multipartFormData}}{{#multipartFormData}}((configuration && configuration.formDataCtor) || FormData)(){{/multipartFormData}};{{/hasFormParams}}{{/vendorExtensions}}
{{#authMethods}}
// authentication {{name}} required
{{#isApiKey}}
{{#isKeyInHeader}}
await setApiKeyToObject(localVarHeaderParameter, "{{keyParamName}}", configuration)
{{/isKeyInHeader}}
{{#isKeyInQuery}}
await setApiKeyToObject(localVarQueryParameter, "{{keyParamName}}", configuration)
{{/isKeyInQuery}}
{{/isApiKey}}
{{#isBasicBasic}}
// http basic authentication required
setBasicAuthToObject(localVarRequestOptions, configuration)
{{/isBasicBasic}}
{{#isBasicBearer}}
// http bearer authentication required
await setBearerAuthToObject(localVarHeaderParameter, configuration)
{{/isBasicBearer}}
{{#isOAuth}}
// oauth required
await setOAuthToObject(localVarHeaderParameter, "{{name}}", [{{#scopes}}"{{{scope}}}"{{^-last}}, {{/-last}}{{/scopes}}], configuration)
{{/isOAuth}}
{{/authMethods}}
{{#queryParams}}
{{#isArray}}
if ({{paramName}}) {
{{#isCollectionFormatMulti}}
{{#uniqueItems}}
localVarQueryParameter['{{baseName}}'] = Array.from({{paramName}});
{{/uniqueItems}}
{{^uniqueItems}}
localVarQueryParameter['{{baseName}}'] = {{paramName}};
{{/uniqueItems}}
{{/isCollectionFormatMulti}}
{{^isCollectionFormatMulti}}
{{#uniqueItems}}
localVarQueryParameter['{{baseName}}'] = Array.from({{paramName}}).join(COLLECTION_FORMATS.{{collectionFormat}});
{{/uniqueItems}}
{{^uniqueItems}}
localVarQueryParameter['{{baseName}}'] = {{paramName}}.join(COLLECTION_FORMATS.{{collectionFormat}});
{{/uniqueItems}}
{{/isCollectionFormatMulti}}
}
{{/isArray}}
{{^isArray}}
if ({{paramName}} !== undefined) {
{{#isDateTime}}
localVarQueryParameter['{{baseName}}'] = ({{paramName}} as any instanceof Date) ?
({{paramName}} as any).toISOString() :
{{paramName}};
{{/isDateTime}}
{{^isDateTime}}
{{#isDate}}
localVarQueryParameter['{{baseName}}'] = ({{paramName}} as any instanceof Date) ?
({{paramName}} as any).toISOString().substr(0,10) :
{{paramName}};
{{/isDate}}
{{^isDate}}
localVarQueryParameter['{{baseName}}'] = {{paramName}};
{{/isDate}}
{{/isDateTime}}
}
{{/isArray}}
{{/queryParams}}
{{#headerParams}}
{{#isArray}}
if ({{paramName}}) {
{{#uniqueItems}}
let mapped = Array.from({{paramName}}).map(value => (<any>"{{{dataType}}}" !== "Set<string>") ? JSON.stringify(value) : (value || ""));
{{/uniqueItems}}
{{^uniqueItems}}
let mapped = {{paramName}}.map(value => (<any>"{{{dataType}}}" !== "Array<string>") ? JSON.stringify(value) : (value || ""));
{{/uniqueItems}}
localVarHeaderParameter['{{baseName}}'] = mapped.join(COLLECTION_FORMATS["{{collectionFormat}}"]);
}
{{/isArray}}
{{^isArray}}
if ({{paramName}} !== undefined && {{paramName}} !== null) {
{{#isString}}
localVarHeaderParameter['{{baseName}}'] = String({{paramName}});
{{/isString}}
{{^isString}}
localVarHeaderParameter['{{baseName}}'] = String(JSON.stringify({{paramName}}));
{{/isString}}
}
{{/isArray}}
{{/headerParams}}
{{#vendorExtensions}}
{{#formParams}}
{{#isArray}}
if ({{paramName}}) {
{{#isCollectionFormatMulti}}
{{paramName}}.forEach((element) => {
localVarFormParams.{{#multipartFormData}}append{{/multipartFormData}}{{^multipartFormData}}set{{/multipartFormData}}('{{baseName}}', element as any);
})
{{/isCollectionFormatMulti}}
{{^isCollectionFormatMulti}}
localVarFormParams.{{#multipartFormData}}append{{/multipartFormData}}{{^multipartFormData}}set{{/multipartFormData}}('{{baseName}}', {{paramName}}.join(COLLECTION_FORMATS.{{collectionFormat}}));
{{/isCollectionFormatMulti}}
}{{/isArray}}
{{^isArray}}
if ({{paramName}} !== undefined) { {{^multipartFormData}}
localVarFormParams.set('{{baseName}}', {{paramName}} as any);{{/multipartFormData}}{{#multipartFormData}}{{#isPrimitiveType}}
localVarFormParams.append('{{baseName}}', {{paramName}} as any);{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isEnum}}
localVarFormParams.append('{{baseName}}', {{paramName}} as any);{{/isEnum}}{{^isEnum}}
localVarFormParams.append('{{baseName}}', new Blob([JSON.stringify({{paramName}})], { type: "application/json", }));{{/isEnum}}{{/isPrimitiveType}}{{/multipartFormData}}
}{{/isArray}}
{{/formParams}}{{/vendorExtensions}}
{{#vendorExtensions}}{{#hasFormParams}}{{^multipartFormData}}
localVarHeaderParameter['Content-Type'] = 'application/x-www-form-urlencoded';{{/multipartFormData}}{{#multipartFormData}}
localVarHeaderParameter['Content-Type'] = 'multipart/form-data';{{/multipartFormData}}
{{/hasFormParams}}{{/vendorExtensions}}
{{#bodyParam}}
{{^consumes}}
localVarHeaderParameter['Content-Type'] = 'application/json';
{{/consumes}}
{{#consumes.0}}
localVarHeaderParameter['Content-Type'] = '{{{mediaType}}}';
{{/consumes.0}}
{{/bodyParam}}
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions,{{#hasFormParams}}{{#multipartFormData}} ...(localVarFormParams as any).getHeaders?.(),{{/multipartFormData}}{{/hasFormParams}} ...options.headers};
{{#hasFormParams}}
localVarRequestOptions.data = localVarFormParams{{#vendorExtensions}}{{^multipartFormData}}.toString(){{/multipartFormData}}{{/vendorExtensions}};
{{/hasFormParams}}
{{#bodyParam}}
localVarRequestOptions.data = serializeDataIfNeeded({{paramName}}, localVarRequestOptions, configuration)
{{/bodyParam}}
return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
{{/operation}}
}
};
/**
* {{classname}} - functional programming interface{{#description}}
* {{{.}}}{{/description}}
* @export
*/
export const {{classname}}Fp = function(configuration?: Configuration) {
const localVarAxiosParamCreator = {{classname}}AxiosParamCreator(configuration)
return {
{{#operation}}
/**
* {{&notes}}
{{#summary}}
* @summary {{&summary}}
{{/summary}}
{{#allParams}}
* @param {{=<% %>=}}{<%&dataType%>}<%={{ }}=%> {{^required}}[{{/required}}{{paramName}}{{^required}}]{{/required}} {{description}}
{{/allParams}}
* @param {*} [options] Override http request option.{{#isDeprecated}}
* @deprecated{{/isDeprecated}}
* @throws {RequiredError}
*/
async {{nickname}}({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/allParams}}options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<{{{returnType}}}{{^returnType}}void{{/returnType}}>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.{{nickname}}({{#allParams}}{{paramName}}, {{/allParams}}options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
{{/operation}}
}
};
/**
* {{classname}} - factory interface{{#description}}
* {{&description}}{{/description}}
* @export
*/
export const {{classname}}Factory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) {
const localVarFp = {{classname}}Fp(configuration)
return {
{{#operation}}
/**
* {{&notes}}
{{#summary}}
* @summary {{&summary}}
{{/summary}}
{{#allParams}}
* @param {{=<% %>=}}{<%&dataType%>}<%={{ }}=%> {{^required}}[{{/required}}{{paramName}}{{^required}}]{{/required}} {{description}}
{{/allParams}}
* @param {*} [options] Override http request option.{{#isDeprecated}}
* @deprecated{{/isDeprecated}}
* @throws {RequiredError}
*/
{{nickname}}({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/allParams}}options?: any): AxiosPromise<{{{returnType}}}{{^returnType}}void{{/returnType}}> {
return localVarFp.{{nickname}}({{#allParams}}{{paramName}}, {{/allParams}}options).then((request) => request(axios, basePath));
},
{{/operation}}
};
};
{{#withInterfaces}}
/**
* {{classname}} - interface{{#description}}
* {{&description}}{{/description}}
* @export
* @interface {{classname}}
*/
export interface {{classname}}Interface {
{{#operation}}
/**
* {{&notes}}
{{#summary}}
* @summary {{&summary}}
{{/summary}}
{{#allParams}}
* @param {{=<% %>=}}{<%&dataType%>}<%={{ }}=%> {{^required}}[{{/required}}{{paramName}}{{^required}}]{{/required}} {{description}}
{{/allParams}}
* @param {*} [options] Override http request option.{{#isDeprecated}}
* @deprecated{{/isDeprecated}}
* @throws {RequiredError}
* @memberof {{classname}}Interface
*/
{{nickname}}({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/allParams}}options?: AxiosRequestConfig): AxiosPromise<{{{returnType}}}{{^returnType}}void{{/returnType}}>;
{{/operation}}
}
{{/withInterfaces}}
{{#useSingleRequestParameter}}
{{#operation}}
{{#allParams.0}}
/**
* Request parameters for {{nickname}} operation in {{classname}}.
* @export
* @interface {{classname}}{{operationIdCamelCase}}Request
*/
export interface {{classname}}{{operationIdCamelCase}}Request {
{{#allParams}}
/**
* {{description}}
* @type {{=<% %>=}}{<%&dataType%>}<%={{ }}=%>
* @memberof {{classname}}{{operationIdCamelCase}}
*/
readonly {{paramName}}{{^required}}?{{/required}}: {{{dataType}}}
{{^-last}}
{{/-last}}
{{/allParams}}
}
{{/allParams.0}}
{{/operation}}
{{/useSingleRequestParameter}}
/**
* {{classname}} - object-oriented interface{{#description}}
* {{{.}}}{{/description}}
* @export
* @class {{classname}}
* @extends {BaseAPI}
*/
{{#withInterfaces}}
export class {{classname}} extends BaseAPI implements {{classname}}Interface {
{{/withInterfaces}}
{{^withInterfaces}}
export class {{classname}} extends BaseAPI {
{{/withInterfaces}}
{{#operation}}
/**
* {{&notes}}
{{#summary}}
* @summary {{&summary}}
{{/summary}}
{{#useSingleRequestParameter}}
{{#allParams.0}}
* @param {{=<% %>=}}{<%& classname %><%& operationIdCamelCase %>Request}<%={{ }}=%> requestParameters Request parameters.
{{/allParams.0}}
{{/useSingleRequestParameter}}
{{^useSingleRequestParameter}}
{{#allParams}}
* @param {{=<% %>=}}{<%&dataType%>}<%={{ }}=%> {{^required}}[{{/required}}{{paramName}}{{^required}}]{{/required}} {{description}}
{{/allParams}}
{{/useSingleRequestParameter}}
* @param {*} [options] Override http request option.{{#isDeprecated}}
* @deprecated{{/isDeprecated}}
* @throws {RequiredError}
* @memberof {{classname}}
*/
{{#useSingleRequestParameter}}
public {{nickname}}({{#allParams.0}}requestParameters: {{classname}}{{operationIdCamelCase}}Request{{^hasRequiredParams}} = {}{{/hasRequiredParams}}, {{/allParams.0}}options?: AxiosRequestConfig) {
return {{classname}}Fp(this.configuration).{{nickname}}({{#allParams.0}}{{#allParams}}requestParameters.{{paramName}}, {{/allParams}}{{/allParams.0}}options).then((request) => request(this.axios, this.basePath));
}
{{/useSingleRequestParameter}}
{{^useSingleRequestParameter}}
public {{nickname}}({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/allParams}}options?: AxiosRequestConfig) {
return {{classname}}Fp(this.configuration).{{nickname}}({{#allParams}}{{paramName}}, {{/allParams}}options).then((request) => request(this.axios, this.basePath));
}
{{/useSingleRequestParameter}}
{{^-last}}
{{/-last}}
{{/operation}}
}
{{/operations}}

View File

@ -0,0 +1,14 @@
--- apiInner.mustache 2023-02-10 17:44:20.945845049 +0000
+++ apiInner.mustache.patch 2023-02-10 17:46:28.669054112 +0000
@@ -173,8 +173,9 @@
{{^isArray}}
if ({{paramName}} !== undefined) { {{^multipartFormData}}
localVarFormParams.set('{{baseName}}', {{paramName}} as any);{{/multipartFormData}}{{#multipartFormData}}{{#isPrimitiveType}}
- localVarFormParams.append('{{baseName}}', {{paramName}} as any);{{/isPrimitiveType}}{{^isPrimitiveType}}
- localVarFormParams.append('{{baseName}}', new Blob([JSON.stringify({{paramName}})], { type: "application/json", }));{{/isPrimitiveType}}{{/multipartFormData}}
+ localVarFormParams.append('{{baseName}}', {{paramName}} as any);{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isEnum}}
+ localVarFormParams.append('{{baseName}}', {{paramName}} as any);{{/isEnum}}{{^isEnum}}
+ localVarFormParams.append('{{baseName}}', new Blob([JSON.stringify({{paramName}})], { type: "application/json", }));{{/isEnum}}{{/isPrimitiveType}}{{/multipartFormData}}
}{{/isArray}}
{{/formParams}}{{/vendorExtensions}}
{{#vendorExtensions}}{{#hasFormParams}}{{^multipartFormData}}

View File

@ -4402,13 +4402,37 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration
}, },
/** /**
* *
* @param {AssetTypeEnum} assetType
* @param {any} assetData * @param {any} assetData
* @param {string} deviceAssetId
* @param {string} deviceId
* @param {string} createdAt
* @param {string} modifiedAt
* @param {boolean} isFavorite
* @param {string} fileExtension
* @param {any} [livePhotoData]
* @param {boolean} [isVisible]
* @param {string} [duration]
* @param {*} [options] Override http request option. * @param {*} [options] Override http request option.
* @throws {RequiredError} * @throws {RequiredError}
*/ */
uploadFile: async (assetData: any, options: AxiosRequestConfig = {}): Promise<RequestArgs> => { uploadFile: async (assetType: AssetTypeEnum, assetData: any, deviceAssetId: string, deviceId: string, createdAt: string, modifiedAt: string, isFavorite: boolean, fileExtension: string, livePhotoData?: any, isVisible?: boolean, duration?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'assetType' is not null or undefined
assertParamExists('uploadFile', 'assetType', assetType)
// verify required parameter 'assetData' is not null or undefined // verify required parameter 'assetData' is not null or undefined
assertParamExists('uploadFile', 'assetData', assetData) assertParamExists('uploadFile', 'assetData', assetData)
// verify required parameter 'deviceAssetId' is not null or undefined
assertParamExists('uploadFile', 'deviceAssetId', deviceAssetId)
// verify required parameter 'deviceId' is not null or undefined
assertParamExists('uploadFile', 'deviceId', deviceId)
// verify required parameter 'createdAt' is not null or undefined
assertParamExists('uploadFile', 'createdAt', createdAt)
// verify required parameter 'modifiedAt' is not null or undefined
assertParamExists('uploadFile', 'modifiedAt', modifiedAt)
// verify required parameter 'isFavorite' is not null or undefined
assertParamExists('uploadFile', 'isFavorite', isFavorite)
// verify required parameter 'fileExtension' is not null or undefined
assertParamExists('uploadFile', 'fileExtension', fileExtension)
const localVarPath = `/asset/upload`; const localVarPath = `/asset/upload`;
// use dummy base URL string because the URL constructor only accepts absolute URLs. // use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@ -4427,10 +4451,50 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration
await setBearerAuthToObject(localVarHeaderParameter, configuration) await setBearerAuthToObject(localVarHeaderParameter, configuration)
if (assetType !== undefined) {
localVarFormParams.append('assetType', new Blob([JSON.stringify(assetType)], { type: "application/json", }));
}
if (assetData !== undefined) { if (assetData !== undefined) {
localVarFormParams.append('assetData', assetData as any); localVarFormParams.append('assetData', assetData as any);
} }
if (livePhotoData !== undefined) {
localVarFormParams.append('livePhotoData', livePhotoData as any);
}
if (deviceAssetId !== undefined) {
localVarFormParams.append('deviceAssetId', deviceAssetId as any);
}
if (deviceId !== undefined) {
localVarFormParams.append('deviceId', deviceId as any);
}
if (createdAt !== undefined) {
localVarFormParams.append('createdAt', createdAt as any);
}
if (modifiedAt !== undefined) {
localVarFormParams.append('modifiedAt', modifiedAt as any);
}
if (isFavorite !== undefined) {
localVarFormParams.append('isFavorite', isFavorite as any);
}
if (isVisible !== undefined) {
localVarFormParams.append('isVisible', isVisible as any);
}
if (fileExtension !== undefined) {
localVarFormParams.append('fileExtension', fileExtension as any);
}
if (duration !== undefined) {
localVarFormParams.append('duration', duration as any);
}
localVarHeaderParameter['Content-Type'] = 'multipart/form-data'; localVarHeaderParameter['Content-Type'] = 'multipart/form-data';
@ -4668,12 +4732,22 @@ export const AssetApiFp = function(configuration?: Configuration) {
}, },
/** /**
* *
* @param {AssetTypeEnum} assetType
* @param {any} assetData * @param {any} assetData
* @param {string} deviceAssetId
* @param {string} deviceId
* @param {string} createdAt
* @param {string} modifiedAt
* @param {boolean} isFavorite
* @param {string} fileExtension
* @param {any} [livePhotoData]
* @param {boolean} [isVisible]
* @param {string} [duration]
* @param {*} [options] Override http request option. * @param {*} [options] Override http request option.
* @throws {RequiredError} * @throws {RequiredError}
*/ */
async uploadFile(assetData: any, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<AssetFileUploadResponseDto>> { async uploadFile(assetType: AssetTypeEnum, assetData: any, deviceAssetId: string, deviceId: string, createdAt: string, modifiedAt: string, isFavorite: boolean, fileExtension: string, livePhotoData?: any, isVisible?: boolean, duration?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<AssetFileUploadResponseDto>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.uploadFile(assetData, options); const localVarAxiosArgs = await localVarAxiosParamCreator.uploadFile(assetType, assetData, deviceAssetId, deviceId, createdAt, modifiedAt, isFavorite, fileExtension, livePhotoData, isVisible, duration, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
}, },
} }
@ -4879,12 +4953,22 @@ export const AssetApiFactory = function (configuration?: Configuration, basePath
}, },
/** /**
* *
* @param {AssetTypeEnum} assetType
* @param {any} assetData * @param {any} assetData
* @param {string} deviceAssetId
* @param {string} deviceId
* @param {string} createdAt
* @param {string} modifiedAt
* @param {boolean} isFavorite
* @param {string} fileExtension
* @param {any} [livePhotoData]
* @param {boolean} [isVisible]
* @param {string} [duration]
* @param {*} [options] Override http request option. * @param {*} [options] Override http request option.
* @throws {RequiredError} * @throws {RequiredError}
*/ */
uploadFile(assetData: any, options?: any): AxiosPromise<AssetFileUploadResponseDto> { uploadFile(assetType: AssetTypeEnum, assetData: any, deviceAssetId: string, deviceId: string, createdAt: string, modifiedAt: string, isFavorite: boolean, fileExtension: string, livePhotoData?: any, isVisible?: boolean, duration?: string, options?: any): AxiosPromise<AssetFileUploadResponseDto> {
return localVarFp.uploadFile(assetData, options).then((request) => request(axios, basePath)); return localVarFp.uploadFile(assetType, assetData, deviceAssetId, deviceId, createdAt, modifiedAt, isFavorite, fileExtension, livePhotoData, isVisible, duration, options).then((request) => request(axios, basePath));
}, },
}; };
}; };
@ -5131,13 +5215,23 @@ export class AssetApi extends BaseAPI {
/** /**
* *
* @param {AssetTypeEnum} assetType
* @param {any} assetData * @param {any} assetData
* @param {string} deviceAssetId
* @param {string} deviceId
* @param {string} createdAt
* @param {string} modifiedAt
* @param {boolean} isFavorite
* @param {string} fileExtension
* @param {any} [livePhotoData]
* @param {boolean} [isVisible]
* @param {string} [duration]
* @param {*} [options] Override http request option. * @param {*} [options] Override http request option.
* @throws {RequiredError} * @throws {RequiredError}
* @memberof AssetApi * @memberof AssetApi
*/ */
public uploadFile(assetData: any, options?: AxiosRequestConfig) { public uploadFile(assetType: AssetTypeEnum, assetData: any, deviceAssetId: string, deviceId: string, createdAt: string, modifiedAt: string, isFavorite: boolean, fileExtension: string, livePhotoData?: any, isVisible?: boolean, duration?: string, options?: AxiosRequestConfig) {
return AssetApiFp(this.configuration).uploadFile(assetData, options).then((request) => request(this.axios, this.basePath)); return AssetApiFp(this.configuration).uploadFile(assetType, assetData, deviceAssetId, deviceId, createdAt, modifiedAt, isFavorite, fileExtension, livePhotoData, isVisible, duration, options).then((request) => request(this.axios, this.basePath));
} }
} }