9 Commits

Author SHA1 Message Date
ac319f9994 AspNetRoles ...
Some checks failed
Dotnet build and test / log-the-inputs (push) Successful in 48s
Dotnet build and test / build (push) Failing after 1m29s
2025-07-31 11:44:02 +01:00
27a55a1cc4 testing 2025-07-30 15:52:01 +01:00
da7b950eed version bumps 2025-07-30 15:51:06 +01:00
d9ff6274d3 repo cleanup 2025-07-30 15:50:19 +01:00
8d36f198d1 Launch Web 2025-07-30 15:50:08 +01:00
e7e5fa4988 allow testing resource owner 2025-07-30 15:49:15 +01:00
041d70a301 Hide the Chat 2025-07-30 15:46:43 +01:00
b4d9bd502d Find the client 2025-07-30 15:45:50 +01:00
124f3092fb build cli 2025-07-16 00:47:50 +01:00
54 changed files with 7292 additions and 1479 deletions

17
.vscode/launch.json vendored
View File

@ -4,6 +4,17 @@
// Pour plus d'informations, visitez : https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "cli .NET Core Launch (console)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/src/cli/bin/Debug/net9.0/cli.dll",
"args": [],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
"console": "internalConsole"
},
{
"name": "C#: sampleWebAsWebApiClient Debug",
"type": "dotnet",
@ -15,9 +26,9 @@
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/bin/Debug/<target-framework>/<project-name.dll>",
"program": "${workspaceFolder}/src/Yavsc/bin/Debug/net9.0/Yavsc.dll",
"args": [],
"cwd": "${workspaceFolder}",
"cwd": "${workspaceFolder}/src/Yavsc",
"stopAtEntry": false,
"serverReadyAction": {
"action": "openExternally",
@ -120,7 +131,7 @@
"name": "web core",
"type": "coreclr",
"request": "launch",
"program": "${workspaceFolder}/src/Yavsc/bin/Debug/net8.0/Yavsc.dll",
"program": "${workspaceFolder}/src/Yavsc/bin/Debug/net9.0/Yavsc.dll",
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
},

7
.vscode/tasks.json vendored
View File

@ -8,14 +8,11 @@
"type": "process",
"args": [
"build",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary;ForceNoAlign",
"/property:GenerateFullPaths=true"
],
"group": "build",
"isBuildCommand": true,
"isTestCommand": false,
"problemMatcher": "$msCompile"
"isTestCommand": false
},
{
"label": "build-web",

View File

@ -3,11 +3,12 @@
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="IdentityModel.OidcClient" Version="6.0.0" />
<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="Google.Apis.Compute.v1" Version="1.70.0.3841" />
<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" />
@ -22,12 +23,16 @@
<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.Razor.Language" Version="6.0.36" />
<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.CommandLineUtils" Version="1.1.1" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="9.0.7" />
<PackageVersion Include="Microsoft.Extensions.Logging" 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" />
@ -40,6 +45,7 @@
<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="Selenium.WebDriver" Version="4.34.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" />

View File

@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Yavsc.Models;
using Yavsc.Models.Chat;
using Yavsc.Server.Helpers;
namespace Yavsc.Controllers
{
@ -45,7 +46,7 @@ namespace Yavsc.Controllers
var uid = User.FindFirstValue(ClaimTypes.NameIdentifier);
if (uid != chatRoomAccess.UserId && uid != chatRoomAccess.Room.OwnerId
&& ! User.IsInRole(Constants.AdminGroupName))
&& ! User.IsInMsRole(Constants.AdminGroupName))
{
ModelState.AddModelError("UserId","get refused");
@ -71,7 +72,7 @@ namespace Yavsc.Controllers
}
var room = _context.ChatRoom.First(channel => channel.Name == chatRoomAccess.ChannelName );
if (uid != room.OwnerId && ! User.IsInRole(Constants.AdminGroupName))
if (uid != room.OwnerId && ! User.IsInMsRole(Constants.AdminGroupName))
{
ModelState.AddModelError("ChannelName", "access put refused");
return BadRequest(ModelState);
@ -109,7 +110,7 @@ namespace Yavsc.Controllers
var uid = User.FindFirstValue(ClaimTypes.NameIdentifier);
var room = _context.ChatRoom.First(channel => channel.Name == chatRoomAccess.ChannelName );
if (room == null || (uid != room.OwnerId && ! User.IsInRole(Constants.AdminGroupName)))
if (room == null || (uid != room.OwnerId && ! User.IsInMsRole(Constants.AdminGroupName)))
{
ModelState.AddModelError("ChannelName", "access post refused");
return BadRequest(ModelState);
@ -153,7 +154,7 @@ namespace Yavsc.Controllers
var uid = User.FindFirstValue(ClaimTypes.NameIdentifier);
var room = _context.ChatRoom.First(channel => channel.Name == chatRoomAccess.ChannelName );
if (room == null || (uid != room.OwnerId && chatRoomAccess.UserId != uid && ! User.IsInRole(Constants.AdminGroupName)))
if (room == null || (uid != room.OwnerId && chatRoomAccess.UserId != uid && ! User.IsInMsRole(Constants.AdminGroupName)))
{
ModelState.AddModelError("UserId", "access drop refused");
return BadRequest(ModelState);

View File

@ -137,7 +137,7 @@ namespace Yavsc.Controllers
if (User.GetUserId() != chatRoom.OwnerId )
{
if (!User.IsInRole(Constants.AdminGroupName))
if (!User.IsInMsRole(Constants.AdminGroupName))
return BadRequest(new {error = "OwnerId"});
}

View File

@ -1,482 +0,0 @@
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Net;
using System.Text;
using GetUsernameAsyncFunc=System.Func<System.Collections.Generic.IDictionary<string,string>, System.Threading.Tasks.Task<string>>;
using System.IO;
using Newtonsoft.Json;
namespace Yavsc.Authentication
{
public class OAuthenticator
{
public OAuthenticator()
{
}
readonly string clientId;
readonly string clientSecret;
readonly string scope;
readonly Uri authorizeUrl;
readonly Uri accessTokenUrl;
readonly Uri redirectUrl;
readonly GetUsernameAsyncFunc getUsernameAsync;
readonly string requestState;
bool reportedForgery = false;
/// <summary>
/// Gets the client identifier.
/// </summary>
/// <value>The client identifier.</value>
public string ClientId
{
get { return this.clientId; }
}
/// <summary>
/// Gets the client secret.
/// </summary>
/// <value>The client secret.</value>
public string ClientSecret
{
get { return this.clientSecret; }
}
/// <summary>
/// Gets the authorization scope.
/// </summary>
/// <value>The authorization scope.</value>
public string Scope
{
get { return this.scope; }
}
/// <summary>
/// Gets the authorize URL.
/// </summary>
/// <value>The authorize URL.</value>
public Uri AuthorizeUrl
{
get { return this.authorizeUrl; }
}
/// <summary>
/// Gets the access token URL.
/// </summary>
/// <value>The URL used to request access tokens after an authorization code was received.</value>
public Uri AccessTokenUrl
{
get { return this.accessTokenUrl; }
}
/// <summary>
/// Redirect Url
/// </summary>
public Uri RedirectUrl
{
get { return this.redirectUrl; }
}
/// <summary>
/// Initializes a new <see cref="Yavsc.Authentication.YaOAuth2WebAuthenticator"/>
/// that authenticates using implicit granting (token).
/// </summary>
/// <param name='clientId'>
/// Client identifier.
/// </param>
/// <param name='scope'>
/// Authorization scope.
/// </param>
/// <param name='authorizeUrl'>
/// Authorize URL.
/// </param>
/// <param name='redirectUrl'>
/// Redirect URL.
/// </param>
/// <param name='getUsernameAsync'>
/// Method used to fetch the username of an account
/// after it has been successfully authenticated.
/// </param>
public OAuthenticator(string clientId, string scope, Uri authorizeUrl, Uri redirectUrl, GetUsernameAsyncFunc getUsernameAsync = null)
: this(redirectUrl)
{
if (string.IsNullOrEmpty(clientId))
{
throw new ArgumentException("clientId must be provided", "clientId");
}
if (authorizeUrl==null)
throw new ArgumentNullException("authorizeUrl");
this.clientId = clientId;
this.scope = scope ?? "";
this.authorizeUrl = authorizeUrl ;
this.getUsernameAsync = getUsernameAsync;
this.accessTokenUrl = null;
}
/// <summary>
/// Initializes a new instance <see cref="ZicMoove.Droid.OAuth.YaOAuth2WebAuthenticator"/>
/// that authenticates using authorization codes (code).
/// </summary>
/// <param name='clientId'>
/// Client identifier.
/// </param>
/// <param name='clientSecret'>
/// Client secret.
/// </param>
/// <param name='scope'>
/// Authorization scope.
/// </param>
/// <param name='authorizeUrl'>
/// Authorize URL.
/// </param>
/// <param name='redirectUrl'>
/// Redirect URL.
/// </param>
/// <param name='accessTokenUrl'>
/// URL used to request access tokens after an authorization code was received.
/// </param>
/// <param name='getUsernameAsync'>
/// Method used to fetch the username of an account
/// after it has been successfully authenticated.
/// </param>
public OAuthenticator(string clientId, string clientSecret, string scope, Uri authorizeUrl, Uri redirectUrl, Uri accessTokenUrl, GetUsernameAsyncFunc getUsernameAsync = null)
: this(redirectUrl, clientSecret, accessTokenUrl)
{
if (string.IsNullOrEmpty(clientId))
{
throw new ArgumentException("clientId must be provided", "clientId");
}
this.clientId = clientId;
if (string.IsNullOrEmpty(clientSecret))
{
throw new ArgumentException("clientSecret must be provided", "clientSecret");
}
this.clientSecret = clientSecret;
this.scope = scope ?? "";
if (authorizeUrl == null)
{
throw new ArgumentNullException("authorizeUrl");
}
this.authorizeUrl = authorizeUrl;
if (accessTokenUrl == null)
{
throw new ArgumentNullException("accessTokenUrl");
}
this.accessTokenUrl = accessTokenUrl;
if (redirectUrl == null)
throw new Exception("redirectUrl is null");
this.redirectUrl = redirectUrl;
this.getUsernameAsync = getUsernameAsync;
}
OAuthenticator(Uri redirectUrl, string clientSecret = null, Uri accessTokenUrl = null)
{
this.redirectUrl = redirectUrl;
this.clientSecret = clientSecret;
this.accessTokenUrl = accessTokenUrl;
//
// Generate a unique state string to check for forgeries
//
var chars = new char[16];
var rand = new Random();
for (var i = 0; i < chars.Length; i++)
{
chars[i] = (char)rand.Next((int)'a', (int)'z' + 1);
}
this.requestState = new string(chars);
}
bool IsImplicit { get { return accessTokenUrl == null; } }
/// <summary>
/// Method that returns the initial URL to be displayed in the web browser.
/// </summary>
/// <returns>
/// A task that will return the initial URL.
/// </returns>
public Task<Uri> GetInitialUrlAsync()
{
var url = new Uri(string.Format(
"{0}?client_id={1}&redirect_uri={2}&response_type={3}&scope={4}&state={5}",
authorizeUrl.AbsoluteUri,
Uri.EscapeDataString(clientId),
Uri.EscapeDataString(RedirectUrl.AbsoluteUri),
IsImplicit ? "token" : "code",
Uri.EscapeDataString(scope),
Uri.EscapeDataString(requestState)));
var tcs = new TaskCompletionSource<Uri>();
tcs.SetResult(url);
return tcs.Task;
}
/// <summary>
/// Raised when a new page has been loaded.
/// </summary>
/// <param name='url'>
/// URL of the page.
/// </param>
/// <param name='query'>
/// The parsed query of the URL.
/// </param>
/// <param name='fragment'>
/// The parsed fragment of the URL.
/// </param>
protected void OnPageEncountered(Uri url, IDictionary<string, string> query, IDictionary<string, string> fragment)
{
if (url.AbsoluteUri.StartsWith(this.redirectUrl.AbsoluteUri))
{
if (!this.redirectUrl.Equals(url)) {
// this is not our redirect page,
// but perhaps one one the third party identity providers
// One don't check for a state here.
//
if (fragment.ContainsKey("continue")) {
var cont = fragment["continue"];
// TODO continue browsing this address
var tcs = new TaskCompletionSource<Uri>();
tcs.SetResult(new Uri(cont));
tcs.Task.RunSynchronously();
}
return;
}
var all = new Dictionary<string, string>(query);
foreach (var kv in fragment)
all[kv.Key] = kv.Value;
//
// Check for forgeries
//
if (all.ContainsKey("state"))
{
if (all["state"] != requestState && !reportedForgery)
{
reportedForgery = true;
OnError("Invalid state from server. Possible forgery!");
return;
}
}
}
}
private void OnError(string v)
{
throw new NotImplementedException();
}
private void OnError(AggregateException ex)
{
throw new NotImplementedException();
}
/// <summary>
/// Raised when a new page has been loaded.
/// </summary>
/// <param name='url'>
/// URL of the page.
/// </param>
/// <param name='query'>
/// The parsed query string of the URL.
/// </param>
/// <param name='fragment'>
/// The parsed fragment of the URL.
/// </param>
protected void OnRedirectPageLoaded(Uri url, IDictionary<string, string> query, IDictionary<string, string> fragment)
{
//
// Look for the access_token
//
if (fragment.ContainsKey("access_token"))
{
//
// We found an access_token
//
OnRetrievedAccountProperties(fragment);
}
else if (!IsImplicit)
{
//
// Look for the code
//
if (query.ContainsKey("code"))
{
var code = query["code"];
RequestAccessTokenAsync(code).ContinueWith(task =>
{
if (task.IsFaulted)
{
OnError(task.Exception);
}
else
{
OnRetrievedAccountProperties(task.Result);
}
}, TaskScheduler.FromCurrentSynchronizationContext());
}
else
{
OnError("Expected code in response, but did not receive one.");
return;
}
}
else
{
OnError("Expected access_token in response, but did not receive one.");
return;
}
}
/// <summary>
/// Asynchronously requests an access token with an authorization <paramref name="code"/>.
/// </summary>
/// <returns>
/// A dictionary of data returned from the authorization request.
/// </returns>
/// <param name='code'>The authorization code.</param>
/// <remarks>Implements: http://tools.ietf.org/html/rfc6749#section-4.1</remarks>
Task<IDictionary<string, string>> RequestAccessTokenAsync(string code)
{
var queryValues = new Dictionary<string, string> {
{ "grant_type", "authorization_code" },
{ "code", code },
{ "redirect_uri", RedirectUrl.AbsoluteUri },
{ "client_id", clientId }
};
if (!string.IsNullOrEmpty(clientSecret))
{
queryValues["client_secret"] = clientSecret;
}
return RequestAccessTokenAsync(queryValues);
}
/// <summary>
/// Asynchronously makes a request to the access token URL with the given parameters.
/// </summary>
/// <param name="queryValues">The parameters to make the request with.</param>
/// <returns>The data provided in the response to the access token request.</returns>
public async Task<IDictionary<string, string>> RequestAccessTokenAsync(IDictionary<string, string> queryValues)
{
StringBuilder postData = new StringBuilder();
if (!queryValues.ContainsKey("client_id"))
{
postData.Append("client_id="+Uri.EscapeDataString($"{this.clientId}")+"&");
}
if (!queryValues.ContainsKey("client_secret"))
{
postData.Append("client_secret="+Uri.EscapeDataString($"{this.clientSecret}")+"&");
}
if (!queryValues.ContainsKey("scope"))
{
postData.Append("scope="+Uri.EscapeDataString($"{this.scope}")+"&");
}
foreach (string key in queryValues.Keys)
{
postData.Append($"{key}="+Uri.EscapeDataString($"{queryValues[key]}")+"&");
}
var req = WebRequest.Create(accessTokenUrl);
(req as HttpWebRequest).Accept = "application/json";
req.Method = "POST";
var body = Encoding.UTF8.GetBytes(postData.ToString());
req.ContentLength = body.Length;
req.ContentType = "application/x-www-form-urlencoded";
var s = req.GetRequestStream();
s.Write(body, 0, body.Length);
var auth = await req.GetResponseAsync();
var repstream = auth.GetResponseStream();
var respReader = new StreamReader(repstream);
var text = await respReader.ReadToEndAsync();
req.Abort();
// Parse the response
var data = text.Contains("{") ? JsonDecode(text) : FormDecode(text);
if (data.ContainsKey("error"))
{
OnError("Error authenticating: " + data["error"]);
}
else if (data.ContainsKey("access_token"))
{
return data;
}
else
{
OnError("Expected access_token in access token response, but did not receive one.");
}
return data;
}
private IDictionary<string,string> FormDecode(string text)
{
throw new NotImplementedException();
}
private IDictionary<string,string> JsonDecode(string text)
{
return JsonConvert.DeserializeObject<Dictionary<string,string>>(text);
}
/// <summary>
/// Event handler that is fired when an access token has been retreived.
/// </summary>
/// <param name='accountProperties'>
/// The retrieved account properties
/// </param>
protected virtual void OnRetrievedAccountProperties(IDictionary<string, string> accountProperties)
{
//
// Now we just need a username for the account
//
if (getUsernameAsync != null)
{
getUsernameAsync(accountProperties).ContinueWith(task =>
{
if (task.IsFaulted)
{
OnError(task.Exception);
}
else
{
OnSucceeded(task.Result, accountProperties);
}
}, TaskScheduler.FromCurrentSynchronizationContext());
}
else
{
OnSucceeded("", accountProperties);
}
}
private void OnSucceeded(string v, IDictionary<string, string> accountProperties)
{
throw new NotImplementedException();
}
}
}

View File

@ -12,7 +12,7 @@ namespace Yavsc.Abstract.Helpers
public bool Done { get; set; } = false;
public ErrorCode ErrorCode { get; set; }
public string ErrorMessage { get; set; }
public string? ErrorMessage { get; set; }
}
}

View File

@ -58,7 +58,7 @@ public static class Config
ClientName = "Client Credentials Client",
ClientSecrets = { new Secret("511536EF-F270-4058-80CA-1C89C192F69A".Sha256()) },
AllowedGrantTypes = GrantTypes.ClientCredentials,
AllowedGrantTypes = GrantTypes.ResourceOwnerPasswordAndClientCredentials,
AllowedScopes = { "scope1" }
},

View File

@ -19,5 +19,10 @@ namespace Yavsc.Server.Helpers
return user.Identity.IsAuthenticated;
}
public static bool IsInMsRole(this ClaimsPrincipal user, string roleName)
{
return user.HasClaim("http://schemas.microsoft.com/ws/2008/06/identity/claims/role", roleName);
}
}
}

View File

@ -86,7 +86,7 @@ namespace Yavsc
var userId = _dbContext.Users.First(u => u.UserName == Context.User.Identity.Name).Id;
await Clients.Group(ChatHubConstants.HubGroupFollowingPrefix + userId).SendAsync("notifyUser", NotificationTypes.Connected, userName, null);
isCop = Context.User.IsInRole(Constants.AdminGroupName) ;
isCop = Context.User.IsInMsRole(Constants.AdminGroupName) ;
if (isCop)
{
await Groups.AddToGroupAsync(Context.ConnectionId, ChatHubConstants.HubGroupCops);
@ -353,7 +353,7 @@ namespace Yavsc
var identityUserName = Context.User.GetUserName();
if (userName[0] != '?' && Context.User!=null)
if (!Context.User.IsInRole(Constants.AdminGroupName))
if (!Context.User.IsInMsRole(Constants.AdminGroupName))
{
var bl = _dbContext.BlackListed

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,44 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Yavsc.Migrations
{
/// <inheritdoc />
public partial class test : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropPrimaryKey(
name: "PK_Applications",
table: "Applications");
migrationBuilder.RenameTable(
name: "Applications",
newName: "Client");
migrationBuilder.AddPrimaryKey(
name: "PK_Client",
table: "Client",
column: "Id");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropPrimaryKey(
name: "PK_Client",
table: "Client");
migrationBuilder.RenameTable(
name: "Client",
newName: "Applications");
migrationBuilder.AddPrimaryKey(
name: "PK_Applications",
table: "Applications",
column: "Id");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,40 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Yavsc.Migrations
{
/// <inheritdoc />
public partial class nullReturnUrl : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "LogoutRedirectUri",
table: "Client",
type: "character varying(512)",
maxLength: 512,
nullable: true,
oldClrType: typeof(string),
oldType: "character varying(512)",
oldMaxLength: 512);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "LogoutRedirectUri",
table: "Client",
type: "character varying(512)",
maxLength: 512,
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "character varying(512)",
oldMaxLength: 512,
oldNullable: true);
}
}
}

View File

@ -447,7 +447,6 @@ namespace Yavsc.Migrations
.HasColumnType("character varying(128)");
b.Property<string>("LogoutRedirectUri")
.IsRequired()
.HasMaxLength(512)
.HasColumnType("character varying(512)");
@ -468,7 +467,7 @@ namespace Yavsc.Migrations
b.HasKey("Id");
b.ToTable("Applications");
b.ToTable("Client");
});
modelBuilder.Entity("Yavsc.Models.Auth.Scope", b =>

View File

@ -17,7 +17,7 @@ namespace Yavsc.Models.Auth
[MaxLength(512)]
public string LogoutRedirectUri { get; set; }
public string? LogoutRedirectUri { get; set; }
[MaxLength(512)]
public string Secret { get; set; }
public ApplicationTypes Type { get; set; }

View File

@ -86,6 +86,11 @@ namespace Yavsc.Services
return msg.MessageId;
}
public void SendEmailFromCriteria(string Criteria)
{
throw new NotImplementedException();
}
public async Task SendPasswordResetCodeAsync(ApplicationUser user, string email, string resetCode)
{
var callbackUrl = siteSettings.Audience + "/Account/ResetPassword/" +

View File

@ -1,169 +0,0 @@
\dt
select user,password from users;
select user,passwd from users;
select user from users;
select username,pwd from users;
select username,passwd from users;
select username,password from users;
\dT users
\d users
select username,passwd from users;
select username,passd from users;
\d users
select username,passw from users;
\d profiledata
select gregid from profiledata;
select uniqueid,gregid from profiledata;
select uniqueid,username from profile;
select uniqueid,username from profiles;
select uniqueid,gregid from profiledata;
select uniqueid,username from profiles;
select uniqueid,gregid from profiledata;
select uniqueid,gregid from profiledata;
select uniqueid,gregid from profiledata;
select uniqueid,gregid from profiledata;
select uniqueid,gregid from profiledata;
drop table GitRepositoryReference;
\use YavscDev
\use
\?
\use \?
\dt
drop table "GitRepositoryReference";
drop table "GitRepositoryReference" CASCADE;
exit;
\q
delete from "Project"
;
\q
create database dotnetmvc
;
create user dotnetmvc ;
grant CREATE on paul;
grant admins TO paul;
grant CREATE TO paul;
grant postgres TO paul;
grant paul TO postgres;
commit;
CREATE ROLE baget nocreatedb nocreaterole noreplication;
CREATE ROLE baget nocreatedb nocreaterole noreplication;
CREATE ROLE baget nocreatedb nocreaterole noreplication;
DROP ROLE baget;
commit;
alter role baget with superuser
;
commit;
\dT Project
\dt Project
\dt "Project"
desc "Project"
\?
\d "Project"
\d BlogSpot
\d Blogspot
\d "Blogspot"
\d "BlogSpot"
\d "BlogPost"
\d "BlogPost"
\d "BlogPost"
\d "BlogPost"
\d "BlogPost"
\d AspNetUsers
\d "AspNetUsers"
\dT "AspNetUsers"
update "AspNetUsers" set "LockoutEnable" = false;
\d "AspNetUsers"
\d "AspNetUsers"
update "AspNetUsers" set "LockoutEnabled" = false;
commit ;
\quit
update "AspNetUsers" set "LockoutEnabled" = true;
\s
\d
\dT
\?
\dn
\?
\?
\conninfo
\h create database
\h create user
create user forgejo with login 'ogVZ)f#m85zx';
create user forgejo with login;
\h alter user
alter user forgejo with PASSWORD 'ogVZ)f#m85zx';
commit:
commit;
commit;
\h create databse
\h create databse
create database forgejo with owner forgejo;
create user woodpecker with password 'aormb%$98zv<U&@' ;'
\sd
\?d
\dd
\dT
\dt
\d
\dd
\?
\dS
\?
\dD
\?
\dg
\?
\dn
\?
\l
\dl
\l
\dg
create database woodpecker with OWNER 'woodpecker';
select count(*) from "Users"
;
select count(*) from "AspNetUsers";
desc "AspNetUsers";
\dT "AspNetUsers"
\d "AspNetUsers"
update "AspNetUsers" set "EmailConfirmed" = true;
commit
;
select "UserName" from "AspNetUsers" ;
desc "AspNetUsers"
\d "AspNetUsers"
select "UserName", "Email" from "AspNetUsers" ;
select "UserName", "Email" from "AspNetUsers" ;
\d "AspNetUsers"
select "Id", "UserName", "Email" from "AspNetUsers" ;
\d "AspNetUsers"
select "Id", "UserName", "Email", "ConfirmedEmail" from "AspNetUsers" ;
\d "AspNetUsers"
select "Id", "UserName", "Email", "EmailConfirmed" from "AspNetUsers" ;
select * from "AspNetUsers" ;
\d "AspNetUsers"
select "Id", "UserName", "Email", "EmailConfirmed", "LockoutEnabe" from "AspNetUsers" ;
\d "AspNetUsers"
select "Id", "UserName", "Email", "EmailConfirmed", "LockoutEnabled" from "AspNetUsers" ;
upate AspNetUsers set LockoutEnabled = false;
update AspNetUsers set LockoutEnabled = false;
update "AspNetUsers" set "LockoutEnabled" = false;
commit;
select "Id", "UserName", "Email", "EmailConfirmed", "LockoutEnabled" from "AspNetUsers" ;
SELECT a."Id", a."AccessFailedCount", a."AllowMonthlyEmail", a."Avatar", a."BankInfoId", a."ConcurrencyStamp", a."DedicatedGoogleCalendar", a."DiskQuota", a."DiskUsage", a."Email", a."EmailConfirmed", a."FullName", a."LockoutEnabled", a."LockoutEnd", a."MaxFileSize", a."NormalizedEmail", a."NormalizedUserName", a."PasswordHash", a."PhoneNumber", a."PhoneNumberConfirmed", a."PostalAddressId", a."SecurityStamp", a."TwoFactorEnabled", a."UserName"
FROM "AspNetUsers" AS a
WHERE a."Email" = 'paul@pschneider.fr';
update "AspNetUsers" set "UserName" = 'Paul' where "Email" = 'paul@pschneider.fr';
update "AspNetUsers" set "UserName" = 'PaulS' where "Email" = 'contact@pschneider.fr';
update "AspNetUsers" set "UserName" = 'PaulSc' where "Email" = 'redienhcs.luap@gmail.com';
delete from Users where "userName" = 'pa'
;
delete from "Users" where "UserName" = 'pa';
delete from "AspNetUsers" where "UserName" = 'pa';
select "Id", "UserName", "Email", "EmailConfirmed", "LockoutEnabled" from "AspNetUsers" ;
\dT
\d
alter table "Activity" rename to "Activities";
\d
alter table "BlogPost" rename to "BlogSpot";
\s "BlogSpot"

View File

@ -625,7 +625,7 @@ namespace Yavsc.Controllers
else _dbContext.Performers.Add(model);
_dbContext.SaveChanges(User.GetUserId());
// Give this user the Performer role
if (!User.IsInRole("Performer"))
if (!User.IsInMsRole("Performer"))
await _userManager.AddToRoleAsync(user, "Performer");
var message = ManageMessageId.SetActivitySuccess;

View File

@ -68,7 +68,7 @@ namespace Yavsc.Controllers
if (admins != null && admins.Count > 0)
{
// All is ok, nothing to do here.
if (User.IsInRole(Constants.AdminGroupName))
if (User.IsInMsRole(Constants.AdminGroupName))
{
return Ok(new { message = "you already got it." });

View File

@ -8,6 +8,7 @@ using Microsoft.Extensions.Localization;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using Yavsc.Server.Helpers;
namespace Yavsc.Controllers
{
@ -58,8 +59,8 @@ namespace Yavsc.Controllers
}
private async Task SetupView(Announce announce)
{
ViewBag.IsAdmin = User.IsInRole(Constants.AdminGroupName);
ViewBag.IsPerformer = User.IsInRole(Constants.PerformerGroupName);
ViewBag.IsAdmin = User.IsInMsRole(Constants.AdminGroupName);
ViewBag.IsPerformer = User.IsInMsRole(Constants.PerformerGroupName);
ViewBag.AllowEdit = announce==null || announce.Id<=0 || !_authorizationService.AuthorizeAsync(User,announce,new EditPermission()).IsFaulted;
List<SelectListItem> dl = new List<SelectListItem>();
var rnames = System.Enum.GetNames(typeof(Reason));
@ -78,7 +79,6 @@ namespace Yavsc.Controllers
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(Announce announce)
{
await SetupView(announce);
if (ModelState.IsValid)
{
// Only allow admin to create corporate annonces
@ -99,6 +99,7 @@ namespace Yavsc.Controllers
await _context.SaveChangesAsync();
return RedirectToAction("Index");
}
await SetupView(announce);
return View(announce);
}

View File

@ -74,7 +74,7 @@ namespace Yavsc.Controllers
{
var blog = await blogSpotService.Details(User, id.Value);
ViewData["apicmtctlr"] = "/api/blogcomments";
ViewData["moderatoFlag"] = User.IsInRole(Constants.BlogModeratorGroupName);
ViewData["moderatoFlag"] = User.IsInMsRole(Constants.BlogModeratorGroupName);
return View(blog);

View File

@ -90,7 +90,7 @@ namespace Yavsc.Controllers
public IActionResult Create(UserActivity userActivity)
{
var uid = User.FindFirstValue(ClaimTypes.NameIdentifier);
if (!User.IsInRole("Administrator"))
if (!User.IsInMsRole("Administrator"))
if (uid != userActivity.UserId)
ModelState.AddModelError("User","You're not admin.");
if (userActivity.UserId == null) userActivity.UserId = uid;
@ -133,7 +133,7 @@ namespace Yavsc.Controllers
[ValidateAntiForgeryToken]
public IActionResult Edit(UserActivity userActivity)
{
if (!User.IsInRole("Administrator"))
if (!User.IsInMsRole("Administrator"))
if (User.GetUserId() != userActivity.UserId)
ModelState.AddModelError("User","You're not admin.");
if (ModelState.IsValid)
@ -162,7 +162,7 @@ namespace Yavsc.Controllers
{
return NotFound();
}
if (!User.IsInRole("Administrator"))
if (!User.IsInMsRole("Administrator"))
if (User.GetUserId() != userActivity.UserId)
ModelState.AddModelError("User","You're not admin.");
return View(userActivity);
@ -175,7 +175,7 @@ namespace Yavsc.Controllers
{
if (!ModelState.IsValid)
return new BadRequestObjectResult(ModelState);
if (!User.IsInRole("Administrator"))
if (!User.IsInMsRole("Administrator"))
if (User.GetUserId() != userActivity.UserId) {
ModelState.AddModelError("User","You're not admin.");
return RedirectToAction("Index");

View File

@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using Yavsc.Models;
using Yavsc.Models.Musical;
using Yavsc.Server.Helpers;
namespace Yavsc.Controllers
{
@ -60,7 +61,7 @@ namespace Yavsc.Controllers
ViewBag.YetAvailableInstruments = _context.Instrument.Select(k=>new SelectListItem
{ Text = k.Name, Value = k.Id.ToString(), Disabled = actual.Contains(k.Id) });
if (User.IsInRole("Administrator"))
if (User.IsInMsRole("Administrator"))
ViewBag.OwnerIds = new SelectList(_context.Performers, "PerformerId", "Profile");
return View();
}

View File

@ -64,7 +64,7 @@ namespace Yavsc.Controllers
var uid = User.FindFirstValue(ClaimTypes.NameIdentifier);
if (ModelState.IsValid)
{
if (model.UserId != uid) if (!User.IsInRole(Constants.AdminGroupName))
if (model.UserId != uid) if (!User.IsInMsRole(Constants.AdminGroupName))
return new ChallengeResult();
_context.Instrumentation.Add(model);
@ -82,7 +82,7 @@ namespace Yavsc.Controllers
{
return NotFound();
}
if (id != uid) if (!User.IsInRole(Constants.AdminGroupName))
if (id != uid) if (!User.IsInMsRole(Constants.AdminGroupName))
return new ChallengeResult();
Instrumentation musicianSettings = await _context.Instrumentation.SingleAsync(m => m.UserId == id);
if (musicianSettings == null)
@ -98,7 +98,7 @@ namespace Yavsc.Controllers
public async Task<IActionResult> Edit(Instrumentation musicianSettings)
{
var uid = User.FindFirstValue(ClaimTypes.NameIdentifier);
if (musicianSettings.UserId != uid) if (!User.IsInRole(Constants.AdminGroupName))
if (musicianSettings.UserId != uid) if (!User.IsInMsRole(Constants.AdminGroupName))
return new ChallengeResult();
if (ModelState.IsValid)
{
@ -124,7 +124,7 @@ namespace Yavsc.Controllers
return NotFound();
}
var uid = User.FindFirstValue(ClaimTypes.NameIdentifier);
if (musicianSettings.UserId != uid) if (!User.IsInRole(Constants.AdminGroupName))
if (musicianSettings.UserId != uid) if (!User.IsInMsRole(Constants.AdminGroupName))
return new ChallengeResult();
return View(musicianSettings);
}
@ -137,7 +137,7 @@ namespace Yavsc.Controllers
Instrumentation musicianSettings = await _context.Instrumentation.SingleAsync(m => m.UserId == id);
var uid = User.FindFirstValue(ClaimTypes.NameIdentifier);
if (musicianSettings.UserId != uid) if (!User.IsInRole(Constants.AdminGroupName))
if (musicianSettings.UserId != uid) if (!User.IsInMsRole(Constants.AdminGroupName))
return new ChallengeResult();

View File

@ -27,6 +27,7 @@ using Microsoft.IdentityModel.Tokens;
using Microsoft.IdentityModel.Protocols.Configuration;
using IdentityModel;
using Yavsc.Interfaces;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
namespace Yavsc.Extensions;
@ -48,8 +49,9 @@ public static class HostingExtensions
_ = services.AddSingleton<IConnexionManager, HubConnectionManager>();
_ = services.AddSingleton<ILiveProcessor, LiveProcessor>();
_ = services.AddTransient<IFileSystemAuthManager, FileSystemAuthManager>();
AddIdentityDBAndStores(builder).AddDefaultTokenProviders();
AddIdentityDBAndStores(builder)
.AddDefaultTokenProviders();
AddIdentityServer(builder);
services.AddSignalR(o =>
@ -107,7 +109,9 @@ public static class HostingExtensions
AddAuthentication(builder);
// accepts any access token issued by identity server
services.AddTransient<RoleManager<IdentityRole>>();
services.AddTransient<IRoleStore<IdentityRole>, RoleStore<IdentityRole, ApplicationDbContext>>();
return builder.Build();
}
@ -118,13 +122,15 @@ public static class HostingExtensions
services.AddDbContext<ApplicationDbContext>(options =>
options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection")));
return services.AddIdentity<ApplicationUser, IdentityRole>(
return services.AddIdentity<ApplicationUser,IdentityRole>(
options =>
{
options.SignIn.RequireConfirmedAccount = true;
options.ClaimsIdentity.UserNameClaimType = JwtClaimTypes.PreferredUserName;
options.ClaimsIdentity.RoleClaimType = JwtClaimTypes.Role;
}
)
.AddEntityFrameworkStores<ApplicationDbContext>();
.AddEntityFrameworkStores<ApplicationDbContext>();
}
@ -226,13 +232,16 @@ public static class HostingExtensions
// see https://IdentityServer8.readthedocs.io/en/latest/topics/resources.html
options.EmitStaticAudienceClaim = true;
})
.AddInMemoryIdentityResources(Config.IdentityResources)
.AddInMemoryClients(Config.TestingClients)
.AddClientStore<ClientStore>()
.AddInMemoryApiScopes(Config.TestingApiScopes)
.AddAspNetIdentity<ApplicationUser>()
;
.AddAspNetIdentity<ApplicationUser>();
if (builder.Environment.IsDevelopment())
{
identityServerBuilder.AddDeveloperSigningCredential();

View File

@ -35,7 +35,7 @@ public class PermissionHandler : IAuthorizationHandler
{
context.Succeed(requirement);
}
else if (context.User.IsInRole("Administrator"))
else if (context.User.IsInMsRole("Administrator"))
{
context.Succeed(requirement);
}

View File

@ -16,8 +16,8 @@ public class ClientStore : IClientStore
public async Task<Client> FindClientByIdAsync(string clientId)
{
var clientFromDb = await ApplicationDbContext.Client.FirstAsync(c => c.Id == clientId);
var clientFromDb = await ApplicationDbContext.Client.FirstOrDefaultAsync(c => c.Id == clientId);
if (clientFromDb == null) return null;
return new Client
{
ClientId = clientFromDb.Id,

View File

@ -10,7 +10,7 @@
<div class="form-horizontal">
<h4>Announce</h4>
<hr />
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="For" class="col-md-2 control-label"></label>

View File

@ -14,13 +14,14 @@
<li><a class="dropdown-item" asp-controller="Feature" asp-action="Index">Features</a></li>
</ul>
</li>
@if (User.IsInRole(Constants.AdminGroupName)) {
@if (User.IsInMsRole(Constants.AdminGroupName)) {
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="dropdown05" data-bs-toggle="dropdown" aria-expanded="false">
Administration
</a>
<ul class="dropdown-menu" aria-labelledby="dropdown05">
<li><a class="dropdown-item" asp-controller="Administration" asp-action="Index">Index</a></li>
<li><a class="dropdown-item" asp-controller="Announces" asp-action="Index">Announces</a></li>
<li><a class="dropdown-item" asp-controller="Activity" asp-action="Index">Activités</a></li>
<li><a class="dropdown-item" asp-controller="CommandForms" asp-action="Index">Formulaires</a></li>
<li><a class="dropdown-item" asp-controller="Notifications" asp-action="Index">Notifications</a></li>

View File

@ -9,7 +9,6 @@
<ul class="navbar-nav me-auto" >
<li class="nav-item"><a class="nav-link active" aria-current="page" href="/">Home</a></li>
<li class="nav-item"><a asp-controller="Blogspot" asp-action="Index" class="nav-link">@SR["Blogs"]</a></li>
<li class="nav-item"><a asp-controller="Home" asp-action="Chat" class="nav-link">@SR["Chat"]</a></li>
<li class="nav-item"><a asp-controller="Home" asp-action="Contact" class="nav-link">@SR["Contact"]</a></li>
<li class="nav-item"><a asp-controller="Home" asp-action="About" class="nav-link">@SR["About"]</a></li>
<partial name="_LoginPartial" />

View File

@ -1,11 +1,9 @@
using System;
using System.Collections.Generic;
using System.Text;
using cli.Model;
using Microsoft.Extensions.CommandLineUtils;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Yavsc.Authentication;
namespace cli.Commands
{
@ -42,10 +40,10 @@ namespace cli.Commands
});
loginCommand.OnExecute(async () =>
{
string authUrl = Startup.ConnectionSettings.AuthorizeUrl;
string redirect = Startup.ConnectionSettings.RedirectUrl;
string tokenUrl = Startup.ConnectionSettings.AccessTokenUrl;
string? authUrl = Program.AppConfiguration.GetValue<String>("ConnectionSettings:ServerApi:Authority");
throw new NotImplementedException();
/*
OAuthenticator oauthor = new OAuthenticator(_apiKey.HasValue() ? _apiKey.Value() : Startup.ConnectionSettings.ClientId,
_secret.HasValue() ? _secret.Value() : Startup.ConnectionSettings.ClientSecret,
_scope.HasValue() ? _scope.Value() : Startup.ConnectionSettings.Scope,
@ -72,11 +70,11 @@ namespace cli.Commands
_logger.LogError(ex.Message);
}
return 0;
return 0; */
});
}, false);
return authApp;
return authApp;
}
public static string GetPassword(string userName)

View File

@ -1,61 +0,0 @@
using Microsoft.Extensions.CommandLineUtils;
using System.Threading.Tasks;
using NJsonSchema;
using System.IO;
using cli.Model;
using Yavsc.Abstract.IT;
namespace cli
{
public class GenerateJsonSchema : ICommander
{
public CommandLineApplication Integrate(CommandLineApplication rootApp)
{
CommandArgument genargclass = null;
CommandArgument genargjson = null;
CommandOption genopthelp = null;
var cmd = rootApp.Command("gen",
(target) =>
{
target.FullName = "Generete";
target.Description = "generates some objects ...";
genopthelp = target.HelpOption("-? | -h | --help");
genargclass = target.Argument(
"class",
"class name of generation to execute (actually, only 'jsonSchema') .",
multipleValues: false);
genargjson = target.Argument(
"json",
"Json file generated",
multipleValues: false);
}, false);
cmd.OnExecute(
() => {
if (genargclass.Value == "jsonSchema") {
GenerateCiBuildSettingsSchema(genargjson.Value);
} else {
cmd.ShowHint();
return 1;
}
return 0;
}
);
return cmd;
}
public static void GenerateCiBuildSettingsSchema(string outputFileName = "pauls-ci-schema.json")
{
var schema = JsonSchema.FromType(typeof(CiBuildSettings));
var schemaData = schema.ToJson();
FileInfo ofi = new FileInfo(outputFileName);
var ostream = ofi.OpenWrite();
var owritter = new StreamWriter(ostream);
owritter.WriteLine(schemaData);
owritter.Close();
ostream.Close();
}
}
}

View File

@ -1,11 +1,11 @@
using Microsoft.Extensions.CommandLineUtils;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.OptionsModel;
using cli.Model;
using cli.Services;
using cli.Settings;
using Microsoft.Extensions.CommandLineUtils;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace cli.Commands
{
@ -34,18 +34,13 @@ namespace cli.Commands
config.HelpOption("-? | -h | --help");
});
cmd.OnExecute(() => {
var host = new WebHostBuilder();
var hostEngine = host.UseEnvironment("Development")
.UseServer("cli")
.UseStartup<Startup>()
.Build();
var app = hostEngine.Start();
var mailer = app.Services.GetService<MvcGenerator>();
var loggerFactory = app.Services.GetService<ILoggerFactory>();
var mailer = Program.AppHost.Services.GetService<MvcGenerator>();
var loggerFactory = Program.AppHost.Services.GetService<ILoggerFactory>();
var logger = loggerFactory.CreateLogger<GenerationCommander>();
var options = app.Services.GetService<IOptions<GenMvcSettings>>();
var options = Program.AppHost.Services.GetService<IOptions<GenMvcSettings>>();
MvcGenerator generator = app.Services.GetService<MvcGenerator>();
MvcGenerator generator = Program.AppHost.Services.GetService<MvcGenerator>();
var modelFullName = mdClass?.Value ?? options?.Value.ModelFullName;
var nameSpace = nameSpaceArg?.Value?? options?.Value.NameSpace;

View File

@ -1,26 +1,21 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.CommandLineUtils;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using cli.Services;
using cli.Model;
using Yavsc.Server.Settings;
using Microsoft.Extensions.CommandLineUtils;
using Microsoft.Extensions.Logging;
using Yavsc.Services;
namespace cli
{
public class SendMailCommandProvider : ICommander
{
EMailer emailer;
MailSender emailer;
private ILogger<SendMailCommandProvider> logger;
public SendMailCommandProvider(EMailer emailer, ILoggerFactory loggerFactory)
public SendMailCommandProvider(MailSender emailer, ILoggerFactory loggerFactory)
{
this.emailer = emailer;
this.logger = loggerFactory.CreateLogger<SendMailCommandProvider>();
}
public CommandLineApplication Integrate(CommandLineApplication rootApp)
{
CommandArgument critCommandArg = null;
CommandOption sendHelpOption = null;
CommandLineApplication sendMailCommandApp
= rootApp.Command("send-email",
@ -29,28 +24,16 @@ namespace cli
target.FullName = "Send email";
target.Description = "Sends emails using given template from code";
sendHelpOption = target.HelpOption("-? | -h | --help");
critCommandArg = target.Argument(
"criteria",
"user selection criteria : 'allow-monthly' or 'email-not-confirmed'");
}, false);
sendMailCommandApp.OnExecute(() =>
{
bool showhelp = !UserPolicies.Criterias.ContainsKey(critCommandArg.Value)
|| sendHelpOption.HasValue();
bool showhelp = sendHelpOption.HasValue();
if (!showhelp)
{
var host = new WebHostBuilder();
var hostengnine = host.UseEnvironment(Program.HostingEnvironment.EnvironmentName)
.UseServer("cli")
.UseStartup<Startup>()
.Build();
logger.LogInformation("Starting emailling");
emailer.SendEmailFromCriteria(critCommandArg.Value);
emailer.SendEmailFromCriteria("allow-monthly");
logger.LogInformation("Finished emailling");
}
else

View File

@ -1,13 +1,9 @@
using System;
using System.IO;
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using cli.Model;
using Microsoft.Extensions.CommandLineUtils;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.OptionsModel;
using Microsoft.Extensions.Options;
namespace cli {

View File

@ -3,12 +3,10 @@ using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.CommandLineUtils;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using cli.Services;
using Yavsc.Server.Settings;
using Yavsc.Models;
using Microsoft.AspNetCore.Identity;
using System.Linq;
using System;
using Yavsc.Services;
namespace cli.Commands
{
@ -32,19 +30,13 @@ namespace cli.Commands
if (!showhelp)
{
var host = new WebHostBuilder();
var hostengnine = host.UseEnvironment(Program.HostingEnvironment.EnvironmentName)
.UseServer("cli")
.UseStartup<Startup>()
.Build();
var app = hostengnine.Start();
var mailer = app.Services.GetService<EMailer>();
var loggerFactory = app.Services.GetService<ILoggerFactory>();
var mailer = Program.AppHost.Services.GetService<MailSender>();
var loggerFactory = Program.AppHost.Services.GetService<ILoggerFactory>();
var logger = loggerFactory.CreateLogger<Program>();
var userManager = app.Services.GetService<UserManager<ApplicationDbContext>>();
ApplicationDbContext dbContext = app.Services.GetService<ApplicationDbContext>();
var userManager = Program.AppHost.Services.GetService<UserManager<ApplicationUser>>();
ApplicationDbContext dbContext = Program.AppHost.Services.GetService<ApplicationDbContext>();
Func<ApplicationUser, bool> criteria = UserPolicies.Criterias["user-to-remove"];
if (userManager==null)
@ -54,12 +46,14 @@ namespace cli.Commands
}
logger.LogInformation("Starting emailling");
try {
try
{
mailer.SendEmailFromCriteria("user-to-remove");
}
catch (NoMaillingTemplateException ex)
catch (Exception ex)
{
logger.LogWarning(ex.Message);
throw;
}
ApplicationUser [] users = dbContext.ApplicationUser.Where(
u => criteria(u)).ToArray();

View File

@ -1,8 +1,6 @@
using System;
using System.Text;
using cli.Model;
using Microsoft.Extensions.CommandLineUtils;
using Yavsc.Authentication;
namespace cli.Helpers
{
@ -13,28 +11,6 @@ namespace cli.Helpers
return commander.Integrate(rootApp);
}
public static OAuthenticator OAuthorInstance { get; private set; }
public static OAuthenticator InitAuthor(
this ConnectionSettings settings)
{
return OAuthorInstance = new OAuthenticator(settings.ClientId,
settings.ClientSecret,
settings.Scope,
new Uri(settings.AuthorizeUrl), new Uri(settings.RedirectUrl), new Uri(settings.AccessTokenUrl));
}
/* TODO add OAut console client
public static async Task<IDictionary<string, string>> GetAuthFromPass(
string login,
string pass)
{
var query = new Dictionary<string, string>();
query[Parameters.Username] = login;
query[Parameters.Password] = pass;
query[Parameters.GrantType] = GrantTypes.Password;
return await OAuthorInstance.RequestAccessTokenAsync(query);
} */
public static string GetPassword()
{
var pwd = new StringBuilder();

View File

@ -1,2 +1,21 @@
// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");
using cli;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
internal class Program
{
public static IHost? AppHost { get; private set; }
public static IConfigurationRoot? AppConfiguration { get; private set; }
public static IHostEnvironment? AppEnvironment { get; private set; }
private static void Main(string[] args)
{
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
AppHost = builder.Build();
AppConfiguration = builder.Configuration;
AppHost.Start();
AppEnvironment = builder.Environment;
Console.WriteLine("Hello, World!");
}
}

View File

@ -1,136 +0,0 @@

using System;
using System.Runtime.Versioning;
using cli.Commands;
using Microsoft.Extensions.CommandLineUtils;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Yavsc;
namespace cli
{
public class CliAppEnv : IApplicationEnvironment
{
public CliAppEnv(IApplicationEnvironment defaultEnv)
{
var envAppVar = Environment.GetEnvironmentVariable("ASPNET_ENV");
Configuration = envAppVar ?? defaultEnv.Configuration;
ApplicationName = defaultEnv.ApplicationName;
ApplicationVersion = defaultEnv.ApplicationVersion;
ApplicationBasePath = defaultEnv.ApplicationBasePath;
RuntimeFramework = defaultEnv.RuntimeFramework;
}
public string ApplicationName { get; private set; }
public string ApplicationVersion { get; private set; }
public string ApplicationBasePath { get; private set; }
public string Configuration { get; private set; }
public FrameworkName RuntimeFramework { get; private set; }
public object GetData(string name)
{
throw new NotImplementedException();
}
public void SetData(string name, object value)
{
throw new NotImplementedException();
}
}
public partial class Program
{
private static IApplicationEnvironment appEnv;
public static IHostingEnvironment HostingEnvironment { get; private set; }
public Program()
{
appEnv = new CliAppEnv(PlatformServices.Default.Application);
}
/// <summary>
/// Initializes the application by
/// </summary>
private static ApplicationBuilder ConfigureApplication()
{
AppDomain.CurrentDomain.UnhandledException += OnUnHandledException;
var services = new ServiceCollection();
// create a service provider with the HostEnvironment.
HostingEnvironment = new HostingEnvironment
{
EnvironmentName = appEnv.Configuration
};
var startup = new Startup(HostingEnvironment, appEnv);
startup.ConfigureServices(services);
services.AddInstance<IHostingEnvironment>(HostingEnvironment);
var serviceProvider = services.BuildServiceProvider();
var app = new ApplicationBuilder(serviceProvider)
{
ApplicationServices = serviceProvider
};
var siteSettings = serviceProvider.GetRequiredService<IOptions<SiteSettings>>();
var cxSettings = serviceProvider.GetRequiredService<IOptions<ConnectionSettings>>();
var userCxSettings = serviceProvider.GetRequiredService<IOptions<UserConnectionSettings>>();
var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();
startup.Configure(cxSettings, userCxSettings, loggerFactory);
return app;
}
private static void OnUnHandledException(object sender, UnhandledExceptionEventArgs e)
{
Console.WriteLine("Unhandled Exception occured:");
Console.WriteLine(JsonConvert.SerializeObject(e.ExceptionObject));
}
[STAThread]
public static int Main(string[] args)
{
CommandLineApplication cliapp = new CommandLineApplication(false)
{
Name = "cli",
FullName = "Yavsc command line interface",
Description = "Dnx console app for yavsc server side",
ShortVersionGetter = () => "v1.0",
LongVersionGetter = () => "version 1.0 (stable)"
};
// calling a Startup sequence
var appBuilder = ConfigureApplication();
var loggerFactory = appBuilder.ApplicationServices.GetRequiredService<ILoggerFactory>();
var cxSettings = appBuilder.ApplicationServices.GetRequiredService<IOptions<ConnectionSettings>>();
var usercxSettings = appBuilder.ApplicationServices.GetRequiredService<IOptions<UserConnectionSettings>>();
var emailer = appBuilder.ApplicationServices.GetService<Emailer>();
CommandOption rootCommandHelpOption = cliapp.HelpOption("-? | -h | --help");
new SendMailCommandProvider().Integrate(cliapp);
new GenerateJsonSchema().Integrate(cliapp);
new AuthCommander(loggerFactory).Integrate(cliapp);
new GenerationCommander().Integrate(cliapp);
new Streamer(loggerFactory, cxSettings, usercxSettings ).Integrate(cliapp);
new UserListCleanUp().Integrate(cliapp);
if (args.Length == 0)
{
cliapp.ShowHint();
return -1;
}
var result = cliapp.Execute(args);
if (cliapp.RemainingArguments.Count > 0)
{
cliapp.ShowHint();
return -1;
}
return result;
}
}
}

View File

@ -1,63 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="MonthlySubjectTemplate"><value>[{0} Monthly] {1}</value></data>
</root>

View File

@ -1,6 +1,6 @@
using System;
using Microsoft.Extensions.CodeGenerators.Mvc.Controller;
using Microsoft.Extensions.Logging;
using Microsoft.VisualStudio.Web.CodeGenerators.Mvc.Controller;
namespace cli.Services
{

View File

@ -1,253 +0,0 @@
using Yavsc;
using cli.Services;
using cli.Settings;
using System.Runtime.Versioning;
using Newtonsoft.Json;
using Microsoft.Extensions.DependencyInjection;
namespace cli
{
public class Startup
{
public string ConnectionString
{
get; set;
}
public static ConnectionSettings ConnectionSettings { get; set; }
public static UserConnectionSettings UserConnectionSettings { get; set; }
public static string HostingFullName { get; private set; }
public static string EnvironmentName { get; private set; }
public static Microsoft.Extensions.Logging.ILogger Logger { get; private set; }
public Startup()
{
var devtag = env.IsDevelopment() ? "D" : "";
var prodtag = env.IsProduction() ? "P" : "";
var stagetag = env.IsStaging() ? "S" : "";
EnvironmentName = env.EnvironmentName;
HostingFullName = $"{appEnv.RuntimeFramework.FullName} [{env.EnvironmentName}:{prodtag}{devtag}{stagetag}]";
// Set up configuration sources.
UserConnectionsettingsFileName = $"connectionsettings.{env.EnvironmentName}.json";
var builder = new ConfigurationBuilder()
.AddEnvironmentVariables()
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddJsonFile(UserConnectionsettingsFileName, optional: true);
Configuration = builder.Build();
ConnectionString = Configuration["ConnectionStrings:Default"];
}
public static void SaveCredentials(string fileName, bool condensed=false) {
var cf = new FileInfo(fileName);
using (var writer = cf.OpenWrite())
{
using (var textWriter = new StreamWriter(writer))
{
var data = new { UserConnection = UserConnectionSettings, Connection = ConnectionSettings };
var json = JsonConvert.SerializeObject(data, condensed ? Formatting.None : Formatting.Indented);
textWriter.Write(json);
textWriter.Close();
}
writer.Close();
}
}
public static string UserConnectionsettingsFileName { get ; private set;}
const string userCxKey = "UserConnection";
public void ConfigureServices(IServiceCollection services)
{
services.AddOptions();
var cxSettings = Configuration.GetSection("Connection");
services.Configure<ConnectionSettings>(cxSettings);
var cxUserSettings = Configuration.GetSection(userCxKey);
services.Configure<UserConnectionSettings>(cxUserSettings);
var smtpSettingsconf = Configuration.GetSection("Smtp");
// TODO give it a look : Microsoft.Extensions.CodeGenerators.Mvc.View.ViewGeneratorTemplateModel v;
services.Configure<SmtpSettings>(smtpSettingsconf);
services.Configure<GenMvcSettings>(Configuration.GetSection("gen_mvc"));
services.AddInstance(typeof(ILoggerFactory), new LoggerFactory());
services.AddTransient(typeof(IEmailSender), typeof(MailSender));
services.AddTransient(typeof(RazorEngineHost),
svs => {
var settings = svs.GetService<GenMvcSettings>();
return new YaRazorEngineHost {
DefaultBaseClass = "Microsoft.Extensions.CodeGenerators.Mvc.View.ViewGeneratorTemplateModel",
DefaultClassName = settings.ControllerName,
DefaultNamespace = settings.NameSpace }; }
);
// Well ... I'll perhaps have, one day, enough trust to use it ...
services.AddTransient(typeof(MvcGenerator), typeof(MvcGenerator));
services.AddEntityFramework().AddNpgsql().AddDbContext<ApplicationDbContext>(
db => db.UseNpgsql(ConnectionString)
);
services.AddTransient((s) => new RazorTemplateEngine(s.GetService<RazorEngineHost>()));
services.AddTransient(typeof(IModelTypesLocator), typeof(ModelTypesLocator));
services.AddTransient(typeof(ILibraryExporter), typeof(RuntimeLibraryExporter));
services.AddLogging();
services.AddTransient<EMailer>();
services.AddLocalization(options =>
{
options.ResourcesPath = "Resources";
});
services.Configure<SharedAuthenticationOptions>(options =>
{
options.SignInScheme = "Bearer";
});
services.AddTransient<Microsoft.Extensions.WebEncoders.UrlEncoder, UrlEncoder>();
services.AddAuthentication("Bearer");
services.AddSingleton(typeof(IApplicationEnvironment), svs => PlatformServices.Default.Application);
services.AddSingleton(typeof(IRuntimeEnvironment), svs => PlatformServices.Default.Runtime);
services.AddSingleton(typeof(IAssemblyLoadContextAccessor), svs => PlatformServices.Default.AssemblyLoadContextAccessor);
services.AddSingleton(typeof(IAssemblyLoaderContainer), svs => PlatformServices.Default.AssemblyLoaderContainer);
services.AddSingleton(typeof(ILibraryManager), svs => PlatformServices.Default.LibraryManager);
services.AddSingleton<UserManager<ApplicationDbContext>>();
services.AddSingleton(typeof(BootstrapperContext),
svs => new BootstrapperContext
{
RuntimeDirectory = Path.GetDirectoryName(typeof(BootstrapperContext).Assembly.Location),
ApplicationBase = Configuration["gen_mvc:AppBase"],
// NOTE(anurse): Mono is always "dnx451" (for now).
TargetFramework = new FrameworkName("DNX", new Version(4, 5, 1)),
RuntimeType = "Mono"
}
);
services.AddTransient(typeof(CompilationEngine),
svs => {
var logger = svs.GetService<ILoggerFactory>().CreateLogger<Startup>();
var project = svs.GetService<Project>();
var env = new ApplicationEnvironment(project,
PlatformServices.Default.Application.RuntimeFramework,
PlatformServices.Default.Application.Configuration,
PlatformServices.Default.Application
);
logger.LogInformation("app name: "+env.ApplicationName);
return new CompilationEngine(
new CompilationEngineContext(PlatformServices.Default.Application,
PlatformServices.Default.Runtime,
PlatformServices.Default.AssemblyLoadContextAccessor.Default, new CompilationCache()));
});
services.AddTransient(typeof(IFrameworkReferenceResolver),
svs => new FrameworkReferenceResolver());
services.AddTransient(
typeof(Project), svs =>
{
Project project = null;
var diag = new List<DiagnosticMessage>();
var settings = svs.GetService<IOptions<GenMvcSettings>>();
if (Project.TryGetProject(settings.Value.AppBase, out project, diag))
{
return project;
}
return null;
}
);
services.AddTransient(
typeof(ILibraryExporter),
svs =>
{
var settings = svs.GetService<IOptions<GenMvcSettings>>();
var compilationEngine = svs.GetService<CompilationEngine>();
var bootstrappercontext = svs.GetService<BootstrapperContext>();
var project = svs.GetService<Project>();
if (settings == null)
throw new Exception("settings are missing to generate some server code (GenMvcSettings) ");
return
new RuntimeLibraryExporter(
() => compilationEngine.CreateProjectExporter
(project, bootstrappercontext.TargetFramework, settings.Value.ConfigurationName));
}
);
services.AddTransient(typeof(IEntityFrameworkService), typeof(EntityFrameworkServices));
services.AddTransient(typeof(IDbContextEditorServices), typeof(DbContextEditorServices));
services.AddTransient(typeof(IFilesLocator), typeof(FilesLocator));
services.AddTransient(typeof(
Microsoft.Extensions.CodeGeneration.Templating.ITemplating), typeof(
Microsoft.Extensions.CodeGeneration.Templating.RazorTemplating));
services.AddTransient(
typeof(Microsoft.Extensions.CodeGeneration.Templating.Compilation.ICompilationService),
typeof(Microsoft.Extensions.CodeGeneration.Templating.Compilation.RoslynCompilationService));
services.AddTransient(
typeof(
Microsoft.Extensions.CodeGeneration.ICodeGeneratorActionsService),
typeof(Microsoft.Extensions.CodeGeneration.CodeGeneratorActionsService));
services.AddTransient(typeof(Microsoft.Dnx.Compilation.ICompilerOptionsProvider),
svs =>
{
var bsContext = svs.GetService<BootstrapperContext>();
var compileEngine = svs.GetService<ICompilationEngine>();
var applicationHostContext = new ApplicationHostContext
{
ProjectDirectory = bsContext.ApplicationBase,
RuntimeIdentifiers = new string[] { "dnx451" },
TargetFramework = bsContext.TargetFramework
};
var libraries = ApplicationHostContext.GetRuntimeLibraries(applicationHostContext, throwOnInvalidLockFile: true);
var projects = libraries.Where(p => p.Type == LibraryTypes.Project)
.ToDictionary(p => p.Identity.Name, p => (ProjectDescription)p);
Logger.LogInformation($"Found {projects?.Count} projects");
return new CompilerOptionsProvider(projects);
});
services.AddMvc();
services.AddTransient(typeof(IPackageInstaller),typeof(PackageInstaller));
services.AddTransient(typeof(Microsoft.Extensions.CodeGeneration.ILogger),typeof(Microsoft.Extensions.CodeGeneration.ConsoleLogger));
services.AddIdentity<ApplicationUser, IdentityRole>(
option =>
{
option.User.RequireUniqueEmail = true;
option.SignIn.RequireConfirmedAccount = true;
}
).AddEntityFrameworkStores<ApplicationDbContext>();
Services = services;
}
public void Configure(
IOptions<ConnectionSettings> cxSettings,
IOptions<UserConnectionSettings> useCxSettings,
ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
Logger = loggerFactory.CreateLogger<Startup>();
var authConf = Configuration.GetSection("Authentication").GetSection("Yavsc");
var clientId = authConf.GetSection("ClientId").Value;
var clientSecret = authConf.GetSection("ClientSecret").Value;
ConnectionSettings = cxSettings?.Value ?? new ConnectionSettings();
UserConnectionSettings = useCxSettings?.Value ?? new UserConnectionSettings();
Logger.LogInformation($"Configuration ended, with hosting Full Name: {HostingFullName}");
}
}
}

View File

@ -1,7 +1,6 @@
{
"ConnectionSettings" : {
"Site": {
"Authority": "oauth.server-example.com",
"Title": "[Site title]",
"Slogan": "[Site Slogan]",
"Banner": "/images/[bannerAsset]",
@ -9,7 +8,8 @@
"FavIcon": "/favicon.ico",
"Icon": "/images/[Site Icon]"
},
"ServerApiKey": {
"ServerApi": {
"Authority": "oauth.server-example.com",
"ClientId": "[OAuth2NativeClientId]",
"ClientSecret": "[OAuth2ClientSecret]"
}

View File

@ -1,24 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Razor" Version="2.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Razor.Language" Version="6.0.36" />
<PackageReference Include="Microsoft.Extensions.CommandLineUtils" Version="1.1.1" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.3" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.3" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Razor" />
<PackageReference Include="Microsoft.AspNetCore.Razor.Language" />
<PackageReference Include="Microsoft.Extensions.CommandLineUtils" />
<PackageReference Include="Microsoft.Extensions.Configuration" />
<PackageReference Include="Newtonsoft.Json" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Yavsc.Abstract\Yavsc.Abstract.csproj" />
<ProjectReference Include="..\Yavsc.Server\Yavsc.Server.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,30 @@
using System;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
namespace SeleniumDocs.GettingStarted;
public static class FirstScript
{
public static void DoTestSeleniumWebSite()
{
IWebDriver driver = new ChromeDriver();
driver.Navigate().GoToUrl("https://www.selenium.dev/selenium/web/web-form.html");
var title = driver.Title;
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromMilliseconds(500);
var textBox = driver.FindElement(By.Name("my-text"));
var submitButton = driver.FindElement(By.TagName("button"));
textBox.SendKeys("Selenium");
submitButton.Click();
var message = driver.FindElement(By.Id("message"));
var value = message.Text;
driver.Quit();
}
}

View File

@ -1,28 +1,15 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using Xunit;
using Yavsc;
using Yavsc.Models;
using Yavsc.Services;
using System.Runtime.Versioning;
using System.Diagnostics;
using Yavsc.Helpers;
using Xunit.Abstractions;
using Yavsc.Server.Models.IT.SourceCode;
using yavscTests.Settings;
using Microsoft.EntityFrameworkCore;
using Microsoft.DotNet.Scaffolding.Shared.ProjectModel;
using Microsoft.AspNetCore.Identity;
using Yavsc.Settings;
using Microsoft.AspNetCore.Razor.Language;
using isnd.tests;
namespace yavscTests
{
[Collection("Yavsc mandatory success story")]
[Collection("Yavsc Server")]
[Trait("regression", "oui")]
public class BaseTestContext: IClassFixture<WebServerFixture>, IDisposable
{

View File

@ -1,16 +1,10 @@
// // YavscWorkInProgress.cs
// /*
// paul 21/06/2018 10:11 20182018 6 21
// */
using System.Net;
using isnd.tests;
using Xunit;
using isnd.tests;
using Xunit.Abstractions;
using Yavsc.Authentication;
using IdentityModel.Client;
namespace yavscTests
{
[Collection("Yavsc Work In Progress")]
[Collection("Yavsc Server")]
[Trait("regression", "oui")]
public class Remoting : BaseTestContext, IClassFixture<WebServerFixture>
{
@ -21,64 +15,79 @@ namespace yavscTests
}
[Theory]
[MemberData(nameof(GetLoginIntentData), parameters: 1)]
[MemberData(nameof(GetLoginIntentData))]
public async Task TestUserMayLogin
(
string userName,
string password
)
{
try
{
var serverUrl = _serverFixture.Addresses.FirstOrDefault();
String auth = _serverFixture.SiteSettings.Authority;
var oauthor = new OAuthenticator(_serverFixture.TestClientId, _serverFixture.TestClientSecret,
"profile",
new Uri(serverUrl), new Uri(serverUrl), new Uri(serverUrl+"/connect/token"));
var query = new Dictionary<string, string>
{
["Username"] = userName,
["Password"] = password,
["GrantType"] = "Password"
};
var result = await oauthor.RequestAccessTokenAsync(query);
Console.WriteLine(">> Got an output");
Console.WriteLine( "AccessToken " + result["AccessToken"]);
Console.WriteLine("TokenType " + result["TokenType"]);
Console.WriteLine("ExpiresIn " + result["ExpiresIn"]);
Console.WriteLine("RefreshToken : " + result["RefreshToken"]);
}
catch (Exception ex)
{
var webex = ex as WebException;
if (webex != null && webex.Status == (WebExceptionStatus)400)
{
if (_serverFixture?.TestingSetup?.ValidCreds.UserName == "lame-user")
{
Console.WriteLine("Bad pass joe!");
return;
}
}
throw;
}
}
public static IEnumerable<object[]> GetLoginIntentData(int countFakes = 0)
[Fact]
public async Task ObtainServiceToken()
{
if (countFakes == 0)
return new object[][] { new object[] { "testuser", "test" } };
var serverUrl = _serverFixture.Addresses.FirstOrDefault(
u => u.StartsWith("https:")
);
var fakUsers = new List<String[]>();
for (int i = 0; i < countFakes; i++)
String authority = _serverFixture.SiteSettings.Authority;
var client = new HttpClient();
var disco = await client.GetDiscoveryDocumentAsync(authority);
if (disco.IsError) throw new Exception(disco.Error);
var response = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
{
fakUsers.Add(new String[] { "fakeTester" + i, "pass" + i });
}
return fakUsers;
Address = disco.TokenEndpoint,
ClientId = "m2m.client", // _serverFixture.TestClientId,
ClientSecret = "511536EF-F270-4058-80CA-1C89C192F69A" //_serverFixture.TestClientSecret,
});
/*"mvc";
options.ClientSecret = "49C1A7E1-0C79-4A89-A3D6-A37998FB86B0";*/
if (response.IsError) throw new Exception(response.Error);
}
[Fact]
public async Task ObtainResourceOwnerPasswordToken()
{
var serverUrl = _serverFixture.Addresses.FirstOrDefault(
u => u.StartsWith("https:")
);
String authority = _serverFixture.SiteSettings.Authority;
var client = new HttpClient();
var disco = await client.GetDiscoveryDocumentAsync(authority);
if (disco.IsError) throw new Exception(disco.Error);
var response = await client.RequestPasswordTokenAsync(new PasswordTokenRequest
{
Address = disco.TokenEndpoint,
ClientId = "m2m.client",
ClientSecret = "511536EF-F270-4058-80CA-1C89C192F69A",
UserName = _serverFixture.TestingUserName,
Password = _serverFixture.TestingUserPassword,
Scope = "scope1",
Parameters =
{
{ "acr_values", "tenant:custom_account_store1 foo bar quux" }
}
});
if (response.IsError) throw new Exception(response.Error);
}
public static IEnumerable<object[]> GetLoginIntentData()
{
return new object[][] { new object[] { "testuser", "test" } };
}
}
}

View File

@ -1,8 +1,12 @@
using isnd.tests;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Xunit;
using Xunit.Abstractions;
using Yavsc.Abstract.Manage;
using Yavsc.Interface;
using Yavsc.Models;
namespace yavscTests
{
@ -25,12 +29,18 @@ namespace yavscTests
[Fact]
public void SendEMailSynchrone()
{
AssertAsync.CompletesIn(2, () =>
AssertAsync.CompletesIn(2, () =>
{
using IServiceScope scope = _serverFixture.Services.CreateScope();
ITrueEmailSender mailSender = scope.ServiceProvider.GetRequiredService<ITrueEmailSender>();
output.WriteLine("SendEMailSynchrone ...");
_serverFixture.MailSender.SendEmailAsync
(_serverFixture.SiteSettings.Owner.EMail, $"monthly email", "test boby monthly email").Wait();
mailSender.SendEmailAsync
(
_serverFixture.SiteSettings.Owner.Name,
_serverFixture.SiteSettings.Owner.EMail,
$"monthly email",
"test boby monthly email").Wait();
});
}

View File

@ -1,66 +0,0 @@
using System;
using Xunit;
using System.IO;
using System.Diagnostics;
namespace yavscTests
{
/// <summary>
/// Since node isn't any requirement by here,
/// It may regress
/// </summary>
[Trait("regression", "allways")]
public class NodeTests
{
void TestNodeJsForAnsitohtml ()
{
var procStart = new ProcessStartInfo("node", "node_modules/ansi-to-html/bin/ansi-to-html")
{
UseShellExecute = false,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true
};
var proc = Process.Start(procStart);
proc.StandardInput.WriteLine("\x001b[30mblack\x1b[37mwhite");
proc.StandardInput.Close();
while (!proc.StandardOutput.EndOfStream)
{
Console.Write(proc.StandardOutput.ReadToEnd());
}
}
void AnsiToHtml()
{
var procStart = new ProcessStartInfo("ls", "-l --color=always")
{
UseShellExecute = false,
RedirectStandardInput = false,
RedirectStandardOutput = true
};
var proc = Process.Start(procStart);
var encoded = GetStream(proc.StandardOutput);
var reader = new StreamReader(encoded);
var txt = reader.ReadToEnd();
Console.WriteLine(txt);
}
public static Stream GetStream(StreamReader reader)
{
var procStart = new ProcessStartInfo("node", "node_modules/ansi-to-html/bin/ansi-to-html");
procStart.UseShellExecute = false;
procStart.RedirectStandardInput = true;
procStart.RedirectStandardOutput = true;
procStart.RedirectStandardError = true;
var mem = new MemoryStream();
StreamWriter writer = new StreamWriter(mem);
var proc = Process.Start(procStart);
var text = reader.ReadToEnd();
proc.StandardInput.WriteLine(text);
proc.StandardInput.Close();
return proc.StandardOutput.BaseStream;
}
}
}

View File

@ -4,11 +4,15 @@ using System.Threading.Tasks;
namespace yavscTests {
public static class AssertAsync {
public static void CompletesIn(int timeout, Action action)
/// <summary>
/// Completes In
/// </summary>
/// <param name="timeoutFromSecond"></param>
/// <param name="action"></param>
public static void CompletesIn(int timeoutFromSecond, Action action)
{
var task = Task.Run(action);
var completedInTime = Task.WaitAll(new[] { task }, TimeSpan.FromSeconds(timeout));
var completedInTime = Task.WaitAll(new[] { task }, TimeSpan.FromSeconds(timeoutFromSecond));
if (task.Exception != null)
{
@ -22,7 +26,7 @@ namespace yavscTests {
if (!completedInTime)
{
throw new TimeoutException($"Task did not complete in {timeout} seconds.");
throw new TimeoutException($"Task did not complete in {timeoutFromSecond} seconds.");
}
}
}

View File

@ -18,6 +18,9 @@ using Yavsc.Extensions;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
using Yavsc.Models.Auth;
using Serilog;
using Serilog.Events;
using Serilog.Sinks.SystemConsole.Themes;
namespace isnd.tests
{
@ -37,11 +40,12 @@ namespace isnd.tests
public IServiceProvider Services { get; private set; }
public string TestingUserName { get; private set; }
public string TestingUserPassword { get; private set; }
public string ProtectedTestingApiKey { get; internal set; }
public ApplicationUser TestingUser { get; private set; }
public bool DbCreated { get; internal set; }
public SiteSettings SiteSettings { get => siteSettings; set => siteSettings = value; }
public MailSender MailSender { get; internal set; }
public TestingSetup? TestingSetup { get; internal set; }
public string TestClientSecret { get; private set; } = "TestClientSecret";
@ -55,11 +59,27 @@ namespace isnd.tests
if (app!=null)
app.StopAsync().Wait();
}
void ConfigureLogger() => Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.MinimumLevel.Override("Microsoft.Hosting.Lifetime", LogEventLevel.Information)
.MinimumLevel.Override("System", LogEventLevel.Warning)
.MinimumLevel.Override("Microsoft.AspNetCore.Authentication", LogEventLevel.Information)
.Enrich.FromLogContext()
// uncomment to write to Azure diagnostics stream
//.WriteTo.File(
// @"D:\home\LogFiles\Application\identityserver.txt",
// fileSizeLimitBytes: 1_000_000,
// rollOnFileSizeLimit: true,
// shared: true,
// flushToDiskInterval: TimeSpan.FromSeconds(1))
.WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", theme: AnsiConsoleTheme.Code)
.CreateLogger();
public async Task SetupHost()
{
var builder = WebApplication.CreateBuilder();
var builder = WebApplication.CreateBuilder();
ConfigureLogger();
Configuration = builder.Configuration
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true)
@ -99,9 +119,10 @@ namespace isnd.tests
dbContext.Database.Migrate();
TestingUserName = "Tester";
TestingUserPassword = "test";
TestClientId = "testClientId";
TestingUser = await dbContext.Users.FirstOrDefaultAsync(u => u.UserName == TestingUserName);
EnsureUser(TestingUserName);
EnsureUser(TestingUserName, TestingUserPassword);
// ensure a client
var testClient = await dbContext.Client.FirstOrDefaultAsync((c) => c.Id == TestClientId);
if (testClient == null)
@ -119,9 +140,18 @@ namespace isnd.tests
dbContext.Client.Add(testClient);
dbContext.SaveChanges();
}
else
{
testClient.DisplayName = "Testing Client";
testClient.Secret = TestClientSecret;
testClient.Active = true;
testClient.Type = ApplicationTypes.NativeConfidential;
testClient.AccessTokenLifetime = 900;
testClient.RefreshTokenLifeTime = 1500;
}
}
public void EnsureUser(string testingUserName)
public void EnsureUser(string testingUserName, string password)
{
if (TestingUser == null)
{
@ -137,7 +167,7 @@ namespace isnd.tests
EmailConfirmed = true
};
var result = userManager.CreateAsync(TestingUser,"test").Result;
var result = userManager.CreateAsync(TestingUser,password).Result;
Assert.True(result.Succeeded);

View File

@ -12,14 +12,16 @@
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="xunit" />
<PackageReference Include="xunit.runner.visualstudio" />
<PackageReference Include="IdentityModel.OidcClient" />
<PackageReference Include="Selenium.WebDriver" />
<PackageReference Include="Microsoft.AspNetCore.Hosting" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" />
<PackageReference Include="Microsoft.Extensions.Options" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" />
<PackageReference Include="Microsoft.Playwright" />
<PackageReference Include="Newtonsoft.Json" />
<PackageReference Include="xunit" />
<PackageReference Include="xunit.runner.visualstudio" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Yavsc\Yavsc.csproj" />
@ -29,4 +31,4 @@
<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>
</Project>
</Project>

View File

@ -1,4 +1,4 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
@ -26,6 +26,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution items", "Solution
Directory.Packages.props = Directory.Packages.props
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cli", "src\cli\cli.csproj", "{7311313C-1837-420D-9AB2-E743AF78592A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -59,6 +61,10 @@ Global
{D565C5C8-19A6-4134-A18B-FE71986FBA35}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D565C5C8-19A6-4134-A18B-FE71986FBA35}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D565C5C8-19A6-4134-A18B-FE71986FBA35}.Release|Any CPU.Build.0 = Release|Any CPU
{7311313C-1837-420D-9AB2-E743AF78592A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7311313C-1837-420D-9AB2-E743AF78592A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7311313C-1837-420D-9AB2-E743AF78592A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7311313C-1837-420D-9AB2-E743AF78592A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{5AFB6255-CF1B-4660-BB35-F24C8C75FECE} = {503DDD6B-BE10-4235-9EBD-E9B1FA6067DF}
@ -67,5 +73,6 @@ Global
{38AA74FE-3932-49C3-A382-338E7C861BB1} = {503DDD6B-BE10-4235-9EBD-E9B1FA6067DF}
{16CCC793-BF57-4E8B-9BB5-76283379BA3F} = {503DDD6B-BE10-4235-9EBD-E9B1FA6067DF}
{D565C5C8-19A6-4134-A18B-FE71986FBA35} = {27336229-4130-45CC-8284-7F3B54D16463}
{7311313C-1837-420D-9AB2-E743AF78592A} = {503DDD6B-BE10-4235-9EBD-E9B1FA6067DF}
EndGlobalSection
EndGlobal