Added ping route. Allow register from authentication window.
parent
43f0e3823d
commit
cad74115e1
|
@ -11,6 +11,7 @@ using System.Net;
|
|||
using System.Net.NetworkInformation;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Media.Converters;
|
||||
|
||||
namespace LANCommander.PlaynitePlugin
|
||||
{
|
||||
|
@ -85,6 +86,36 @@ namespace LANCommander.PlaynitePlugin
|
|||
}
|
||||
}
|
||||
|
||||
public async Task<AuthResponse> RegisterAsync(string username, string password)
|
||||
{
|
||||
var response = await Client.ExecuteAsync<AuthResponse>(new RestRequest("/api/auth/register", Method.POST).AddJsonBody(new AuthRequest()
|
||||
{
|
||||
UserName = username,
|
||||
Password = password
|
||||
}));
|
||||
|
||||
switch (response.StatusCode)
|
||||
{
|
||||
case HttpStatusCode.OK:
|
||||
return response.Data;
|
||||
|
||||
case HttpStatusCode.BadRequest:
|
||||
case HttpStatusCode.Forbidden:
|
||||
case HttpStatusCode.Unauthorized:
|
||||
throw new WebException(response.Data.Message);
|
||||
|
||||
default:
|
||||
throw new WebException("Could not communicate with the server");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> PingAsync()
|
||||
{
|
||||
var response = await Client.ExecuteAsync(new RestRequest("/api/Ping", Method.GET));
|
||||
|
||||
return response.StatusCode == HttpStatusCode.OK;
|
||||
}
|
||||
|
||||
public AuthResponse RefreshToken(AuthToken token)
|
||||
{
|
||||
var request = new RestRequest("/api/Auth/Refresh")
|
||||
|
|
|
@ -312,7 +312,8 @@ namespace LANCommander.PlaynitePlugin
|
|||
};
|
||||
|
||||
window.Owner = PlayniteApi.Dialogs.GetCurrentAppWindow();
|
||||
window.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterOwner;
|
||||
window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
|
||||
window.ResizeMode = ResizeMode.NoResize;
|
||||
window.ShowDialog();
|
||||
});
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
<sys:Double x:Key="EllipseBorderThickness">1</sys:Double>
|
||||
<CornerRadius x:Key="ControlCornerRadius">1</CornerRadius>
|
||||
<Thickness x:Key="SidebarItemPadding">8</Thickness>
|
||||
|
||||
|
||||
<Color x:Key="BlackColor">#FF000000</Color>
|
||||
<Color x:Key="WhiteColor">#FFFFFFFF</Color>
|
||||
<Color x:Key="TextColor">#f2f2f2</Color>
|
||||
|
@ -202,6 +202,7 @@
|
|||
<RowDefinition Height="auto" />
|
||||
<RowDefinition Height="auto" />
|
||||
<RowDefinition Height="auto" />
|
||||
<RowDefinition Height="auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto" />
|
||||
|
@ -214,6 +215,20 @@
|
|||
<TextBox Grid.Row="1" Grid.Column="1" Name="Username" Text="{Binding UserName}" KeyDown="TextBox_KeyDown" />
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Text="Password" />
|
||||
<PasswordBox Grid.Row="2" Grid.Column="1" Name="Password" PasswordChanged="Password_PasswordChanged" KeyDown="TextBox_KeyDown" />
|
||||
<Button Grid.Row="3" Grid.ColumnSpan="2" Command="{Binding LoginCommand}" x:Name="LoginButton">Login</Button>
|
||||
|
||||
<GridSplitter Grid.Row="4" />
|
||||
|
||||
<Grid Grid.Row="5" Grid.ColumnSpan="2">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Button Grid.Row="0" Grid.Column="0" Click="LoginButton_Click" x:Name="LoginButton">Login</Button>
|
||||
<Button Grid.Row="0" Grid.Column="1" Click="RegisterButton_Click" x:Name="RegisterButton">Register</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
|
@ -60,6 +60,11 @@ namespace LANCommander.PlaynitePlugin.Views
|
|||
Authenticate();
|
||||
}
|
||||
|
||||
private void RegisterButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Register();
|
||||
}
|
||||
|
||||
private void Password_PasswordChanged(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext != null)
|
||||
|
@ -121,5 +126,46 @@ namespace LANCommander.PlaynitePlugin.Views
|
|||
}));
|
||||
}
|
||||
}
|
||||
|
||||
private async Task Register()
|
||||
{
|
||||
try
|
||||
{
|
||||
LoginButton.IsEnabled = false;
|
||||
RegisterButton.IsEnabled = false;
|
||||
RegisterButton.Content = "Working...";
|
||||
|
||||
if (Plugin.LANCommander == null || Plugin.LANCommander.Client == null)
|
||||
Plugin.LANCommander = new LANCommanderClient(Context.ServerAddress);
|
||||
else
|
||||
Plugin.LANCommander.Client.BaseUrl = new Uri(Context.ServerAddress);
|
||||
|
||||
var response = await Plugin.LANCommander.RegisterAsync(Context.UserName, Context.Password);
|
||||
|
||||
Plugin.Settings.ServerAddress = Context.ServerAddress;
|
||||
Plugin.Settings.AccessToken = response.AccessToken;
|
||||
Plugin.Settings.RefreshToken = response.RefreshToken;
|
||||
|
||||
Plugin.LANCommander.Token = new AuthToken()
|
||||
{
|
||||
AccessToken = response.AccessToken,
|
||||
RefreshToken = response.RefreshToken,
|
||||
};
|
||||
|
||||
Context.Password = String.Empty;
|
||||
|
||||
Plugin.SavePluginSettings(Plugin.Settings);
|
||||
|
||||
Window.GetWindow(this).Close();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Plugin.PlayniteApi.Dialogs.ShowErrorMessage(ex.Message);
|
||||
|
||||
LoginButton.IsEnabled = true;
|
||||
RegisterButton.IsEnabled = true;
|
||||
RegisterButton.Content = "Register";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,5 +9,6 @@ namespace LANCommander.SDK.Models
|
|||
public string AccessToken { get; set; }
|
||||
public string RefreshToken { get; set; }
|
||||
public DateTime Expiration { get; set; }
|
||||
public string Message { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ namespace LANCommander.Controllers.Api
|
|||
{
|
||||
public string AccessToken { get; set; }
|
||||
public string RefreshToken { get; set; }
|
||||
public DateTime Expiration { get; set; }
|
||||
}
|
||||
|
||||
public class LoginModel
|
||||
|
@ -24,17 +25,25 @@ namespace LANCommander.Controllers.Api
|
|||
public string Password { get; set; }
|
||||
}
|
||||
|
||||
public class RegisterModel
|
||||
{
|
||||
public string UserName { get; set; }
|
||||
public string Password { get; set; }
|
||||
}
|
||||
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class AuthController : ControllerBase
|
||||
{
|
||||
private readonly UserManager<User> UserManager;
|
||||
private readonly IUserStore<User> UserStore;
|
||||
private readonly RoleManager<Role> RoleManager;
|
||||
private readonly LANCommanderSettings Settings;
|
||||
|
||||
public AuthController(UserManager<User> userManager, RoleManager<Role> roleManager)
|
||||
public AuthController(UserManager<User> userManager, IUserStore<User> userStore, RoleManager<Role> roleManager)
|
||||
{
|
||||
UserManager = userManager;
|
||||
UserStore = userStore;
|
||||
RoleManager = roleManager;
|
||||
Settings = SettingService.GetSettings();
|
||||
}
|
||||
|
@ -44,38 +53,16 @@ namespace LANCommander.Controllers.Api
|
|||
{
|
||||
var user = await UserManager.FindByNameAsync(model.UserName);
|
||||
|
||||
if (user != null && await UserManager.CheckPasswordAsync(user, model.Password))
|
||||
try
|
||||
{
|
||||
var userRoles = await UserManager.GetRolesAsync(user);
|
||||
var token = await Login(user, model.Password);
|
||||
|
||||
var authClaims = new List<Claim>
|
||||
{
|
||||
new Claim(ClaimTypes.Name, user.UserName),
|
||||
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
|
||||
};
|
||||
|
||||
foreach (var userRole in userRoles)
|
||||
{
|
||||
authClaims.Add(new Claim(ClaimTypes.Role, userRole));
|
||||
}
|
||||
|
||||
var token = GetToken(authClaims);
|
||||
var refreshToken = GenerateRefreshToken();
|
||||
|
||||
user.RefreshToken = refreshToken;
|
||||
user.RefreshTokenExpiration = DateTime.Now.AddDays(Settings.TokenLifetime);
|
||||
|
||||
await UserManager.UpdateAsync(user);
|
||||
|
||||
return Ok(new
|
||||
{
|
||||
AccessToken = new JwtSecurityTokenHandler().WriteToken(token),
|
||||
RefreshToken = refreshToken,
|
||||
Expiration = token.ValidTo
|
||||
});
|
||||
return Ok(token);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return Unauthorized();
|
||||
}
|
||||
|
||||
return Unauthorized();
|
||||
}
|
||||
|
||||
[HttpPost("Validate")]
|
||||
|
@ -125,6 +112,82 @@ namespace LANCommander.Controllers.Api
|
|||
});
|
||||
}
|
||||
|
||||
[HttpPost("Register")]
|
||||
public async Task<IActionResult> Register([FromBody] RegisterModel model)
|
||||
{
|
||||
var user = await UserManager.FindByNameAsync(model.UserName);
|
||||
|
||||
if (user != null)
|
||||
return Unauthorized(new
|
||||
{
|
||||
Message = "Username is unavailable"
|
||||
});
|
||||
|
||||
user = new User();
|
||||
|
||||
await UserStore.SetUserNameAsync(user, model.UserName, CancellationToken.None);
|
||||
|
||||
var result = await UserManager.CreateAsync(user, model.Password);
|
||||
|
||||
if (result.Succeeded)
|
||||
{
|
||||
try
|
||||
{
|
||||
var token = await Login(user, model.Password);
|
||||
|
||||
return Ok(token);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return BadRequest(new
|
||||
{
|
||||
Message = "An unknown error occurred"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return Unauthorized(new
|
||||
{
|
||||
Message = "Error:\n" + String.Join('\n', result.Errors.Select(e => e.Description))
|
||||
});
|
||||
}
|
||||
|
||||
private async Task<TokenModel> Login(User user, string password)
|
||||
{
|
||||
if (user != null && await UserManager.CheckPasswordAsync(user, password))
|
||||
{
|
||||
var userRoles = await UserManager.GetRolesAsync(user);
|
||||
|
||||
var authClaims = new List<Claim>
|
||||
{
|
||||
new Claim(ClaimTypes.Name, user.UserName),
|
||||
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
|
||||
};
|
||||
|
||||
foreach (var userRole in userRoles)
|
||||
{
|
||||
authClaims.Add(new Claim(ClaimTypes.Role, userRole));
|
||||
}
|
||||
|
||||
var token = GetToken(authClaims);
|
||||
var refreshToken = GenerateRefreshToken();
|
||||
|
||||
user.RefreshToken = refreshToken;
|
||||
user.RefreshTokenExpiration = DateTime.Now.AddDays(Settings.TokenLifetime);
|
||||
|
||||
await UserManager.UpdateAsync(user);
|
||||
|
||||
return new TokenModel()
|
||||
{
|
||||
AccessToken = new JwtSecurityTokenHandler().WriteToken(token),
|
||||
RefreshToken = refreshToken,
|
||||
Expiration = token.ValidTo
|
||||
};
|
||||
}
|
||||
|
||||
throw new Exception("Invalid username or password");
|
||||
}
|
||||
|
||||
private JwtSecurityToken GetToken(List<Claim> authClaims)
|
||||
{
|
||||
var authSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Settings.TokenSecret));
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace LANCommander.Controllers.Api
|
||||
{
|
||||
public class PingController : Controller
|
||||
{
|
||||
public IActionResult Index()
|
||||
{
|
||||
return Ok("Pong!");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue