public ArchiveController(ICacheClient cacheClient, IBlogService blogService, IOptions <BlogOptions> blogOption) { _cacheClient = cacheClient; _blogService = blogService; _blogOptions = blogOption.Value; }
public Startup(IConfiguration configuration, IHostEnvironment hostEnvironment) { Configuration = configuration; HostEnvironment = hostEnvironment; BlogOptions = new BlogOptions(); }
public static async Task <SyndicationFeed> BuildSyndication(this IBlogService service, string baseAddress) { ClientUrlGenerator generator = new ClientUrlGenerator { BaseAddress = baseAddress }; BlogOptions blogOptions = await service.GetOptions(); SyndicationFeed feed = new SyndicationFeed(blogOptions.Name, blogOptions.Description, new Uri(baseAddress)); SyndicationPerson author = new SyndicationPerson("", blogOptions.Onwer, baseAddress); feed.Authors.Add(author); Dictionary <string, SyndicationCategory> categoryMap = new Dictionary <string, SyndicationCategory>(); { /*var cates = await BlogService.CategoryService.GetCategories(await BlogService.CategoryService.All()); * foreach (var p in cates) * { * var cate = new SyndicationCategory(p.Name); * categoryMap.Add(p.Id, cate); * feed.Categories.Add(cate); * }*/ } { var posts = await service.PostService.GetPosts(await service.PostService.All()); List <SyndicationItem> items = new List <SyndicationItem>(); foreach (var p in posts) { if (p is null) { continue; } var s = new SyndicationItem(p.Title, SyndicationContent.CreateHtmlContent(Markdown.ToHtml(p.Content.Raw, Pipeline)), new Uri(generator.Post(p.Id)), p.Id, p.ModificationTime); s.Authors.Add(author); string summary; if (await service.PostService.Protector.IsProtected(p.Content)) { summary = "Protected Post"; } else { summary = Markdown.ToPlainText(p.Content.Raw, Pipeline); } s.Summary = SyndicationContent.CreatePlaintextContent(summary.Length <= 100 ? summary : summary.Substring(0, 100)); s.Categories.Add(new SyndicationCategory(p.Category.ToString())); /*if (categoryMap.TryGetValue(p.CategoryId, out var cate)) * s.Categories.Add(cate);*/ s.PublishDate = p.CreationTime; items.Add(s); } feed.Items = items.AsEnumerable(); } return(feed); }
public BlogBuilder(BlogOptions options, string rootPath) { RootPath = rootPath; Options = options; FsBuilder = new FSBuilder(rootPath); }
public IndexModel( IBlogService blogManager, BlogOptions blogOptions ) { _blogManager = blogManager; _blogOptions = blogOptions; }
public HomeController( IBlogService blogService, IOptions <BlogOptions> config, ICacheClient cacheClient) { _cacheClient = cacheClient; _blogService = blogService; _blogOptions = config.Value; }
public AccountController(ILogger <AccountController> logger, BlogUserManager blogUserManager, BlogSignInManager signInManager, IEmailSender emailSender, IOptionsSnapshot <BlogOptions> blogOptions, AdvancedSettings advancedSettings) { _logger = logger; _userManager = blogUserManager; _signInManager = signInManager; _emailSender = emailSender; _blogOptions = blogOptions.Value; _advancedSettings = advancedSettings; }
public BlogController(IOptions <BlogOptions> blogOptions, IAuthorizationService authorizationService, ICategoriesCache categoriesCache, OperationKeysContainer operationKeysContainer, IBlogPresenter blogPresenter, IServiceProvider serviceProvider) : base(serviceProvider) { OperationKeys = operationKeysContainer; this.blogOptions = blogOptions.Value; this.authorizationService = authorizationService; this.categoriesCache = categoriesCache; this.blogPresenter = blogPresenter; }
public BlogService( IPostRepository postRepository, ICommentRepository commentRepository, IPostBuilder postBuilder, ICommentBuilder commentBuilder, IEmailService emailService, INotificationBuilder notificationBuilder, BlogOptions options, ILogger <BlogService> logger) { _postRepository = postRepository; _commentRepository = commentRepository; _postBuilder = postBuilder; _commentBuilder = commentBuilder; _emailService = emailService; _notificationBuilder = notificationBuilder; _options = options; _logger = logger; }
public async Task <bool> SetOptions(BlogOptions options, CancellationToken cancellationToken = default) { var entry = await DataContext.BlogEntries.FindAsync(new object[] { BlogOptionsEntry }, cancellationToken).ConfigureAwait(false); if (entry is null) { DataContext.BlogEntries.Add(new RawEntry { Id = BlogOptionsEntry, Value = JsonSerializer.Serialize(options) }); } else { entry.Value = JsonSerializer.Serialize(options); } await DataContext.SaveChangesAsync(cancellationToken).ConfigureAwait(false); return(true); }
public LocalFileService(IOptions <BlogOptions> blogOptions, IHttpContextAccessor httpContextAccessor, IWebHostEnvironment webHostEnvironment) { _blogOptions = blogOptions.Value; _webHostEnvironment = webHostEnvironment; _httpContextAccessor = httpContextAccessor; if (_blogOptions.Upload.Provider != BlogUploadProvider.Local && _blogOptions.Upload.Provider != BlogUploadProvider.Unknow) { throw new Exception("The blog upload option provider is not 'local'."); } var folder = _blogOptions.Upload.Value ?? "uploads"; _serverBaseFolder = _webHostEnvironment.WebRootPath; var fullFolder = Path.Combine(_serverBaseFolder, folder, DateTime.Now.ToString("yyyyMMdd")); if (!Directory.Exists(fullFolder)) { Directory.CreateDirectory(fullFolder); } _serverFullFolder = fullFolder; }
public async Task Setup() { RootPath = Path.Join(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "fstest"); FSStaticBuilder.EnsureDirectoryExists(RootPath); PostData = Enumerable.Range(0, 100).Select(x => Generator.GetPost()).ToArray(); LayoutData = Enumerable.Range(0, 100).Select(x => Generator.GetLayout()).ToArray(); PageData = Enumerable.Range(0, 100).Select(x => Generator.GetPage()).ToArray(); FileData = Enumerable.Range(0, 100).Select(x => Generator.GetFile()).ToArray(); BlogOptionsData = new BlogOptions(); BlogBuilder builder = new BlogBuilder(BlogOptionsData, RootPath); await builder.Build(); await builder.BuildPosts(PostData); await builder.BuildLayouts(LayoutData); await builder.BuildPages(PageData); await builder.BuildFiles(FileData); BlogService = new FileSystemBlogService(new PhysicalFileProvider(RootPath).AsFileProvider()); }
public BlogDbContext CreateDbContext(string[] args) { var configuration = BuildConfiguration(); var blogOptions = new BlogOptions(); var connectionString = configuration.GetConnectionString("Blog"); configuration.GetSection("Blog").Bind(blogOptions); var builder = blogOptions.DbType switch { DbType.SqlServer => new DbContextOptionsBuilder <BlogDbContext>() .UseSqlServer(connectionString), DbType.MySQL => new DbContextOptionsBuilder <BlogDbContext>() .UseMySql(connectionString, ServerVersion.Parse(blogOptions.ServerVersion)), DbType.PostgreSql => new DbContextOptionsBuilder <BlogDbContext>() .UseNpgsql(connectionString), DbType.Oracle => new DbContextOptionsBuilder <BlogDbContext>() .UseOracle(connectionString), _ => new DbContextOptionsBuilder <BlogDbContext>() .UseSqlite(connectionString), }; return(new BlogDbContext(builder.Options)); }
public BlogController(IPostService postService, IOptions <BlogOptions> blogSettings, IOptions <SocialMedia> socialMediaSettings) { _postService = postService; _blogSettings = blogSettings.Value; _socialMediaSettings = socialMediaSettings.Value; }
public override void PreConfigureServices(ServiceConfigurationContext context) { var configuration = context.Services.GetConfiguration(); var https = new HttpsOptions(); var blog = new BlogOptions(); var notification = new NotificationOptions(); var swagger = new SwaggerOptions(); var storage = new StorageOptions(); var cors = new CorsOptions(); var jwt = new JwtOptions(); var worker = new WorkerOptions(); var tencentCloud = new TencentCloudOptions(); var authorize = new AuthorizeOptions(); PreConfigure <HttpsOptions>(options => { var httpsOption = configuration.GetSection("https"); Configure <HttpsOptions>(httpsOption); options.ListenAddress = httpsOption.GetValue <string>(nameof(options.ListenAddress)); options.ListenPort = httpsOption.GetValue <int>(nameof(options.ListenPort)); options.PublicCertFile = httpsOption.GetValue <string>(nameof(options.PublicCertFile)); options.PrivateCertFile = httpsOption.GetValue <string>(nameof(options.PrivateCertFile)); https = options; }); PreConfigure <BlogOptions>(options => { var blogOption = configuration.GetSection("blog"); Configure <BlogOptions>(blogOption); options.StaticUrl = blogOption.GetValue <string>(nameof(options.StaticUrl)); options.ApiUrl = blogOption.GetValue <string>(nameof(options.ApiUrl)); options.WebUrl = blogOption.GetValue <string>(nameof(options.WebUrl)); options.AdminUrl = blogOption.GetValue <string>(nameof(options.AdminUrl)); blog = options; }); PreConfigure <NotificationOptions>(options => { var notificationOption = configuration.GetSection("notification"); Configure <NotificationOptions>(notificationOption); options.FtqqUrl = notificationOption.GetValue <string>(nameof(options.FtqqUrl)); notification = options; }); PreConfigure <SwaggerOptions>(options => { var swaggerOption = configuration.GetSection("swagger"); Configure <SwaggerOptions>(swaggerOption); options.Version = swaggerOption.GetValue <string>(nameof(options.Version)); options.Name = swaggerOption.GetValue <string>(nameof(options.Name)); options.Title = swaggerOption.GetValue <string>(nameof(options.Title)); options.Description = swaggerOption.GetValue <string>(nameof(options.Description)); options.RoutePrefix = swaggerOption.GetValue <string>(nameof(options.RoutePrefix)); options.DocumentTitle = swaggerOption.GetValue <string>(nameof(options.DocumentTitle)); swagger = options; }); PreConfigure <StorageOptions>(options => { var storageOption = configuration.GetSection("storage"); Configure <StorageOptions>(storageOption); options.Mongodb = storageOption.GetValue <string>(nameof(options.Mongodb)); options.RedisIsEnabled = storageOption.GetValue <bool>(nameof(options.RedisIsEnabled)); options.Redis = storageOption.GetValue <string>(nameof(options.Redis)); storage = options; }); PreConfigure <CorsOptions>(options => { var corsOption = configuration.GetSection("cors"); Configure <CorsOptions>(corsOption); options.PolicyName = corsOption.GetValue <string>(nameof(options.PolicyName)); options.Origins = corsOption.GetValue <string>(nameof(options.Origins)); cors = options; }); PreConfigure <JwtOptions>(options => { var jwtOption = configuration.GetSection("jwt"); Configure <JwtOptions>(jwtOption); options.Issuer = jwtOption.GetValue <string>(nameof(options.Issuer)); options.Audience = jwtOption.GetValue <string>(nameof(options.Audience)); options.SigningKey = jwtOption.GetValue <string>(nameof(options.SigningKey)); jwt = options; }); PreConfigure <WorkerOptions>(options => { var workerOption = configuration.GetSection("worker"); Configure <WorkerOptions>(workerOption); options.IsEnabled = workerOption.GetValue <bool>(nameof(options.IsEnabled)); options.Cron = workerOption.GetValue <string>(nameof(options.Cron)); worker = options; }); PreConfigure <TencentCloudOptions>(options => { var tencentCloudOption = configuration.GetSection("tencentCloud"); Configure <TencentCloudOptions>(tencentCloudOption); options.SecretId = tencentCloudOption.GetValue <string>(nameof(options.SecretId)); options.SecretKey = tencentCloudOption.GetValue <string>(nameof(options.SecretKey)); tencentCloud = options; }); PreConfigure <AuthorizeOptions>(options => { var authorizeOption = configuration.GetSection("authorize"); var githubOption = authorizeOption.GetSection("github"); var giteeOption = authorizeOption.GetSection("gitee"); var alipayOption = authorizeOption.GetSection("alipay"); var dingtalkOption = authorizeOption.GetSection("dingtalk"); var microsoftOption = authorizeOption.GetSection("microsoft"); var weiboOptions = authorizeOption.GetSection("weibo"); var qqOptions = authorizeOption.GetSection("qq"); Configure <AuthorizeOptions>(authorizeOption); Configure <GithubOptions>(githubOption); Configure <GiteeOptions>(giteeOption); Configure <AlipayOptions>(alipayOption); Configure <DingtalkOptions>(dingtalkOption); Configure <MicrosoftOptions>(microsoftOption); Configure <WeiboOptions>(weiboOptions); Configure <QQOptions>(qqOptions); options.Github = new GithubOptions { ClientId = githubOption.GetValue <string>(nameof(options.Github.ClientId)), ClientSecret = githubOption.GetValue <string>(nameof(options.Github.ClientSecret)), RedirectUrl = githubOption.GetValue <string>(nameof(options.Github.RedirectUrl)), Scope = githubOption.GetValue <string>(nameof(options.Github.Scope)) }; options.Gitee = new GiteeOptions { ClientId = giteeOption.GetValue <string>(nameof(options.Gitee.ClientId)), ClientSecret = giteeOption.GetValue <string>(nameof(options.Gitee.ClientSecret)), RedirectUrl = giteeOption.GetValue <string>(nameof(options.Gitee.RedirectUrl)), Scope = giteeOption.GetValue <string>(nameof(options.Gitee.Scope)) }; options.Alipay = new AlipayOptions { AppId = alipayOption.GetValue <string>(nameof(options.Alipay.AppId)), RedirectUrl = alipayOption.GetValue <string>(nameof(options.Alipay.RedirectUrl)), Scope = alipayOption.GetValue <string>(nameof(options.Alipay.Scope)), PrivateKey = alipayOption.GetValue <string>(nameof(options.Alipay.PrivateKey)), PublicKey = alipayOption.GetValue <string>(nameof(options.Alipay.PublicKey)) }; options.Dingtalk = new DingtalkOptions { AppId = dingtalkOption.GetValue <string>(nameof(options.Dingtalk.AppId)), AppSecret = dingtalkOption.GetValue <string>(nameof(options.Dingtalk.AppSecret)), RedirectUrl = dingtalkOption.GetValue <string>(nameof(options.Dingtalk.RedirectUrl)), Scope = dingtalkOption.GetValue <string>(nameof(options.Dingtalk.Scope)) }; options.Microsoft = new MicrosoftOptions { ClientId = microsoftOption.GetValue <string>(nameof(options.Microsoft.ClientId)), ClientSecret = microsoftOption.GetValue <string>(nameof(options.Microsoft.ClientSecret)), RedirectUrl = microsoftOption.GetValue <string>(nameof(options.Microsoft.RedirectUrl)), Scope = microsoftOption.GetValue <string>(nameof(options.Microsoft.Scope)) }; options.Weibo = new WeiboOptions { ClientId = weiboOptions.GetValue <string>(nameof(options.Weibo.ClientId)), ClientSecret = weiboOptions.GetValue <string>(nameof(options.Weibo.ClientSecret)), RedirectUrl = weiboOptions.GetValue <string>(nameof(options.Weibo.RedirectUrl)), Scope = weiboOptions.GetValue <string>(nameof(options.Weibo.Scope)) }; options.QQ = new QQOptions { ClientId = qqOptions.GetValue <string>(nameof(options.QQ.ClientId)), ClientSecret = qqOptions.GetValue <string>(nameof(options.QQ.ClientSecret)), RedirectUrl = qqOptions.GetValue <string>(nameof(options.QQ.RedirectUrl)), Scope = qqOptions.GetValue <string>(nameof(options.QQ.Scope)) }; authorize = options; }); PreConfigure <AppOptions>(options => { options.Https = https; options.Blog = blog; options.Swagger = swagger; options.Storage = storage; options.Cors = cors; options.Jwt = jwt; options.Worker = worker; options.TencentCloud = tencentCloud; options.Authorize = authorize; Configure <AppOptions>(item => { item.Swagger = swagger; item.Storage = storage; item.Cors = cors; item.Jwt = jwt; item.Worker = worker; item.TencentCloud = tencentCloud; item.Authorize = authorize; }); }); }
public Task <bool> SetOptions(BlogOptions options, CancellationToken cancellationToken = default) => throw new NotImplementedException();
public BlogPresenter( DataBaseConnection db, IOptions <BlogOptions> blogOptions) : base(db) { this.blogOptions = blogOptions.Value; }
public UpdateBlogOptionsModel(BlogOptions options) { NumberOfPostsToShowOnHomePage = options.NumberOfPostsToShowOnHomePage; }
public static IServiceCollection ConfigureIdenittyService(this IServiceCollection services, IConfiguration configuration, BlogOptions blogOptions) { services.AddIdentity <User, Role>(options => { options.Password.RequireDigit = false; options.Password.RequireLowercase = true; options.Password.RequireUppercase = false; options.Password.RequireNonAlphanumeric = false; options.SignIn.RequireConfirmedAccount = blogOptions.Account.RequireConfirmedAccount; }) .AddUserManager <BlogUserManager>() .AddRoleManager <BlogRoleManager>() .AddSignInManager <BlogSignInManager>() .AddDefaultTokenProviders() .AddEntityFrameworkStores <BlogDbContext>(); services.AddScoped <CustomCookieAuthenticationEvents>(); services.ConfigureApplicationCookie(options => { options.EventsType = typeof(CustomCookieAuthenticationEvents); }); // default add by identity // services.AddAuthentication(); var authenticationBuilder = services.AddAuthentication(); services.Configure <AuthenticationOptions>(options => { // options.DefaultScheme = "Cookies"; }); if (configuration.GetValue <bool>("Authentication:Microsoft:Enabled")) { // test ok authenticationBuilder.AddMicrosoftAccount(options => { options.ClientId = configuration["Authentication:Microsoft:ClientId"]; options.ClientSecret = configuration["Authentication:Microsoft:ClientSecret"]; options.CallbackPath = new PathString("/signin-microsoft"); options.AccessDeniedPath = new PathString("/account/accessdenied"); }); } if (configuration.GetValue <bool>("Authentication:GitHub:Enabled")) { // test ok authenticationBuilder.AddGitHub(options => { options.ClientId = configuration["Authentication:GitHub:ClientId"]; options.ClientSecret = configuration["Authentication:GitHub:ClientSecret"]; options.CallbackPath = new PathString("/signin-github"); options.AccessDeniedPath = new PathString("/account/accessdenied"); }); } if (configuration.GetValue <bool>("Authentication:Google:Enabled")) { // test ok authenticationBuilder.AddGoogle(options => { options.ClientId = configuration["Authentication:Google:ClientId"]; options.ClientSecret = configuration["Authentication:Google:ClientSecret"]; options.CallbackPath = new PathString("/signin-google"); options.AccessDeniedPath = new PathString("/account/accessdenied"); }); } if (configuration.GetValue <bool>("Authentication:AzureAD:Enabled")) { // test ok authenticationBuilder.AddAzureAD(options => { options.TenantId = configuration["Authentication:AzureAD:TenantId"]; options.ClientId = configuration["Authentication:AzureAD:ClientId"]; options.Instance = configuration["Authentication:AzureAD:Instance"]; options.Domain = configuration["Authentication:AzureAD:Domain"]; options.ClientSecret = configuration["Authentication:AzureAD:ClientSecret"]; options.CallbackPath = new PathString("/signin-azuread"); options.SignedOutCallbackPath = new PathString("/signout-callback-oidc"); options.CookieSchemeName = "Identity.External"; // import }); services.Configure <OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options => { options.Authority = options.Authority + "/v2.0/"; // Per the code below, this application signs in users in any Work and School // accounts and any Microsoft Personal Accounts. // If you want to direct Azure AD to restrict the users that can sign-in, change // the tenant value of the appsettings.json file in the following way: // - only Work and School accounts => 'organizations' // - only Microsoft Personal accounts => 'consumers' // - Work and School and Personal accounts => 'common' // If you want to restrict the users that can sign-in to only one tenant // set the tenant value in the appsettings.json file to the tenant ID of this // organization, and set ValidateIssuer below to true. // If you want to restrict the users that can sign-in to several organizations // Set the tenant value in the appsettings.json file to 'organizations', set // ValidateIssuer, above to 'true', and add the issuers you want to accept to the // options.TokenValidationParameters.ValidIssuers collection options.TokenValidationParameters.ValidateIssuer = false; }); } if (configuration.GetValue <bool>("Authentication:OpenIdConnect:Enabled")) { authenticationBuilder.AddOpenIdConnect(options => { options.CallbackPath = new PathString("/signin-oidc"); options.AccessDeniedPath = new PathString("/account/accessdenied"); options.ClientId = configuration["Authentication:OpenIdConnect:ClientId"]; options.ClientSecret = configuration["Authentication:OpenIdConnect:ClientSecret"]; options.Authority = configuration["Authentication:OpenIdConnect:Authority"]; options.ResponseType = configuration["Authentication:OpenIdConnect:ResponseType"]; options.RequireHttpsMetadata = false; options.Scope.Add("openid"); options.Scope.Add("email"); }); } services.AddAuthorization(options => { }); return(services); }
public Task <bool> SetOptions(BlogOptions options, CancellationToken cancellationToken = default) => Main.SetOptions(options, cancellationToken);
public async Task <bool> SetOptions([FromBody] BlogOptions options) { return(await BlogService.SetOptions(options)); }
public async Task OnGetAsync() { BlogOptions = await Service.GetOptions(); }
// full: delete diff post for api remote public async Task Push(string name = "", bool full = false) { if (string.IsNullOrEmpty(name)) { name = Option.CurrentRemote; } Logger.LogInformation($"Push to remote {name}."); if (Option.Remotes.TryGetValue(name, out var remote)) { Logger.LogInformation($"Detect remote {remote.Name} ({Enum.GetName(typeof(RemoteType), remote.Type)})."); switch (remote.Type) { case RemoteType.LocalFS: { await toLocalFS(remote); } break; case RemoteType.RemoteFS: { throw new NotSupportedException("Not support pushing to remote file system, please push to local file system and sync to remote."); } case RemoteType.Api: { await Connect(name); Logger.LogInformation($"Fetch remote posts."); await Remote.SetOptions(await Local.GetOptions()); await SyncRecordRepository(Local.PostService, Remote.PostService, full); await SyncRecordRepository(Local.PageService, Remote.PageService, full); await SyncRecordRepository(Local.LayoutService, Remote.LayoutService, full); } break; case RemoteType.Git: { await Connect(name); string tempDist = Path.Join(Environment.CurrentDirectory, "temp/dist"); Logger.LogInformation("Generate data."); await toLocalFS(new RemoteOption { Uri = tempDist, Type = RemoteType.LocalFS, Name = remote.Name }); FSExtensions.CopyDirectory(tempDist, GitTempFolder); Logger.LogInformation("Load git config."); string userName = Option.Properties[$"remote.{remote.Name}.git.username"], password = Option.Properties[$"remote.{remote.Name}.git.password"]; { if (string.IsNullOrEmpty(userName)) { userName = ConsoleExtensions.Input("Input username: "******"Input password: "******"Commit to git."); LibGit2Sharp.Commands.Stage(repo, "*"); var signature = new LibGit2Sharp.Signature( new Identity("AcBlog.Tools.Sdk", "tools.sdk@acblog"), DateTimeOffset.Now); repo.Commit(DateTimeOffset.Now.ToString(), signature, signature, new CommitOptions { AllowEmptyCommit = true }); Logger.LogInformation($"Push to {repo.Head.RemoteName}."); PushOptions options = new PushOptions { CredentialsProvider = new CredentialsHandler( (url, usernameFromUrl, types) => new UsernamePasswordCredentials() { Username = string.IsNullOrEmpty(userName) ? usernameFromUrl : userName, Password = password }) }; repo.Network.Push(repo.Head, options); } } break; } } else { throw new Exception("No remote"); } async Task toLocalFS(RemoteOption remote) { FSBuilder fsBuilder = new FSBuilder(remote.Uri); fsBuilder.EnsureDirectoryEmpty(); List <Post> posts = new List <Post>(); await foreach (var item in Local.PostService.GetAllItems().IgnoreNull()) { Logger.LogInformation($"Loaded Post {item.Id}: {item.Title}"); posts.Add(item); } List <Layout> layouts = new List <Layout>(); await foreach (var item in Local.LayoutService.GetAllItems().IgnoreNull()) { Logger.LogInformation($"Loaded Layout {item.Id}"); layouts.Add(item); } List <Page> pages = new List <Page>(); await foreach (var item in Local.PageService.GetAllItems().IgnoreNull()) { Logger.LogInformation($"Loaded Page {item.Id}: {item.Title}"); pages.Add(item); } var baseAddress = Option.Properties[$"remote.{remote.Name}.generator.baseAddress"]; List <Data.Models.File> files = new List <Data.Models.File>(); { string path = Path.Join(Environment.CurrentDirectory, AssetsPath); if (Directory.Exists(path)) { foreach (var file in Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories)) { var id = Path.GetRelativePath(Environment.CurrentDirectory, file).Replace('\\', '/'); Data.Models.File f = new Data.Models.File { Id = id, Uri = string.IsNullOrWhiteSpace(baseAddress) ? $"/{id}" : $"{baseAddress.TrimEnd('/')}/{id}" }; files.Add(f); } } } Logger.LogInformation("Build data."); { BlogOptions options = await Local.GetOptions(); BlogBuilder builder = new BlogBuilder(options, Path.Join(remote.Uri)); await builder.Build(); await builder.BuildPosts(posts); await builder.BuildLayouts(layouts); await builder.BuildPages(pages); await builder.BuildFiles(files); } { if (!string.IsNullOrEmpty(baseAddress)) { Logger.LogInformation("Build sitemap."); var sub = fsBuilder.CreateSubDirectoryBuilder("Site"); { var siteMapBuilder = await Local.BuildSitemap(baseAddress); await using var st = sub.GetFileRewriteStream("sitemap.xml"); await using var writer = XmlWriter.Create(st, new XmlWriterSettings { Async = true }); siteMapBuilder.Build().WriteTo(writer); } Logger.LogInformation("Build feed."); { var feed = await Local.BuildSyndication(baseAddress); await using (var st = sub.GetFileRewriteStream("atom.xml")) { await using var writer = XmlWriter.Create(st, new XmlWriterSettings { Async = true }); feed.GetAtom10Formatter().WriteTo(writer); } await using (var st = sub.GetFileRewriteStream("rss.xml")) { await using var writer = XmlWriter.Create(st, new XmlWriterSettings { Async = true }); feed.GetRss20Formatter().WriteTo(writer); } } } } { string assetsPath = Path.Join(Environment.CurrentDirectory, AssetsPath); if (Directory.Exists(assetsPath)) { Logger.LogInformation("Copy assets."); FSExtensions.CopyDirectory(assetsPath, Path.Join(remote.Uri, AssetsPath)); } } } }
internal static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { config.AddYamlFile("appsettings.yml", optional: true, reloadOnChange: true); var configDictionary = config.Build().SerializeToJson(); Console.ForegroundColor = ConsoleColor.Blue; Console.WriteLine($"appsettings {@configDictionary}"); Console.ResetColor(); }) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup <Startup>(); }) .ConfigureServices((hostingContext, services) => { var https = new HttpsOptions(); var blog = new BlogOptions(); var httpsOption = hostingContext.Configuration.GetSection("https"); https.ListenAddress = httpsOption.GetValue <string>(nameof(https.ListenAddress)); https.ListenPort = httpsOption.GetValue <int>(nameof(https.ListenPort)); https.PublicCertFile = httpsOption.GetValue <string>(nameof(https.PublicCertFile)); https.PrivateCertFile = httpsOption.GetValue <string>(nameof(https.PrivateCertFile)); services.Configure <HttpsOptions>(httpsOption); var blogOption = hostingContext.Configuration.GetSection("blog"); blog.AdminUrl = blogOption.GetValue <string>(nameof(BlogOptions.AdminUrl)); blog.ApiUrl = blogOption.GetValue <string>(nameof(BlogOptions.ApiUrl)); blog.WebUrl = blogOption.GetValue <string>(nameof(BlogOptions.WebUrl)); blog.StaticUrl = blogOption.GetValue <string>(nameof(BlogOptions.StaticUrl)); blog.TelegramUrl = blogOption.GetValue <string>(nameof(BlogOptions.TelegramUrl)); blog.GithubUrl = blogOption.GetValue <string>(nameof(BlogOptions.GithubUrl)); blog.Title = blogOption.GetValue <string>(nameof(BlogOptions.Title)); services.Configure <BlogOptions>(blogOption); services.Configure <KestrelServerOptions>(options => { IPAddress address = null; try { address = IPAddress.Parse(https.ListenAddress); } catch (FormatException) { address = Dns.GetHostAddresses(https.ListenAddress).FirstOrDefault(); } IPEndPoint SharpBlogEndpoint = new IPEndPoint(address, https.ListenPort); options.Listen(SharpBlogEndpoint, listenOptions => { listenOptions.UseHttps(httpsOptions => { if (!File.Exists(https.PrivateCertFile) || !File.Exists(https.PublicCertFile)) { X509Certificate2 certificate = SharpBlogEndpoint.Address.CreateSelfSignedCertificate("CN=SharpBlog"); File.WriteAllBytes(https.PrivateCertFile, certificate.Export(X509ContentType.Pfx)); File.WriteAllBytes(https.PublicCertFile, certificate.Export(X509ContentType.Cert)); } try { httpsOptions.ServerCertificate = new X509Certificate2(https.PrivateCertFile); } catch (CryptographicException) { Console.Error.WriteLine("Error importing SharpBlog certificate."); } httpsOptions.SslProtocols = SslProtocols.Tls12; }); }); }); services.AddRazorPages(); services.AddServerSideBlazor() .AddHubOptions(options => { options.EnableDetailedErrors = true; options.MaximumReceiveMessageSize = 10 * 1024 * 1024; }); services.AddAntDesign(); services.AddScoped <AuthenticationStateProvider, OAuthService>(); services.Configure <ProSettings>(x => { x.Title = blog.Title; x.NavTheme = "light"; x.Layout = "mix"; x.PrimaryColor = "daybreak"; x.ContentWidth = "Fluid"; x.HeaderHeight = 50; }); services.AddHttpClient("api", x => { x.BaseAddress = new Uri(blog.ApiUrl); }).ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler { ServerCertificateCustomValidationCallback = (httpRequestMessage, cert, cetChain, policyErrors) => { return(true); } }); }).UseSerilog();
// full: delete diff post for api remote public async Task Push(string name = "", bool full = false) { if (string.IsNullOrEmpty(name)) { name = Option.CurrentRemote; } Logger.LogInformation($"Push to remote {name}."); if (Option.Remotes.TryGetValue(name, out var remote)) { Logger.LogInformation($"Detect remote {remote.Name} ({Enum.GetName(typeof(RemoteType), remote.Type)})."); switch (remote.Type) { case RemoteType.LocalFS: { await toLocalFS(remote); } break; case RemoteType.RemoteFS: { throw new NotSupportedException("Not support pushing to remote file system, please push to local file system and sync to remote."); } case RemoteType.Api: { await Connect(name); Logger.LogInformation($"Fetch remote posts."); HashSet <string> remoteIds = (await Remote.PostService.All()).ToHashSet(); foreach (var item in await Local.PostService.GetAllPosts()) { if (item is null) { continue; } Logger.LogInformation($"Loaded {item.Id}: {item.Title}"); if (remoteIds.Contains(item.Id)) { var result = await Remote.PostService.Update(item); if (result) { Logger.LogInformation($"Updated {item.Id}"); } else { Logger.LogError($"Failed to update {item.Id}"); } } else { var result = await Remote.PostService.Create(item); if (result is null) { Logger.LogError($"Failed to create {item.Id}"); } else { Logger.LogInformation($"Created {item.Id}"); } } remoteIds.Remove(item.Id); } if (full) { foreach (var v in remoteIds) { var result = await Remote.PostService.Delete(v); if (result) { Logger.LogInformation($"Deleted {v}."); } else { Logger.LogError($"Failed to deleted {v}."); } } } } break; case RemoteType.Git: { await Connect(name); string tempDist = Path.Join(Environment.CurrentDirectory, "temp/dist"); Logger.LogInformation("Generate data."); await toLocalFS(new RemoteOption { Uri = tempDist, Type = RemoteType.LocalFS, Name = remote.Name }); FSExtensions.CopyDirectory(tempDist, GitTempFolder); Logger.LogInformation("Load git config."); string userName = Option.Properties[$"remote.{remote.Name}.git.username"], password = Option.Properties[$"remote.{remote.Name}.git.password"]; { if (string.IsNullOrEmpty(userName)) { userName = ConsoleExtensions.Input("Input username: "******"Input password: "******"Commit to git."); LibGit2Sharp.Commands.Stage(repo, "*"); var signature = new LibGit2Sharp.Signature( new Identity("AcBlog.Tools.Sdk", "tools.sdk@acblog"), DateTimeOffset.Now); repo.Commit(DateTimeOffset.Now.ToString(), signature, signature, new CommitOptions { AllowEmptyCommit = true }); Logger.LogInformation($"Push to {repo.Head.RemoteName}."); PushOptions options = new LibGit2Sharp.PushOptions(); options.CredentialsProvider = new CredentialsHandler( (url, usernameFromUrl, types) => new UsernamePasswordCredentials() { Username = string.IsNullOrEmpty(userName) ? usernameFromUrl : userName, Password = password }); repo.Network.Push(repo.Head, options); } } break; } } else { throw new Exception("No remote"); } async Task toLocalFS(RemoteOption remote) { FSBuilder fsBuilder = new FSBuilder(remote.Uri); fsBuilder.EnsureDirectoryEmpty(); List <Post> posts = new List <Post>(); foreach (var item in await Local.PostService.GetAllPosts()) { if (item is null) { continue; } Logger.LogInformation($"Loaded {item.Id}: {item.Title}"); posts.Add(item); } Logger.LogInformation("Build data."); { BlogOptions options = await Local.GetOptions(); BlogBuilder builder = new BlogBuilder(options, Path.Join(remote.Uri)); await builder.Build(); } { PostRepositoryBuilder builder = new PostRepositoryBuilder(posts, Path.Join(remote.Uri, "posts")); await builder.Build(); } { var baseAddress = Option.Properties[$"remote.{remote.Name}.generator.baseAddress"]; if (!string.IsNullOrEmpty(baseAddress)) { Logger.LogInformation("Build sitemap."); var sub = fsBuilder.CreateSubDirectoryBuilder("Site"); { var siteMapBuilder = await Local.BuildSitemap(baseAddress); using var st = sub.GetFileRewriteStream("sitemap.xml"); using var writer = XmlWriter.Create(st); siteMapBuilder.Build().WriteTo(writer); } Logger.LogInformation("Build feed."); { var feed = await Local.BuildSyndication(baseAddress); using var st = sub.GetFileRewriteStream("atom.xml"); using var writer = XmlWriter.Create(st); feed.GetAtom10Formatter().WriteTo(writer); } } } } }