From 3505d5aa6c06f1cc9a2a721e17bfd0d73172ca26 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Sun, 15 Jul 2018 00:29:06 +0200 Subject: [PATCH] servicing --- Yavsc.Server/Services/MessageServices.cs | 6 +- Yavsc/Services/Coding.cs | 193 +++++++++++++++++++++++ Yavsc/Services/GitClone.cs | 58 +++++++ cli/Services/EMailer.cs | 17 +- cli/Startup.cs | 31 ++-- cli/project.json | 6 +- rc-num.txt | 2 +- test/src/YavscWorkInProgress.cs | 46 ++++++ testOauthClient/Startup.cs | 2 +- 9 files changed, 332 insertions(+), 29 deletions(-) create mode 100644 Yavsc/Services/Coding.cs create mode 100644 Yavsc/Services/GitClone.cs create mode 100644 test/src/YavscWorkInProgress.cs diff --git a/Yavsc.Server/Services/MessageServices.cs b/Yavsc.Server/Services/MessageServices.cs index dca6e7e0..133d017b 100755 --- a/Yavsc.Server/Services/MessageServices.cs +++ b/Yavsc.Server/Services/MessageServices.cs @@ -38,9 +38,9 @@ namespace Yavsc.Services ) { _logger = loggerFactory.CreateLogger(); - siteSettings = sitesOptions.Value; - smtpSettings = smtpOptions.Value; - googleSettings = googleOptions.Value; + siteSettings = sitesOptions?.Value; + smtpSettings = smtpOptions?.Value; + googleSettings = googleOptions?.Value; } public async Task NotifyEvent diff --git a/Yavsc/Services/Coding.cs b/Yavsc/Services/Coding.cs new file mode 100644 index 00000000..84be9e7c --- /dev/null +++ b/Yavsc/Services/Coding.cs @@ -0,0 +1,193 @@ +// // Coding.cs +// /* +// paul 26/06/2018 12:18 20182018 6 26 +// */ +using System; +using Microsoft.AspNet.Razor; +using Yavsc.Templates; +using Microsoft.CodeAnalysis; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using Microsoft.CSharp; +using Microsoft.AspNet.Identity.EntityFramework; +using Newtonsoft.Json; +using Microsoft.AspNet.Razor.Parser; + +using Yavsc.Models; +using Yavsc.Models.Identity; +using Yavsc.Services; +using System.Collections.Generic; +using System.Linq; +using System.IO; +using System.Reflection; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.Emit; +using Microsoft.Extensions.Logging.Console; +using Yavsc.Abstract.Templates; + +namespace Yavsc.Lib +{ + public class YaRazorEngineHost : RazorEngineHost + { + public YaRazorEngineHost() : base() + { + } + } + public class EMailer + { + const string DefaultBaseClassName = "ATemplate"; + const string DefaultBaseClass = nameof(UserOrientedTemplate); + const string DefaultNamespace = "CompiledRazorTemplates"; + + RazorTemplateEngine razorEngine; + IStringLocalizer stringLocalizer; + + ApplicationDbContext dbContext; + IEmailSender mailSender; + RazorEngineHost host; + ILogger logger; + + public EMailer(ApplicationDbContext context, IEmailSender sender, + IStringLocalizer localizer, + ILoggerFactory loggerFactory) + { + stringLocalizer = localizer; + mailSender = sender; + + logger = loggerFactory.CreateLogger(); + + var language = new CSharpRazorCodeLanguage(); + + host = new RazorEngineHost(language) + { + DefaultBaseClass = DefaultBaseClass, + DefaultClassName = DefaultBaseClassName, + DefaultNamespace = DefaultNamespace + }; + + host.NamespaceImports.Add("System"); + host.NamespaceImports.Add("Yavsc.Templates"); + host.NamespaceImports.Add("Yavsc.Models"); + host.NamespaceImports.Add("Yavsc.Models.Identity"); + host.NamespaceImports.Add("Microsoft.AspNet.Identity.EntityFramework"); + host.InstrumentedSourceFilePath = "."; + host.StaticHelpers = true; + dbContext = context; + razorEngine = new RazorTemplateEngine(host); + } + + public string GenerateTemplateObject(string baseclassName = DefaultBaseClassName) + { + throw new NotImplementedException(); + } + + public void SendMonthlyEmail(long templateCode, string baseclassName = DefaultBaseClassName) + { + string className = "Generated" + baseclassName; + + string subtemp = stringLocalizer["MonthlySubjectTemplate"].Value; + + logger.LogInformation($"Generating {subtemp}[{className}]"); + + + var templateInfo = dbContext.MailingTemplate.FirstOrDefault(t => t.Id == templateCode); + + logger.LogInformation($"Using code: {templateCode}, subject: {subtemp} "); + logger.LogInformation("And body:\n" + templateInfo.Body); + using (StringReader reader = new StringReader(templateInfo.Body)) + { + + // Generate code for the template + var razorResult = razorEngine.GenerateCode(reader, className, DefaultNamespace, DefaultNamespace + ".cs"); + + logger.LogInformation("Razor exited " + (razorResult.Success ? "Ok" : "Ko") + "."); + + logger.LogInformation(razorResult.GeneratedCode); + SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(razorResult.GeneratedCode); + logger.LogInformation("CSharp parsed"); + List references = new List(); + + foreach (var type in new Type[] { + typeof(object), + typeof(Enumerable), + typeof(IdentityUser), + typeof(ApplicationUser), + typeof(Template), + typeof(UserOrientedTemplate), + typeof(System.Threading.Tasks.TaskExtensions) + }) + { + var location = type.Assembly.Location; + if (!string.IsNullOrWhiteSpace(location)) + { + references.Add( + MetadataReference.CreateFromFile(location) + ); + logger.LogInformation($"Assembly for {type.Name} found at {location}"); + } + else logger.LogWarning($"Assembly Not found for {type.Name}"); + } + + logger.LogInformation("Compilation creation ..."); + + var compilationOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) + .WithAllowUnsafe(true).WithOptimizationLevel(OptimizationLevel.Debug) + .WithOutputKind(OutputKind.DynamicallyLinkedLibrary).WithPlatform(Platform.AnyCpu) + .WithUsings("Yavsc.Templates") + ; + string assemblyName = DefaultNamespace; + CSharpCompilation compilation = CSharpCompilation.Create( + assemblyName, + syntaxTrees: new[] { syntaxTree }, + references: references, + options: compilationOptions + ); + + using (var ms = new MemoryStream()) + { + logger.LogInformation("Emitting result ..."); + EmitResult result = compilation.Emit(ms); + foreach (Diagnostic diagnostic in result.Diagnostics.Where(diagnostic => + diagnostic.Severity < DiagnosticSeverity.Error && !diagnostic.IsWarningAsError)) + { + logger.LogWarning("{0}: {1}", diagnostic.Id, diagnostic.GetMessage()); + logger.LogWarning("{0}: {1}", diagnostic.Id, diagnostic.Location.GetLineSpan()); + } + if (!result.Success) + { + logger.LogInformation(razorResult.GeneratedCode); + IEnumerable failures = result.Diagnostics.Where(diagnostic => + diagnostic.IsWarningAsError || + diagnostic.Severity == DiagnosticSeverity.Error); + foreach (Diagnostic diagnostic in failures) + { + logger.LogCritical("{0}: {1}", diagnostic.Id, diagnostic.GetMessage()); + logger.LogCritical("{0}: {1}", diagnostic.Id, diagnostic.Location.GetLineSpan()); + } + } + else + { + logger.LogInformation(razorResult.GeneratedCode); + ms.Seek(0, SeekOrigin.Begin); + Assembly assembly = Assembly.Load(ms.ToArray()); + + Type type = assembly.GetType(DefaultNamespace + "." + className); + var generatedtemplate = (UserOrientedTemplate)Activator.CreateInstance(type); + foreach (var user in dbContext.ApplicationUser.Where( + u => u.AllowMonthlyEmail + )) + { + logger.LogInformation("Generation for " + user.UserName); + generatedtemplate.Init(); + generatedtemplate.User = user; + generatedtemplate.ExecuteAsync(); + logger.LogInformation(generatedtemplate.GeneratedText); + } + + } + } + } + + } + } +} diff --git a/Yavsc/Services/GitClone.cs b/Yavsc/Services/GitClone.cs new file mode 100644 index 00000000..66228c94 --- /dev/null +++ b/Yavsc/Services/GitClone.cs @@ -0,0 +1,58 @@ +// // GitClone.cs +// /* +// paul 21/06/2018 11:27 20182018 6 21 +// */ +using System; +using Yavsc.Server.Models.IT.SourceCode; +using Yavsc.Server.Models.IT; +using System.Threading.Tasks; +using System.Diagnostics; +using System.IO; + +namespace Yavsc.Lib +{ + public class GitClone : Batch + { + string _repositoryRootPath; + + public GitClone(string repoRoot) + { + _repositoryRootPath = repoRoot; + } + + public override void Launch(Project input) + { + WorkingDir = _repositoryRootPath; + LogPath = $"{input.Name}.git-clone.ansi.log"; + // TODO honor Args property + // Model annotations => input.Repository!=null => input.Name == input.Repository.Path + var prjPath = Path.Combine(WorkingDir, input.Name); + var repoInfo = new DirectoryInfo(prjPath); + var gitCmd = repoInfo.Exists ? "pull" : "clone"; + + var cloneStart = new ProcessStartInfo + ( gitCmd, $"{gitCmd} {input.Repository.Url} {input.Repository.Path}" ) + { + WorkingDirectory = WorkingDir, + RedirectStandardOutput = true, + UseShellExecute = false + }; + // TODO make `.ansi.log` a defined constant. + var logFile = new FileInfo + ( Path.Combine + ( _repositoryRootPath, $"{input.Name}.ansi.log" )); + using (var stream = logFile.Create()) + using (var writer = new StreamWriter(stream)) + { + var process = Process.Start(cloneStart); + // TODO announce ... + while (!process.HasExited) + { + if (process.StandardOutput.Peek() > -1) + writer.WriteLine(process.StandardOutput.ReadLine()); + } + } + ResultHandler(true); + } + } +} diff --git a/cli/Services/EMailer.cs b/cli/Services/EMailer.cs index 3ed31857..ce2afa32 100644 --- a/cli/Services/EMailer.cs +++ b/cli/Services/EMailer.cs @@ -68,10 +68,6 @@ namespace cli.Services razorEngine = new RazorTemplateEngine(host); } - public string GenerateTemplateObject(string baseclassName = DefaultBaseClassName) - { - throw new NotImplementedException(); - } public void SendMonthlyEmail(long templateCode, string baseclassName = DefaultBaseClassName) { @@ -162,7 +158,11 @@ namespace cli.Services Assembly assembly = Assembly.Load(ms.ToArray()); Type type = assembly.GetType(DefaultNamespace + "." + className); - var generatedtemplate = (UserOrientedTemplate)Activator.CreateInstance(type); + var generatedtemplate = (UserOrientedTemplate) Activator.CreateInstance(type); + if (generatedtemplate==null) { + logger.LogError("No generated template ... exiting."); + throw new InvalidOperationException("No generated template"); + } foreach (var user in dbContext.ApplicationUser.Where( u => u.AllowMonthlyEmail )) @@ -172,6 +172,13 @@ namespace cli.Services generatedtemplate.User = user; generatedtemplate.ExecuteAsync(); logger.LogInformation(generatedtemplate.GeneratedText); + var mailSentInfo = this.mailSender.SendEmailAsync + (user.UserName, user.Email, $"monthly email", generatedtemplate.GeneratedText).Result; + if (!mailSentInfo.Sent) + logger.LogError($"{mailSentInfo.ErrorMessage}"); + else + logger.LogInformation($"mailId:{mailSentInfo.MessageId} \nto:{user.UserName}"); + } } diff --git a/cli/Startup.cs b/cli/Startup.cs index 63de2c6c..ebe09199 100644 --- a/cli/Startup.cs +++ b/cli/Startup.cs @@ -3,34 +3,21 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.OptionsModel; - -using System.Globalization; -using System.Reflection; -// using Microsoft.AspNet.Authorization; using Microsoft.AspNet.Builder; -// using Microsoft.AspNet.Diagnostics; using Microsoft.AspNet.Hosting; -using Microsoft.AspNet.Identity; -using Microsoft.AspNet.Identity.EntityFramework; -using Microsoft.AspNet.Localization; -using Microsoft.AspNet.Mvc; -using Microsoft.AspNet.Mvc.Filters; -using Microsoft.AspNet.Mvc.Razor; -using Microsoft.Net.Http.Headers; using Microsoft.AspNet.Razor; -using Microsoft.Extensions.DependencyInjection.Abstractions; using Microsoft.Extensions.PlatformAbstractions; using cli.Services; using Yavsc; using Yavsc.Models; -using Yavsc.Server.Helpers; using Yavsc.Services; -using Yavsc.Templates; using Microsoft.Data.Entity; +using Microsoft.AspNet.Authentication; +using Microsoft.Extensions.WebEncoders; namespace cli { - public class Startup + public class Startup { public string ConnectionString { @@ -86,6 +73,15 @@ namespace cli .AddDbContext( db => db.UseNpgsql(ConnectionString) ); + services.Configure(options => + { + options.SignInScheme = "Bearer"; + }); + + services.AddTransient(); + + services.AddAuthentication(); + } public void Configure (IApplicationBuilder app, IHostingEnvironment env, @@ -95,6 +91,9 @@ namespace cli loggerFactory.AddDebug(); logger = loggerFactory.CreateLogger(); logger.LogInformation(env.EnvironmentName); + var authConf = Configuration.GetSection("Authentication").GetSection("Yavsc"); + var clientId = authConf.GetSection("ClientId").Value; + var clientSecret = authConf.GetSection("ClientSecret").Value; } diff --git a/cli/project.json b/cli/project.json index d93f16fb..c06bd675 100644 --- a/cli/project.json +++ b/cli/project.json @@ -44,15 +44,15 @@ "Microsoft.Framework.ConfigurationModel.Json": "1.0.0-beta4", "Newtonsoft.Json": "9.0.1", "Yavsc": { - "version": "1.0.5-rc21-beta5", + "version": "1.0.5-rc21-beta7", "target": "package" }, "Yavsc.Abstract": { - "version": "1.0.5-rc21-beta5", + "version": "1.0.5-rc21-beta7", "target": "package" }, "Yavsc.Server": { - "version": "1.0.5-rc21-beta5", + "version": "1.0.5-rc21-beta7", "target": "package" }, "Yavsc.Lib.Portable": "1.0.2" diff --git a/rc-num.txt b/rc-num.txt index db0a8931..81cd254a 100644 --- a/rc-num.txt +++ b/rc-num.txt @@ -1 +1 @@ -21-beta6 +21-beta7 diff --git a/test/src/YavscWorkInProgress.cs b/test/src/YavscWorkInProgress.cs new file mode 100644 index 00000000..cbe2af29 --- /dev/null +++ b/test/src/YavscWorkInProgress.cs @@ -0,0 +1,46 @@ +// // YavscWorkInProgress.cs +// /* +// paul 21/06/2018 10:11 20182018 6 21 +// */ +using System; +using System.Linq; +using Microsoft.AspNet.Builder; +using Microsoft.AspNet.Builder.Internal; +using Microsoft.Dnx.Compilation.CSharp; +using Microsoft.Dnx.Runtime; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.OptionsModel; +using Microsoft.Extensions.PlatformAbstractions; +using Xunit; +using Yavsc; +using Yavsc.Lib; +using Yavsc.Models; + +namespace Test +{ + [Collection("Yavsc Work In Progress")] + public class YavscWorkInProgress : BaseTestContext + { + + [Fact] + public void GitClone() + { + + AppDomain.CurrentDomain.SetData("YAVSC_DB_CONNECTION", "Server=localhost;Port=5432;Database=YavscDev;Username=yavscdev;Password=admin;"); + ServiceCollection services = new ServiceCollection(); + + YavscMandatory.ConfigureServices(services, testprojectAssetPath, out configuration, out provider); + + var siteConfig = provider.GetRequiredService>().Value; + var dbc = provider.GetRequiredService(); + + var firstProject = dbc.Projects.FirstOrDefault(); + Assert.NotNull (firstProject); + + var clone = new GitClone(siteConfig.GitRepository); + clone.Launch(firstProject); + } + } +} diff --git a/testOauthClient/Startup.cs b/testOauthClient/Startup.cs index 0e29a10d..4dc9a514 100755 --- a/testOauthClient/Startup.cs +++ b/testOauthClient/Startup.cs @@ -80,7 +80,7 @@ namespace testOauthClient LoginPath = new PathString("/signin"), LogoutPath = new PathString("/signout") }); - var host = "http://dev.pschneider.fr"; + var host = "http://dev.pschneider.fr"; app.UseOAuthAuthentication( options => {