Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add for #7 - new configuration for dev only * add for #22 - remove properties * add for #9 - email client * add for #8 - cleanup csproj files * for #8 and #9 (#24) * add for #9 - email client * add for #8 - cleanup csproj files * add for #4 - support SASS * add for #1 - subscribe * add for #12 * add for #15 - post metadata * add for #19 * add for #17 * ::SERVER:: :bot: update posts from server, @2019/10/2 21:58:15 * add for #25 - remove octokit * add for #10 * add for #20 * add for #5 - redesign UI * add for #10 - refactor html headers * add for #10 - add sitemap * add for #21 - validate github hook * add for #10 - refactor * add for #10 - optimize scripts and styles * add for #10 - optimize for github hook * add for #10 - post hosted service executed at midnignt * add for #22 - cleanup gitignot * add for #10 - optimize * add for #10 fix feed issues introduce ga-lite.js add logging * add for #10 optimize * add for #10 - optimze * add for #10 fix issues * Finalize V2 For #11 - add README and LICENSE For #10 - A lot of refactors and changes For #13 - Simply log to system * fix merge issues
- Loading branch information
Showing
1,998 changed files
with
214,648 additions
and
12,690 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
Source of building my personal websites. | ||
|
||
There are three branches for different purposes: | ||
|
||
- master: This is the source for production environment, running at https://blog.laobian.me | ||
- stage: This is the source for staging environment. While new development is kicked off, we can reach it at https://stage.blog.laobian.me. Having said that, it was disabled by default. | ||
- dev: This is the latest source code for development. | ||
|
||
### Build | ||
|
||
Clone repository to locally. You need tools like Microsoft Visual Studio 2019+, and npm, they will be used in normal development. | ||
|
||
Before building the source, make sure you have .NET Core 3.0 installed. | ||
|
||
```cs | ||
dotnet --info | ||
``` | ||
|
||
Now just start the msbuild, either in the CLI or visual studio. | ||
|
||
For the assets configuration, you can just refer to the code... | ||
|
||
### License | ||
|
||
MIT. |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,77 +1,123 @@ | ||
using System; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Security.Cryptography; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using Laobian.Share.BlogEngine; | ||
using Laobian.Share.Infrastructure.GitHub; | ||
using Laobian.Share.Config; | ||
using Laobian.Share.Helper; | ||
using Laobian.Share.Infrastructure.Git; | ||
using Microsoft.AspNetCore.Mvc; | ||
using Microsoft.Extensions.Logging; | ||
using Microsoft.Extensions.Options; | ||
|
||
namespace Laobian.Blog.Controllers | ||
{ | ||
[ApiController] | ||
[Route("github")] | ||
public class GitHubController : ControllerBase | ||
{ | ||
private readonly AppConfig _appConfig; | ||
private readonly IBlogService _blogService; | ||
private readonly ILogger<GitHubController> _logger; | ||
|
||
public GitHubController(IBlogService blogService) | ||
public GitHubController(IBlogService blogService, IOptions<AppConfig> appConfig, ILogger<GitHubController> logger) | ||
{ | ||
_logger = logger; | ||
_blogService = blogService; | ||
_appConfig = appConfig.Value; | ||
} | ||
|
||
// http://michaco.net/blog/HowToValidateGitHubWebhooksInCSharpWithASPNETCoreMVC | ||
[HttpPost] | ||
[Route("hook")] | ||
public async Task<IActionResult> Hook(GitHubPayload payload) | ||
public async Task<IActionResult> Hook() | ||
{ | ||
if (!Request.Headers.ContainsKey("X-GitHub-Event")) | ||
if (!Request.Headers.ContainsKey("X-GitHub-Event") || | ||
!Request.Headers.ContainsKey("X-Hub-Signature") || | ||
!Request.Headers.ContainsKey("X-GitHub-Delivery")) | ||
{ | ||
return BadRequest(); | ||
_logger.LogWarning("Headers are not completed."); | ||
return BadRequest("Invalid Request."); | ||
} | ||
var gitHubEvent = Request.Headers["X-GitHub-Event"]; | ||
if (!string.Equals("push", gitHubEvent, StringComparison.OrdinalIgnoreCase)) | ||
|
||
if (!StringEqualsHelper.IgnoreCase("push", Request.Headers["X-GitHub-Event"])) | ||
{ | ||
return BadRequest(); | ||
_logger.LogWarning("Invalid github event {Event}", Request.Headers["X-GitHub-Event"]); | ||
return BadRequest("Only support push event."); | ||
} | ||
|
||
if (!Request.Headers.ContainsKey("X-Hub-Signature")) | ||
var signature = Request.Headers["X-Hub-Signature"].ToString(); | ||
if (!signature.StartsWith("sha1=", StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
return BadRequest(); | ||
_logger.LogWarning("Invalid github signature {Signature}", signature); | ||
return BadRequest("Invalid signature."); | ||
} | ||
|
||
using (var sha1 = SHA1.Create()) | ||
using (var reader = new StreamReader(Request.Body)) | ||
{ | ||
var hash = sha1.ComputeHash(Encoding.UTF8.GetBytes("abc")); | ||
var a = Convert.ToBase64String(hash); | ||
var d = string.Concat(hash.Select(b => b.ToString("x2"))); | ||
var body = await reader.ReadToEndAsync(); | ||
signature = signature.Substring("sha1=".Length); | ||
var secret = Encoding.UTF8.GetBytes(_appConfig.AssetGitHubHookSecret); | ||
var bodyBytes = Encoding.UTF8.GetBytes(body); | ||
|
||
} | ||
//if(!string.Equals()) | ||
using (var hmacSha1 = new HMACSHA1(secret)) | ||
{ | ||
var hash = hmacSha1.ComputeHash(bodyBytes); | ||
var builder = new StringBuilder(hash.Length * 2); | ||
foreach (var b in hash) | ||
{ | ||
builder.AppendFormat("{0:x2}", b); | ||
} | ||
|
||
if (payload.Commits.Any(_ => GitHubMessageProvider.IsServerCommit(_.Message))) | ||
{ | ||
return Ok("Server update, no need to update local."); | ||
} | ||
var hashStr = builder.ToString(); | ||
|
||
await _blogService.UpdateLocalAssetsAsync(); | ||
if (!hashStr.Equals(signature)) | ||
{ | ||
_logger.LogWarning("Invalid github signature {Signature}, {HashString}", signature, hashStr); | ||
return BadRequest("Invalid signature."); | ||
} | ||
} | ||
|
||
var modifiedPosts = payload.Commits.SelectMany(c => c.Modified).ToList(); | ||
if (modifiedPosts.Any()) | ||
{ | ||
var posts = _blogService.GetPosts(); | ||
foreach (var blogPost in posts) | ||
var payload = SerializeHelper.FromJson<GitHubPayload>(body); | ||
if (payload.Commits.Any(c => | ||
StringEqualsHelper.IgnoreCase(_appConfig.AssetGitCommitEmail, c.Author.Email) && | ||
StringEqualsHelper.IgnoreCase(_appConfig.AssetGitCommitUser, c.Author.User))) | ||
{ | ||
var modifiedPost = modifiedPosts.FirstOrDefault(p => | ||
string.Equals(p, blogPost.GitHubPath, StringComparison.OrdinalIgnoreCase)); | ||
if (modifiedPost != null) | ||
_logger.LogInformation("Got request from server, no need to refresh."); | ||
return Ok("No need to refresh."); | ||
} | ||
|
||
var modifiedPosts = payload.Commits.SelectMany(c => c.Modified).Distinct().ToList(); | ||
await _blogService.UpdateMemoryAssetsAsync(); | ||
_logger.LogInformation("Local assets refreshed."); | ||
|
||
bool requireCommit = false; | ||
|
||
if (modifiedPosts.Any()) | ||
{ | ||
var posts = _blogService.GetPosts(); | ||
foreach (var blogPost in posts) | ||
{ | ||
blogPost.LastUpdateTimeUtc = DateTime.UtcNow; | ||
var modifiedPost = modifiedPosts.FirstOrDefault(p => | ||
string.Equals(p, blogPost.GitHubPath, StringComparison.OrdinalIgnoreCase)); | ||
if (modifiedPost != null) | ||
{ | ||
requireCommit = true; | ||
blogPost.LastUpdateTimeUtc = DateTime.UtcNow; | ||
} | ||
} | ||
} | ||
} | ||
|
||
return Ok("Local updated."); | ||
if (requireCommit || payload.Commits.SelectMany(c => c.Added).Any()) | ||
{ | ||
await _blogService.UpdateCloudAssetsAsync(); | ||
_logger.LogInformation("Cloud assets updated."); | ||
} | ||
|
||
return Ok("Local updated."); | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.