mirror of
				https://github.com/KevinMidboe/immich.git
				synced 2025-10-29 17:40:28 +00:00 
			
		
		
		
	feat(server): asset entity audit (#3824)
* feat(server): audit log * feedback * Insert to database * migration * test * controller/repository/service * test * module * feat(server): implement audit endpoint * directly return changed assets * add daily cleanup of audit table * fix tests * review feedback * ci * refactor(server): audit implementation * chore: open api --------- Co-authored-by: Alex Tran <alex.tran1502@gmail.com> Co-authored-by: Fynn Petersen-Frey <zoodyy@users.noreply.github.com> Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
This commit is contained in:
		
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							d6887117ac
						
					
				
				
					commit
					cf9e04c8ec
				
			
							
								
								
									
										215
									
								
								web/src/api/open-api/api.ts
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										215
									
								
								web/src/api/open-api/api.ts
									
									
									
										generated
									
									
									
								
							| @@ -752,6 +752,25 @@ export const AudioCodec = { | ||||
| export type AudioCodec = typeof AudioCodec[keyof typeof AudioCodec]; | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
|  *  | ||||
|  * @export | ||||
|  * @interface AuditDeletesResponseDto | ||||
|  */ | ||||
| export interface AuditDeletesResponseDto { | ||||
|     /** | ||||
|      *  | ||||
|      * @type {Array<string>} | ||||
|      * @memberof AuditDeletesResponseDto | ||||
|      */ | ||||
|     'ids': Array<string>; | ||||
|     /** | ||||
|      *  | ||||
|      * @type {boolean} | ||||
|      * @memberof AuditDeletesResponseDto | ||||
|      */ | ||||
|     'needsFullSync': boolean; | ||||
| } | ||||
| /** | ||||
|  *  | ||||
|  * @export | ||||
| @@ -1243,6 +1262,20 @@ export interface DownloadResponseDto { | ||||
|      */ | ||||
|     'totalSize': number; | ||||
| } | ||||
| /** | ||||
|  *  | ||||
|  * @export | ||||
|  * @enum {string} | ||||
|  */ | ||||
| 
 | ||||
| export const EntityType = { | ||||
|     Asset: 'ASSET', | ||||
|     Album: 'ALBUM' | ||||
| } as const; | ||||
| 
 | ||||
| export type EntityType = typeof EntityType[keyof typeof EntityType]; | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
|  *  | ||||
|  * @export | ||||
| @@ -5120,11 +5153,12 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration | ||||
|          * @param {boolean} [isArchived]  | ||||
|          * @param {boolean} [withoutThumbs] Include assets without thumbnails | ||||
|          * @param {number} [skip]  | ||||
|          * @param {string} [updatedAfter]  | ||||
|          * @param {string} [ifNoneMatch] ETag of data already cached on the client | ||||
|          * @param {*} [options] Override http request option. | ||||
|          * @throws {RequiredError} | ||||
|          */ | ||||
|         getAllAssets: async (userId?: string, isFavorite?: boolean, isArchived?: boolean, withoutThumbs?: boolean, skip?: number, ifNoneMatch?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => { | ||||
|         getAllAssets: async (userId?: string, isFavorite?: boolean, isArchived?: boolean, withoutThumbs?: boolean, skip?: number, updatedAfter?: string, ifNoneMatch?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => { | ||||
|             const localVarPath = `/asset`; | ||||
|             // use dummy base URL string because the URL constructor only accepts absolute URLs.
 | ||||
|             const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); | ||||
| @@ -5166,6 +5200,12 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration | ||||
|                 localVarQueryParameter['skip'] = skip; | ||||
|             } | ||||
| 
 | ||||
|             if (updatedAfter !== undefined) { | ||||
|                 localVarQueryParameter['updatedAfter'] = (updatedAfter as any instanceof Date) ? | ||||
|                     (updatedAfter as any).toISOString() : | ||||
|                     updatedAfter; | ||||
|             } | ||||
| 
 | ||||
|             if (ifNoneMatch != null) { | ||||
|                 localVarHeaderParameter['if-none-match'] = String(ifNoneMatch); | ||||
|             } | ||||
| @@ -6274,12 +6314,13 @@ export const AssetApiFp = function(configuration?: Configuration) { | ||||
|          * @param {boolean} [isArchived]  | ||||
|          * @param {boolean} [withoutThumbs] Include assets without thumbnails | ||||
|          * @param {number} [skip]  | ||||
|          * @param {string} [updatedAfter]  | ||||
|          * @param {string} [ifNoneMatch] ETag of data already cached on the client | ||||
|          * @param {*} [options] Override http request option. | ||||
|          * @throws {RequiredError} | ||||
|          */ | ||||
|         async getAllAssets(userId?: string, isFavorite?: boolean, isArchived?: boolean, withoutThumbs?: boolean, skip?: number, ifNoneMatch?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<AssetResponseDto>>> { | ||||
|             const localVarAxiosArgs = await localVarAxiosParamCreator.getAllAssets(userId, isFavorite, isArchived, withoutThumbs, skip, ifNoneMatch, options); | ||||
|         async getAllAssets(userId?: string, isFavorite?: boolean, isArchived?: boolean, withoutThumbs?: boolean, skip?: number, updatedAfter?: string, ifNoneMatch?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<AssetResponseDto>>> { | ||||
|             const localVarAxiosArgs = await localVarAxiosParamCreator.getAllAssets(userId, isFavorite, isArchived, withoutThumbs, skip, updatedAfter, ifNoneMatch, options); | ||||
|             return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); | ||||
|         }, | ||||
|         /** | ||||
| @@ -6576,7 +6617,7 @@ export const AssetApiFactory = function (configuration?: Configuration, basePath | ||||
|          * @throws {RequiredError} | ||||
|          */ | ||||
|         getAllAssets(requestParameters: AssetApiGetAllAssetsRequest = {}, options?: AxiosRequestConfig): AxiosPromise<Array<AssetResponseDto>> { | ||||
|             return localVarFp.getAllAssets(requestParameters.userId, requestParameters.isFavorite, requestParameters.isArchived, requestParameters.withoutThumbs, requestParameters.skip, requestParameters.ifNoneMatch, options).then((request) => request(axios, basePath)); | ||||
|             return localVarFp.getAllAssets(requestParameters.userId, requestParameters.isFavorite, requestParameters.isArchived, requestParameters.withoutThumbs, requestParameters.skip, requestParameters.updatedAfter, requestParameters.ifNoneMatch, options).then((request) => request(axios, basePath)); | ||||
|         }, | ||||
|         /** | ||||
|          * Get a single asset\'s information | ||||
| @@ -6895,6 +6936,13 @@ export interface AssetApiGetAllAssetsRequest { | ||||
|      */ | ||||
|     readonly skip?: number | ||||
| 
 | ||||
|     /** | ||||
|      *  | ||||
|      * @type {string} | ||||
|      * @memberof AssetApiGetAllAssets | ||||
|      */ | ||||
|     readonly updatedAfter?: string | ||||
| 
 | ||||
|     /** | ||||
|      * ETag of data already cached on the client | ||||
|      * @type {string} | ||||
| @@ -7460,7 +7508,7 @@ export class AssetApi extends BaseAPI { | ||||
|      * @memberof AssetApi | ||||
|      */ | ||||
|     public getAllAssets(requestParameters: AssetApiGetAllAssetsRequest = {}, options?: AxiosRequestConfig) { | ||||
|         return AssetApiFp(this.configuration).getAllAssets(requestParameters.userId, requestParameters.isFavorite, requestParameters.isArchived, requestParameters.withoutThumbs, requestParameters.skip, requestParameters.ifNoneMatch, options).then((request) => request(this.axios, this.basePath)); | ||||
|         return AssetApiFp(this.configuration).getAllAssets(requestParameters.userId, requestParameters.isFavorite, requestParameters.isArchived, requestParameters.withoutThumbs, requestParameters.skip, requestParameters.updatedAfter, requestParameters.ifNoneMatch, options).then((request) => request(this.axios, this.basePath)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @@ -7671,6 +7719,163 @@ export class AssetApi extends BaseAPI { | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
|  * AuditApi - axios parameter creator | ||||
|  * @export | ||||
|  */ | ||||
| export const AuditApiAxiosParamCreator = function (configuration?: Configuration) { | ||||
|     return { | ||||
|         /** | ||||
|          *  | ||||
|          * @param {EntityType} entityType  | ||||
|          * @param {string} after  | ||||
|          * @param {string} [userId]  | ||||
|          * @param {*} [options] Override http request option. | ||||
|          * @throws {RequiredError} | ||||
|          */ | ||||
|         getAuditDeletes: async (entityType: EntityType, after: string, userId?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => { | ||||
|             // verify required parameter 'entityType' is not null or undefined
 | ||||
|             assertParamExists('getAuditDeletes', 'entityType', entityType) | ||||
|             // verify required parameter 'after' is not null or undefined
 | ||||
|             assertParamExists('getAuditDeletes', 'after', after) | ||||
|             const localVarPath = `/audit/deletes`; | ||||
|             // 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: 'GET', ...baseOptions, ...options}; | ||||
|             const localVarHeaderParameter = {} as any; | ||||
|             const localVarQueryParameter = {} as any; | ||||
| 
 | ||||
|             // authentication cookie required
 | ||||
| 
 | ||||
|             // authentication api_key required
 | ||||
|             await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration) | ||||
| 
 | ||||
|             // authentication bearer required
 | ||||
|             // http bearer authentication required
 | ||||
|             await setBearerAuthToObject(localVarHeaderParameter, configuration) | ||||
| 
 | ||||
|             if (entityType !== undefined) { | ||||
|                 localVarQueryParameter['entityType'] = entityType; | ||||
|             } | ||||
| 
 | ||||
|             if (userId !== undefined) { | ||||
|                 localVarQueryParameter['userId'] = userId; | ||||
|             } | ||||
| 
 | ||||
|             if (after !== undefined) { | ||||
|                 localVarQueryParameter['after'] = (after as any instanceof Date) ? | ||||
|                     (after as any).toISOString() : | ||||
|                     after; | ||||
|             } | ||||
| 
 | ||||
| 
 | ||||
|      | ||||
|             setSearchParams(localVarUrlObj, localVarQueryParameter); | ||||
|             let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; | ||||
|             localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; | ||||
| 
 | ||||
|             return { | ||||
|                 url: toPathString(localVarUrlObj), | ||||
|                 options: localVarRequestOptions, | ||||
|             }; | ||||
|         }, | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| /** | ||||
|  * AuditApi - functional programming interface | ||||
|  * @export | ||||
|  */ | ||||
| export const AuditApiFp = function(configuration?: Configuration) { | ||||
|     const localVarAxiosParamCreator = AuditApiAxiosParamCreator(configuration) | ||||
|     return { | ||||
|         /** | ||||
|          *  | ||||
|          * @param {EntityType} entityType  | ||||
|          * @param {string} after  | ||||
|          * @param {string} [userId]  | ||||
|          * @param {*} [options] Override http request option. | ||||
|          * @throws {RequiredError} | ||||
|          */ | ||||
|         async getAuditDeletes(entityType: EntityType, after: string, userId?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<AuditDeletesResponseDto>> { | ||||
|             const localVarAxiosArgs = await localVarAxiosParamCreator.getAuditDeletes(entityType, after, userId, options); | ||||
|             return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); | ||||
|         }, | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| /** | ||||
|  * AuditApi - factory interface | ||||
|  * @export | ||||
|  */ | ||||
| export const AuditApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { | ||||
|     const localVarFp = AuditApiFp(configuration) | ||||
|     return { | ||||
|         /** | ||||
|          *  | ||||
|          * @param {AuditApiGetAuditDeletesRequest} requestParameters Request parameters. | ||||
|          * @param {*} [options] Override http request option. | ||||
|          * @throws {RequiredError} | ||||
|          */ | ||||
|         getAuditDeletes(requestParameters: AuditApiGetAuditDeletesRequest, options?: AxiosRequestConfig): AxiosPromise<AuditDeletesResponseDto> { | ||||
|             return localVarFp.getAuditDeletes(requestParameters.entityType, requestParameters.after, requestParameters.userId, options).then((request) => request(axios, basePath)); | ||||
|         }, | ||||
|     }; | ||||
| }; | ||||
| 
 | ||||
| /** | ||||
|  * Request parameters for getAuditDeletes operation in AuditApi. | ||||
|  * @export | ||||
|  * @interface AuditApiGetAuditDeletesRequest | ||||
|  */ | ||||
| export interface AuditApiGetAuditDeletesRequest { | ||||
|     /** | ||||
|      *  | ||||
|      * @type {EntityType} | ||||
|      * @memberof AuditApiGetAuditDeletes | ||||
|      */ | ||||
|     readonly entityType: EntityType | ||||
| 
 | ||||
|     /** | ||||
|      *  | ||||
|      * @type {string} | ||||
|      * @memberof AuditApiGetAuditDeletes | ||||
|      */ | ||||
|     readonly after: string | ||||
| 
 | ||||
|     /** | ||||
|      *  | ||||
|      * @type {string} | ||||
|      * @memberof AuditApiGetAuditDeletes | ||||
|      */ | ||||
|     readonly userId?: string | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * AuditApi - object-oriented interface | ||||
|  * @export | ||||
|  * @class AuditApi | ||||
|  * @extends {BaseAPI} | ||||
|  */ | ||||
| export class AuditApi extends BaseAPI { | ||||
|     /** | ||||
|      *  | ||||
|      * @param {AuditApiGetAuditDeletesRequest} requestParameters Request parameters. | ||||
|      * @param {*} [options] Override http request option. | ||||
|      * @throws {RequiredError} | ||||
|      * @memberof AuditApi | ||||
|      */ | ||||
|     public getAuditDeletes(requestParameters: AuditApiGetAuditDeletesRequest, options?: AxiosRequestConfig) { | ||||
|         return AuditApiFp(this.configuration).getAuditDeletes(requestParameters.entityType, requestParameters.after, requestParameters.userId, options).then((request) => request(this.axios, this.basePath)); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
|  * AuthenticationApi - axios parameter creator | ||||
|  * @export | ||||
|   | ||||
		Reference in New Issue
	
	Block a user