mirror of
https://github.com/immich-app/immich.git
synced 2025-04-13 19:46:24 +02:00
feat: persistent memories (#8330)
* feat: persistent memories * refactor: use new add/remove asset utility
This commit is contained in:
parent
0849dbd1af
commit
cd0e537e3e
43 changed files with 3497 additions and 0 deletions
e2e/src/api/specs
mobile/openapi
open-api
server
src
controllers
cores
dtos
entities
interfaces
migrations
queries
repositories
services
test
376
e2e/src/api/specs/memory.e2e-spec.ts
Normal file
376
e2e/src/api/specs/memory.e2e-spec.ts
Normal file
|
@ -0,0 +1,376 @@
|
|||
import {
|
||||
AssetFileUploadResponseDto,
|
||||
LoginResponseDto,
|
||||
MemoryResponseDto,
|
||||
MemoryType,
|
||||
createMemory,
|
||||
getMemory,
|
||||
} from '@immich/sdk';
|
||||
import { createUserDto, uuidDto } from 'src/fixtures';
|
||||
import { errorDto } from 'src/responses';
|
||||
import { app, asBearerAuth, utils } from 'src/utils';
|
||||
import request from 'supertest';
|
||||
import { beforeAll, describe, expect, it } from 'vitest';
|
||||
|
||||
describe('/memories', () => {
|
||||
let admin: LoginResponseDto;
|
||||
let user: LoginResponseDto;
|
||||
let adminAsset: AssetFileUploadResponseDto;
|
||||
let userAsset1: AssetFileUploadResponseDto;
|
||||
let userAsset2: AssetFileUploadResponseDto;
|
||||
let userMemory: MemoryResponseDto;
|
||||
|
||||
beforeAll(async () => {
|
||||
await utils.resetDatabase();
|
||||
|
||||
admin = await utils.adminSetup();
|
||||
user = await utils.userSetup(admin.accessToken, createUserDto.user1);
|
||||
[adminAsset, userAsset1, userAsset2] = await Promise.all([
|
||||
utils.createAsset(admin.accessToken),
|
||||
utils.createAsset(user.accessToken),
|
||||
utils.createAsset(user.accessToken),
|
||||
]);
|
||||
userMemory = await createMemory(
|
||||
{
|
||||
memoryCreateDto: {
|
||||
type: MemoryType.OnThisDay,
|
||||
memoryAt: new Date(2021).toISOString(),
|
||||
data: { year: 2021 },
|
||||
assetIds: [],
|
||||
},
|
||||
},
|
||||
{ headers: asBearerAuth(user.accessToken) },
|
||||
);
|
||||
});
|
||||
|
||||
describe('GET /memories', () => {
|
||||
it('should require authentication', async () => {
|
||||
const { status, body } = await request(app).get('/memories');
|
||||
|
||||
expect(status).toBe(401);
|
||||
expect(body).toEqual(errorDto.unauthorized);
|
||||
});
|
||||
});
|
||||
|
||||
describe('POST /memories', () => {
|
||||
it('should require authentication', async () => {
|
||||
const { status, body } = await request(app).post('/memories');
|
||||
|
||||
expect(status).toBe(401);
|
||||
expect(body).toEqual(errorDto.unauthorized);
|
||||
});
|
||||
|
||||
it('should validate data when type is on this day', async () => {
|
||||
const { status, body } = await request(app)
|
||||
.post('/memories')
|
||||
.set('Authorization', `Bearer ${user.accessToken}`)
|
||||
.send({
|
||||
type: 'on_this_day',
|
||||
data: {},
|
||||
memoryAt: new Date(2021).toISOString(),
|
||||
});
|
||||
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(
|
||||
errorDto.badRequest(['data.year must be a positive number', 'data.year must be an integer number']),
|
||||
);
|
||||
});
|
||||
|
||||
it('should create a new memory', async () => {
|
||||
const { status, body } = await request(app)
|
||||
.post('/memories')
|
||||
.set('Authorization', `Bearer ${user.accessToken}`)
|
||||
.send({
|
||||
type: 'on_this_day',
|
||||
data: { year: 2021 },
|
||||
memoryAt: new Date(2021).toISOString(),
|
||||
});
|
||||
|
||||
expect(status).toBe(201);
|
||||
expect(body).toEqual({
|
||||
id: expect.any(String),
|
||||
type: 'on_this_day',
|
||||
data: { year: 2021 },
|
||||
createdAt: expect.any(String),
|
||||
updatedAt: expect.any(String),
|
||||
deletedAt: null,
|
||||
seenAt: null,
|
||||
isSaved: false,
|
||||
memoryAt: expect.any(String),
|
||||
ownerId: user.userId,
|
||||
assets: [],
|
||||
});
|
||||
});
|
||||
|
||||
it('should create a new memory (with assets)', async () => {
|
||||
const { status, body } = await request(app)
|
||||
.post('/memories')
|
||||
.set('Authorization', `Bearer ${user.accessToken}`)
|
||||
.send({
|
||||
type: 'on_this_day',
|
||||
data: { year: 2021 },
|
||||
memoryAt: new Date(2021).toISOString(),
|
||||
assetIds: [userAsset1.id, userAsset2.id],
|
||||
});
|
||||
|
||||
expect(status).toBe(201);
|
||||
expect(body).toMatchObject({
|
||||
id: expect.any(String),
|
||||
assets: expect.arrayContaining([
|
||||
expect.objectContaining({ id: userAsset1.id }),
|
||||
expect.objectContaining({ id: userAsset2.id }),
|
||||
]),
|
||||
});
|
||||
expect(body.assets).toHaveLength(2);
|
||||
});
|
||||
|
||||
it('should create a new memory and ignore assets the user does not have access to', async () => {
|
||||
const { status, body } = await request(app)
|
||||
.post('/memories')
|
||||
.set('Authorization', `Bearer ${user.accessToken}`)
|
||||
.send({
|
||||
type: 'on_this_day',
|
||||
data: { year: 2021 },
|
||||
memoryAt: new Date(2021).toISOString(),
|
||||
assetIds: [userAsset1.id, adminAsset.id],
|
||||
});
|
||||
|
||||
expect(status).toBe(201);
|
||||
expect(body).toMatchObject({
|
||||
id: expect.any(String),
|
||||
assets: [expect.objectContaining({ id: userAsset1.id })],
|
||||
});
|
||||
expect(body.assets).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /memories/:id', () => {
|
||||
it('should require authentication', async () => {
|
||||
const { status, body } = await request(app).get(`/memories/${uuidDto.invalid}`);
|
||||
|
||||
expect(status).toBe(401);
|
||||
expect(body).toEqual(errorDto.unauthorized);
|
||||
});
|
||||
|
||||
it('should require a valid id', async () => {
|
||||
const { status, body } = await request(app)
|
||||
.get(`/memories/${uuidDto.invalid}`)
|
||||
.set('Authorization', `Bearer ${user.accessToken}`);
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorDto.badRequest(['id must be a UUID']));
|
||||
});
|
||||
|
||||
it('should require access', async () => {
|
||||
const { status, body } = await request(app)
|
||||
.get(`/memories/${userMemory.id}`)
|
||||
.set('Authorization', `Bearer ${admin.accessToken}`);
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorDto.noPermission);
|
||||
});
|
||||
|
||||
it('should get the memory', async () => {
|
||||
const { status, body } = await request(app)
|
||||
.get(`/memories/${userMemory.id}`)
|
||||
.set('Authorization', `Bearer ${user.accessToken}`);
|
||||
expect(status).toBe(200);
|
||||
expect(body).toMatchObject({ id: userMemory.id });
|
||||
});
|
||||
});
|
||||
|
||||
describe('PUT /memories/:id', () => {
|
||||
it('should require authentication', async () => {
|
||||
const { status, body } = await request(app).put(`/memories/${uuidDto.invalid}`).send({ isSaved: true });
|
||||
|
||||
expect(status).toBe(401);
|
||||
expect(body).toEqual(errorDto.unauthorized);
|
||||
});
|
||||
|
||||
it('should require a valid id', async () => {
|
||||
const { status, body } = await request(app)
|
||||
.put(`/memories/${uuidDto.invalid}`)
|
||||
.send({ isSaved: true })
|
||||
.set('Authorization', `Bearer ${user.accessToken}`);
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorDto.badRequest(['id must be a UUID']));
|
||||
});
|
||||
|
||||
it('should require access', async () => {
|
||||
const { status, body } = await request(app)
|
||||
.put(`/memories/${userMemory.id}`)
|
||||
.send({ isSaved: true })
|
||||
.set('Authorization', `Bearer ${admin.accessToken}`);
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorDto.noPermission);
|
||||
});
|
||||
|
||||
it('should update the memory', async () => {
|
||||
const before = await getMemory({ id: userMemory.id }, { headers: asBearerAuth(user.accessToken) });
|
||||
expect(before.isSaved).toBe(false);
|
||||
|
||||
const { status, body } = await request(app)
|
||||
.put(`/memories/${userMemory.id}`)
|
||||
.send({ isSaved: true })
|
||||
.set('Authorization', `Bearer ${user.accessToken}`);
|
||||
expect(status).toBe(200);
|
||||
expect(body).toMatchObject({
|
||||
id: userMemory.id,
|
||||
isSaved: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('PUT /memories/:id/assets', () => {
|
||||
it('should require authentication', async () => {
|
||||
const { status, body } = await request(app)
|
||||
.put(`/memories/${userMemory.id}/assets`)
|
||||
.send({ ids: [userAsset1.id] });
|
||||
expect(status).toBe(401);
|
||||
expect(body).toEqual(errorDto.unauthorized);
|
||||
});
|
||||
|
||||
it('should require a valid id', async () => {
|
||||
const { status, body } = await request(app)
|
||||
.put(`/memories/${uuidDto.invalid}/assets`)
|
||||
.send({ ids: [userAsset1.id] })
|
||||
.set('Authorization', `Bearer ${user.accessToken}`);
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorDto.badRequest(['id must be a UUID']));
|
||||
});
|
||||
|
||||
it('should require access', async () => {
|
||||
const { status, body } = await request(app)
|
||||
.put(`/memories/${userMemory.id}/assets`)
|
||||
.send({ ids: [userAsset1.id] })
|
||||
.set('Authorization', `Bearer ${admin.accessToken}`);
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorDto.noPermission);
|
||||
});
|
||||
|
||||
it('should require a valid asset id', async () => {
|
||||
const { status, body } = await request(app)
|
||||
.put(`/memories/${userMemory.id}/assets`)
|
||||
.send({ ids: [uuidDto.invalid] })
|
||||
.set('Authorization', `Bearer ${user.accessToken}`);
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorDto.badRequest(['each value in ids must be a UUID']));
|
||||
});
|
||||
|
||||
it('should require asset access', async () => {
|
||||
const { status, body } = await request(app)
|
||||
.put(`/memories/${userMemory.id}/assets`)
|
||||
.send({ ids: [adminAsset.id] })
|
||||
.set('Authorization', `Bearer ${user.accessToken}`);
|
||||
expect(status).toBe(200);
|
||||
expect(body).toHaveLength(1);
|
||||
expect(body[0]).toEqual({
|
||||
id: adminAsset.id,
|
||||
success: false,
|
||||
error: 'no_permission',
|
||||
});
|
||||
});
|
||||
|
||||
it('should add assets to the memory', async () => {
|
||||
const { status, body } = await request(app)
|
||||
.put(`/memories/${userMemory.id}/assets`)
|
||||
.send({ ids: [userAsset1.id] })
|
||||
.set('Authorization', `Bearer ${user.accessToken}`);
|
||||
expect(status).toBe(200);
|
||||
expect(body).toHaveLength(1);
|
||||
expect(body[0]).toEqual({ id: userAsset1.id, success: true });
|
||||
});
|
||||
});
|
||||
|
||||
describe('DELETE /memories/:id/assets', () => {
|
||||
it('should require authentication', async () => {
|
||||
const { status, body } = await request(app)
|
||||
.delete(`/memories/${userMemory.id}/assets`)
|
||||
.send({ ids: [userAsset1.id] });
|
||||
expect(status).toBe(401);
|
||||
expect(body).toEqual(errorDto.unauthorized);
|
||||
});
|
||||
|
||||
it('should require a valid id', async () => {
|
||||
const { status, body } = await request(app)
|
||||
.delete(`/memories/${uuidDto.invalid}/assets`)
|
||||
.send({ ids: [userAsset1.id] })
|
||||
.set('Authorization', `Bearer ${user.accessToken}`);
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorDto.badRequest(['id must be a UUID']));
|
||||
});
|
||||
|
||||
it('should require access', async () => {
|
||||
const { status, body } = await request(app)
|
||||
.delete(`/memories/${userMemory.id}/assets`)
|
||||
.send({ ids: [userAsset1.id] })
|
||||
.set('Authorization', `Bearer ${admin.accessToken}`);
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorDto.noPermission);
|
||||
});
|
||||
|
||||
it('should require a valid asset id', async () => {
|
||||
const { status, body } = await request(app)
|
||||
.delete(`/memories/${userMemory.id}/assets`)
|
||||
.send({ ids: [uuidDto.invalid] })
|
||||
.set('Authorization', `Bearer ${user.accessToken}`);
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorDto.badRequest(['each value in ids must be a UUID']));
|
||||
});
|
||||
|
||||
it('should only remove assets in the memory', async () => {
|
||||
const { status, body } = await request(app)
|
||||
.delete(`/memories/${userMemory.id}/assets`)
|
||||
.send({ ids: [adminAsset.id] })
|
||||
.set('Authorization', `Bearer ${user.accessToken}`);
|
||||
expect(status).toBe(200);
|
||||
expect(body).toHaveLength(1);
|
||||
expect(body[0]).toEqual({
|
||||
id: adminAsset.id,
|
||||
success: false,
|
||||
error: 'not_found',
|
||||
});
|
||||
});
|
||||
|
||||
it('should remove assets from the memory', async () => {
|
||||
const { status, body } = await request(app)
|
||||
.delete(`/memories/${userMemory.id}/assets`)
|
||||
.send({ ids: [userAsset1.id] })
|
||||
.set('Authorization', `Bearer ${user.accessToken}`);
|
||||
expect(status).toBe(200);
|
||||
expect(body).toHaveLength(1);
|
||||
expect(body[0]).toEqual({ id: userAsset1.id, success: true });
|
||||
});
|
||||
});
|
||||
|
||||
describe('DELETE /memories/:id', () => {
|
||||
it('should require authentication', async () => {
|
||||
const { status, body } = await request(app).delete(`/memories/${uuidDto.invalid}`);
|
||||
|
||||
expect(status).toBe(401);
|
||||
expect(body).toEqual(errorDto.unauthorized);
|
||||
});
|
||||
|
||||
it('should require a valid id', async () => {
|
||||
const { status, body } = await request(app)
|
||||
.delete(`/memories/${uuidDto.invalid}`)
|
||||
.set('Authorization', `Bearer ${user.accessToken}`);
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorDto.badRequest(['id must be a UUID']));
|
||||
});
|
||||
|
||||
it('should require access', async () => {
|
||||
const { status, body } = await request(app)
|
||||
.delete(`/memories/${userMemory.id}`)
|
||||
.set('Authorization', `Bearer ${admin.accessToken}`);
|
||||
expect(status).toBe(400);
|
||||
expect(body).toEqual(errorDto.noPermission);
|
||||
});
|
||||
|
||||
it('should delete the memory', async () => {
|
||||
const { status } = await request(app)
|
||||
.delete(`/memories/${userMemory.id}`)
|
||||
.send({ isSaved: true })
|
||||
.set('Authorization', `Bearer ${user.accessToken}`);
|
||||
expect(status).toBe(204);
|
||||
});
|
||||
});
|
||||
});
|
15
mobile/openapi/.openapi-generator/FILES
generated
15
mobile/openapi/.openapi-generator/FILES
generated
|
@ -90,7 +90,12 @@ doc/LoginResponseDto.md
|
|||
doc/LogoutResponseDto.md
|
||||
doc/MapMarkerResponseDto.md
|
||||
doc/MapTheme.md
|
||||
doc/MemoryApi.md
|
||||
doc/MemoryCreateDto.md
|
||||
doc/MemoryLaneResponseDto.md
|
||||
doc/MemoryResponseDto.md
|
||||
doc/MemoryType.md
|
||||
doc/MemoryUpdateDto.md
|
||||
doc/MergePersonDto.md
|
||||
doc/MetadataSearchDto.md
|
||||
doc/ModelType.md
|
||||
|
@ -205,6 +210,7 @@ lib/api/download_api.dart
|
|||
lib/api/face_api.dart
|
||||
lib/api/job_api.dart
|
||||
lib/api/library_api.dart
|
||||
lib/api/memory_api.dart
|
||||
lib/api/o_auth_api.dart
|
||||
lib/api/partner_api.dart
|
||||
lib/api/person_api.dart
|
||||
|
@ -301,7 +307,11 @@ lib/model/login_response_dto.dart
|
|||
lib/model/logout_response_dto.dart
|
||||
lib/model/map_marker_response_dto.dart
|
||||
lib/model/map_theme.dart
|
||||
lib/model/memory_create_dto.dart
|
||||
lib/model/memory_lane_response_dto.dart
|
||||
lib/model/memory_response_dto.dart
|
||||
lib/model/memory_type.dart
|
||||
lib/model/memory_update_dto.dart
|
||||
lib/model/merge_person_dto.dart
|
||||
lib/model/metadata_search_dto.dart
|
||||
lib/model/model_type.dart
|
||||
|
@ -481,7 +491,12 @@ test/login_response_dto_test.dart
|
|||
test/logout_response_dto_test.dart
|
||||
test/map_marker_response_dto_test.dart
|
||||
test/map_theme_test.dart
|
||||
test/memory_api_test.dart
|
||||
test/memory_create_dto_test.dart
|
||||
test/memory_lane_response_dto_test.dart
|
||||
test/memory_response_dto_test.dart
|
||||
test/memory_type_test.dart
|
||||
test/memory_update_dto_test.dart
|
||||
test/merge_person_dto_test.dart
|
||||
test/metadata_search_dto_test.dart
|
||||
test/model_type_test.dart
|
||||
|
|
11
mobile/openapi/README.md
generated
11
mobile/openapi/README.md
generated
|
@ -140,6 +140,13 @@ Class | Method | HTTP request | Description
|
|||
*LibraryApi* | [**scanLibrary**](doc//LibraryApi.md#scanlibrary) | **POST** /library/{id}/scan |
|
||||
*LibraryApi* | [**updateLibrary**](doc//LibraryApi.md#updatelibrary) | **PUT** /library/{id} |
|
||||
*LibraryApi* | [**validate**](doc//LibraryApi.md#validate) | **POST** /library/{id}/validate |
|
||||
*MemoryApi* | [**addMemoryAssets**](doc//MemoryApi.md#addmemoryassets) | **PUT** /memories/{id}/assets |
|
||||
*MemoryApi* | [**createMemory**](doc//MemoryApi.md#creatememory) | **POST** /memories |
|
||||
*MemoryApi* | [**deleteMemory**](doc//MemoryApi.md#deletememory) | **DELETE** /memories/{id} |
|
||||
*MemoryApi* | [**getMemory**](doc//MemoryApi.md#getmemory) | **GET** /memories/{id} |
|
||||
*MemoryApi* | [**removeMemoryAssets**](doc//MemoryApi.md#removememoryassets) | **DELETE** /memories/{id}/assets |
|
||||
*MemoryApi* | [**searchMemories**](doc//MemoryApi.md#searchmemories) | **GET** /memories |
|
||||
*MemoryApi* | [**updateMemory**](doc//MemoryApi.md#updatememory) | **PUT** /memories/{id} |
|
||||
*OAuthApi* | [**finishOAuth**](doc//OAuthApi.md#finishoauth) | **POST** /oauth/callback |
|
||||
*OAuthApi* | [**linkOAuthAccount**](doc//OAuthApi.md#linkoauthaccount) | **POST** /oauth/link |
|
||||
*OAuthApi* | [**redirectOAuthToMobile**](doc//OAuthApi.md#redirectoauthtomobile) | **GET** /oauth/mobile-redirect |
|
||||
|
@ -293,7 +300,11 @@ Class | Method | HTTP request | Description
|
|||
- [LogoutResponseDto](doc//LogoutResponseDto.md)
|
||||
- [MapMarkerResponseDto](doc//MapMarkerResponseDto.md)
|
||||
- [MapTheme](doc//MapTheme.md)
|
||||
- [MemoryCreateDto](doc//MemoryCreateDto.md)
|
||||
- [MemoryLaneResponseDto](doc//MemoryLaneResponseDto.md)
|
||||
- [MemoryResponseDto](doc//MemoryResponseDto.md)
|
||||
- [MemoryType](doc//MemoryType.md)
|
||||
- [MemoryUpdateDto](doc//MemoryUpdateDto.md)
|
||||
- [MergePersonDto](doc//MergePersonDto.md)
|
||||
- [MetadataSearchDto](doc//MetadataSearchDto.md)
|
||||
- [ModelType](doc//ModelType.md)
|
||||
|
|
406
mobile/openapi/doc/MemoryApi.md
generated
Normal file
406
mobile/openapi/doc/MemoryApi.md
generated
Normal file
|
@ -0,0 +1,406 @@
|
|||
# openapi.api.MemoryApi
|
||||
|
||||
## Load the API package
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
```
|
||||
|
||||
All URIs are relative to */api*
|
||||
|
||||
Method | HTTP request | Description
|
||||
------------- | ------------- | -------------
|
||||
[**addMemoryAssets**](MemoryApi.md#addmemoryassets) | **PUT** /memories/{id}/assets |
|
||||
[**createMemory**](MemoryApi.md#creatememory) | **POST** /memories |
|
||||
[**deleteMemory**](MemoryApi.md#deletememory) | **DELETE** /memories/{id} |
|
||||
[**getMemory**](MemoryApi.md#getmemory) | **GET** /memories/{id} |
|
||||
[**removeMemoryAssets**](MemoryApi.md#removememoryassets) | **DELETE** /memories/{id}/assets |
|
||||
[**searchMemories**](MemoryApi.md#searchmemories) | **GET** /memories |
|
||||
[**updateMemory**](MemoryApi.md#updatememory) | **PUT** /memories/{id} |
|
||||
|
||||
|
||||
# **addMemoryAssets**
|
||||
> List<BulkIdResponseDto> addMemoryAssets(id, bulkIdsDto)
|
||||
|
||||
|
||||
|
||||
### Example
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
// TODO Configure API key authorization: cookie
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure API key authorization: api_key
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure HTTP Bearer authorization: bearer
|
||||
// Case 1. Use String Token
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
|
||||
// Case 2. Use Function which generate token.
|
||||
// String yourTokenGeneratorFunction() { ... }
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
||||
|
||||
final api_instance = MemoryApi();
|
||||
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
|
||||
final bulkIdsDto = BulkIdsDto(); // BulkIdsDto |
|
||||
|
||||
try {
|
||||
final result = api_instance.addMemoryAssets(id, bulkIdsDto);
|
||||
print(result);
|
||||
} catch (e) {
|
||||
print('Exception when calling MemoryApi->addMemoryAssets: $e\n');
|
||||
}
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
Name | Type | Description | Notes
|
||||
------------- | ------------- | ------------- | -------------
|
||||
**id** | **String**| |
|
||||
**bulkIdsDto** | [**BulkIdsDto**](BulkIdsDto.md)| |
|
||||
|
||||
### Return type
|
||||
|
||||
[**List<BulkIdResponseDto>**](BulkIdResponseDto.md)
|
||||
|
||||
### Authorization
|
||||
|
||||
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
|
||||
|
||||
### HTTP request headers
|
||||
|
||||
- **Content-Type**: application/json
|
||||
- **Accept**: application/json
|
||||
|
||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||
|
||||
# **createMemory**
|
||||
> MemoryResponseDto createMemory(memoryCreateDto)
|
||||
|
||||
|
||||
|
||||
### Example
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
// TODO Configure API key authorization: cookie
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure API key authorization: api_key
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure HTTP Bearer authorization: bearer
|
||||
// Case 1. Use String Token
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
|
||||
// Case 2. Use Function which generate token.
|
||||
// String yourTokenGeneratorFunction() { ... }
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
||||
|
||||
final api_instance = MemoryApi();
|
||||
final memoryCreateDto = MemoryCreateDto(); // MemoryCreateDto |
|
||||
|
||||
try {
|
||||
final result = api_instance.createMemory(memoryCreateDto);
|
||||
print(result);
|
||||
} catch (e) {
|
||||
print('Exception when calling MemoryApi->createMemory: $e\n');
|
||||
}
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
Name | Type | Description | Notes
|
||||
------------- | ------------- | ------------- | -------------
|
||||
**memoryCreateDto** | [**MemoryCreateDto**](MemoryCreateDto.md)| |
|
||||
|
||||
### Return type
|
||||
|
||||
[**MemoryResponseDto**](MemoryResponseDto.md)
|
||||
|
||||
### Authorization
|
||||
|
||||
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
|
||||
|
||||
### HTTP request headers
|
||||
|
||||
- **Content-Type**: application/json
|
||||
- **Accept**: application/json
|
||||
|
||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||
|
||||
# **deleteMemory**
|
||||
> deleteMemory(id)
|
||||
|
||||
|
||||
|
||||
### Example
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
// TODO Configure API key authorization: cookie
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure API key authorization: api_key
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure HTTP Bearer authorization: bearer
|
||||
// Case 1. Use String Token
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
|
||||
// Case 2. Use Function which generate token.
|
||||
// String yourTokenGeneratorFunction() { ... }
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
||||
|
||||
final api_instance = MemoryApi();
|
||||
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
|
||||
|
||||
try {
|
||||
api_instance.deleteMemory(id);
|
||||
} catch (e) {
|
||||
print('Exception when calling MemoryApi->deleteMemory: $e\n');
|
||||
}
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
Name | Type | Description | Notes
|
||||
------------- | ------------- | ------------- | -------------
|
||||
**id** | **String**| |
|
||||
|
||||
### Return type
|
||||
|
||||
void (empty response body)
|
||||
|
||||
### Authorization
|
||||
|
||||
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
|
||||
|
||||
### HTTP request headers
|
||||
|
||||
- **Content-Type**: Not defined
|
||||
- **Accept**: Not defined
|
||||
|
||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||
|
||||
# **getMemory**
|
||||
> MemoryResponseDto getMemory(id)
|
||||
|
||||
|
||||
|
||||
### Example
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
// TODO Configure API key authorization: cookie
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure API key authorization: api_key
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure HTTP Bearer authorization: bearer
|
||||
// Case 1. Use String Token
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
|
||||
// Case 2. Use Function which generate token.
|
||||
// String yourTokenGeneratorFunction() { ... }
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
||||
|
||||
final api_instance = MemoryApi();
|
||||
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
|
||||
|
||||
try {
|
||||
final result = api_instance.getMemory(id);
|
||||
print(result);
|
||||
} catch (e) {
|
||||
print('Exception when calling MemoryApi->getMemory: $e\n');
|
||||
}
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
Name | Type | Description | Notes
|
||||
------------- | ------------- | ------------- | -------------
|
||||
**id** | **String**| |
|
||||
|
||||
### Return type
|
||||
|
||||
[**MemoryResponseDto**](MemoryResponseDto.md)
|
||||
|
||||
### Authorization
|
||||
|
||||
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
|
||||
|
||||
### HTTP request headers
|
||||
|
||||
- **Content-Type**: Not defined
|
||||
- **Accept**: application/json
|
||||
|
||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||
|
||||
# **removeMemoryAssets**
|
||||
> List<BulkIdResponseDto> removeMemoryAssets(id, bulkIdsDto)
|
||||
|
||||
|
||||
|
||||
### Example
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
// TODO Configure API key authorization: cookie
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure API key authorization: api_key
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure HTTP Bearer authorization: bearer
|
||||
// Case 1. Use String Token
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
|
||||
// Case 2. Use Function which generate token.
|
||||
// String yourTokenGeneratorFunction() { ... }
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
||||
|
||||
final api_instance = MemoryApi();
|
||||
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
|
||||
final bulkIdsDto = BulkIdsDto(); // BulkIdsDto |
|
||||
|
||||
try {
|
||||
final result = api_instance.removeMemoryAssets(id, bulkIdsDto);
|
||||
print(result);
|
||||
} catch (e) {
|
||||
print('Exception when calling MemoryApi->removeMemoryAssets: $e\n');
|
||||
}
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
Name | Type | Description | Notes
|
||||
------------- | ------------- | ------------- | -------------
|
||||
**id** | **String**| |
|
||||
**bulkIdsDto** | [**BulkIdsDto**](BulkIdsDto.md)| |
|
||||
|
||||
### Return type
|
||||
|
||||
[**List<BulkIdResponseDto>**](BulkIdResponseDto.md)
|
||||
|
||||
### Authorization
|
||||
|
||||
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
|
||||
|
||||
### HTTP request headers
|
||||
|
||||
- **Content-Type**: application/json
|
||||
- **Accept**: application/json
|
||||
|
||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||
|
||||
# **searchMemories**
|
||||
> List<MemoryResponseDto> searchMemories()
|
||||
|
||||
|
||||
|
||||
### Example
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
// TODO Configure API key authorization: cookie
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure API key authorization: api_key
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure HTTP Bearer authorization: bearer
|
||||
// Case 1. Use String Token
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
|
||||
// Case 2. Use Function which generate token.
|
||||
// String yourTokenGeneratorFunction() { ... }
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
||||
|
||||
final api_instance = MemoryApi();
|
||||
|
||||
try {
|
||||
final result = api_instance.searchMemories();
|
||||
print(result);
|
||||
} catch (e) {
|
||||
print('Exception when calling MemoryApi->searchMemories: $e\n');
|
||||
}
|
||||
```
|
||||
|
||||
### Parameters
|
||||
This endpoint does not need any parameter.
|
||||
|
||||
### Return type
|
||||
|
||||
[**List<MemoryResponseDto>**](MemoryResponseDto.md)
|
||||
|
||||
### Authorization
|
||||
|
||||
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
|
||||
|
||||
### HTTP request headers
|
||||
|
||||
- **Content-Type**: Not defined
|
||||
- **Accept**: application/json
|
||||
|
||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||
|
||||
# **updateMemory**
|
||||
> MemoryResponseDto updateMemory(id, memoryUpdateDto)
|
||||
|
||||
|
||||
|
||||
### Example
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
// TODO Configure API key authorization: cookie
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure API key authorization: api_key
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
|
||||
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
|
||||
// TODO Configure HTTP Bearer authorization: bearer
|
||||
// Case 1. Use String Token
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
|
||||
// Case 2. Use Function which generate token.
|
||||
// String yourTokenGeneratorFunction() { ... }
|
||||
//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
|
||||
|
||||
final api_instance = MemoryApi();
|
||||
final id = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
|
||||
final memoryUpdateDto = MemoryUpdateDto(); // MemoryUpdateDto |
|
||||
|
||||
try {
|
||||
final result = api_instance.updateMemory(id, memoryUpdateDto);
|
||||
print(result);
|
||||
} catch (e) {
|
||||
print('Exception when calling MemoryApi->updateMemory: $e\n');
|
||||
}
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
Name | Type | Description | Notes
|
||||
------------- | ------------- | ------------- | -------------
|
||||
**id** | **String**| |
|
||||
**memoryUpdateDto** | [**MemoryUpdateDto**](MemoryUpdateDto.md)| |
|
||||
|
||||
### Return type
|
||||
|
||||
[**MemoryResponseDto**](MemoryResponseDto.md)
|
||||
|
||||
### Authorization
|
||||
|
||||
[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
|
||||
|
||||
### HTTP request headers
|
||||
|
||||
- **Content-Type**: application/json
|
||||
- **Accept**: application/json
|
||||
|
||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||
|
20
mobile/openapi/doc/MemoryCreateDto.md
generated
Normal file
20
mobile/openapi/doc/MemoryCreateDto.md
generated
Normal file
|
@ -0,0 +1,20 @@
|
|||
# openapi.model.MemoryCreateDto
|
||||
|
||||
## Load the model package
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
```
|
||||
|
||||
## Properties
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**assetIds** | **List<String>** | | [optional] [default to const []]
|
||||
**data** | [**Object**](.md) | |
|
||||
**isSaved** | **bool** | | [optional]
|
||||
**memoryAt** | [**DateTime**](DateTime.md) | |
|
||||
**seenAt** | [**DateTime**](DateTime.md) | | [optional]
|
||||
**type** | [**MemoryType**](MemoryType.md) | |
|
||||
|
||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||
|
||||
|
25
mobile/openapi/doc/MemoryResponseDto.md
generated
Normal file
25
mobile/openapi/doc/MemoryResponseDto.md
generated
Normal file
|
@ -0,0 +1,25 @@
|
|||
# openapi.model.MemoryResponseDto
|
||||
|
||||
## Load the model package
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
```
|
||||
|
||||
## Properties
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**assets** | [**List<AssetResponseDto>**](AssetResponseDto.md) | | [default to const []]
|
||||
**createdAt** | [**DateTime**](DateTime.md) | |
|
||||
**data** | [**Object**](.md) | |
|
||||
**deletedAt** | [**DateTime**](DateTime.md) | | [optional]
|
||||
**id** | **String** | |
|
||||
**isSaved** | **bool** | |
|
||||
**memoryAt** | [**DateTime**](DateTime.md) | |
|
||||
**ownerId** | **String** | |
|
||||
**seenAt** | [**DateTime**](DateTime.md) | | [optional]
|
||||
**type** | **String** | |
|
||||
**updatedAt** | [**DateTime**](DateTime.md) | |
|
||||
|
||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||
|
||||
|
14
mobile/openapi/doc/MemoryType.md
generated
Normal file
14
mobile/openapi/doc/MemoryType.md
generated
Normal file
|
@ -0,0 +1,14 @@
|
|||
# openapi.model.MemoryType
|
||||
|
||||
## Load the model package
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
```
|
||||
|
||||
## Properties
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
|
||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||
|
||||
|
17
mobile/openapi/doc/MemoryUpdateDto.md
generated
Normal file
17
mobile/openapi/doc/MemoryUpdateDto.md
generated
Normal file
|
@ -0,0 +1,17 @@
|
|||
# openapi.model.MemoryUpdateDto
|
||||
|
||||
## Load the model package
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
```
|
||||
|
||||
## Properties
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**isSaved** | **bool** | | [optional]
|
||||
**memoryAt** | [**DateTime**](DateTime.md) | | [optional]
|
||||
**seenAt** | [**DateTime**](DateTime.md) | | [optional]
|
||||
|
||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||
|
||||
|
5
mobile/openapi/lib/api.dart
generated
5
mobile/openapi/lib/api.dart
generated
|
@ -39,6 +39,7 @@ part 'api/download_api.dart';
|
|||
part 'api/face_api.dart';
|
||||
part 'api/job_api.dart';
|
||||
part 'api/library_api.dart';
|
||||
part 'api/memory_api.dart';
|
||||
part 'api/o_auth_api.dart';
|
||||
part 'api/partner_api.dart';
|
||||
part 'api/person_api.dart';
|
||||
|
@ -128,7 +129,11 @@ part 'model/login_response_dto.dart';
|
|||
part 'model/logout_response_dto.dart';
|
||||
part 'model/map_marker_response_dto.dart';
|
||||
part 'model/map_theme.dart';
|
||||
part 'model/memory_create_dto.dart';
|
||||
part 'model/memory_lane_response_dto.dart';
|
||||
part 'model/memory_response_dto.dart';
|
||||
part 'model/memory_type.dart';
|
||||
part 'model/memory_update_dto.dart';
|
||||
part 'model/merge_person_dto.dart';
|
||||
part 'model/metadata_search_dto.dart';
|
||||
part 'model/model_type.dart';
|
||||
|
|
359
mobile/openapi/lib/api/memory_api.dart
generated
Normal file
359
mobile/openapi/lib/api/memory_api.dart
generated
Normal file
|
@ -0,0 +1,359 @@
|
|||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.12
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
|
||||
class MemoryApi {
|
||||
MemoryApi([ApiClient? apiClient]) : apiClient = apiClient ?? defaultApiClient;
|
||||
|
||||
final ApiClient apiClient;
|
||||
|
||||
/// Performs an HTTP 'PUT /memories/{id}/assets' operation and returns the [Response].
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [String] id (required):
|
||||
///
|
||||
/// * [BulkIdsDto] bulkIdsDto (required):
|
||||
Future<Response> addMemoryAssetsWithHttpInfo(String id, BulkIdsDto bulkIdsDto,) async {
|
||||
// ignore: prefer_const_declarations
|
||||
final path = r'/memories/{id}/assets'
|
||||
.replaceAll('{id}', id);
|
||||
|
||||
// ignore: prefer_final_locals
|
||||
Object? postBody = bulkIdsDto;
|
||||
|
||||
final queryParams = <QueryParam>[];
|
||||
final headerParams = <String, String>{};
|
||||
final formParams = <String, String>{};
|
||||
|
||||
const contentTypes = <String>['application/json'];
|
||||
|
||||
|
||||
return apiClient.invokeAPI(
|
||||
path,
|
||||
'PUT',
|
||||
queryParams,
|
||||
postBody,
|
||||
headerParams,
|
||||
formParams,
|
||||
contentTypes.isEmpty ? null : contentTypes.first,
|
||||
);
|
||||
}
|
||||
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [String] id (required):
|
||||
///
|
||||
/// * [BulkIdsDto] bulkIdsDto (required):
|
||||
Future<List<BulkIdResponseDto>?> addMemoryAssets(String id, BulkIdsDto bulkIdsDto,) async {
|
||||
final response = await addMemoryAssetsWithHttpInfo(id, bulkIdsDto,);
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||
// FormatException when trying to decode an empty string.
|
||||
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||
final responseBody = await _decodeBodyBytes(response);
|
||||
return (await apiClient.deserializeAsync(responseBody, 'List<BulkIdResponseDto>') as List)
|
||||
.cast<BulkIdResponseDto>()
|
||||
.toList(growable: false);
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Performs an HTTP 'POST /memories' operation and returns the [Response].
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [MemoryCreateDto] memoryCreateDto (required):
|
||||
Future<Response> createMemoryWithHttpInfo(MemoryCreateDto memoryCreateDto,) async {
|
||||
// ignore: prefer_const_declarations
|
||||
final path = r'/memories';
|
||||
|
||||
// ignore: prefer_final_locals
|
||||
Object? postBody = memoryCreateDto;
|
||||
|
||||
final queryParams = <QueryParam>[];
|
||||
final headerParams = <String, String>{};
|
||||
final formParams = <String, String>{};
|
||||
|
||||
const contentTypes = <String>['application/json'];
|
||||
|
||||
|
||||
return apiClient.invokeAPI(
|
||||
path,
|
||||
'POST',
|
||||
queryParams,
|
||||
postBody,
|
||||
headerParams,
|
||||
formParams,
|
||||
contentTypes.isEmpty ? null : contentTypes.first,
|
||||
);
|
||||
}
|
||||
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [MemoryCreateDto] memoryCreateDto (required):
|
||||
Future<MemoryResponseDto?> createMemory(MemoryCreateDto memoryCreateDto,) async {
|
||||
final response = await createMemoryWithHttpInfo(memoryCreateDto,);
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||
// FormatException when trying to decode an empty string.
|
||||
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'MemoryResponseDto',) as MemoryResponseDto;
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Performs an HTTP 'DELETE /memories/{id}' operation and returns the [Response].
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [String] id (required):
|
||||
Future<Response> deleteMemoryWithHttpInfo(String id,) async {
|
||||
// ignore: prefer_const_declarations
|
||||
final path = r'/memories/{id}'
|
||||
.replaceAll('{id}', id);
|
||||
|
||||
// ignore: prefer_final_locals
|
||||
Object? postBody;
|
||||
|
||||
final queryParams = <QueryParam>[];
|
||||
final headerParams = <String, String>{};
|
||||
final formParams = <String, String>{};
|
||||
|
||||
const contentTypes = <String>[];
|
||||
|
||||
|
||||
return apiClient.invokeAPI(
|
||||
path,
|
||||
'DELETE',
|
||||
queryParams,
|
||||
postBody,
|
||||
headerParams,
|
||||
formParams,
|
||||
contentTypes.isEmpty ? null : contentTypes.first,
|
||||
);
|
||||
}
|
||||
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [String] id (required):
|
||||
Future<void> deleteMemory(String id,) async {
|
||||
final response = await deleteMemoryWithHttpInfo(id,);
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
}
|
||||
|
||||
/// Performs an HTTP 'GET /memories/{id}' operation and returns the [Response].
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [String] id (required):
|
||||
Future<Response> getMemoryWithHttpInfo(String id,) async {
|
||||
// ignore: prefer_const_declarations
|
||||
final path = r'/memories/{id}'
|
||||
.replaceAll('{id}', id);
|
||||
|
||||
// ignore: prefer_final_locals
|
||||
Object? postBody;
|
||||
|
||||
final queryParams = <QueryParam>[];
|
||||
final headerParams = <String, String>{};
|
||||
final formParams = <String, String>{};
|
||||
|
||||
const contentTypes = <String>[];
|
||||
|
||||
|
||||
return apiClient.invokeAPI(
|
||||
path,
|
||||
'GET',
|
||||
queryParams,
|
||||
postBody,
|
||||
headerParams,
|
||||
formParams,
|
||||
contentTypes.isEmpty ? null : contentTypes.first,
|
||||
);
|
||||
}
|
||||
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [String] id (required):
|
||||
Future<MemoryResponseDto?> getMemory(String id,) async {
|
||||
final response = await getMemoryWithHttpInfo(id,);
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||
// FormatException when trying to decode an empty string.
|
||||
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'MemoryResponseDto',) as MemoryResponseDto;
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Performs an HTTP 'DELETE /memories/{id}/assets' operation and returns the [Response].
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [String] id (required):
|
||||
///
|
||||
/// * [BulkIdsDto] bulkIdsDto (required):
|
||||
Future<Response> removeMemoryAssetsWithHttpInfo(String id, BulkIdsDto bulkIdsDto,) async {
|
||||
// ignore: prefer_const_declarations
|
||||
final path = r'/memories/{id}/assets'
|
||||
.replaceAll('{id}', id);
|
||||
|
||||
// ignore: prefer_final_locals
|
||||
Object? postBody = bulkIdsDto;
|
||||
|
||||
final queryParams = <QueryParam>[];
|
||||
final headerParams = <String, String>{};
|
||||
final formParams = <String, String>{};
|
||||
|
||||
const contentTypes = <String>['application/json'];
|
||||
|
||||
|
||||
return apiClient.invokeAPI(
|
||||
path,
|
||||
'DELETE',
|
||||
queryParams,
|
||||
postBody,
|
||||
headerParams,
|
||||
formParams,
|
||||
contentTypes.isEmpty ? null : contentTypes.first,
|
||||
);
|
||||
}
|
||||
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [String] id (required):
|
||||
///
|
||||
/// * [BulkIdsDto] bulkIdsDto (required):
|
||||
Future<List<BulkIdResponseDto>?> removeMemoryAssets(String id, BulkIdsDto bulkIdsDto,) async {
|
||||
final response = await removeMemoryAssetsWithHttpInfo(id, bulkIdsDto,);
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||
// FormatException when trying to decode an empty string.
|
||||
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||
final responseBody = await _decodeBodyBytes(response);
|
||||
return (await apiClient.deserializeAsync(responseBody, 'List<BulkIdResponseDto>') as List)
|
||||
.cast<BulkIdResponseDto>()
|
||||
.toList(growable: false);
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Performs an HTTP 'GET /memories' operation and returns the [Response].
|
||||
Future<Response> searchMemoriesWithHttpInfo() async {
|
||||
// ignore: prefer_const_declarations
|
||||
final path = r'/memories';
|
||||
|
||||
// ignore: prefer_final_locals
|
||||
Object? postBody;
|
||||
|
||||
final queryParams = <QueryParam>[];
|
||||
final headerParams = <String, String>{};
|
||||
final formParams = <String, String>{};
|
||||
|
||||
const contentTypes = <String>[];
|
||||
|
||||
|
||||
return apiClient.invokeAPI(
|
||||
path,
|
||||
'GET',
|
||||
queryParams,
|
||||
postBody,
|
||||
headerParams,
|
||||
formParams,
|
||||
contentTypes.isEmpty ? null : contentTypes.first,
|
||||
);
|
||||
}
|
||||
|
||||
Future<List<MemoryResponseDto>?> searchMemories() async {
|
||||
final response = await searchMemoriesWithHttpInfo();
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||
// FormatException when trying to decode an empty string.
|
||||
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||
final responseBody = await _decodeBodyBytes(response);
|
||||
return (await apiClient.deserializeAsync(responseBody, 'List<MemoryResponseDto>') as List)
|
||||
.cast<MemoryResponseDto>()
|
||||
.toList(growable: false);
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Performs an HTTP 'PUT /memories/{id}' operation and returns the [Response].
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [String] id (required):
|
||||
///
|
||||
/// * [MemoryUpdateDto] memoryUpdateDto (required):
|
||||
Future<Response> updateMemoryWithHttpInfo(String id, MemoryUpdateDto memoryUpdateDto,) async {
|
||||
// ignore: prefer_const_declarations
|
||||
final path = r'/memories/{id}'
|
||||
.replaceAll('{id}', id);
|
||||
|
||||
// ignore: prefer_final_locals
|
||||
Object? postBody = memoryUpdateDto;
|
||||
|
||||
final queryParams = <QueryParam>[];
|
||||
final headerParams = <String, String>{};
|
||||
final formParams = <String, String>{};
|
||||
|
||||
const contentTypes = <String>['application/json'];
|
||||
|
||||
|
||||
return apiClient.invokeAPI(
|
||||
path,
|
||||
'PUT',
|
||||
queryParams,
|
||||
postBody,
|
||||
headerParams,
|
||||
formParams,
|
||||
contentTypes.isEmpty ? null : contentTypes.first,
|
||||
);
|
||||
}
|
||||
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [String] id (required):
|
||||
///
|
||||
/// * [MemoryUpdateDto] memoryUpdateDto (required):
|
||||
Future<MemoryResponseDto?> updateMemory(String id, MemoryUpdateDto memoryUpdateDto,) async {
|
||||
final response = await updateMemoryWithHttpInfo(id, memoryUpdateDto,);
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||
// FormatException when trying to decode an empty string.
|
||||
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'MemoryResponseDto',) as MemoryResponseDto;
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
8
mobile/openapi/lib/api_client.dart
generated
8
mobile/openapi/lib/api_client.dart
generated
|
@ -336,8 +336,16 @@ class ApiClient {
|
|||
return MapMarkerResponseDto.fromJson(value);
|
||||
case 'MapTheme':
|
||||
return MapThemeTypeTransformer().decode(value);
|
||||
case 'MemoryCreateDto':
|
||||
return MemoryCreateDto.fromJson(value);
|
||||
case 'MemoryLaneResponseDto':
|
||||
return MemoryLaneResponseDto.fromJson(value);
|
||||
case 'MemoryResponseDto':
|
||||
return MemoryResponseDto.fromJson(value);
|
||||
case 'MemoryType':
|
||||
return MemoryTypeTypeTransformer().decode(value);
|
||||
case 'MemoryUpdateDto':
|
||||
return MemoryUpdateDto.fromJson(value);
|
||||
case 'MergePersonDto':
|
||||
return MergePersonDto.fromJson(value);
|
||||
case 'MetadataSearchDto':
|
||||
|
|
3
mobile/openapi/lib/api_helper.dart
generated
3
mobile/openapi/lib/api_helper.dart
generated
|
@ -97,6 +97,9 @@ String parameterToString(dynamic value) {
|
|||
if (value is MapTheme) {
|
||||
return MapThemeTypeTransformer().encode(value).toString();
|
||||
}
|
||||
if (value is MemoryType) {
|
||||
return MemoryTypeTypeTransformer().encode(value).toString();
|
||||
}
|
||||
if (value is ModelType) {
|
||||
return ModelTypeTypeTransformer().encode(value).toString();
|
||||
}
|
||||
|
|
157
mobile/openapi/lib/model/memory_create_dto.dart
generated
Normal file
157
mobile/openapi/lib/model/memory_create_dto.dart
generated
Normal file
|
@ -0,0 +1,157 @@
|
|||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.12
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
class MemoryCreateDto {
|
||||
/// Returns a new [MemoryCreateDto] instance.
|
||||
MemoryCreateDto({
|
||||
this.assetIds = const [],
|
||||
required this.data,
|
||||
this.isSaved,
|
||||
required this.memoryAt,
|
||||
this.seenAt,
|
||||
required this.type,
|
||||
});
|
||||
|
||||
List<String> assetIds;
|
||||
|
||||
Object data;
|
||||
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
/// does not include a default value (using the "default:" property), however, the generated
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
bool? isSaved;
|
||||
|
||||
DateTime memoryAt;
|
||||
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
/// does not include a default value (using the "default:" property), however, the generated
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
DateTime? seenAt;
|
||||
|
||||
MemoryType type;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is MemoryCreateDto &&
|
||||
_deepEquality.equals(other.assetIds, assetIds) &&
|
||||
other.data == data &&
|
||||
other.isSaved == isSaved &&
|
||||
other.memoryAt == memoryAt &&
|
||||
other.seenAt == seenAt &&
|
||||
other.type == type;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(assetIds.hashCode) +
|
||||
(data.hashCode) +
|
||||
(isSaved == null ? 0 : isSaved!.hashCode) +
|
||||
(memoryAt.hashCode) +
|
||||
(seenAt == null ? 0 : seenAt!.hashCode) +
|
||||
(type.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'MemoryCreateDto[assetIds=$assetIds, data=$data, isSaved=$isSaved, memoryAt=$memoryAt, seenAt=$seenAt, type=$type]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
json[r'assetIds'] = this.assetIds;
|
||||
json[r'data'] = this.data;
|
||||
if (this.isSaved != null) {
|
||||
json[r'isSaved'] = this.isSaved;
|
||||
} else {
|
||||
// json[r'isSaved'] = null;
|
||||
}
|
||||
json[r'memoryAt'] = this.memoryAt.toUtc().toIso8601String();
|
||||
if (this.seenAt != null) {
|
||||
json[r'seenAt'] = this.seenAt!.toUtc().toIso8601String();
|
||||
} else {
|
||||
// json[r'seenAt'] = null;
|
||||
}
|
||||
json[r'type'] = this.type;
|
||||
return json;
|
||||
}
|
||||
|
||||
/// Returns a new [MemoryCreateDto] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static MemoryCreateDto? fromJson(dynamic value) {
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return MemoryCreateDto(
|
||||
assetIds: json[r'assetIds'] is Iterable
|
||||
? (json[r'assetIds'] as Iterable).cast<String>().toList(growable: false)
|
||||
: const [],
|
||||
data: mapValueOfType<Object>(json, r'data')!,
|
||||
isSaved: mapValueOfType<bool>(json, r'isSaved'),
|
||||
memoryAt: mapDateTime(json, r'memoryAt', r'')!,
|
||||
seenAt: mapDateTime(json, r'seenAt', r''),
|
||||
type: MemoryType.fromJson(json[r'type'])!,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<MemoryCreateDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <MemoryCreateDto>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = MemoryCreateDto.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, MemoryCreateDto> mapFromJson(dynamic json) {
|
||||
final map = <String, MemoryCreateDto>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = MemoryCreateDto.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of MemoryCreateDto-objects as value to a dart map
|
||||
static Map<String, List<MemoryCreateDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<MemoryCreateDto>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = MemoryCreateDto.listFromJson(entry.value, growable: growable,);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'data',
|
||||
'memoryAt',
|
||||
'type',
|
||||
};
|
||||
}
|
||||
|
267
mobile/openapi/lib/model/memory_response_dto.dart
generated
Normal file
267
mobile/openapi/lib/model/memory_response_dto.dart
generated
Normal file
|
@ -0,0 +1,267 @@
|
|||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.12
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
class MemoryResponseDto {
|
||||
/// Returns a new [MemoryResponseDto] instance.
|
||||
MemoryResponseDto({
|
||||
this.assets = const [],
|
||||
required this.createdAt,
|
||||
required this.data,
|
||||
this.deletedAt,
|
||||
required this.id,
|
||||
required this.isSaved,
|
||||
required this.memoryAt,
|
||||
required this.ownerId,
|
||||
this.seenAt,
|
||||
required this.type,
|
||||
required this.updatedAt,
|
||||
});
|
||||
|
||||
List<AssetResponseDto> assets;
|
||||
|
||||
DateTime createdAt;
|
||||
|
||||
Object data;
|
||||
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
/// does not include a default value (using the "default:" property), however, the generated
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
DateTime? deletedAt;
|
||||
|
||||
String id;
|
||||
|
||||
bool isSaved;
|
||||
|
||||
DateTime memoryAt;
|
||||
|
||||
String ownerId;
|
||||
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
/// does not include a default value (using the "default:" property), however, the generated
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
DateTime? seenAt;
|
||||
|
||||
MemoryResponseDtoTypeEnum type;
|
||||
|
||||
DateTime updatedAt;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is MemoryResponseDto &&
|
||||
_deepEquality.equals(other.assets, assets) &&
|
||||
other.createdAt == createdAt &&
|
||||
other.data == data &&
|
||||
other.deletedAt == deletedAt &&
|
||||
other.id == id &&
|
||||
other.isSaved == isSaved &&
|
||||
other.memoryAt == memoryAt &&
|
||||
other.ownerId == ownerId &&
|
||||
other.seenAt == seenAt &&
|
||||
other.type == type &&
|
||||
other.updatedAt == updatedAt;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(assets.hashCode) +
|
||||
(createdAt.hashCode) +
|
||||
(data.hashCode) +
|
||||
(deletedAt == null ? 0 : deletedAt!.hashCode) +
|
||||
(id.hashCode) +
|
||||
(isSaved.hashCode) +
|
||||
(memoryAt.hashCode) +
|
||||
(ownerId.hashCode) +
|
||||
(seenAt == null ? 0 : seenAt!.hashCode) +
|
||||
(type.hashCode) +
|
||||
(updatedAt.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'MemoryResponseDto[assets=$assets, createdAt=$createdAt, data=$data, deletedAt=$deletedAt, id=$id, isSaved=$isSaved, memoryAt=$memoryAt, ownerId=$ownerId, seenAt=$seenAt, type=$type, updatedAt=$updatedAt]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
json[r'assets'] = this.assets;
|
||||
json[r'createdAt'] = this.createdAt.toUtc().toIso8601String();
|
||||
json[r'data'] = this.data;
|
||||
if (this.deletedAt != null) {
|
||||
json[r'deletedAt'] = this.deletedAt!.toUtc().toIso8601String();
|
||||
} else {
|
||||
// json[r'deletedAt'] = null;
|
||||
}
|
||||
json[r'id'] = this.id;
|
||||
json[r'isSaved'] = this.isSaved;
|
||||
json[r'memoryAt'] = this.memoryAt.toUtc().toIso8601String();
|
||||
json[r'ownerId'] = this.ownerId;
|
||||
if (this.seenAt != null) {
|
||||
json[r'seenAt'] = this.seenAt!.toUtc().toIso8601String();
|
||||
} else {
|
||||
// json[r'seenAt'] = null;
|
||||
}
|
||||
json[r'type'] = this.type;
|
||||
json[r'updatedAt'] = this.updatedAt.toUtc().toIso8601String();
|
||||
return json;
|
||||
}
|
||||
|
||||
/// Returns a new [MemoryResponseDto] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static MemoryResponseDto? fromJson(dynamic value) {
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return MemoryResponseDto(
|
||||
assets: AssetResponseDto.listFromJson(json[r'assets']),
|
||||
createdAt: mapDateTime(json, r'createdAt', r'')!,
|
||||
data: mapValueOfType<Object>(json, r'data')!,
|
||||
deletedAt: mapDateTime(json, r'deletedAt', r''),
|
||||
id: mapValueOfType<String>(json, r'id')!,
|
||||
isSaved: mapValueOfType<bool>(json, r'isSaved')!,
|
||||
memoryAt: mapDateTime(json, r'memoryAt', r'')!,
|
||||
ownerId: mapValueOfType<String>(json, r'ownerId')!,
|
||||
seenAt: mapDateTime(json, r'seenAt', r''),
|
||||
type: MemoryResponseDtoTypeEnum.fromJson(json[r'type'])!,
|
||||
updatedAt: mapDateTime(json, r'updatedAt', r'')!,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<MemoryResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <MemoryResponseDto>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = MemoryResponseDto.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, MemoryResponseDto> mapFromJson(dynamic json) {
|
||||
final map = <String, MemoryResponseDto>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = MemoryResponseDto.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of MemoryResponseDto-objects as value to a dart map
|
||||
static Map<String, List<MemoryResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<MemoryResponseDto>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = MemoryResponseDto.listFromJson(entry.value, growable: growable,);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'assets',
|
||||
'createdAt',
|
||||
'data',
|
||||
'id',
|
||||
'isSaved',
|
||||
'memoryAt',
|
||||
'ownerId',
|
||||
'type',
|
||||
'updatedAt',
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
class MemoryResponseDtoTypeEnum {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const MemoryResponseDtoTypeEnum._(this.value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const onThisDay = MemoryResponseDtoTypeEnum._(r'on_this_day');
|
||||
|
||||
/// List of all possible values in this [enum][MemoryResponseDtoTypeEnum].
|
||||
static const values = <MemoryResponseDtoTypeEnum>[
|
||||
onThisDay,
|
||||
];
|
||||
|
||||
static MemoryResponseDtoTypeEnum? fromJson(dynamic value) => MemoryResponseDtoTypeEnumTypeTransformer().decode(value);
|
||||
|
||||
static List<MemoryResponseDtoTypeEnum> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <MemoryResponseDtoTypeEnum>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = MemoryResponseDtoTypeEnum.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
}
|
||||
|
||||
/// Transformation class that can [encode] an instance of [MemoryResponseDtoTypeEnum] to String,
|
||||
/// and [decode] dynamic data back to [MemoryResponseDtoTypeEnum].
|
||||
class MemoryResponseDtoTypeEnumTypeTransformer {
|
||||
factory MemoryResponseDtoTypeEnumTypeTransformer() => _instance ??= const MemoryResponseDtoTypeEnumTypeTransformer._();
|
||||
|
||||
const MemoryResponseDtoTypeEnumTypeTransformer._();
|
||||
|
||||
String encode(MemoryResponseDtoTypeEnum data) => data.value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a MemoryResponseDtoTypeEnum.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
/// cannot be decoded successfully, then an [UnimplementedError] is thrown.
|
||||
///
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
MemoryResponseDtoTypeEnum? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'on_this_day': return MemoryResponseDtoTypeEnum.onThisDay;
|
||||
default:
|
||||
if (!allowNull) {
|
||||
throw ArgumentError('Unknown enum value to decode: $data');
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [MemoryResponseDtoTypeEnumTypeTransformer] instance.
|
||||
static MemoryResponseDtoTypeEnumTypeTransformer? _instance;
|
||||
}
|
||||
|
||||
|
82
mobile/openapi/lib/model/memory_type.dart
generated
Normal file
82
mobile/openapi/lib/model/memory_type.dart
generated
Normal file
|
@ -0,0 +1,82 @@
|
|||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.12
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
|
||||
class MemoryType {
|
||||
/// Instantiate a new enum with the provided [value].
|
||||
const MemoryType._(this.value);
|
||||
|
||||
/// The underlying value of this enum member.
|
||||
final String value;
|
||||
|
||||
@override
|
||||
String toString() => value;
|
||||
|
||||
String toJson() => value;
|
||||
|
||||
static const onThisDay = MemoryType._(r'on_this_day');
|
||||
|
||||
/// List of all possible values in this [enum][MemoryType].
|
||||
static const values = <MemoryType>[
|
||||
onThisDay,
|
||||
];
|
||||
|
||||
static MemoryType? fromJson(dynamic value) => MemoryTypeTypeTransformer().decode(value);
|
||||
|
||||
static List<MemoryType> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <MemoryType>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = MemoryType.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
}
|
||||
|
||||
/// Transformation class that can [encode] an instance of [MemoryType] to String,
|
||||
/// and [decode] dynamic data back to [MemoryType].
|
||||
class MemoryTypeTypeTransformer {
|
||||
factory MemoryTypeTypeTransformer() => _instance ??= const MemoryTypeTypeTransformer._();
|
||||
|
||||
const MemoryTypeTypeTransformer._();
|
||||
|
||||
String encode(MemoryType data) => data.value;
|
||||
|
||||
/// Decodes a [dynamic value][data] to a MemoryType.
|
||||
///
|
||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||
/// cannot be decoded successfully, then an [UnimplementedError] is thrown.
|
||||
///
|
||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||
/// and users are still using an old app with the old code.
|
||||
MemoryType? decode(dynamic data, {bool allowNull = true}) {
|
||||
if (data != null) {
|
||||
switch (data) {
|
||||
case r'on_this_day': return MemoryType.onThisDay;
|
||||
default:
|
||||
if (!allowNull) {
|
||||
throw ArgumentError('Unknown enum value to decode: $data');
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Singleton [MemoryTypeTypeTransformer] instance.
|
||||
static MemoryTypeTypeTransformer? _instance;
|
||||
}
|
||||
|
141
mobile/openapi/lib/model/memory_update_dto.dart
generated
Normal file
141
mobile/openapi/lib/model/memory_update_dto.dart
generated
Normal file
|
@ -0,0 +1,141 @@
|
|||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.12
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
part of openapi.api;
|
||||
|
||||
class MemoryUpdateDto {
|
||||
/// Returns a new [MemoryUpdateDto] instance.
|
||||
MemoryUpdateDto({
|
||||
this.isSaved,
|
||||
this.memoryAt,
|
||||
this.seenAt,
|
||||
});
|
||||
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
/// does not include a default value (using the "default:" property), however, the generated
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
bool? isSaved;
|
||||
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
/// does not include a default value (using the "default:" property), however, the generated
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
DateTime? memoryAt;
|
||||
|
||||
///
|
||||
/// Please note: This property should have been non-nullable! Since the specification file
|
||||
/// does not include a default value (using the "default:" property), however, the generated
|
||||
/// source code must fall back to having a nullable type.
|
||||
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||
///
|
||||
DateTime? seenAt;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is MemoryUpdateDto &&
|
||||
other.isSaved == isSaved &&
|
||||
other.memoryAt == memoryAt &&
|
||||
other.seenAt == seenAt;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(isSaved == null ? 0 : isSaved!.hashCode) +
|
||||
(memoryAt == null ? 0 : memoryAt!.hashCode) +
|
||||
(seenAt == null ? 0 : seenAt!.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'MemoryUpdateDto[isSaved=$isSaved, memoryAt=$memoryAt, seenAt=$seenAt]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
if (this.isSaved != null) {
|
||||
json[r'isSaved'] = this.isSaved;
|
||||
} else {
|
||||
// json[r'isSaved'] = null;
|
||||
}
|
||||
if (this.memoryAt != null) {
|
||||
json[r'memoryAt'] = this.memoryAt!.toUtc().toIso8601String();
|
||||
} else {
|
||||
// json[r'memoryAt'] = null;
|
||||
}
|
||||
if (this.seenAt != null) {
|
||||
json[r'seenAt'] = this.seenAt!.toUtc().toIso8601String();
|
||||
} else {
|
||||
// json[r'seenAt'] = null;
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
/// Returns a new [MemoryUpdateDto] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static MemoryUpdateDto? fromJson(dynamic value) {
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return MemoryUpdateDto(
|
||||
isSaved: mapValueOfType<bool>(json, r'isSaved'),
|
||||
memoryAt: mapDateTime(json, r'memoryAt', r''),
|
||||
seenAt: mapDateTime(json, r'seenAt', r''),
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<MemoryUpdateDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <MemoryUpdateDto>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = MemoryUpdateDto.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, MemoryUpdateDto> mapFromJson(dynamic json) {
|
||||
final map = <String, MemoryUpdateDto>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = MemoryUpdateDto.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of MemoryUpdateDto-objects as value to a dart map
|
||||
static Map<String, List<MemoryUpdateDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<MemoryUpdateDto>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = MemoryUpdateDto.listFromJson(entry.value, growable: growable,);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
};
|
||||
}
|
||||
|
56
mobile/openapi/test/memory_api_test.dart
generated
Normal file
56
mobile/openapi/test/memory_api_test.dart
generated
Normal file
|
@ -0,0 +1,56 @@
|
|||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.12
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
import 'package:openapi/api.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
|
||||
/// tests for MemoryApi
|
||||
void main() {
|
||||
// final instance = MemoryApi();
|
||||
|
||||
group('tests for MemoryApi', () {
|
||||
//Future<List<BulkIdResponseDto>> addMemoryAssets(String id, BulkIdsDto bulkIdsDto) async
|
||||
test('test addMemoryAssets', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
//Future<MemoryResponseDto> createMemory(MemoryCreateDto memoryCreateDto) async
|
||||
test('test createMemory', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
//Future deleteMemory(String id) async
|
||||
test('test deleteMemory', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
//Future<MemoryResponseDto> getMemory(String id) async
|
||||
test('test getMemory', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
//Future<List<BulkIdResponseDto>> removeMemoryAssets(String id, BulkIdsDto bulkIdsDto) async
|
||||
test('test removeMemoryAssets', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
//Future<List<MemoryResponseDto>> searchMemories() async
|
||||
test('test searchMemories', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
//Future<MemoryResponseDto> updateMemory(String id, MemoryUpdateDto memoryUpdateDto) async
|
||||
test('test updateMemory', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
});
|
||||
}
|
52
mobile/openapi/test/memory_create_dto_test.dart
generated
Normal file
52
mobile/openapi/test/memory_create_dto_test.dart
generated
Normal file
|
@ -0,0 +1,52 @@
|
|||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.12
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
import 'package:openapi/api.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
// tests for MemoryCreateDto
|
||||
void main() {
|
||||
// final instance = MemoryCreateDto();
|
||||
|
||||
group('test MemoryCreateDto', () {
|
||||
// List<String> assetIds (default value: const [])
|
||||
test('to test the property `assetIds`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// Object data
|
||||
test('to test the property `data`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// bool isSaved
|
||||
test('to test the property `isSaved`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// DateTime memoryAt
|
||||
test('to test the property `memoryAt`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// DateTime seenAt
|
||||
test('to test the property `seenAt`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// MemoryType type
|
||||
test('to test the property `type`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
}
|
77
mobile/openapi/test/memory_response_dto_test.dart
generated
Normal file
77
mobile/openapi/test/memory_response_dto_test.dart
generated
Normal file
|
@ -0,0 +1,77 @@
|
|||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.12
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
import 'package:openapi/api.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
// tests for MemoryResponseDto
|
||||
void main() {
|
||||
// final instance = MemoryResponseDto();
|
||||
|
||||
group('test MemoryResponseDto', () {
|
||||
// List<AssetResponseDto> assets (default value: const [])
|
||||
test('to test the property `assets`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// DateTime createdAt
|
||||
test('to test the property `createdAt`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// Object data
|
||||
test('to test the property `data`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// DateTime deletedAt
|
||||
test('to test the property `deletedAt`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// String id
|
||||
test('to test the property `id`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// bool isSaved
|
||||
test('to test the property `isSaved`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// DateTime memoryAt
|
||||
test('to test the property `memoryAt`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// String ownerId
|
||||
test('to test the property `ownerId`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// DateTime seenAt
|
||||
test('to test the property `seenAt`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// String type
|
||||
test('to test the property `type`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// DateTime updatedAt
|
||||
test('to test the property `updatedAt`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
}
|
21
mobile/openapi/test/memory_type_test.dart
generated
Normal file
21
mobile/openapi/test/memory_type_test.dart
generated
Normal file
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.12
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
import 'package:openapi/api.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
// tests for MemoryType
|
||||
void main() {
|
||||
|
||||
group('test MemoryType', () {
|
||||
|
||||
});
|
||||
|
||||
}
|
37
mobile/openapi/test/memory_update_dto_test.dart
generated
Normal file
37
mobile/openapi/test/memory_update_dto_test.dart
generated
Normal file
|
@ -0,0 +1,37 @@
|
|||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.12
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
import 'package:openapi/api.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
// tests for MemoryUpdateDto
|
||||
void main() {
|
||||
// final instance = MemoryUpdateDto();
|
||||
|
||||
group('test MemoryUpdateDto', () {
|
||||
// bool isSaved
|
||||
test('to test the property `isSaved`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// DateTime memoryAt
|
||||
test('to test the property `memoryAt`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// DateTime seenAt
|
||||
test('to test the property `seenAt`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
}
|
|
@ -3435,6 +3435,314 @@
|
|||
]
|
||||
}
|
||||
},
|
||||
"/memories": {
|
||||
"get": {
|
||||
"operationId": "searchMemories",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/MemoryResponseDto"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearer": []
|
||||
},
|
||||
{
|
||||
"cookie": []
|
||||
},
|
||||
{
|
||||
"api_key": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Memory"
|
||||
]
|
||||
},
|
||||
"post": {
|
||||
"operationId": "createMemory",
|
||||
"parameters": [],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/MemoryCreateDto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": true
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/MemoryResponseDto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearer": []
|
||||
},
|
||||
{
|
||||
"cookie": []
|
||||
},
|
||||
{
|
||||
"api_key": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Memory"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/memories/{id}": {
|
||||
"delete": {
|
||||
"operationId": "deleteMemory",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearer": []
|
||||
},
|
||||
{
|
||||
"cookie": []
|
||||
},
|
||||
{
|
||||
"api_key": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Memory"
|
||||
]
|
||||
},
|
||||
"get": {
|
||||
"operationId": "getMemory",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/MemoryResponseDto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearer": []
|
||||
},
|
||||
{
|
||||
"cookie": []
|
||||
},
|
||||
{
|
||||
"api_key": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Memory"
|
||||
]
|
||||
},
|
||||
"put": {
|
||||
"operationId": "updateMemory",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/MemoryUpdateDto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": true
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/MemoryResponseDto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearer": []
|
||||
},
|
||||
{
|
||||
"cookie": []
|
||||
},
|
||||
{
|
||||
"api_key": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Memory"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/memories/{id}/assets": {
|
||||
"delete": {
|
||||
"operationId": "removeMemoryAssets",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/BulkIdsDto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": true
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/BulkIdResponseDto"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearer": []
|
||||
},
|
||||
{
|
||||
"cookie": []
|
||||
},
|
||||
{
|
||||
"api_key": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Memory"
|
||||
]
|
||||
},
|
||||
"put": {
|
||||
"operationId": "addMemoryAssets",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/BulkIdsDto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": true
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/BulkIdResponseDto"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearer": []
|
||||
},
|
||||
{
|
||||
"cookie": []
|
||||
},
|
||||
{
|
||||
"api_key": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Memory"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/oauth/authorize": {
|
||||
"post": {
|
||||
"operationId": "startOAuth",
|
||||
|
@ -8451,6 +8759,40 @@
|
|||
],
|
||||
"type": "string"
|
||||
},
|
||||
"MemoryCreateDto": {
|
||||
"properties": {
|
||||
"assetIds": {
|
||||
"items": {
|
||||
"format": "uuid",
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"data": {
|
||||
"type": "object"
|
||||
},
|
||||
"isSaved": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"memoryAt": {
|
||||
"format": "date-time",
|
||||
"type": "string"
|
||||
},
|
||||
"seenAt": {
|
||||
"format": "date-time",
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"$ref": "#/components/schemas/MemoryType"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"data",
|
||||
"memoryAt",
|
||||
"type"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"MemoryLaneResponseDto": {
|
||||
"properties": {
|
||||
"assets": {
|
||||
|
@ -8474,6 +8816,88 @@
|
|||
],
|
||||
"type": "object"
|
||||
},
|
||||
"MemoryResponseDto": {
|
||||
"properties": {
|
||||
"assets": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/AssetResponseDto"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"createdAt": {
|
||||
"format": "date-time",
|
||||
"type": "string"
|
||||
},
|
||||
"data": {
|
||||
"type": "object"
|
||||
},
|
||||
"deletedAt": {
|
||||
"format": "date-time",
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"isSaved": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"memoryAt": {
|
||||
"format": "date-time",
|
||||
"type": "string"
|
||||
},
|
||||
"ownerId": {
|
||||
"type": "string"
|
||||
},
|
||||
"seenAt": {
|
||||
"format": "date-time",
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"on_this_day"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"updatedAt": {
|
||||
"format": "date-time",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"assets",
|
||||
"createdAt",
|
||||
"data",
|
||||
"id",
|
||||
"isSaved",
|
||||
"memoryAt",
|
||||
"ownerId",
|
||||
"type",
|
||||
"updatedAt"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"MemoryType": {
|
||||
"enum": [
|
||||
"on_this_day"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"MemoryUpdateDto": {
|
||||
"properties": {
|
||||
"isSaved": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"memoryAt": {
|
||||
"format": "date-time",
|
||||
"type": "string"
|
||||
},
|
||||
"seenAt": {
|
||||
"format": "date-time",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"MergePersonDto": {
|
||||
"properties": {
|
||||
"ids": {
|
||||
|
|
|
@ -494,6 +494,32 @@ export type ValidateLibraryImportPathResponseDto = {
|
|||
export type ValidateLibraryResponseDto = {
|
||||
importPaths?: ValidateLibraryImportPathResponseDto[];
|
||||
};
|
||||
export type MemoryResponseDto = {
|
||||
assets: AssetResponseDto[];
|
||||
createdAt: string;
|
||||
data: object;
|
||||
deletedAt?: string;
|
||||
id: string;
|
||||
isSaved: boolean;
|
||||
memoryAt: string;
|
||||
ownerId: string;
|
||||
seenAt?: string;
|
||||
"type": Type2;
|
||||
updatedAt: string;
|
||||
};
|
||||
export type MemoryCreateDto = {
|
||||
assetIds?: string[];
|
||||
data: object;
|
||||
isSaved?: boolean;
|
||||
memoryAt: string;
|
||||
seenAt?: string;
|
||||
"type": MemoryType;
|
||||
};
|
||||
export type MemoryUpdateDto = {
|
||||
isSaved?: boolean;
|
||||
memoryAt?: string;
|
||||
seenAt?: string;
|
||||
};
|
||||
export type OAuthConfigDto = {
|
||||
redirectUri: string;
|
||||
};
|
||||
|
@ -1908,6 +1934,83 @@ export function validate({ id, validateLibraryDto }: {
|
|||
body: validateLibraryDto
|
||||
})));
|
||||
}
|
||||
export function searchMemories(opts?: Oazapfts.RequestOpts) {
|
||||
return oazapfts.ok(oazapfts.fetchJson<{
|
||||
status: 200;
|
||||
data: MemoryResponseDto[];
|
||||
}>("/memories", {
|
||||
...opts
|
||||
}));
|
||||
}
|
||||
export function createMemory({ memoryCreateDto }: {
|
||||
memoryCreateDto: MemoryCreateDto;
|
||||
}, opts?: Oazapfts.RequestOpts) {
|
||||
return oazapfts.ok(oazapfts.fetchJson<{
|
||||
status: 201;
|
||||
data: MemoryResponseDto;
|
||||
}>("/memories", oazapfts.json({
|
||||
...opts,
|
||||
method: "POST",
|
||||
body: memoryCreateDto
|
||||
})));
|
||||
}
|
||||
export function deleteMemory({ id }: {
|
||||
id: string;
|
||||
}, opts?: Oazapfts.RequestOpts) {
|
||||
return oazapfts.ok(oazapfts.fetchText(`/memories/${encodeURIComponent(id)}`, {
|
||||
...opts,
|
||||
method: "DELETE"
|
||||
}));
|
||||
}
|
||||
export function getMemory({ id }: {
|
||||
id: string;
|
||||
}, opts?: Oazapfts.RequestOpts) {
|
||||
return oazapfts.ok(oazapfts.fetchJson<{
|
||||
status: 200;
|
||||
data: MemoryResponseDto;
|
||||
}>(`/memories/${encodeURIComponent(id)}`, {
|
||||
...opts
|
||||
}));
|
||||
}
|
||||
export function updateMemory({ id, memoryUpdateDto }: {
|
||||
id: string;
|
||||
memoryUpdateDto: MemoryUpdateDto;
|
||||
}, opts?: Oazapfts.RequestOpts) {
|
||||
return oazapfts.ok(oazapfts.fetchJson<{
|
||||
status: 200;
|
||||
data: MemoryResponseDto;
|
||||
}>(`/memories/${encodeURIComponent(id)}`, oazapfts.json({
|
||||
...opts,
|
||||
method: "PUT",
|
||||
body: memoryUpdateDto
|
||||
})));
|
||||
}
|
||||
export function removeMemoryAssets({ id, bulkIdsDto }: {
|
||||
id: string;
|
||||
bulkIdsDto: BulkIdsDto;
|
||||
}, opts?: Oazapfts.RequestOpts) {
|
||||
return oazapfts.ok(oazapfts.fetchJson<{
|
||||
status: 200;
|
||||
data: BulkIdResponseDto[];
|
||||
}>(`/memories/${encodeURIComponent(id)}/assets`, oazapfts.json({
|
||||
...opts,
|
||||
method: "DELETE",
|
||||
body: bulkIdsDto
|
||||
})));
|
||||
}
|
||||
export function addMemoryAssets({ id, bulkIdsDto }: {
|
||||
id: string;
|
||||
bulkIdsDto: BulkIdsDto;
|
||||
}, opts?: Oazapfts.RequestOpts) {
|
||||
return oazapfts.ok(oazapfts.fetchJson<{
|
||||
status: 200;
|
||||
data: BulkIdResponseDto[];
|
||||
}>(`/memories/${encodeURIComponent(id)}/assets`, oazapfts.json({
|
||||
...opts,
|
||||
method: "PUT",
|
||||
body: bulkIdsDto
|
||||
})));
|
||||
}
|
||||
export function startOAuth({ oAuthConfigDto }: {
|
||||
oAuthConfigDto: OAuthConfigDto;
|
||||
}, opts?: Oazapfts.RequestOpts) {
|
||||
|
@ -2842,6 +2945,12 @@ export enum LibraryType {
|
|||
Upload = "UPLOAD",
|
||||
External = "EXTERNAL"
|
||||
}
|
||||
export enum Type2 {
|
||||
OnThisDay = "on_this_day"
|
||||
}
|
||||
export enum MemoryType {
|
||||
OnThisDay = "on_this_day"
|
||||
}
|
||||
export enum SearchSuggestionType {
|
||||
Country = "country",
|
||||
State = "state",
|
||||
|
|
|
@ -10,6 +10,7 @@ import { DownloadController } from 'src/controllers/download.controller';
|
|||
import { FaceController } from 'src/controllers/face.controller';
|
||||
import { JobController } from 'src/controllers/job.controller';
|
||||
import { LibraryController } from 'src/controllers/library.controller';
|
||||
import { MemoryController } from 'src/controllers/memory.controller';
|
||||
import { OAuthController } from 'src/controllers/oauth.controller';
|
||||
import { PartnerController } from 'src/controllers/partner.controller';
|
||||
import { PersonController } from 'src/controllers/person.controller';
|
||||
|
@ -36,6 +37,7 @@ export const controllers = [
|
|||
FaceController,
|
||||
JobController,
|
||||
LibraryController,
|
||||
MemoryController,
|
||||
OAuthController,
|
||||
PartnerController,
|
||||
SearchController,
|
||||
|
|
64
server/src/controllers/memory.controller.ts
Normal file
64
server/src/controllers/memory.controller.ts
Normal file
|
@ -0,0 +1,64 @@
|
|||
import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Put } from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { BulkIdResponseDto, BulkIdsDto } from 'src/dtos/asset-ids.response.dto';
|
||||
import { AuthDto } from 'src/dtos/auth.dto';
|
||||
import { MemoryCreateDto, MemoryResponseDto, MemoryUpdateDto } from 'src/dtos/memory.dto';
|
||||
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
||||
import { MemoryService } from 'src/services/memory.service';
|
||||
import { UUIDParamDto } from 'src/validation';
|
||||
|
||||
@ApiTags('Memory')
|
||||
@Controller('memories')
|
||||
@Authenticated()
|
||||
export class MemoryController {
|
||||
constructor(private service: MemoryService) {}
|
||||
|
||||
@Get()
|
||||
searchMemories(@Auth() auth: AuthDto): Promise<MemoryResponseDto[]> {
|
||||
return this.service.search(auth);
|
||||
}
|
||||
|
||||
@Post()
|
||||
createMemory(@Auth() auth: AuthDto, @Body() dto: MemoryCreateDto): Promise<MemoryResponseDto> {
|
||||
return this.service.create(auth, dto);
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
getMemory(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<MemoryResponseDto> {
|
||||
return this.service.get(auth, id);
|
||||
}
|
||||
|
||||
@Put(':id')
|
||||
updateMemory(
|
||||
@Auth() auth: AuthDto,
|
||||
@Param() { id }: UUIDParamDto,
|
||||
@Body() dto: MemoryUpdateDto,
|
||||
): Promise<MemoryResponseDto> {
|
||||
return this.service.update(auth, id, dto);
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
@HttpCode(HttpStatus.NO_CONTENT)
|
||||
deleteMemory(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<void> {
|
||||
return this.service.remove(auth, id);
|
||||
}
|
||||
|
||||
@Put(':id/assets')
|
||||
addMemoryAssets(
|
||||
@Auth() auth: AuthDto,
|
||||
@Param() { id }: UUIDParamDto,
|
||||
@Body() dto: BulkIdsDto,
|
||||
): Promise<BulkIdResponseDto[]> {
|
||||
return this.service.addAssets(auth, id, dto);
|
||||
}
|
||||
|
||||
@Delete(':id/assets')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
removeMemoryAssets(
|
||||
@Auth() auth: AuthDto,
|
||||
@Body() dto: BulkIdsDto,
|
||||
@Param() { id }: UUIDParamDto,
|
||||
): Promise<BulkIdResponseDto[]> {
|
||||
return this.service.removeAssets(auth, id, dto);
|
||||
}
|
||||
}
|
|
@ -33,6 +33,10 @@ export enum Permission {
|
|||
TIMELINE_READ = 'timeline.read',
|
||||
TIMELINE_DOWNLOAD = 'timeline.download',
|
||||
|
||||
MEMORY_READ = 'memory.read',
|
||||
MEMORY_WRITE = 'memory.write',
|
||||
MEMORY_DELETE = 'memory.delete',
|
||||
|
||||
PERSON_READ = 'person.read',
|
||||
PERSON_WRITE = 'person.write',
|
||||
PERSON_MERGE = 'person.merge',
|
||||
|
@ -259,6 +263,18 @@ export class AccessCore {
|
|||
return ids.has(auth.user.id) ? new Set([auth.user.id]) : new Set();
|
||||
}
|
||||
|
||||
case Permission.MEMORY_READ: {
|
||||
return this.repository.memory.checkOwnerAccess(auth.user.id, ids);
|
||||
}
|
||||
|
||||
case Permission.MEMORY_WRITE: {
|
||||
return this.repository.memory.checkOwnerAccess(auth.user.id, ids);
|
||||
}
|
||||
|
||||
case Permission.MEMORY_DELETE: {
|
||||
return this.repository.memory.checkOwnerAccess(auth.user.id, ids);
|
||||
}
|
||||
|
||||
case Permission.PERSON_READ: {
|
||||
return await this.repository.person.checkOwnerAccess(auth.user.id, ids);
|
||||
}
|
||||
|
|
84
server/src/dtos/memory.dto.ts
Normal file
84
server/src/dtos/memory.dto.ts
Normal file
|
@ -0,0 +1,84 @@
|
|||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { Type } from 'class-transformer';
|
||||
import { IsEnum, IsInt, IsObject, IsPositive, ValidateNested } from 'class-validator';
|
||||
import { AssetResponseDto, mapAsset } from 'src/dtos/asset-response.dto';
|
||||
import { MemoryEntity, MemoryType } from 'src/entities/memory.entity';
|
||||
import { ValidateBoolean, ValidateDate, ValidateUUID } from 'src/validation';
|
||||
|
||||
class MemoryBaseDto {
|
||||
@ValidateBoolean({ optional: true })
|
||||
isSaved?: boolean;
|
||||
|
||||
@ValidateDate({ optional: true })
|
||||
seenAt?: Date;
|
||||
}
|
||||
|
||||
class OnThisDayDto {
|
||||
@IsInt()
|
||||
@IsPositive()
|
||||
year!: number;
|
||||
}
|
||||
|
||||
type MemoryData = OnThisDayDto;
|
||||
|
||||
export class MemoryUpdateDto extends MemoryBaseDto {
|
||||
@ValidateDate({ optional: true })
|
||||
memoryAt?: Date;
|
||||
}
|
||||
|
||||
export class MemoryCreateDto extends MemoryBaseDto {
|
||||
@IsEnum(MemoryType)
|
||||
@ApiProperty({ enum: MemoryType, enumName: 'MemoryType' })
|
||||
type!: MemoryType;
|
||||
|
||||
@IsObject()
|
||||
@ValidateNested()
|
||||
@Type((options) => {
|
||||
switch (options?.object.type) {
|
||||
case MemoryType.ON_THIS_DAY: {
|
||||
return OnThisDayDto;
|
||||
}
|
||||
|
||||
default: {
|
||||
return Object;
|
||||
}
|
||||
}
|
||||
})
|
||||
data!: MemoryData;
|
||||
|
||||
@ValidateDate()
|
||||
memoryAt!: Date;
|
||||
|
||||
@ValidateUUID({ optional: true, each: true })
|
||||
assetIds?: string[];
|
||||
}
|
||||
|
||||
export class MemoryResponseDto {
|
||||
id!: string;
|
||||
createdAt!: Date;
|
||||
updatedAt!: Date;
|
||||
deletedAt?: Date;
|
||||
memoryAt!: Date;
|
||||
seenAt?: Date;
|
||||
ownerId!: string;
|
||||
type!: MemoryType;
|
||||
data!: MemoryData;
|
||||
isSaved!: boolean;
|
||||
assets!: AssetResponseDto[];
|
||||
}
|
||||
|
||||
export const mapMemory = (entity: MemoryEntity): MemoryResponseDto => {
|
||||
return {
|
||||
id: entity.id,
|
||||
createdAt: entity.createdAt,
|
||||
updatedAt: entity.updatedAt,
|
||||
deletedAt: entity.deletedAt,
|
||||
memoryAt: entity.memoryAt,
|
||||
seenAt: entity.seenAt,
|
||||
ownerId: entity.ownerId,
|
||||
type: entity.type,
|
||||
data: entity.data,
|
||||
isSaved: entity.isSaved,
|
||||
assets: entity.assets.map((asset) => mapAsset(asset)),
|
||||
};
|
||||
};
|
|
@ -9,6 +9,7 @@ import { AuditEntity } from 'src/entities/audit.entity';
|
|||
import { ExifEntity } from 'src/entities/exif.entity';
|
||||
import { GeodataPlacesEntity } from 'src/entities/geodata-places.entity';
|
||||
import { LibraryEntity } from 'src/entities/library.entity';
|
||||
import { MemoryEntity } from 'src/entities/memory.entity';
|
||||
import { MoveEntity } from 'src/entities/move.entity';
|
||||
import { PartnerEntity } from 'src/entities/partner.entity';
|
||||
import { PersonEntity } from 'src/entities/person.entity';
|
||||
|
@ -32,6 +33,7 @@ export const entities = [
|
|||
AuditEntity,
|
||||
ExifEntity,
|
||||
GeodataPlacesEntity,
|
||||
MemoryEntity,
|
||||
MoveEntity,
|
||||
PartnerEntity,
|
||||
PersonEntity,
|
||||
|
|
67
server/src/entities/memory.entity.ts
Normal file
67
server/src/entities/memory.entity.ts
Normal file
|
@ -0,0 +1,67 @@
|
|||
import { AssetEntity } from 'src/entities/asset.entity';
|
||||
import { UserEntity } from 'src/entities/user.entity';
|
||||
import {
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
DeleteDateColumn,
|
||||
Entity,
|
||||
JoinTable,
|
||||
ManyToMany,
|
||||
ManyToOne,
|
||||
PrimaryGeneratedColumn,
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm';
|
||||
|
||||
export enum MemoryType {
|
||||
/** pictures taken on this day X years ago */
|
||||
ON_THIS_DAY = 'on_this_day',
|
||||
}
|
||||
|
||||
export type OnThisDayData = { year: number };
|
||||
|
||||
export interface MemoryData {
|
||||
[MemoryType.ON_THIS_DAY]: OnThisDayData;
|
||||
}
|
||||
|
||||
@Entity('memories')
|
||||
export class MemoryEntity<T extends MemoryType = MemoryType> {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id!: string;
|
||||
|
||||
@CreateDateColumn({ type: 'timestamptz' })
|
||||
createdAt!: Date;
|
||||
|
||||
@UpdateDateColumn({ type: 'timestamptz' })
|
||||
updatedAt!: Date;
|
||||
|
||||
@DeleteDateColumn({ type: 'timestamptz' })
|
||||
deletedAt?: Date;
|
||||
|
||||
@ManyToOne(() => UserEntity, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: false })
|
||||
owner!: UserEntity;
|
||||
|
||||
@Column()
|
||||
ownerId!: string;
|
||||
|
||||
@Column()
|
||||
type!: T;
|
||||
|
||||
@Column({ type: 'jsonb' })
|
||||
data!: MemoryData[T];
|
||||
|
||||
/** unless set to true, will be automatically deleted in the future */
|
||||
@Column({ default: false })
|
||||
isSaved!: boolean;
|
||||
|
||||
/** memories are sorted in ascending order by this value */
|
||||
@Column({ type: 'timestamptz' })
|
||||
memoryAt!: Date;
|
||||
|
||||
/** when the user last viewed the memory */
|
||||
@Column({ type: 'timestamptz', nullable: true })
|
||||
seenAt?: Date;
|
||||
|
||||
@ManyToMany(() => AssetEntity)
|
||||
@JoinTable()
|
||||
assets!: AssetEntity[];
|
||||
}
|
|
@ -32,6 +32,10 @@ export interface IAccessRepository {
|
|||
checkPartnerAccess(userId: string, partnerIds: Set<string>): Promise<Set<string>>;
|
||||
};
|
||||
|
||||
memory: {
|
||||
checkOwnerAccess(userId: string, memoryIds: Set<string>): Promise<Set<string>>;
|
||||
};
|
||||
|
||||
person: {
|
||||
checkFaceOwnerAccess(userId: string, assetFaceId: Set<string>): Promise<Set<string>>;
|
||||
checkOwnerAccess(userId: string, personIds: Set<string>): Promise<Set<string>>;
|
||||
|
|
14
server/src/interfaces/memory.interface.ts
Normal file
14
server/src/interfaces/memory.interface.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { MemoryEntity } from 'src/entities/memory.entity';
|
||||
|
||||
export const IMemoryRepository = 'IMemoryRepository';
|
||||
|
||||
export interface IMemoryRepository {
|
||||
search(ownerId: string): Promise<MemoryEntity[]>;
|
||||
get(id: string): Promise<MemoryEntity | null>;
|
||||
create(memory: Partial<MemoryEntity>): Promise<MemoryEntity>;
|
||||
update(memory: Partial<MemoryEntity>): Promise<MemoryEntity>;
|
||||
delete(id: string): Promise<void>;
|
||||
getAssetIds(id: string, assetIds: string[]): Promise<Set<string>>;
|
||||
addAssetIds(id: string, assetIds: string[]): Promise<void>;
|
||||
removeAssetIds(id: string, assetIds: string[]): Promise<void>;
|
||||
}
|
26
server/src/migrations/1711637874206-AddMemoryTable.ts
Normal file
26
server/src/migrations/1711637874206-AddMemoryTable.ts
Normal file
|
@ -0,0 +1,26 @@
|
|||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class AddMemoryTable1711637874206 implements MigrationInterface {
|
||||
name = 'AddMemoryTable1711637874206'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`CREATE TABLE "memories" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "ownerId" uuid NOT NULL, "type" character varying NOT NULL, "data" jsonb NOT NULL, "isSaved" boolean NOT NULL DEFAULT false, "memoryAt" TIMESTAMP WITH TIME ZONE NOT NULL, "seenAt" TIMESTAMP WITH TIME ZONE, CONSTRAINT "PK_aaa0692d9496fe827b0568612f8" PRIMARY KEY ("id"))`);
|
||||
await queryRunner.query(`CREATE TABLE "memories_assets_assets" ("memoriesId" uuid NOT NULL, "assetsId" uuid NOT NULL, CONSTRAINT "PK_fcaf7112a013d1703c011c6793d" PRIMARY KEY ("memoriesId", "assetsId"))`);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_984e5c9ab1f04d34538cd32334" ON "memories_assets_assets" ("memoriesId") `);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_6942ecf52d75d4273de19d2c16" ON "memories_assets_assets" ("assetsId") `);
|
||||
await queryRunner.query(`ALTER TABLE "memories" ADD CONSTRAINT "FK_575842846f0c28fa5da46c99b19" FOREIGN KEY ("ownerId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE`);
|
||||
await queryRunner.query(`ALTER TABLE "memories_assets_assets" ADD CONSTRAINT "FK_984e5c9ab1f04d34538cd32334e" FOREIGN KEY ("memoriesId") REFERENCES "memories"("id") ON DELETE CASCADE ON UPDATE CASCADE`);
|
||||
await queryRunner.query(`ALTER TABLE "memories_assets_assets" ADD CONSTRAINT "FK_6942ecf52d75d4273de19d2c16f" FOREIGN KEY ("assetsId") REFERENCES "assets"("id") ON DELETE CASCADE ON UPDATE CASCADE`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "memories_assets_assets" DROP CONSTRAINT "FK_6942ecf52d75d4273de19d2c16f"`);
|
||||
await queryRunner.query(`ALTER TABLE "memories_assets_assets" DROP CONSTRAINT "FK_984e5c9ab1f04d34538cd32334e"`);
|
||||
await queryRunner.query(`ALTER TABLE "memories" DROP CONSTRAINT "FK_575842846f0c28fa5da46c99b19"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_6942ecf52d75d4273de19d2c16"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_984e5c9ab1f04d34538cd32334"`);
|
||||
await queryRunner.query(`DROP TABLE "memories_assets_assets"`);
|
||||
await queryRunner.query(`DROP TABLE "memories"`);
|
||||
}
|
||||
|
||||
}
|
|
@ -196,6 +196,20 @@ WHERE
|
|||
)
|
||||
AND ("LibraryEntity"."deletedAt" IS NULL)
|
||||
|
||||
-- AccessRepository.memory.checkOwnerAccess
|
||||
SELECT
|
||||
"MemoryEntity"."id" AS "MemoryEntity_id"
|
||||
FROM
|
||||
"memories" "MemoryEntity"
|
||||
WHERE
|
||||
(
|
||||
(
|
||||
("MemoryEntity"."id" IN ($1))
|
||||
AND ("MemoryEntity"."ownerId" = $2)
|
||||
)
|
||||
)
|
||||
AND ("MemoryEntity"."deletedAt" IS NULL)
|
||||
|
||||
-- AccessRepository.person.checkOwnerAccess
|
||||
SELECT
|
||||
"PersonEntity"."id" AS "PersonEntity_id"
|
||||
|
|
18
server/src/queries/memory.repository.sql
Normal file
18
server/src/queries/memory.repository.sql
Normal file
|
@ -0,0 +1,18 @@
|
|||
-- NOTE: This file is auto generated by ./sql-generator
|
||||
|
||||
-- MemoryRepository.getAssetIds
|
||||
SELECT
|
||||
"memories_assets"."assetsId" AS "assetId"
|
||||
FROM
|
||||
"memories_assets_assets" "memories_assets"
|
||||
WHERE
|
||||
"memories_assets"."memoriesId" = $1
|
||||
AND "memories_assets"."assetsId" IN ($2)
|
||||
|
||||
-- MemoryRepository.removeAssetIds
|
||||
DELETE FROM "memories_assets_assets"
|
||||
WHERE
|
||||
(
|
||||
"memoriesId" = $1
|
||||
AND "assetsId" IN ($2)
|
||||
)
|
|
@ -5,6 +5,7 @@ import { AlbumEntity } from 'src/entities/album.entity';
|
|||
import { AssetFaceEntity } from 'src/entities/asset-face.entity';
|
||||
import { AssetEntity } from 'src/entities/asset.entity';
|
||||
import { LibraryEntity } from 'src/entities/library.entity';
|
||||
import { MemoryEntity } from 'src/entities/memory.entity';
|
||||
import { PartnerEntity } from 'src/entities/partner.entity';
|
||||
import { PersonEntity } from 'src/entities/person.entity';
|
||||
import { SharedLinkEntity } from 'src/entities/shared-link.entity';
|
||||
|
@ -19,6 +20,7 @@ type IAssetAccess = IAccessRepository['asset'];
|
|||
type IAuthDeviceAccess = IAccessRepository['authDevice'];
|
||||
type ILibraryAccess = IAccessRepository['library'];
|
||||
type ITimelineAccess = IAccessRepository['timeline'];
|
||||
type IMemoryAccess = IAccessRepository['memory'];
|
||||
type IPersonAccess = IAccessRepository['person'];
|
||||
type IPartnerAccess = IAccessRepository['partner'];
|
||||
|
||||
|
@ -345,6 +347,28 @@ class TimelineAccess implements ITimelineAccess {
|
|||
}
|
||||
}
|
||||
|
||||
class MemoryAccess implements IMemoryAccess {
|
||||
constructor(private memoryRepository: Repository<MemoryEntity>) {}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] })
|
||||
@ChunkedSet({ paramIndex: 1 })
|
||||
async checkOwnerAccess(userId: string, memoryIds: Set<string>): Promise<Set<string>> {
|
||||
if (memoryIds.size === 0) {
|
||||
return new Set();
|
||||
}
|
||||
|
||||
return this.memoryRepository
|
||||
.find({
|
||||
select: { id: true },
|
||||
where: {
|
||||
id: In([...memoryIds]),
|
||||
ownerId: userId,
|
||||
},
|
||||
})
|
||||
.then((memories) => new Set(memories.map((memory) => memory.id)));
|
||||
}
|
||||
}
|
||||
|
||||
class PersonAccess implements IPersonAccess {
|
||||
constructor(
|
||||
private assetFaceRepository: Repository<AssetFaceEntity>,
|
||||
|
@ -416,6 +440,7 @@ export class AccessRepository implements IAccessRepository {
|
|||
asset: IAssetAccess;
|
||||
authDevice: IAuthDeviceAccess;
|
||||
library: ILibraryAccess;
|
||||
memory: IMemoryAccess;
|
||||
person: IPersonAccess;
|
||||
partner: IPartnerAccess;
|
||||
timeline: ITimelineAccess;
|
||||
|
@ -425,6 +450,7 @@ export class AccessRepository implements IAccessRepository {
|
|||
@InjectRepository(AssetEntity) assetRepository: Repository<AssetEntity>,
|
||||
@InjectRepository(AlbumEntity) albumRepository: Repository<AlbumEntity>,
|
||||
@InjectRepository(LibraryEntity) libraryRepository: Repository<LibraryEntity>,
|
||||
@InjectRepository(MemoryEntity) memoryRepository: Repository<MemoryEntity>,
|
||||
@InjectRepository(PartnerEntity) partnerRepository: Repository<PartnerEntity>,
|
||||
@InjectRepository(PersonEntity) personRepository: Repository<PersonEntity>,
|
||||
@InjectRepository(AssetFaceEntity) assetFaceRepository: Repository<AssetFaceEntity>,
|
||||
|
@ -436,6 +462,7 @@ export class AccessRepository implements IAccessRepository {
|
|||
this.asset = new AssetAccess(albumRepository, assetRepository, partnerRepository, sharedLinkRepository);
|
||||
this.authDevice = new AuthDeviceAccess(tokenRepository);
|
||||
this.library = new LibraryAccess(libraryRepository);
|
||||
this.memory = new MemoryAccess(memoryRepository);
|
||||
this.person = new PersonAccess(assetFaceRepository, personRepository);
|
||||
this.partner = new PartnerAccess(partnerRepository);
|
||||
this.timeline = new TimelineAccess(partnerRepository);
|
||||
|
|
|
@ -13,6 +13,7 @@ import { IJobRepository } from 'src/interfaces/job.interface';
|
|||
import { ILibraryRepository } from 'src/interfaces/library.interface';
|
||||
import { IMachineLearningRepository } from 'src/interfaces/machine-learning.interface';
|
||||
import { IMediaRepository } from 'src/interfaces/media.interface';
|
||||
import { IMemoryRepository } from 'src/interfaces/memory.interface';
|
||||
import { IMetadataRepository } from 'src/interfaces/metadata.interface';
|
||||
import { IMetricRepository } from 'src/interfaces/metric.interface';
|
||||
import { IMoveRepository } from 'src/interfaces/move.interface';
|
||||
|
@ -42,6 +43,7 @@ import { JobRepository } from 'src/repositories/job.repository';
|
|||
import { LibraryRepository } from 'src/repositories/library.repository';
|
||||
import { MachineLearningRepository } from 'src/repositories/machine-learning.repository';
|
||||
import { MediaRepository } from 'src/repositories/media.repository';
|
||||
import { MemoryRepository } from 'src/repositories/memory.repository';
|
||||
import { MetadataRepository } from 'src/repositories/metadata.repository';
|
||||
import { MetricRepository } from 'src/repositories/metric.repository';
|
||||
import { MoveRepository } from 'src/repositories/move.repository';
|
||||
|
@ -72,6 +74,7 @@ export const repositories = [
|
|||
{ provide: ILibraryRepository, useClass: LibraryRepository },
|
||||
{ provide: IKeyRepository, useClass: ApiKeyRepository },
|
||||
{ provide: IMachineLearningRepository, useClass: MachineLearningRepository },
|
||||
{ provide: IMemoryRepository, useClass: MemoryRepository },
|
||||
{ provide: IMetadataRepository, useClass: MetadataRepository },
|
||||
{ provide: IMetricRepository, useClass: MetricRepository },
|
||||
{ provide: IMoveRepository, useClass: MoveRepository },
|
||||
|
|
104
server/src/repositories/memory.repository.ts
Normal file
104
server/src/repositories/memory.repository.ts
Normal file
|
@ -0,0 +1,104 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
|
||||
import { Chunked, ChunkedSet, DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { AssetEntity } from 'src/entities/asset.entity';
|
||||
import { MemoryEntity } from 'src/entities/memory.entity';
|
||||
import { IMemoryRepository } from 'src/interfaces/memory.interface';
|
||||
import { Instrumentation } from 'src/utils/instrumentation';
|
||||
import { DataSource, In, Repository } from 'typeorm';
|
||||
|
||||
@Instrumentation()
|
||||
@Injectable()
|
||||
export class MemoryRepository implements IMemoryRepository {
|
||||
constructor(
|
||||
@InjectRepository(AssetEntity) private assetRepository: Repository<AssetEntity>,
|
||||
@InjectRepository(MemoryEntity) private repository: Repository<MemoryEntity>,
|
||||
@InjectDataSource() private dataSource: DataSource,
|
||||
) {}
|
||||
|
||||
search(ownerId: string): Promise<MemoryEntity[]> {
|
||||
return this.repository.find({
|
||||
where: {
|
||||
ownerId,
|
||||
},
|
||||
order: {
|
||||
memoryAt: 'DESC',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
get(id: string): Promise<MemoryEntity | null> {
|
||||
return this.repository.findOne({
|
||||
where: {
|
||||
id,
|
||||
},
|
||||
relations: {
|
||||
assets: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
create(memory: Partial<MemoryEntity>): Promise<MemoryEntity> {
|
||||
return this.save(memory);
|
||||
}
|
||||
|
||||
update(memory: Partial<MemoryEntity>): Promise<MemoryEntity> {
|
||||
return this.save(memory);
|
||||
}
|
||||
|
||||
async delete(id: string): Promise<void> {
|
||||
await this.repository.delete({ id });
|
||||
}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID, [DummyValue.UUID]] })
|
||||
@ChunkedSet({ paramIndex: 1 })
|
||||
async getAssetIds(id: string, assetIds: string[]): Promise<Set<string>> {
|
||||
if (assetIds.length === 0) {
|
||||
return new Set();
|
||||
}
|
||||
|
||||
const results = await this.dataSource
|
||||
.createQueryBuilder()
|
||||
.select('memories_assets.assetsId', 'assetId')
|
||||
.from('memories_assets_assets', 'memories_assets')
|
||||
.where('"memories_assets"."memoriesId" = :memoryId', { memoryId: id })
|
||||
.andWhere('memories_assets.assetsId IN (:...assetIds)', { assetIds })
|
||||
.getRawMany();
|
||||
|
||||
return new Set(results.map((row) => row['assetId']));
|
||||
}
|
||||
|
||||
@GenerateSql({ params: [{ albumId: DummyValue.UUID, assetIds: [DummyValue.UUID] }] })
|
||||
async addAssetIds(id: string, assetIds: string[]): Promise<void> {
|
||||
await this.dataSource
|
||||
.createQueryBuilder()
|
||||
.insert()
|
||||
.into('memories_assets_assets', ['memoriesId', 'assetsId'])
|
||||
.values(assetIds.map((assetId) => ({ memoriesId: id, assetsId: assetId })))
|
||||
.execute();
|
||||
}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID, [DummyValue.UUID]] })
|
||||
@Chunked({ paramIndex: 1 })
|
||||
async removeAssetIds(id: string, assetIds: string[]): Promise<void> {
|
||||
await this.dataSource
|
||||
.createQueryBuilder()
|
||||
.delete()
|
||||
.from('memories_assets_assets')
|
||||
.where({
|
||||
memoriesId: id,
|
||||
assetsId: In(assetIds),
|
||||
})
|
||||
.execute();
|
||||
}
|
||||
|
||||
private async save(memory: Partial<MemoryEntity>): Promise<MemoryEntity> {
|
||||
const { id } = await this.repository.save(memory);
|
||||
return this.repository.findOneOrFail({
|
||||
where: { id },
|
||||
relations: {
|
||||
assets: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
|
@ -11,6 +11,7 @@ import { DownloadService } from 'src/services/download.service';
|
|||
import { JobService } from 'src/services/job.service';
|
||||
import { LibraryService } from 'src/services/library.service';
|
||||
import { MediaService } from 'src/services/media.service';
|
||||
import { MemoryService } from 'src/services/memory.service';
|
||||
import { MetadataService } from 'src/services/metadata.service';
|
||||
import { MicroservicesService } from 'src/services/microservices.service';
|
||||
import { PartnerService } from 'src/services/partner.service';
|
||||
|
@ -42,6 +43,7 @@ export const services = [
|
|||
JobService,
|
||||
LibraryService,
|
||||
MediaService,
|
||||
MemoryService,
|
||||
MetadataService,
|
||||
PartnerService,
|
||||
PersonService,
|
||||
|
|
214
server/src/services/memory.service.spec.ts
Normal file
214
server/src/services/memory.service.spec.ts
Normal file
|
@ -0,0 +1,214 @@
|
|||
import { BadRequestException } from '@nestjs/common';
|
||||
import { MemoryType } from 'src/entities/memory.entity';
|
||||
import { IMemoryRepository } from 'src/interfaces/memory.interface';
|
||||
import { MemoryService } from 'src/services/memory.service';
|
||||
import { authStub } from 'test/fixtures/auth.stub';
|
||||
import { memoryStub } from 'test/fixtures/memory.stub';
|
||||
import { userStub } from 'test/fixtures/user.stub';
|
||||
import { IAccessRepositoryMock, newAccessRepositoryMock } from 'test/repositories/access.repository.mock';
|
||||
import { newMemoryRepositoryMock } from 'test/repositories/memory.repository.mock';
|
||||
|
||||
describe(MemoryService.name, () => {
|
||||
let accessMock: IAccessRepositoryMock;
|
||||
let memoryMock: jest.Mocked<IMemoryRepository>;
|
||||
let sut: MemoryService;
|
||||
|
||||
beforeEach(() => {
|
||||
accessMock = newAccessRepositoryMock();
|
||||
memoryMock = newMemoryRepositoryMock();
|
||||
|
||||
sut = new MemoryService(accessMock, memoryMock);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(sut).toBeDefined();
|
||||
});
|
||||
|
||||
describe('search', () => {
|
||||
it('should search memories', async () => {
|
||||
memoryMock.search.mockResolvedValue([memoryStub.memory1, memoryStub.empty]);
|
||||
await expect(sut.search(authStub.admin)).resolves.toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ id: 'memory1', assets: expect.any(Array) }),
|
||||
expect.objectContaining({ id: 'memoryEmpty', assets: [] }),
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
it('should map ', async () => {
|
||||
await expect(sut.search(authStub.admin)).resolves.toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('get', () => {
|
||||
it('should throw an error when no access', async () => {
|
||||
await expect(sut.get(authStub.admin, 'not-found')).rejects.toBeInstanceOf(BadRequestException);
|
||||
});
|
||||
|
||||
it('should throw an error when the memory is not found', async () => {
|
||||
accessMock.memory.checkOwnerAccess.mockResolvedValue(new Set(['race-condition']));
|
||||
await expect(sut.get(authStub.admin, 'race-condition')).rejects.toBeInstanceOf(BadRequestException);
|
||||
});
|
||||
|
||||
it('should get a memory by id', async () => {
|
||||
memoryMock.get.mockResolvedValue(memoryStub.memory1);
|
||||
accessMock.memory.checkOwnerAccess.mockResolvedValue(new Set(['memory1']));
|
||||
await expect(sut.get(authStub.admin, 'memory1')).resolves.toMatchObject({ id: 'memory1' });
|
||||
expect(memoryMock.get).toHaveBeenCalledWith('memory1');
|
||||
expect(accessMock.memory.checkOwnerAccess).toHaveBeenCalledWith(userStub.admin.id, new Set(['memory1']));
|
||||
});
|
||||
});
|
||||
|
||||
describe('create', () => {
|
||||
it('should skip assets the user does not have access to', async () => {
|
||||
memoryMock.create.mockResolvedValue(memoryStub.empty);
|
||||
await expect(
|
||||
sut.create(authStub.admin, {
|
||||
type: MemoryType.ON_THIS_DAY,
|
||||
data: { year: 2024 },
|
||||
assetIds: ['not-mine'],
|
||||
memoryAt: new Date(2024),
|
||||
}),
|
||||
).resolves.toMatchObject({ assets: [] });
|
||||
expect(memoryMock.create).toHaveBeenCalledWith(expect.objectContaining({ assets: [] }));
|
||||
});
|
||||
|
||||
it('should create a memory', async () => {
|
||||
accessMock.asset.checkOwnerAccess.mockResolvedValue(new Set(['asset1']));
|
||||
memoryMock.create.mockResolvedValue(memoryStub.memory1);
|
||||
await expect(
|
||||
sut.create(authStub.admin, {
|
||||
type: MemoryType.ON_THIS_DAY,
|
||||
data: { year: 2024 },
|
||||
assetIds: ['asset1'],
|
||||
memoryAt: new Date(2024),
|
||||
}),
|
||||
).resolves.toBeDefined();
|
||||
expect(memoryMock.create).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
ownerId: userStub.admin.id,
|
||||
assets: [{ id: 'asset1' }],
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('should create a memory without assets', async () => {
|
||||
memoryMock.create.mockResolvedValue(memoryStub.memory1);
|
||||
await expect(
|
||||
sut.create(authStub.admin, {
|
||||
type: MemoryType.ON_THIS_DAY,
|
||||
data: { year: 2024 },
|
||||
memoryAt: new Date(2024),
|
||||
}),
|
||||
).resolves.toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('update', () => {
|
||||
it('should require access', async () => {
|
||||
await expect(sut.update(authStub.admin, 'not-found', { isSaved: true })).rejects.toBeInstanceOf(
|
||||
BadRequestException,
|
||||
);
|
||||
expect(memoryMock.update).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should update a memory', async () => {
|
||||
accessMock.memory.checkOwnerAccess.mockResolvedValue(new Set(['memory1']));
|
||||
memoryMock.update.mockResolvedValue(memoryStub.memory1);
|
||||
await expect(sut.update(authStub.admin, 'memory1', { isSaved: true })).resolves.toBeDefined();
|
||||
expect(memoryMock.update).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
id: 'memory1',
|
||||
isSaved: true,
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('remove', () => {
|
||||
it('should require access', async () => {
|
||||
await expect(sut.remove(authStub.admin, 'not-found')).rejects.toBeInstanceOf(BadRequestException);
|
||||
expect(memoryMock.delete).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should delete a memory', async () => {
|
||||
accessMock.memory.checkOwnerAccess.mockResolvedValue(new Set(['memory1']));
|
||||
await expect(sut.remove(authStub.admin, 'memory1')).resolves.toBeUndefined();
|
||||
expect(memoryMock.delete).toHaveBeenCalledWith('memory1');
|
||||
});
|
||||
});
|
||||
|
||||
describe('addAssets', () => {
|
||||
it('should require memory access', async () => {
|
||||
await expect(sut.addAssets(authStub.admin, 'not-found', { ids: ['asset1'] })).rejects.toBeInstanceOf(
|
||||
BadRequestException,
|
||||
);
|
||||
expect(memoryMock.addAssetIds).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should require asset access', async () => {
|
||||
accessMock.memory.checkOwnerAccess.mockResolvedValue(new Set(['memory1']));
|
||||
memoryMock.get.mockResolvedValue(memoryStub.memory1);
|
||||
await expect(sut.addAssets(authStub.admin, 'memory1', { ids: ['not-found'] })).resolves.toEqual([
|
||||
{ error: 'no_permission', id: 'not-found', success: false },
|
||||
]);
|
||||
expect(memoryMock.addAssetIds).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should skip assets already in the memory', async () => {
|
||||
accessMock.memory.checkOwnerAccess.mockResolvedValue(new Set(['memory1']));
|
||||
memoryMock.get.mockResolvedValue(memoryStub.memory1);
|
||||
memoryMock.getAssetIds.mockResolvedValue(new Set(['asset1']));
|
||||
await expect(sut.addAssets(authStub.admin, 'memory1', { ids: ['asset1'] })).resolves.toEqual([
|
||||
{ error: 'duplicate', id: 'asset1', success: false },
|
||||
]);
|
||||
expect(memoryMock.addAssetIds).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should add assets', async () => {
|
||||
accessMock.memory.checkOwnerAccess.mockResolvedValue(new Set(['memory1']));
|
||||
accessMock.asset.checkOwnerAccess.mockResolvedValue(new Set(['asset1']));
|
||||
memoryMock.get.mockResolvedValue(memoryStub.memory1);
|
||||
await expect(sut.addAssets(authStub.admin, 'memory1', { ids: ['asset1'] })).resolves.toEqual([
|
||||
{ id: 'asset1', success: true },
|
||||
]);
|
||||
expect(memoryMock.addAssetIds).toHaveBeenCalledWith('memory1', ['asset1']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('removeAssets', () => {
|
||||
it('should require memory access', async () => {
|
||||
await expect(sut.removeAssets(authStub.admin, 'not-found', { ids: ['asset1'] })).rejects.toBeInstanceOf(
|
||||
BadRequestException,
|
||||
);
|
||||
expect(memoryMock.removeAssetIds).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should skip assets not in the memory', async () => {
|
||||
accessMock.memory.checkOwnerAccess.mockResolvedValue(new Set(['memory1']));
|
||||
await expect(sut.removeAssets(authStub.admin, 'memory1', { ids: ['not-found'] })).resolves.toEqual([
|
||||
{ error: 'not_found', id: 'not-found', success: false },
|
||||
]);
|
||||
expect(memoryMock.removeAssetIds).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should require asset access', async () => {
|
||||
accessMock.memory.checkOwnerAccess.mockResolvedValue(new Set(['memory1']));
|
||||
memoryMock.getAssetIds.mockResolvedValue(new Set(['asset1']));
|
||||
await expect(sut.removeAssets(authStub.admin, 'memory1', { ids: ['asset1'] })).resolves.toEqual([
|
||||
{ error: 'no_permission', id: 'asset1', success: false },
|
||||
]);
|
||||
expect(memoryMock.removeAssetIds).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should remove assets', async () => {
|
||||
accessMock.memory.checkOwnerAccess.mockResolvedValue(new Set(['memory1']));
|
||||
accessMock.asset.checkOwnerAccess.mockResolvedValue(new Set(['asset1']));
|
||||
memoryMock.getAssetIds.mockResolvedValue(new Set(['asset1']));
|
||||
await expect(sut.removeAssets(authStub.admin, 'memory1', { ids: ['asset1'] })).resolves.toEqual([
|
||||
{ id: 'asset1', success: true },
|
||||
]);
|
||||
expect(memoryMock.removeAssetIds).toHaveBeenCalledWith('memory1', ['asset1']);
|
||||
});
|
||||
});
|
||||
});
|
105
server/src/services/memory.service.ts
Normal file
105
server/src/services/memory.service.ts
Normal file
|
@ -0,0 +1,105 @@
|
|||
import { BadRequestException, Inject, Injectable } from '@nestjs/common';
|
||||
import { AccessCore, Permission } from 'src/cores/access.core';
|
||||
import { BulkIdResponseDto, BulkIdsDto } from 'src/dtos/asset-ids.response.dto';
|
||||
import { AuthDto } from 'src/dtos/auth.dto';
|
||||
import { MemoryCreateDto, MemoryResponseDto, MemoryUpdateDto, mapMemory } from 'src/dtos/memory.dto';
|
||||
import { AssetEntity } from 'src/entities/asset.entity';
|
||||
import { IAccessRepository } from 'src/interfaces/access.interface';
|
||||
import { IMemoryRepository } from 'src/interfaces/memory.interface';
|
||||
import { addAssets, removeAssets } from 'src/utils/asset.util';
|
||||
|
||||
@Injectable()
|
||||
export class MemoryService {
|
||||
private access: AccessCore;
|
||||
|
||||
constructor(
|
||||
@Inject(IAccessRepository) private accessRepository: IAccessRepository,
|
||||
@Inject(IMemoryRepository) private repository: IMemoryRepository,
|
||||
) {
|
||||
this.access = AccessCore.create(accessRepository);
|
||||
}
|
||||
|
||||
async search(auth: AuthDto) {
|
||||
const memories = await this.repository.search(auth.user.id);
|
||||
return memories.map((memory) => mapMemory(memory));
|
||||
}
|
||||
|
||||
async get(auth: AuthDto, id: string): Promise<MemoryResponseDto> {
|
||||
await this.access.requirePermission(auth, Permission.MEMORY_READ, id);
|
||||
const memory = await this.findOrFail(id);
|
||||
return mapMemory(memory);
|
||||
}
|
||||
|
||||
async create(auth: AuthDto, dto: MemoryCreateDto) {
|
||||
// TODO validate type/data combination
|
||||
|
||||
const assetIds = dto.assetIds || [];
|
||||
const allowedAssetIds = await this.access.checkAccess(auth, Permission.ASSET_SHARE, assetIds);
|
||||
const memory = await this.repository.create({
|
||||
ownerId: auth.user.id,
|
||||
type: dto.type,
|
||||
data: dto.data,
|
||||
isSaved: dto.isSaved,
|
||||
memoryAt: dto.memoryAt,
|
||||
seenAt: dto.seenAt,
|
||||
assets: [...allowedAssetIds].map((id) => ({ id }) as AssetEntity),
|
||||
});
|
||||
|
||||
return mapMemory(memory);
|
||||
}
|
||||
|
||||
async update(auth: AuthDto, id: string, dto: MemoryUpdateDto): Promise<MemoryResponseDto> {
|
||||
await this.access.requirePermission(auth, Permission.MEMORY_WRITE, id);
|
||||
|
||||
const memory = await this.repository.update({
|
||||
id,
|
||||
isSaved: dto.isSaved,
|
||||
memoryAt: dto.memoryAt,
|
||||
seenAt: dto.seenAt,
|
||||
});
|
||||
|
||||
return mapMemory(memory);
|
||||
}
|
||||
|
||||
async remove(auth: AuthDto, id: string): Promise<void> {
|
||||
await this.access.requirePermission(auth, Permission.MEMORY_DELETE, id);
|
||||
await this.repository.delete(id);
|
||||
}
|
||||
|
||||
async addAssets(auth: AuthDto, id: string, dto: BulkIdsDto): Promise<BulkIdResponseDto[]> {
|
||||
await this.access.requirePermission(auth, Permission.MEMORY_READ, id);
|
||||
|
||||
const repos = { accessRepository: this.accessRepository, repository: this.repository };
|
||||
const results = await addAssets(auth, repos, { id, assetIds: dto.ids });
|
||||
|
||||
const hasSuccess = results.find(({ success }) => success);
|
||||
if (hasSuccess) {
|
||||
await this.repository.update({ id, updatedAt: new Date() });
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
async removeAssets(auth: AuthDto, id: string, dto: BulkIdsDto): Promise<BulkIdResponseDto[]> {
|
||||
await this.access.requirePermission(auth, Permission.MEMORY_WRITE, id);
|
||||
|
||||
const repos = { accessRepository: this.accessRepository, repository: this.repository };
|
||||
const permissions = [Permission.ASSET_SHARE];
|
||||
const results = await removeAssets(auth, repos, { id, assetIds: dto.ids, permissions });
|
||||
|
||||
const hasSuccess = results.find(({ success }) => success);
|
||||
if (hasSuccess) {
|
||||
await this.repository.update({ id, updatedAt: new Date() });
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private async findOrFail(id: string) {
|
||||
const memory = await this.repository.get(id);
|
||||
if (!memory) {
|
||||
throw new BadRequestException('Memory not found');
|
||||
}
|
||||
return memory;
|
||||
}
|
||||
}
|
30
server/test/fixtures/memory.stub.ts
vendored
Normal file
30
server/test/fixtures/memory.stub.ts
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
import { MemoryEntity, MemoryType } from 'src/entities/memory.entity';
|
||||
import { assetStub } from 'test/fixtures/asset.stub';
|
||||
import { userStub } from 'test/fixtures/user.stub';
|
||||
|
||||
export const memoryStub = {
|
||||
empty: <MemoryEntity>{
|
||||
id: 'memoryEmpty',
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
memoryAt: new Date(2024),
|
||||
ownerId: userStub.admin.id,
|
||||
owner: userStub.admin,
|
||||
type: MemoryType.ON_THIS_DAY,
|
||||
data: { year: 2024 },
|
||||
isSaved: false,
|
||||
assets: [],
|
||||
},
|
||||
memory1: <MemoryEntity>{
|
||||
id: 'memory1',
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
memoryAt: new Date(2024),
|
||||
ownerId: userStub.admin.id,
|
||||
owner: userStub.admin,
|
||||
type: MemoryType.ON_THIS_DAY,
|
||||
data: { year: 2024 },
|
||||
isSaved: false,
|
||||
assets: [assetStub.image1],
|
||||
},
|
||||
};
|
|
@ -8,6 +8,7 @@ export interface IAccessRepositoryMock {
|
|||
authDevice: jest.Mocked<IAccessRepository['authDevice']>;
|
||||
library: jest.Mocked<IAccessRepository['library']>;
|
||||
timeline: jest.Mocked<IAccessRepository['timeline']>;
|
||||
memory: jest.Mocked<IAccessRepository['memory']>;
|
||||
person: jest.Mocked<IAccessRepository['person']>;
|
||||
partner: jest.Mocked<IAccessRepository['partner']>;
|
||||
}
|
||||
|
@ -49,6 +50,10 @@ export const newAccessRepositoryMock = (reset = true): IAccessRepositoryMock =>
|
|||
checkPartnerAccess: jest.fn().mockResolvedValue(new Set()),
|
||||
},
|
||||
|
||||
memory: {
|
||||
checkOwnerAccess: jest.fn().mockResolvedValue(new Set()),
|
||||
},
|
||||
|
||||
person: {
|
||||
checkFaceOwnerAccess: jest.fn().mockResolvedValue(new Set()),
|
||||
checkOwnerAccess: jest.fn().mockResolvedValue(new Set()),
|
||||
|
|
14
server/test/repositories/memory.repository.mock.ts
Normal file
14
server/test/repositories/memory.repository.mock.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { IMemoryRepository } from 'src/interfaces/memory.interface';
|
||||
|
||||
export const newMemoryRepositoryMock = (): jest.Mocked<IMemoryRepository> => {
|
||||
return {
|
||||
search: jest.fn().mockResolvedValue([]),
|
||||
get: jest.fn(),
|
||||
create: jest.fn(),
|
||||
update: jest.fn(),
|
||||
delete: jest.fn(),
|
||||
getAssetIds: jest.fn().mockResolvedValue(new Set()),
|
||||
addAssetIds: jest.fn(),
|
||||
removeAssetIds: jest.fn(),
|
||||
};
|
||||
};
|
Loading…
Add table
Reference in a new issue