diff options
author | unknown <crupest@outlook.com> | 2019-08-07 17:38:56 +0800 |
---|---|---|
committer | unknown <crupest@outlook.com> | 2019-08-07 17:38:56 +0800 |
commit | 29bd71cd93b03248254f341aff9252374abc74ec (patch) | |
tree | df5d1325c3b73b17f4f86b71097775e9ce3fa122 | |
parent | 0c0e0c963458aae3ba9589622fc688388833fa9c (diff) | |
download | timeline-29bd71cd93b03248254f341aff9252374abc74ec.tar.gz timeline-29bd71cd93b03248254f341aff9252374abc74ec.tar.bz2 timeline-29bd71cd93b03248254f341aff9252374abc74ec.zip |
Add script to convert encoding and eof. And of course run it.
46 files changed, 1552 insertions, 1511 deletions
diff --git a/.vscode/launch.json b/.vscode/launch.json index bb765851..74744083 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,9 +1,16 @@ { - // Use IntelliSense to find out which attributes exist for C# debugging - // Use hover for the description of the existing attributes - // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md - "version": "0.2.0", - "configurations": [ + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Current File", + "type": "python", + "request": "launch", + "program": "${file}", + "console": "integratedTerminal" + }, { "name": ".NET Core Launch (web)", "type": "coreclr", diff --git a/Timeline.Tests/AuthorizationUnitTest.cs b/Timeline.Tests/AuthorizationUnitTest.cs index a25a8f9b..8df23c45 100644 --- a/Timeline.Tests/AuthorizationUnitTest.cs +++ b/Timeline.Tests/AuthorizationUnitTest.cs @@ -1,68 +1,68 @@ -using Microsoft.AspNetCore.Mvc.Testing; -using System.Net; -using System.Threading.Tasks; -using Timeline.Tests.Helpers; -using Timeline.Tests.Helpers.Authentication; -using Xunit; -using Xunit.Abstractions; - -namespace Timeline.Tests -{ - public class AuthorizationUnitTest : IClassFixture<MyWebApplicationFactory<Startup>> - { - private const string AuthorizeUrl = "Test/User/Authorize"; - private const string UserUrl = "Test/User/User"; - private const string AdminUrl = "Test/User/Admin"; - - private readonly WebApplicationFactory<Startup> _factory; - - public AuthorizationUnitTest(MyWebApplicationFactory<Startup> factory, ITestOutputHelper outputHelper) - { - _factory = factory.WithTestLogging(outputHelper); - } - - [Fact] - public async Task UnauthenticationTest() - { - using (var client = _factory.CreateDefaultClient()) - { - var response = await client.GetAsync(AuthorizeUrl); - Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); - } - } - - [Fact] - public async Task AuthenticationTest() - { - using (var client = await _factory.CreateClientWithUser("user", "user")) - { - var response = await client.GetAsync(AuthorizeUrl); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - } - } - - [Fact] - public async Task UserAuthorizationTest() - { - using (var client = await _factory.CreateClientWithUser("user", "user")) - { - var response1 = await client.GetAsync(UserUrl); - Assert.Equal(HttpStatusCode.OK, response1.StatusCode); - var response2 = await client.GetAsync(AdminUrl); - Assert.Equal(HttpStatusCode.Forbidden, response2.StatusCode); - } - } - - [Fact] - public async Task AdminAuthorizationTest() - { - using (var client = await _factory.CreateClientWithUser("admin", "admin")) - { - var response1 = await client.GetAsync(UserUrl); - Assert.Equal(HttpStatusCode.OK, response1.StatusCode); - var response2 = await client.GetAsync(AdminUrl); - Assert.Equal(HttpStatusCode.OK, response2.StatusCode); - } - } - } -} +using Microsoft.AspNetCore.Mvc.Testing;
+using System.Net;
+using System.Threading.Tasks;
+using Timeline.Tests.Helpers;
+using Timeline.Tests.Helpers.Authentication;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace Timeline.Tests
+{
+ public class AuthorizationUnitTest : IClassFixture<MyWebApplicationFactory<Startup>>
+ {
+ private const string AuthorizeUrl = "Test/User/Authorize";
+ private const string UserUrl = "Test/User/User";
+ private const string AdminUrl = "Test/User/Admin";
+
+ private readonly WebApplicationFactory<Startup> _factory;
+
+ public AuthorizationUnitTest(MyWebApplicationFactory<Startup> factory, ITestOutputHelper outputHelper)
+ {
+ _factory = factory.WithTestLogging(outputHelper);
+ }
+
+ [Fact]
+ public async Task UnauthenticationTest()
+ {
+ using (var client = _factory.CreateDefaultClient())
+ {
+ var response = await client.GetAsync(AuthorizeUrl);
+ Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
+ }
+ }
+
+ [Fact]
+ public async Task AuthenticationTest()
+ {
+ using (var client = await _factory.CreateClientWithUser("user", "user"))
+ {
+ var response = await client.GetAsync(AuthorizeUrl);
+ Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+ }
+ }
+
+ [Fact]
+ public async Task UserAuthorizationTest()
+ {
+ using (var client = await _factory.CreateClientWithUser("user", "user"))
+ {
+ var response1 = await client.GetAsync(UserUrl);
+ Assert.Equal(HttpStatusCode.OK, response1.StatusCode);
+ var response2 = await client.GetAsync(AdminUrl);
+ Assert.Equal(HttpStatusCode.Forbidden, response2.StatusCode);
+ }
+ }
+
+ [Fact]
+ public async Task AdminAuthorizationTest()
+ {
+ using (var client = await _factory.CreateClientWithUser("admin", "admin"))
+ {
+ var response1 = await client.GetAsync(UserUrl);
+ Assert.Equal(HttpStatusCode.OK, response1.StatusCode);
+ var response2 = await client.GetAsync(AdminUrl);
+ Assert.Equal(HttpStatusCode.OK, response2.StatusCode);
+ }
+ }
+ }
+}
diff --git a/Timeline.Tests/Helpers/Authentication/AuthenticationExtensions.cs b/Timeline.Tests/Helpers/Authentication/AuthenticationExtensions.cs index 27362ac3..c8bec266 100644 --- a/Timeline.Tests/Helpers/Authentication/AuthenticationExtensions.cs +++ b/Timeline.Tests/Helpers/Authentication/AuthenticationExtensions.cs @@ -1,28 +1,28 @@ -using Microsoft.AspNetCore.Mvc.Testing; -using Newtonsoft.Json; -using System.Net.Http; -using System.Threading.Tasks; -using Timeline.Entities.Http; - -namespace Timeline.Tests.Helpers.Authentication -{ - public static class AuthenticationExtensions - { - private const string CreateTokenUrl = "/token/create"; - - public static async Task<CreateTokenResponse> CreateUserTokenAsync(this HttpClient client, string username, string password, double? expireOffset = null) - { - var response = await client.PostAsJsonAsync(CreateTokenUrl, new CreateTokenRequest { Username = username, Password = password, ExpireOffset = expireOffset }); - var result = JsonConvert.DeserializeObject<CreateTokenResponse>(await response.Content.ReadAsStringAsync()); - return result; - } - - public static async Task<HttpClient> CreateClientWithUser<T>(this WebApplicationFactory<T> factory, string username, string password) where T : class - { - var client = factory.CreateDefaultClient(); - var token = (await client.CreateUserTokenAsync(username, password)).Token; - client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token); - return client; - } - } -} +using Microsoft.AspNetCore.Mvc.Testing;
+using Newtonsoft.Json;
+using System.Net.Http;
+using System.Threading.Tasks;
+using Timeline.Entities.Http;
+
+namespace Timeline.Tests.Helpers.Authentication
+{
+ public static class AuthenticationExtensions
+ {
+ private const string CreateTokenUrl = "/token/create";
+
+ public static async Task<CreateTokenResponse> CreateUserTokenAsync(this HttpClient client, string username, string password, double? expireOffset = null)
+ {
+ var response = await client.PostAsJsonAsync(CreateTokenUrl, new CreateTokenRequest { Username = username, Password = password, ExpireOffset = expireOffset });
+ var result = JsonConvert.DeserializeObject<CreateTokenResponse>(await response.Content.ReadAsStringAsync());
+ return result;
+ }
+
+ public static async Task<HttpClient> CreateClientWithUser<T>(this WebApplicationFactory<T> factory, string username, string password) where T : class
+ {
+ var client = factory.CreateDefaultClient();
+ var token = (await client.CreateUserTokenAsync(username, password)).Token;
+ client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
+ return client;
+ }
+ }
+}
diff --git a/Timeline.Tests/Helpers/MyWebApplicationFactory.cs b/Timeline.Tests/Helpers/MyWebApplicationFactory.cs index 903cd670..d9503526 100644 --- a/Timeline.Tests/Helpers/MyWebApplicationFactory.cs +++ b/Timeline.Tests/Helpers/MyWebApplicationFactory.cs @@ -1,16 +1,16 @@ -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Data.Sqlite;
-using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Timeline.Models; +using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using Timeline.Models;
using Timeline.Services;
-using Xunit.Abstractions; - -namespace Timeline.Tests.Helpers -{ +using Xunit.Abstractions;
+
+namespace Timeline.Tests.Helpers
+{
public class MyWebApplicationFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup : class
{
// We should keep the connection, so the database is persisted but not recreate every time.
@@ -65,19 +65,19 @@ namespace Timeline.Tests.Helpers base.Dispose(disposing);
}
- } - - public static class WebApplicationFactoryExtensions - { - public static WebApplicationFactory<TEntry> WithTestLogging<TEntry>(this WebApplicationFactory<TEntry> factory, ITestOutputHelper outputHelper) where TEntry : class - { - return factory.WithWebHostBuilder(builder => - { + }
+
+ public static class WebApplicationFactoryExtensions
+ {
+ public static WebApplicationFactory<TEntry> WithTestLogging<TEntry>(this WebApplicationFactory<TEntry> factory, ITestOutputHelper outputHelper) where TEntry : class
+ {
+ return factory.WithWebHostBuilder(builder =>
+ {
builder.ConfigureLogging(logging =>
{
logging.AddXunit(outputHelper);
- }); - }); - } - } -} + });
+ });
+ }
+ }
+}
diff --git a/Timeline.Tests/Helpers/ResponseExtensions.cs b/Timeline.Tests/Helpers/ResponseExtensions.cs index 86ac1c88..155836fb 100644 --- a/Timeline.Tests/Helpers/ResponseExtensions.cs +++ b/Timeline.Tests/Helpers/ResponseExtensions.cs @@ -1,14 +1,14 @@ -using Newtonsoft.Json; -using System.Net.Http; -using System.Threading.Tasks; - -namespace Timeline.Tests.Helpers -{ - public static class ResponseExtensions - { - public static async Task<T> ReadBodyAsJson<T>(this HttpResponseMessage response) - { - return JsonConvert.DeserializeObject<T>(await response.Content.ReadAsStringAsync()); - } - } -} +using Newtonsoft.Json;
+using System.Net.Http;
+using System.Threading.Tasks;
+
+namespace Timeline.Tests.Helpers
+{
+ public static class ResponseExtensions
+ {
+ public static async Task<T> ReadBodyAsJson<T>(this HttpResponseMessage response)
+ {
+ return JsonConvert.DeserializeObject<T>(await response.Content.ReadAsStringAsync());
+ }
+ }
+}
diff --git a/Timeline.Tests/Helpers/TestClock.cs b/Timeline.Tests/Helpers/TestClock.cs index 91523f2b..ea90305f 100644 --- a/Timeline.Tests/Helpers/TestClock.cs +++ b/Timeline.Tests/Helpers/TestClock.cs @@ -1,4 +1,4 @@ -using Microsoft.AspNetCore.Mvc.Testing;
+using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Extensions.DependencyInjection;
using System;
using Timeline.Services;
diff --git a/Timeline.Tests/Helpers/TestUsers.cs b/Timeline.Tests/Helpers/TestUsers.cs index 41dd83a9..71de8237 100644 --- a/Timeline.Tests/Helpers/TestUsers.cs +++ b/Timeline.Tests/Helpers/TestUsers.cs @@ -1,42 +1,42 @@ -using System.Collections.Generic; -using System.Linq; -using Timeline.Entities; -using Timeline.Models; -using Timeline.Services; - -namespace Timeline.Tests.Helpers -{ - public static class TestMockUsers - { - static TestMockUsers() - { - var mockUsers = new List<User>(); - var passwordService = new PasswordService(); - - mockUsers.Add(new User - { - Name = "user", - EncryptedPassword = passwordService.HashPassword("user"), - RoleString = UserUtility.IsAdminToRoleString(false), - Version = 0, - }); - mockUsers.Add(new User - { - Name = "admin", - EncryptedPassword = passwordService.HashPassword("admin"), - RoleString = UserUtility.IsAdminToRoleString(true), - Version = 0, - }); - - MockUsers = mockUsers; - - var mockUserInfos = mockUsers.Select(u => UserUtility.CreateUserInfo(u)).ToList(); - mockUserInfos.Sort(UserInfoComparers.Comparer); - MockUserInfos = mockUserInfos; - } - - public static List<User> MockUsers { get; } - - public static IReadOnlyList<UserInfo> MockUserInfos { get; } - } -} +using System.Collections.Generic;
+using System.Linq;
+using Timeline.Entities;
+using Timeline.Models;
+using Timeline.Services;
+
+namespace Timeline.Tests.Helpers
+{
+ public static class TestMockUsers
+ {
+ static TestMockUsers()
+ {
+ var mockUsers = new List<User>();
+ var passwordService = new PasswordService();
+
+ mockUsers.Add(new User
+ {
+ Name = "user",
+ EncryptedPassword = passwordService.HashPassword("user"),
+ RoleString = UserUtility.IsAdminToRoleString(false),
+ Version = 0,
+ });
+ mockUsers.Add(new User
+ {
+ Name = "admin",
+ EncryptedPassword = passwordService.HashPassword("admin"),
+ RoleString = UserUtility.IsAdminToRoleString(true),
+ Version = 0,
+ });
+
+ MockUsers = mockUsers;
+
+ var mockUserInfos = mockUsers.Select(u => UserUtility.CreateUserInfo(u)).ToList();
+ mockUserInfos.Sort(UserInfoComparers.Comparer);
+ MockUserInfos = mockUserInfos;
+ }
+
+ public static List<User> MockUsers { get; }
+
+ public static IReadOnlyList<UserInfo> MockUserInfos { get; }
+ }
+}
diff --git a/Timeline.Tests/Helpers/UserInfoComparers.cs b/Timeline.Tests/Helpers/UserInfoComparers.cs index fcf37e5c..c7c584b7 100644 --- a/Timeline.Tests/Helpers/UserInfoComparers.cs +++ b/Timeline.Tests/Helpers/UserInfoComparers.cs @@ -1,47 +1,47 @@ -using System.Collections.Generic; -using Timeline.Entities; - -namespace Timeline.Tests.Helpers -{ - public static class UserInfoComparers - { - public static IEqualityComparer<UserInfo> EqualityComparer { get; } = new EqualityComparerImpl(); - public static IComparer<UserInfo> Comparer { get; } = Comparer<UserInfo>.Create(Compare); - - - private class EqualityComparerImpl : IEqualityComparer<UserInfo> - { - bool IEqualityComparer<UserInfo>.Equals(UserInfo x, UserInfo y) - { - return Compare(x, y) == 0; - } - - int IEqualityComparer<UserInfo>.GetHashCode(UserInfo obj) - { - return obj.Username.GetHashCode() ^ obj.Administrator.GetHashCode(); - } - } - - public static int Compare(UserInfo left, UserInfo right) - { - if (left == null) - { - if (right == null) - return 0; - return -1; - } - - if (right == null) - return 1; - - var uc = string.Compare(left.Username, right.Username); - if (uc != 0) - return uc; - - if (left.Administrator == right.Administrator) - return 0; - - return left.Administrator ? -1 : 1; - } - } -} +using System.Collections.Generic;
+using Timeline.Entities;
+
+namespace Timeline.Tests.Helpers
+{
+ public static class UserInfoComparers
+ {
+ public static IEqualityComparer<UserInfo> EqualityComparer { get; } = new EqualityComparerImpl();
+ public static IComparer<UserInfo> Comparer { get; } = Comparer<UserInfo>.Create(Compare);
+
+
+ private class EqualityComparerImpl : IEqualityComparer<UserInfo>
+ {
+ bool IEqualityComparer<UserInfo>.Equals(UserInfo x, UserInfo y)
+ {
+ return Compare(x, y) == 0;
+ }
+
+ int IEqualityComparer<UserInfo>.GetHashCode(UserInfo obj)
+ {
+ return obj.Username.GetHashCode() ^ obj.Administrator.GetHashCode();
+ }
+ }
+
+ public static int Compare(UserInfo left, UserInfo right)
+ {
+ if (left == null)
+ {
+ if (right == null)
+ return 0;
+ return -1;
+ }
+
+ if (right == null)
+ return 1;
+
+ var uc = string.Compare(left.Username, right.Username);
+ if (uc != 0)
+ return uc;
+
+ if (left.Administrator == right.Administrator)
+ return 0;
+
+ return left.Administrator ? -1 : 1;
+ }
+ }
+}
diff --git a/Timeline.Tests/Timeline.Tests.csproj b/Timeline.Tests/Timeline.Tests.csproj index 854c63ac..8cc304f4 100644 --- a/Timeline.Tests/Timeline.Tests.csproj +++ b/Timeline.Tests/Timeline.Tests.csproj @@ -1,4 +1,4 @@ -<Project Sdk="Microsoft.NET.Sdk.Web">
+<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
diff --git a/Timeline.Tests/TokenUnitTest.cs b/Timeline.Tests/TokenUnitTest.cs index 7b83cd13..f942767d 100644 --- a/Timeline.Tests/TokenUnitTest.cs +++ b/Timeline.Tests/TokenUnitTest.cs @@ -1,4 +1,4 @@ -using Microsoft.AspNetCore.Mvc.Testing;
+using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using System;
diff --git a/Timeline.Tests/UserUnitTest.cs b/Timeline.Tests/UserUnitTest.cs index b3377f7b..de429c7f 100644 --- a/Timeline.Tests/UserUnitTest.cs +++ b/Timeline.Tests/UserUnitTest.cs @@ -1,36 +1,36 @@ -using Microsoft.AspNetCore.Mvc.Testing; -using Newtonsoft.Json; -using System.Linq; -using System.Net; -using System.Threading.Tasks; -using Timeline.Entities; -using Timeline.Tests.Helpers; -using Timeline.Tests.Helpers.Authentication; -using Xunit; -using Xunit.Abstractions; - -namespace Timeline.Tests -{ - public class UserUnitTest : IClassFixture<MyWebApplicationFactory<Startup>> - { - private readonly WebApplicationFactory<Startup> _factory; - - public UserUnitTest(MyWebApplicationFactory<Startup> factory, ITestOutputHelper outputHelper) - { - _factory = factory.WithTestLogging(outputHelper); - } - - [Fact] - public async Task UserTest() - { - using (var client = await _factory.CreateClientWithUser("admin", "admin")) - { - var res1 = await client.GetAsync("users"); - Assert.Equal(HttpStatusCode.OK, res1.StatusCode); - var users = JsonConvert.DeserializeObject<UserInfo[]>(await res1.Content.ReadAsStringAsync()).ToList(); - users.Sort(UserInfoComparers.Comparer); - Assert.Equal(TestMockUsers.MockUserInfos, users, UserInfoComparers.EqualityComparer); - } - } - } -} +using Microsoft.AspNetCore.Mvc.Testing;
+using Newtonsoft.Json;
+using System.Linq;
+using System.Net;
+using System.Threading.Tasks;
+using Timeline.Entities;
+using Timeline.Tests.Helpers;
+using Timeline.Tests.Helpers.Authentication;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace Timeline.Tests
+{
+ public class UserUnitTest : IClassFixture<MyWebApplicationFactory<Startup>>
+ {
+ private readonly WebApplicationFactory<Startup> _factory;
+
+ public UserUnitTest(MyWebApplicationFactory<Startup> factory, ITestOutputHelper outputHelper)
+ {
+ _factory = factory.WithTestLogging(outputHelper);
+ }
+
+ [Fact]
+ public async Task UserTest()
+ {
+ using (var client = await _factory.CreateClientWithUser("admin", "admin"))
+ {
+ var res1 = await client.GetAsync("users");
+ Assert.Equal(HttpStatusCode.OK, res1.StatusCode);
+ var users = JsonConvert.DeserializeObject<UserInfo[]>(await res1.Content.ReadAsStringAsync()).ToList();
+ users.Sort(UserInfoComparers.Comparer);
+ Assert.Equal(TestMockUsers.MockUserInfos, users, UserInfoComparers.EqualityComparer);
+ }
+ }
+ }
+}
diff --git a/Timeline.sln b/Timeline.sln index 9d041499..055989e9 100644 --- a/Timeline.sln +++ b/Timeline.sln @@ -1,31 +1,30 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.28307.271 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Timeline", "Timeline\Timeline.csproj", "{A34D323C-5233-4754-B14F-4819CE9C27CA}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Timeline.Tests", "Timeline.Tests\Timeline.Tests.csproj", "{3D76D578-37BC-43C2-97BF-9C6DD3825F10}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {A34D323C-5233-4754-B14F-4819CE9C27CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A34D323C-5233-4754-B14F-4819CE9C27CA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A34D323C-5233-4754-B14F-4819CE9C27CA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A34D323C-5233-4754-B14F-4819CE9C27CA}.Release|Any CPU.Build.0 = Release|Any CPU - {3D76D578-37BC-43C2-97BF-9C6DD3825F10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3D76D578-37BC-43C2-97BF-9C6DD3825F10}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3D76D578-37BC-43C2-97BF-9C6DD3825F10}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3D76D578-37BC-43C2-97BF-9C6DD3825F10}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {9A7526E5-E68F-465C-9E0F-88BF6E040F14} - EndGlobalSection -EndGlobal +Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.28307.271
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Timeline", "Timeline\Timeline.csproj", "{A34D323C-5233-4754-B14F-4819CE9C27CA}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Timeline.Tests", "Timeline.Tests\Timeline.Tests.csproj", "{3D76D578-37BC-43C2-97BF-9C6DD3825F10}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {A34D323C-5233-4754-B14F-4819CE9C27CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A34D323C-5233-4754-B14F-4819CE9C27CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A34D323C-5233-4754-B14F-4819CE9C27CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A34D323C-5233-4754-B14F-4819CE9C27CA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3D76D578-37BC-43C2-97BF-9C6DD3825F10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3D76D578-37BC-43C2-97BF-9C6DD3825F10}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3D76D578-37BC-43C2-97BF-9C6DD3825F10}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3D76D578-37BC-43C2-97BF-9C6DD3825F10}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {9A7526E5-E68F-465C-9E0F-88BF6E040F14}
+ EndGlobalSection
+EndGlobal
diff --git a/Timeline/Authenticate/Attribute.cs b/Timeline/Authenticate/Attribute.cs index 50b2681d..1875a21b 100644 --- a/Timeline/Authenticate/Attribute.cs +++ b/Timeline/Authenticate/Attribute.cs @@ -1,21 +1,21 @@ -using Microsoft.AspNetCore.Authorization; -using Timeline.Models; - -namespace Timeline.Authenticate -{ - public class AdminAuthorizeAttribute : AuthorizeAttribute - { - public AdminAuthorizeAttribute() - { - Roles = UserRoles.Admin; - } - } - - public class UserAuthorizeAttribute : AuthorizeAttribute - { - public UserAuthorizeAttribute() - { - Roles = UserRoles.User; - } - } -} +using Microsoft.AspNetCore.Authorization;
+using Timeline.Models;
+
+namespace Timeline.Authenticate
+{
+ public class AdminAuthorizeAttribute : AuthorizeAttribute
+ {
+ public AdminAuthorizeAttribute()
+ {
+ Roles = UserRoles.Admin;
+ }
+ }
+
+ public class UserAuthorizeAttribute : AuthorizeAttribute
+ {
+ public UserAuthorizeAttribute()
+ {
+ Roles = UserRoles.User;
+ }
+ }
+}
diff --git a/Timeline/Authenticate/AuthHandler.cs b/Timeline/Authenticate/AuthHandler.cs index 41cb11c6..5b26716d 100644 --- a/Timeline/Authenticate/AuthHandler.cs +++ b/Timeline/Authenticate/AuthHandler.cs @@ -1,101 +1,101 @@ -using Microsoft.AspNetCore.Authentication; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Microsoft.Net.Http.Headers; -using System; -using System.Linq; -using System.Security.Claims; -using System.Text.Encodings.Web; -using System.Threading.Tasks; -using Timeline.Services; - -namespace Timeline.Authenticate -{ - static class AuthConstants - { - public const string Scheme = "Bearer"; - public const string DisplayName = "My Jwt Auth Scheme"; - } - - class AuthOptions : AuthenticationSchemeOptions - { - /// <summary> - /// The query param key to search for token. If null then query params are not searched for token. Default to <c>"token"</c>. - /// </summary> - public string TokenQueryParamKey { get; set; } = "token"; - } - - class AuthHandler : AuthenticationHandler<AuthOptions> - { - private readonly ILogger<AuthHandler> _logger; - private readonly IUserService _userService; - - public AuthHandler(IOptionsMonitor<AuthOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, IUserService userService) - : base(options, logger, encoder, clock) - { - _logger = logger.CreateLogger<AuthHandler>(); - _userService = userService; - } - - // return null if no token is found - private string ExtractToken() - { - // check the authorization header - string header = Request.Headers[HeaderNames.Authorization]; - if (!string.IsNullOrEmpty(header) && header.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase)) - { - var token = header.Substring("Bearer ".Length).Trim(); - _logger.LogInformation("Token is found in authorization header. Token is {} .", token); - return token; - } - - // check the query params - var paramQueryKey = Options.TokenQueryParamKey; - if (!string.IsNullOrEmpty(paramQueryKey)) - { - string token = Request.Query[paramQueryKey]; - if (!string.IsNullOrEmpty(token)) - { - _logger.LogInformation("Token is found in query param with key \"{}\". Token is {} .", paramQueryKey, token); - return token; - } - } - - // not found anywhere then return null - return null; - } - - protected override async Task<AuthenticateResult> HandleAuthenticateAsync() - { - var token = ExtractToken(); - if (string.IsNullOrEmpty(token)) - { - _logger.LogInformation("No jwt token is found."); - return AuthenticateResult.NoResult(); - } - - try - { - var userInfo = await _userService.VerifyToken(token); - - var identity = new ClaimsIdentity(AuthConstants.Scheme); - identity.AddClaim(new Claim(identity.NameClaimType, userInfo.Username, ClaimValueTypes.String)); - identity.AddClaims(Entities.UserUtility.IsAdminToRoleArray(userInfo.Administrator).Select(role => new Claim(identity.RoleClaimType, role, ClaimValueTypes.String))); - - var principal = new ClaimsPrincipal(); - principal.AddIdentity(identity); - - return AuthenticateResult.Success(new AuthenticationTicket(principal, AuthConstants.Scheme)); - } - catch (ArgumentException) - { - throw; // this exception usually means server error. - } - catch (Exception e) - { - _logger.LogInformation(e, "A jwt token validation failed."); - return AuthenticateResult.Fail(e); - } - } - } -} +using Microsoft.AspNetCore.Authentication;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using Microsoft.Net.Http.Headers;
+using System;
+using System.Linq;
+using System.Security.Claims;
+using System.Text.Encodings.Web;
+using System.Threading.Tasks;
+using Timeline.Services;
+
+namespace Timeline.Authenticate
+{
+ static class AuthConstants
+ {
+ public const string Scheme = "Bearer";
+ public const string DisplayName = "My Jwt Auth Scheme";
+ }
+
+ class AuthOptions : AuthenticationSchemeOptions
+ {
+ /// <summary>
+ /// The query param key to search for token. If null then query params are not searched for token. Default to <c>"token"</c>.
+ /// </summary>
+ public string TokenQueryParamKey { get; set; } = "token";
+ }
+
+ class AuthHandler : AuthenticationHandler<AuthOptions>
+ {
+ private readonly ILogger<AuthHandler> _logger;
+ private readonly IUserService _userService;
+
+ public AuthHandler(IOptionsMonitor<AuthOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, IUserService userService)
+ : base(options, logger, encoder, clock)
+ {
+ _logger = logger.CreateLogger<AuthHandler>();
+ _userService = userService;
+ }
+
+ // return null if no token is found
+ private string ExtractToken()
+ {
+ // check the authorization header
+ string header = Request.Headers[HeaderNames.Authorization];
+ if (!string.IsNullOrEmpty(header) && header.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
+ {
+ var token = header.Substring("Bearer ".Length).Trim();
+ _logger.LogInformation("Token is found in authorization header. Token is {} .", token);
+ return token;
+ }
+
+ // check the query params
+ var paramQueryKey = Options.TokenQueryParamKey;
+ if (!string.IsNullOrEmpty(paramQueryKey))
+ {
+ string token = Request.Query[paramQueryKey];
+ if (!string.IsNullOrEmpty(token))
+ {
+ _logger.LogInformation("Token is found in query param with key \"{}\". Token is {} .", paramQueryKey, token);
+ return token;
+ }
+ }
+
+ // not found anywhere then return null
+ return null;
+ }
+
+ protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
+ {
+ var token = ExtractToken();
+ if (string.IsNullOrEmpty(token))
+ {
+ _logger.LogInformation("No jwt token is found.");
+ return AuthenticateResult.NoResult();
+ }
+
+ try
+ {
+ var userInfo = await _userService.VerifyToken(token);
+
+ var identity = new ClaimsIdentity(AuthConstants.Scheme);
+ identity.AddClaim(new Claim(identity.NameClaimType, userInfo.Username, ClaimValueTypes.String));
+ identity.AddClaims(Entities.UserUtility.IsAdminToRoleArray(userInfo.Administrator).Select(role => new Claim(identity.RoleClaimType, role, ClaimValueTypes.String)));
+
+ var principal = new ClaimsPrincipal();
+ principal.AddIdentity(identity);
+
+ return AuthenticateResult.Success(new AuthenticationTicket(principal, AuthConstants.Scheme));
+ }
+ catch (ArgumentException)
+ {
+ throw; // this exception usually means server error.
+ }
+ catch (Exception e)
+ {
+ _logger.LogInformation(e, "A jwt token validation failed.");
+ return AuthenticateResult.Fail(e);
+ }
+ }
+ }
+}
diff --git a/Timeline/Configs/DatabaseConfig.cs b/Timeline/Configs/DatabaseConfig.cs index 05dc630e..e24ecdfb 100644 --- a/Timeline/Configs/DatabaseConfig.cs +++ b/Timeline/Configs/DatabaseConfig.cs @@ -1,7 +1,7 @@ -namespace Timeline.Configs -{ - public class DatabaseConfig - { - public string ConnectionString { get; set; } - } -} +namespace Timeline.Configs
+{
+ public class DatabaseConfig
+ {
+ public string ConnectionString { get; set; }
+ }
+}
diff --git a/Timeline/Configs/JwtConfig.cs b/Timeline/Configs/JwtConfig.cs index 4d5ef97f..8c61d7bc 100644 --- a/Timeline/Configs/JwtConfig.cs +++ b/Timeline/Configs/JwtConfig.cs @@ -1,15 +1,15 @@ -namespace Timeline.Configs -{ - public class JwtConfig - { - public string Issuer { get; set; } - public string Audience { get; set; } - public string SigningKey { get; set; } - - /// <summary> - /// Set the default value of expire offset of jwt token. - /// Unit is second. Default is 3600 * 24 seconds, aka 1 day. - /// </summary> - public long DefaultExpireOffset { get; set; } = 3600 * 24; - } -} +namespace Timeline.Configs
+{
+ public class JwtConfig
+ {
+ public string Issuer { get; set; }
+ public string Audience { get; set; }
+ public string SigningKey { get; set; }
+
+ /// <summary>
+ /// Set the default value of expire offset of jwt token.
+ /// Unit is second. Default is 3600 * 24 seconds, aka 1 day.
+ /// </summary>
+ public long DefaultExpireOffset { get; set; } = 3600 * 24;
+ }
+}
diff --git a/Timeline/Controllers/TokenController.cs b/Timeline/Controllers/TokenController.cs index 549e227b..ff397518 100644 --- a/Timeline/Controllers/TokenController.cs +++ b/Timeline/Controllers/TokenController.cs @@ -1,55 +1,55 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Logging; +using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Tokens;
-using System; +using System;
using System.Collections.Generic;
-using System.Threading.Tasks; -using Timeline.Entities.Http; -using Timeline.Services; -using static Timeline.Helpers.MyLogHelper; - -namespace Timeline.Controllers -{ - [Route("token")] - public class TokenController : Controller - { - private static class LoggingEventIds - { - public const int CreateSucceeded = 1000; - public const int CreateFailed = 1001; - - public const int VerifySucceeded = 2000; - public const int VerifyFailed = 2001; - } - - public static class ErrorCodes - { - public const int Create_UserNotExist = -1001; - public const int Create_BadPassword = -1002; - public const int Create_BadExpireOffset = -1003; - - public const int Verify_BadToken = -2001; - public const int Verify_UserNotExist = -2002; - public const int Verify_BadVersion = -2003; - public const int Verify_Expired = -2004; - } - - private readonly IUserService _userService; - private readonly ILogger<TokenController> _logger; - private readonly IClock _clock; - - public TokenController(IUserService userService, ILogger<TokenController> logger, IClock clock) - { - _userService = userService; - _logger = logger; - _clock = clock; - } - - [HttpPost("create")] - [AllowAnonymous] - public async Task<IActionResult> Create([FromBody] CreateTokenRequest request) - { +using System.Threading.Tasks;
+using Timeline.Entities.Http;
+using Timeline.Services;
+using static Timeline.Helpers.MyLogHelper;
+
+namespace Timeline.Controllers
+{
+ [Route("token")]
+ public class TokenController : Controller
+ {
+ private static class LoggingEventIds
+ {
+ public const int CreateSucceeded = 1000;
+ public const int CreateFailed = 1001;
+
+ public const int VerifySucceeded = 2000;
+ public const int VerifyFailed = 2001;
+ }
+
+ public static class ErrorCodes
+ {
+ public const int Create_UserNotExist = -1001;
+ public const int Create_BadPassword = -1002;
+ public const int Create_BadExpireOffset = -1003;
+
+ public const int Verify_BadToken = -2001;
+ public const int Verify_UserNotExist = -2002;
+ public const int Verify_BadVersion = -2003;
+ public const int Verify_Expired = -2004;
+ }
+
+ private readonly IUserService _userService;
+ private readonly ILogger<TokenController> _logger;
+ private readonly IClock _clock;
+
+ public TokenController(IUserService userService, ILogger<TokenController> logger, IClock clock)
+ {
+ _userService = userService;
+ _logger = logger;
+ _clock = clock;
+ }
+
+ [HttpPost("create")]
+ [AllowAnonymous]
+ public async Task<IActionResult> Create([FromBody] CreateTokenRequest request)
+ {
void LogFailure(string reason, int code, Exception e = null)
{
_logger.LogInformation(LoggingEventIds.CreateFailed, e, FormatLogMessage("Attemp to login failed.",
@@ -58,51 +58,51 @@ namespace Timeline.Controllers Pair("Username", request.Username),
Pair("Password", request.Password),
Pair("Expire Offset (in days)", request.ExpireOffset)));
- } - - TimeSpan? expireOffset = null; - if (request.ExpireOffset != null) - { - if (request.ExpireOffset.Value <= 0.0) - { - const string message = "Expire time is not bigger than 0."; - var code = ErrorCodes.Create_BadExpireOffset; - LogFailure(message, code); - return BadRequest(new CommonResponse(code, message)); - } - expireOffset = TimeSpan.FromDays(request.ExpireOffset.Value); - } - - try - { - var expiredTime = expireOffset == null ? null : (DateTime?)(_clock.GetCurrentTime() + expireOffset.Value); - var result = await _userService.CreateToken(request.Username, request.Password, expiredTime); + }
+
+ TimeSpan? expireOffset = null;
+ if (request.ExpireOffset != null)
+ {
+ if (request.ExpireOffset.Value <= 0.0)
+ {
+ const string message = "Expire time is not bigger than 0.";
+ var code = ErrorCodes.Create_BadExpireOffset;
+ LogFailure(message, code);
+ return BadRequest(new CommonResponse(code, message));
+ }
+ expireOffset = TimeSpan.FromDays(request.ExpireOffset.Value);
+ }
+
+ try
+ {
+ var expiredTime = expireOffset == null ? null : (DateTime?)(_clock.GetCurrentTime() + expireOffset.Value);
+ var result = await _userService.CreateToken(request.Username, request.Password, expiredTime);
_logger.LogInformation(LoggingEventIds.CreateSucceeded, FormatLogMessage("Attemp to login succeeded.",
Pair("Username", request.Username),
- Pair("Expire Time", expiredTime == null ? "default" : expiredTime.Value.ToString()))); - return Ok(new CreateTokenResponse - { - Token = result.Token, - User = result.User - }); - } - catch (UserNotExistException e) - { - var code = ErrorCodes.Create_UserNotExist; - LogFailure("User does not exist.", code, e); - return BadRequest(new CommonResponse(code, "Bad username or password.")); - } - catch (BadPasswordException e) - { - var code = ErrorCodes.Create_BadPassword; - LogFailure("Password is wrong.", code, e); - return BadRequest(new CommonResponse(code, "Bad username or password.")); - } - } - - [HttpPost("verify")] - [AllowAnonymous] - public async Task<IActionResult> Verify([FromBody] VerifyTokenRequest request) + Pair("Expire Time", expiredTime == null ? "default" : expiredTime.Value.ToString())));
+ return Ok(new CreateTokenResponse
+ {
+ Token = result.Token,
+ User = result.User
+ });
+ }
+ catch (UserNotExistException e)
+ {
+ var code = ErrorCodes.Create_UserNotExist;
+ LogFailure("User does not exist.", code, e);
+ return BadRequest(new CommonResponse(code, "Bad username or password."));
+ }
+ catch (BadPasswordException e)
+ {
+ var code = ErrorCodes.Create_BadPassword;
+ LogFailure("Password is wrong.", code, e);
+ return BadRequest(new CommonResponse(code, "Bad username or password."));
+ }
+ }
+
+ [HttpPost("verify")]
+ [AllowAnonymous]
+ public async Task<IActionResult> Verify([FromBody] VerifyTokenRequest request)
{
void LogFailure(string reason, int code, Exception e = null, params KeyValuePair<string, object>[] otherProperties)
{
@@ -112,52 +112,52 @@ namespace Timeline.Controllers properties[2] = Pair("Token", request.Token);
otherProperties.CopyTo(properties, 3);
_logger.LogInformation(LoggingEventIds.VerifyFailed, e, FormatLogMessage("Token verification failed.", properties));
- } - - try - { - var result = await _userService.VerifyToken(request.Token); + }
+
+ try
+ {
+ var result = await _userService.VerifyToken(request.Token);
_logger.LogInformation(LoggingEventIds.VerifySucceeded,
FormatLogMessage("Token verification succeeded.",
- Pair("Username", result.Username), Pair("Token", request.Token))); - return Ok(new VerifyTokenResponse - { - User = result - }); - } - catch (JwtTokenVerifyException e) - { - if (e.ErrorCode == JwtTokenVerifyException.ErrorCodes.Expired) - { - const string message = "Token is expired."; - var code = ErrorCodes.Verify_Expired; - var innerException = e.InnerException as SecurityTokenExpiredException; - LogFailure(message, code, e, Pair("Expires", innerException.Expires)); - return BadRequest(new CommonResponse(code, message)); - } - else - { - const string message = "Token is of bad format."; - var code = ErrorCodes.Verify_BadToken; - LogFailure(message, code, e); - return BadRequest(new CommonResponse(code, message)); - } - } - catch (UserNotExistException e) + Pair("Username", result.Username), Pair("Token", request.Token)));
+ return Ok(new VerifyTokenResponse
+ {
+ User = result
+ });
+ }
+ catch (JwtTokenVerifyException e)
{
- const string message = "User does not exist. Administrator might have deleted this user."; + if (e.ErrorCode == JwtTokenVerifyException.ErrorCodes.Expired)
+ {
+ const string message = "Token is expired.";
+ var code = ErrorCodes.Verify_Expired;
+ var innerException = e.InnerException as SecurityTokenExpiredException;
+ LogFailure(message, code, e, Pair("Expires", innerException.Expires));
+ return BadRequest(new CommonResponse(code, message));
+ }
+ else
+ {
+ const string message = "Token is of bad format.";
+ var code = ErrorCodes.Verify_BadToken;
+ LogFailure(message, code, e);
+ return BadRequest(new CommonResponse(code, message));
+ }
+ }
+ catch (UserNotExistException e)
+ {
+ const string message = "User does not exist. Administrator might have deleted this user.";
var code = ErrorCodes.Verify_UserNotExist;
- LogFailure(message, code, e); - return BadRequest(new CommonResponse(code, message)); - } - catch (BadTokenVersionException e) - { - const string message = "Token has a old version."; - var code = ErrorCodes.Verify_BadVersion; - LogFailure(message, code, e); - _logger.LogInformation(LoggingEventIds.VerifyFailed, e, "Attemp to verify a bad token because version is old. Code: {} Token: {}.", code, request.Token); - return BadRequest(new CommonResponse(code, message)); - } - } - } -} + LogFailure(message, code, e);
+ return BadRequest(new CommonResponse(code, message));
+ }
+ catch (BadTokenVersionException e)
+ {
+ const string message = "Token has a old version.";
+ var code = ErrorCodes.Verify_BadVersion;
+ LogFailure(message, code, e);
+ _logger.LogInformation(LoggingEventIds.VerifyFailed, e, "Attemp to verify a bad token because version is old. Code: {} Token: {}.", code, request.Token);
+ return BadRequest(new CommonResponse(code, message));
+ }
+ }
+ }
+}
diff --git a/Timeline/Controllers/UserController.cs b/Timeline/Controllers/UserController.cs index 2099690c..8d338949 100644 --- a/Timeline/Controllers/UserController.cs +++ b/Timeline/Controllers/UserController.cs @@ -1,126 +1,126 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Logging; -using System; -using System.Threading.Tasks; -using Timeline.Authenticate; -using Timeline.Entities; -using Timeline.Entities.Http; -using Timeline.Services; -using static Timeline.Helpers.MyLogHelper; - -namespace Timeline.Controllers -{ - public class UserController : Controller - { - private static class ErrorCodes - { - public const int Get_NotExists = -1001; - - public const int Put_NoPassword = -2001; - - public const int Patch_NotExists = -3001; - - public const int ChangePassword_BadOldPassword = -4001; - } - - private readonly ILogger<UserController> _logger; - private readonly IUserService _userService; - - public UserController(ILogger<UserController> logger, IUserService userService) - { - _logger = logger; - _userService = userService; - } - - [HttpGet("users"), AdminAuthorize] - public async Task<ActionResult<UserInfo[]>> List() - { - return Ok(await _userService.ListUsers()); - } - - [HttpGet("user/{username}"), AdminAuthorize] - public async Task<IActionResult> Get([FromRoute] string username) - { - var user = await _userService.GetUser(username); - if (user == null) - { - _logger.LogInformation(FormatLogMessage("Attempt to get a non-existent user.", Pair("Username", username))); - return NotFound(new CommonResponse(ErrorCodes.Get_NotExists, "The user does not exist.")); - } - return Ok(user); - } - - [HttpPut("user/{username}"), AdminAuthorize] - public async Task<IActionResult> Put([FromBody] UserPutRequest request, [FromRoute] string username) - { - if (request.Password == null) // This place will be refactored. - { - _logger.LogInformation("Attempt to put a user without a password. Username: {} .", username); - return BadRequest(); - } - - var result = await _userService.PutUser(username, request.Password, request.Administrator); - switch (result) - { - case PutResult.Created: - _logger.LogInformation(FormatLogMessage("A user is created.", Pair("Username", username))); - return CreatedAtAction("Get", new { username }, CommonPutResponse.Created); - case PutResult.Modified: - _logger.LogInformation(FormatLogMessage("A user is modified.", Pair("Username", username))); - return Ok(CommonPutResponse.Modified); - default: - throw new Exception("Unreachable code."); - } - } - - [HttpPatch("user/{username}"), AdminAuthorize] - public async Task<IActionResult> Patch([FromBody] UserPatchRequest request, [FromRoute] string username) - { - try - { - await _userService.PatchUser(username, request.Password, request.Administrator); - return Ok(); - } - catch (UserNotExistException e) - { - _logger.LogInformation(e, FormatLogMessage("Attempt to patch a non-existent user.", Pair("Username", username))); - return BadRequest(new CommonResponse(ErrorCodes.Patch_NotExists, "The user does not exist.")); - } - } - - [HttpDelete("user/{username}"), AdminAuthorize] - public async Task<IActionResult> Delete([FromRoute] string username) - { - try - { - await _userService.DeleteUser(username); - _logger.LogInformation(FormatLogMessage("A user is deleted.", Pair("Username", username))); - return Ok(CommonDeleteResponse.Deleted); - } - catch (UserNotExistException e) - { - _logger.LogInformation(e, FormatLogMessage("Attempt to delete a non-existent user.", Pair("Username", username))); - return Ok(CommonDeleteResponse.NotExists); - } - } - - [HttpPost("userop/changepassword"), Authorize] - public async Task<IActionResult> ChangePassword([FromBody] ChangePasswordRequest request) - { - try - { - await _userService.ChangePassword(User.Identity.Name, request.OldPassword, request.NewPassword); - _logger.LogInformation(FormatLogMessage("A user changed password.", Pair("Username", User.Identity.Name))); - return Ok(); - } - catch (BadPasswordException e) - { +using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Logging;
+using System;
+using System.Threading.Tasks;
+using Timeline.Authenticate;
+using Timeline.Entities;
+using Timeline.Entities.Http;
+using Timeline.Services;
+using static Timeline.Helpers.MyLogHelper;
+
+namespace Timeline.Controllers
+{
+ public class UserController : Controller
+ {
+ private static class ErrorCodes
+ {
+ public const int Get_NotExists = -1001;
+
+ public const int Put_NoPassword = -2001;
+
+ public const int Patch_NotExists = -3001;
+
+ public const int ChangePassword_BadOldPassword = -4001;
+ }
+
+ private readonly ILogger<UserController> _logger;
+ private readonly IUserService _userService;
+
+ public UserController(ILogger<UserController> logger, IUserService userService)
+ {
+ _logger = logger;
+ _userService = userService;
+ }
+
+ [HttpGet("users"), AdminAuthorize]
+ public async Task<ActionResult<UserInfo[]>> List()
+ {
+ return Ok(await _userService.ListUsers());
+ }
+
+ [HttpGet("user/{username}"), AdminAuthorize]
+ public async Task<IActionResult> Get([FromRoute] string username)
+ {
+ var user = await _userService.GetUser(username);
+ if (user == null)
+ {
+ _logger.LogInformation(FormatLogMessage("Attempt to get a non-existent user.", Pair("Username", username)));
+ return NotFound(new CommonResponse(ErrorCodes.Get_NotExists, "The user does not exist."));
+ }
+ return Ok(user);
+ }
+
+ [HttpPut("user/{username}"), AdminAuthorize]
+ public async Task<IActionResult> Put([FromBody] UserPutRequest request, [FromRoute] string username)
+ {
+ if (request.Password == null) // This place will be refactored.
+ {
+ _logger.LogInformation("Attempt to put a user without a password. Username: {} .", username);
+ return BadRequest();
+ }
+
+ var result = await _userService.PutUser(username, request.Password, request.Administrator);
+ switch (result)
+ {
+ case PutResult.Created:
+ _logger.LogInformation(FormatLogMessage("A user is created.", Pair("Username", username)));
+ return CreatedAtAction("Get", new { username }, CommonPutResponse.Created);
+ case PutResult.Modified:
+ _logger.LogInformation(FormatLogMessage("A user is modified.", Pair("Username", username)));
+ return Ok(CommonPutResponse.Modified);
+ default:
+ throw new Exception("Unreachable code.");
+ }
+ }
+
+ [HttpPatch("user/{username}"), AdminAuthorize]
+ public async Task<IActionResult> Patch([FromBody] UserPatchRequest request, [FromRoute] string username)
+ {
+ try
+ {
+ await _userService.PatchUser(username, request.Password, request.Administrator);
+ return Ok();
+ }
+ catch (UserNotExistException e)
+ {
+ _logger.LogInformation(e, FormatLogMessage("Attempt to patch a non-existent user.", Pair("Username", username)));
+ return BadRequest(new CommonResponse(ErrorCodes.Patch_NotExists, "The user does not exist."));
+ }
+ }
+
+ [HttpDelete("user/{username}"), AdminAuthorize]
+ public async Task<IActionResult> Delete([FromRoute] string username)
+ {
+ try
+ {
+ await _userService.DeleteUser(username);
+ _logger.LogInformation(FormatLogMessage("A user is deleted.", Pair("Username", username)));
+ return Ok(CommonDeleteResponse.Deleted);
+ }
+ catch (UserNotExistException e)
+ {
+ _logger.LogInformation(e, FormatLogMessage("Attempt to delete a non-existent user.", Pair("Username", username)));
+ return Ok(CommonDeleteResponse.NotExists);
+ }
+ }
+
+ [HttpPost("userop/changepassword"), Authorize]
+ public async Task<IActionResult> ChangePassword([FromBody] ChangePasswordRequest request)
+ {
+ try
+ {
+ await _userService.ChangePassword(User.Identity.Name, request.OldPassword, request.NewPassword);
+ _logger.LogInformation(FormatLogMessage("A user changed password.", Pair("Username", User.Identity.Name)));
+ return Ok();
+ }
+ catch (BadPasswordException e)
+ {
_logger.LogInformation(e, FormatLogMessage("A user attempt to change password but old password is wrong.",
- Pair("Username", User.Identity.Name), Pair("Old Password", request.OldPassword))); - return BadRequest(new CommonResponse(ErrorCodes.ChangePassword_BadOldPassword, "Old password is wrong.")); - } - // User can't be non-existent or the token is bad. - } - } -} + Pair("Username", User.Identity.Name), Pair("Old Password", request.OldPassword)));
+ return BadRequest(new CommonResponse(ErrorCodes.ChangePassword_BadOldPassword, "Old password is wrong."));
+ }
+ // User can't be non-existent or the token is bad.
+ }
+ }
+}
diff --git a/Timeline/Controllers/UserTestController.cs b/Timeline/Controllers/UserTestController.cs index 21686b81..f65d9857 100644 --- a/Timeline/Controllers/UserTestController.cs +++ b/Timeline/Controllers/UserTestController.cs @@ -1,31 +1,31 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Timeline.Authenticate; - -namespace Timeline.Controllers -{ - [Route("Test/User")] - public class UserTestController : Controller - { - [HttpGet("[action]")] - [Authorize] - public ActionResult Authorize() - { - return Ok(); - } - - [HttpGet("[action]")] - [UserAuthorize] - public new ActionResult User() - { - return Ok(); - } - - [HttpGet("[action]")] - [AdminAuthorize] - public ActionResult Admin() - { - return Ok(); - } - } -} +using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using Timeline.Authenticate;
+
+namespace Timeline.Controllers
+{
+ [Route("Test/User")]
+ public class UserTestController : Controller
+ {
+ [HttpGet("[action]")]
+ [Authorize]
+ public ActionResult Authorize()
+ {
+ return Ok();
+ }
+
+ [HttpGet("[action]")]
+ [UserAuthorize]
+ public new ActionResult User()
+ {
+ return Ok();
+ }
+
+ [HttpGet("[action]")]
+ [AdminAuthorize]
+ public ActionResult Admin()
+ {
+ return Ok();
+ }
+ }
+}
diff --git a/Timeline/Entities/Http/Common.cs b/Timeline/Entities/Http/Common.cs index 3a45a0ae..4cdc85dd 100644 --- a/Timeline/Entities/Http/Common.cs +++ b/Timeline/Entities/Http/Common.cs @@ -1,37 +1,37 @@ -namespace Timeline.Entities.Http -{ - public class CommonResponse - { - public CommonResponse() - { - - } - - public CommonResponse(int code, string message) - { - Code = code; - Message = message; - } - - public int Code { get; set; } - public string Message { get; set; } - } - - public static class CommonPutResponse - { - public const int CreatedCode = 0; - public const int ModifiedCode = 1; - - public static CommonResponse Created { get; } = new CommonResponse(CreatedCode, "A new item is created."); - public static CommonResponse Modified { get; } = new CommonResponse(ModifiedCode, "An existent item is modified."); - } - - public static class CommonDeleteResponse - { - public const int DeletedCode = 0; - public const int NotExistsCode = 1; - - public static CommonResponse Deleted { get; } = new CommonResponse(DeletedCode, "An existent item is deleted."); - public static CommonResponse NotExists { get; } = new CommonResponse(NotExistsCode, "The item does not exist."); - } -} +namespace Timeline.Entities.Http
+{
+ public class CommonResponse
+ {
+ public CommonResponse()
+ {
+
+ }
+
+ public CommonResponse(int code, string message)
+ {
+ Code = code;
+ Message = message;
+ }
+
+ public int Code { get; set; }
+ public string Message { get; set; }
+ }
+
+ public static class CommonPutResponse
+ {
+ public const int CreatedCode = 0;
+ public const int ModifiedCode = 1;
+
+ public static CommonResponse Created { get; } = new CommonResponse(CreatedCode, "A new item is created.");
+ public static CommonResponse Modified { get; } = new CommonResponse(ModifiedCode, "An existent item is modified.");
+ }
+
+ public static class CommonDeleteResponse
+ {
+ public const int DeletedCode = 0;
+ public const int NotExistsCode = 1;
+
+ public static CommonResponse Deleted { get; } = new CommonResponse(DeletedCode, "An existent item is deleted.");
+ public static CommonResponse NotExists { get; } = new CommonResponse(NotExistsCode, "The item does not exist.");
+ }
+}
diff --git a/Timeline/Entities/Http/Token.cs b/Timeline/Entities/Http/Token.cs index 8a02ed2e..5e261f30 100644 --- a/Timeline/Entities/Http/Token.cs +++ b/Timeline/Entities/Http/Token.cs @@ -1,26 +1,26 @@ -namespace Timeline.Entities.Http -{ - public class CreateTokenRequest - { - public string Username { get; set; } - public string Password { get; set; } - // in day - public double? ExpireOffset { get; set; } - } - - public class CreateTokenResponse - { - public string Token { get; set; } - public UserInfo User { get; set; } - } - - public class VerifyTokenRequest - { - public string Token { get; set; } - } - - public class VerifyTokenResponse - { - public UserInfo User { get; set; } - } -} +namespace Timeline.Entities.Http
+{
+ public class CreateTokenRequest
+ {
+ public string Username { get; set; }
+ public string Password { get; set; }
+ // in day
+ public double? ExpireOffset { get; set; }
+ }
+
+ public class CreateTokenResponse
+ {
+ public string Token { get; set; }
+ public UserInfo User { get; set; }
+ }
+
+ public class VerifyTokenRequest
+ {
+ public string Token { get; set; }
+ }
+
+ public class VerifyTokenResponse
+ {
+ public UserInfo User { get; set; }
+ }
+}
diff --git a/Timeline/Entities/Http/User.cs b/Timeline/Entities/Http/User.cs index b5384778..e9aaf795 100644 --- a/Timeline/Entities/Http/User.cs +++ b/Timeline/Entities/Http/User.cs @@ -1,20 +1,20 @@ -namespace Timeline.Entities.Http -{ - public class UserPutRequest - { - public string Password { get; set; } - public bool Administrator { get; set; } - } - - public class UserPatchRequest - { - public string Password { get; set; } - public bool? Administrator { get; set; } - } - - public class ChangePasswordRequest - { - public string OldPassword { get; set; } - public string NewPassword { get; set; } - } -} +namespace Timeline.Entities.Http
+{
+ public class UserPutRequest
+ {
+ public string Password { get; set; }
+ public bool Administrator { get; set; }
+ }
+
+ public class UserPatchRequest
+ {
+ public string Password { get; set; }
+ public bool? Administrator { get; set; }
+ }
+
+ public class ChangePasswordRequest
+ {
+ public string OldPassword { get; set; }
+ public string NewPassword { get; set; }
+ }
+}
diff --git a/Timeline/Entities/PutResult.cs b/Timeline/Entities/PutResult.cs index 4ed48572..32b87e25 100644 --- a/Timeline/Entities/PutResult.cs +++ b/Timeline/Entities/PutResult.cs @@ -1,17 +1,17 @@ -namespace Timeline.Entities -{ - /// <summary> - /// Represents the result of a "put" operation. - /// </summary> - public enum PutResult - { - /// <summary> - /// Indicates the item did not exist and now is created. - /// </summary> - Created, - /// <summary> - /// Indicates the item exists already and is modified. - /// </summary> - Modified - } -} +namespace Timeline.Entities
+{
+ /// <summary>
+ /// Represents the result of a "put" operation.
+ /// </summary>
+ public enum PutResult
+ {
+ /// <summary>
+ /// Indicates the item did not exist and now is created.
+ /// </summary>
+ Created,
+ /// <summary>
+ /// Indicates the item exists already and is modified.
+ /// </summary>
+ Modified
+ }
+}
diff --git a/Timeline/Entities/UserInfo.cs b/Timeline/Entities/UserInfo.cs index 414a8dfe..c75168b8 100644 --- a/Timeline/Entities/UserInfo.cs +++ b/Timeline/Entities/UserInfo.cs @@ -1,23 +1,23 @@ -namespace Timeline.Entities -{ - public sealed class UserInfo - { - public UserInfo() - { - } - - public UserInfo(string username, bool administrator) - { - Username = username; - Administrator = administrator; - } - - public string Username { get; set; } - public bool Administrator { get; set; } - - public override string ToString() - { - return $"Username: {Username} ; Administrator: {Administrator}"; - } - } -} +namespace Timeline.Entities
+{
+ public sealed class UserInfo
+ {
+ public UserInfo()
+ {
+ }
+
+ public UserInfo(string username, bool administrator)
+ {
+ Username = username;
+ Administrator = administrator;
+ }
+
+ public string Username { get; set; }
+ public bool Administrator { get; set; }
+
+ public override string ToString()
+ {
+ return $"Username: {Username} ; Administrator: {Administrator}";
+ }
+ }
+}
diff --git a/Timeline/Entities/UserUtility.cs b/Timeline/Entities/UserUtility.cs index 14cdb2d6..351d0299 100644 --- a/Timeline/Entities/UserUtility.cs +++ b/Timeline/Entities/UserUtility.cs @@ -1,60 +1,60 @@ -using System; -using System.Linq; -using Timeline.Models; -using Timeline.Services; - -namespace Timeline.Entities -{ - public static class UserUtility - { - public const string UserRole = UserRoles.User; - public const string AdminRole = UserRoles.Admin; - - public static string[] UserRoleArray { get; } = new string[] { UserRole }; - public static string[] AdminRoleArray { get; } = new string[] { UserRole, AdminRole }; - - public static string[] IsAdminToRoleArray(bool isAdmin) - { - return isAdmin ? AdminRoleArray : UserRoleArray; - } - - public static bool RoleArrayToIsAdmin(string[] roles) - { - return roles.Contains(AdminRole); - } - - public static string[] RoleStringToRoleArray(string roleString) - { - return roleString.Split(',').ToArray(); - } - - public static string RoleArrayToRoleString(string[] roles) - { - return string.Join(',', roles); - } - - public static string IsAdminToRoleString(bool isAdmin) - { - return RoleArrayToRoleString(IsAdminToRoleArray(isAdmin)); - } - - public static bool RoleStringToIsAdmin(string roleString) - { - return RoleArrayToIsAdmin(RoleStringToRoleArray(roleString)); - } - - public static UserInfo CreateUserInfo(User user) - { - if (user == null) - throw new ArgumentNullException(nameof(user)); - return new UserInfo(user.Name, RoleStringToIsAdmin(user.RoleString)); - } - - internal static UserCache CreateUserCache(User user) - { - if (user == null) - throw new ArgumentNullException(nameof(user)); - return new UserCache { Username = user.Name, Administrator = RoleStringToIsAdmin(user.RoleString), Version = user.Version }; - } - } -} +using System;
+using System.Linq;
+using Timeline.Models;
+using Timeline.Services;
+
+namespace Timeline.Entities
+{
+ public static class UserUtility
+ {
+ public const string UserRole = UserRoles.User;
+ public const string AdminRole = UserRoles.Admin;
+
+ public static string[] UserRoleArray { get; } = new string[] { UserRole };
+ public static string[] AdminRoleArray { get; } = new string[] { UserRole, AdminRole };
+
+ public static string[] IsAdminToRoleArray(bool isAdmin)
+ {
+ return isAdmin ? AdminRoleArray : UserRoleArray;
+ }
+
+ public static bool RoleArrayToIsAdmin(string[] roles)
+ {
+ return roles.Contains(AdminRole);
+ }
+
+ public static string[] RoleStringToRoleArray(string roleString)
+ {
+ return roleString.Split(',').ToArray();
+ }
+
+ public static string RoleArrayToRoleString(string[] roles)
+ {
+ return string.Join(',', roles);
+ }
+
+ public static string IsAdminToRoleString(bool isAdmin)
+ {
+ return RoleArrayToRoleString(IsAdminToRoleArray(isAdmin));
+ }
+
+ public static bool RoleStringToIsAdmin(string roleString)
+ {
+ return RoleArrayToIsAdmin(RoleStringToRoleArray(roleString));
+ }
+
+ public static UserInfo CreateUserInfo(User user)
+ {
+ if (user == null)
+ throw new ArgumentNullException(nameof(user));
+ return new UserInfo(user.Name, RoleStringToIsAdmin(user.RoleString));
+ }
+
+ internal static UserCache CreateUserCache(User user)
+ {
+ if (user == null)
+ throw new ArgumentNullException(nameof(user));
+ return new UserCache { Username = user.Name, Administrator = RoleStringToIsAdmin(user.RoleString), Version = user.Version };
+ }
+ }
+}
diff --git a/Timeline/Helpers/Log.cs b/Timeline/Helpers/Log.cs index ac231810..123e8a8e 100644 --- a/Timeline/Helpers/Log.cs +++ b/Timeline/Helpers/Log.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic;
+using System.Collections.Generic;
using System.Text;
namespace Timeline.Helpers
diff --git a/Timeline/Migrations/20190412102517_InitCreate.Designer.cs b/Timeline/Migrations/20190412102517_InitCreate.Designer.cs index c68183de..5281da05 100644 --- a/Timeline/Migrations/20190412102517_InitCreate.Designer.cs +++ b/Timeline/Migrations/20190412102517_InitCreate.Designer.cs @@ -1,43 +1,43 @@ -// <auto-generated /> -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Timeline.Models; - -namespace Timeline.Migrations -{ - [DbContext(typeof(DatabaseContext))] - [Migration("20190412102517_InitCreate")] - partial class InitCreate - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "2.2.3-servicing-35854") - .HasAnnotation("Relational:MaxIdentifierLength", 64); - - modelBuilder.Entity("Timeline.Models.User", b => - { - b.Property<long>("Id") - .ValueGeneratedOnAdd() - .HasColumnName("id"); - - b.Property<string>("EncryptedPassword") - .HasColumnName("password"); - - b.Property<string>("Name") - .HasColumnName("name"); - - b.Property<string>("RoleString") - .HasColumnName("roles"); - - b.HasKey("Id"); - - b.ToTable("user"); - }); -#pragma warning restore 612, 618 - } - } -} +// <auto-generated />
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Timeline.Models;
+
+namespace Timeline.Migrations
+{
+ [DbContext(typeof(DatabaseContext))]
+ [Migration("20190412102517_InitCreate")]
+ partial class InitCreate
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "2.2.3-servicing-35854")
+ .HasAnnotation("Relational:MaxIdentifierLength", 64);
+
+ modelBuilder.Entity("Timeline.Models.User", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnName("id");
+
+ b.Property<string>("EncryptedPassword")
+ .HasColumnName("password");
+
+ b.Property<string>("Name")
+ .HasColumnName("name");
+
+ b.Property<string>("RoleString")
+ .HasColumnName("roles");
+
+ b.HasKey("Id");
+
+ b.ToTable("user");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/Timeline/Migrations/20190412102517_InitCreate.cs b/Timeline/Migrations/20190412102517_InitCreate.cs index c8f3b0ac..55930f6d 100644 --- a/Timeline/Migrations/20190412102517_InitCreate.cs +++ b/Timeline/Migrations/20190412102517_InitCreate.cs @@ -1,32 +1,32 @@ -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace Timeline.Migrations -{ - public partial class InitCreate : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "user", - columns: table => new - { - id = table.Column<long>(nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - name = table.Column<string>(nullable: true), - password = table.Column<string>(nullable: true), - roles = table.Column<string>(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_user", x => x.id); - }); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "user"); - } - } -} +using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace Timeline.Migrations
+{
+ public partial class InitCreate : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.CreateTable(
+ name: "user",
+ columns: table => new
+ {
+ id = table.Column<long>(nullable: false)
+ .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
+ name = table.Column<string>(nullable: true),
+ password = table.Column<string>(nullable: true),
+ roles = table.Column<string>(nullable: true)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_user", x => x.id);
+ });
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropTable(
+ name: "user");
+ }
+ }
+}
diff --git a/Timeline/Migrations/20190412144150_AddAdminUser.Designer.cs b/Timeline/Migrations/20190412144150_AddAdminUser.Designer.cs index 319c646a..b3139efa 100644 --- a/Timeline/Migrations/20190412144150_AddAdminUser.Designer.cs +++ b/Timeline/Migrations/20190412144150_AddAdminUser.Designer.cs @@ -1,43 +1,43 @@ -// <auto-generated /> -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Timeline.Models; - -namespace Timeline.Migrations -{ - [DbContext(typeof(DatabaseContext))] - [Migration("20190412144150_AddAdminUser")] - partial class AddAdminUser - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "2.2.3-servicing-35854") - .HasAnnotation("Relational:MaxIdentifierLength", 64); - - modelBuilder.Entity("Timeline.Models.User", b => - { - b.Property<long>("Id") - .ValueGeneratedOnAdd() - .HasColumnName("id"); - - b.Property<string>("EncryptedPassword") - .HasColumnName("password"); - - b.Property<string>("Name") - .HasColumnName("name"); - - b.Property<string>("RoleString") - .HasColumnName("roles"); - - b.HasKey("Id"); - - b.ToTable("user"); - }); -#pragma warning restore 612, 618 - } - } -} +// <auto-generated />
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Timeline.Models;
+
+namespace Timeline.Migrations
+{
+ [DbContext(typeof(DatabaseContext))]
+ [Migration("20190412144150_AddAdminUser")]
+ partial class AddAdminUser
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "2.2.3-servicing-35854")
+ .HasAnnotation("Relational:MaxIdentifierLength", 64);
+
+ modelBuilder.Entity("Timeline.Models.User", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnName("id");
+
+ b.Property<string>("EncryptedPassword")
+ .HasColumnName("password");
+
+ b.Property<string>("Name")
+ .HasColumnName("name");
+
+ b.Property<string>("RoleString")
+ .HasColumnName("roles");
+
+ b.HasKey("Id");
+
+ b.ToTable("user");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/Timeline/Migrations/20190412144150_AddAdminUser.cs b/Timeline/Migrations/20190412144150_AddAdminUser.cs index 1b3f14b7..b6760f3e 100644 --- a/Timeline/Migrations/20190412144150_AddAdminUser.cs +++ b/Timeline/Migrations/20190412144150_AddAdminUser.cs @@ -1,19 +1,19 @@ -using Microsoft.EntityFrameworkCore.Migrations; -using Timeline.Services; - -namespace Timeline.Migrations -{ - public partial class AddAdminUser : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.InsertData("user", new string[] { "name", "password", "roles" }, - new string[] { "crupest", new PasswordService().HashPassword("yang0101"), "user,admin" }); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DeleteData("user", "name", "crupest"); - } - } -} +using Microsoft.EntityFrameworkCore.Migrations;
+using Timeline.Services;
+
+namespace Timeline.Migrations
+{
+ public partial class AddAdminUser : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.InsertData("user", new string[] { "name", "password", "roles" },
+ new string[] { "crupest", new PasswordService().HashPassword("yang0101"), "user,admin" });
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DeleteData("user", "name", "crupest");
+ }
+ }
+}
diff --git a/Timeline/Migrations/20190412153003_MakeColumnsInUserNotNull.Designer.cs b/Timeline/Migrations/20190412153003_MakeColumnsInUserNotNull.Designer.cs index c1d1565f..e2adf9d4 100644 --- a/Timeline/Migrations/20190412153003_MakeColumnsInUserNotNull.Designer.cs +++ b/Timeline/Migrations/20190412153003_MakeColumnsInUserNotNull.Designer.cs @@ -1,46 +1,46 @@ -// <auto-generated /> -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Timeline.Models; - -namespace Timeline.Migrations -{ - [DbContext(typeof(DatabaseContext))] - [Migration("20190412153003_MakeColumnsInUserNotNull")] - partial class MakeColumnsInUserNotNull - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "2.2.3-servicing-35854") - .HasAnnotation("Relational:MaxIdentifierLength", 64); - - modelBuilder.Entity("Timeline.Models.User", b => - { - b.Property<long>("Id") - .ValueGeneratedOnAdd() - .HasColumnName("id"); - - b.Property<string>("EncryptedPassword") - .IsRequired() - .HasColumnName("password"); - - b.Property<string>("Name") - .IsRequired() - .HasColumnName("name"); - - b.Property<string>("RoleString") - .IsRequired() - .HasColumnName("roles"); - - b.HasKey("Id"); - - b.ToTable("user"); - }); -#pragma warning restore 612, 618 - } - } -} +// <auto-generated />
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Timeline.Models;
+
+namespace Timeline.Migrations
+{
+ [DbContext(typeof(DatabaseContext))]
+ [Migration("20190412153003_MakeColumnsInUserNotNull")]
+ partial class MakeColumnsInUserNotNull
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "2.2.3-servicing-35854")
+ .HasAnnotation("Relational:MaxIdentifierLength", 64);
+
+ modelBuilder.Entity("Timeline.Models.User", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnName("id");
+
+ b.Property<string>("EncryptedPassword")
+ .IsRequired()
+ .HasColumnName("password");
+
+ b.Property<string>("Name")
+ .IsRequired()
+ .HasColumnName("name");
+
+ b.Property<string>("RoleString")
+ .IsRequired()
+ .HasColumnName("roles");
+
+ b.HasKey("Id");
+
+ b.ToTable("user");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/Timeline/Migrations/20190412153003_MakeColumnsInUserNotNull.cs b/Timeline/Migrations/20190412153003_MakeColumnsInUserNotNull.cs index 0b7b5f08..12053906 100644 --- a/Timeline/Migrations/20190412153003_MakeColumnsInUserNotNull.cs +++ b/Timeline/Migrations/20190412153003_MakeColumnsInUserNotNull.cs @@ -1,52 +1,52 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -namespace Timeline.Migrations -{ - public partial class MakeColumnsInUserNotNull : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn<string>( - name: "roles", - table: "user", - nullable: false, - oldClrType: typeof(string), - oldNullable: true); - - migrationBuilder.AlterColumn<string>( - name: "name", - table: "user", - nullable: false, - oldClrType: typeof(string), - oldNullable: true); - - migrationBuilder.AlterColumn<string>( - name: "password", - table: "user", - nullable: false, - oldClrType: typeof(string), - oldNullable: true); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn<string>( - name: "roles", - table: "user", - nullable: true, - oldClrType: typeof(string)); - - migrationBuilder.AlterColumn<string>( - name: "name", - table: "user", - nullable: true, - oldClrType: typeof(string)); - - migrationBuilder.AlterColumn<string>( - name: "password", - table: "user", - nullable: true, - oldClrType: typeof(string)); - } - } -} +using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace Timeline.Migrations
+{
+ public partial class MakeColumnsInUserNotNull : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.AlterColumn<string>(
+ name: "roles",
+ table: "user",
+ nullable: false,
+ oldClrType: typeof(string),
+ oldNullable: true);
+
+ migrationBuilder.AlterColumn<string>(
+ name: "name",
+ table: "user",
+ nullable: false,
+ oldClrType: typeof(string),
+ oldNullable: true);
+
+ migrationBuilder.AlterColumn<string>(
+ name: "password",
+ table: "user",
+ nullable: false,
+ oldClrType: typeof(string),
+ oldNullable: true);
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.AlterColumn<string>(
+ name: "roles",
+ table: "user",
+ nullable: true,
+ oldClrType: typeof(string));
+
+ migrationBuilder.AlterColumn<string>(
+ name: "name",
+ table: "user",
+ nullable: true,
+ oldClrType: typeof(string));
+
+ migrationBuilder.AlterColumn<string>(
+ name: "password",
+ table: "user",
+ nullable: true,
+ oldClrType: typeof(string));
+ }
+ }
+}
diff --git a/Timeline/Migrations/20190719115321_Add-User-Version.Designer.cs b/Timeline/Migrations/20190719115321_Add-User-Version.Designer.cs index 42eeeb40..0216ff5b 100644 --- a/Timeline/Migrations/20190719115321_Add-User-Version.Designer.cs +++ b/Timeline/Migrations/20190719115321_Add-User-Version.Designer.cs @@ -1,49 +1,49 @@ -// <auto-generated /> -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Timeline.Models; - -namespace Timeline.Migrations -{ - [DbContext(typeof(DatabaseContext))] - [Migration("20190719115321_Add-User-Version")] - partial class AddUserVersion - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "2.2.6-servicing-10079") - .HasAnnotation("Relational:MaxIdentifierLength", 64); - - modelBuilder.Entity("Timeline.Models.User", b => - { - b.Property<long>("Id") - .ValueGeneratedOnAdd() - .HasColumnName("id"); - - b.Property<string>("EncryptedPassword") - .IsRequired() - .HasColumnName("password"); - - b.Property<string>("Name") - .IsRequired() - .HasColumnName("name"); - - b.Property<string>("RoleString") - .IsRequired() - .HasColumnName("roles"); - - b.Property<long>("Version") - .HasColumnName("version"); - - b.HasKey("Id"); - - b.ToTable("user"); - }); -#pragma warning restore 612, 618 - } - } -} +// <auto-generated />
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Timeline.Models;
+
+namespace Timeline.Migrations
+{
+ [DbContext(typeof(DatabaseContext))]
+ [Migration("20190719115321_Add-User-Version")]
+ partial class AddUserVersion
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "2.2.6-servicing-10079")
+ .HasAnnotation("Relational:MaxIdentifierLength", 64);
+
+ modelBuilder.Entity("Timeline.Models.User", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnName("id");
+
+ b.Property<string>("EncryptedPassword")
+ .IsRequired()
+ .HasColumnName("password");
+
+ b.Property<string>("Name")
+ .IsRequired()
+ .HasColumnName("name");
+
+ b.Property<string>("RoleString")
+ .IsRequired()
+ .HasColumnName("roles");
+
+ b.Property<long>("Version")
+ .HasColumnName("version");
+
+ b.HasKey("Id");
+
+ b.ToTable("user");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/Timeline/Migrations/20190719115321_Add-User-Version.cs b/Timeline/Migrations/20190719115321_Add-User-Version.cs index 715af909..4d6bd60a 100644 --- a/Timeline/Migrations/20190719115321_Add-User-Version.cs +++ b/Timeline/Migrations/20190719115321_Add-User-Version.cs @@ -1,23 +1,23 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -namespace Timeline.Migrations -{ - public partial class AddUserVersion : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn<long>( - name: "version", - table: "user", - nullable: false, - defaultValue: 0L); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "version", - table: "user"); - } - } -} +using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace Timeline.Migrations
+{
+ public partial class AddUserVersion : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.AddColumn<long>(
+ name: "version",
+ table: "user",
+ nullable: false,
+ defaultValue: 0L);
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropColumn(
+ name: "version",
+ table: "user");
+ }
+ }
+}
diff --git a/Timeline/Migrations/DatabaseContextModelSnapshot.cs b/Timeline/Migrations/DatabaseContextModelSnapshot.cs index 7d244969..c26ae5e6 100644 --- a/Timeline/Migrations/DatabaseContextModelSnapshot.cs +++ b/Timeline/Migrations/DatabaseContextModelSnapshot.cs @@ -1,47 +1,47 @@ -// <auto-generated /> -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Timeline.Models; - -namespace Timeline.Migrations -{ - [DbContext(typeof(DatabaseContext))] - partial class DatabaseContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "2.2.6-servicing-10079") - .HasAnnotation("Relational:MaxIdentifierLength", 64); - - modelBuilder.Entity("Timeline.Models.User", b => - { - b.Property<long>("Id") - .ValueGeneratedOnAdd() - .HasColumnName("id"); - - b.Property<string>("EncryptedPassword") - .IsRequired() - .HasColumnName("password"); - - b.Property<string>("Name") - .IsRequired() - .HasColumnName("name"); - - b.Property<string>("RoleString") - .IsRequired() - .HasColumnName("roles"); - - b.Property<long>("Version") - .HasColumnName("version"); - - b.HasKey("Id"); - - b.ToTable("user"); - }); -#pragma warning restore 612, 618 - } - } -} +// <auto-generated />
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Timeline.Models;
+
+namespace Timeline.Migrations
+{
+ [DbContext(typeof(DatabaseContext))]
+ partial class DatabaseContextModelSnapshot : ModelSnapshot
+ {
+ protected override void BuildModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "2.2.6-servicing-10079")
+ .HasAnnotation("Relational:MaxIdentifierLength", 64);
+
+ modelBuilder.Entity("Timeline.Models.User", b =>
+ {
+ b.Property<long>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnName("id");
+
+ b.Property<string>("EncryptedPassword")
+ .IsRequired()
+ .HasColumnName("password");
+
+ b.Property<string>("Name")
+ .IsRequired()
+ .HasColumnName("name");
+
+ b.Property<string>("RoleString")
+ .IsRequired()
+ .HasColumnName("roles");
+
+ b.Property<long>("Version")
+ .HasColumnName("version");
+
+ b.HasKey("Id");
+
+ b.ToTable("user");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/Timeline/Models/DatabaseContext.cs b/Timeline/Models/DatabaseContext.cs index afd5a333..2e33bf8d 100644 --- a/Timeline/Models/DatabaseContext.cs +++ b/Timeline/Models/DatabaseContext.cs @@ -1,42 +1,42 @@ -using Microsoft.EntityFrameworkCore; -using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; - -namespace Timeline.Models -{ - public static class UserRoles - { - public const string Admin = "admin"; - public const string User = "user"; - } - - [Table("user")] - public class User - { - [Column("id"), Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] - public long Id { get; set; } - - [Column("name"), Required] - public string Name { get; set; } - - [Column("password"), Required] - public string EncryptedPassword { get; set; } - - [Column("roles"), Required] - public string RoleString { get; set; } - - [Column("version"), Required] - public long Version { get; set; } - } - - public class DatabaseContext : DbContext - { - public DatabaseContext(DbContextOptions<DatabaseContext> options) - : base(options) - { - - } - - public DbSet<User> Users { get; set; } - } -} +using Microsoft.EntityFrameworkCore;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+
+namespace Timeline.Models
+{
+ public static class UserRoles
+ {
+ public const string Admin = "admin";
+ public const string User = "user";
+ }
+
+ [Table("user")]
+ public class User
+ {
+ [Column("id"), Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
+ public long Id { get; set; }
+
+ [Column("name"), Required]
+ public string Name { get; set; }
+
+ [Column("password"), Required]
+ public string EncryptedPassword { get; set; }
+
+ [Column("roles"), Required]
+ public string RoleString { get; set; }
+
+ [Column("version"), Required]
+ public long Version { get; set; }
+ }
+
+ public class DatabaseContext : DbContext
+ {
+ public DatabaseContext(DbContextOptions<DatabaseContext> options)
+ : base(options)
+ {
+
+ }
+
+ public DbSet<User> Users { get; set; }
+ }
+}
diff --git a/Timeline/Program.cs b/Timeline/Program.cs index 480f5e9e..f343de44 100644 --- a/Timeline/Program.cs +++ b/Timeline/Program.cs @@ -1,25 +1,25 @@ -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.FileProviders; - -namespace Timeline -{ - public class Program - { - public static void Main(string[] args) - { - CreateWebHostBuilder(args) - .ConfigureAppConfiguration((context, config) => - { - if (context.HostingEnvironment.IsProduction()) - config.AddJsonFile(new PhysicalFileProvider("/etc/webapp/timeline/"), "config.json", true, true); - }) - .Build().Run(); - } - - public static IWebHostBuilder CreateWebHostBuilder(string[] args) => - WebHost.CreateDefaultBuilder(args) - .UseStartup<Startup>(); - } -} +using Microsoft.AspNetCore;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.FileProviders;
+
+namespace Timeline
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateWebHostBuilder(args)
+ .ConfigureAppConfiguration((context, config) =>
+ {
+ if (context.HostingEnvironment.IsProduction())
+ config.AddJsonFile(new PhysicalFileProvider("/etc/webapp/timeline/"), "config.json", true, true);
+ })
+ .Build().Run();
+ }
+
+ public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
+ WebHost.CreateDefaultBuilder(args)
+ .UseStartup<Startup>();
+ }
+}
diff --git a/Timeline/Services/Clock.cs b/Timeline/Services/Clock.cs index 98451ad9..0499c0c6 100644 --- a/Timeline/Services/Clock.cs +++ b/Timeline/Services/Clock.cs @@ -1,32 +1,32 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Timeline.Services -{ - /// <summary> - /// Convenient for unit test. - /// </summary> - public interface IClock - { - /// <summary> - /// Get current time. - /// </summary> - /// <returns>Current time.</returns> - DateTime GetCurrentTime(); - } - - public class Clock : IClock - { - public Clock() - { - - } - - public DateTime GetCurrentTime() - { - return DateTime.Now; - } - } -} +using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Timeline.Services
+{
+ /// <summary>
+ /// Convenient for unit test.
+ /// </summary>
+ public interface IClock
+ {
+ /// <summary>
+ /// Get current time.
+ /// </summary>
+ /// <returns>Current time.</returns>
+ DateTime GetCurrentTime();
+ }
+
+ public class Clock : IClock
+ {
+ public Clock()
+ {
+
+ }
+
+ public DateTime GetCurrentTime()
+ {
+ return DateTime.Now;
+ }
+ }
+}
diff --git a/Timeline/Services/JwtService.cs b/Timeline/Services/JwtService.cs index 94afe745..350c5e80 100644 --- a/Timeline/Services/JwtService.cs +++ b/Timeline/Services/JwtService.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.Options;
+using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using System;
using System.IdentityModel.Tokens.Jwt;
diff --git a/Timeline/Services/PasswordService.cs b/Timeline/Services/PasswordService.cs index 8c67d046..e09a1365 100644 --- a/Timeline/Services/PasswordService.cs +++ b/Timeline/Services/PasswordService.cs @@ -1,4 +1,4 @@ -using Microsoft.AspNetCore.Cryptography.KeyDerivation;
+using Microsoft.AspNetCore.Cryptography.KeyDerivation;
using System;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
diff --git a/Timeline/Startup.cs b/Timeline/Startup.cs index 242e816d..0ce6b989 100644 --- a/Timeline/Startup.cs +++ b/Timeline/Startup.cs @@ -1,90 +1,90 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.HttpOverrides; -using Microsoft.AspNetCore.Mvc; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Diagnostics; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Timeline.Authenticate; -using Timeline.Configs; -using Timeline.Models; -using Timeline.Services; - -namespace Timeline -{ - public class Startup - { - private const string corsPolicyName = "MyPolicy"; - - public Startup(IConfiguration configuration, IHostingEnvironment environment) - { - Environment = environment; - Configuration = configuration; - } - - public IHostingEnvironment Environment { get; } - public IConfiguration Configuration { get; } - - // This method gets called by the runtime. Use this method to add services to the container. - public void ConfigureServices(IServiceCollection services) - { - services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); - - services.AddCors(options => - { - options.AddPolicy(corsPolicyName, builder => - { - if (Environment.IsProduction()) - builder.WithOrigins("https://www.crupest.xyz", "https://crupest.xyz").AllowAnyMethod().AllowAnyHeader().AllowCredentials(); - else - builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader(); - }); - }); - - services.Configure<JwtConfig>(Configuration.GetSection(nameof(JwtConfig))); - var jwtConfig = Configuration.GetSection(nameof(JwtConfig)).Get<JwtConfig>(); - - services.AddAuthentication(AuthConstants.Scheme) - .AddScheme<AuthOptions, AuthHandler>(AuthConstants.Scheme, AuthConstants.DisplayName, o => { }); - - services.AddScoped<IUserService, UserService>(); - services.AddScoped<IJwtService, JwtService>(); - services.AddTransient<IPasswordService, PasswordService>(); - services.AddTransient<IClock, Clock>(); - - var databaseConfig = Configuration.GetSection(nameof(DatabaseConfig)).Get<DatabaseConfig>(); - - services.AddDbContext<DatabaseContext>(options => - { - options.UseMySql(databaseConfig.ConnectionString) - .ConfigureWarnings(warnings => - { - if (Environment.IsProduction()) - warnings.Log(RelationalEventId.QueryClientEvaluationWarning); - else - warnings.Throw(RelationalEventId.QueryClientEvaluationWarning); - }); - }); - - services.AddHttpClient(); - - services.AddMemoryCache(); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app) - { - app.UseCors(corsPolicyName); - - app.UseForwardedHeaders(new ForwardedHeadersOptions - { - ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto - }); - - app.UseAuthentication(); - - app.UseMvcWithDefaultRoute(); - } - } -} +using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.HttpOverrides;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Diagnostics;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Timeline.Authenticate;
+using Timeline.Configs;
+using Timeline.Models;
+using Timeline.Services;
+
+namespace Timeline
+{
+ public class Startup
+ {
+ private const string corsPolicyName = "MyPolicy";
+
+ public Startup(IConfiguration configuration, IHostingEnvironment environment)
+ {
+ Environment = environment;
+ Configuration = configuration;
+ }
+
+ public IHostingEnvironment Environment { get; }
+ public IConfiguration Configuration { get; }
+
+ // This method gets called by the runtime. Use this method to add services to the container.
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
+
+ services.AddCors(options =>
+ {
+ options.AddPolicy(corsPolicyName, builder =>
+ {
+ if (Environment.IsProduction())
+ builder.WithOrigins("https://www.crupest.xyz", "https://crupest.xyz").AllowAnyMethod().AllowAnyHeader().AllowCredentials();
+ else
+ builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader();
+ });
+ });
+
+ services.Configure<JwtConfig>(Configuration.GetSection(nameof(JwtConfig)));
+ var jwtConfig = Configuration.GetSection(nameof(JwtConfig)).Get<JwtConfig>();
+
+ services.AddAuthentication(AuthConstants.Scheme)
+ .AddScheme<AuthOptions, AuthHandler>(AuthConstants.Scheme, AuthConstants.DisplayName, o => { });
+
+ services.AddScoped<IUserService, UserService>();
+ services.AddScoped<IJwtService, JwtService>();
+ services.AddTransient<IPasswordService, PasswordService>();
+ services.AddTransient<IClock, Clock>();
+
+ var databaseConfig = Configuration.GetSection(nameof(DatabaseConfig)).Get<DatabaseConfig>();
+
+ services.AddDbContext<DatabaseContext>(options =>
+ {
+ options.UseMySql(databaseConfig.ConnectionString)
+ .ConfigureWarnings(warnings =>
+ {
+ if (Environment.IsProduction())
+ warnings.Log(RelationalEventId.QueryClientEvaluationWarning);
+ else
+ warnings.Throw(RelationalEventId.QueryClientEvaluationWarning);
+ });
+ });
+
+ services.AddHttpClient();
+
+ services.AddMemoryCache();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app)
+ {
+ app.UseCors(corsPolicyName);
+
+ app.UseForwardedHeaders(new ForwardedHeadersOptions
+ {
+ ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
+ });
+
+ app.UseAuthentication();
+
+ app.UseMvcWithDefaultRoute();
+ }
+ }
+}
diff --git a/Timeline/Timeline.csproj b/Timeline/Timeline.csproj index 93513bd3..5f07cabc 100644 --- a/Timeline/Timeline.csproj +++ b/Timeline/Timeline.csproj @@ -1,16 +1,16 @@ -<Project Sdk="Microsoft.NET.Sdk.Web"> - <PropertyGroup> - <TargetFramework>netcoreapp2.2</TargetFramework> - <IsPackable>false</IsPackable> - <UserSecretsId>1f6fb74d-4277-4bc0-aeea-b1fc5ffb0b43</UserSecretsId> - <Authors>crupest</Authors> - </PropertyGroup> - - <ItemGroup> - <PackageReference Include="Microsoft.AspNetCore.App" /> - <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" /> - <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.2.3" /> - <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="2.2.0" /> - <PackageReference Include="Pomelo.EntityFrameworkCore.MySql.Design" Version="1.1.2" /> - </ItemGroup> -</Project> +<Project Sdk="Microsoft.NET.Sdk.Web">
+ <PropertyGroup>
+ <TargetFramework>netcoreapp2.2</TargetFramework>
+ <IsPackable>false</IsPackable>
+ <UserSecretsId>1f6fb74d-4277-4bc0-aeea-b1fc5ffb0b43</UserSecretsId>
+ <Authors>crupest</Authors>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <PackageReference Include="Microsoft.AspNetCore.App" />
+ <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
+ <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.2.3" />
+ <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="2.2.0" />
+ <PackageReference Include="Pomelo.EntityFrameworkCore.MySql.Design" Version="1.1.2" />
+ </ItemGroup>
+</Project>
diff --git a/Timeline/appsettings.Development.json b/Timeline/appsettings.Development.json index b1cd5a3b..db4b074a 100644 --- a/Timeline/appsettings.Development.json +++ b/Timeline/appsettings.Development.json @@ -1,12 +1,12 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Debug", - "System": "Information", - "Microsoft": "Information" - } - }, - "JwtConfig": { - "SigningKey": "crupest hahahahahahahhahahahahaha" - } -} +{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Debug",
+ "System": "Information",
+ "Microsoft": "Information"
+ }
+ },
+ "JwtConfig": {
+ "SigningKey": "crupest hahahahahahahhahahahahaha"
+ }
+}
diff --git a/Timeline/appsettings.json b/Timeline/appsettings.json index 94986fbb..2d0f2b9f 100644 --- a/Timeline/appsettings.json +++ b/Timeline/appsettings.json @@ -1,11 +1,11 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Warning" - } - }, - "JwtConfig": { - "Issuer": "api.crupest.xyz", - "Audience": "api.crupest.xyz" - } -} +{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Warning"
+ }
+ },
+ "JwtConfig": {
+ "Issuer": "api.crupest.xyz",
+ "Audience": "api.crupest.xyz"
+ }
+}
diff --git a/nuget.config b/nuget.config index 6e408d84..22519a86 100644 --- a/nuget.config +++ b/nuget.config @@ -1,8 +1,8 @@ -<?xml version="1.0" encoding="utf-8"?> -<configuration> - <packageSources> - <clear/> - <add key="nuget.org" value="https://api.nuget.org/v3/index.json"/> - <add key="aspnetcore-dev" value="https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json" /> - </packageSources> -</configuration> +<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+ <packageSources>
+ <clear/>
+ <add key="nuget.org" value="https://api.nuget.org/v3/index.json"/>
+ <add key="aspnetcore-dev" value="https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json" />
+ </packageSources>
+</configuration>
diff --git a/tools/convert-eol.py b/tools/convert-eol.py new file mode 100644 index 00000000..3ea8ed7c --- /dev/null +++ b/tools/convert-eol.py @@ -0,0 +1,35 @@ +# This is a python script that converts all text source codes into
+# CRLF (Windows line ending) eol format and UTF-8 with NO BOM encoding.
+
+import glob
+import os.path
+
+project_root = os.path.relpath(os.path.join(os.path.dirname(__file__), '..'))
+
+
+def convert(file_path):
+ with open(file_path, 'r', encoding='utf-8') as open_file:
+ content = open_file.read()
+
+ #if there is BOM, remove BOM
+ if content[0] == '\ufeff':
+ content = content[1:]
+
+ with open(file_path, 'w', encoding='utf-8', newline='\r\n') as open_file:
+ open_file.write(content)
+
+
+glob_list = [
+ './nuget.config',
+ '**/*.sln',
+ '**/*.cs',
+ '**/*.csproj',
+ '**/appsettings*.json'
+]
+
+for glob_pattern in glob_list:
+ for f in glob.glob(glob_pattern, recursive=True):
+ print('Converting {}'.format(f))
+ convert(f)
+
+print('Done!!!')
|