Skip to content

Commit 4a18bf7

Browse files
committed
add api update author
1 parent e7b7954 commit 4a18bf7

5 files changed

Lines changed: 140 additions & 9 deletions

File tree

constant/config.message.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,4 +94,5 @@ class ErrorMessage {
9494
static const String MISSING_QUERY_PARAM = 'query không được rỗng';
9595
static const String INVALID_AVATAR_AUTHOR =
9696
'Ảnh đại diện tác giả không hợp lệ';
97+
static const String INVALID_AUTHOR_ID = 'authorId không tồn tại ';
9798
}

controllers/author_controller.dart

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,17 @@ class AuthorController {
2020
await _authorRepository.showAuthorPaging(offset: offset, limit: limit);
2121
return author;
2222
}
23+
2324
Future<int?> createAuthor(Author author, String avatarPath) async {
24-
final authorId =
25-
await _authorRepository.createAuthor(author, avatarPath);
25+
final authorId = await _authorRepository.createAuthor(author, avatarPath);
2626
return authorId;
2727
}
28+
29+
Future<Author?> updateAuthor(
30+
int authorId,
31+
Map<String, dynamic> updateFields,
32+
) async {
33+
final author = await _authorRepository.updateAuthor(authorId, updateFields);
34+
return author;
35+
}
2836
}

repository/author_repository.dart

Lines changed: 76 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ abstract class IAuthorRepo {
1515
Future<Author?> findAuthorByName(String name);
1616
Future<List<Author>> showAuthorPaging({int offset = 0, int limit = 8});
1717
Future<int?> createAuthor(Author author, String avatarPath);
18+
Future<Author?> updateAuthor(
19+
int authorId,
20+
Map<String, dynamic> updateFields,
21+
);
1822
}
1923

2024
class AuthorRepository implements IAuthorRepo {
@@ -37,7 +41,9 @@ class AuthorRepository implements IAuthorRepo {
3741

3842
if (authorResult.isEmpty || authorResult.first.isEmpty) {
3943
throw const CustomHttpException(
40-
ErrorMessage.AUTHOR_NOT_FOUND, HttpStatus.notFound,);
44+
ErrorMessage.AUTHOR_NOT_FOUND,
45+
HttpStatus.notFound,
46+
);
4147
}
4248

4349
final authorRow = authorResult.first;
@@ -212,16 +218,19 @@ SELECT al.id,
212218
@override
213219
Future<List<Author>> showAuthorPaging({int offset = 0, int limit = 8}) async {
214220
try {
215-
final authorResult = await _db.executor.execute(Sql.named('''
221+
final authorResult = await _db.executor.execute(
222+
Sql.named('''
216223
SELECT id, name,avatarUrl
217224
FROM author
218225
ORDER BY RANDOM()
219226
LIMIT @limit
220227
OFFSET @offset
221-
'''), parameters: {
222-
'limit': limit,
223-
'offset': offset,
224-
},);
228+
'''),
229+
parameters: {
230+
'limit': limit,
231+
'offset': offset,
232+
},
233+
);
225234

226235
if (authorResult.isEmpty) {
227236
return [];
@@ -288,6 +297,67 @@ OFFSET @offset
288297
}
289298
}
290299

300+
@override
301+
Future<Author?> updateAuthor(
302+
int authorId,
303+
Map<String, dynamic> updateFields,
304+
) async {
305+
try {
306+
final setClauseParts = <String>[];
307+
final parameters = <String, dynamic>{
308+
'id': authorId,
309+
'updatedAt': DateTime.now(),
310+
};
311+
312+
if (updateFields.containsKey('name')) {
313+
setClauseParts.add('name = @name');
314+
parameters['name'] = updateFields['name'];
315+
}
316+
if (updateFields.containsKey('description')) {
317+
setClauseParts.add('description = @description');
318+
parameters['description'] = updateFields['description'];
319+
}
320+
setClauseParts.add('updatedAt = @updatedAt');
321+
final setClause = setClauseParts.join(', ');
322+
final query = '''
323+
UPDATE author
324+
SET $setClause
325+
WHERE id = @id
326+
RETURNING id,name,description,avatarUrl,createdAt,updatedAt,followingCount
327+
''';
328+
329+
final result = await _db.executor.execute(
330+
Sql.named(query),
331+
parameters: parameters,
332+
);
333+
if (result.isEmpty || result.first.isEmpty) {
334+
throw const CustomHttpException(
335+
ErrorMessageSQL.SQL_QUERY_ERROR,
336+
HttpStatus.internalServerError,
337+
);
338+
}
339+
340+
final row = result.first;
341+
return Author(
342+
id: row[0]! as int,
343+
name: row[1]! as String,
344+
description: row[2]! as String,
345+
avatarUrl: row[3] as String?,
346+
followingCount: row[4]! as int,
347+
createdAt: _parseDate(row[5]),
348+
updatedAt: _parseDate(row[6]),
349+
);
350+
} catch (e) {
351+
if (e is CustomHttpException) {
352+
rethrow;
353+
}
354+
throw const CustomHttpException(
355+
ErrorMessageSQL.SQL_QUERY_ERROR,
356+
HttpStatus.internalServerError,
357+
);
358+
}
359+
}
360+
291361
DateTime? _parseDate(dynamic date) {
292362
if (date == null) {
293363
return null;
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import 'dart:io';
2+
3+
import 'package:dart_frog/dart_frog.dart';
4+
5+
import '../../../../constant/config.message.dart';
6+
import '../../../../controllers/author_controller.dart';
7+
import '../../../../exception/config.exception.dart';
8+
import '../../../../model/response.dart';
9+
import '../../../../model/users.dart';
10+
11+
Future<Response> onRequest(RequestContext context, String id) async {
12+
if (context.request.method.value != 'POST') {
13+
return AppResponse()
14+
.error(HttpStatus.methodNotAllowed, ErrorMessage.MSG_METHOD_NOT_ALLOW);
15+
}
16+
17+
18+
final authorController = context.read<AuthorController>();
19+
final user = context.read<User?>();
20+
if (user == null || user.role?.name != 'admin') {
21+
return AppResponse().error(HttpStatus.forbidden, ErrorMessage.FORBIDDEN);
22+
}
23+
24+
final authorId = int.tryParse(context.request.uri.pathSegments.last);
25+
if (authorId == null) {
26+
return AppResponse()
27+
.error(HttpStatus.badRequest, ErrorMessage.INVALID_AUTHOR_ID);
28+
}
29+
try{
30+
final body = await context.request.json() as Map<String,dynamic>;
31+
final updateFields = <String,dynamic>{};
32+
33+
if (body.containsKey('name')) {
34+
updateFields['name'] = body['name'].toString();
35+
}
36+
37+
if (body.containsKey('description')) {
38+
updateFields['description'] = body['description'].toString();
39+
}
40+
if (updateFields.isEmpty) {
41+
return AppResponse()
42+
.error(HttpStatus.badRequest, ErrorMessage.EMPTY_FIELD);
43+
}
44+
final result = await authorController.updateAuthor(authorId, updateFields);
45+
return AppResponse().ok(HttpStatus.ok, result?.toJson());
46+
} catch (e) {
47+
if (e is CustomHttpException) {
48+
return AppResponse().error(e.statusCode, e.message);
49+
}
50+
return AppResponse().error(HttpStatus.internalServerError, e.toString());
51+
}
52+
}

security/reset-password-token.security.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ Map<String, dynamic>? decodeResetToken(String token) {
3838
throw const CustomHttpException(
3939
ErrorMessage.TOKEN_INVALID, HttpStatus.internalServerError,);
4040
}
41-
}
41+
}
4242

4343
AppException? verifyResetToken(String token) {
4444
try {

0 commit comments

Comments
 (0)