build cli

This commit is contained in:
Paul Schneider
2025-07-16 00:47:50 +01:00
parent a9b809f5e5
commit 124f3092fb
34 changed files with 7154 additions and 1232 deletions

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; }
}
}

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,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>