Merge branch 'user_login' into 'master'

Frontend account and http service updates

See merge request murphg62/2023-ca400-murphg62-byrnm257!9
This commit is contained in:
gaz8860 Gary 2023-04-30 20:12:24 +00:00
commit ed399bfbde
12 changed files with 202 additions and 7 deletions

View File

@ -0,0 +1,13 @@
using System.ComponentModel.DataAnnotations;
namespace PanoptesFrontend.Data.Account;
public class AddUser{
[Required]
public string Username { get; set; }
[Required]
[MinLength(10, ErrorMessage = "The Password field must be a minimum of 10 characters")]
public string Password { get; set; }
}

View File

@ -0,0 +1,13 @@
using System.ComponentModel.DataAnnotations;
namespace PanoptesFrontend.Data.Account
{
public class Login
{
[Required]
public string Username { get; set; }
[Required]
public string Password { get; set; }
}
}

View File

@ -0,0 +1,12 @@
using System.ComponentModel.DataAnnotations;
namespace PanoptesFrontend.Data.Account;
public class LoginUser
{
[Required]
public string Username { get; set; }
[Required]
public string Password { get; set; }
}

View File

@ -0,0 +1,15 @@
public class Post {
public int userId {get; set;}
public int id {get; set;}
public string title {get; set;}
public string body {get; set;}
public Post(int userId, int id, string title, string body){
userId = userId;
id = id;
title = title;
body = body;
}
}

View File

@ -0,0 +1,9 @@
namespace PanoptesFrontend.Data
{
public class User
{
public string Id { get; set; }
public string Username { get; set; }
public string Token { get; set; }
}
}

View File

@ -0,0 +1,38 @@
@page "/account/login"
@using PanoptesFrontend.Data.Account;
@using PanoptesFrontend.Services;
@inject IAccountService AccountService
<div class="card">
<h4 class="card-header">Login</h4>
<div class="card-body">
<EditForm Model="@model" OnValidSubmit="@OnValidSubmit">
<DataAnnotationsValidator />
<div class="form-group">
<label>Username</label>
<InputText @bind-Value="@model.Username" class="form-control" />
<ValidationMessage For="@(() => model.Username)" />
</div>
<div class="form-group">
<label>Password</label>
<InputText @bind-Value="@model.Password" type="password" class="form-control" />
<ValidationMessage For="@(() => model.Password)" />
</div>
<button class="btn btn-primary" type="submit">
Login
</button>
<NavLink href="account/register" class="btn btn-link">Register</NavLink>
</EditForm>
</div>
</div>
@code {
private LoginUser model = new LoginUser();
private async void OnValidSubmit()
{
Console.WriteLine("Method called");
await AccountService.Login(model);
}
}

View File

@ -0,0 +1,38 @@
@page "/account/register"
@using PanoptesFrontend.Data.Account;
@using PanoptesFrontend.Services;
@inject IAccountService AccountService
<div class="card">
<h4 class="card-header">Register</h4>
<div class="card-body">
<EditForm Model="@model" OnValidSubmit="@OnValidSubmit">
<DataAnnotationsValidator />
<div class="form-group">
<label>Username</label>
<InputText @bind-Value="@model.Username" class="form-control" />
<ValidationMessage For="@(() => model.Username)" />
</div>
<div class="form-group">
<label>Password</label>
<InputText @bind-Value="@model.Password" type="password" class="form-control" />
<ValidationMessage For="@(() => model.Password)" />
</div>
<button class="btn btn-primary" type="submit">
Register
</button>
<NavLink href="account/login" class="btn btn-link">Cancel</NavLink>
</EditForm>
</div>
</div>
@code {
private AddUser model = new AddUser();
private async void OnValidSubmit()
{
Console.WriteLine("Method called");
await AccountService.Register(model);
}
}

View File

@ -1,6 +1,8 @@
@page "/test" @page "/test"
@using System.Net;
@using PanoptesFrontend.Data @using PanoptesFrontend.Data
@using PanoptesFrontend.Services
@using System.Text.Json; @using System.Text.Json;
@inject IHttpService httpService @inject IHttpService httpService
@ -33,6 +35,8 @@
@code { @code {
private Component[] data; private Component[] data;
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
var response = await httpService.GetAsync<Schema>("http://localhost:10000/localhost:8080/schema"); var response = await httpService.GetAsync<Schema>("http://localhost:10000/localhost:8080/schema");

View File

@ -1,6 +1,6 @@
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.Web;
using PanoptesFrontend.Data; using PanoptesFrontend.Services;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
@ -9,6 +9,7 @@ builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor(); builder.Services.AddServerSideBlazor();
builder.Services.AddHttpClient(); builder.Services.AddHttpClient();
builder.Services.AddSingleton<IHttpService, HttpService>(); builder.Services.AddSingleton<IHttpService, HttpService>();
builder.Services.AddSingleton<IAccountService, AccountService>();
var app = builder.Build(); var app = builder.Build();

View File

@ -0,0 +1,40 @@
using PanoptesFrontend.Data.Account;
using PanoptesFrontend.Data;
using Microsoft.AspNetCore.Components;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace PanoptesFrontend.Services;
public interface IAccountService
{
Task Register(AddUser model);
Task Login(LoginUser model);
Task Logout(User model);
}
public class AccountService : IAccountService
{
private IHttpService httpService;
public AccountService(IHttpService httpService) {
this.httpService = httpService;
}
public async Task Register(AddUser model){
// endpoint doesnt exist yet
await httpService.PostAsync("http://localhost:8080/user/register", model);
}
public async Task Login(LoginUser model){
// endpoint doesnt exist yet
await httpService.PostAsync("http://localhost:8080/user/authenticate", model);
}
public async Task Logout(User model){
// endpoint doesnt exist yet
await httpService.PostAsync("http://localhost:8080/user/logout", model);
}
}

View File

@ -1,11 +1,14 @@
namespace PanoptesFrontend.Data; namespace PanoptesFrontend.Services;
using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Net.Http.Json;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Text.Json; using System.Text.Json;
public interface IHttpService public interface IHttpService
{ {
Task<T> GetAsync<T>(string endpoint); Task<T> GetAsync<T>(string endpoint);
Task<HttpStatusCode> PostAsync(string endpoint, object value);
} }
public class HttpService : IHttpService { public class HttpService : IHttpService {
@ -28,4 +31,12 @@ public class HttpService : IHttpService {
throw new Exception($"Failed to get data from endpoint: {endpoint}. Error code: {response.StatusCode}"); throw new Exception($"Failed to get data from endpoint: {endpoint}. Error code: {response.StatusCode}");
} }
} }
public async Task<HttpStatusCode> PostAsync(string endpoint, object value){
var request = await httpClient.PostAsJsonAsync(endpoint, value);
request.EnsureSuccessStatusCode();
return request.StatusCode;
}
} }

View File

@ -1,4 +1,5 @@
@using PanoptesFrontend.Data @using PanoptesFrontend.Data;
@using PanoptesFrontend.Services;
@using System.Text.Json; @using System.Text.Json;
@inject IHttpService httpService @inject IHttpService httpService
@ -13,7 +14,7 @@
<div class="@NavMenuCssClass" @onclick="ToggleNavMenu"> <div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
<nav class="flex-column"> <nav class="flex-column">
@if (response != null) @* @if (response != null)
{ {
@foreach (var module in response){ @foreach (var module in response){
<div class="nav-item px-3"> <div class="nav-item px-3">
@ -22,18 +23,18 @@
</NavLink> </NavLink>
</div> </div>
} }
} } *@
</nav> </nav>
</div> </div>
@code { @code {
public Module[] response; @* public Module[] response;
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
response = await httpService.GetAsync<Module[]>("http://localhost:10000/modules"); response = await httpService.GetAsync<Module[]>("http://localhost:10000/modules");
} } *@
private bool collapseNavMenu = true; private bool collapseNavMenu = true;
private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null; private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null;