4 Commits

Author SHA1 Message Date
50be1ea726 Bump braces and gulp
Bumps [braces](https://github.com/micromatch/braces) to 3.0.3 and updates ancestor dependency [gulp](https://github.com/gulpjs/gulp). These dependencies need to be updated together.


Updates `braces` from 2.3.2 to 3.0.3
- [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/braces/commits/3.0.3)

Updates `gulp` from 4.0.2 to 5.0.1
- [Release notes](https://github.com/gulpjs/gulp/releases)
- [Changelog](https://github.com/gulpjs/gulp/blob/master/CHANGELOG.md)
- [Commits](https://github.com/gulpjs/gulp/compare/v4.0.2...v5.0.1)

---
updated-dependencies:
- dependency-name: braces
  dependency-version: 3.0.3
  dependency-type: indirect
- dependency-name: gulp
  dependency-version: 5.0.1
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-13 14:46:45 +00:00
fe6f1581dd updated js (bis) 2025-06-13 15:45:25 +01:00
f322e3f485 updated js 2025-06-13 15:38:03 +01:00
c4dc16dde4 migration net9.0 2025-06-13 15:22:02 +01:00
291 changed files with 5052 additions and 39931 deletions

View File

@ -44,7 +44,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 9.0.x
dotnet-version: 8.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build

7
.github/workflows/main.yml vendored Normal file
View File

@ -0,0 +1,7 @@
on: workflow_call
jobs:
my_first_job:
runs-on: ubuntu-latest
steps:
- name: Run my action
uses: ./.github/worklflows/dotnet

31
.vscode/launch.json vendored
View File

@ -4,32 +4,6 @@
// Pour plus d'informations, visitez : https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "C#: sampleWebAsWebApiClient Debug",
"type": "dotnet",
"request": "launch",
"projectPath": "${workspaceFolder}/src/sampleWebAsWebApiClient/sampleWebAsWebApiClient.csproj"
},
{
"name": ".NET Core Launch (web)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/bin/Debug/<target-framework>/<project-name.dll>",
"args": [],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
"serverReadyAction": {
"action": "openExternally",
"pattern": "\\bNow listening on:\\s+(https?://\\S+)"
},
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"sourceFileMap": {
"/Views": "${workspaceFolder}/Views"
}
},
/* {
@ -109,11 +83,6 @@
"serverReadyAction": {
"action": "openExternally",
"pattern": "\\bNow listening on:\\s+(https?://\\S+)"
},
"presentation": {
"hidden": false,
"group": "run",
"order": 1
}
},
{

17
.vscode/settings.json vendored
View File

@ -1,9 +1,20 @@
{
"dotnet-test-explorer.testProjectPath": "test/**/*Tests.csproj",
"dotnet-test-explorer.testProjectPath": "**/*Tests.@(csproj|vbproj|fsproj)",
"sqltools.connections": [
{
"previewLimit": 50,
"server": "localhost",
"port": 5432,
"driver": "PostgreSQL",
"name": "yavscdev",
"group": "yavsc",
"database": "YavscDev",
"username": "yavscdev",
"password": "admin"
}
],
"cSpell.words": [
"appsettings",
"Cratie",
"Newtonsoft",
"Npgsql",
"Yavsc"

6
.vscode/tasks.json vendored
View File

@ -9,12 +9,8 @@
"args": [
"build",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary;ForceNoAlign",
"/consoleloggerparameters:NoSummary;ForceNoAlign"
],
"group": "build",
"isBuildCommand": true,
"isTestCommand": false,
"problemMatcher": "$msCompile"
},
{

View File

@ -1,50 +0,0 @@
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="AsciiDocNet" Version="1.0.0" />
<PackageVersion Include="bootstrap" Version="5.3.7" />
<PackageVersion Include="coverlet.collector" Version="6.0.4" />
<PackageVersion Include="Google.Apis.Calendar.v3" Version="1.69.0.3746" />
<PackageVersion Include="Google.Apis.Compute.v1" Version="1.70.0.3829" />
<PackageVersion Include="HigginsSoft.IdentityServer8" Version="8.0.5-preview-net9" />
<PackageVersion Include="HigginsSoft.IdentityServer8.AspNetIdentity" Version="8.0.5-preview-net9" />
<PackageVersion Include="IdentityModel.AspNetCore" Version="4.3.0" />
<PackageVersion Include="MailKit" Version="4.13.0" />
<PackageVersion Include="Microsoft.AspNetCore.Antiforgery" Version="2.3.0" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.Google" Version="9.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="9.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Hosting" Version="2.3.0" />
<PackageVersion Include="Microsoft.AspNetCore.Http.Features" Version="5.0.17" />
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="9.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Identity.UI" Version="9.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="9.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Razor" Version="2.3.0" />
<PackageVersion Include="Microsoft.AspNetCore.SignalR" Version="1.2.0" />
<PackageVersion Include="Microsoft.AspNetCore.StaticFiles" Version="2.3.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.7" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.7" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.7" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="9.0.7" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="9.0.7" />
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="9.0.7" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageVersion Include="Microsoft.Playwright" Version="1.53.0" />
<PackageVersion Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="9.0.0" />
<PackageVersion Include="MimeKit" Version="4.13.0" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
<PackageVersion Include="PayPalMerchantSDK" Version="2.16.250" />
<PackageVersion Include="pazof.rules" Version="1.1.3" />
<PackageVersion Include="popper.js" Version="1.16.1" />
<PackageVersion Include="RazorEngine.NetCore" Version="3.1.0" />
<PackageVersion Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageVersion Include="SixLabors.ImageSharp" Version="3.1.10" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="9.0.3" />
<PackageVersion Include="System.Security.Cryptography.Pkcs" Version="9.0.7" />
<PackageVersion Include="xunit" Version="2.9.3" />
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.2" />
</ItemGroup>
</Project>

View File

@ -15,13 +15,14 @@ WorkingDirectory=/srv/www/yavsc/
ExecStart=/srv/www/yavsc/Yavsc
Restart=always
Environment="HOME=/srv/www/yavsc"
Environment="ASPNETCORE_ENVIRONMENT=Production"
Environment="ASPNETCORE_ConnectionStrings__DefaultConnection=YOUR Postgresql CONNECTION STRING"
Environment="ASPNETCORE_ENVIRONMENT=lua"
Environment="ASPNETCORE_ConnectionStrings__DefaultConnection=Server=localhost;Port=5432;Database=lua;Username=lua;Password=f3s-*Vx$;"
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=yavsc
SyslogIdentifier=isnd
[Install]
WantedBy=multi-user.target

View File

@ -1,12 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>1c73094f-959f-4211-b1a1-6a69b236c283</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" />
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.6" />
<ProjectReference Include="../Yavsc.Server/Yavsc.Server.csproj" />
</ItemGroup>
</Project>
</ItemGroup>
</Project>

View File

@ -8,7 +8,6 @@ using Microsoft.EntityFrameworkCore;
using Yavsc.Helpers;
using Yavsc.Models;
using Yavsc.Models.Blog;
using Yavsc.Server.Helpers;
namespace Yavsc.Controllers
{

View File

@ -6,7 +6,6 @@ using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Yavsc.Helpers;
using Yavsc.Models;
using Yavsc.Models.Blog;
using Yavsc.Server.Helpers;
namespace Yavsc.Controllers
{

View File

@ -111,9 +111,9 @@ namespace Yavsc.ApiControllers
var user = dbContext.Users.Single(
u => u.Id == uid
);
var info = user.MoveUserFileToDir(query.Id, query.To);
var info = user.MoveUserFileToDir(query.id, query.to);
if (!info.Done) return new BadRequestObjectResult(info);
return Ok(new { moved = query.Id });
return Ok(new { moved = query.id });
}
[HttpPost]
@ -124,21 +124,21 @@ namespace Yavsc.ApiControllers
if (!ModelState.IsValid) {
var idvr = new ValidRemoteUserFilePathAttribute();
return this.BadRequest(new { id = idvr.IsValid(query.Id), to = idvr.IsValid(query.To), errors = ModelState });
return this.BadRequest(new { id = idvr.IsValid(query.id), to = idvr.IsValid(query.to), errors = ModelState });
}
_logger.LogInformation($"Valid move query: {query.Id} => {query.To}");
_logger.LogInformation($"Valid move query: {query.id} => {query.to}");
var uid = User.FindFirstValue(ClaimTypes.NameIdentifier);
var user = dbContext.Users.Single(
u => u.Id == uid
);
try {
if (Config.UserFilesOptions.FileProvider.GetFileInfo(Path.Combine(user.UserName, query.Id)).Exists)
if (Config.UserFilesOptions.FileProvider.GetFileInfo(Path.Combine(user.UserName, query.id)).Exists)
{
var result = user.MoveUserFile(query.Id, query.To);
var result = user.MoveUserFile(query.id, query.to);
if (!result.Done) return new BadRequestObjectResult(result);
}
else {
var result = user.MoveUserDir(query.Id, query.To);
var result = user.MoveUserDir(query.id, query.to);
if (!result.Done) return new BadRequestObjectResult(result);
}
}

View File

@ -1,16 +1,23 @@
using Yavsc.Attributes.Validation;
namespace Yavsc.Models.FileSystem
{
public class RenameFileQuery {
[ValidRemoteUserFilePath]
[YaStringLength(1, 512)]
public string id { get; set; }
public class MoveFileQuery
{
[ValidRemoteUserFilePath]
[YaStringLength(1, 512)]
public required string Id { get; set; }
[YaStringLength(0, 512)]
[ValidRemoteUserFilePath]
public string to { get; set; }
}
public class MoveFileQuery {
[ValidRemoteUserFilePath]
[YaStringLength(1, 512)]
public string id { get; set; }
[YaStringLength(0, 512)]
[ValidRemoteUserFilePath]
public required string To { get; set; }
}
[YaStringLength(0, 512)]
[ValidRemoteUserFilePath]
public string to { get; set; }
}
}

View File

@ -10,7 +10,6 @@ namespace Yavsc.Controllers
using Models;
using Yavsc.Helpers;
using Yavsc.Models.Blog;
using Yavsc.Server.Helpers;
[Produces("application/json")]
[Route("~/api/PostTagsApi")]

View File

@ -1,15 +0,0 @@
using Yavsc.Attributes.Validation;
namespace Yavsc.Models.FileSystem
{
public class RenameFileQuery
{
[ValidRemoteUserFilePath]
[YaStringLength(1, 512)]
public required string Id { get; set; }
[YaStringLength(0, 512)]
[ValidRemoteUserFilePath]
public required string To { get; set; }
}
}

View File

@ -8,7 +8,6 @@ namespace Yavsc.Controllers
using Microsoft.EntityFrameworkCore;
using Models.Relationship;
using Yavsc.Helpers;
using Yavsc.Server.Helpers;
[Produces("application/json")]
[Route("api/TagsApi")]

View File

@ -6,7 +6,7 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Yavsc.Server.Helpers;
using Yavsc.Api.Helpers;
using Yavsc.Models;
using Yavsc.Models.Workflow;

View File

@ -15,7 +15,6 @@ namespace Yavsc.Controllers
using Yavsc.Abstract.Identity;
using Microsoft.EntityFrameworkCore;
using Yavsc.Helpers;
using Yavsc.Server.Helpers;
[Produces("application/json")]
[Route("api/bookquery"), Authorize(Roles = "Performer,Administrator")]

View File

@ -10,7 +10,6 @@ using Newtonsoft.Json;
using Yavsc.Helpers;
using Yavsc.Models;
using Yavsc.Models.Billing;
using Yavsc.Server.Helpers;
namespace Yavsc.Controllers
{
@ -38,7 +37,7 @@ namespace Yavsc.Controllers
}
// GET: api/Estimate{?ownerId=User.GetUserId()}
[HttpGet]
public IActionResult GetEstimates(string? ownerId = null)
public IActionResult GetEstimates(string ownerId = null)
{
if (ownerId == null) ownerId = User.GetUserId();
else if (!UserIsAdminOrThis(ownerId)) // throw new Exception("Not authorized") ;

View File

@ -4,7 +4,6 @@ using Microsoft.EntityFrameworkCore;
using Yavsc.Helpers;
using Yavsc.Models;
using Yavsc.Models.Billing;
using Yavsc.Server.Helpers;
namespace Yavsc.Controllers
{

View File

@ -40,7 +40,7 @@ namespace Yavsc.ApiControllers
return Ok();
}
[HttpPost("query/accept")]
[HttpPost("query/reject")]
public IActionResult AcceptQuery(string billingCode, long queryId)
{
if (billingCode == null) return BadRequest("billingCode");
@ -51,6 +51,7 @@ namespace Yavsc.ApiControllers
billing.Decided = true;
dbContext.SaveChanges();
return Ok();
}
}
}

View File

@ -4,7 +4,6 @@ using Microsoft.EntityFrameworkCore;
using Yavsc.Helpers;
using Yavsc.Models;
using Yavsc.Models.Market;
using Yavsc.Server.Helpers;
namespace Yavsc.Controllers
{

View File

@ -5,7 +5,6 @@ using Microsoft.EntityFrameworkCore;
using Yavsc.Helpers;
using Yavsc.Models;
using Yavsc.Models.Messaging;
using Yavsc.Server.Helpers;
namespace Yavsc.Controllers
{

View File

@ -3,7 +3,6 @@ using Microsoft.EntityFrameworkCore;
using Yavsc.Helpers;
using Yavsc.Models;
using Yavsc.Models.Haircut;
using Yavsc.Server.Helpers;
namespace Yavsc.Controllers
{

View File

@ -22,7 +22,6 @@ namespace Yavsc.ApiControllers
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Authorization;
using Yavsc.Server.Helpers;
[Route("api/haircut")][Authorize]
public class HairCutController : Controller

View File

@ -3,7 +3,6 @@ using Microsoft.EntityFrameworkCore;
using Yavsc.Helpers;
using Yavsc.Models;
using Yavsc.Models.Musical;
using Yavsc.Server.Helpers;
namespace Yavsc.Controllers
{

View File

@ -3,7 +3,6 @@ using Microsoft.EntityFrameworkCore;
using Yavsc.Helpers;
using Yavsc.Models;
using Yavsc.Models.Musical;
using Yavsc.Server.Helpers;
namespace Yavsc.Controllers
{

View File

@ -8,7 +8,6 @@ using Microsoft.Extensions.Logging;
using Yavsc.Helpers;
using Yavsc.Models;
using Yavsc.Models.Identity;
using Yavsc.Server.Helpers;
[Authorize, Route("~/api/gcm")]
public class NativeConfidentialController : Controller
@ -33,8 +32,7 @@ public class NativeConfidentialController : Controller
[FromBody] DeviceDeclaration declaration)
{
var uid = User.FindFirstValue(ClaimTypes.NameIdentifier);
if (uid == null)
throw new InvalidOperationException("no name identifier from claims");
if (!ModelState.IsValid)
{
_logger.LogError("Invalid model for GCMD");

View File

@ -4,7 +4,6 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Yavsc.Helpers;
using Yavsc.Models;
using Yavsc.Server.Helpers;
namespace Yavsc.Controllers
{

View File

@ -5,7 +5,6 @@ using Microsoft.EntityFrameworkCore;
using Yavsc.Helpers;
using Yavsc.Models;
using Yavsc.Models.Access;
using Yavsc.Server.Helpers;
namespace Yavsc.Controllers
{

View File

@ -4,7 +4,6 @@ using Microsoft.EntityFrameworkCore;
using Yavsc.Helpers;
using Yavsc.Models;
using Yavsc.Models.Access;
using Yavsc.Server.Helpers;
namespace Yavsc.Controllers
{

View File

@ -3,7 +3,6 @@ using Microsoft.EntityFrameworkCore;
using Yavsc.Helpers;
using Yavsc.Models;
using Yavsc.Models.Chat;
using Yavsc.Server.Helpers;
namespace Yavsc.Controllers
{

View File

@ -3,7 +3,6 @@ using Microsoft.EntityFrameworkCore;
using Yavsc.Helpers;
using Yavsc.Models;
using Yavsc.Models.Relationship;
using Yavsc.Server.Helpers;
namespace Yavsc.Controllers
{

View File

@ -3,7 +3,6 @@ using Microsoft.EntityFrameworkCore;
using Yavsc.Abstract.Identity;
using Yavsc.Helpers;
using Yavsc.Models;
using Yavsc.Server.Helpers;
namespace Yavsc.Controllers
{

View File

@ -4,7 +4,6 @@ using Microsoft.EntityFrameworkCore;
using Yavsc.Helpers;
using Yavsc.Models;
using Yavsc.Models.Market;
using Yavsc.Server.Helpers;
namespace Yavsc.Controllers
{

View File

@ -6,7 +6,6 @@ using Microsoft.EntityFrameworkCore;
using Yavsc.Models;
using Yavsc.Api.Helpers;
using Yavsc.Server.Helpers;
using System.Diagnostics;
namespace Yavsc.WebApi.Controllers
{
@ -31,9 +30,9 @@ namespace Yavsc.WebApi.Controllers
return new BadRequestObjectResult(
new { error = "user not found" });
var uid = User.GetUserId();
Debug.Assert(uid != null, "uid is null");
var userData = await GetUserData(uid);
Debug.Assert(userData != null, "userData is null");
var user = new Yavsc.Models.Auth.Me(userData.Id, userData.UserName, userData.Email,
userData.Avatar,
userData.PostalAddress, userData.DedicatedGoogleCalendar);
@ -58,7 +57,7 @@ namespace Yavsc.WebApi.Controllers
[HttpGet("myhost")]
public IActionResult MyHost ()
{
return Ok(new { host = Request.ForwardedFor() });
return Ok(new { host = Request.ForHost() });
}

View File

@ -8,7 +8,6 @@ using Microsoft.EntityFrameworkCore;
using Yavsc.Abstract.Identity;
using Yavsc.Helpers;
using Yavsc.Models;
using Yavsc.Server.Helpers;
namespace Yavsc.Controllers
{

View File

@ -6,7 +6,6 @@ using System.Linq;
using Yavsc.Models;
using Yavsc.Abstract.Identity;
using Yavsc.Helpers;
using Yavsc.Server.Helpers;
namespace Yavsc.ApiControllers.accounting
{

View File

@ -13,8 +13,8 @@ namespace Yavsc.Api.Helpers
public static class RequestHelpers
{
// Check for some apache proxy header, if any
public static string? ForwardedFor(this HttpRequest request) {
string? host = request.Headers["X-Forwarded-For"];
public static string ForHost(this HttpRequest request) {
string host = request.Headers["X-Forwarded-For"];
if (string.IsNullOrEmpty(host)) {
host = request.Host.Value;
} else { // Using X-Forwarded-For last address

View File

@ -0,0 +1,17 @@
using System.Security.Claims;
using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Yavsc.Models;
using Yavsc.Models.Blog;
namespace Yavsc.Api.Helpers
{
public static class UserHelpers
{
public static string GetUserId(this ClaimsPrincipal user)
{
return user.FindFirstValue("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier");
}
}
}

View File

@ -11,6 +11,8 @@
*/
using IdentityModel;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Yavsc.Helpers;
@ -61,8 +63,7 @@ internal class Program
options.IncludeErrorDetails = true;
options.Authority = "https://localhost:5001";
options.TokenValidationParameters =
new() { ValidateAudience = false, RoleClaimType = JwtClaimTypes.Role };
options.MapInboundClaims = true;
new() { ValidateAudience = false };
});
services.AddDbContext<ApplicationDbContext>(options =>
@ -72,7 +73,12 @@ internal class Program
.AddTransient<IBillingService, BillingService>()
.AddTransient<ICalendarManager, CalendarManager>();
services.AddTransient<IFileSystemAuthManager, FileSystemAuthManager>();
/*
services.AddSingleton<IConnexionManager, HubConnectionManager>();
services.AddSingleton<ILiveProcessor, LiveProcessor>();
services.AddIdentityApiEndpoints<ApplicationUser>();
services.AddSession();
*/
WorkflowHelpers.ConfigureBillingService();
using (var app = builder.Build())
{
@ -95,10 +101,15 @@ internal class Program
app.MapDefaultControllerRoute();
app.MapGet("/identity", (HttpContext context) =>
new JsonResult(context?.User?.Claims.Select(c => new { c.Type, c.Value }))
);
);
// app.UseSession();
await app.RunAsync();
}
;
}
}

View File

@ -1,5 +1,5 @@
<Project>
<Project >
<PropertyGroup>
<Version>1.0.8</Version>
</PropertyGroup>
</Project>
</Project>

View File

@ -1,19 +1,16 @@

using Yavsc.Abstract.Identity;
namespace Yavsc
{
public interface IBlogPostPayLoad
{
string? Content { get; set; }
string? Photo { get; set; }
string Content { get; set; }
string Photo { get; set; }
}
public interface IBlogPost : IBlogPostPayLoad, ITrackedEntity, IIdentified<long>, ITitle
public interface IBlogPost :IBlogPostPayLoad, ITrackedEntity, IIdentified<long>, ITitle
{
string AuthorId { get; set; }
IApplicationUser Author { get; }
}
}

View File

@ -5,21 +5,21 @@ namespace Yavsc
public static class Constants
{
public static readonly Scope[] SiteScopes = {
new Scope { Id = "profile", Description = "Your profile informations" },
new Scope { Id = "book" , Description ="Your booking interface"},
new Scope { Id = "blog" , Description ="Your blogging interface"},
new Scope { Id = "estimate" , Description ="Your estimation interface"},
new Scope { Id = "contract" , Description ="Your contract signature access"},
new Scope { Id = "admin" , Description ="Your administration rights on this site"},
new Scope { Id = "moderation" , Description ="Your moderator interface"},
public static readonly Scope[] SiteScopes = { 
new Scope { Id = "profile", Description = "Your profile informations" },  
new Scope { Id = "book" , Description ="Your booking interface"},  
new Scope { Id = "blog" , Description ="Your blogging interface"},  
new Scope { Id = "estimate" , Description ="Your estimation interface"},  
new Scope { Id = "contract" , Description ="Your contract signature access"}, 
new Scope { Id = "admin" , Description ="Your administration rights on this site"}, 
new Scope { Id = "moderation" , Description ="Your moderator interface"}, 
new Scope { Id = "frontoffice" , Description ="Your front office interface" }
};
public const string CompanyClaimType = "https://schemas.pschneider.fr/identity/claims/Company";
public const string UserNameRegExp = @"^[a-zA-Z][a-zA-Z0-9._-]*$";
public const string UserFileNamePatternRegExp = @"^([a-zA-Z0-9._-]*/)*[a-zA-Z0-9._-]+$";
public const string LoginPath = "/signin";
public const string LogoutPath = "/signout";
@ -37,7 +37,7 @@ namespace Yavsc
public const string FrontOfficeGroupName = "FrontOffice";
public const string DefaultAvatar = "/images/Users/icon_user.png";
public const string AnonAvatar = "/images/Users/icon_anon_user.png";
public const string YavscConnectionStringEnvName = "YAVSC_CONNECTION_STRING";
public const string YavscConnectionStringEnvName = "DEFAULTCONNECTION_CONNECTIONSTRING";
// at the end, let 4*4 bytes in peace
public const int WebSocketsMaxBufLen = 4096;
@ -52,7 +52,9 @@ namespace Yavsc
public const int MaxUserNameLength = 26;
public const string LivePath = "/live/cast";
public const string StreamingPath = "/api/stream/put";
public const string RoleClaimName = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role";
}
}

View File

@ -54,7 +54,7 @@ namespace Yavsc.Models.Google.Messaging
/// <summary>
/// The error.
/// </summary>
public string? error;
public string error;
}
/// <summary>

View File

@ -3,10 +3,10 @@
public interface IApplicationUser
{
string Id { get; set; }
string? UserName { get; set; }
string? Avatar { get ; set; }
IAccountBalance? AccountBalance { get; }
string? DedicatedGoogleCalendar { get; }
ILocation? PostalAddress { get; }
string UserName { get; set; }
string Avatar { get ; set; }
IAccountBalance AccountBalance { get; set; }
string DedicatedGoogleCalendar { get; set; }
ILocation PostalAddress { get; set; }
}
}

View File

@ -3,7 +3,7 @@ namespace Yavsc.Abstract.Identity.Security
public interface ICircleAuthorized
{
long Id { get; set; }
string AuthorId { get; }
string OwnerId { get; }
bool AuthorizeCircle(long circleId);
ICircleAuthorization [] GetACL();

View File

@ -1,12 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net9.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Description> A shared model for a little client/server app, dealing about establishing some contract, between some human client and provider.
</Description>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
</Project>
</Project>

View File

@ -1,5 +0,0 @@
{
"version": 1,
"isRoot": true,
"tools": {}
}

View File

@ -31,34 +31,38 @@ public static class Config
/// <summary>
/// Lists Available user profile classes,
/// populated at startup, using reflection.
/// populated at startup, using reflexion.
/// </summary>
public static List<Type> ProfileTypes = new List<Type>();
public static IEnumerable<IdentityResource> IdentityResources =>
[
new IdentityResource[]
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResources.Email()
];
};
public static IEnumerable<ApiScope> TestingApiScopes =>
[
public static IEnumerable<ApiScope> ApiScopes =>
new ApiScope[]
{
new ApiScope("scope1",new string[] {"scope1"}),
new ApiScope("scope2",new string[] {"scope2"}),
];
};
public static IEnumerable<Client> TestingClients =>
[
public static IEnumerable<Client> Clients =>
new Client[]
{
// m2m client credentials flow client
new Client
{
ClientId = "m2m.client",
ClientName = "Client Credentials Client",
ClientSecrets = { new Secret("511536EF-F270-4058-80CA-1C89C192F69A".Sha256()) },
AllowedGrantTypes = GrantTypes.ClientCredentials,
ClientSecrets = { new Secret("511536EF-F270-4058-80CA-1C89C192F69A".Sha256()) },
AllowedScopes = { "scope1" }
},
@ -76,14 +80,14 @@ public static class Config
PostLogoutRedirectUris = { "https://localhost:5003/signout-callback-oidc",
"http://localhost:5002/signout-callback-oidc" },
AllowedScopes = {
AllowedScopes = {
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
IdentityServerConstants.StandardScopes.OfflineAccess,
"scope2" },
"scope2" }
},
];
};
public static PayPalSettings? PayPalSettings { get; set; }
}

View File

@ -1,17 +0,0 @@
namespace Yavsc.Server.Exceptions;
[Serializable]
public class AuthorizationFailureException : Exception
{
public AuthorizationFailureException(Microsoft.AspNetCore.Authorization.AuthorizationResult auth) : base(auth?.Failure?.ToString()??auth?.ToString()??"AuthorizationResult failure")
{
}
public AuthorizationFailureException(string? message) : base(message)
{
}
public AuthorizationFailureException(string? message, Exception? innerException) : base(message, innerException)
{
}
}

View File

@ -1,6 +1,11 @@
using System.Security.Claims;
using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Yavsc.Models;
using Yavsc.Models.Blog;
namespace Yavsc.Server.Helpers
namespace Yavsc.Helpers
{
public static class UserHelpers
{
@ -11,7 +16,7 @@ namespace Yavsc.Server.Helpers
public static string GetUserName(this ClaimsPrincipal user)
{
return user.FindFirstValue("name");
return user.FindFirstValue(ClaimTypes.Name);
}
public static bool IsSignedIn(this ClaimsPrincipal user)
@ -19,5 +24,29 @@ namespace Yavsc.Server.Helpers
return user.Identity.IsAuthenticated;
}
public static IEnumerable<BlogPost> UserPosts(this ApplicationDbContext dbContext, string posterId, string readerId)
{
if (readerId == null)
{
var userPosts = dbContext.BlogSpot.Include(
b => b.Author
).Where(x => ((x.AuthorId == posterId))).ToArray();
return userPosts;
}
else
{
long[] readerCirclesMemberships =
dbContext.Circle.Include(c => c.Members)
.Where(c => c.Members.Any(m => m.MemberId == readerId))
.Select(c => c.Id).ToArray();
return dbContext.BlogSpot.Include(
b => b.Author
).Include(p => p.ACL).Where(x => x.Author.Id == posterId &&
(x.ACL.Count == 0 || x.ACL.Any(a => readerCirclesMemberships.Contains(a.CircleId))));
}
}
}
}

View File

@ -16,80 +16,75 @@ namespace Yavsc.Helpers
public static class WorkflowHelpers
{
public static async Task<List<PerformerProfileViewModel>>
ListPerformersAsync(this ApplicationDbContext context,
public static async Task<List<PerformerProfileViewModel>>
ListPerformersAsync(this ApplicationDbContext context,
IBillingService billing,
string actCode)
{
var actors = context.Performers
.Include(p => p.Activity)
.Include(p => p.Performer)
.Where(p => p.Active && p.Activity.Any(u => u.DoesCode == actCode)).OrderBy(x => x.Rate)
.Include(p=>p.Activity)
.Include(p=>p.Performer)
.Where(p => p.Active && p.Activity.Any(u=>u.DoesCode==actCode)).OrderBy( x => x.Rate )
.ToArray();
List<PerformerProfileViewModel> result = new();
List<PerformerProfileViewModel> result = new ();
foreach (var a in actors)
{
var settings = await billing.GetPerformersSettingsAsync(actCode, a.PerformerId);
result.Add(new PerformerProfileViewModel(a, actCode, settings));
result.Add(new PerformerProfileViewModel(a, actCode,settings));
}
return result;
}
public static void RegisterBilling<T>(string code, Func<ApplicationDbContext, long,
IDecidableQuery> getter) where T : IBillable
{
if (BillingService.Billing.ContainsKey(code)
|| BillingService.GlobalBillingMap.ContainsKey(code))
{
throw new InvalidOperationException("Billing setup");
}
BillingService.Billing.Add(code, getter);
BillingService.GlobalBillingMap.Add(typeof(T).Name, code);
}
public static void RegisterBilling<T>(string code, Func<ApplicationDbContext, long,
IDecidableQuery> getter) where T : IBillable
{
BillingService.Billing.Add(code, getter);
BillingService.GlobalBillingMap.Add(typeof(T).Name, code);
}
public static void ConfigureBillingService()
public static void ConfigureBillingService()
{
foreach (var a in System.AppDomain.CurrentDomain.GetAssemblies())
{
foreach (var a in System.AppDomain.CurrentDomain.GetAssemblies())
foreach (var c in a.GetTypes())
{
foreach (var c in a.GetTypes())
if (c.IsClass && !c.IsAbstract &&
c.GetInterface("ISpecializationSettings") != null)
{
if (c.IsClass && !c.IsAbstract &&
c.GetInterface("ISpecializationSettings") != null)
{
Config.ProfileTypes.Add(c);
}
Config.ProfileTypes.Add(c);
}
}
}
foreach (var propertyInfo in typeof(ApplicationDbContext).GetProperties())
foreach (var propertyInfo in typeof(ApplicationDbContext).GetProperties())
{
foreach (var attr in propertyInfo.CustomAttributes)
{
foreach (var attr in propertyInfo.CustomAttributes)
// something like a DbSet?
if (typeof(Yavsc.Attributes.ActivitySettingsAttribute).IsAssignableFrom(attr.AttributeType))
{
// something like a DbSet?
if (typeof(Yavsc.Attributes.ActivitySettingsAttribute).IsAssignableFrom(attr.AttributeType))
{
BillingService.UserSettings.Add(propertyInfo);
}
BillingService.UserSettings.Add(propertyInfo);
}
}
RegisterBilling<HairCutQuery>(BillingCodes.Brush, new Func<ApplicationDbContext, long, IDecidableQuery>
((db, id) =>
{
var query = db.HairCutQueries.Include(q => q.Prestation).Include(q => q.Regularisation).Single(q => q.Id == id);
query.SelectedProfile = db.BrusherProfile.Single(b => b.UserId == query.PerformerId);
return query;
}));
RegisterBilling<HairMultiCutQuery>(BillingCodes.MBrush, new Func<ApplicationDbContext, long, IDecidableQuery>
((db, id) => db.HairMultiCutQueries.Include(q => q.Regularisation).Single(q => q.Id == id)));
RegisterBilling<RdvQuery>(BillingCodes.Rdv, new Func<ApplicationDbContext, long, IDecidableQuery>
((db, id) => db.RdvQueries.Include(q => q.Regularisation).Single(q => q.Id == id)));
}
RegisterBilling<HairCutQuery>(BillingCodes.Brush, new Func<ApplicationDbContext, long, IDecidableQuery>
((db, id) =>
{
var query = db.HairCutQueries.Include(q => q.Prestation).Include(q => q.Regularisation).Single(q => q.Id == id);
query.SelectedProfile = db.BrusherProfile.Single(b => b.UserId == query.PerformerId);
return query;
}));
RegisterBilling<HairMultiCutQuery>(BillingCodes.MBrush, new Func<ApplicationDbContext, long, IDecidableQuery>
((db, id) => db.HairMultiCutQueries.Include(q => q.Regularisation).Single(q => q.Id == id)));
RegisterBilling<RdvQuery>(BillingCodes.Rdv, new Func<ApplicationDbContext, long, IDecidableQuery>
((db, id) => db.RdvQueries.Include(q => q.Regularisation).Single(q => q.Id == id)));
}
}
}

View File

@ -29,14 +29,11 @@ using Microsoft.Extensions.Localization;
namespace Yavsc
{
using System.Diagnostics;
using Microsoft.AspNetCore.Authorization;
using Microsoft.EntityFrameworkCore;
using Models;
using Models.Chat;
using Yavsc.Abstract.Chat;
using Yavsc.Helpers;
using Yavsc.Server.Helpers;
using Yavsc.Services;
public partial class ChatHub : Hub, IDisposable
{
@ -195,11 +192,10 @@ namespace Yavsc
NotifyUserInRoom(NotificationTypes.Error, room, "already registered.");
return;
}
Debug.Assert(Context.User != null);
string userName = Context.User.GetUserName();
string userName = Context.User.Identity.Name;
var user = _dbContext.Users.FirstOrDefault(u => u.UserName == userName);
var newroom = new ChatRoom { Name = room, OwnerId = Context.User.GetUserId() };
var newroom = new ChatRoom { Name = room, OwnerId = user.Id };
ChatRoomInfo chanInfo;
if (_cxManager.TryGetChanInfo(room, out chanInfo))
{
@ -323,7 +319,7 @@ namespace Yavsc
async Task NotifyUser(string type, string targetId, string message)
{
_logger.LogInformation($"notifying user {type} {targetId} : {message}");
_logger.LogInformation("notifying user {type} {targetId} : {message}");
await Clients.Caller.SendAsync("notifyUser", type, targetId, message);
}
@ -335,8 +331,6 @@ namespace Yavsc
[Authorize]
public async Task SendPV(string userName, string message)
{
// Authorized code
Debug.Assert(Context.User != null);
_logger.LogInformation($"Sending pv to {userName}");
if (!InputValidator.ValidateUserName(userName))
@ -350,21 +344,19 @@ namespace Yavsc
return ;
}
_logger.LogInformation($"Message form is validated.");
var identityUserName = Context.User.GetUserName();
if (userName[0] != '?' && Context.User!=null)
if (userName[0] != '?')
if (!Context.User.IsInRole(Constants.AdminGroupName))
{
var bl = _dbContext.BlackListed
.Include(r => r.User)
.Include(r => r.Owner)
.Where(r => r.User.UserName == identityUserName && r.Owner.UserName == userName)
.Where(r => r.User.UserName == Context.User.Identity.Name && r.Owner.UserName == userName)
.Select(r => r.OwnerId);
if (bl.Count() > 0)
{
_logger.LogError($"Black listed : {identityUserName}");
_logger.LogError($"Black listed : {Context.User.Identity.Name}");
await NotifyUser(NotificationTypes.PrivateMessageDenied, userName, "you are black listed.");
return;
}
@ -380,7 +372,7 @@ namespace Yavsc
_logger.LogInformation($"cx: {connectionId}");
var cli = Clients.Client(connectionId);
_logger.LogInformation($"cli: {cli.ToString()}");
await cli.SendAsync("addPV", identityUserName, message);
await cli.SendAsync("addPV", Context.User.Identity.Name, message);
_logger.LogInformation($"Sent pv to cx {connectionId}");
}
}
@ -388,9 +380,6 @@ namespace Yavsc
[Authorize]
public async Task SendStream(string connectionId, long streamId, string message)
{
// Authorized code
Debug.Assert(Context.User != null);
Debug.Assert(Context.User.Identity != null);
if (!InputValidator.ValidateMessage(message)) return;
var sender = Context.User.Identity.Name;
var cli = Clients.Client(connectionId);

View File

@ -1,2 +1,26 @@
listConnections:
dotnet ef migrations list --connection "$(YAVSC_CONNECTION_STRING)"
SOURCE_DIR=../..
MAKEFILE_DIR=$(SOURCE_DIR)/scripts/make
BASERESX=Resources/Yavsc.Models.Relationship.HyperLink.resx \
Resources/Yavsc.Models.Streaming.LiveFlow.resx
BASERESXGEN=$(BASERESX:.resx=.Designer.cs)
include $(MAKEFILE_DIR)/dnx.mk
include $(MAKEFILE_DIR)/versioning.mk
default: all
$(BINTARGETPATH): ../OAuth.AspNet.AuthServer/bin/$(CONFIGURATION)/OAuth.AspNet.AuthServer.dll \
../Yavsc.Abstract/bin/$(CONFIGURATION)/Yavsc.Abstract.dll prepare_code
../OAuth.AspNet.AuthServer/bin/$(CONFIGURATION)/OAuth.AspNet.AuthServer.dll:
make -C ../OAuth.AspNet.AuthServer
../Yavsc.Abstract/bin/$(CONFIGURATION)/Yavsc.Abstract.dll:
make -C ../Yavsc.Abstract
%.Designer.cs: %.resx
strongresbuildercli -l -p -t -r "Yavsc.Server.Resources." $^
prepare_code: $(BASERESXGEN)
all: $(BINTARGETPATH)

File diff suppressed because it is too large Load Diff

View File

@ -1,108 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Yavsc.Migrations
{
/// <inheritdoc />
public partial class ActivityNulls : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "UserModified",
table: "Activities",
type: "text",
nullable: true,
oldClrType: typeof(string),
oldType: "text");
migrationBuilder.AlterColumn<string>(
name: "UserCreated",
table: "Activities",
type: "text",
nullable: true,
oldClrType: typeof(string),
oldType: "text");
migrationBuilder.AlterColumn<string>(
name: "SettingsClassName",
table: "Activities",
type: "text",
nullable: true,
oldClrType: typeof(string),
oldType: "text");
migrationBuilder.AlterColumn<string>(
name: "Photo",
table: "Activities",
type: "text",
nullable: true,
oldClrType: typeof(string),
oldType: "text");
migrationBuilder.AlterColumn<string>(
name: "ModeratorGroupName",
table: "Activities",
type: "text",
nullable: true,
oldClrType: typeof(string),
oldType: "text");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "UserModified",
table: "Activities",
type: "text",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "text",
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "UserCreated",
table: "Activities",
type: "text",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "text",
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "SettingsClassName",
table: "Activities",
type: "text",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "text",
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "Photo",
table: "Activities",
type: "text",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "text",
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "ModeratorGroupName",
table: "Activities",
type: "text",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "text",
oldNullable: true);
}
}
}

View File

@ -1,59 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Yavsc.Migrations
{
/// <inheritdoc />
public partial class BrusherProfileSchedulerId : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_BrusherProfile_Schedule_ScheduleOwnerId",
table: "BrusherProfile");
migrationBuilder.AlterColumn<string>(
name: "ScheduleOwnerId",
table: "BrusherProfile",
type: "text",
nullable: true,
oldClrType: typeof(string),
oldType: "text");
migrationBuilder.AddForeignKey(
name: "FK_BrusherProfile_Schedule_ScheduleOwnerId",
table: "BrusherProfile",
column: "ScheduleOwnerId",
principalTable: "Schedule",
principalColumn: "OwnerId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_BrusherProfile_Schedule_ScheduleOwnerId",
table: "BrusherProfile");
migrationBuilder.AlterColumn<string>(
name: "ScheduleOwnerId",
table: "BrusherProfile",
type: "text",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "text",
oldNullable: true);
migrationBuilder.AddForeignKey(
name: "FK_BrusherProfile_Schedule_ScheduleOwnerId",
table: "BrusherProfile",
column: "ScheduleOwnerId",
principalTable: "Schedule",
principalColumn: "OwnerId",
onDelete: ReferentialAction.Cascade);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,38 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Yavsc.Migrations
{
/// <inheritdoc />
public partial class blogPostPub : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "blogspotPublications",
columns: table => new
{
BlogpostId = table.Column<long>(type: "bigint", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_blogspotPublications", x => x.BlogpostId);
table.ForeignKey(
name: "FK_blogspotPublications_BlogSpot_BlogpostId",
column: x => x.BlogpostId,
principalTable: "BlogSpot",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "blogspotPublications");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,79 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Yavsc.Migrations
{
/// <inheritdoc />
public partial class blogPusb2 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_blogspotPublications_BlogSpot_BlogpostId",
table: "blogspotPublications");
migrationBuilder.DropPrimaryKey(
name: "PK_blogspotPublications",
table: "blogspotPublications");
migrationBuilder.RenameTable(
name: "blogspotPublications",
newName: "blogSpotPublications");
migrationBuilder.AddColumn<bool>(
name: "Publish",
table: "BlogSpot",
type: "boolean",
nullable: false,
defaultValue: false);
migrationBuilder.AddPrimaryKey(
name: "PK_blogSpotPublications",
table: "blogSpotPublications",
column: "BlogpostId");
migrationBuilder.AddForeignKey(
name: "FK_blogSpotPublications_BlogSpot_BlogpostId",
table: "blogSpotPublications",
column: "BlogpostId",
principalTable: "BlogSpot",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_blogSpotPublications_BlogSpot_BlogpostId",
table: "blogSpotPublications");
migrationBuilder.DropPrimaryKey(
name: "PK_blogSpotPublications",
table: "blogSpotPublications");
migrationBuilder.DropColumn(
name: "Publish",
table: "BlogSpot");
migrationBuilder.RenameTable(
name: "blogSpotPublications",
newName: "blogspotPublications");
migrationBuilder.AddPrimaryKey(
name: "PK_blogspotPublications",
table: "blogspotPublications",
column: "BlogpostId");
migrationBuilder.AddForeignKey(
name: "FK_blogspotPublications_BlogSpot_BlogpostId",
table: "blogspotPublications",
column: "BlogpostId",
principalTable: "BlogSpot",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,22 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Yavsc.Migrations
{
/// <inheritdoc />
public partial class blogPub2 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,54 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Yavsc.Migrations
{
/// <inheritdoc />
public partial class commentAllowed : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "Comment",
table: "CircleAuthorizationToBlogPost",
type: "boolean",
nullable: false,
defaultValue: false);
migrationBuilder.AlterColumn<string>(
name: "Avatar",
table: "AspNetUsers",
type: "character varying(512)",
maxLength: 512,
nullable: true,
defaultValue: "/images/Users/icon_user.png",
oldClrType: typeof(string),
oldType: "character varying(512)",
oldMaxLength: 512,
oldDefaultValue: "/images/Users/icon_user.png");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Comment",
table: "CircleAuthorizationToBlogPost");
migrationBuilder.AlterColumn<string>(
name: "Avatar",
table: "AspNetUsers",
type: "character varying(512)",
maxLength: 512,
nullable: false,
defaultValue: "/images/Users/icon_user.png",
oldClrType: typeof(string),
oldType: "character varying(512)",
oldMaxLength: 512,
oldNullable: true,
oldDefaultValue: "/images/Users/icon_user.png");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,29 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Yavsc.Migrations
{
/// <inheritdoc />
public partial class noPublishColumn : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Publish",
table: "BlogSpot");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "Publish",
table: "BlogSpot",
type: "boolean",
nullable: false,
defaultValue: false);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,182 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Yavsc.Migrations
{
/// <inheritdoc />
public partial class nullPaimentIdOnQuery : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_HairCutQueries_PayPalPayment_PaymentId",
table: "HairCutQueries");
migrationBuilder.DropForeignKey(
name: "FK_HairMultiCutQueries_PayPalPayment_PaymentId",
table: "HairMultiCutQueries");
migrationBuilder.DropForeignKey(
name: "FK_Project_PayPalPayment_PaymentId",
table: "Project");
migrationBuilder.DropForeignKey(
name: "FK_RdvQueries_PayPalPayment_PaymentId",
table: "RdvQueries");
migrationBuilder.AlterColumn<string>(
name: "PaymentId",
table: "RdvQueries",
type: "text",
nullable: true,
oldClrType: typeof(string),
oldType: "text");
migrationBuilder.AlterColumn<string>(
name: "PaymentId",
table: "Project",
type: "text",
nullable: true,
oldClrType: typeof(string),
oldType: "text");
migrationBuilder.AlterColumn<string>(
name: "PaymentId",
table: "HairMultiCutQueries",
type: "text",
nullable: true,
oldClrType: typeof(string),
oldType: "text");
migrationBuilder.AlterColumn<string>(
name: "PaymentId",
table: "HairCutQueries",
type: "text",
nullable: true,
oldClrType: typeof(string),
oldType: "text");
migrationBuilder.AddForeignKey(
name: "FK_HairCutQueries_PayPalPayment_PaymentId",
table: "HairCutQueries",
column: "PaymentId",
principalTable: "PayPalPayment",
principalColumn: "CreationToken");
migrationBuilder.AddForeignKey(
name: "FK_HairMultiCutQueries_PayPalPayment_PaymentId",
table: "HairMultiCutQueries",
column: "PaymentId",
principalTable: "PayPalPayment",
principalColumn: "CreationToken");
migrationBuilder.AddForeignKey(
name: "FK_Project_PayPalPayment_PaymentId",
table: "Project",
column: "PaymentId",
principalTable: "PayPalPayment",
principalColumn: "CreationToken");
migrationBuilder.AddForeignKey(
name: "FK_RdvQueries_PayPalPayment_PaymentId",
table: "RdvQueries",
column: "PaymentId",
principalTable: "PayPalPayment",
principalColumn: "CreationToken");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_HairCutQueries_PayPalPayment_PaymentId",
table: "HairCutQueries");
migrationBuilder.DropForeignKey(
name: "FK_HairMultiCutQueries_PayPalPayment_PaymentId",
table: "HairMultiCutQueries");
migrationBuilder.DropForeignKey(
name: "FK_Project_PayPalPayment_PaymentId",
table: "Project");
migrationBuilder.DropForeignKey(
name: "FK_RdvQueries_PayPalPayment_PaymentId",
table: "RdvQueries");
migrationBuilder.AlterColumn<string>(
name: "PaymentId",
table: "RdvQueries",
type: "text",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "text",
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "PaymentId",
table: "Project",
type: "text",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "text",
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "PaymentId",
table: "HairMultiCutQueries",
type: "text",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "text",
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "PaymentId",
table: "HairCutQueries",
type: "text",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "text",
oldNullable: true);
migrationBuilder.AddForeignKey(
name: "FK_HairCutQueries_PayPalPayment_PaymentId",
table: "HairCutQueries",
column: "PaymentId",
principalTable: "PayPalPayment",
principalColumn: "CreationToken",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_HairMultiCutQueries_PayPalPayment_PaymentId",
table: "HairMultiCutQueries",
column: "PaymentId",
principalTable: "PayPalPayment",
principalColumn: "CreationToken",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_Project_PayPalPayment_PaymentId",
table: "Project",
column: "PaymentId",
principalTable: "PayPalPayment",
principalColumn: "CreationToken",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_RdvQueries_PayPalPayment_PaymentId",
table: "RdvQueries",
column: "PaymentId",
principalTable: "PayPalPayment",
principalColumn: "CreationToken",
onDelete: ReferentialAction.Cascade);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,117 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Yavsc.Migrations
{
/// <inheritdoc />
public partial class dbCleanup : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_BankBook_BankStatus_BalanceId",
table: "BankBook");
migrationBuilder.DropTable(
name: "OAuth2Tokens");
migrationBuilder.DropTable(
name: "RefreshTokens");
migrationBuilder.DropPrimaryKey(
name: "PK_BankBook",
table: "BankBook");
migrationBuilder.RenameTable(
name: "BankBook",
newName: "BalanceImpact");
migrationBuilder.RenameIndex(
name: "IX_BankBook_BalanceId",
table: "BalanceImpact",
newName: "IX_BalanceImpact_BalanceId");
migrationBuilder.AddPrimaryKey(
name: "PK_BalanceImpact",
table: "BalanceImpact",
column: "Id");
migrationBuilder.AddForeignKey(
name: "FK_BalanceImpact_BankStatus_BalanceId",
table: "BalanceImpact",
column: "BalanceId",
principalTable: "BankStatus",
principalColumn: "UserId",
onDelete: ReferentialAction.Cascade);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_BalanceImpact_BankStatus_BalanceId",
table: "BalanceImpact");
migrationBuilder.DropPrimaryKey(
name: "PK_BalanceImpact",
table: "BalanceImpact");
migrationBuilder.RenameTable(
name: "BalanceImpact",
newName: "BankBook");
migrationBuilder.RenameIndex(
name: "IX_BalanceImpact_BalanceId",
table: "BankBook",
newName: "IX_BankBook_BalanceId");
migrationBuilder.AddPrimaryKey(
name: "PK_BankBook",
table: "BankBook",
column: "Id");
migrationBuilder.CreateTable(
name: "OAuth2Tokens",
columns: table => new
{
UserId = table.Column<string>(type: "text", nullable: false),
AccessToken = table.Column<string>(type: "text", nullable: false),
Expiration = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
ExpiresIn = table.Column<string>(type: "text", nullable: false),
RefreshToken = table.Column<string>(type: "text", nullable: false),
TokenType = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_OAuth2Tokens", x => x.UserId);
});
migrationBuilder.CreateTable(
name: "RefreshTokens",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
ClientId = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
ExpiresUtc = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
IssuedUtc = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
ProtectedTicket = table.Column<string>(type: "text", nullable: false),
Subject = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_RefreshTokens", x => x.Id);
});
migrationBuilder.AddForeignKey(
name: "FK_BankBook_BankStatus_BalanceId",
table: "BankBook",
column: "BalanceId",
principalTable: "BankStatus",
principalColumn: "UserId",
onDelete: ReferentialAction.Cascade);
}
}
}

View File

@ -17,7 +17,7 @@ namespace Yavsc.Migrations
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.7")
.HasAnnotation("ProductVersion", "9.0.6")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
@ -303,9 +303,6 @@ namespace Yavsc.Migrations
b.Property<long>("BlogPostId")
.HasColumnType("bigint");
b.Property<bool>("Comment")
.HasColumnType("boolean");
b.HasKey("CircleId", "BlogPostId");
b.HasIndex("BlogPostId");
@ -341,6 +338,7 @@ namespace Yavsc.Migrations
.HasColumnType("boolean");
b.Property<string>("Avatar")
.IsRequired()
.ValueGeneratedOnAdd()
.HasMaxLength(512)
.HasColumnType("character varying(512)")
@ -471,6 +469,65 @@ namespace Yavsc.Migrations
b.ToTable("Applications");
});
modelBuilder.Entity("Yavsc.Models.Auth.OAuth2Tokens", b =>
{
b.Property<string>("UserId")
.HasColumnType("text");
b.Property<string>("AccessToken")
.IsRequired()
.HasColumnType("text");
b.Property<DateTime>("Expiration")
.HasColumnType("timestamp with time zone");
b.Property<string>("ExpiresIn")
.IsRequired()
.HasColumnType("text");
b.Property<string>("RefreshToken")
.IsRequired()
.HasColumnType("text");
b.Property<string>("TokenType")
.IsRequired()
.HasColumnType("text");
b.HasKey("UserId");
b.ToTable("OAuth2Tokens");
});
modelBuilder.Entity("Yavsc.Models.Auth.RefreshToken", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("ClientId")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<DateTime>("ExpiresUtc")
.HasColumnType("timestamp with time zone");
b.Property<DateTime>("IssuedUtc")
.HasColumnType("timestamp with time zone");
b.Property<string>("ProtectedTicket")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Subject")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.HasKey("Id");
b.ToTable("RefreshTokens");
});
modelBuilder.Entity("Yavsc.Models.Auth.Scope", b =>
{
b.Property<string>("Id")
@ -512,7 +569,7 @@ namespace Yavsc.Migrations
b.HasIndex("BalanceId");
b.ToTable("BalanceImpact");
b.ToTable("BankBook");
});
modelBuilder.Entity("Yavsc.Models.Bank.BankIdentity", b =>
@ -800,16 +857,6 @@ namespace Yavsc.Migrations
b.ToTable("Comment");
});
modelBuilder.Entity("Yavsc.Models.BlogSpotPublication", b =>
{
b.Property<long>("BlogpostId")
.HasColumnType("bigint");
b.HasKey("BlogpostId");
b.ToTable("blogSpotPublications");
});
modelBuilder.Entity("Yavsc.Models.Calendar.Schedule", b =>
{
b.Property<string>("OwnerId")
@ -1076,6 +1123,7 @@ namespace Yavsc.Migrations
.HasColumnType("numeric");
b.Property<string>("ScheduleOwnerId")
.IsRequired()
.HasColumnType("text");
b.Property<decimal>("ShampooPrice")
@ -1167,6 +1215,7 @@ namespace Yavsc.Migrations
.HasColumnType("bigint");
b.Property<string>("PaymentId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("PerformerId")
@ -1257,6 +1306,7 @@ namespace Yavsc.Migrations
.HasColumnType("bigint");
b.Property<string>("PaymentId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("PerformerId")
@ -2031,6 +2081,7 @@ namespace Yavsc.Migrations
.HasColumnType("boolean");
b.Property<string>("ModeratorGroupName")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Name")
@ -2041,18 +2092,22 @@ namespace Yavsc.Migrations
.HasColumnType("text");
b.Property<string>("Photo")
.IsRequired()
.HasColumnType("text");
b.Property<int>("Rate")
.HasColumnType("integer");
b.Property<string>("SettingsClassName")
.IsRequired()
.HasColumnType("text");
b.Property<string>("UserCreated")
.IsRequired()
.HasColumnType("text");
b.Property<string>("UserModified")
.IsRequired()
.HasColumnType("text");
b.HasKey("Code");
@ -2222,6 +2277,7 @@ namespace Yavsc.Migrations
.HasColumnType("integer");
b.Property<string>("PaymentId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("PerformerId")
@ -2382,6 +2438,7 @@ namespace Yavsc.Migrations
.HasColumnType("text");
b.Property<string>("PaymentId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("PerformerId")
@ -2712,17 +2769,6 @@ namespace Yavsc.Migrations
b.Navigation("Post");
});
modelBuilder.Entity("Yavsc.Models.BlogSpotPublication", b =>
{
b.HasOne("Yavsc.Models.Blog.BlogPost", "BlogPost")
.WithMany()
.HasForeignKey("BlogpostId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("BlogPost");
});
modelBuilder.Entity("Yavsc.Models.Calendar.Schedule", b =>
{
b.HasOne("Yavsc.Models.ApplicationUser", "Owner")
@ -2794,7 +2840,9 @@ namespace Yavsc.Migrations
{
b.HasOne("Yavsc.Models.Calendar.Schedule", "Schedule")
.WithMany()
.HasForeignKey("ScheduleOwnerId");
.HasForeignKey("ScheduleOwnerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "BaseProfile")
.WithMany()
@ -2827,7 +2875,9 @@ namespace Yavsc.Migrations
b.HasOne("Yavsc.Models.Payment.PayPalPayment", "Regularisation")
.WithMany()
.HasForeignKey("PaymentId");
.HasForeignKey("PaymentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "PerformerProfile")
.WithMany()
@ -2882,7 +2932,9 @@ namespace Yavsc.Migrations
b.HasOne("Yavsc.Models.Payment.PayPalPayment", "Regularisation")
.WithMany()
.HasForeignKey("PaymentId");
.HasForeignKey("PaymentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "PerformerProfile")
.WithMany()
@ -3218,7 +3270,9 @@ namespace Yavsc.Migrations
b.HasOne("Yavsc.Models.Payment.PayPalPayment", "Regularisation")
.WithMany()
.HasForeignKey("PaymentId");
.HasForeignKey("PaymentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "PerformerProfile")
.WithMany()
@ -3278,7 +3332,9 @@ namespace Yavsc.Migrations
b.HasOne("Yavsc.Models.Payment.PayPalPayment", "Regularisation")
.WithMany()
.HasForeignKey("PaymentId");
.HasForeignKey("PaymentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Yavsc.Models.Workflow.PerformerProfile", "PerformerProfile")
.WithMany()
@ -3321,7 +3377,8 @@ namespace Yavsc.Migrations
modelBuilder.Entity("Yavsc.Models.ApplicationUser", b =>
{
b.Navigation("AccountBalance");
b.Navigation("AccountBalance")
.IsRequired();
b.Navigation("BankInfo");

View File

@ -8,8 +8,8 @@ namespace Yavsc.Models.Access
public class CircleAuthorizationToBlogPost : ICircleAuthorization
{
public long CircleId { get; set; }
public long BlogPostId { get; set; }
public long CircleId { get; set; }
public long BlogPostId { get; set; }
[JsonIgnore]
[ForeignKey("BlogPostId")]
@ -17,10 +17,7 @@ namespace Yavsc.Models.Access
[JsonIgnore]
[ForeignKey("CircleId")]
public virtual Circle Allowed { get; set; }
public bool Comment { get; set; }
public virtual Circle Allowed { get; set; }
}
}

View File

@ -1,22 +1,22 @@

using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Yavsc.Abstract.Models.Messaging;
using System;
using System.Linq;
using System.Threading.Tasks;
using System.Threading;
using Yavsc.Models.Haircut;
using Yavsc.Models.IT.Evolution;
using Yavsc.Models.IT.Fixing;
using Yavsc.Server.Models.EMailing;
using Yavsc.Server.Models.IT.SourceCode;
using Yavsc.Server.Models.IT;
using Yavsc.Abstract.Identity;
using Yavsc.Server.Models.Calendar;
using Yavsc.Models.Streaming;
using Yavsc.Models.Musical;
namespace Yavsc.Models
{
using Haircut;
using IT.Evolution;
using IT.Fixing;
using Streaming;
using Relationship;
using Forms;
using Yavsc;
using Auth;
using Billing;
using Musical;
@ -32,7 +32,15 @@ namespace Yavsc.Models
using Attributes;
using Bank;
using Payment;
using Calendar;
using Blog;
using Yavsc.Abstract.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Yavsc.Server.Models.Calendar;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Yavsc.Abstract.Models.Messaging;
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
@ -42,8 +50,8 @@ namespace Yavsc.Models
}
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{
}
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
@ -53,7 +61,7 @@ namespace Yavsc.Models
builder.Entity<Contact>().HasKey(x => new { x.OwnerId, x.UserId });
builder.Entity<DeviceDeclaration>().Property(x => x.DeclarationDate).HasDefaultValueSql("LOCALTIMESTAMP");
builder.Entity<BlogTag>().HasKey(x => new { x.PostId, x.TagId });
builder.Entity<ApplicationUser>().Property(u => u.FullName).IsRequired(false);
builder.Entity<ApplicationUser>().Property(u => u.DedicatedGoogleCalendar).IsRequired(false);
builder.Entity<ApplicationUser>().HasMany<ChatConnection>(c => c.Connections);
@ -70,10 +78,10 @@ namespace Yavsc.Models
builder.Entity<HairTaintInstance>().HasKey(ti => new { ti.TaintId, ti.PrestationId });
builder.Entity<HyperLink>().HasKey(l => new { l.HRef, l.Method });
builder.Entity<Period>().HasKey(l => new { l.Start, l.End });
builder.Entity<Cratie.Option>().HasKey(o => new { o.Code, o.CodeScrutin });
builder.Entity<Models.Cratie.Option>().HasKey(o => new { o.Code, o.CodeScrutin });
builder.Entity<Notification>().Property(n => n.icon).HasDefaultValue("exclam");
builder.Entity<ChatRoomAccess>().HasKey(p => new { room = p.ChannelName, user = p.UserId });
builder.Entity<InstrumentRating>().HasAlternateKey(i => new { Instrument = i.InstrumentId, owner = i.OwnerId });
builder.Entity<InstrumentRating>().HasAlternateKey(i => new { Instrument= i.InstrumentId, owner = i.OwnerId });
foreach (var et in builder.Model.GetEntityTypes())
{
@ -81,18 +89,30 @@ namespace Yavsc.Models
et.FindProperty("DateCreated").SetAfterSaveBehavior(Microsoft.EntityFrameworkCore.Metadata.PropertySaveBehavior.Ignore);
}
builder.Entity<Activity>().Property(a => a.ParentCode).IsRequired(false);
// builder.Entity<IdentityUserLogin<String>>().HasKey(i=> new { i.LoginProvider, i.UserId, i.ProviderKey });
builder.Entity<Activity>().Property(a=>a.ParentCode).IsRequired(false);
//builder.Entity<BlogPost>().HasOne(p => p.Author).WithMany(a => a.Posts);
}
// this is not a failback procedure.
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
string? envCxStr = Environment.GetEnvironmentVariable(Constants.YavscConnectionStringEnvName);
if (envCxStr != null)
optionsBuilder.UseNpgsql(envCxStr);
base.OnConfiguring(optionsBuilder);
var appSetup = (string) AppDomain.CurrentDomain.GetData(Constants.YavscConnectionStringEnvName);
if (!string.IsNullOrWhiteSpace(appSetup))
{
optionsBuilder.UseNpgsql(appSetup);
return;
}
var envSetup = Environment.GetEnvironmentVariable(Constants.YavscConnectionStringEnvName);
if (envSetup!=null)
optionsBuilder.UseNpgsql(envSetup);
else optionsBuilder.UseNpgsql();
}
public DbSet<Client> Applications { get; set; }
public DbSet<RefreshToken> RefreshTokens { get; set; }
/// <summary>
/// Activities referenced on this site
@ -105,7 +125,7 @@ namespace Yavsc.Models
/// Users posts
/// </summary>
/// <returns></returns>
public DbSet<BlogPost> BlogSpot { get; set; }
public DbSet<Blog.BlogPost> BlogSpot { get; set; }
/// <summary>
/// Skills powered by this site
@ -133,7 +153,14 @@ namespace Yavsc.Models
public DbSet<Estimate> Estimates { get; set; }
public DbSet<AccountBalance> BankStatus { get; set; }
public DbSet<BalanceImpact> BalanceImpact { get; set; }
public DbSet<BalanceImpact> BankBook { get; set; }
/// <summary>
/// Google Calendar offline
/// open auth tokens
/// </summary>
/// <returns>tokens</returns>
public DbSet<OAuth2Tokens> OAuth2Tokens { get; set; }
/// <summary>
/// References all declared external NativeConfidential devices
@ -199,13 +226,14 @@ namespace Yavsc.Models
((ITrackedEntity)entity.Entity).UserModified = userId;
}
}
public int SaveChanges(string userId)
{
AddTimestamps(userId);
return base.SaveChanges();
}
public async Task<int> SaveChangesAsync(string userId, CancellationToken ctoken = default(CancellationToken))
{
@ -254,7 +282,7 @@ namespace Yavsc.Models
public DbSet<Comment> Comment { get; set; }
public DbSet<Announce> Announce { get; set; }
// TODO remove and opt for for memory only storing,
// as long as it must be set empty each time the service is restarted,
// and that chatting should be kept as must as possible independent from db context
@ -267,7 +295,7 @@ namespace Yavsc.Models
public DbSet<GitRepositoryReference> GitRepositoryReference { get; set; }
public DbSet<Project> Project { get; set; }
[Obsolete("use signaled flows")]
public DbSet<LiveFlow> LiveFlow { get; set; }
@ -277,7 +305,5 @@ namespace Yavsc.Models
public DbSet<Scope> Scopes { get; set; }
public DbSet<BlogSpotPublication> blogSpotPublications { get; set; }
public DbSet<Client> Client { get; set; }
}
}

View File

@ -7,12 +7,10 @@ using Yavsc.Models.Identity;
using Yavsc.Models.Chat;
using Yavsc.Models.Bank;
using Yavsc.Models.Access;
using Yavsc.Abstract.Identity;
namespace Yavsc.Models
{
[Table("AspNetUsers")]
public class ApplicationUser : IdentityUser, IApplicationUser
public class ApplicationUser : IdentityUser
{
/// <summary>
/// Another me, as a byte array.TG7@Eu%80rufzkhbb
@ -24,10 +22,10 @@ namespace Yavsc.Models
/// </summary>
/// <returns></returns>
[MaxLength(512)]
public string? Avatar { get; set; }
public string Avatar { get; set; }
[MaxLength(512)]
public string? FullName { get; set; }
public string FullName { get; set; }
/// <summary>
@ -35,31 +33,32 @@ namespace Yavsc.Models
/// </summary>
/// <returns></returns>
[Display(Name = "Account balance")]
public virtual AccountBalance? AccountBalance { get; set; }
public virtual AccountBalance AccountBalance { get; set; }
/// <summary>
/// User's posts
/// </summary>
/// <returns></returns>
[InverseProperty("Author"), JsonIgnore]
public virtual List<Blog.BlogPost>? Posts { get; set; }
public virtual List<Blog.BlogPost> Posts { get; set; }
/// <summary>
/// User's contact list
/// </summary>
/// <returns></returns>
[InverseProperty("Owner"), JsonIgnore]
public virtual List<Contact>? Book { get; set; }
public virtual List<Contact> Book { get; set; }
/// <summary>
/// External devices using the API
/// </summary>
/// <returns></returns>
[InverseProperty("DeviceOwner"), JsonIgnore]
public virtual List<DeviceDeclaration>? DeviceDeclaration { get; set; }
public virtual List<DeviceDeclaration> DeviceDeclaration { get; set; }
[InverseProperty("Owner"), JsonIgnore]
public virtual List<ChatConnection>? Connections { get; set; }
public virtual List<ChatConnection> Connections { get; set; }
/// <summary>
/// User's circles
@ -67,7 +66,7 @@ namespace Yavsc.Models
/// <returns></returns>
[InverseProperty("Owner"), JsonIgnore]
public virtual List<Circle>? Circles { get; set; }
public virtual List<Circle> Circles { get; set; }
/// <summary>
/// Billing postal address
@ -82,14 +81,14 @@ namespace Yavsc.Models
/// </summary>
/// <returns></returns>
[MaxLength(512)]
public string? DedicatedGoogleCalendar { get; set; }
public string DedicatedGoogleCalendar { get; set; }
public override string ToString()
{
return this.Id + " " + this.AccountBalance?.Credits.ToString() + this.Email + " " + this.UserName + " $" + this.AccountBalance?.Credits.ToString();
}
public virtual List<BankIdentity>? BankInfo { get; set; }
public virtual List<BankIdentity> BankInfo { get; set; }
public long DiskQuota { get; set; } = 512 * 1024 * 1024;
public long DiskUsage { get; set; } = 0;
@ -98,24 +97,21 @@ namespace Yavsc.Models
[JsonIgnore]
[InverseProperty("Owner")]
public virtual List<BlackListed>? BlackList { get; set; }
public virtual List<BlackListed> BlackList { get; set; }
public bool AllowMonthlyEmail { get; set; } = false;
[JsonIgnore]
[InverseProperty("Owner")]
public virtual List<ChatRoom>? Rooms { get; set; }
public virtual List<ChatRoom> Rooms { get; set; }
[JsonIgnore]
[InverseProperty("User")]
public virtual List<ChatRoomAccess>? RoomAccess { get; set; }
public virtual List<ChatRoomAccess> RoomAccess { get; set; }
[JsonIgnore]
[InverseProperty("Member")]
public virtual List<CircleMember>? Membership { get; set; }
public virtual List<CircleMember> Membership { get; set; }
IAccountBalance? IApplicationUser.AccountBalance => AccountBalance;
ILocation? IApplicationUser.PostalAddress { get => PostalAddress; }
}
}

View File

@ -98,7 +98,7 @@ namespace Yavsc.Models.Billing
[ForeignKey("Regularisation")]
public string? PaymentId { get; set; }
public string PaymentId { get; set; }
[Display(Name = "Acquittement de la facture")]
public virtual PayPalPayment Regularisation { get; set; }

View File

@ -5,8 +5,6 @@ using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using Yavsc;
using Yavsc.Abstract.Identity;
using Yavsc.Abstract.Identity.Security;
using Yavsc.Attributes.Validation;
using Yavsc.Interfaces;
@ -16,8 +14,7 @@ using Yavsc.ViewModels.Blog;
namespace Yavsc.Models.Blog
{
public class BlogPost : BlogPostBase,
IBlogPost, ICircleAuthorized, ITaggable<long>
public class BlogPost : BlogPostInputViewModel, IBlogPost, ICircleAuthorized, ITaggable<long>, IIdentified<long>
{
[Key(), DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Display(Name="Identifiant du post")]
@ -88,6 +85,7 @@ namespace Yavsc.Models.Blog
[InverseProperty("Post")]
public virtual List<Comment> Comments { get; set; }
IApplicationUser IBlogPost.Author { get => this.Author; }
[NotMapped]
public string OwnerId => AuthorId;
}
}

View File

@ -1,15 +0,0 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Yavsc.Models.Blog;
namespace Yavsc.Models
{
public class BlogSpotPublication
{
[Key]
public long BlogpostId { get; set; }
[ForeignKey("BlogpostId")]
public virtual BlogPost BlogPost{ get; set; }
}
}

View File

@ -60,7 +60,7 @@ namespace Yavsc.Models.Haircut
[DisplayFormat(ConvertEmptyStringToNull = true, NullDisplayText = "[Pas d'emploi du temps spécifié]")]
[Display(Name="Emploi du temps")]
public virtual Schedule? Schedule { get; set; }
public virtual Schedule Schedule { get; set; }
[Display(Name="Coupe femme cheveux longs"),DisplayFormat(DataFormatString="{0:C}")]

View File

@ -1,33 +0,0 @@
namespace Yavsc.Models.Auth
{
using Microsoft.AspNetCore.Identity;
using System.ComponentModel.DataAnnotations.Schema;
public class YaIdentityUserLogin
{
/// <summary>
/// Gets or sets the login provider for the login (e.g. facebook, google)
/// </summary>
public virtual string LoginProvider { get; set; } = default!;
/// <summary>
/// Gets or sets the unique provider identifier for this login.
/// </summary>
public virtual string ProviderKey { get; set; } = default!;
/// <summary>
/// Gets or sets the friendly name used in a UI for this login.
/// </summary>
public virtual string? ProviderDisplayName { get; set; }
/// <summary>
/// Gets or sets the primary key of the user associated with this login.
/// </summary>
public String UserId { get; set; } = default!;
[ForeignKey("UserId")]
public virtual ApplicationUser User { get; set; }
}
}

View File

@ -28,7 +28,7 @@ namespace Yavsc.Models.Workflow
[YaStringLength(512)]
[Display(Name = "Code du parent")]
[ForeignKey("Parent")]
public string? ParentCode { get; set; }
public string ParentCode { get; set; }
[Display(Name = "Activité parent"), JsonIgnore]
public virtual Activity Parent { get; set; }
@ -41,7 +41,7 @@ namespace Yavsc.Models.Workflow
public string Description { get; set; }
[Display(Name = "Photo")]
public string? Photo { get; set; }
public string Photo { get; set; }
[InverseProperty("Context")]
[DisplayAttribute(Name = "Services liés")]
@ -52,7 +52,7 @@ namespace Yavsc.Models.Workflow
/// </summary>
/// <returns></returns>
[DisplayAttribute(Name = "Groupe de modération")]
public string? ModeratorGroupName { get; set; }
public string ModeratorGroupName { get; set; }
/// <summary>
/// indice de recherche de cette activité
@ -64,7 +64,7 @@ namespace Yavsc.Models.Workflow
[DisplayFormatAttribute(DataFormatString="{0}%")]
public int Rate { get; set; }
[DisplayAttribute(Name = "Classe de paramétrage")]
public string? SettingsClassName { get; set; }
public string SettingsClassName { get; set; }
[InverseProperty("Context")]
[Display(Name="Formulaires de commande")]
@ -77,7 +77,7 @@ namespace Yavsc.Models.Workflow
}
[Display(Name="Createur")]
public string? UserCreated
public string UserCreated
{
get; set;
}
@ -89,7 +89,7 @@ namespace Yavsc.Models.Workflow
}
[Display(Name="Utilisateur ayant modifié le dernier")]
public string? UserModified
public string UserModified
{
get; set;
}

View File

@ -8,10 +8,10 @@ namespace Yavsc.Models.societe.com
public class CompanyInfoMessage
{
public bool success { get; set; }
public string? errorType { get; set; }
public string? errorCode { get; set; }
public string? errorMessage { get; set; }
public CompanyInfo? result { get; set; }
public string errorType { get; set; }
public string errorCode { get; set; }
public string errorMessage { get; set; }
public CompanyInfo result { get; set; }
}

View File

@ -1,13 +0,0 @@
using Yavsc.Models.Blog;
public class BlogPostEdition
{
public string Content { get; internal set; }
public string Title { get; internal set; }
public string Photo { get; internal set; }
internal static BlogPostEdition From(BlogPost blog)
{
throw new NotImplementedException();
}
}

View File

@ -49,8 +49,10 @@ namespace Yavsc.Services
public static ConcurrentDictionary<string, ChatRoomInfo> Channels = new ConcurrentDictionary<string, ChatRoomInfo>();
readonly ApplicationDbContext _dbContext;
readonly IStringLocalizer _localizer;
public HubConnectionManager(IServiceScopeFactory ssf )
{
var scope = ssf.CreateScope();
_dbContext = scope.ServiceProvider.GetService<ApplicationDbContext>();
var loggerFactory = scope.ServiceProvider.GetService<ILoggerFactory>();
@ -128,6 +130,7 @@ namespace Yavsc.Services
public bool Part(string cxId, string roomName, string reason)
{
ChatRoomInfo chanInfo;
var userName = ChatUserNames[cxId];
if (Channels.TryGetValue(roomName, out chanInfo))
{
if (!chanInfo.Users.Contains(cxId))

View File

@ -5,7 +5,6 @@ using Microsoft.Extensions.Options;
using rules;
using Yavsc.Helpers;
using Yavsc.Models;
using Yavsc.Server.Helpers;
namespace Yavsc.Services
{

View File

@ -1,9 +1,13 @@
using System.Text;
using System;
using System.Net;
using System.Threading.Tasks;
using MailKit.Net.Smtp;
using MailKit.Security;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using MimeKit;
using Yavsc.Abstract.Manage;
using Microsoft.AspNetCore.Identity;
using Yavsc.Interface;
using Yavsc.Settings;
@ -23,7 +27,8 @@ namespace Yavsc.Services
public MailSender(
IOptions<SiteSettings> sitesOptions,
IOptions<SmtpSettings> smtpOptions,
ILoggerFactory loggerFactory
ILoggerFactory loggerFactory,
IStringLocalizer<Yavsc.YavscLocalization> localizer
)
{
this.localizer = localizer;

View File

@ -57,18 +57,18 @@ namespace Yavsc.Services
var roles = await this._userManager.GetRolesAsync(user);
if (roles.Count()>0)
{
claims.AddRange(roles.Select(r => new Claim(JwtClaimTypes.Role, r)));
claims.AddRange(roles.Select(r => new Claim(Constants.RoleClaimName, r)));
}
}
return claims;
}
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var subjectId = GetSubjectId(context.Subject);
if (subjectId == null) return;
if (subjectId==null) return;
var user = await _userManager.FindByIdAsync(subjectId);
if (user == null) return;
if (user==null) return ;
context.IssuedClaims = await GetClaimsFromUserAsync(context, user);
}

View File

@ -0,0 +1,66 @@
using IdentityServer8.Models;
using IdentityServer8.Stores;
using Microsoft.EntityFrameworkCore;
using Yavsc.Models;
namespace Yavsc.Services;
public class YavscClientStore : IClientStore
{
ApplicationDbContext _context=null;
public YavscClientStore(ApplicationDbContext context)
{
_context = context;
}
async Task<Client> IClientStore.FindClientByIdAsync(string clientId)
{
var app = await _context.Applications.FirstOrDefaultAsync(c=>c.Id == clientId);
if (app == null) return null;
Client client = new()
{
ClientId = app.Id,
ClientName = app.DisplayName,
AbsoluteRefreshTokenLifetime = app.RefreshTokenLifeTime,
AccessTokenLifetime = app.AccessTokenLifetime,
AllowedGrantTypes =
[
GrantType.AuthorizationCode,
GrantType.DeviceFlow,
GrantType.ClientCredentials
],
ClientSecrets = [
new Secret(app.Secret),
]
};
switch(app.Type)
{
case Models.Auth.ApplicationTypes.NativeConfidential:
client.AccessTokenType = AccessTokenType.Reference;
client.AllowedGrantTypes =
[
GrantType.DeviceFlow
];
client.AllowedScopes = [] ;
break;
case Models.Auth.ApplicationTypes.JavaScript:
default:
client.AccessTokenType = AccessTokenType.Jwt;
client.AllowedGrantTypes =
[
GrantType.AuthorizationCode,
GrantType.ClientCredentials
];
client.AllowedScopes = ["openid", "profile"];
break;
}
return client;
}
}

View File

@ -6,9 +6,7 @@ namespace Yavsc
public class SiteSettings
{
public string Title { get; set; } = "Yavsc";
public string Slogan { get; set; } = "";
public string Banner { get; set; } = "";
public string StyleSheet { get; set; } = "site.css";
public string FavIcon { get; set; } = "favicon.ico";

View File

@ -1,50 +1,11 @@
using System.ComponentModel.DataAnnotations;
using Yavsc.Models.Blog;
namespace Yavsc.ViewModels.Blog;
public class BlogPostCreateViewModel : BlogPostBase
{
public bool Publish { get; set; }
}
public class BlogPostEditViewModel : BlogPostCreateViewModel
public class BlogPostEditViewModel : BlogPostInputViewModel
{
[Required]
public required long Id { get; set; }
public BlogPostEditViewModel()
{
}
public static BlogPostEditViewModel From(BlogPost blogInput)
{
return new BlogPostEditViewModel
{
Id = blogInput.Id,
Title = blogInput.Title,
Publish = false,
Photo = blogInput.Photo,
Content = blogInput.Content,
ACL = blogInput.ACL
};
}
public static BlogPostEditViewModel FromViewModel(BlogPostEditViewModel blogInput)
{
return new BlogPostEditViewModel
{
Id = blogInput.Id,
Title = blogInput.Title,
Publish = false,
Photo = blogInput.Photo,
Content = blogInput.Content,
ACL = blogInput.ACL
};
}
public required long Id { get; set; }
}

View File

@ -5,8 +5,8 @@ using Yavsc.Models.Access;
namespace Yavsc.ViewModels.Blog
{
public class BlogPostBase
{
public class BlogPostInputViewModel
{
[StringLength(1024)]
public string? Photo { get; set; }
@ -18,8 +18,8 @@ namespace Yavsc.ViewModels.Blog
public string? Content { get; set; }
[InverseProperty("Target")]
[Display(Name = "Liste de contrôle d'accès")]
public virtual List<CircleAuthorizationToBlogPost>? ACL { get; set; }
[Display(Name="Liste de contrôle d'accès")]
public virtual List<CircleAuthorizationToBlogPost>? ACL { get; set; }
}

View File

@ -1,32 +1,39 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<UserSecretsId>53bd70e8-ff81-497a-847f-a15fd8ea7a09</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" />
<PackageReference Include="HigginsSoft.IdentityServer8" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" />
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" />
<PackageReference Include="Microsoft.AspNetCore.Http.Features" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design">
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
<PackageReference Include="HigginsSoft.IdentityServer8" Version="8.0.4" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="9.0.6" />
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="9.0.6" />
<PackageReference Include="Microsoft.AspNetCore.Http.Features" Version="5.0.17" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.6">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" />
<PackageReference Include="Google.Apis.Calendar.v3" />
<PackageReference Include="PayPalMerchantSDK" />
<PackageReference Include="SixLabors.ImageSharp" />
<PackageReference Include="RazorEngine.NetCore" />
<PackageReference Include="MailKit" />
<PackageReference Include="MimeKit" />
<PackageReference Include="pazof.rules" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.3.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.6" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="9.0.0" />
<PackageReference Include="Google.Apis.Calendar.v3" Version="1.60.0.2993" />
<PackageReference Include="PayPalMerchantSDK" Version="2.16.250" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.9" />
<PackageReference Include="RazorEngine.NetCore" Version="3.1.0" />
<PackageReference Include="MailKit" Version="4.12.1" />
<PackageReference Include="MimeKit" Version="4.12.0" />
<PackageReference Include="pazof.rules" Version="1.1.3" />
</ItemGroup>
<ItemGroup>
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Xml" />
<Reference Include="System.Net" />
<Reference Include="System.Net.Http" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../Yavsc.Abstract/Yavsc.Abstract.csproj" />
</ItemGroup>
</Project>
</Project>

520
src/Yavsc.Server/ansi2html.sh Executable file
View File

@ -0,0 +1,520 @@
#!/bin/sh
# Convert ANSI (terminal) colours and attributes to HTML
# Licence: LGPLv2
# Author:
# http://www.pixelbeat.org/docs/terminal_colours/
# Examples:
# ls -l --color=always | ansi2html.sh > ls.html
# git show --color | ansi2html.sh > last_change.html
# Generally one can use the `script` util to capture full terminal output.
# Changes:
# V0.1, 24 Apr 2008, Initial release
# V0.2, 01 Jan 2009, Phil Harnish <philharnish@gmail.com>
# Support `git diff --color` output by
# matching ANSI codes that specify only
# bold or background colour.
# P@draigBrady.com
# Support `ls --color` output by stripping
# redundant leading 0s from ANSI codes.
# Support `grep --color=always` by stripping
# unhandled ANSI codes (specifically ^[[K).
# V0.3, 20 Mar 2009, http://eexpress.blog.ubuntu.org.cn/
# Remove cat -v usage which mangled non ascii input.
# Cleanup regular expressions used.
# Support other attributes like reverse, ...
# P@draigBrady.com
# Correctly nest <span> tags (even across lines).
# Add a command line option to use a dark background.
# Strip more terminal control codes.
# V0.4, 17 Sep 2009, P@draigBrady.com
# Handle codes with combined attributes and color.
# Handle isolated <bold> attributes with css.
# Strip more terminal control codes.
# V0.24, 14 Sep 2017
# http://github.com/pixelb/scripts/commits/master/scripts/ansi2html.sh
gawk --version >/dev/null || exit 1
if [ "$1" = "--version" ]; then
printf '0.23\n' && exit
fi
usage()
{
printf '%s\n' \
'This utility converts ANSI codes in data passed to stdin
It has 4 optional parameters:
--bg=dark --palette=linux|solarized|tango|xterm --css-only|--body-only
E.g.: ls -l --color=always | ansi2html.sh --bg=dark > ls.html' >&2
exit
}
if [ "$1" = "--help" ]; then
usage
fi
processArg()
{
[ "$1" = "--bg=dark" ] && { dark_bg=yes; return; }
[ "$1" = "--css-only" ] && { css_only=yes; return; }
[ "$1" = "--body-only" ] && { body_only=yes; return; }
if [ "$1" = "--palette=solarized" ]; then
# See http://ethanschoonover.com/solarized
P0=073642; P1=D30102; P2=859900; P3=B58900;
P4=268BD2; P5=D33682; P6=2AA198; P7=EEE8D5;
P8=002B36; P9=CB4B16; P10=586E75; P11=657B83;
P12=839496; P13=6C71C4; P14=93A1A1; P15=FDF6E3;
return;
elif [ "$1" = "--palette=solarized-xterm" ]; then
# Above mapped onto the xterm 256 color palette
P0=262626; P1=AF0000; P2=5F8700; P3=AF8700;
P4=0087FF; P5=AF005F; P6=00AFAF; P7=E4E4E4;
P8=1C1C1C; P9=D75F00; P10=585858; P11=626262;
P12=808080; P13=5F5FAF; P14=8A8A8A; P15=FFFFD7;
return;
elif [ "$1" = "--palette=tango" ]; then
# Gnome default
P0=000000; P1=CC0000; P2=4E9A06; P3=C4A000;
P4=3465A4; P5=75507B; P6=06989A; P7=D3D7CF;
P8=555753; P9=EF2929; P10=8AE234; P11=FCE94F;
P12=729FCF; P13=AD7FA8; P14=34E2E2; P15=EEEEEC;
return;
elif [ "$1" = "--palette=xterm" ]; then
P0=000000; P1=CD0000; P2=00CD00; P3=CDCD00;
P4=0000EE; P5=CD00CD; P6=00CDCD; P7=E5E5E5;
P8=7F7F7F; P9=FF0000; P10=00FF00; P11=FFFF00;
P12=5C5CFF; P13=FF00FF; P14=00FFFF; P15=FFFFFF;
return;
else # linux console
P0=000000; P1=AA0000; P2=00AA00; P3=AA5500;
P4=0000AA; P5=AA00AA; P6=00AAAA; P7=AAAAAA;
P8=555555; P9=FF5555; P10=55FF55; P11=FFFF55;
P12=5555FF; P13=FF55FF; P14=55FFFF; P15=FFFFFF;
[ "$1" = "--palette=linux" ] && return;
fi
}
processArg #defaults
for var in "$@"; do processArg $var; done
[ "$css_only" ] && [ "$body_only" ] && usage
# Mac OSX's GNU sed is installed as gsed
# use e.g. homebrew 'gnu-sed' to get it
if ! sed --version >/dev/null 2>&1; then
if gsed --version >/dev/null 2>&1; then
alias sed=gsed
else
echo "Error, can't find an acceptable GNU sed." >&2
exit 1
fi
fi
[ "$css_only" ] || [ "$body_only" ] || printf '%s' "<html>
<head>
<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>
<style type=\"text/css\">
"
[ "$body_only" ] || printf ".ef0,.f0 { color: #$P0; } .eb0,.b0 { background-color: #$P0; }
.ef1,.f1 { color: #$P1; } .eb1,.b1 { background-color: #$P1; }
.ef2,.f2 { color: #$P2; } .eb2,.b2 { background-color: #$P2; }
.ef3,.f3 { color: #$P3; } .eb3,.b3 { background-color: #$P3; }
.ef4,.f4 { color: #$P4; } .eb4,.b4 { background-color: #$P4; }
.ef5,.f5 { color: #$P5; } .eb5,.b5 { background-color: #$P5; }
.ef6,.f6 { color: #$P6; } .eb6,.b6 { background-color: #$P6; }
.ef7,.f7 { color: #$P7; } .eb7,.b7 { background-color: #$P7; }
.ef8, .f0 > .bold,.bold > .f0 { color: #$P8; font-weight: normal; }
.ef9, .f1 > .bold,.bold > .f1 { color: #$P9; font-weight: normal; }
.ef10,.f2 > .bold,.bold > .f2 { color: #$P10; font-weight: normal; }
.ef11,.f3 > .bold,.bold > .f3 { color: #$P11; font-weight: normal; }
.ef12,.f4 > .bold,.bold > .f4 { color: #$P12; font-weight: normal; }
.ef13,.f5 > .bold,.bold > .f5 { color: #$P13; font-weight: normal; }
.ef14,.f6 > .bold,.bold > .f6 { color: #$P14; font-weight: normal; }
.ef15,.f7 > .bold,.bold > .f7 { color: #$P15; font-weight: normal; }
.eb8 { background-color: #$P8; }
.eb9 { background-color: #$P9; }
.eb10 { background-color: #$P10; }
.eb11 { background-color: #$P11; }
.eb12 { background-color: #$P12; }
.eb13 { background-color: #$P13; }
.eb14 { background-color: #$P14; }
.eb15 { background-color: #$P15; }
"
# The default xterm 256 colour palette
for red in 0 1 2 3 4 5 ; do
for green in 0 1 2 3 4 5 ; do
for blue in 0 1 2 3 4 5 ; do
c=$((16 + ($red * 36) + ($green * 6) + $blue))
r=$((($red * 40 + 55) * ($red > 0)))
g=$((($green * 40 + 55) * ($green > 0)))
b=$((($blue * 40 + 55) * ($blue > 0)))
[ "$body_only" ] || printf ".ef%d { color: #%2.2x%2.2x%2.2x; } " $c $r $g $b
[ "$body_only" ] || printf ".eb%d { background-color: #%2.2x%2.2x%2.2x; }\n" $c $r $g $b
done
done
done
for gray in $(seq 0 23); do
c=$(($gray+232))
l=$(($gray*10 + 8))
[ "$body_only" ] || printf ".ef%d { color: #%2.2x%2.2x%2.2x; } " $c $l $l $l
[ "$body_only" ] || printf ".eb%d { background-color: #%2.2x%2.2x%2.2x; }\n" $c $l $l $l
done
[ "$body_only" ] || printf '%s' '
.f9 { color: '`[ "$dark_bg" ] && printf "#$P7;" || printf "#$P0;"`' }
.b9 { background-color: #'`[ "$dark_bg" ] && printf $P0 || printf $P15`'; }
.f9 > .bold,.bold > .f9, body.f9 > pre > .bold {
/* Bold is heavy black on white, or bright white
depending on the default background */
color: '`[ "$dark_bg" ] && printf "#$P15;" || printf "#$P0;"`'
font-weight: '`[ "$dark_bg" ] && printf 'normal;' || printf 'bold;'`'
}
.reverse {
/* CSS does not support swapping fg and bg colours unfortunately,
so just hardcode something that will look OK on all backgrounds. */
'"color: #$P0; background-color: #$P7;"'
}
.underline { text-decoration: underline; }
.line-through { text-decoration: line-through; }
.blink { text-decoration: blink; }
/* Avoid pixels between adjacent span elements.
Note this only works for lines less than 80 chars
where we close span elements on the same line.
span { display: inline-block; }
*/
'
[ "$body_only" ] || [ "$css_only" ] && printf '%s\n' \
'To use the css generated from --css-only, do: '\
'<head><link rel="stylesheet" type="text/css" href="style.css"></head>' >&2
[ "$css_only" ] && exit
[ "$body_only" ] || printf '%s' '</style>
</head>
<body class="f9 b9">
<pre>
'
[ "$body_only" ] && printf '%s\n' 'Be sure to use <body class="f9 b9"> and <pre>' >&2
p='\x1b\[' #shortcut to match escape codes
# Handle various xterm control sequences.
# See /usr/share/doc/xterm-*/ctlseqs.txt
sed "
# escape ampersand and quote
s#&#\&amp;#g; s#\"#\&quot;#g;
s#\x1b[^\x1b]*\x1b\\\##g # strip anything between \e and ST
s#\x1b][0-9]*;[^\a]*\a##g # strip any OSC (xterm title etc.)
s#\r\$## # strip trailing \r
# strip other non SGR escape sequences
s#[\x07]##g
s#\x1b[]>=\][0-9;]*##g
s#\x1bP+.\{5\}##g
# Mark cursor positioning codes \"Jr;c;
s#${p}\([0-9]\{1,2\}\)G#\"J;\1;#g
s#${p}\([0-9]\{1,2\}\);\([0-9]\{1,2\}\)H#\"J\1;\2;#g
# Mark clear as \"Cn where n=1 is screen and n=0 is to end-of-line
s#${p}H#\"C1;#g
s#${p}K#\"C0;#g
# Mark Cursor move columns as \"Mn where n is +ve for right, -ve for left
s#${p}C#\"M1;#g
s#${p}\([0-9]\{1,\}\)C#\"M\1;#g
s#${p}\([0-9]\{1,\}\)D#\"M-\1;#g
s#${p}\([0-9]\{1,\}\)P#\"X\1;#g
s#${p}[0-9;?]*[^0-9;?m]##g
" |
# Normalize the input before transformation
sed "
# escape HTML (ampersand and quote done above)
s#>#\&gt;#g; s#<#\&lt;#g;
# handle truecolor
s#${p}38;2;\([0-9]\{1,3\}\);\([0-9]\{1,3\}\);\([0-9]\{1,3\}\)m#\
<span style=\"color:rgb(\1\,\2\,\3\)\">#g
s#${p}48;2;\([0-9]\{1,3\}\);\([0-9]\{1,3\}\);\([0-9]\{1,3\}\)m#\
<span style=\"background-color:rgb(\1\,\2\,\3\)\">#g
# normalize SGR codes a little
# split 256 colors out and mark so that they're not
# recognised by the following 'split combined' line
:e
s#${p}\([0-9;]\{1,\}\);\([34]8;5;[0-9]\{1,3\}\)m#${p}\1m${p}¬\2m#g; t e
s#${p}\([34]8;5;[0-9]\{1,3\}\)m#${p}¬\1m#g;
:c
s#${p}\([0-9]\{1,\}\);\([0-9;]\{1,\}\)m#${p}\1m${p}\2m#g; t c # split combined
s#${p}0\([0-7]\)#${p}\1#g #strip leading 0
s#${p}1m\(\(${p}[4579]m\)*\)#\1${p}1m#g #bold last (with clr)
s#${p}m#${p}0m#g #add leading 0 to norm
# undo any 256 color marking
s#${p}¬\([34]8;5;[0-9]\{1,3\}\)m#${p}\1m#g;
# map 16 color codes to color + bold
s#${p}9\([0-7]\)m#${p}3\1m${p}1m#g;
s#${p}10\([0-7]\)m#${p}4\1m${p}1m#g;
# change 'reset' code to \"R
s#${p}0m#\"R;#g
" |
# Convert SGR sequences to HTML
sed "
# common combinations to minimise html (optional)
:f
s#${p}3[0-7]m${p}3\([0-7]\)m#${p}3\1m#g; t f
:b
s#${p}4[0-7]m${p}4\([0-7]\)m#${p}4\1m#g; t b
s#${p}3\([0-7]\)m${p}4\([0-7]\)m#<span class=\"f\1 b\2\">#g
s#${p}4\([0-7]\)m${p}3\([0-7]\)m#<span class=\"f\2 b\1\">#g
s#${p}1m#<span class=\"bold\">#g
s#${p}4m#<span class=\"underline\">#g
s#${p}5m#<span class=\"blink\">#g
s#${p}7m#<span class=\"reverse\">#g
s#${p}9m#<span class=\"line-through\">#g
s#${p}3\([0-9]\)m#<span class=\"f\1\">#g
s#${p}4\([0-9]\)m#<span class=\"b\1\">#g
s#${p}38;5;\([0-9]\{1,3\}\)m#<span class=\"ef\1\">#g
s#${p}48;5;\([0-9]\{1,3\}\)m#<span class=\"eb\1\">#g
s#${p}[0-9;]*m##g # strip unhandled codes
" |
# Convert alternative character set and handle cursor movement codes
# Note we convert here, as if we do at start we have to worry about avoiding
# conversion of SGR codes etc., whereas doing here we only have to
# avoid conversions of stuff between &...; or <...>
#
# Note we could use sed to do this based around:
# sed 'y/abcdefghijklmnopqrstuvwxyz{}`~/▒␉␌␍␊°±␤␋┘┐┌└┼⎺⎻─⎼⎽├┤┴┬│≤≥π£◆·/'
# However that would be very awkward as we need to only conv some input.
# The basic scheme that we do in the awk script below is:
# 1. enable transliterate once "T1; is seen
# 2. disable once "T0; is seen (may be on diff line)
# 3. never transliterate between &; or <> chars
# 4. track x,y movements and active display mode at each position
# 5. buffer line/screen and dump when required
sed "
# change 'smacs' and 'rmacs' to \"T1 and \"T0 to simplify matching.
s#\x1b(0#\"T1;#g;
s#\x0E#\"T1;#g;
s#\x1b(B#\"T0;#g
s#\x0F#\"T0;#g
" |
(
gawk '
function dump_line(l,del,c,blanks,ret) {
for(c=1;c<maxX;c++) {
if ((c SUBSEP l) in attr || length(cur)) {
ret = ret blanks fixas(cur,attr[c,l])
if(del) delete attr[c,l]
blanks=""
}
if ((c SUBSEP l) in dump) {
ret=ret blanks dump[c,l]
if(del) delete dump[c,l]
blanks=""
} else blanks=blanks " "
}
if(length(cur)) ret=ret blanks
return ret
}
function dump_screen(l,ret) {
for(l=1;l<=maxY;l++)
ret=ret dump_line(l,0) "\n"
return ret fixas(cur, "")
}
function atos(a,i,ret) {
for(i=1;i<=length(a);i++) if(i in a) ret=ret a[i]
return ret
}
function fixas(a,s,spc,i,attr,rm,ret) {
spc=length(a)
l=split(s,attr,">")
for(i=1;i<=spc;i++) {
rm=rm?rm:(a[i]!=attr[i]">")
if(rm) {
ret=ret "</span>"
delete a[i];
}
}
for(i=1;i<l;i++) {
attr[i]=attr[i]">"
if(a[i]!=attr[i]) {
a[i]=attr[i]
ret = ret attr[i]
}
}
return ret
}
function encode(string,start,end,i,ret,pos,sc,buf) {
if(!end) end=length(string);
if(!start) start=1;
state=3
for(i=1;i<=length(string);i++) {
c=substr(string,i,1)
if(state==2) {
sc=sc c
if(c==";") {
c=sc
state=last_mode
} else continue
} else {
if(c=="\r") { x=1; continue }
if(c=="<") {
# Change attributes - store current active
# attributes in span array
split(substr(string,i),cord,">");
i+=length(cord[1])
span[++spc]=cord[1] ">"
continue
}
else if(c=="&") {
# All goes to single position till we see a semicolon
sc=c
state=2
continue
}
else if(c=="\b") {
# backspace move insertion point back 1
if(spc) attr[x,y]=atos(span)
x=x>1?x-1:1
continue
}
else if(c=="\"") {
split(substr(string,i+2),cord,";")
cc=substr(string,i+1,1);
if(cc=="T") {
# Transliterate on/off
if(cord[1]==1&&state==3) last_mode=state=4
if(cord[1]==0&&state==4) last_mode=state=3
}
else if(cc=="C") {
# Clear
if(cord[1]+0) {
# Screen - if Recording dump screen
if(dumpStatus==dsActive) ret=ret dump_screen()
dumpStatus=dsActive
delete dump
delete attr
x=y=1
} else {
# To end of line
for(pos=x;pos<maxX;pos++) {
dump[pos,y]=" "
if (!spc) delete attr[pos,y]
else attr[pos,y]=atos(span)
}
}
}
else if(cc=="J") {
# Jump to x,y
i+=length(cord[2])+1
# If line is higher - dump previous screen
if(dumpStatus==dsActive&&cord[1]<y) {
ret=ret dump_screen();
dumpStatus=dsNew;
}
x=cord[2]
if(length(cord[1]) && y!=cord[1]){
y=cord[1]
if(y>maxY) maxY=y
# Change y - start recording
dumpStatus=dumpStatus?dumpStatus:dsReset
}
}
else if(cc=="M") {
# Move left/right on current line
x+=cord[1]
}
else if(cc=="X") {
# delete on right
for(pos=x;pos<=maxX;pos++) {
nx=pos+cord[1]
if(nx<maxX) {
if((nx SUBSEP y) in attr) attr[pos,y] = attr[nx,y]
else delete attr[pos,y]
if((nx SUBSEP y) in dump) dump[pos,y] = dump[nx,y]
else delete dump[pos,y]
} else if(spc) {
attr[pos,y]=atos(span)
dump[pos,y]=" "
}
}
}
else if(cc=="R") {
# Reset attributes
while(spc) delete span[spc--]
}
i+=length(cord[1])+2
continue
}
else if(state==4&&i>=start&&i<=end&&c in Trans) c=Trans[c]
}
if(dumpStatus==dsReset) {
delete dump
delete attr
ret=ret"\n"
dumpStatus=dsActive
}
if(dumpStatus==dsNew) {
# After moving/clearing we are now ready to write
# somthing to the screen so start recording now
ret=ret"\n"
dumpStatus=dsActive
}
if(dumpStatus==dsActive||dumpStatus==dsOff) {
dump[x,y] = c
if(!spc) delete attr[x,y]
else attr[x,y] = atos(span)
if(++x>maxX) maxX=x;
}
}
# End of line if dumping increment y and set x back to first col
x=1
if(!dumpStatus) return ret dump_line(y,1);
else if(++y>maxY) maxY=y;
return ret
}
BEGIN{
OFS=FS
# dump screen status
dsOff=0 # Not dumping screen contents just write output direct
dsNew=1 # Just after move/clear waiting for activity to start recording
dsReset=2 # Screen cleared build new empty buffer and record
dsActive=3 # Currently recording
F="abcdefghijklmnopqrstuvwxyz{}`~"
T="▒␉␌␍␊°±␤␋┘┐┌└┼⎺⎻─⎼⎽├┤┴┬│≤≥π£◆·"
maxX=80
delete cur;
x=y=1
for(i=1;i<=length(F);i++)Trans[substr(F,i,1)]=substr(T,i,1);
}
{ $0=encode($0) }
1
END {
if(dumpStatus) {
print dump_screen();
}
}'
)
[ "$body_only" ] || printf '</pre>
</body>
</html>\n'

View File

@ -27,7 +27,6 @@ using IdentityModel;
using System.Security.Cryptography;
using System.Text.Unicode;
using System.Text;
using Yavsc.Server.Helpers;
namespace Yavsc.Controllers
{

View File

@ -1,228 +0,0 @@
/*
Copyright (c) 2024 HigginsSoft, Alexander Higgins - https://github.com/alexhiggins732/
Copyright (c) 2018, Brock Allen & Dominick Baier. All rights reserved.
Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
Source code and license this software can be found
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
*/
using System.Security.Claims;
using IdentityModel;
using IdentityServer8;
using IdentityServer8.Events;
using IdentityServer8.Services;
using IdentityServer8.Stores;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Yavsc;
using Yavsc.Extensions;
using Yavsc.Interfaces;
using Yavsc.Models;
namespace IdentityServerHost.Quickstart.UI;
[SecurityHeaders]
[AllowAnonymous]
public class ExternalController : Controller
{
private readonly IIdentityServerInteractionService _interaction;
private readonly IClientStore _clientStore;
private readonly ILogger<ExternalController> _logger;
private readonly IEventService _events;
private IExternalIdentityManager _users;
private readonly SignInManager<ApplicationUser> _signInManager;
private readonly RoleManager<IdentityRole> _roleManager;
private readonly ApplicationDbContext _dbContext;
public ExternalController(
IIdentityServerInteractionService interaction,
IClientStore clientStore,
IEventService events,
ILogger<ExternalController> logger,
IExternalIdentityManager externalIdentityProviderManager,
SignInManager<ApplicationUser> signInManager,
ApplicationDbContext dbContext,
RoleManager<IdentityRole> roleManager
)
{
// if the TestUserStore is not in DI, then we'll just use the global users collection
// this is where you would plug in your own custom identity management library (e.g. ASP.NET Identity)
_users = externalIdentityProviderManager;
_interaction = interaction;
_clientStore = clientStore;
_logger = logger;
_events = events;
_signInManager = signInManager;
_roleManager = roleManager;
_dbContext = dbContext;
}
/// <summary>
/// initiate roundtrip to external authentication provider
/// </summary>
[HttpGet]
public IActionResult Challenge(string scheme, string returnUrl)
{
if (string.IsNullOrEmpty(returnUrl)) returnUrl = "~/";
// validate returnUrl - either it is a valid OIDC URL or back to a local page
if (Url.IsLocalUrl(returnUrl) == false && _interaction.IsValidReturnUrl(returnUrl) == false)
{
// user might have clicked on a malicious link - should be logged
throw new Exception("invalid return URL");
}
// start challenge and roundtrip the return URL and scheme
var props = new AuthenticationProperties
{
RedirectUri = Url.Action(nameof(Callback)),
Items =
{
{ "returnUrl", returnUrl },
{ "scheme", scheme },
}
};
return Challenge(props, scheme);
}
/// <summary>
/// Post processing of external authentication
/// </summary>
[HttpGet]
public async Task<IActionResult> Callback()
{
// read external identity from the temporary cookie
var result = await HttpContext.AuthenticateAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);
if (result?.Succeeded != true)
{
throw new Exception("External authentication error");
}
if (_logger.IsEnabled(LogLevel.Debug))
{
var externalClaims = result.Principal.Claims.Select(c => $"{c.Type}: {c.Value}");
_logger.LogDebug("External claims: {@claims}", externalClaims);
}
// lookup our user and external provider info
var (user, provider, providerUserId, claims) = await FindUserFromExternalProvider(result);
if (user == null)
{
// this might be where you might initiate a custom workflow for user registration
// in this sample we don't show how that would be done, as our sample implementation
// simply auto-provisions new external user
user = AutoProvisionUser(provider, providerUserId, claims);
}
// this allows us to collect any additional claims or properties
// for the specific protocols used and store them in the local auth cookie.
// this is typically used to store data needed for signout from those protocols.
var additionalLocalClaims = new List<Claim>();
var localSignInProps = new AuthenticationProperties();
ProcessLoginCallback(result, additionalLocalClaims, localSignInProps);
// issue authentication cookie for user
var isuser = new IdentityServerUser(user.Id)
{
DisplayName = user.UserName,
IdentityProvider = provider,
AdditionalClaims = additionalLocalClaims
};
await HttpContext.SignInAsync(isuser, localSignInProps);
//await HttpContext.SignInAsync(user, _roleManager, false, _dbContext);
// delete temporary cookie used during external authentication
await HttpContext.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);
// retrieve return URL
var returnUrl = result.Properties.Items["returnUrl"] ?? "~/";
// check if external login is in the context of an OIDC request
var context = await _interaction.GetAuthorizationContextAsync(returnUrl);
await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.Id, user.UserName, true, context?.Client.ClientId));
if (context != null)
{
if (context.IsNativeClient())
{
// The client is native, so this change in how to
// return the response is for better UX for the end user.
return this.LoadingPage("Redirect", returnUrl);
}
}
return Redirect(returnUrl);
}
private async Task<(ApplicationUser user,
string provider,
string providerUserId,
IEnumerable<Claim> claims)>
FindUserFromExternalProvider(AuthenticateResult result)
{
var externalUser = result.Principal;
// try to determine the unique id of the external user (issued by the provider)
// the most common claim type for that are the sub claim and the NameIdentifier
// depending on the external provider, some other claim type might be used
var userIdClaim = externalUser.FindFirst(JwtClaimTypes.Subject) ??
externalUser.FindFirst(ClaimTypes.NameIdentifier) ??
throw new Exception("Unknown userid");
// remove the user id claim so we don't include it as an extra claim if/when we provision the user
var claims = externalUser.Claims.ToList();
claims.Remove(userIdClaim);
var provider = result.Properties.Items["scheme"];
var providerUserId = userIdClaim.Value;
// find external user
ApplicationUser? user = await _users.FindByExternaleProviderAsync (provider, providerUserId);
return (user, provider, providerUserId, claims);
}
/// <summary>
/// Register a new user by external id
/// </summary>
/// <param name="provider"></param>
/// <param name="providerUserId"></param>
/// <param name="claims"></param>
/// <returns></returns>
private ApplicationUser AutoProvisionUser(string provider, string providerUserId, IEnumerable<Claim> claims)
{
var user = _users.AutoProvisionUser(provider, providerUserId, claims.ToList());
return user;
}
// if the external login is OIDC-based, there are certain things we need to preserve to make logout work
// this will be different for WS-Fed, SAML2p or other protocols
private void ProcessLoginCallback(AuthenticateResult externalResult, List<Claim> localClaims, AuthenticationProperties localSignInProps)
{
// if the external system sent a session id claim, copy it over
// so we can use it for single sign-out
var sid = externalResult.Principal.Claims.FirstOrDefault(x => x.Type == JwtClaimTypes.SessionId);
if (sid != null)
{
localClaims.Add(new Claim(JwtClaimTypes.SessionId, sid.Value));
}
// if the external provider issued an id_token, we'll keep it for signout
var idToken = externalResult.Properties.GetTokenValue("id_token");
if (idToken != null)
{
localSignInProps.StoreTokens(new[] { new AuthenticationToken { Name = "id_token", Value = idToken } });
}
}
}

View File

@ -1,22 +0,0 @@
/*
Copyright (c) 2024 HigginsSoft, Alexander Higgins - https://github.com/alexhiggins732/
Copyright (c) 2018, Brock Allen & Dominick Baier. All rights reserved.
Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
Source code and license this software can be found
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
*/
using System.Security.Claims;
using Yavsc.Models;
namespace Yavsc.Interfaces;
public interface IExternalIdentityManager
{
ApplicationUser AutoProvisionUser(string provider, string providerUserId, List<Claim> claims);
Task<ApplicationUser?> FindByExternaleProviderAsync(string provider, string providerUserId);
}

View File

@ -16,7 +16,6 @@ using Yavsc.Services;
using Yavsc.ViewModels.Manage;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Authorization;
using Yavsc.Server.Helpers;
namespace Yavsc.Controllers
{
@ -710,8 +709,7 @@ namespace Yavsc.Controllers
private async Task<ApplicationUser> GetCurrentUserAsync()
{
return await _dbContext.Users.Include(u => u.PostalAddress)
.FirstOrDefaultAsync(u => u.Id == User.GetUserId());
return await _dbContext.Users.Include(u => u.PostalAddress).FirstOrDefaultAsync(u => u.Id == User.GetUserId());
}
#endregion

Some files were not shown because too many files have changed in this diff Show More