Skip to content

Commit 665ca4a

Browse files
authored
ResourceApi Infrastructure & Sample Improvement (#26)
* ResourceApi Infrastructure & Sample Improvement * Cleanup Not Needed ResourceApi Definitions * Completed ResourceApi Infrastructure & Sample * Added Integration Test Project & First Login Tests
1 parent 7f941a5 commit 665ca4a

File tree

70 files changed

+1346
-375
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+1346
-375
lines changed

UltimateAuth.slnx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
<File Path="Roadmap.md" />
1717
</Folder>
1818
<Folder Name="/Tests/">
19+
<Project Path="tests/CodeBeam.UltimateAuth.Tests.Integration/CodeBeam.UltimateAuth.Tests.Integration.csproj" Id="fe34a0b1-8038-400d-b8ab-02dad7051f2d" />
1920
<Project Path="tests/CodeBeam.UltimateAuth.Tests.Unit/CodeBeam.UltimateAuth.Tests.Unit.csproj" Id="6f4b22da-849a-4a79-b5c5-aee7cb1429a6" />
2021
</Folder>
2122
<Project Path="src/authentication/CodeBeam.UltimateAuth.Authentication.EntityFrameworkCore/CodeBeam.UltimateAuth.Authentication.EntityFrameworkCore.csproj" Id="a8d758ad-052e-4331-9bf7-280ea9a55981" />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
@using CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm.ResourceApi
2+
@inject ProductApiService Api
3+
@inject ISnackbar Snackbar
4+
5+
<MudDialog Class="mud-width-full" ContentClass="uauth-dialog">
6+
7+
<TitleContent>
8+
<MudText>Resource Api</MudText>
9+
<MudText Typo="Typo.subtitle2" Color="Color.Primary">Sample demonstration of a resource.</MudText>
10+
</TitleContent>
11+
12+
<DialogContent>
13+
<MudButton OnClick="GetProducts">Reload</MudButton>
14+
15+
<MudDataGrid Items="@_products" Dense="true" Striped="true" Hover="true"
16+
EditMode="DataGridEditMode.Form" ReadOnly="false" CommittedItemChanges="@CommittedItemChanges">
17+
<Columns>
18+
<PropertyColumn Property="x => x.Id" Title="Id" Editable="false" />
19+
<PropertyColumn Property="x => x.Name" Title="Name" />
20+
<TemplateColumn Title="Actions" Editable="false">
21+
<CellTemplate>
22+
<MudStack Style="min-width: 120px" Row="true" Spacing="2" Wrap="Wrap.Wrap">
23+
<MudTooltip Text="Edit" Color="Color.Primary" Delay="300" ShowOnFocus="false">
24+
<MudIconButton Color="Color.Primary" Variant="Variant.Filled" Icon="@Icons.Material.Filled.Edit" Size="Size.Small" OnClick="@context.Actions.StartEditingItemAsync" />
25+
</MudTooltip>
26+
27+
<MudTooltip Text="Delete" Color="Color.Error" Delay="300" ShowOnFocus="false">
28+
<MudIconButton Color="Color.Error" Variant="Variant.Filled" Icon="@Icons.Material.Filled.Delete" Size="Size.Small" OnClick="@(() => DeleteProduct(context.Item.Id))" />
29+
</MudTooltip>
30+
</MudStack>
31+
</CellTemplate>
32+
</TemplateColumn>
33+
</Columns>
34+
<PagerContent>
35+
<MudDataGridPager T="SampleProduct" PageSizeOptions="new int[] { 5, 10, 20 }" />
36+
</PagerContent>
37+
</MudDataGrid>
38+
39+
<MudExpansionPanels Class="mt-4" Elevation="0">
40+
<MudExpansionPanel Style="background: var(--mud-palette-background-gray)" Text="Add New Product" Expanded="false">
41+
<MudGrid>
42+
<MudItem xs="12" sm="6">
43+
<MudTextField @bind-Value="_newName" Variant="Variant.Outlined" Label="Name" />
44+
</MudItem>
45+
46+
<MudItem xs="12">
47+
<MudButton Style="width: fit-content" Color="Color.Primary" Variant="Variant.Outlined" OnClick="CreateProduct">Add</MudButton>
48+
</MudItem>
49+
</MudGrid>
50+
</MudExpansionPanel>
51+
</MudExpansionPanels>
52+
</DialogContent>
53+
54+
</MudDialog>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
using CodeBeam.UltimateAuth.Client;
2+
using CodeBeam.UltimateAuth.Core.Contracts;
3+
using CodeBeam.UltimateAuth.Core.Domain;
4+
using CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm.ResourceApi;
5+
using CodeBeam.UltimateAuth.Users.Contracts;
6+
using Microsoft.AspNetCore.Components;
7+
using MudBlazor;
8+
9+
namespace CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm.Components.Dialogs;
10+
11+
public partial class ResourceApiDialog
12+
{
13+
[CascadingParameter]
14+
private IMudDialogInstance MudDialog { get; set; } = default!;
15+
16+
[Parameter]
17+
public UAuthState AuthState { get; set; } = default!;
18+
19+
private List<SampleProduct> _products = new List<SampleProduct>();
20+
private string? _newName = null;
21+
22+
protected override async Task OnAfterRenderAsync(bool firstRender)
23+
{
24+
if (firstRender)
25+
{
26+
_products = (await Api.GetAllAsync()).Value ?? new();
27+
StateHasChanged();
28+
}
29+
}
30+
31+
private async Task<DataGridEditFormAction> CommittedItemChanges(SampleProduct item)
32+
{
33+
var result = await Api.UpdateAsync(item.Id, item);
34+
35+
if (result.IsSuccess)
36+
{
37+
Snackbar.Add("Product updated successfully", Severity.Success);
38+
}
39+
else
40+
{
41+
Snackbar.Add(result?.ErrorText ?? "Failed to update product.", Severity.Error);
42+
}
43+
44+
return DataGridEditFormAction.Close;
45+
}
46+
47+
private async Task GetProducts()
48+
{
49+
var result = await Api.GetAllAsync();
50+
51+
if (result.IsSuccess)
52+
{
53+
_products = result.Value ?? new();
54+
}
55+
else
56+
{
57+
Snackbar.Add(result.ErrorText ?? "Process failed.", Severity.Error);
58+
}
59+
}
60+
61+
private async Task CreateProduct()
62+
{
63+
var product = new SampleProduct
64+
{
65+
Name = _newName
66+
};
67+
68+
var result = await Api.CreateAsync(product);
69+
70+
if (result.IsSuccess)
71+
{
72+
Snackbar.Add("New product created.");
73+
_products = (await Api.GetAllAsync()).Value ?? new();
74+
}
75+
else
76+
{
77+
Snackbar.Add(result.ErrorText ?? "Process failed.", Severity.Error);
78+
}
79+
}
80+
81+
private async Task DeleteProduct(int id)
82+
{
83+
var result = await Api.DeleteAsync(id);
84+
85+
if (result.IsSuccess)
86+
{
87+
Snackbar.Add("Product deleted succesfully.", Severity.Success);
88+
_products = (await Api.GetAllAsync()).Value ?? new();
89+
}
90+
else
91+
{
92+
Snackbar.Add(result.ErrorText ?? "Process failed.", Severity.Error);
93+
}
94+
}
95+
}

samples/blazor-standalone-wasm/CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm/Pages/Home.razor

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,15 @@
142142
</MudItem>
143143
</MudGrid>
144144
}
145+
146+
<MudStack Class="mt-4" Row="true" AlignItems="AlignItems.Center">
147+
<MudText Typo="Typo.subtitle2">Resource Api</MudText>
148+
<MudDivider Style="width: 60%" />
149+
</MudStack>
150+
151+
<MudButton FullWidth Variant="Variant.Outlined" StartIcon="@Icons.Material.Filled.Api" OnClick="OpenResourceApiDialog">
152+
<MudText Class="mud-width-full" Align="Align.Center">Manage Resource</MudText>
153+
</MudButton>
145154
</MudStack>
146155
</MudExpansionPanel>
147156
</MudItem>

samples/blazor-standalone-wasm/CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm/Pages/Home.razor.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,11 @@ private async Task OpenRoleDialog()
190190
await DialogService.ShowAsync<RoleDialog>("Role Management", GetDialogParameters(), UAuthDialog.GetDialogOptions());
191191
}
192192

193+
private async Task OpenResourceApiDialog()
194+
{
195+
await DialogService.ShowAsync<ResourceApiDialog>("Resource Api", GetDialogParameters(), UAuthDialog.GetDialogOptions());
196+
}
197+
193198
private DialogParameters GetDialogParameters()
194199
{
195200
return new DialogParameters

samples/blazor-standalone-wasm/CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm/Program.cs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using CodeBeam.UltimateAuth.Core.Extensions;
44
using CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm;
55
using CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm.Infrastructure;
6+
using CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm.ResourceApi;
67
using Microsoft.AspNetCore.Components.Web;
78
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
89
using MudBlazor.Services;
@@ -28,16 +29,21 @@
2829
});
2930
builder.Services.AddMudExtensions();
3031

32+
builder.Services.AddScoped<ProductApiService>();
3133
builder.Services.AddScoped<DarkModeManager>();
3234

33-
//builder.Services.AddHttpClient("UAuthHub", client =>
34-
//{
35-
// client.BaseAddress = new Uri("https://localhost:6110");
36-
//});
3735

3836
//builder.Services.AddHttpClient("ResourceApi", client =>
3937
//{
4038
// client.BaseAddress = new Uri("https://localhost:6120");
4139
//});
4240

41+
builder.Services.AddScoped(sp =>
42+
{
43+
return new HttpClient
44+
{
45+
BaseAddress = new Uri("https://localhost:6120") // Resource API
46+
};
47+
});
48+
4349
await builder.Build().RunAsync();
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
using CodeBeam.UltimateAuth.Core.Contracts;
2+
using Microsoft.AspNetCore.Components.WebAssembly.Http;
3+
using System.Net.Http.Json;
4+
5+
namespace CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm.ResourceApi;
6+
7+
public class ProductApiService
8+
{
9+
private readonly HttpClient _http;
10+
11+
public ProductApiService(HttpClient http)
12+
{
13+
_http = http;
14+
}
15+
16+
private HttpRequestMessage CreateRequest(HttpMethod method, string url, object? body = null)
17+
{
18+
var request = new HttpRequestMessage(method, url);
19+
request.SetBrowserRequestCredentials(BrowserRequestCredentials.Include);
20+
21+
if (body is not null)
22+
{
23+
request.Content = JsonContent.Create(body);
24+
}
25+
26+
return request;
27+
}
28+
29+
public Task<UAuthResult<List<SampleProduct>>> GetAllAsync()
30+
=> SendAsync<List<SampleProduct>>(CreateRequest(HttpMethod.Get, "/api/products"));
31+
32+
public Task<UAuthResult<SampleProduct?>> GetAsync(int id)
33+
=> SendAsync<SampleProduct?>(CreateRequest(HttpMethod.Get, $"/api/products/{id}"));
34+
35+
public Task<UAuthResult<SampleProduct?>> CreateAsync(SampleProduct product)
36+
=> SendAsync<SampleProduct?>(CreateRequest(HttpMethod.Post, $"/api/products", product));
37+
38+
public Task<UAuthResult<SampleProduct?>> UpdateAsync(int id, SampleProduct product)
39+
=> SendAsync<SampleProduct?>(CreateRequest(HttpMethod.Put, $"/api/products/{id}", product));
40+
41+
public Task<UAuthResult<SampleProduct?>> DeleteAsync(int id)
42+
=> SendAsync<SampleProduct?>(CreateRequest(HttpMethod.Delete, $"/api/products/{id}"));
43+
44+
private async Task<UAuthResult<T>> SendAsync<T>(HttpRequestMessage request)
45+
{
46+
var response = await _http.SendAsync(request);
47+
48+
var result = new UAuthResult<T>
49+
{
50+
Status = (int)response.StatusCode,
51+
IsSuccess = response.IsSuccessStatusCode
52+
};
53+
54+
if (response.IsSuccessStatusCode)
55+
{
56+
result.Value = await response.Content.ReadFromJsonAsync<T>();
57+
return result;
58+
}
59+
60+
result.Problem = await TryReadProblem(response);
61+
return result;
62+
}
63+
64+
private async Task<UAuthProblem?> TryReadProblem(HttpResponseMessage response)
65+
{
66+
try
67+
{
68+
return await response.Content.ReadFromJsonAsync<UAuthProblem>();
69+
}
70+
catch
71+
{
72+
return new UAuthProblem
73+
{
74+
Title = response.ReasonPhrase
75+
};
76+
}
77+
}
78+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm.ResourceApi;
2+
3+
public class SampleProduct
4+
{
5+
public int Id { get; set; }
6+
public string? Name { get; set; }
7+
}

samples/blazor-standalone-wasm/CodeBeam.UltimateAuth.Sample.BlazorStandaloneWasm/wwwroot/index.html

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
<base href="/" />
99
<link rel="stylesheet" href="css/app.css" />
1010
<link rel="icon" type="image/png" href="UltimateAuth-Logo.png" />
11-
<link href="UltimateAuth.Sample.BlazorStandaloneWasm.styles.css" rel="stylesheet" />
12-
1311
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" rel="stylesheet" />
1412
<link href="_content/MudBlazor/MudBlazor.min.css" rel="stylesheet" />
1513
<link href="_content/CodeBeam.MudBlazor.Extensions/MudExtensions.min.css" rel="stylesheet" />

samples/resource-api/CodeBeam.UltimateAuth.Sample.ResourceApi/Controllers/WeatherForecastController.cs

Lines changed: 0 additions & 26 deletions
This file was deleted.

0 commit comments

Comments
 (0)