mirror of
https://github.com/immich-app/immich.git
synced 2025-06-03 13:44:16 -04:00
refactor: create album users (#9315)
This commit is contained in:
parent
e9f99673b9
commit
e79d1b1ec2
@ -1,6 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
ActivityCreateDto,
|
ActivityCreateDto,
|
||||||
AlbumResponseDto,
|
AlbumResponseDto,
|
||||||
|
AlbumUserRole,
|
||||||
AssetFileUploadResponseDto,
|
AssetFileUploadResponseDto,
|
||||||
LoginResponseDto,
|
LoginResponseDto,
|
||||||
ReactionType,
|
ReactionType,
|
||||||
@ -33,7 +34,7 @@ describe('/activity', () => {
|
|||||||
createAlbumDto: {
|
createAlbumDto: {
|
||||||
albumName: 'Album 1',
|
albumName: 'Album 1',
|
||||||
assetIds: [asset.id],
|
assetIds: [asset.id],
|
||||||
sharedWithUserIds: [nonOwner.userId],
|
albumUsers: [{ userId: nonOwner.userId, role: AlbumUserRole.Editor }],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{ headers: asBearerAuth(admin.accessToken) },
|
{ headers: asBearerAuth(admin.accessToken) },
|
||||||
|
@ -49,72 +49,50 @@ describe('/album', () => {
|
|||||||
utils.createAsset(user1.accessToken),
|
utils.createAsset(user1.accessToken),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const albums = await Promise.all([
|
user1Albums = await Promise.all([
|
||||||
// user 1
|
|
||||||
/* 0 */
|
|
||||||
utils.createAlbum(user1.accessToken, {
|
utils.createAlbum(user1.accessToken, {
|
||||||
albumName: user1SharedEditorUser,
|
albumName: user1SharedEditorUser,
|
||||||
sharedWithUserIds: [user2.userId],
|
albumUsers: [{ userId: user2.userId, role: AlbumUserRole.Editor }],
|
||||||
assetIds: [user1Asset1.id],
|
assetIds: [user1Asset1.id],
|
||||||
}),
|
}),
|
||||||
/* 1 */
|
|
||||||
utils.createAlbum(user1.accessToken, {
|
utils.createAlbum(user1.accessToken, {
|
||||||
albumName: user1SharedLink,
|
albumName: user1SharedLink,
|
||||||
assetIds: [user1Asset1.id],
|
assetIds: [user1Asset1.id],
|
||||||
}),
|
}),
|
||||||
/* 2 */
|
|
||||||
utils.createAlbum(user1.accessToken, {
|
utils.createAlbum(user1.accessToken, {
|
||||||
albumName: user1NotShared,
|
albumName: user1NotShared,
|
||||||
assetIds: [user1Asset1.id, user1Asset2.id],
|
assetIds: [user1Asset1.id, user1Asset2.id],
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// user 2
|
|
||||||
/* 3 */
|
|
||||||
utils.createAlbum(user2.accessToken, {
|
|
||||||
albumName: user2SharedUser,
|
|
||||||
sharedWithUserIds: [user1.userId, user3.userId],
|
|
||||||
}),
|
|
||||||
/* 4 */
|
|
||||||
utils.createAlbum(user2.accessToken, { albumName: user2SharedLink }),
|
|
||||||
/* 5 */
|
|
||||||
utils.createAlbum(user2.accessToken, { albumName: user2NotShared }),
|
|
||||||
|
|
||||||
// user 3
|
|
||||||
/* 6 */
|
|
||||||
utils.createAlbum(user3.accessToken, {
|
|
||||||
albumName: 'Deleted',
|
|
||||||
sharedWithUserIds: [user1.userId],
|
|
||||||
}),
|
|
||||||
|
|
||||||
// user1 shared with an editor
|
|
||||||
/* 7 */
|
|
||||||
utils.createAlbum(user1.accessToken, {
|
utils.createAlbum(user1.accessToken, {
|
||||||
albumName: user1SharedViewerUser,
|
albumName: user1SharedViewerUser,
|
||||||
sharedWithUserIds: [user2.userId],
|
albumUsers: [{ userId: user2.userId, role: AlbumUserRole.Viewer }],
|
||||||
assetIds: [user1Asset1.id],
|
assetIds: [user1Asset1.id],
|
||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Make viewer
|
user2Albums = await Promise.all([
|
||||||
await utils.updateAlbumUser(user1.accessToken, {
|
utils.createAlbum(user2.accessToken, {
|
||||||
id: albums[7].id,
|
albumName: user2SharedUser,
|
||||||
userId: user2.userId,
|
albumUsers: [
|
||||||
updateAlbumUserDto: { role: AlbumUserRole.Viewer },
|
{ userId: user1.userId, role: AlbumUserRole.Editor },
|
||||||
|
{ userId: user3.userId, role: AlbumUserRole.Editor },
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
utils.createAlbum(user2.accessToken, { albumName: user2SharedLink }),
|
||||||
|
utils.createAlbum(user2.accessToken, { albumName: user2NotShared }),
|
||||||
|
]);
|
||||||
|
|
||||||
|
await utils.createAlbum(user3.accessToken, {
|
||||||
|
albumName: 'Deleted',
|
||||||
|
albumUsers: [{ userId: user1.userId, role: AlbumUserRole.Editor }],
|
||||||
});
|
});
|
||||||
|
|
||||||
albums[0].albumUsers[0].role = AlbumUserRole.Editor;
|
|
||||||
albums[3].albumUsers[0].role = AlbumUserRole.Editor;
|
|
||||||
albums[6].albumUsers[0].role = AlbumUserRole.Editor;
|
|
||||||
|
|
||||||
await addAssetsToAlbum(
|
await addAssetsToAlbum(
|
||||||
{ id: albums[3].id, bulkIdsDto: { ids: [user1Asset1.id] } },
|
{ id: user2Albums[0].id, bulkIdsDto: { ids: [user1Asset1.id] } },
|
||||||
{ headers: asBearerAuth(user1.accessToken) },
|
{ headers: asBearerAuth(user1.accessToken) },
|
||||||
);
|
);
|
||||||
|
|
||||||
albums[3] = await getAlbumInfo({ id: albums[3].id }, { headers: asBearerAuth(user2.accessToken) });
|
user2Albums[0] = await getAlbumInfo({ id: user2Albums[0].id }, { headers: asBearerAuth(user2.accessToken) });
|
||||||
|
|
||||||
user1Albums = [...albums.slice(0, 3), albums[7]];
|
|
||||||
user2Albums = albums.slice(3, 6);
|
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
// add shared link to user1SharedLink album
|
// add shared link to user1SharedLink album
|
||||||
@ -641,9 +619,11 @@ describe('/album', () => {
|
|||||||
it('should allow the album owner to change the role of a shared user', async () => {
|
it('should allow the album owner to change the role of a shared user', async () => {
|
||||||
const album = await utils.createAlbum(user1.accessToken, {
|
const album = await utils.createAlbum(user1.accessToken, {
|
||||||
albumName: 'testAlbum',
|
albumName: 'testAlbum',
|
||||||
sharedWithUserIds: [user2.userId],
|
albumUsers: [{ userId: user2.userId, role: AlbumUserRole.Viewer }],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
expect(album.albumUsers[0].role).toEqual(AlbumUserRole.Viewer);
|
||||||
|
|
||||||
const { status } = await request(app)
|
const { status } = await request(app)
|
||||||
.put(`/album/${album.id}/user/${user2.userId}`)
|
.put(`/album/${album.id}/user/${user2.userId}`)
|
||||||
.set('Authorization', `Bearer ${user1.accessToken}`)
|
.set('Authorization', `Bearer ${user1.accessToken}`)
|
||||||
@ -663,9 +643,11 @@ describe('/album', () => {
|
|||||||
it('should not allow a shared user to change the role of another shared user', async () => {
|
it('should not allow a shared user to change the role of another shared user', async () => {
|
||||||
const album = await utils.createAlbum(user1.accessToken, {
|
const album = await utils.createAlbum(user1.accessToken, {
|
||||||
albumName: 'testAlbum',
|
albumName: 'testAlbum',
|
||||||
sharedWithUserIds: [user2.userId],
|
albumUsers: [{ userId: user2.userId, role: AlbumUserRole.Viewer }],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
expect(album.albumUsers[0].role).toEqual(AlbumUserRole.Viewer);
|
||||||
|
|
||||||
const { status, body } = await request(app)
|
const { status, body } = await request(app)
|
||||||
.put(`/album/${album.id}/user/${user2.userId}`)
|
.put(`/album/${album.id}/user/${user2.userId}`)
|
||||||
.set('Authorization', `Bearer ${user2.accessToken}`)
|
.set('Authorization', `Bearer ${user2.accessToken}`)
|
||||||
|
3
mobile/openapi/.openapi-generator/FILES
generated
3
mobile/openapi/.openapi-generator/FILES
generated
@ -18,6 +18,7 @@ doc/AlbumApi.md
|
|||||||
doc/AlbumCountResponseDto.md
|
doc/AlbumCountResponseDto.md
|
||||||
doc/AlbumResponseDto.md
|
doc/AlbumResponseDto.md
|
||||||
doc/AlbumUserAddDto.md
|
doc/AlbumUserAddDto.md
|
||||||
|
doc/AlbumUserCreateDto.md
|
||||||
doc/AlbumUserResponseDto.md
|
doc/AlbumUserResponseDto.md
|
||||||
doc/AlbumUserRole.md
|
doc/AlbumUserRole.md
|
||||||
doc/AllJobStatusResponseDto.md
|
doc/AllJobStatusResponseDto.md
|
||||||
@ -257,6 +258,7 @@ lib/model/admin_onboarding_update_dto.dart
|
|||||||
lib/model/album_count_response_dto.dart
|
lib/model/album_count_response_dto.dart
|
||||||
lib/model/album_response_dto.dart
|
lib/model/album_response_dto.dart
|
||||||
lib/model/album_user_add_dto.dart
|
lib/model/album_user_add_dto.dart
|
||||||
|
lib/model/album_user_create_dto.dart
|
||||||
lib/model/album_user_response_dto.dart
|
lib/model/album_user_response_dto.dart
|
||||||
lib/model/album_user_role.dart
|
lib/model/album_user_role.dart
|
||||||
lib/model/all_job_status_response_dto.dart
|
lib/model/all_job_status_response_dto.dart
|
||||||
@ -444,6 +446,7 @@ test/album_api_test.dart
|
|||||||
test/album_count_response_dto_test.dart
|
test/album_count_response_dto_test.dart
|
||||||
test/album_response_dto_test.dart
|
test/album_response_dto_test.dart
|
||||||
test/album_user_add_dto_test.dart
|
test/album_user_add_dto_test.dart
|
||||||
|
test/album_user_create_dto_test.dart
|
||||||
test/album_user_response_dto_test.dart
|
test/album_user_response_dto_test.dart
|
||||||
test/album_user_role_test.dart
|
test/album_user_role_test.dart
|
||||||
test/all_job_status_response_dto_test.dart
|
test/all_job_status_response_dto_test.dart
|
||||||
|
1
mobile/openapi/README.md
generated
1
mobile/openapi/README.md
generated
@ -235,6 +235,7 @@ Class | Method | HTTP request | Description
|
|||||||
- [AlbumCountResponseDto](doc//AlbumCountResponseDto.md)
|
- [AlbumCountResponseDto](doc//AlbumCountResponseDto.md)
|
||||||
- [AlbumResponseDto](doc//AlbumResponseDto.md)
|
- [AlbumResponseDto](doc//AlbumResponseDto.md)
|
||||||
- [AlbumUserAddDto](doc//AlbumUserAddDto.md)
|
- [AlbumUserAddDto](doc//AlbumUserAddDto.md)
|
||||||
|
- [AlbumUserCreateDto](doc//AlbumUserCreateDto.md)
|
||||||
- [AlbumUserResponseDto](doc//AlbumUserResponseDto.md)
|
- [AlbumUserResponseDto](doc//AlbumUserResponseDto.md)
|
||||||
- [AlbumUserRole](doc//AlbumUserRole.md)
|
- [AlbumUserRole](doc//AlbumUserRole.md)
|
||||||
- [AllJobStatusResponseDto](doc//AllJobStatusResponseDto.md)
|
- [AllJobStatusResponseDto](doc//AllJobStatusResponseDto.md)
|
||||||
|
16
mobile/openapi/doc/AlbumUserCreateDto.md
generated
Normal file
16
mobile/openapi/doc/AlbumUserCreateDto.md
generated
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# openapi.model.AlbumUserCreateDto
|
||||||
|
|
||||||
|
## Load the model package
|
||||||
|
```dart
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
```
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**role** | [**AlbumUserRole**](AlbumUserRole.md) | |
|
||||||
|
**userId** | **String** | |
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
3
mobile/openapi/doc/CreateAlbumDto.md
generated
3
mobile/openapi/doc/CreateAlbumDto.md
generated
@ -9,9 +9,10 @@ import 'package:openapi/api.dart';
|
|||||||
Name | Type | Description | Notes
|
Name | Type | Description | Notes
|
||||||
------------ | ------------- | ------------- | -------------
|
------------ | ------------- | ------------- | -------------
|
||||||
**albumName** | **String** | |
|
**albumName** | **String** | |
|
||||||
|
**albumUsers** | [**List<AlbumUserCreateDto>**](AlbumUserCreateDto.md) | This property was added in v1.104.0 | [optional] [default to const []]
|
||||||
**assetIds** | **List<String>** | | [optional] [default to const []]
|
**assetIds** | **List<String>** | | [optional] [default to const []]
|
||||||
**description** | **String** | | [optional]
|
**description** | **String** | | [optional]
|
||||||
**sharedWithUserIds** | **List<String>** | | [optional] [default to const []]
|
**sharedWithUserIds** | **List<String>** | This property was deprecated in v1.104.0 | [optional] [default to const []]
|
||||||
|
|
||||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.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)
|
||||||
|
|
||||||
|
1
mobile/openapi/lib/api.dart
generated
1
mobile/openapi/lib/api.dart
generated
@ -68,6 +68,7 @@ part 'model/admin_onboarding_update_dto.dart';
|
|||||||
part 'model/album_count_response_dto.dart';
|
part 'model/album_count_response_dto.dart';
|
||||||
part 'model/album_response_dto.dart';
|
part 'model/album_response_dto.dart';
|
||||||
part 'model/album_user_add_dto.dart';
|
part 'model/album_user_add_dto.dart';
|
||||||
|
part 'model/album_user_create_dto.dart';
|
||||||
part 'model/album_user_response_dto.dart';
|
part 'model/album_user_response_dto.dart';
|
||||||
part 'model/album_user_role.dart';
|
part 'model/album_user_role.dart';
|
||||||
part 'model/all_job_status_response_dto.dart';
|
part 'model/all_job_status_response_dto.dart';
|
||||||
|
2
mobile/openapi/lib/api_client.dart
generated
2
mobile/openapi/lib/api_client.dart
generated
@ -206,6 +206,8 @@ class ApiClient {
|
|||||||
return AlbumResponseDto.fromJson(value);
|
return AlbumResponseDto.fromJson(value);
|
||||||
case 'AlbumUserAddDto':
|
case 'AlbumUserAddDto':
|
||||||
return AlbumUserAddDto.fromJson(value);
|
return AlbumUserAddDto.fromJson(value);
|
||||||
|
case 'AlbumUserCreateDto':
|
||||||
|
return AlbumUserCreateDto.fromJson(value);
|
||||||
case 'AlbumUserResponseDto':
|
case 'AlbumUserResponseDto':
|
||||||
return AlbumUserResponseDto.fromJson(value);
|
return AlbumUserResponseDto.fromJson(value);
|
||||||
case 'AlbumUserRole':
|
case 'AlbumUserRole':
|
||||||
|
106
mobile/openapi/lib/model/album_user_create_dto.dart
generated
Normal file
106
mobile/openapi/lib/model/album_user_create_dto.dart
generated
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
//
|
||||||
|
// 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 AlbumUserCreateDto {
|
||||||
|
/// Returns a new [AlbumUserCreateDto] instance.
|
||||||
|
AlbumUserCreateDto({
|
||||||
|
required this.role,
|
||||||
|
required this.userId,
|
||||||
|
});
|
||||||
|
|
||||||
|
AlbumUserRole role;
|
||||||
|
|
||||||
|
String userId;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) => identical(this, other) || other is AlbumUserCreateDto &&
|
||||||
|
other.role == role &&
|
||||||
|
other.userId == userId;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
// ignore: unnecessary_parenthesis
|
||||||
|
(role.hashCode) +
|
||||||
|
(userId.hashCode);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'AlbumUserCreateDto[role=$role, userId=$userId]';
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final json = <String, dynamic>{};
|
||||||
|
json[r'role'] = this.role;
|
||||||
|
json[r'userId'] = this.userId;
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a new [AlbumUserCreateDto] instance and imports its values from
|
||||||
|
/// [value] if it's a [Map], null otherwise.
|
||||||
|
// ignore: prefer_constructors_over_static_methods
|
||||||
|
static AlbumUserCreateDto? fromJson(dynamic value) {
|
||||||
|
if (value is Map) {
|
||||||
|
final json = value.cast<String, dynamic>();
|
||||||
|
|
||||||
|
return AlbumUserCreateDto(
|
||||||
|
role: AlbumUserRole.fromJson(json[r'role'])!,
|
||||||
|
userId: mapValueOfType<String>(json, r'userId')!,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<AlbumUserCreateDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final result = <AlbumUserCreateDto>[];
|
||||||
|
if (json is List && json.isNotEmpty) {
|
||||||
|
for (final row in json) {
|
||||||
|
final value = AlbumUserCreateDto.fromJson(row);
|
||||||
|
if (value != null) {
|
||||||
|
result.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toList(growable: growable);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Map<String, AlbumUserCreateDto> mapFromJson(dynamic json) {
|
||||||
|
final map = <String, AlbumUserCreateDto>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
final value = AlbumUserCreateDto.fromJson(entry.value);
|
||||||
|
if (value != null) {
|
||||||
|
map[entry.key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
// maps a json object with a list of AlbumUserCreateDto-objects as value to a dart map
|
||||||
|
static Map<String, List<AlbumUserCreateDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final map = <String, List<AlbumUserCreateDto>>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
json = json.cast<String, dynamic>();
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
map[entry.key] = AlbumUserCreateDto.listFromJson(entry.value, growable: growable,);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The list of required keys that must be present in a JSON.
|
||||||
|
static const requiredKeys = <String>{
|
||||||
|
'role',
|
||||||
|
'userId',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
11
mobile/openapi/lib/model/create_album_dto.dart
generated
11
mobile/openapi/lib/model/create_album_dto.dart
generated
@ -14,6 +14,7 @@ class CreateAlbumDto {
|
|||||||
/// Returns a new [CreateAlbumDto] instance.
|
/// Returns a new [CreateAlbumDto] instance.
|
||||||
CreateAlbumDto({
|
CreateAlbumDto({
|
||||||
required this.albumName,
|
required this.albumName,
|
||||||
|
this.albumUsers = const [],
|
||||||
this.assetIds = const [],
|
this.assetIds = const [],
|
||||||
this.description,
|
this.description,
|
||||||
this.sharedWithUserIds = const [],
|
this.sharedWithUserIds = const [],
|
||||||
@ -21,6 +22,9 @@ class CreateAlbumDto {
|
|||||||
|
|
||||||
String albumName;
|
String albumName;
|
||||||
|
|
||||||
|
/// This property was added in v1.104.0
|
||||||
|
List<AlbumUserCreateDto> albumUsers;
|
||||||
|
|
||||||
List<String> assetIds;
|
List<String> assetIds;
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -31,11 +35,13 @@ class CreateAlbumDto {
|
|||||||
///
|
///
|
||||||
String? description;
|
String? description;
|
||||||
|
|
||||||
|
/// This property was deprecated in v1.104.0
|
||||||
List<String> sharedWithUserIds;
|
List<String> sharedWithUserIds;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) => identical(this, other) || other is CreateAlbumDto &&
|
bool operator ==(Object other) => identical(this, other) || other is CreateAlbumDto &&
|
||||||
other.albumName == albumName &&
|
other.albumName == albumName &&
|
||||||
|
_deepEquality.equals(other.albumUsers, albumUsers) &&
|
||||||
_deepEquality.equals(other.assetIds, assetIds) &&
|
_deepEquality.equals(other.assetIds, assetIds) &&
|
||||||
other.description == description &&
|
other.description == description &&
|
||||||
_deepEquality.equals(other.sharedWithUserIds, sharedWithUserIds);
|
_deepEquality.equals(other.sharedWithUserIds, sharedWithUserIds);
|
||||||
@ -44,16 +50,18 @@ class CreateAlbumDto {
|
|||||||
int get hashCode =>
|
int get hashCode =>
|
||||||
// ignore: unnecessary_parenthesis
|
// ignore: unnecessary_parenthesis
|
||||||
(albumName.hashCode) +
|
(albumName.hashCode) +
|
||||||
|
(albumUsers.hashCode) +
|
||||||
(assetIds.hashCode) +
|
(assetIds.hashCode) +
|
||||||
(description == null ? 0 : description!.hashCode) +
|
(description == null ? 0 : description!.hashCode) +
|
||||||
(sharedWithUserIds.hashCode);
|
(sharedWithUserIds.hashCode);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => 'CreateAlbumDto[albumName=$albumName, assetIds=$assetIds, description=$description, sharedWithUserIds=$sharedWithUserIds]';
|
String toString() => 'CreateAlbumDto[albumName=$albumName, albumUsers=$albumUsers, assetIds=$assetIds, description=$description, sharedWithUserIds=$sharedWithUserIds]';
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final json = <String, dynamic>{};
|
final json = <String, dynamic>{};
|
||||||
json[r'albumName'] = this.albumName;
|
json[r'albumName'] = this.albumName;
|
||||||
|
json[r'albumUsers'] = this.albumUsers;
|
||||||
json[r'assetIds'] = this.assetIds;
|
json[r'assetIds'] = this.assetIds;
|
||||||
if (this.description != null) {
|
if (this.description != null) {
|
||||||
json[r'description'] = this.description;
|
json[r'description'] = this.description;
|
||||||
@ -73,6 +81,7 @@ class CreateAlbumDto {
|
|||||||
|
|
||||||
return CreateAlbumDto(
|
return CreateAlbumDto(
|
||||||
albumName: mapValueOfType<String>(json, r'albumName')!,
|
albumName: mapValueOfType<String>(json, r'albumName')!,
|
||||||
|
albumUsers: AlbumUserCreateDto.listFromJson(json[r'albumUsers']),
|
||||||
assetIds: json[r'assetIds'] is Iterable
|
assetIds: json[r'assetIds'] is Iterable
|
||||||
? (json[r'assetIds'] as Iterable).cast<String>().toList(growable: false)
|
? (json[r'assetIds'] as Iterable).cast<String>().toList(growable: false)
|
||||||
: const [],
|
: const [],
|
||||||
|
32
mobile/openapi/test/album_user_create_dto_test.dart
generated
Normal file
32
mobile/openapi/test/album_user_create_dto_test.dart
generated
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
//
|
||||||
|
// 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 AlbumUserCreateDto
|
||||||
|
void main() {
|
||||||
|
// final instance = AlbumUserCreateDto();
|
||||||
|
|
||||||
|
group('test AlbumUserCreateDto', () {
|
||||||
|
// AlbumUserRole role
|
||||||
|
test('to test the property `role`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// String userId
|
||||||
|
test('to test the property `userId`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
7
mobile/openapi/test/create_album_dto_test.dart
generated
7
mobile/openapi/test/create_album_dto_test.dart
generated
@ -21,6 +21,12 @@ void main() {
|
|||||||
// TODO
|
// TODO
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// This property was added in v1.104.0
|
||||||
|
// List<AlbumUserCreateDto> albumUsers (default value: const [])
|
||||||
|
test('to test the property `albumUsers`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
// List<String> assetIds (default value: const [])
|
// List<String> assetIds (default value: const [])
|
||||||
test('to test the property `assetIds`', () async {
|
test('to test the property `assetIds`', () async {
|
||||||
// TODO
|
// TODO
|
||||||
@ -31,6 +37,7 @@ void main() {
|
|||||||
// TODO
|
// TODO
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// This property was deprecated in v1.104.0
|
||||||
// List<String> sharedWithUserIds (default value: const [])
|
// List<String> sharedWithUserIds (default value: const [])
|
||||||
test('to test the property `sharedWithUserIds`', () async {
|
test('to test the property `sharedWithUserIds`', () async {
|
||||||
// TODO
|
// TODO
|
||||||
|
@ -6779,6 +6779,22 @@
|
|||||||
],
|
],
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
"AlbumUserCreateDto": {
|
||||||
|
"properties": {
|
||||||
|
"role": {
|
||||||
|
"$ref": "#/components/schemas/AlbumUserRole"
|
||||||
|
},
|
||||||
|
"userId": {
|
||||||
|
"format": "uuid",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"role",
|
||||||
|
"userId"
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
"AlbumUserResponseDto": {
|
"AlbumUserResponseDto": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"role": {
|
"role": {
|
||||||
@ -7599,6 +7615,13 @@
|
|||||||
"albumName": {
|
"albumName": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"albumUsers": {
|
||||||
|
"description": "This property was added in v1.104.0",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/AlbumUserCreateDto"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
"assetIds": {
|
"assetIds": {
|
||||||
"items": {
|
"items": {
|
||||||
"format": "uuid",
|
"format": "uuid",
|
||||||
@ -7610,6 +7633,8 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"sharedWithUserIds": {
|
"sharedWithUserIds": {
|
||||||
|
"deprecated": true,
|
||||||
|
"description": "This property was deprecated in v1.104.0",
|
||||||
"items": {
|
"items": {
|
||||||
"format": "uuid",
|
"format": "uuid",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
@ -169,10 +169,17 @@ export type AlbumResponseDto = {
|
|||||||
startDate?: string;
|
startDate?: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
};
|
};
|
||||||
|
export type AlbumUserCreateDto = {
|
||||||
|
role: AlbumUserRole;
|
||||||
|
userId: string;
|
||||||
|
};
|
||||||
export type CreateAlbumDto = {
|
export type CreateAlbumDto = {
|
||||||
albumName: string;
|
albumName: string;
|
||||||
|
/** This property was added in v1.104.0 */
|
||||||
|
albumUsers?: AlbumUserCreateDto[];
|
||||||
assetIds?: string[];
|
assetIds?: string[];
|
||||||
description?: string;
|
description?: string;
|
||||||
|
/** This property was deprecated in v1.104.0 */
|
||||||
sharedWithUserIds?: string[];
|
sharedWithUserIds?: string[];
|
||||||
};
|
};
|
||||||
export type AlbumCountResponseDto = {
|
export type AlbumCountResponseDto = {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { ArrayNotEmpty, IsEnum, IsString } from 'class-validator';
|
import { Type } from 'class-transformer';
|
||||||
|
import { ArrayNotEmpty, IsArray, IsEnum, IsString, ValidateNested } from 'class-validator';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { PropertyLifecycle } from 'src/decorators';
|
import { PropertyLifecycle } from 'src/decorators';
|
||||||
import { AssetResponseDto, mapAsset } from 'src/dtos/asset-response.dto';
|
import { AssetResponseDto, mapAsset } from 'src/dtos/asset-response.dto';
|
||||||
@ -32,6 +33,14 @@ export class AddUsersDto {
|
|||||||
albumUsers!: AlbumUserAddDto[];
|
albumUsers!: AlbumUserAddDto[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AlbumUserCreateDto {
|
||||||
|
@ValidateUUID()
|
||||||
|
userId!: string;
|
||||||
|
|
||||||
|
@IsEnum(AlbumUserRole)
|
||||||
|
role!: AlbumUserRole;
|
||||||
|
}
|
||||||
|
|
||||||
export class CreateAlbumDto {
|
export class CreateAlbumDto {
|
||||||
@IsString()
|
@IsString()
|
||||||
@ApiProperty()
|
@ApiProperty()
|
||||||
@ -41,7 +50,15 @@ export class CreateAlbumDto {
|
|||||||
@Optional()
|
@Optional()
|
||||||
description?: string;
|
description?: string;
|
||||||
|
|
||||||
|
@Optional()
|
||||||
|
@IsArray()
|
||||||
|
@ValidateNested({ each: true })
|
||||||
|
@Type(() => AlbumUserCreateDto)
|
||||||
|
@PropertyLifecycle({ addedAt: 'v1.104.0' })
|
||||||
|
albumUsers?: AlbumUserCreateDto[];
|
||||||
|
|
||||||
@ValidateUUID({ optional: true, each: true })
|
@ValidateUUID({ optional: true, each: true })
|
||||||
|
@PropertyLifecycle({ deprecatedAt: 'v1.104.0' })
|
||||||
sharedWithUserIds?: string[];
|
sharedWithUserIds?: string[];
|
||||||
|
|
||||||
@ValidateUUID({ optional: true, each: true })
|
@ValidateUUID({ optional: true, each: true })
|
||||||
|
@ -281,11 +281,11 @@ export class AlbumRepository implements IAlbumRepository {
|
|||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
async create(album: Partial<AlbumEntity>): Promise<AlbumEntity> {
|
create(album: Partial<AlbumEntity>): Promise<AlbumEntity> {
|
||||||
return this.save(album);
|
return this.save(album);
|
||||||
}
|
}
|
||||||
|
|
||||||
async update(album: Partial<AlbumEntity>): Promise<AlbumEntity> {
|
update(album: Partial<AlbumEntity>): Promise<AlbumEntity> {
|
||||||
return this.save(album);
|
return this.save(album);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,7 +194,7 @@ describe(AlbumService.name, () => {
|
|||||||
ownerId: authStub.admin.user.id,
|
ownerId: authStub.admin.user.id,
|
||||||
albumName: albumStub.empty.albumName,
|
albumName: albumStub.empty.albumName,
|
||||||
description: albumStub.empty.description,
|
description: albumStub.empty.description,
|
||||||
albumUsers: [{ user: { id: 'user-id' } }],
|
albumUsers: [{ userId: 'user-id', role: AlbumUserRole.EDITOR }],
|
||||||
assets: [{ id: '123' }],
|
assets: [{ id: '123' }],
|
||||||
albumThumbnailAssetId: '123',
|
albumThumbnailAssetId: '123',
|
||||||
});
|
});
|
||||||
|
@ -114,7 +114,12 @@ export class AlbumService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async create(auth: AuthDto, dto: CreateAlbumDto): Promise<AlbumResponseDto> {
|
async create(auth: AuthDto, dto: CreateAlbumDto): Promise<AlbumResponseDto> {
|
||||||
|
const albumUsers = dto.albumUsers || [];
|
||||||
for (const userId of dto.sharedWithUserIds || []) {
|
for (const userId of dto.sharedWithUserIds || []) {
|
||||||
|
albumUsers.push({ userId, role: AlbumUserRole.EDITOR });
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const { userId } of albumUsers) {
|
||||||
const exists = await this.userRepository.get(userId, {});
|
const exists = await this.userRepository.get(userId, {});
|
||||||
if (!exists) {
|
if (!exists) {
|
||||||
throw new BadRequestException('User not found');
|
throw new BadRequestException('User not found');
|
||||||
@ -128,7 +133,7 @@ export class AlbumService {
|
|||||||
ownerId: auth.user.id,
|
ownerId: auth.user.id,
|
||||||
albumName: dto.albumName,
|
albumName: dto.albumName,
|
||||||
description: dto.description,
|
description: dto.description,
|
||||||
albumUsers: dto.sharedWithUserIds?.map((userId) => ({ user: { id: userId } }) as AlbumUserEntity) ?? [],
|
albumUsers: albumUsers.map((albumUser) => albumUser as AlbumUserEntity) ?? [],
|
||||||
assets,
|
assets,
|
||||||
albumThumbnailAssetId: assets[0]?.id || null,
|
albumThumbnailAssetId: assets[0]?.id || null,
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user