Skip to content

Commit

Permalink
add profile page
Browse files Browse the repository at this point in the history
  • Loading branch information
josxha committed Jan 6, 2024
1 parent a017e3a commit 4461c7b
Show file tree
Hide file tree
Showing 15 changed files with 261 additions and 12 deletions.
20 changes: 16 additions & 4 deletions KratosSelfService/Controllers/HomeController.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
using KratosSelfService.Models;
using KratosSelfService.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Ory.Kratos.Client.Model;

namespace KratosSelfService.Controllers;

public class HomeController(ILogger<HomeController> logger) : Controller
public class HomeController(IdentitySchemaService schemaService) : Controller
{
[HttpGet("")]
[AllowAnonymous]
public IActionResult Home()
public async Task<IActionResult> Home()
{
return View("Home");
var session = (KratosSession)HttpContext.Items[typeof(KratosSession)]!;
var schema = await schemaService.FetchSchema(session.Identity.SchemaId,
session.Identity.SchemaUrl);
return View("Profile", new ProfileModel(session, IdentitySchemaService.GetTraits(schema)));
}

[HttpGet("welcome")]
Expand All @@ -19,4 +24,11 @@ public IActionResult Welcome()
// this endpoint exists for parity reason to the ory kratos self service ui
return Redirect("~/");
}

[HttpGet("links")]
[AllowAnonymous]
public IActionResult Links()
{
return View("Links");
}
}
2 changes: 1 addition & 1 deletion KratosSelfService/Controllers/WellknownController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace KratosSelfService.Controllers;

public class WellknownController(ILogger<WellknownController> logger, ApiService api) : Controller
public class WellknownController(ApiService api) : Controller
{
[HttpGet("/.well-known/ory/webauthn.js")]
[AllowAnonymous]
Expand Down
5 changes: 5 additions & 0 deletions KratosSelfService/KratosSelfService.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
<ItemGroup>
<PackageReference Include="Ory.Hydra.Client" Version="2.2.0-rc.3"/>
<PackageReference Include="Ory.Kratos.Client" Version="1.0.0"/>
<PackageReference Include="UAParser" Version="3.1.47"/>
</ItemGroup>

<ItemGroup>
Expand All @@ -82,4 +83,8 @@
<AdditionalFiles Include="Views\Settings\Settings.cshtml"/>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\OryAdmin\OryAdmin.csproj"/>
</ItemGroup>

</Project>
8 changes: 7 additions & 1 deletion KratosSelfService/Models/models.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Ory.Hydra.Client.Model;
using Newtonsoft.Json.Schema;
using Ory.Hydra.Client.Model;
using Ory.Kratos.Client.Model;

namespace KratosSelfService.Models;
Expand All @@ -14,6 +15,11 @@ public record LoginModel(
string? logoutUrl
);

public record ProfileModel(
KratosSession session,
Dictionary<List<string>, JSchema> traitSchemas
);

public record LogoutModel(
string logoutChallenge
);
Expand Down
3 changes: 3 additions & 0 deletions KratosSelfService/Resources/CustomTranslator.de.resx
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,7 @@
<data name="sessions.authenticationMethods" xml:space="preserve">
<value>Authentifizierungsmethoden</value>
</data>
<data name="Hello" xml:space="preserve">
<value>Hallo</value>
</data>
</root>
3 changes: 3 additions & 0 deletions KratosSelfService/Resources/CustomTranslator.resx
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,7 @@
<data name="sessions.authenticationMethods" xml:space="preserve">
<value>Authentication methods</value>
</data>
<data name="Hello" xml:space="preserve">
<value>Hello</value>
</data>
</root>
51 changes: 51 additions & 0 deletions KratosSelfService/Services/IdentitySchemaService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using Newtonsoft.Json.Schema;

namespace KratosSelfService.Services;

public class IdentitySchemaService
{
private readonly HttpClient _httpClient = new();
private readonly Dictionary<string, JSchema> _schemaCache = new();

public async Task<JSchema> FetchSchema(string schemaId, string schemaUri)
{
// check if schema object is cached
if (_schemaCache.TryGetValue(schemaId, out var schema))
return schema;
var response = await _httpClient.GetStringAsync(schemaUri);
// request and cache new schema object
_schemaCache[schemaId] = JSchema.Parse(response);
return _schemaCache[schemaId];
}

public static Dictionary<List<string>, JSchema> GetTraits(JSchema schema)
{
var traits = schema.Properties["traits"].Properties;
return FlattenTraits(traits, []);
}

private static Dictionary<List<string>, JSchema> FlattenTraits(IDictionary<string, JSchema> traits,
IReadOnlyCollection<string> pathSections)
{
var map = new Dictionary<List<string>, JSchema>();
foreach (var (traitKey, trait) in traits)
{
var newPathSections = new List<string>(pathSections) { traitKey };
switch (trait.Type)
{
case JSchemaType.Object:
foreach (var entry in FlattenTraits(trait.Properties, newPathSections))
map[entry.Key] = entry.Value;
break;
case JSchemaType.Array:
// TODO support arrays
break;
default: // string, etc.
map[newPathSections] = trait;
break;
}
}

return map;
}
}
1 change: 1 addition & 0 deletions KratosSelfService/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public void ConfigureServices(IServiceCollection services)
// own services
services.AddSingleton<EnvService>();
services.AddSingleton<ApiService>();
services.AddSingleton<IdentitySchemaService>();
}

public void Configure(WebApplication app)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@{
ViewData["Title"] = CustomTranslator.Get("Welcome");
ViewData["Title"] = CustomTranslator.Get("Links");
Layout = "_CardLayout";
}

Expand Down
51 changes: 51 additions & 0 deletions KratosSelfService/Views/Home/Profile.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
@using OryAdmin.Extensions
@using Newtonsoft.Json.Linq
@model ProfileModel
@{
ViewData["Title"] = "View Profile";
Layout = "_Layout";
var traits = (JObject)Model.session.Identity.Traits;
}

<section class="hero has-background-white-ter is-fullheight">
<div class="hero-body">
<div class="container">
<div class="columns is-centered">
<div class="column is-10-tablet is-8-desktop is-6-widescreen">
<div class="box">
<h1 class="title">
@CustomTranslator.Get("Hello") @traits.GetTraitValueFromPath(["name", "first"])
</h1>
<div class="columns is-one-third">
<div class="column">
<figure class="image is-128x128">
<img alt="Profile picture" class="is-rounded"
src="img/Missing_avatar.svg">
</figure>
</div>
<div class="column is-two-thirds">
<table class="table is-fullwidth">
<tbody>
@foreach (var (schemaPathSections, schema) in Model.traitSchemas)
{
<tr>
<td>@schema.Title</td>
<td>@traits.GetTraitValueFromPath(schemaPathSections)</td>
</tr>
}
</tbody>
</table>
</div>
</div>
<hr/>
<div class="buttons is-right mt-3">
<a class="button is-info" href="settings">@OryTranslator.Get("settings.title")</a>
<a class="button is-info" href="sessions">@CustomTranslator.Get("sessions.title")</a>
<a class="button is-warning" href="logout">@CustomTranslator.Get("Logout")</a>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
27 changes: 25 additions & 2 deletions KratosSelfService/Views/Sessions/Sessions.cshtml
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
@model SessionsModel
@using UAParser
@model SessionsModel
@{
ViewData["Title"] = CustomTranslator.Get("sessions.title");
var totalSessions = Model.OtherSessions.Count + 1;
var uaParser = Parser.GetDefault();
}

<div class="section">
Expand All @@ -21,7 +23,17 @@
</thead>
<tbody>
<tr>
<td>@string.Join(", ", Model.CurrentSession.Devices.Select(device => device.IpAddress))</td>
<td>
@foreach (var device in Model.CurrentSession.Devices)
{
var info = uaParser.Parse(device.UserAgent);
<p>
@info.Device.Family on @info.OS
@device.IpAddress
@(string.IsNullOrWhiteSpace(device.Location) ? "" : $"({device.Location})")
</p>
}
</td>
<td>@Model.CurrentSession.AuthenticatedAt</td>
<td>@Model.CurrentSession.ExpiresAt</td>
</tr>
Expand Down Expand Up @@ -53,6 +65,17 @@
@foreach (var session in Model.OtherSessions)
{
<tr>
<td>
@foreach (var device in session.Devices)
{
var info = uaParser.Parse(device.UserAgent);
<p>
@info.Device.Family on @info.OS
@device.IpAddress
@(string.IsNullOrWhiteSpace(device.Location) ? "" : $"({device.Location})")
</p>
}
</td>
<td>@string.Join(", ", session.Devices.Select(device => device.IpAddress))</td>
<td>@session.AuthenticatedAt</td>
<td>@session.ExpiresAt</td>
Expand Down
4 changes: 2 additions & 2 deletions KratosSelfService/Views/Settings/Settings.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
</li>
}
</ul>
<p class="menu-label mt-5">@CustomTranslator.Get("Actions")</p>
<!--<p class="menu-label mt-5">@CustomTranslator.Get("Actions")</p>
<ul class="menu-list">
<li>
<a href="logout">
Expand All @@ -49,7 +49,7 @@
</span>
</a>
</li>
</ul>
</ul>-->
</aside>
</div>
</div>
Expand Down
90 changes: 90 additions & 0 deletions KratosSelfService/wwwroot/img/Missing_avatar.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion OryUI.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/UserDictionary/Words/=Kratos/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Kratos/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Wellknown/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
3 changes: 3 additions & 0 deletions OryUI.sln.DotSettings.user
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/ResxEditorPersonal/CheckedGroups/=KratosSelfService_002FResources_002FCustomTranslator/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/ResxEditorPersonal/Initialized/@EntryValue">True</s:Boolean></wpf:ResourceDictionary>

0 comments on commit 4461c7b

Please sign in to comment.