diff --git a/.gitignore b/.gitignore index 73c5bf07..13fcca6a 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,5 @@ omnisharp.json /src/Yavsc/bower_components/ /src/Yavsc/AppData*/ /src/test/testingrepo/ +connectionsettings.Development.json +appsettings.Development.json diff --git a/src/Yavsc.Abstract/Authentication/OAuthenticator.cs b/src/Yavsc.Abstract/Authentication/OAuthenticator.cs index 069baaa3..613cdbcd 100644 --- a/src/Yavsc.Abstract/Authentication/OAuthenticator.cs +++ b/src/Yavsc.Abstract/Authentication/OAuthenticator.cs @@ -399,9 +399,11 @@ namespace Yavsc.Authentication 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); diff --git a/src/cli/Commands/AuthCommander.cs b/src/cli/Commands/AuthCommander.cs index 25db25be..0c2d7574 100644 --- a/src/cli/Commands/AuthCommander.cs +++ b/src/cli/Commands/AuthCommander.cs @@ -1,14 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Text; using cli.Model; using Microsoft.Extensions.CommandLineUtils; +using Microsoft.Extensions.Logging; +using Yavsc.Authentication; namespace cli.Commands { public class AuthCommander : ICommander { + private CommandArgument _login; + private CommandOption _apiKey; + private CommandOption _secret; + private CommandOption _scope; + private CommandOption _save; + + ILogger _logger; + + public AuthCommander(ILoggerFactory loggerFactory) + { + _logger = loggerFactory.CreateLogger(); + } + public CommandLineApplication Integrate(CommandLineApplication rootApp) { - CommandLineApplication authApp = rootApp.Command("auth", (target) => { @@ -16,16 +33,85 @@ namespace cli.Commands target.Description = "Login, save credentials and get authorized."; target.HelpOption("-? | -h | --help"); var loginCommand = target.Command("login", app => { - var loginarg = app.Argument("login", "login to use", true); - app.Option( "-s | --save", "Save authentication token to file", CommandOptionType.NoValue); + _login = app.Argument("login", "login to use", true); + _apiKey = app.Option("-a | --api", "API key to use against authorization server", CommandOptionType.SingleValue); + _secret = app.Option( "-e | --secret", "Secret phrase associated to API key", CommandOptionType.SingleValue); + _scope = app.Option( "-c | --scope", "invoked scope asking for a security token", CommandOptionType.SingleValue); + _save = app.Option( "-s | --save", "Save authentication token to given file", CommandOptionType.SingleValue); app.HelpOption("-? | -h | --help"); } ); - }, false); - authApp.OnExecute(()=> + loginCommand.OnExecute(async ()=> { + var authUrl = Startup.ConnectionSettings.AuthorizeUrl; + var redirect = Startup.ConnectionSettings.RedirectUrl; + var tokenUrl = Startup.ConnectionSettings.AccessTokenUrl; + + var oauthor = new OAuthenticator(_apiKey.HasValue() ? _apiKey.Value() : Startup.ConnectionSettings.ClientId, + _secret.HasValue() ? _secret.Value() : Startup.ConnectionSettings.ClientSecret, + _scope.HasValue() ? _scope.Value() : Startup.ConnectionSettings.Scope, + new Uri(authUrl), new Uri(redirect), new Uri(tokenUrl)); + var query = new Dictionary(); + query["username"] = _login.Value; + query["password"] = GetPassword(_login.Value); + query["grant_type"] = "password"; + try { + var result = await oauthor.RequestAccessTokenAsync(query); + Startup.UserConnectionSettings.AccessToken = result["access_token"]; + Startup.UserConnectionSettings.ExpiresIn = result["expires_in"]; + Startup.UserConnectionSettings.RefreshToken = result["refresh_token"]; + Startup.UserConnectionSettings.TokenType = result["token_type"]; + Startup.UserConnectionSettings.UserName = _login.Value; + Startup.SaveCredentials(_save.HasValue() ? _save.Value() : Startup.UserConnectionsettingsFileName); + + } + catch (Exception ex) + { + _logger.LogError(ex.Message); + } + return 0; }); + }, false); + return authApp; } + + public static string GetPassword(string userName) + { + var oldBack = Console.BackgroundColor; + var oldFore = Console.ForegroundColor; + Console.BackgroundColor = ConsoleColor.Red; + Console.ForegroundColor = ConsoleColor.White; + Console.Write($"{userName}'s password:"); + Console.BackgroundColor = oldBack; + Console.ForegroundColor = oldFore; + + var pwd = new StringBuilder(); + while (true) + { + var len = pwd.ToString().Length; + ConsoleKeyInfo i = Console.ReadKey(true); + if (i.Key == ConsoleKey.Enter) + { + break; + } + else if (i.Key == ConsoleKey.Backspace) + { + if (pwd.Length > 0) + { + pwd.Remove(len - 1, 1); + Console.Write("\b \b"); + } + } + else + { + pwd.Append(i.KeyChar); + Console.Write("*"); + } + } + Console.WriteLine(); + return pwd.ToString(); + } + } } \ No newline at end of file diff --git a/src/cli/Commands/Streamer.cs b/src/cli/Commands/Streamer.cs index 0e5eaf48..ed4f31ea 100644 --- a/src/cli/Commands/Streamer.cs +++ b/src/cli/Commands/Streamer.cs @@ -1,11 +1,25 @@ using System.Net.WebSockets; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.OptionsModel; -public class Streamer { - private ClientWebSocket _client; +namespace cli { + + public class Streamer { + private ClientWebSocket _client; + private ILogger _logger; + private ConnectionSettings _cxSettings; + private UserConnectionSettings _userCxSettings; - public Streamer(string token) - { - _client = new ClientWebSocket(); - _client.Options.SetRequestHeader("Authorization", $"Bearer {token}"); - } + public Streamer(ILoggerFactory loggerFactory, + IOptions cxSettings, + IOptions userCxSettings + ) + { + _logger = loggerFactory.CreateLogger(); + _cxSettings = cxSettings.Value; + _userCxSettings = userCxSettings.Value; + _client = new ClientWebSocket(); + _client.Options.SetRequestHeader("Authorization", $"Bearer {_userCxSettings.AccessToken}"); + } + } } \ No newline at end of file diff --git a/src/cli/Program.cs b/src/cli/Program.cs index e09c470f..ce43b13d 100644 --- a/src/cli/Program.cs +++ b/src/cli/Program.cs @@ -1,44 +1,132 @@  using System; +using System.Runtime.Versioning; using cli.Commands; +using Microsoft.AspNet.Builder.Internal; +using Microsoft.AspNet.Hosting; +using Microsoft.Dnx.Runtime; using Microsoft.Extensions.CommandLineUtils; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.OptionsModel; +using Microsoft.Extensions.PlatformAbstractions; +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 { - public static void Main(string[] args) + private static IApplicationEnvironment appEnv; + public static IHostingEnvironment HostingEnvironment { get; private set; } + + public Program() { - CommandOption rootCommandHelpOption = null; + appEnv = new CliAppEnv(PlatformServices.Default.Application); + } + /// + /// Initializes the application by + /// + private static ApplicationBuilder ConfigureApplication() + { + AppDomain.CurrentDomain.UnhandledException += OnUnHandledException; + + var services = new ServiceCollection(); + // create a service provider with the HostEnvironment. + HostingEnvironment = new HostingEnvironment(); + HostingEnvironment.EnvironmentName = appEnv.Configuration; + + var startup = new Startup(HostingEnvironment, appEnv); + startup.ConfigureServices(services); + services.AddInstance(HostingEnvironment); + var serviceProvider = services.BuildServiceProvider(); + + var app = new ApplicationBuilder(serviceProvider); + app.ApplicationServices = serviceProvider; + + var siteSettings = serviceProvider.GetRequiredService>(); + var cxSettings = serviceProvider.GetRequiredService>(); + var userCxSettings = serviceProvider.GetRequiredService>(); + var loggerFactory = serviceProvider.GetRequiredService(); + + startup.Configure(app, HostingEnvironment, siteSettings, 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); cliapp.Name = "cli"; cliapp.FullName = "Yavsc command line interface"; cliapp.Description = "Dnx console app for yavsc server side"; cliapp.ShortVersionGetter = () => "v1.0"; cliapp.LongVersionGetter = () => "version 1.0 (stable)"; - rootCommandHelpOption = cliapp.HelpOption("-? | -h | --help"); + + // calling a Startup sequence + var appBuilder = ConfigureApplication(); + var loggerFactory = appBuilder.ApplicationServices.GetRequiredService(); + + CommandOption rootCommandHelpOption = cliapp.HelpOption("-? | -h | --help"); (new SendMailCommandProvider()).Integrate(cliapp); (new GenerateJsonSchema()).Integrate(cliapp); - (new AuthCommander()).Integrate(cliapp); + (new AuthCommander(loggerFactory)).Integrate(cliapp); (new CiBuildCommand()).Integrate(cliapp); (new GenerationCommander()).Integrate(cliapp); if (args.Length == 0) { cliapp.ShowHint(); - Environment.Exit(1); + return -1; } - - cliapp.Execute(args); + var result = cliapp.Execute(args); if (cliapp.RemainingArguments.Count > 0) { cliapp.ShowHint(); - Environment.Exit(2); + return -1; } - + return result; } } } diff --git a/src/cli/Startup.cs b/src/cli/Startup.cs index fbe6dd47..94459ce6 100644 --- a/src/cli/Startup.cs +++ b/src/cli/Startup.cs @@ -26,6 +26,7 @@ using System; using System.Collections.Generic; using Microsoft.Extensions.CodeGeneration.EntityFramework; using System.Linq; +using Newtonsoft.Json; namespace cli { @@ -36,39 +37,66 @@ namespace cli get; set; } - public static ConnectionSettings Settings { get; private set; } + public static ConnectionSettings ConnectionSettings { get; set; } + + public static UserConnectionSettings UserConnectionSettings { get; set; } + public static IConfiguration Configuration { get; set; } public static string HostingFullName { get; private set; } public static IServiceCollection Services { get; private set; } - - - Microsoft.Extensions.Logging.ILogger logger; + public static string EnvironmentName { get; private set; } + public static Microsoft.Extensions.Logging.ILogger Logger { get; private set; } public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv) { 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($"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(cxSettings); + var cxUserSettings = Configuration.GetSection(userCxKey); + services.Configure(cxUserSettings); + var smtpSettingsconf = Configuration.GetSection("Smtp"); // TODO give it a look : Microsoft.Extensions.CodeGenerators.Mvc.View.ViewGeneratorTemplateModel v; @@ -212,7 +240,7 @@ Microsoft.Extensions.CodeGeneration.ICodeGeneratorActionsService), 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"); + Logger.LogInformation($"Found {projects?.Count} projects"); return new CompilerOptionsProvider(projects); }); services.AddMvc(); @@ -220,21 +248,23 @@ Microsoft.Extensions.CodeGeneration.ICodeGeneratorActionsService), services.AddTransient(typeof(Microsoft.Extensions.CodeGeneration.ILogger),typeof(Microsoft.Extensions.CodeGeneration.ConsoleLogger)); Services = services; - } public void Configure(IApplicationBuilder app, IHostingEnvironment env, - IOptions siteSettings, ILoggerFactory loggerFactory) + IOptions siteSettings, + IOptions cxSettings, + IOptions useCxSettings, + ILoggerFactory loggerFactory) { loggerFactory.AddConsole(Configuration.GetSection("Logging")); loggerFactory.AddDebug(); - logger = loggerFactory.CreateLogger(); - logger.LogInformation(env.EnvironmentName); + Logger = loggerFactory.CreateLogger(); 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}"); } - } } diff --git a/src/cli/appsettings.Development.json b/src/cli/appsettings.Development.json deleted file mode 100644 index 98021872..00000000 --- a/src/cli/appsettings.Development.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "Connection": { - "Authority": "dev.pschneider.fr", - "ClientId": "53f4d5da-93a9-4584-82f9-b8fdf243b002", - "ClientSecret": "blouh", - "Audience": "dev.pschneider.fr" - }, - "Smtp": { - "Host": "127.0.0.1", - "Port": 25, - "EnableSSL": false - }, - "Logging": { - "IncludeScopes": true, - "LogLevel": { - "Default": "Debug", - "System": "Warning", - "Microsoft": "Warning" - } - }, - "ConnectionStrings": { - "Default":"Server=localhost;Port=5432;Database=YavscDev;Username=yavscdev;Password=admin;" - }, - "gen_mvc" : { - "NameSpace": "Yavsc", - "AppBase": "../Yavsc", - "RelativePath": "Controllers/Generated", - "DbContextFullName": "Yavsc.Models.ApplicationDbContext", - "ControllerName": "LiveFlowController", - "ModelFullName": "Yavsc.Models.Streaming.LiveFlow" - } -} \ No newline at end of file