mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-07-09 03:04:19 -04:00
Added new API for getting Member (aka Users but for use in FE). User is just used for login/registering.
This commit is contained in:
parent
a920be092d
commit
13ed323949
@ -5,6 +5,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="8.1.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="5.0.1" NoWarn="NU1605" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="5.0.1" NoWarn="NU1605" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.1">
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System.Security.Cryptography;
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using API.Data;
|
||||
@ -15,12 +16,14 @@ namespace API.Controllers
|
||||
{
|
||||
private readonly DataContext _context;
|
||||
private readonly ITokenService _tokenService;
|
||||
private readonly IUserRepository _userRepository;
|
||||
private readonly ILogger<AccountController> _logger;
|
||||
|
||||
public AccountController(DataContext context, ITokenService tokenService, ILogger<AccountController> logger)
|
||||
public AccountController(DataContext context, ITokenService tokenService, IUserRepository userRepository, ILogger<AccountController> logger)
|
||||
{
|
||||
_context = context;
|
||||
_tokenService = tokenService;
|
||||
_userRepository = userRepository;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
@ -39,7 +42,8 @@ namespace API.Controllers
|
||||
UserName = registerDto.Username.ToLower(),
|
||||
PasswordHash = hmac.ComputeHash(Encoding.UTF8.GetBytes(registerDto.Password)),
|
||||
PasswordSalt = hmac.Key,
|
||||
IsAdmin = registerDto.IsAdmin
|
||||
IsAdmin = registerDto.IsAdmin,
|
||||
LastActive = DateTime.Now
|
||||
};
|
||||
|
||||
_context.Users.Add(user);
|
||||
@ -68,11 +72,17 @@ namespace API.Controllers
|
||||
{
|
||||
if (computedHash[i] != user.PasswordHash[i]) return Unauthorized("Invalid password");
|
||||
}
|
||||
|
||||
// Update LastActive on account
|
||||
user.LastActive = DateTime.Now;
|
||||
_userRepository.Update(user);
|
||||
await _userRepository.SaveAllAsync();
|
||||
|
||||
return new UserDto()
|
||||
{
|
||||
Username = user.UserName,
|
||||
Token = _tokenService.CreateToken(user)
|
||||
Token = _tokenService.CreateToken(user),
|
||||
IsAdmin = user.IsAdmin
|
||||
};
|
||||
}
|
||||
|
||||
|
28
API/Controllers/UsersController.cs
Normal file
28
API/Controllers/UsersController.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using API.Data;
|
||||
using API.DTOs;
|
||||
using API.Interfaces;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace API.Controllers
|
||||
{
|
||||
public class UsersController : BaseApiController
|
||||
{
|
||||
private readonly DataContext _context;
|
||||
private readonly IUserRepository _userRepository;
|
||||
|
||||
public UsersController(DataContext context, IUserRepository userRepository)
|
||||
{
|
||||
_context = context;
|
||||
_userRepository = userRepository;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<ActionResult<IEnumerable<MemberDto>>> GetUsers()
|
||||
{
|
||||
return Ok(await _userRepository.GetMembersAsync());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace API.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a number to a boolean.
|
||||
/// This is needed for HDHomerun.
|
||||
/// </summary>
|
||||
public class JsonBoolNumberConverter : JsonConverter<bool>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override bool Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
if (reader.TokenType == JsonTokenType.Number)
|
||||
{
|
||||
return Convert.ToBoolean(reader.GetInt32());
|
||||
}
|
||||
|
||||
return reader.GetBoolean();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Write(Utf8JsonWriter writer, bool value, JsonSerializerOptions options)
|
||||
{
|
||||
writer.WriteBooleanValue(value);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace API.Converters
|
||||
{
|
||||
public class JsonBoolStringConverter : JsonConverter<bool>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override bool Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
if (reader.TokenType == JsonTokenType.String)
|
||||
{
|
||||
return reader.GetString().ToLower() == "true";
|
||||
}
|
||||
|
||||
return reader.GetBoolean();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Write(Utf8JsonWriter writer, bool value, JsonSerializerOptions options)
|
||||
{
|
||||
writer.WriteBooleanValue(value);
|
||||
}
|
||||
}
|
||||
}
|
16
API/DTOs/MemberDto.cs
Normal file
16
API/DTOs/MemberDto.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using System;
|
||||
|
||||
namespace API.DTOs
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a member of a Kavita server.
|
||||
/// </summary>
|
||||
public class MemberDto
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Username { get; set; }
|
||||
public DateTime Created { get; set; }
|
||||
public DateTime LastActive { get; set; }
|
||||
public bool IsAdmin { get; set; }
|
||||
}
|
||||
}
|
@ -1,6 +1,4 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Text.Json.Serialization;
|
||||
using API.Converters;
|
||||
|
||||
namespace API.DTOs
|
||||
{
|
||||
@ -11,7 +9,6 @@ namespace API.DTOs
|
||||
[Required]
|
||||
[StringLength(8, MinimumLength = 4)]
|
||||
public string Password { get; set; }
|
||||
[JsonConverter(typeof(JsonBoolNumberConverter))]
|
||||
public bool IsAdmin { get; set; }
|
||||
}
|
||||
}
|
61
API/Data/UserRepository.cs
Normal file
61
API/Data/UserRepository.cs
Normal file
@ -0,0 +1,61 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using API.DTOs;
|
||||
using API.Entities;
|
||||
using API.Interfaces;
|
||||
using AutoMapper;
|
||||
using AutoMapper.QueryableExtensions;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace API.Data
|
||||
{
|
||||
public class UserRepository : IUserRepository
|
||||
{
|
||||
private readonly DataContext _context;
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
public UserRepository(DataContext context, IMapper mapper)
|
||||
{
|
||||
_context = context;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
public void Update(AppUser user)
|
||||
{
|
||||
_context.Entry(user).State = EntityState.Modified;
|
||||
}
|
||||
|
||||
public async Task<bool> SaveAllAsync()
|
||||
{
|
||||
return await _context.SaveChangesAsync() > 0;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<AppUser>> GetUsersAsync()
|
||||
{
|
||||
return await _context.Users.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<AppUser> GetUserByIdAsync(int id)
|
||||
{
|
||||
return await _context.Users.FindAsync(id);
|
||||
}
|
||||
|
||||
public async Task<AppUser> GetUserByUsernameAsync(string username)
|
||||
{
|
||||
return await _context.Users.SingleOrDefaultAsync(x => x.UserName == username);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<MemberDto>> GetMembersAsync()
|
||||
{
|
||||
return await _context.Users.ProjectTo<MemberDto>(_mapper.ConfigurationProvider).ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<MemberDto> GetMemberAsync(string username)
|
||||
{
|
||||
return await _context.Users.Where(x => x.UserName == username)
|
||||
.ProjectTo<MemberDto>(_mapper.ConfigurationProvider)
|
||||
.SingleOrDefaultAsync();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
using API.Data;
|
||||
using API.Helpers;
|
||||
using API.Interfaces;
|
||||
using API.Services;
|
||||
using AutoMapper;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
@ -11,6 +13,8 @@ namespace API.Extensions
|
||||
{
|
||||
public static IServiceCollection AddApplicationServices(this IServiceCollection services, IConfiguration config)
|
||||
{
|
||||
services.AddAutoMapper(typeof(AutoMapperProfiles).Assembly);
|
||||
services.AddScoped<IUserRepository, UserRepository>();
|
||||
services.AddScoped<ITokenService, TokenService>();
|
||||
services.AddDbContext<DataContext>(options =>
|
||||
{
|
||||
|
12
API/Extensions/ClaimsPrincipalExtensions.cs
Normal file
12
API/Extensions/ClaimsPrincipalExtensions.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System.Security.Claims;
|
||||
|
||||
namespace API.Extensions
|
||||
{
|
||||
public static class ClaimsPrincipalExtensions
|
||||
{
|
||||
public static string GetUsername(this ClaimsPrincipal user)
|
||||
{
|
||||
return user.FindFirst(ClaimTypes.NameIdentifier)?.Value;
|
||||
}
|
||||
}
|
||||
}
|
14
API/Helpers/AutoMapperProfiles.cs
Normal file
14
API/Helpers/AutoMapperProfiles.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using API.DTOs;
|
||||
using API.Entities;
|
||||
using AutoMapper;
|
||||
|
||||
namespace API.Helpers
|
||||
{
|
||||
public class AutoMapperProfiles : Profile
|
||||
{
|
||||
public AutoMapperProfiles()
|
||||
{
|
||||
CreateMap<AppUser, MemberDto>();
|
||||
}
|
||||
}
|
||||
}
|
19
API/Interfaces/IUserRepository.cs
Normal file
19
API/Interfaces/IUserRepository.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using API.DTOs;
|
||||
using API.Entities;
|
||||
|
||||
namespace API.Interfaces
|
||||
{
|
||||
public interface IUserRepository
|
||||
{
|
||||
void Update(AppUser user);
|
||||
Task<bool> SaveAllAsync();
|
||||
Task<IEnumerable<AppUser>> GetUsersAsync();
|
||||
Task<AppUser> GetUserByIdAsync(int id);
|
||||
Task<AppUser> GetUserByUsernameAsync(string username);
|
||||
Task<IEnumerable<MemberDto>> GetMembersAsync();
|
||||
Task<MemberDto> GetMemberAsync(string username);
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@ namespace API.Middleware
|
||||
private readonly RequestDelegate _next;
|
||||
private readonly ILogger<ExceptionMiddleware> _logger;
|
||||
private readonly IHostEnvironment _env;
|
||||
|
||||
|
||||
public ExceptionMiddleware(RequestDelegate next, ILogger<ExceptionMiddleware> logger, IHostEnvironment env)
|
||||
{
|
||||
|
@ -11,7 +11,7 @@
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": false,
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
@ -20,7 +20,7 @@
|
||||
"API": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": "true",
|
||||
"launchBrowser": true,
|
||||
"launchBrowser": false,
|
||||
"launchUrl": "swagger",
|
||||
"applicationUrl": "https://localhost:5001;http://localhost:5000",
|
||||
"environmentVariables": {
|
||||
|
Loading…
x
Reference in New Issue
Block a user