add role to addUsersToAlbum endpoint

This commit is contained in:
mgabor
2024-04-24 11:36:09 +02:00
parent dd149e5235
commit 5bb3ddb1f5
14 changed files with 246 additions and 11 deletions
+3
View File
@@ -12,6 +12,7 @@ doc/ActivityApi.md
doc/ActivityCreateDto.md doc/ActivityCreateDto.md
doc/ActivityResponseDto.md doc/ActivityResponseDto.md
doc/ActivityStatisticsResponseDto.md doc/ActivityStatisticsResponseDto.md
doc/AddUserDto.md
doc/AddUsersDto.md doc/AddUsersDto.md
doc/AdminOnboardingUpdateDto.md doc/AdminOnboardingUpdateDto.md
doc/AlbumApi.md doc/AlbumApi.md
@@ -248,6 +249,7 @@ lib/auth/oauth.dart
lib/model/activity_create_dto.dart lib/model/activity_create_dto.dart
lib/model/activity_response_dto.dart lib/model/activity_response_dto.dart
lib/model/activity_statistics_response_dto.dart lib/model/activity_statistics_response_dto.dart
lib/model/add_user_dto.dart
lib/model/add_users_dto.dart lib/model/add_users_dto.dart
lib/model/admin_onboarding_update_dto.dart lib/model/admin_onboarding_update_dto.dart
lib/model/album_count_response_dto.dart lib/model/album_count_response_dto.dart
@@ -430,6 +432,7 @@ test/activity_api_test.dart
test/activity_create_dto_test.dart test/activity_create_dto_test.dart
test/activity_response_dto_test.dart test/activity_response_dto_test.dart
test/activity_statistics_response_dto_test.dart test/activity_statistics_response_dto_test.dart
test/add_user_dto_test.dart
test/add_users_dto_test.dart test/add_users_dto_test.dart
test/admin_onboarding_update_dto_test.dart test/admin_onboarding_update_dto_test.dart
test/album_api_test.dart test/album_api_test.dart
+1
View File
@@ -235,6 +235,7 @@ Class | Method | HTTP request | Description
- [ActivityCreateDto](doc//ActivityCreateDto.md) - [ActivityCreateDto](doc//ActivityCreateDto.md)
- [ActivityResponseDto](doc//ActivityResponseDto.md) - [ActivityResponseDto](doc//ActivityResponseDto.md)
- [ActivityStatisticsResponseDto](doc//ActivityStatisticsResponseDto.md) - [ActivityStatisticsResponseDto](doc//ActivityStatisticsResponseDto.md)
- [AddUserDto](doc//AddUserDto.md)
- [AddUsersDto](doc//AddUsersDto.md) - [AddUsersDto](doc//AddUsersDto.md)
- [AdminOnboardingUpdateDto](doc//AdminOnboardingUpdateDto.md) - [AdminOnboardingUpdateDto](doc//AdminOnboardingUpdateDto.md)
- [AlbumCountResponseDto](doc//AlbumCountResponseDto.md) - [AlbumCountResponseDto](doc//AlbumCountResponseDto.md)
+16
View File
@@ -0,0 +1,16 @@
# openapi.model.AddUserDto
## Load the model package
```dart
import 'package:openapi/api.dart';
```
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**role** | [**AlbumUserRole**](AlbumUserRole.md) | | [optional]
**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)
+2 -1
View File
@@ -8,7 +8,8 @@ import 'package:openapi/api.dart';
## Properties ## Properties
Name | Type | Description | Notes Name | Type | Description | Notes
------------ | ------------- | ------------- | ------------- ------------ | ------------- | ------------- | -------------
**sharedUserIds** | **List<String>** | | [default to const []] **albumUsers** | [**List<AddUserDto>**](AddUserDto.md) | | [default to const []]
**sharedUserIds** | **List<String>** | Deprecated in favor of albumUsers | [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
View File
@@ -63,6 +63,7 @@ part 'model/api_key_update_dto.dart';
part 'model/activity_create_dto.dart'; part 'model/activity_create_dto.dart';
part 'model/activity_response_dto.dart'; part 'model/activity_response_dto.dart';
part 'model/activity_statistics_response_dto.dart'; part 'model/activity_statistics_response_dto.dart';
part 'model/add_user_dto.dart';
part 'model/add_users_dto.dart'; part 'model/add_users_dto.dart';
part 'model/admin_onboarding_update_dto.dart'; part 'model/admin_onboarding_update_dto.dart';
part 'model/album_count_response_dto.dart'; part 'model/album_count_response_dto.dart';
+2
View File
@@ -196,6 +196,8 @@ class ApiClient {
return ActivityResponseDto.fromJson(value); return ActivityResponseDto.fromJson(value);
case 'ActivityStatisticsResponseDto': case 'ActivityStatisticsResponseDto':
return ActivityStatisticsResponseDto.fromJson(value); return ActivityStatisticsResponseDto.fromJson(value);
case 'AddUserDto':
return AddUserDto.fromJson(value);
case 'AddUsersDto': case 'AddUsersDto':
return AddUsersDto.fromJson(value); return AddUsersDto.fromJson(value);
case 'AdminOnboardingUpdateDto': case 'AdminOnboardingUpdateDto':
+115
View File
@@ -0,0 +1,115 @@
//
// 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 AddUserDto {
/// Returns a new [AddUserDto] instance.
AddUserDto({
this.role,
required this.userId,
});
///
/// 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.
///
AlbumUserRole? role;
String userId;
@override
bool operator ==(Object other) => identical(this, other) || other is AddUserDto &&
other.role == role &&
other.userId == userId;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(role == null ? 0 : role!.hashCode) +
(userId.hashCode);
@override
String toString() => 'AddUserDto[role=$role, userId=$userId]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
if (this.role != null) {
json[r'role'] = this.role;
} else {
// json[r'role'] = null;
}
json[r'userId'] = this.userId;
return json;
}
/// Returns a new [AddUserDto] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static AddUserDto? fromJson(dynamic value) {
if (value is Map) {
final json = value.cast<String, dynamic>();
return AddUserDto(
role: AlbumUserRole.fromJson(json[r'role']),
userId: mapValueOfType<String>(json, r'userId')!,
);
}
return null;
}
static List<AddUserDto> listFromJson(dynamic json, {bool growable = false,}) {
final result = <AddUserDto>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = AddUserDto.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
static Map<String, AddUserDto> mapFromJson(dynamic json) {
final map = <String, AddUserDto>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = AddUserDto.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
}
}
return map;
}
// maps a json object with a list of AddUserDto-objects as value to a dart map
static Map<String, List<AddUserDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<AddUserDto>>{};
if (json is Map && json.isNotEmpty) {
// ignore: parameter_assignments
json = json.cast<String, dynamic>();
for (final entry in json.entries) {
map[entry.key] = AddUserDto.listFromJson(entry.value, growable: growable,);
}
}
return map;
}
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'userId',
};
}
+10 -2
View File
@@ -13,25 +13,32 @@ part of openapi.api;
class AddUsersDto { class AddUsersDto {
/// Returns a new [AddUsersDto] instance. /// Returns a new [AddUsersDto] instance.
AddUsersDto({ AddUsersDto({
this.albumUsers = const [],
this.sharedUserIds = const [], this.sharedUserIds = const [],
}); });
List<AddUserDto> albumUsers;
/// Deprecated in favor of albumUsers
List<String> sharedUserIds; List<String> sharedUserIds;
@override @override
bool operator ==(Object other) => identical(this, other) || other is AddUsersDto && bool operator ==(Object other) => identical(this, other) || other is AddUsersDto &&
_deepEquality.equals(other.albumUsers, albumUsers) &&
_deepEquality.equals(other.sharedUserIds, sharedUserIds); _deepEquality.equals(other.sharedUserIds, sharedUserIds);
@override @override
int get hashCode => int get hashCode =>
// ignore: unnecessary_parenthesis // ignore: unnecessary_parenthesis
(albumUsers.hashCode) +
(sharedUserIds.hashCode); (sharedUserIds.hashCode);
@override @override
String toString() => 'AddUsersDto[sharedUserIds=$sharedUserIds]'; String toString() => 'AddUsersDto[albumUsers=$albumUsers, sharedUserIds=$sharedUserIds]';
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final json = <String, dynamic>{}; final json = <String, dynamic>{};
json[r'albumUsers'] = this.albumUsers;
json[r'sharedUserIds'] = this.sharedUserIds; json[r'sharedUserIds'] = this.sharedUserIds;
return json; return json;
} }
@@ -44,6 +51,7 @@ class AddUsersDto {
final json = value.cast<String, dynamic>(); final json = value.cast<String, dynamic>();
return AddUsersDto( return AddUsersDto(
albumUsers: AddUserDto.listFromJson(json[r'albumUsers']),
sharedUserIds: json[r'sharedUserIds'] is Iterable sharedUserIds: json[r'sharedUserIds'] is Iterable
? (json[r'sharedUserIds'] as Iterable).cast<String>().toList(growable: false) ? (json[r'sharedUserIds'] as Iterable).cast<String>().toList(growable: false)
: const [], : const [],
@@ -94,7 +102,7 @@ class AddUsersDto {
/// The list of required keys that must be present in a JSON. /// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{ static const requiredKeys = <String>{
'sharedUserIds', 'albumUsers',
}; };
} }
+32
View 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 AddUserDto
void main() {
// final instance = AddUserDto();
group('test AddUserDto', () {
// AlbumUserRole role
test('to test the property `role`', () async {
// TODO
});
// String userId
test('to test the property `userId`', () async {
// TODO
});
});
}
+6
View File
@@ -16,6 +16,12 @@ void main() {
// final instance = AddUsersDto(); // final instance = AddUsersDto();
group('test AddUsersDto', () { group('test AddUsersDto', () {
// List<AddUserDto> albumUsers (default value: const [])
test('to test the property `albumUsers`', () async {
// TODO
});
// Deprecated in favor of albumUsers
// List<String> sharedUserIds (default value: const []) // List<String> sharedUserIds (default value: const [])
test('to test the property `sharedUserIds`', () async { test('to test the property `sharedUserIds`', () async {
// TODO // TODO
+24 -1
View File
@@ -7300,9 +7300,32 @@
], ],
"type": "object" "type": "object"
}, },
"AddUserDto": {
"properties": {
"role": {
"$ref": "#/components/schemas/AlbumUserRole"
},
"userId": {
"format": "uuid",
"type": "string"
}
},
"required": [
"userId"
],
"type": "object"
},
"AddUsersDto": { "AddUsersDto": {
"properties": { "properties": {
"albumUsers": {
"items": {
"$ref": "#/components/schemas/AddUserDto"
},
"type": "array"
},
"sharedUserIds": { "sharedUserIds": {
"deprecated": true,
"description": "Deprecated in favor of albumUsers",
"items": { "items": {
"format": "uuid", "format": "uuid",
"type": "string" "type": "string"
@@ -7311,7 +7334,7 @@
} }
}, },
"required": [ "required": [
"sharedUserIds" "albumUsers"
], ],
"type": "object" "type": "object"
}, },
+7 -1
View File
@@ -196,8 +196,14 @@ export type BulkIdResponseDto = {
export type UpdateAlbumUserDto = { export type UpdateAlbumUserDto = {
role: AlbumUserRole; role: AlbumUserRole;
}; };
export type AddUserDto = {
role?: AlbumUserRole;
userId: string;
};
export type AddUsersDto = { export type AddUsersDto = {
sharedUserIds: string[]; albumUsers: AddUserDto[];
/** Deprecated in favor of albumUsers */
sharedUserIds?: string[];
}; };
export type ApiKeyResponseDto = { export type ApiKeyResponseDto = {
createdAt: string; createdAt: string;
+15 -2
View File
@@ -13,10 +13,23 @@ export class AlbumInfoDto {
withoutAssets?: boolean; withoutAssets?: boolean;
} }
export class AddUserDto {
@ValidateUUID()
userId!: string;
@IsEnum(AlbumUserRole)
@ApiProperty({ enum: AlbumUserRole, enumName: 'AlbumUserRole', default: AlbumUserRole.EDITOR })
role?: AlbumUserRole;
}
export class AddUsersDto { export class AddUsersDto {
@ValidateUUID({ each: true }) @ValidateUUID({ each: true, optional: true })
@ArrayNotEmpty() @ArrayNotEmpty()
sharedUserIds!: string[]; @ApiProperty({ deprecated: true, description: 'Deprecated in favor of albumUsers' })
sharedUserIds?: string[];
@ArrayNotEmpty()
albumUsers!: AddUserDto[];
} }
export class CreateAlbumDto { export class CreateAlbumDto {
+12 -4
View File
@@ -14,7 +14,7 @@ import {
} from 'src/dtos/album.dto'; } from 'src/dtos/album.dto';
import { BulkIdResponseDto, BulkIdsDto } from 'src/dtos/asset-ids.response.dto'; import { BulkIdResponseDto, BulkIdsDto } from 'src/dtos/asset-ids.response.dto';
import { AuthDto } from 'src/dtos/auth.dto'; import { AuthDto } from 'src/dtos/auth.dto';
import { AlbumUserEntity } from 'src/entities/album-user.entity'; import { AlbumUserEntity, AlbumUserRole } from 'src/entities/album-user.entity';
import { AlbumEntity } from 'src/entities/album.entity'; import { AlbumEntity } from 'src/entities/album.entity';
import { AssetEntity } from 'src/entities/asset.entity'; import { AssetEntity } from 'src/entities/asset.entity';
import { IAccessRepository } from 'src/interfaces/access.interface'; import { IAccessRepository } from 'src/interfaces/access.interface';
@@ -211,12 +211,20 @@ export class AlbumService {
return results; return results;
} }
async addUsers(auth: AuthDto, id: string, dto: AddUsersDto): Promise<AlbumResponseDto> { async addUsers(auth: AuthDto, id: string, { albumUsers, sharedUserIds }: AddUsersDto): Promise<AlbumResponseDto> {
// Remove once deprecated sharedUserIds is removed
if (!albumUsers) {
if (!sharedUserIds) {
throw new BadRequestException('No users provided');
}
albumUsers = sharedUserIds.map((userId) => ({ userId, role: AlbumUserRole.EDITOR }));
}
await this.access.requirePermission(auth, Permission.ALBUM_SHARE, id); await this.access.requirePermission(auth, Permission.ALBUM_SHARE, id);
const album = await this.findOrFail(id, { withAssets: false }); const album = await this.findOrFail(id, { withAssets: false });
for (const userId of dto.sharedUserIds) { for (const { userId, role } of albumUsers) {
if (album.ownerId === userId) { if (album.ownerId === userId) {
throw new BadRequestException('Cannot be shared with owner'); throw new BadRequestException('Cannot be shared with owner');
} }
@@ -231,7 +239,7 @@ export class AlbumService {
throw new BadRequestException('User not found'); throw new BadRequestException('User not found');
} }
await this.albumUserRepository.create({ userId: userId, albumId: id }); await this.albumUserRepository.create({ userId: userId, albumId: id, role });
} }
return this.findOrFail(id, { withAssets: true }).then(mapAlbumWithoutAssets); return this.findOrFail(id, { withAssets: true }).then(mapAlbumWithoutAssets);