diff --git a/.gitignore b/.gitignore
index 18496c4..8f5f55c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -403,4 +403,5 @@ ASALocalRun/
.mfractor/
# Local History for Visual Studio
-.localhistory/
\ No newline at end of file
+.localhistory/
+/TinyInsights.WebServer/appsettings.local.json
diff --git a/TinyInsights.Web/Components/LoggedInMenuItems.razor b/TinyInsights.Web/Components/LoggedInMenuItems.razor
new file mode 100644
index 0000000..7926044
--- /dev/null
+++ b/TinyInsights.Web/Components/LoggedInMenuItems.razor
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+@code {
+
+}
diff --git a/TinyInsights.Web/Components/Menu.razor b/TinyInsights.Web/Components/Menu.razor
index 9704f75..abb4333 100644
--- a/TinyInsights.Web/Components/Menu.razor
+++ b/TinyInsights.Web/Components/Menu.razor
@@ -1,18 +1,18 @@
+
@inherits TinyInsightsComponentBase
- @if (IsLoggedIn)
+ @if (OperatingSystem.IsBrowser() && IsLoggedIn)
+ {
+
+ }
+ else if(!OperatingSystem.IsBrowser())
{
-
-
-
-
-
-
-
-
+
+
+
}
diff --git a/TinyInsights.Web/Layout/MainLayout.razor b/TinyInsights.Web/Layout/MainLayout.razor
index 6b72cfd..39c3334 100644
--- a/TinyInsights.Web/Layout/MainLayout.razor
+++ b/TinyInsights.Web/Layout/MainLayout.razor
@@ -1,6 +1,7 @@
@using System.ComponentModel.DataAnnotations
@inject NavigationManager NavigationManager
@inherits LayoutComponentBase
+
diff --git a/TinyInsights.Web/Pages/Dashboard.razor b/TinyInsights.Web/Pages/Dashboard.razor
index 08a4d8f..4fa18e2 100644
--- a/TinyInsights.Web/Pages/Dashboard.razor
+++ b/TinyInsights.Web/Pages/Dashboard.razor
@@ -77,35 +77,41 @@
{
isLoadingGraph = true;
- var crashTask = Service.GetCrashesPerDay(GlobalFilter);
- var errorTask = Service.GetErrorsPerDay(GlobalFilter);
+ try
+ {
+ var crashTask = Service.GetCrashesPerDay(GlobalFilter);
+ var errorTask = Service.GetErrorsPerDay(GlobalFilter);
- await Task.WhenAll(crashTask, errorTask);
-
+ await Task.WhenAll(crashTask, errorTask);
- var date = DateOnly.FromDateTime(DateTime.Now).AddDays(-GlobalFilter.NumberOfDays);
- var crashDays = new List();
- var errorDays = new List();
+ var date = DateOnly.FromDateTime(DateTime.Now).AddDays(-GlobalFilter.NumberOfDays);
+ var crashDays = new List();
+ var errorDays = new List();
- for (int i = 0; i <= GlobalFilter.NumberOfDays; i++)
- {
- var currentDate = date.AddDays(i);
- var crashDay = crashTask.Result.SingleOrDefault(x => x.Date == currentDate);
- var errorDay = errorTask.Result.SingleOrDefault(x => x.Date == currentDate);
+ for (int i = 0; i <= GlobalFilter.NumberOfDays; i++)
+ {
+ var currentDate = date.AddDays(i);
+ var crashDay = crashTask.Result.SingleOrDefault(x => x.Date == currentDate);
+ var errorDay = errorTask.Result.SingleOrDefault(x => x.Date == currentDate);
- var crashCount = crashDay?.Count ?? 0;
- var errorCount = errorDay?.Count ?? 0;
+ var crashCount = crashDay?.Count ?? 0;
+ var errorCount = errorDay?.Count ?? 0;
- crashDays.Add(new CountPerDay(currentDate, crashCount));
- errorDays.Add(new CountPerDay(currentDate, errorCount));
- }
+ crashDays.Add(new CountPerDay(currentDate, crashCount));
+ errorDays.Add(new CountPerDay(currentDate, errorCount));
+ }
- crashesPerDays = crashDays;
- errorsPerDays = errorDays;
+ crashesPerDays = crashDays;
+ errorsPerDays = errorDays;
- isLoadingGraph = false;
+ isLoadingGraph = false;
- await InvokeAsync(StateHasChanged);
+ await InvokeAsync(StateHasChanged);
+ }
+ catch(Exception ex)
+ {
+ HandleException(ex);
+ }
}
private async Task LoadUserGraph()
{
diff --git a/TinyInsights.Web/Pages/Dependencies.razor b/TinyInsights.Web/Pages/Dependencies.razor
index dad89c0..96507f7 100644
--- a/TinyInsights.Web/Pages/Dependencies.razor
+++ b/TinyInsights.Web/Pages/Dependencies.razor
@@ -118,12 +118,19 @@
private async Task LoadData()
{
- var topTask = LoadTopDependencies();
- var avgTask = LoadDependencyDuration();
- var failedTask = LoadFailedDependencies();
- var failedPerDaysTask = LoadFailedDependenciesPerDays();
+ try
+ {
+ var topTask = LoadTopDependencies();
+ var avgTask = LoadDependencyDuration();
+ var failedTask = LoadFailedDependencies();
+ var failedPerDaysTask = LoadFailedDependenciesPerDays();
- await Task.WhenAll(topTask, avgTask, failedTask, failedPerDaysTask);
+ await Task.WhenAll(topTask, avgTask, failedTask, failedPerDaysTask);
+ }
+ catch (Exception ex)
+ {
+ HandleException(ex);
+ }
}
private async Task LoadTopDependencies()
diff --git a/TinyInsights.Web/Pages/DeviceAnalytics.razor b/TinyInsights.Web/Pages/DeviceAnalytics.razor
index 58b832c..95df129 100644
--- a/TinyInsights.Web/Pages/DeviceAnalytics.razor
+++ b/TinyInsights.Web/Pages/DeviceAnalytics.razor
@@ -84,7 +84,14 @@
{
await base.OnParametersSetAsync();
- await Task.WhenAll(LoadUserIdioms(), LoadUserOperatingSystems(), LoadManufactures());
+ try
+ {
+ await Task.WhenAll(LoadUserIdioms(), LoadUserOperatingSystems(), LoadManufactures());
+ }
+ catch(Exception ex)
+ {
+ HandleException(ex);
+ }
}
private async Task LoadUserIdioms()
diff --git a/TinyInsights.Web/Pages/ErrorDetails.razor b/TinyInsights.Web/Pages/ErrorDetails.razor
index 2ad60e2..c8cc548 100644
--- a/TinyInsights.Web/Pages/ErrorDetails.razor
+++ b/TinyInsights.Web/Pages/ErrorDetails.razor
@@ -147,17 +147,25 @@
private async Task LoadData()
{
- isLoading = true;
- // Replace ' with the \'
- var escapedId = Id.Replace("'", "\\'");
+ isLoading = true;
- if (isCrash)
+ try
{
- data = await Service.GetCrashDetails(escapedId, GlobalFilter);
+ // Replace ' with the \'
+ var escapedId = Id.Replace("'", "\\'");
+
+ if (isCrash)
+ {
+ data = await Service.GetCrashDetails(escapedId, GlobalFilter);
+ }
+ else
+ {
+ data = await Service.GetErrorDetails(escapedId, GlobalFilter);
+ }
}
- else
+ catch (Exception ex)
{
- data = await Service.GetErrorDetails(escapedId, GlobalFilter);
+ HandleException(ex);
}
isLoading = false;
diff --git a/TinyInsights.Web/Pages/Errors.razor b/TinyInsights.Web/Pages/Errors.razor
index 9d1a29b..c8b0a43 100644
--- a/TinyInsights.Web/Pages/Errors.razor
+++ b/TinyInsights.Web/Pages/Errors.razor
@@ -94,10 +94,17 @@
private async Task LoadData()
{
- var graphTask = LoadGraph();
- var listTask = LoadList();
+ try
+ {
+ var graphTask = LoadGraph();
+ var listTask = LoadList();
- await Task.WhenAll(graphTask, listTask);
+ await Task.WhenAll(graphTask, listTask);
+ }
+ catch (Exception ex)
+ {
+ HandleException(ex);
+ }
}
private async Task LoadGraph()
diff --git a/TinyInsights.Web/Pages/EventDetails.razor b/TinyInsights.Web/Pages/EventDetails.razor
index 39945a7..4f10ab6 100644
--- a/TinyInsights.Web/Pages/EventDetails.razor
+++ b/TinyInsights.Web/Pages/EventDetails.razor
@@ -60,9 +60,16 @@
private async Task LoadData()
{
- var perDayTask = LoadEventsPerDay();
+ try
+ {
+ var perDayTask = LoadEventsPerDay();
- await Task.WhenAll(perDayTask);
+ await Task.WhenAll(perDayTask);
+ }
+ catch(Exception ex)
+ {
+ HandleException(ex);
+ }
}
private async Task LoadEventsPerDay()
diff --git a/TinyInsights.Web/Pages/Events.razor b/TinyInsights.Web/Pages/Events.razor
index 5c645a8..3e719d8 100644
--- a/TinyInsights.Web/Pages/Events.razor
+++ b/TinyInsights.Web/Pages/Events.razor
@@ -1,11 +1,13 @@
@using TinyInsights.Web.Services
+@inherits TinyInsightsComponentBase
+
@inject IInsightsService Service
@inject DialogService DialogService
@if (isLoading)
{
-
+
}
else
{
@@ -13,14 +15,14 @@ else
-
+
-
+
-
+
@@ -44,16 +46,22 @@ else
{
await base.OnParametersSetAsync();
- if(Timestamp.HasValue)
+ try
{
- events = await Service.GetEventsByUser(UserId, Timestamp.Value);
+ if (Timestamp.HasValue)
+ {
+ events = await Service.GetEventsByUser(UserId, Timestamp.Value);
+ }
+ else
+ {
+ events = await Service.GetEventsByUser(UserId, GlobalFilter);
+ }
}
- else
+ catch (Exception ex)
{
- events = await Service.GetEventsByUser(UserId, GlobalFilter);
+ HandleException(ex);
}
-
-
+
isLoading = false;
}
@@ -61,7 +69,7 @@ else
{
await DialogService.OpenAsync($"All properties",
new Dictionary() { { "Properties", item.Data } },
- new DialogOptions() { Width = "700px", Height = "512px", Resizable = true, Draggable = true});
+ new DialogOptions() { Width = "700px", Height = "512px", Resizable = true, Draggable = true });
}
private string GetIcon(EventType eventType) => eventType switch
diff --git a/TinyInsights.Web/Pages/EventsAnalytics.razor b/TinyInsights.Web/Pages/EventsAnalytics.razor
index f6969bc..f5f5b51 100644
--- a/TinyInsights.Web/Pages/EventsAnalytics.razor
+++ b/TinyInsights.Web/Pages/EventsAnalytics.razor
@@ -38,10 +38,10 @@
@code {
-
+
[CascadingParameter]
public GlobalFilter GlobalFilter {get;set;}
-
+
private bool isLoadingPageViews, isLoadingList = true;
private List events = new();
@@ -54,9 +54,16 @@
private async Task LoadData()
{
- var listTask = LoadList();
+ try
+ {
+ var listTask = LoadList();
- await Task.WhenAll(listTask);
+ await Task.WhenAll(listTask);
+ }
+ catch (Exception ex)
+ {
+ HandleException(ex);
+ }
}
private async Task LoadList()
diff --git a/TinyInsights.Web/Pages/FailedDependencies.razor b/TinyInsights.Web/Pages/FailedDependencies.razor
index f12ad40..cda4654 100644
--- a/TinyInsights.Web/Pages/FailedDependencies.razor
+++ b/TinyInsights.Web/Pages/FailedDependencies.razor
@@ -77,11 +77,18 @@
private async Task LoadData()
{
- isLoading = true;
+ try
+ {
+ isLoading = true;
- data = await Service.GetFailedDependencies(Key, GlobalFilter);
+ data = await Service.GetFailedDependencies(Key, GlobalFilter);
- isLoading = false;
+ isLoading = false;
+ }
+ catch(Exception ex)
+ {
+ HandleException(ex);
+ }
}
private async Task ShowAllProperties(ErrorItem item)
diff --git a/TinyInsights.Web/Pages/Home.razor b/TinyInsights.Web/Pages/Home.razor
index 17a89a2..b584ecb 100644
--- a/TinyInsights.Web/Pages/Home.razor
+++ b/TinyInsights.Web/Pages/Home.razor
@@ -37,13 +37,23 @@
[CascadingParameter] public EventCallback IsLoggedInChanged { get; set; }
private readonly AuthModel _model = new();
+ protected override void OnParametersSet()
+ {
+ base.OnParametersSet();
+
+ if (!OperatingSystem.IsBrowser())
+ {
+ NavigationManager.NavigateTo("/login");
+ }
+ }
+
public async Task Open()
{
try
{
if (_model.ApplicationId is not null && _model.ApiKey is not null)
{
- var result = await Service.ValidateToken(_model.ApplicationId, _model.ApiKey);
+ var result = await Service.AddAndValidateApiKey(_model.ApplicationId, _model.ApiKey);
if (result)
{
diff --git a/TinyInsights.Web/Pages/PageAnalytics.razor b/TinyInsights.Web/Pages/PageAnalytics.razor
index 3257ba4..70c2946 100644
--- a/TinyInsights.Web/Pages/PageAnalytics.razor
+++ b/TinyInsights.Web/Pages/PageAnalytics.razor
@@ -52,7 +52,7 @@
@code {
[CascadingParameter]
public GlobalFilter GlobalFilter {get;set;}
-
+
private bool isLoadingPageViews, isLoadingList = true;
private List pageViewsPerDay = new();
private List pageViews = new();
@@ -66,10 +66,17 @@
private async Task LoadData()
{
- var graphTask = LoadGraph();
- var listTask = LoadList();
+ try
+ {
+ var graphTask = LoadGraph();
+ var listTask = LoadList();
- await Task.WhenAll(graphTask, listTask);
+ await Task.WhenAll(graphTask, listTask);
+ }
+ catch (Exception ex)
+ {
+ HandleException(ex);
+ }
}
private async Task LoadGraph()
diff --git a/TinyInsights.Web/Pages/UserAnalytics.razor b/TinyInsights.Web/Pages/UserAnalytics.razor
index 28eedfb..deabfa1 100644
--- a/TinyInsights.Web/Pages/UserAnalytics.razor
+++ b/TinyInsights.Web/Pages/UserAnalytics.razor
@@ -93,8 +93,14 @@
private async Task LoadData()
{
-
- await Task.WhenAll(LoadUsersPerDay(), LoadCountries(), LoadLanguageList());
+ try
+ {
+ await Task.WhenAll(LoadUsersPerDay(), LoadCountries(), LoadLanguageList());
+ }
+ catch (Exception ex)
+ {
+ HandleException(ex);
+ }
}
private async Task LoadUsersPerDay()
diff --git a/TinyInsights.Web/Program.cs b/TinyInsights.Web/Program.cs
index 12ed937..c7caf7e 100644
--- a/TinyInsights.Web/Program.cs
+++ b/TinyInsights.Web/Program.cs
@@ -1,9 +1,9 @@
+using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
+using Radzen;
using TinyInsights.Web;
using TinyInsights.Web.Services;
-using Microsoft.AspNetCore.Components;
-using Radzen;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add("#app");
@@ -16,10 +16,11 @@
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri("https://api.applicationinsights.io/") });
builder.Services.AddSingleton();
+builder.Services.AddSingleton();
-builder.Services.AddCascadingValue( x =>
+builder.Services.AddCascadingValue(provider =>
{
- var filter = new GlobalFilter();
+ var filter = provider.GetRequiredService();
var source = new CascadingValueSource(filter, isFixed: false);
filter.PropertyChanged += (sender, eventArgs) => source.NotifyChangedAsync();
diff --git a/TinyInsights.Web/Services/IInsightsService.cs b/TinyInsights.Web/Services/IInsightsService.cs
index 84ad162..2ae1586 100644
--- a/TinyInsights.Web/Services/IInsightsService.cs
+++ b/TinyInsights.Web/Services/IInsightsService.cs
@@ -2,7 +2,8 @@ namespace TinyInsights.Web.Services;
public interface IInsightsService
{
- Task ValidateToken(string appId, string token);
+ Task AddAndValidateApiKey(string appId, string apiKey);
+ Task<(bool Succeed, string? ErrorMessage)> AddAndValidateBearer(string appId, string token);
Task> GetUniqueAppVersions();
diff --git a/TinyInsights.Web/Services/InsightsService.Diagnostics.cs b/TinyInsights.Web/Services/InsightsService.Diagnostics.cs
index d1e2e56..66c7758 100644
--- a/TinyInsights.Web/Services/InsightsService.Diagnostics.cs
+++ b/TinyInsights.Web/Services/InsightsService.Diagnostics.cs
@@ -5,6 +5,8 @@ namespace TinyInsights.Web.Services;
public partial class InsightsService : IInsightsService
{
+ public event EventHandler UnAuthorized;
+
private readonly HttpClient httpClient;
private string? appId;
@@ -15,11 +17,11 @@ public InsightsService(IHttpClientFactory httpClientFactory)
httpClient.BaseAddress = new Uri("https://api.applicationinsights.io/");
}
- public async Task ValidateToken(string appId, string token)
+ public async Task AddAndValidateApiKey(string appId, string apiKey)
{
this.appId = appId;
- httpClient.DefaultRequestHeaders.Add("x-api-key", token);
+ httpClient.DefaultRequestHeaders.Add("x-api-key", apiKey);
var url = $"/v1/apps/{appId}/events/$all?$top=5";
@@ -28,6 +30,25 @@ public async Task ValidateToken(string appId, string token)
return response.IsSuccessStatusCode;
}
+ public async Task<(bool Succeed, string? ErrorMessage)> AddAndValidateBearer(string appId, string token)
+ {
+ this.appId = appId;
+
+ httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
+
+ var url = $"/v1/apps/{appId}/events/$all?$top=5";
+
+ var response = await httpClient.GetAsync(url);
+
+ if (!response.IsSuccessStatusCode)
+ {
+ var responseContent = await response.Content.ReadAsStringAsync();
+ return (false, responseContent);
+ }
+
+ return (true, null);
+ }
+
public async Task> GetErrorsPerDay(GlobalFilter filter)
{
var queryFilter = GetFilter(filter);
@@ -334,6 +355,11 @@ private async Task GetQueryResult(string query)
var response = await httpClient.PostAsync(url, content);
+ if (response.IsSuccessStatusCode is false && (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || response.StatusCode == System.Net.HttpStatusCode.NotFound))
+ {
+ throw new UnauthorizedAccessException();
+ }
+
var responseContent = await response.Content.ReadAsStringAsync();
var queryResult = JsonSerializer.Deserialize(responseContent,
diff --git a/TinyInsights.Web/TinyInsights.Web.csproj b/TinyInsights.Web/TinyInsights.Web.csproj
index e1b5df5..4aef6c1 100644
--- a/TinyInsights.Web/TinyInsights.Web.csproj
+++ b/TinyInsights.Web/TinyInsights.Web.csproj
@@ -7,6 +7,7 @@
+
diff --git a/TinyInsights.Web/TinyInsightsComponentBase.cs b/TinyInsights.Web/TinyInsightsComponentBase.cs
index 9ab3acc..3fef71d 100644
--- a/TinyInsights.Web/TinyInsightsComponentBase.cs
+++ b/TinyInsights.Web/TinyInsightsComponentBase.cs
@@ -7,6 +7,23 @@ public abstract class TinyInsightsComponentBase : ComponentBase
[CascadingParameter]
public bool IsLoggedIn { get; set; }
- [Inject]
+ [Inject]
public NavigationManager NavigationManager { get; set; } = default!;
+
+ protected void HandleException(Exception ex)
+ {
+ if (ex is UnauthorizedAccessException)
+ {
+ if (OperatingSystem.IsBrowser())
+ {
+ NavigationManager.NavigateTo("/");
+ }
+ else
+ {
+ NavigationManager.NavigateTo("/login");
+ }
+
+ }
+
+ }
}
\ No newline at end of file
diff --git a/TinyInsights.Web/_Imports.razor b/TinyInsights.Web/_Imports.razor
index 3c5b74a..fc42995 100644
--- a/TinyInsights.Web/_Imports.razor
+++ b/TinyInsights.Web/_Imports.razor
@@ -13,4 +13,6 @@
@using TinyInsights.Web.Services.Models
@using Radzen
-@using Radzen.Blazor
\ No newline at end of file
+@using Radzen.Blazor
+
+@using Microsoft.AspNetCore.Components.Authorization
\ No newline at end of file
diff --git a/TinyInsights.Web/wwwroot/css/app.css b/TinyInsights.Web/wwwroot/css/app.css
index 585dcc6..88ccbe9 100644
--- a/TinyInsights.Web/wwwroot/css/app.css
+++ b/TinyInsights.Web/wwwroot/css/app.css
@@ -10,6 +10,7 @@
body{
padding: 0;
margin: 0;
+ font-family: Arial
}
a{
color:#6D8764;
diff --git a/TinyInsights.WebServer/Components/App.razor b/TinyInsights.WebServer/Components/App.razor
index 71f9ad9..7eed765 100644
--- a/TinyInsights.WebServer/Components/App.razor
+++ b/TinyInsights.WebServer/Components/App.razor
@@ -7,13 +7,14 @@
-
+
-
+
+