Implement backend for displaying user info

Frontend display currently not working

Co-authored-by: Reimar <mail@reim.ar>
This commit is contained in:
Alexandertp 2024-09-11 15:34:03 +02:00
parent ebf81906ec
commit 4480080496
9 changed files with 89 additions and 15 deletions

View File

@ -0,0 +1,32 @@
using API.Models;
using API.Persistence.Repositories;
using Microsoft.AspNetCore.Mvc;
using Microsoft.VisualStudio.Web.CodeGenerators.Mvc.Templates.BlazorIdentity.Pages.Manage;
using Newtonsoft.Json.Linq;
namespace API.Application.Users.Queries
{
public class QueryUsersByIds
{
private readonly IUserRepository _repository;
public QueryUsersByIds(IUserRepository repository)
{
_repository = repository;
}
public async Task<ActionResult<List<UserDTO>>> Handle(List<string> ids)
{
List<User> users = await _repository.QueryUsersByIdsAsync(ids);
if (users == null)
{
return new ConflictObjectResult(new { message = "No user on given Id" });
}
return new OkObjectResult(users.Select(user => new { id = user.Id, email = user.Email, username = user.Username, profilePicture = user.ProfilePicture, createdAt = user.CreatedAt }));
}
}
}

View File

@ -22,36 +22,35 @@ namespace API.Controllers
{ {
private readonly QueryAllUsers _queryAllUsers; private readonly QueryAllUsers _queryAllUsers;
private readonly QueryUserById _queryUserById; private readonly QueryUserById _queryUserById;
private readonly QueryUsersByIds _queryUsersByIds;
private readonly CreateUser _createUser; private readonly CreateUser _createUser;
private readonly UpdateUser _updateUser; private readonly UpdateUser _updateUser;
private readonly DeleteUser _deleteUser; private readonly DeleteUser _deleteUser;
private readonly LoginUser _loginUser; private readonly LoginUser _loginUser;
private readonly TokenHelper _tokenHelper; private readonly TokenHelper _tokenHelper;
private readonly IUserRepository _repository; private readonly IUserRepository _repository;
public UsersController( public UsersController(
QueryAllUsers queryAllUsers, QueryAllUsers queryAllUsers,
QueryUserById queryUserById, QueryUserById queryUserById,
QueryUsersByIds queryUsersByIds,
CreateUser createUser, CreateUser createUser,
UpdateUser updateUser, UpdateUser updateUser,
DeleteUser deleteUser, DeleteUser deleteUser,
LoginUser loginUser, LoginUser loginUser,
TokenHelper tokenHelper, TokenHelper tokenHelper,
IUserRepository repository IUserRepository repository
) )
{ {
_queryAllUsers = queryAllUsers; _queryAllUsers = queryAllUsers;
_queryUserById = queryUserById; _queryUserById = queryUserById;
_queryUsersByIds = queryUsersByIds;
_createUser = createUser; _createUser = createUser;
_updateUser = updateUser; _updateUser = updateUser;
_deleteUser = deleteUser; _deleteUser = deleteUser;
_loginUser = loginUser; _loginUser = loginUser;
_tokenHelper = tokenHelper; _tokenHelper = tokenHelper;
_repository = repository; _repository = repository;
} }
[HttpPost("login")] [HttpPost("login")]
@ -73,9 +72,15 @@ namespace API.Controllers
return await _queryUserById.Handle(id); return await _queryUserById.Handle(id);
} }
[HttpGet("UsersByIds")]
public async Task<ActionResult<List<UserDTO>>> GetUsersByIds(List<string> userIds)
{
return await _queryUsersByIds.Handle(userIds);
}
[Authorize] [Authorize]
[HttpPut] [HttpPut]
public async Task<IActionResult> PutUser([FromForm ]UpdateUserDTO UpdateUserDTO) public async Task<IActionResult> PutUser([FromForm] UpdateUserDTO UpdateUserDTO)
{ {
return await _updateUser.Handle(UpdateUserDTO); return await _updateUser.Handle(UpdateUserDTO);
} }

View File

@ -8,6 +8,7 @@ namespace API.Persistence.Repositories
Task<bool> DeleteUserAsync(string id); Task<bool> DeleteUserAsync(string id);
Task<List<User>> QueryAllUsersAsync(); Task<List<User>> QueryAllUsersAsync();
Task<User> QueryUserByIdAsync(string id); Task<User> QueryUserByIdAsync(string id);
Task<List<User>> QueryUsersByIdsAsync(List<string> ids);
Task<User> QueryUserByEmailAsync(string email); Task<User> QueryUserByEmailAsync(string email);
Task<bool> UpdateUserAsync(User user); Task<bool> UpdateUserAsync(User user);
Task<User> QueryUserByRefreshTokenAsync(string refreshToken); Task<User> QueryUserByRefreshTokenAsync(string refreshToken);

View File

@ -1,5 +1,6 @@
using API.Models; using API.Models;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.VisualStudio.Web.CodeGenerators.Mvc.Templates.BlazorIdentity.Pages; using Microsoft.VisualStudio.Web.CodeGenerators.Mvc.Templates.BlazorIdentity.Pages;
namespace API.Persistence.Repositories namespace API.Persistence.Repositories
@ -25,6 +26,18 @@ namespace API.Persistence.Repositories
} }
} }
public async Task<List<User>> QueryUsersByIdsAsync(List<string> ids)
{
try
{
return _context.Users.Where(user => ids.Contains(user.Id)).ToList();
}
catch (Exception)
{
return [];
}
}
public async Task<string> CreateUserAsync(User user) public async Task<string> CreateUserAsync(User user)
{ {
try try

View File

@ -43,7 +43,7 @@ namespace API
builder.Services.AddScoped<DeleteUser>(); builder.Services.AddScoped<DeleteUser>();
builder.Services.AddScoped<LoginUser>(); builder.Services.AddScoped<LoginUser>();
builder.Services.AddScoped<IUserRepository, UserRepository>(); builder.Services.AddScoped<IUserRepository, UserRepository>();
builder.Services.AddScoped<QueryUsersByIds>();
IConfiguration Configuration = builder.Configuration; IConfiguration Configuration = builder.Configuration;

View File

@ -22,7 +22,7 @@ Future<String?> request(BuildContext? context, ApiService service, String method
}; };
final token = prefs.getString('token'); final token = prefs.getString('token');
final Map<String, String> headers = {}; final Map<String, String> headers = {'Accept': 'application/json'};
if (token != null) headers.addAll({'Authorization': 'Bearer $token'}); if (token != null) headers.addAll({'Authorization': 'Bearer $token'});
final http.Response response; final http.Response response;
@ -47,7 +47,7 @@ Future<String?> request(BuildContext? context, ApiService service, String method
); );
} }
} catch (e) { } catch (e) {
debugPrint(e.toString()); debugPrint('Can\'t send requst: ' + e.toString());
messenger?.showSnackBar(const SnackBar(content: Text('Unable to connect to server'))); messenger?.showSnackBar(const SnackBar(content: Text('Unable to connect to server')));
return null; return null;
} }
@ -58,7 +58,7 @@ Future<String?> request(BuildContext? context, ApiService service, String method
messenger?.showSnackBar(SnackBar(content: Text(json['message'] ?? json['title']))); messenger?.showSnackBar(SnackBar(content: Text(json['message'] ?? json['title'])));
debugPrint('API error: ' + json['message']); debugPrint('API error: ' + json['message']);
} catch (e) { } catch (e) {
debugPrint(e.toString()); debugPrint('Can\'t parse response: ' + e.toString());
messenger?.showSnackBar(SnackBar(content: Text('Something went wrong (HTTP ${response.statusCode})'))); messenger?.showSnackBar(SnackBar(content: Text('Something went wrong (HTTP ${response.statusCode})')));
} }
return null; return null;

View File

@ -1,3 +1,5 @@
import 'dart:convert';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:mobile/base/sidemenu.dart'; import 'package:mobile/base/sidemenu.dart';
@ -12,6 +14,27 @@ class ReviewListPage extends StatefulWidget {
} }
class _ReviewListState extends State<ReviewListPage> { class _ReviewListState extends State<ReviewListPage> {
List<models.User> users = [];
@override
void didChangeDependencies() async {
super.didChangeDependencies();
final arg = ModalRoute.of(context)!.settings.arguments as models.ReviewList;
final reviews = arg.reviews;
final userIds = reviews.map((review) => review.userId).toSet().toList();
final queryParams = userIds.map((id) => "userIds=$id");
final queryString = "?${queryParams.join("&")}";
final response = await api.request(context, api.ApiService.auth, 'GET', '/api/Users/UsersByIds$queryString', null);
if (response == null) return;
debugPrint('response: ' + response);
users = (jsonDecode(response) as List<dynamic>).map((user) => models.User.fromJson(user)).toList();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final arg = ModalRoute.of(context)!.settings.arguments as models.ReviewList; final arg = ModalRoute.of(context)!.settings.arguments as models.ReviewList;

View File

@ -194,10 +194,10 @@ packages:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: flutter_lints name: flutter_lints
sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1" sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.2" version: "4.0.0"
flutter_map: flutter_map:
dependency: "direct main" dependency: "direct main"
description: description:
@ -412,10 +412,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: lints name: lints
sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290 sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.0" version: "4.0.0"
lists: lists:
dependency: transitive dependency: transitive
description: description:

View File

@ -53,7 +53,7 @@ dev_dependencies:
# activated in the `analysis_options.yaml` file located at the root of your # activated in the `analysis_options.yaml` file located at the root of your
# package. See that file for information about deactivating specific lint # package. See that file for information about deactivating specific lint
# rules and activating additional ones. # rules and activating additional ones.
flutter_lints: ^3.0.0 flutter_lints: ^4.0.0
# For information on the generic Dart part of this file, see the # For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec # following page: https://dart.dev/tools/pub/pubspec