Added user change status try catch, implement logout. password change admin

This commit is contained in:
Marcel Baumgartner
2023-04-20 12:29:01 +02:00
parent e79ec35bdc
commit 1b1bc80866
13 changed files with 116 additions and 43 deletions

View File

@@ -1,5 +1,4 @@
using System.ComponentModel.DataAnnotations; using Moonlight.App.Models.Misc;
using Moonlight.App.Models.Misc;
namespace Moonlight.App.Database.Entities; namespace Moonlight.App.Database.Entities;
@@ -34,7 +33,7 @@ public class User
// Security // Security
public bool TotpEnabled { get; set; } = false; public bool TotpEnabled { get; set; } = false;
public string TotpSecret { get; set; } = ""; public string TotpSecret { get; set; } = "";
public DateTime TokenValidTime { get; set; } = DateTime.Now; public DateTime TokenValidTime { get; set; } = DateTime.UtcNow;
// Discord // Discord
public ulong DiscordId { get; set; } public ulong DiscordId { get; set; }

View File

@@ -18,17 +18,19 @@ public class OAuth2Controller : Controller
private readonly DiscordOAuth2Service DiscordOAuth2Service; private readonly DiscordOAuth2Service DiscordOAuth2Service;
private readonly UserRepository UserRepository; private readonly UserRepository UserRepository;
private readonly UserService UserService; private readonly UserService UserService;
private readonly DateTimeService DateTimeService;
public OAuth2Controller( public OAuth2Controller(
GoogleOAuth2Service googleOAuth2Service, GoogleOAuth2Service googleOAuth2Service,
UserRepository userRepository, UserRepository userRepository,
UserService userService, UserService userService,
DiscordOAuth2Service discordOAuth2Service) DiscordOAuth2Service discordOAuth2Service, DateTimeService dateTimeService)
{ {
GoogleOAuth2Service = googleOAuth2Service; GoogleOAuth2Service = googleOAuth2Service;
UserRepository = userRepository; UserRepository = userRepository;
UserService = userService; UserService = userService;
DiscordOAuth2Service = discordOAuth2Service; DiscordOAuth2Service = discordOAuth2Service;
DateTimeService = dateTimeService;
} }
[HttpGet("google")] [HttpGet("google")]
@@ -63,7 +65,7 @@ public class OAuth2Controller : Controller
Response.Cookies.Append("token", token, new () Response.Cookies.Append("token", token, new ()
{ {
Expires = new DateTimeOffset(DateTime.UtcNow.AddDays(10)) Expires = new DateTimeOffset(DateTimeService.GetCurrent().AddDays(10))
}); });
return Redirect("/"); return Redirect("/");
@@ -121,7 +123,7 @@ public class OAuth2Controller : Controller
Response.Cookies.Append("token", token, new () Response.Cookies.Append("token", token, new ()
{ {
Expires = new DateTimeOffset(DateTime.UtcNow.AddDays(10)) Expires = new DateTimeOffset(DateTimeService.GetCurrent().AddDays(10))
}); });
return Redirect("/"); return Redirect("/");

View File

@@ -1,16 +1,19 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Moonlight.App.Database; using Moonlight.App.Database;
using Moonlight.App.Database.Entities; using Moonlight.App.Database.Entities;
using Moonlight.App.Services;
namespace Moonlight.App.Repositories; namespace Moonlight.App.Repositories;
public class StatisticsRepository : IDisposable public class StatisticsRepository : IDisposable
{ {
private readonly DataContext DataContext; private readonly DataContext DataContext;
private readonly DateTimeService DateTimeService;
public StatisticsRepository(DataContext dataContext) public StatisticsRepository(DataContext dataContext, DateTimeService dateTimeService)
{ {
DataContext = dataContext; DataContext = dataContext;
DateTimeService = dateTimeService;
} }
public DbSet<StatisticsData> Get() public DbSet<StatisticsData> Get()
@@ -27,7 +30,7 @@ public class StatisticsRepository : IDisposable
public StatisticsData Add(string chart, double value) public StatisticsData Add(string chart, double value)
{ {
return Add(new StatisticsData() {Chart = chart, Value = value, Date = DateTime.Now}); return Add(new StatisticsData() {Chart = chart, Value = value, Date = DateTimeService.GetCurrent()});
} }
public void Dispose() public void Dispose()

View File

@@ -24,20 +24,23 @@ public class CleanupService
private readonly ConfigService ConfigService; private readonly ConfigService ConfigService;
private readonly MessageService MessageService; private readonly MessageService MessageService;
private readonly DateTimeService DateTimeService;
private readonly IServiceScopeFactory ServiceScopeFactory; private readonly IServiceScopeFactory ServiceScopeFactory;
private readonly PeriodicTimer Timer; private readonly PeriodicTimer Timer;
public CleanupService( public CleanupService(
ConfigService configService, ConfigService configService,
IServiceScopeFactory serviceScopeFactory, IServiceScopeFactory serviceScopeFactory,
MessageService messageService) MessageService messageService,
DateTimeService dateTimeService)
{ {
ServiceScopeFactory = serviceScopeFactory; ServiceScopeFactory = serviceScopeFactory;
MessageService = messageService; MessageService = messageService;
DateTimeService = dateTimeService;
ConfigService = configService; ConfigService = configService;
StartedAt = DateTime.Now; StartedAt = DateTimeService.GetCurrent();
CompletedAt = DateTime.Now; CompletedAt = DateTimeService.GetCurrent();
IsRunning = false; IsRunning = false;
var config = ConfigService.GetSection("Moonlight").GetSection("Cleanup"); var config = ConfigService.GetSection("Moonlight").GetSection("Cleanup");

View File

@@ -0,0 +1,31 @@
using Moonlight.App.Helpers;
namespace Moonlight.App.Services;
public class DateTimeService
{
public long GetCurrentUnix()
{
return new DateTimeOffset(GetCurrent()).ToUnixTimeMilliseconds();
}
public long GetCurrentUnixSeconds()
{
return new DateTimeOffset(GetCurrent()).ToUnixTimeSeconds();
}
public DateTime GetCurrent()
{
return DateTime.UtcNow;
}
public string GetDate()
{
return Formatter.FormatDateOnly(GetCurrent());
}
public string GetDateTime()
{
return Formatter.FormatDate(GetCurrent());
}
}

View File

@@ -31,6 +31,7 @@ public class ServerService
private readonly AuditLogService AuditLogService; private readonly AuditLogService AuditLogService;
private readonly ErrorLogService ErrorLogService; private readonly ErrorLogService ErrorLogService;
private readonly NodeService NodeService; private readonly NodeService NodeService;
private readonly DateTimeService DateTimeService;
public ServerService( public ServerService(
ServerRepository serverRepository, ServerRepository serverRepository,
@@ -46,7 +47,8 @@ public class ServerService
AuditLogService auditLogService, AuditLogService auditLogService,
ErrorLogService errorLogService, ErrorLogService errorLogService,
NodeService nodeService, NodeService nodeService,
NodeAllocationRepository nodeAllocationRepository) NodeAllocationRepository nodeAllocationRepository,
DateTimeService dateTimeService)
{ {
ServerRepository = serverRepository; ServerRepository = serverRepository;
WingsApiHelper = wingsApiHelper; WingsApiHelper = wingsApiHelper;
@@ -62,6 +64,7 @@ public class ServerService
ErrorLogService = errorLogService; ErrorLogService = errorLogService;
NodeService = nodeService; NodeService = nodeService;
NodeAllocationRepository = nodeAllocationRepository; NodeAllocationRepository = nodeAllocationRepository;
DateTimeService = dateTimeService;
} }
private Server EnsureNodeData(Server s) private Server EnsureNodeData(Server s)
@@ -115,9 +118,9 @@ public class ServerService
var backup = new ServerBackup() var backup = new ServerBackup()
{ {
Name = $"Created at {DateTime.Now.ToShortDateString()} {DateTime.Now.ToShortTimeString()}", Name = $"Created at {DateTimeService.GetCurrent().ToShortDateString()} {DateTimeService.GetCurrent().ToShortTimeString()}",
Uuid = Guid.NewGuid(), Uuid = Guid.NewGuid(),
CreatedAt = DateTime.Now, CreatedAt = DateTimeService.GetCurrent(),
Created = false Created = false
}; };

View File

@@ -4,6 +4,7 @@ using JWT.Builder;
using JWT.Exceptions; using JWT.Exceptions;
using Logging.Net; using Logging.Net;
using Moonlight.App.Database.Entities; using Moonlight.App.Database.Entities;
using Moonlight.App.Helpers;
using Moonlight.App.Models.Misc; using Moonlight.App.Models.Misc;
using Moonlight.App.Repositories; using Moonlight.App.Repositories;
using Moonlight.App.Services.LogServices; using Moonlight.App.Services.LogServices;
@@ -123,9 +124,9 @@ public class IdentityService
return null; return null;
} }
var issuedAt = DateTimeOffset.FromUnixTimeSeconds(iat).DateTime; var iatD = DateTimeOffset.FromUnixTimeSeconds(iat).ToUniversalTime().DateTime;
if (issuedAt < user.TokenValidTime.ToUniversalTime()) if (iatD < user.TokenValidTime)
return null; return null;
UserCache = user; UserCache = user;

View File

@@ -12,6 +12,7 @@ public class SessionService
private readonly IdentityService IdentityService; private readonly IdentityService IdentityService;
private readonly NavigationManager NavigationManager; private readonly NavigationManager NavigationManager;
private readonly AlertService AlertService; private readonly AlertService AlertService;
private readonly DateTimeService DateTimeService;
private Session? OwnSession; private Session? OwnSession;
@@ -19,12 +20,14 @@ public class SessionService
SessionRepository sessionRepository, SessionRepository sessionRepository,
IdentityService identityService, IdentityService identityService,
NavigationManager navigationManager, NavigationManager navigationManager,
AlertService alertService) AlertService alertService,
DateTimeService dateTimeService)
{ {
SessionRepository = sessionRepository; SessionRepository = sessionRepository;
IdentityService = identityService; IdentityService = identityService;
NavigationManager = navigationManager; NavigationManager = navigationManager;
AlertService = alertService; AlertService = alertService;
DateTimeService = dateTimeService;
} }
public async Task Register() public async Task Register()
@@ -36,7 +39,7 @@ public class SessionService
Ip = IdentityService.GetIp(), Ip = IdentityService.GetIp(),
Url = NavigationManager.Uri, Url = NavigationManager.Uri,
Device = IdentityService.GetDevice(), Device = IdentityService.GetDevice(),
CreatedAt = DateTime.Now, CreatedAt = DateTimeService.GetCurrent(),
User = user, User = user,
Navigation = NavigationManager, Navigation = NavigationManager,
AlertService = AlertService AlertService = AlertService
@@ -64,10 +67,8 @@ public class SessionService
{ {
foreach (var session in SessionRepository.Get()) foreach (var session in SessionRepository.Get())
{ {
if (session.User.Id == user.Id) if(session.User != null && session.User.Id == user.Id)
{
session.Navigation.NavigateTo(session.Navigation.Uri, true); session.Navigation.NavigateTo(session.Navigation.Uri, true);
}
} }
} }
} }

View File

@@ -7,15 +7,17 @@ namespace Moonlight.App.Services.Statistics;
public class StatisticsViewService public class StatisticsViewService
{ {
private readonly StatisticsRepository StatisticsRepository; private readonly StatisticsRepository StatisticsRepository;
private readonly DateTimeService DateTimeService;
public StatisticsViewService(StatisticsRepository statisticsRepository) public StatisticsViewService(StatisticsRepository statisticsRepository, DateTimeService dateTimeService)
{ {
StatisticsRepository = statisticsRepository; StatisticsRepository = statisticsRepository;
DateTimeService = dateTimeService;
} }
public StatisticsData[] GetData(string chart, StatisticsTimeSpan timeSpan) public StatisticsData[] GetData(string chart, StatisticsTimeSpan timeSpan)
{ {
var startDate = DateTime.Now - TimeSpan.FromHours((int)timeSpan); var startDate = DateTimeService.GetCurrent() - TimeSpan.FromHours((int)timeSpan);
var objs = StatisticsRepository.Get().Where(x => x.Date > startDate && x.Chart == chart); var objs = StatisticsRepository.Get().Where(x => x.Date > startDate && x.Chart == chart);

View File

@@ -19,6 +19,7 @@ public class UserService
private readonly MailService MailService; private readonly MailService MailService;
private readonly IdentityService IdentityService; private readonly IdentityService IdentityService;
private readonly IpLocateService IpLocateService; private readonly IpLocateService IpLocateService;
private readonly DateTimeService DateTimeService;
private readonly string JwtSecret; private readonly string JwtSecret;
@@ -29,7 +30,9 @@ public class UserService
SecurityLogService securityLogService, SecurityLogService securityLogService,
AuditLogService auditLogService, AuditLogService auditLogService,
MailService mailService, MailService mailService,
IdentityService identityService, IpLocateService ipLocateService) IdentityService identityService,
IpLocateService ipLocateService,
DateTimeService dateTimeService)
{ {
UserRepository = userRepository; UserRepository = userRepository;
TotpService = totpService; TotpService = totpService;
@@ -38,6 +41,7 @@ public class UserService
MailService = mailService; MailService = mailService;
IdentityService = identityService; IdentityService = identityService;
IpLocateService = ipLocateService; IpLocateService = ipLocateService;
DateTimeService = dateTimeService;
JwtSecret = configService JwtSecret = configService
.GetSection("Moonlight") .GetSection("Moonlight")
@@ -70,12 +74,12 @@ public class UserService
LastName = lastname, LastName = lastname,
State = "", State = "",
Status = UserStatus.Unverified, Status = UserStatus.Unverified,
CreatedAt = DateTime.UtcNow, CreatedAt = DateTimeService.GetCurrent(),
DiscordId = 0, DiscordId = 0,
TotpEnabled = false, TotpEnabled = false,
TotpSecret = "", TotpSecret = "",
UpdatedAt = DateTime.UtcNow, UpdatedAt = DateTimeService.GetCurrent(),
TokenValidTime = DateTime.Now.AddDays(-5) TokenValidTime = DateTimeService.GetCurrent().AddDays(-5)
}); });
await MailService.SendMail(user!, "register", values => {}); await MailService.SendMail(user!, "register", values => {});
@@ -168,7 +172,7 @@ public class UserService
public async Task ChangePassword(User user, string password, bool isSystemAction = false) public async Task ChangePassword(User user, string password, bool isSystemAction = false)
{ {
user.Password = BCrypt.Net.BCrypt.HashPassword(password); user.Password = BCrypt.Net.BCrypt.HashPassword(password);
user.TokenValidTime = DateTime.Now; user.TokenValidTime = DateTimeService.GetCurrent();
UserRepository.Update(user); UserRepository.Update(user);
if (isSystemAction) if (isSystemAction)
@@ -244,8 +248,8 @@ public class UserService
var token = JwtBuilder.Create() var token = JwtBuilder.Create()
.WithAlgorithm(new HMACSHA256Algorithm()) .WithAlgorithm(new HMACSHA256Algorithm())
.WithSecret(JwtSecret) .WithSecret(JwtSecret)
.AddClaim("exp", DateTimeOffset.UtcNow.AddDays(10).ToUnixTimeSeconds()) .AddClaim("exp", new DateTimeOffset(DateTimeService.GetCurrent().AddDays(10)).ToUnixTimeSeconds())
.AddClaim("iat", DateTimeOffset.UtcNow.ToUnixTimeSeconds()) .AddClaim("iat", DateTimeService.GetCurrentUnixSeconds())
.AddClaim("userid", user.Id) .AddClaim("userid", user.Id)
.Encode(); .Encode();

View File

@@ -104,6 +104,7 @@ namespace Moonlight
builder.Services.AddScoped<SmartDeployService>(); builder.Services.AddScoped<SmartDeployService>();
builder.Services.AddScoped<WebSpaceService>(); builder.Services.AddScoped<WebSpaceService>();
builder.Services.AddScoped<StatisticsViewService>(); builder.Services.AddScoped<StatisticsViewService>();
builder.Services.AddSingleton<DateTimeService>();
builder.Services.AddScoped<GoogleOAuth2Service>(); builder.Services.AddScoped<GoogleOAuth2Service>();
builder.Services.AddScoped<DiscordOAuth2Service>(); builder.Services.AddScoped<DiscordOAuth2Service>();

View File

@@ -7,6 +7,7 @@
@using Moonlight.App.Services.Sessions @using Moonlight.App.Services.Sessions
@inject UserRepository UserRepository @inject UserRepository UserRepository
@inject UserService UserService
@inject SessionService SessionService @inject SessionService SessionService
@inject ToastService ToastService @inject ToastService ToastService
@inject SmartTranslateService SmartTranslateService @inject SmartTranslateService SmartTranslateService
@@ -76,17 +77,27 @@
</div> </div>
</div> </div>
<div class="mt-5 card card-body p-10"> <div class="mt-5 card card-body p-10">
<div class="d-flex justify-content-end"> <div class="input-group">
<a href="/admin/users" class="btn btn-danger me-3"> <input @bind="NewPassword" type="password" class="form-control" placeholder="@(SmartTranslateService.Translate("Password"))"/>
<TL>Cancel</TL> <WButton Text="@(SmartTranslateService.Translate("Change"))"
</a> WorkingText="@(SmartTranslateService.Translate("Reloading"))"
<WButton Text="@(SmartTranslateService.Translate("Update"))" CssClasses="btn-primary"
WorkingText="@(SmartTranslateService.Translate("Updating"))" OnClick="ChangePassword">
CssClasses="btn-success" </WButton>
OnClick="Update"> </div>
</WButton> </div>
</div> <div class="mt-5 card card-body p-10">
</div> <div class="d-flex justify-content-end">
<a href="/admin/users" class="btn btn-danger me-3">
<TL>Cancel</TL>
</a>
<WButton Text="@(SmartTranslateService.Translate("Update"))"
WorkingText="@(SmartTranslateService.Translate("Updating"))"
CssClasses="btn-success"
OnClick="Update">
</WButton>
</div>
</div>
</div> </div>
<div class="col-xl-6 mb-5 mb-xl-10"> <div class="col-xl-6 mb-5 mb-xl-10">
<div class="card card-body p-10"> <div class="card card-body p-10">
@@ -148,6 +159,8 @@
private User? User; private User? User;
private string NewPassword = "";
private Task Load(LazyLoader arg) private Task Load(LazyLoader arg)
{ {
User = UserRepository.Get().FirstOrDefault(x => x.Id == Id); User = UserRepository.Get().FirstOrDefault(x => x.Id == Id);
@@ -172,4 +185,14 @@
await ToastService.Success(SmartTranslateService.Translate("Successfully updated user")); await ToastService.Success(SmartTranslateService.Translate("Successfully updated user"));
} }
private async Task ChangePassword()
{
await UserService.ChangePassword(User!, NewPassword, true);
NewPassword = "";
SessionService.ReloadUserSessions(User);
await ToastService.Success(SmartTranslateService.Translate("Successfully updated password"));
}
} }

View File

@@ -64,7 +64,7 @@
<Column TableItem="Session" Title="@(SmartTranslateService.Translate("Time"))" Field="@(x => x.CreatedAt)" Sortable="true" Filterable="true" Width="10%"> <Column TableItem="Session" Title="@(SmartTranslateService.Translate("Time"))" Field="@(x => x.CreatedAt)" Sortable="true" Filterable="true" Width="10%">
<Template> <Template>
@{ @{
var time = Formatter.FormatUptime((DateTime.Now - context.CreatedAt).TotalMilliseconds); var time = Formatter.FormatUptime((DateTime.UtcNow - context.CreatedAt).TotalMilliseconds);
} }
<span>@(time)</span> <span>@(time)</span>
</Template> </Template>