diff --git a/.gitignore b/.gitignore index 6f203acd4..697621123 100644 --- a/.gitignore +++ b/.gitignore @@ -128,6 +128,7 @@ publish/ *.azurePubxml *.pubxml *.pubxml.user +!Release.pubxml # NuGet Packages Directory ## TODO: If you have NuGet Package Restore enabled, uncomment the next line diff --git a/Bonobo.Git.Server.Test/Bonobo.Git.Server.Test.csproj b/Bonobo.Git.Server.Test/Bonobo.Git.Server.Test.csproj index 4a0291c85..e38a19081 100644 --- a/Bonobo.Git.Server.Test/Bonobo.Git.Server.Test.csproj +++ b/Bonobo.Git.Server.Test/Bonobo.Git.Server.Test.csproj @@ -1,223 +1,41 @@ - - - + + - Debug - AnyCPU - {0B124D88-5C2B-47AD-B660-434B709A0DFF} - Library - Properties - Bonobo.Git.Server.Test - Bonobo.Git.Server.Test - v4.6 - 512 - {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 10.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages - False - UnitTest - - - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - true - bin\Test\ - DEBUG;TRACE - full - AnyCPU - prompt - MinimumRecommendedRules.ruleset + netcoreapp2.2 + + false + - - ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll - True - - - ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll - True - - - ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll - True - - - ..\packages\SpecsFor.Mvc.4.8.0\lib\net451\SpecsFor.Mvc.dll - True - - - - - - - ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll - True - - - ..\packages\Microsoft.AspNet.Mvc.Futures.5.0.0\lib\net40\Microsoft.Web.Mvc.dll - True - - - - ..\packages\System.Data.SQLite.Core.1.0.104.0\lib\net46\System.Data.SQLite.dll - True - - - ..\packages\System.Data.SQLite.EF6.1.0.104.0\lib\net46\System.Data.SQLite.EF6.dll - True - - - ..\packages\System.Data.SQLite.Linq.1.0.104.0\lib\net46\System.Data.SQLite.Linq.dll - True - - - - - ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll - True - - - ..\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll - True - - - ..\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll - True - - - ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.dll - True - - - ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Deployment.dll - True - - - ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll - True - - - ..\packages\Selenium.WebDriver.3.3.0\lib\net40\WebDriver.dll - True - - - ..\packages\Selenium.Support.3.3.0\lib\net40\WebDriver.Support.dll - True - + + + + + + - - - - - - - - - - False - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + - - {6129b3fe-b282-4f6f-8836-8af66602f8da} - Bonobo.Git.Server - + + + - - + - - - - - False - - - False - - - False - - - False - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - - - - - - - - - \ No newline at end of file + + diff --git a/Bonobo.Git.Server.Test/MembershipTests/ADTests/ADBackendStoreTest.cs b/Bonobo.Git.Server.Test/MembershipTests/ADTests/ADBackendStoreTest.cs index bcfb1e700..62bfb8dff 100644 --- a/Bonobo.Git.Server.Test/MembershipTests/ADTests/ADBackendStoreTest.cs +++ b/Bonobo.Git.Server.Test/MembershipTests/ADTests/ADBackendStoreTest.cs @@ -2,7 +2,9 @@ using System.IO; using System.Linq; using Bonobo.Git.Server.Data; +using Microsoft.AspNetCore.Hosting; using Microsoft.VisualStudio.TestTools.UnitTesting; +using NSubstitute; namespace Bonobo.Git.Server.Test.MembershipTests.ADTests { @@ -42,7 +44,8 @@ private void SafelyDeleteTestData() private static ADBackendStore MakeStore() { - return new ADBackendStore(Path.GetTempPath(), "BonoboTestStore"); + var hostingEnvironment = Substitute.For(); + return new ADBackendStore(hostingEnvironment, Path.GetTempPath(), "BonoboTestStore"); } [TestMethod] diff --git a/Bonobo.Git.Server.Test/MembershipTests/ADTests/ADPermissionServiceTest.cs b/Bonobo.Git.Server.Test/MembershipTests/ADTests/ADPermissionServiceTest.cs index 9b1d5eaad..8e5b0fb5d 100644 --- a/Bonobo.Git.Server.Test/MembershipTests/ADTests/ADPermissionServiceTest.cs +++ b/Bonobo.Git.Server.Test/MembershipTests/ADTests/ADPermissionServiceTest.cs @@ -31,10 +31,7 @@ private void InitialiseTestObjects() _users = new ADMembershipServiceTestFacade(new ADMembershipService(), _testSupport); _repos = new ADRepositoryRepository(); - _service = new RepositoryPermissionService - { - Repository = _repos, RoleProvider = _roles, TeamRepository = _teams - }; + _service = new RepositoryPermissionService(_repos, _roles, _teams); } protected override TeamModel CreateTeam() diff --git a/Bonobo.Git.Server.Test/MembershipTests/EFTests/EFMembershipServiceTest.cs b/Bonobo.Git.Server.Test/MembershipTests/EFTests/EFMembershipServiceTest.cs index 1ef435350..5f56a6fe8 100644 --- a/Bonobo.Git.Server.Test/MembershipTests/EFTests/EFMembershipServiceTest.cs +++ b/Bonobo.Git.Server.Test/MembershipTests/EFTests/EFMembershipServiceTest.cs @@ -5,6 +5,7 @@ using Bonobo.Git.Server.Data.Update; using Bonobo.Git.Server.Security; using Microsoft.VisualStudio.TestTools.UnitTesting; +using NSubstitute; namespace Bonobo.Git.Server.Test.MembershipTests.EFTests { @@ -19,7 +20,7 @@ public abstract class EFMembershipServiceTest : MembershipServiceTestBase public void UpdatesCanBeRunOnAlreadyUpdatedDatabase() { // Run all the updates again - this should be completely harmless - new AutomaticUpdater().RunWithContext(GetContext()); + new AutomaticUpdater().RunWithContext(GetContext(), Substitute.For()); } [TestMethod] @@ -123,8 +124,8 @@ private BonoboGitServerContext GetContext() protected void InitialiseTestObjects() { - _service = new EFMembershipService {CreateContext = GetContext}; - new AutomaticUpdater().RunWithContext(GetContext()); + _service = new EFMembershipService(GetContext); + new AutomaticUpdater().RunWithContext(GetContext(), Substitute.For()); } } } \ No newline at end of file diff --git a/Bonobo.Git.Server.Test/MembershipTests/EFTests/EFPermissionServiceTest.cs b/Bonobo.Git.Server.Test/MembershipTests/EFTests/EFPermissionServiceTest.cs index 0574023e1..19dac662e 100644 --- a/Bonobo.Git.Server.Test/MembershipTests/EFTests/EFPermissionServiceTest.cs +++ b/Bonobo.Git.Server.Test/MembershipTests/EFTests/EFPermissionServiceTest.cs @@ -3,6 +3,7 @@ using Bonobo.Git.Server.Models; using Bonobo.Git.Server.Security; using Microsoft.VisualStudio.TestTools.UnitTesting; +using NSubstitute; namespace Bonobo.Git.Server.Test.MembershipTests.EFTests { @@ -44,19 +45,14 @@ public abstract class EFPermissionServiceTest : PermissionServiceTestBase protected void InitialiseTestObjects() { - _teams = new EFTeamRepository { CreateContext = () => _connection.GetContext() }; - _users = new EFMembershipService { CreateContext = () => _connection.GetContext() }; - _repos = new EFRepositoryRepository { CreateContext = () => _connection.GetContext() }; - _roles = new EFRoleProvider { CreateContext = () => _connection.GetContext() }; + _teams = new EFTeamRepository(() => _connection.GetContext()); + _users = new EFMembershipService(() => _connection.GetContext()); + _repos = new EFRepositoryRepository(() => _connection.GetContext()); + _roles = new EFRoleProvider(() => _connection.GetContext() ); - _service = new RepositoryPermissionService - { - Repository = _repos, - TeamRepository = _teams, - RoleProvider = _roles - }; + _service = new RepositoryPermissionService(_repos, _roles, _teams); - new AutomaticUpdater().RunWithContext(_connection.GetContext()); + new AutomaticUpdater().RunWithContext(_connection.GetContext(), Substitute.For()); } protected override TeamModel CreateTeam() diff --git a/Bonobo.Git.Server.Test/MembershipTests/EFTests/EFRepositoryRepositoryTest.cs b/Bonobo.Git.Server.Test/MembershipTests/EFTests/EFRepositoryRepositoryTest.cs index 51670c9ed..9acb862ad 100644 --- a/Bonobo.Git.Server.Test/MembershipTests/EFTests/EFRepositoryRepositoryTest.cs +++ b/Bonobo.Git.Server.Test/MembershipTests/EFTests/EFRepositoryRepositoryTest.cs @@ -3,6 +3,7 @@ using Bonobo.Git.Server.Models; using Bonobo.Git.Server.Security; using Microsoft.VisualStudio.TestTools.UnitTesting; +using NSubstitute; namespace Bonobo.Git.Server.Test.MembershipTests.EFTests { @@ -44,14 +45,14 @@ public abstract class EFRepositoryRepositoryTest : RepositoryRepositoryTestBase protected override UserModel AddUserFred() { - IMembershipService memberService = new EFMembershipService { CreateContext = GetContext }; + IMembershipService memberService = new EFMembershipService(GetContext); memberService.CreateUser("fred", "letmein", "Fred", "Blogs", "fred@aol"); return memberService.GetUserModel("fred"); } protected override TeamModel AddTeam() { - EFTeamRepository teams = new EFTeamRepository { CreateContext = GetContext }; + EFTeamRepository teams = new EFTeamRepository(GetContext); var newTeam = new TeamModel { Name="Team1" }; teams.Create(newTeam); return newTeam; @@ -64,8 +65,8 @@ BonoboGitServerContext GetContext() protected void InitialiseTestObjects() { - _repo = new EFRepositoryRepository {CreateContext = () => _connection.GetContext()}; - new AutomaticUpdater().RunWithContext(_connection.GetContext()); + _repo = new EFRepositoryRepository(() => _connection.GetContext()); + new AutomaticUpdater().RunWithContext(_connection.GetContext(), Substitute.For()); } } } \ No newline at end of file diff --git a/Bonobo.Git.Server.Test/MembershipTests/EFTests/EFRoleProviderTest.cs b/Bonobo.Git.Server.Test/MembershipTests/EFTests/EFRoleProviderTest.cs index 0ec799cb8..bae54bae1 100644 --- a/Bonobo.Git.Server.Test/MembershipTests/EFTests/EFRoleProviderTest.cs +++ b/Bonobo.Git.Server.Test/MembershipTests/EFTests/EFRoleProviderTest.cs @@ -4,6 +4,7 @@ using Bonobo.Git.Server.Data.Update; using Bonobo.Git.Server.Security; using Microsoft.VisualStudio.TestTools.UnitTesting; +using NSubstitute; namespace Bonobo.Git.Server.Test.MembershipTests.EFTests { @@ -48,7 +49,7 @@ public abstract class EFRoleProviderTest public void UpdatesCanBeRunOnAlreadyUpdatedDatabase() { // Run all the updates again - this should be completely harmless - new AutomaticUpdater().RunWithContext(GetContext()); + new AutomaticUpdater().RunWithContext(GetContext(), Substitute.For()); } [TestMethod] @@ -148,14 +149,14 @@ public void TestRoleCanBeDeletedWhilePopulatedIfAllowed() Guid AddUserFred() { - EFMembershipService memberService = new EFMembershipService { CreateContext = GetContext }; + EFMembershipService memberService = new EFMembershipService(GetContext); memberService.CreateUser("fred", "letmein", "Fred", "FredBlogs", "fred@aol"); return memberService.GetUserModel("fred").Id; } Guid GetAdminId() { - EFMembershipService memberService = new EFMembershipService { CreateContext = GetContext }; + EFMembershipService memberService = new EFMembershipService(GetContext); return memberService.GetUserModel("Admin").Id; } @@ -166,8 +167,8 @@ private BonoboGitServerContext GetContext() protected void InitialiseTestObjects() { - _provider = new EFRoleProvider {CreateContext = () => _connection.GetContext()}; - new AutomaticUpdater().RunWithContext(_connection.GetContext()); + _provider = new EFRoleProvider(() => _connection.GetContext()); + new AutomaticUpdater().RunWithContext(_connection.GetContext(), Substitute.For()); } } } \ No newline at end of file diff --git a/Bonobo.Git.Server.Test/MembershipTests/EFTests/EFTeamRepositoryTests.cs b/Bonobo.Git.Server.Test/MembershipTests/EFTests/EFTeamRepositoryTests.cs index 238b1d660..63cc3dae1 100644 --- a/Bonobo.Git.Server.Test/MembershipTests/EFTests/EFTeamRepositoryTests.cs +++ b/Bonobo.Git.Server.Test/MembershipTests/EFTests/EFTeamRepositoryTests.cs @@ -6,6 +6,7 @@ using Bonobo.Git.Server.Models; using Bonobo.Git.Server.Security; using Microsoft.VisualStudio.TestTools.UnitTesting; +using NSubstitute; namespace Bonobo.Git.Server.Test.MembershipTests.EFTests { @@ -49,9 +50,9 @@ public abstract class EFTeamRepositoryTests : TeamRepositoryTestsBase protected void InitialiseTestObjects() { - _repo = new EFTeamRepository {CreateContext = () => _connection.GetContext()}; - _membershipService = new EFMembershipService { CreateContext = () => _connection.GetContext() }; - new AutomaticUpdater().RunWithContext(_connection.GetContext()); + _repo = new EFTeamRepository(() => _connection.GetContext()); + _membershipService = new EFMembershipService(() => _connection.GetContext()); + new AutomaticUpdater().RunWithContext(_connection.GetContext(), Substitute.For()); } protected override bool CreateTeam(TeamModel team) diff --git a/Bonobo.Git.Server.Test/MembershipTests/EFTests/SqlServerTestConnection.cs b/Bonobo.Git.Server.Test/MembershipTests/EFTests/SqlServerTestConnection.cs index 869bac6c2..125ec2831 100644 --- a/Bonobo.Git.Server.Test/MembershipTests/EFTests/SqlServerTestConnection.cs +++ b/Bonobo.Git.Server.Test/MembershipTests/EFTests/SqlServerTestConnection.cs @@ -2,12 +2,13 @@ using System.Data.SqlClient; using System.IO; using Bonobo.Git.Server.Data; +using Microsoft.EntityFrameworkCore; namespace Bonobo.Git.Server.Test.MembershipTests.EFTests { class SqlServerTestConnection : IDatabaseTestConnection { - readonly SqlConnection _connection; + readonly DbContextOptionsBuilder _optionsBuilder; private readonly string _databaseName; private static readonly string _instanceName; @@ -52,13 +53,15 @@ public SqlServerTestConnection() Console.WriteLine("Created test database: " + fileName); - _connection = new SqlConnection(String.Format(@"Data Source=(LocalDB)\{0};Integrated Security=True;AttachDbFilename={1};Initial Catalog={2}", _instanceName, fileName, _databaseName)); - _connection.Open(); + _optionsBuilder = new DbContextOptionsBuilder(); + _optionsBuilder.UseSqlServer(string.Format( + @"Data Source=(LocalDB)\{0};Integrated Security=True;AttachDbFilename={1};Initial Catalog={2}", + _instanceName, fileName, _databaseName)); } public BonoboGitServerContext GetContext() { - return BonoboGitServerContext.FromDatabase(_connection); + return new BonoboGitServerContext(_optionsBuilder.Options); } void CreateDB(string fileName) @@ -96,7 +99,6 @@ private void Exec(SqlConnection connection, string commandText) public void Dispose() { - _connection.Dispose(); SqlConnection.ClearAllPools(); TryToDeleteDatabaseFiles(); } diff --git a/Bonobo.Git.Server.Test/MembershipTests/EFTests/SqliteTestConnection.cs b/Bonobo.Git.Server.Test/MembershipTests/EFTests/SqliteTestConnection.cs index 0e0fc99d4..604e9d12a 100644 --- a/Bonobo.Git.Server.Test/MembershipTests/EFTests/SqliteTestConnection.cs +++ b/Bonobo.Git.Server.Test/MembershipTests/EFTests/SqliteTestConnection.cs @@ -1,6 +1,8 @@ using System; using System.Data.Common; using Bonobo.Git.Server.Data; +using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore; namespace Bonobo.Git.Server.Test.MembershipTests.EFTests { @@ -11,18 +13,20 @@ public interface IDatabaseTestConnection : IDisposable class SqliteTestConnection : IDatabaseTestConnection { - readonly DbConnection _connection; + private readonly DbConnection _connection; public SqliteTestConnection() { - _connection = DbProviderFactories.GetFactory("System.Data.SQLite").CreateConnection(); - _connection.ConnectionString = "Data Source =:memory:;BinaryGUID=False"; + _connection = SqliteFactory.Instance.CreateConnection(); + _connection.ConnectionString = "Data Source =:memory:"; _connection.Open(); } public BonoboGitServerContext GetContext() { - return BonoboGitServerContext.FromDatabase(_connection); + var optionsBuilder = new DbContextOptionsBuilder(); + optionsBuilder.UseSqlite(_connection); + return new BonoboGitServerContext(optionsBuilder.Options); } public void Dispose() diff --git a/Bonobo.Git.Server.Test/Properties/AssemblyInfo.cs b/Bonobo.Git.Server.Test/Properties/AssemblyInfo.cs deleted file mode 100644 index 5307292ec..000000000 --- a/Bonobo.Git.Server.Test/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Bonobo.Git.Server.Test")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Bonobo.Git.Server.Test")] -[assembly: AssemblyCopyright("Copyright © 2013")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("94027fbc-c2ed-4081-bed2-8148b04215cd")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Bonobo.Git.Server.Test/TestCategories.cs b/Bonobo.Git.Server.Test/TestCategories.cs index 722cda47b..c1c700755 100644 --- a/Bonobo.Git.Server.Test/TestCategories.cs +++ b/Bonobo.Git.Server.Test/TestCategories.cs @@ -1,9 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - namespace Bonobo.Git.Server.Test { public static class TestCategories @@ -19,4 +13,4 @@ public static class TestCategories public const string AuthWindows = "AuthWindowsAuth"; public const string AuthADFS = "AuthADFS"; } -} +} \ No newline at end of file diff --git a/Bonobo.Git.Server.Test/UnitTests/CustomHtmlHelperTest.cs b/Bonobo.Git.Server.Test/UnitTests/CustomHtmlHelperTest.cs index 95f2984a4..dd67224dd 100644 --- a/Bonobo.Git.Server.Test/UnitTests/CustomHtmlHelperTest.cs +++ b/Bonobo.Git.Server.Test/UnitTests/CustomHtmlHelperTest.cs @@ -1,7 +1,6 @@ using System.ComponentModel.DataAnnotations; -using System.Web.Mvc; -using Bonobo.Git.Server.Data; using Bonobo.Git.Server.Helpers; +using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Bonobo.Git.Server.Test.UnitTests @@ -9,7 +8,7 @@ namespace Bonobo.Git.Server.Test.UnitTests [TestClass] public class CustomHtmlHelperTest { - readonly HtmlHelper Html = new HtmlHelper(new ViewContext(), new ViewPage()); + private readonly IHtmlHelper Html; [TestMethod] public void EnumsWithDisplayAttributesAreFormatted() diff --git a/Bonobo.Git.Server.Test/UnitTests/DatabaseUpdateTestsSqlServer.cs b/Bonobo.Git.Server.Test/UnitTests/DatabaseUpdateTestsSqlServer.cs index d7c399558..d821a3e41 100644 --- a/Bonobo.Git.Server.Test/UnitTests/DatabaseUpdateTestsSqlServer.cs +++ b/Bonobo.Git.Server.Test/UnitTests/DatabaseUpdateTestsSqlServer.cs @@ -3,6 +3,7 @@ using Bonobo.Git.Server.Test.MembershipTests.EFTests; using Bonobo.Git.Server.Data.Update; using Bonobo.Git.Server.Data; +using Microsoft.EntityFrameworkCore; namespace Bonobo.Git.Server.Test.UnitTests { diff --git a/Bonobo.Git.Server.Test/UnitTests/DatabaseUpdateTestsSqlite.cs b/Bonobo.Git.Server.Test/UnitTests/DatabaseUpdateTestsSqlite.cs index 1067bf137..8d3f55df1 100644 --- a/Bonobo.Git.Server.Test/UnitTests/DatabaseUpdateTestsSqlite.cs +++ b/Bonobo.Git.Server.Test/UnitTests/DatabaseUpdateTestsSqlite.cs @@ -3,6 +3,9 @@ using Bonobo.Git.Server.Test.MembershipTests.EFTests; using Bonobo.Git.Server.Data.Update; using Bonobo.Git.Server.Data; +using Bonobo.Git.Server.Security; +using Microsoft.EntityFrameworkCore; +using NSubstitute; namespace Bonobo.Git.Server.Test.UnitTests { @@ -91,7 +94,7 @@ Foreign Key ([Team_Name]) References [Team]([Name]) ); "); - new AutomaticUpdater().RunWithContext(_connection.GetContext()); + new AutomaticUpdater().RunWithContext(_connection.GetContext(), Substitute.For()); } [TestMethod] diff --git a/Bonobo.Git.Server.Test/UnitTests/GitAuthorizeAttributeTest.cs b/Bonobo.Git.Server.Test/UnitTests/GitAuthorizeAttributeTest.cs index e7081ef95..79acddc8d 100644 --- a/Bonobo.Git.Server.Test/UnitTests/GitAuthorizeAttributeTest.cs +++ b/Bonobo.Git.Server.Test/UnitTests/GitAuthorizeAttributeTest.cs @@ -10,9 +10,9 @@ public class GitAuthorizeAttributeTest [TestMethod] public void GetRepoPathTest() { - var repo = GitAuthorizeAttribute.GetRepoPath("/other/test.git/info/refs", "/other"); + var repo = GitAuthorizationHandler.GetRepoPath("/other/test.git/info/refs", "/other"); Assert.AreEqual("test", repo); - repo = GitAuthorizeAttribute.GetRepoPath("/test.git/info/refs", "/"); + repo = GitAuthorizationHandler.GetRepoPath("/test.git/info/refs", "/"); Assert.AreEqual("test", repo); } } diff --git a/Bonobo.Git.Server.Test/app.config b/Bonobo.Git.Server.Test/app.config deleted file mode 100644 index 7cd250804..000000000 --- a/Bonobo.Git.Server.Test/app.config +++ /dev/null @@ -1,80 +0,0 @@ - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Bonobo.Git.Server.Test/packages.config b/Bonobo.Git.Server.Test/packages.config deleted file mode 100644 index ba78b3b29..000000000 --- a/Bonobo.Git.Server.Test/packages.config +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Bonobo.Git.Server.sln b/Bonobo.Git.Server.sln index bf06ec7ef..d84fa0f08 100644 --- a/Bonobo.Git.Server.sln +++ b/Bonobo.Git.Server.sln @@ -1,60 +1,31 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29001.49 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bonobo.Git.Server", "Bonobo.Git.Server\Bonobo.Git.Server.csproj", "{6129B3FE-B282-4F6F-8836-8AF66602F8DA}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bonobo.Git.Server", "Bonobo.Git.Server\Bonobo.Git.Server.csproj", "{7E7F9919-537C-4735-BFE8-80B24D3A2DE8}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bonobo.Git.Server.Test", "Bonobo.Git.Server.Test\Bonobo.Git.Server.Test.csproj", "{0B124D88-5C2B-47AD-B660-434B709A0DFF}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bonobo.Git.Server.Test", "Bonobo.Git.Server.Test\Bonobo.Git.Server.Test.csproj", "{4517FCEF-5456-48AC-9909-7246F8104E5C}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU - Debug|Mixed Platforms = Debug|Mixed Platforms - Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU - Release|Mixed Platforms = Release|Mixed Platforms - Release|x86 = Release|x86 - Test|Any CPU = Test|Any CPU - Test|Mixed Platforms = Test|Mixed Platforms - Test|x86 = Test|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {6129B3FE-B282-4F6F-8836-8AF66602F8DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6129B3FE-B282-4F6F-8836-8AF66602F8DA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6129B3FE-B282-4F6F-8836-8AF66602F8DA}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {6129B3FE-B282-4F6F-8836-8AF66602F8DA}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {6129B3FE-B282-4F6F-8836-8AF66602F8DA}.Debug|x86.ActiveCfg = Debug|Any CPU - {6129B3FE-B282-4F6F-8836-8AF66602F8DA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6129B3FE-B282-4F6F-8836-8AF66602F8DA}.Release|Any CPU.Build.0 = Release|Any CPU - {6129B3FE-B282-4F6F-8836-8AF66602F8DA}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {6129B3FE-B282-4F6F-8836-8AF66602F8DA}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {6129B3FE-B282-4F6F-8836-8AF66602F8DA}.Release|x86.ActiveCfg = Release|Any CPU - {6129B3FE-B282-4F6F-8836-8AF66602F8DA}.Test|Any CPU.ActiveCfg = Test|Any CPU - {6129B3FE-B282-4F6F-8836-8AF66602F8DA}.Test|Any CPU.Build.0 = Test|Any CPU - {6129B3FE-B282-4F6F-8836-8AF66602F8DA}.Test|Mixed Platforms.ActiveCfg = Test|Any CPU - {6129B3FE-B282-4F6F-8836-8AF66602F8DA}.Test|Mixed Platforms.Build.0 = Test|Any CPU - {6129B3FE-B282-4F6F-8836-8AF66602F8DA}.Test|x86.ActiveCfg = Test|Any CPU - {0B124D88-5C2B-47AD-B660-434B709A0DFF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0B124D88-5C2B-47AD-B660-434B709A0DFF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0B124D88-5C2B-47AD-B660-434B709A0DFF}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {0B124D88-5C2B-47AD-B660-434B709A0DFF}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {0B124D88-5C2B-47AD-B660-434B709A0DFF}.Debug|x86.ActiveCfg = Debug|Any CPU - {0B124D88-5C2B-47AD-B660-434B709A0DFF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0B124D88-5C2B-47AD-B660-434B709A0DFF}.Release|Any CPU.Build.0 = Release|Any CPU - {0B124D88-5C2B-47AD-B660-434B709A0DFF}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {0B124D88-5C2B-47AD-B660-434B709A0DFF}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {0B124D88-5C2B-47AD-B660-434B709A0DFF}.Release|x86.ActiveCfg = Release|Any CPU - {0B124D88-5C2B-47AD-B660-434B709A0DFF}.Test|Any CPU.ActiveCfg = Test|Any CPU - {0B124D88-5C2B-47AD-B660-434B709A0DFF}.Test|Any CPU.Build.0 = Test|Any CPU - {0B124D88-5C2B-47AD-B660-434B709A0DFF}.Test|Mixed Platforms.ActiveCfg = Test|Any CPU - {0B124D88-5C2B-47AD-B660-434B709A0DFF}.Test|Mixed Platforms.Build.0 = Test|Any CPU - {0B124D88-5C2B-47AD-B660-434B709A0DFF}.Test|x86.ActiveCfg = Test|Any CPU + {7E7F9919-537C-4735-BFE8-80B24D3A2DE8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7E7F9919-537C-4735-BFE8-80B24D3A2DE8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7E7F9919-537C-4735-BFE8-80B24D3A2DE8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7E7F9919-537C-4735-BFE8-80B24D3A2DE8}.Release|Any CPU.Build.0 = Release|Any CPU + {4517FCEF-5456-48AC-9909-7246F8104E5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4517FCEF-5456-48AC-9909-7246F8104E5C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4517FCEF-5456-48AC-9909-7246F8104E5C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4517FCEF-5456-48AC-9909-7246F8104E5C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - EnterpriseLibraryConfigurationToolBinariesPath = packages\Unity.2.1.505.2\lib\NET35 + SolutionGuid = {D7177A2D-3FB7-46B2-8371-D9B3D24498A7} EndGlobalSection EndGlobal diff --git a/Bonobo.Git.Server/App.config b/Bonobo.Git.Server/App.config new file mode 100644 index 000000000..93d49879d --- /dev/null +++ b/Bonobo.Git.Server/App.config @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Bonobo.Git.Server/App_GlobalResources/Resources.Designer.cs b/Bonobo.Git.Server/App_GlobalResources/Resources.Designer.cs index eafec560a..5317b5e50 100644 --- a/Bonobo.Git.Server/App_GlobalResources/Resources.Designer.cs +++ b/Bonobo.Git.Server/App_GlobalResources/Resources.Designer.cs @@ -19,7 +19,7 @@ namespace Bonobo.Git.Server.App_GlobalResources { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] public class Resources { diff --git a/Bonobo.Git.Server/App_GlobalResources/Resources.it-IT.designer.cs b/Bonobo.Git.Server/App_GlobalResources/Resources.it-IT.designer.cs deleted file mode 100644 index e69de29bb..000000000 diff --git a/Bonobo.Git.Server/App_Start/BundleConfig.cs b/Bonobo.Git.Server/App_Start/BundleConfig.cs deleted file mode 100644 index 58dbf656c..000000000 --- a/Bonobo.Git.Server/App_Start/BundleConfig.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Bonobo.Git.Server.Helpers; -using System.Web.Optimization; - -namespace Bonobo.Git.Server.App_Start -{ - public class BundleConfig - { - // For more information on bundling, visit http://go.microsoft.com/fwlink/?LinkId=301862 - public static void RegisterBundles(BundleCollection bundles) - { - - bundles.Add(new ScriptBundle("~/bundledJs") - .Include("~/Scripts/jquery-{version}.js") - .Include("~/Scripts/jquery.validate*", "~/Content/uni/js/uni-form-validation.jquery.js", "~/Scripts/MicrosoftAjax.js", "~/Scripts/MicrosoftMvcAjax.js") - .Include("~/Scripts/highlight.pack.js") - .Include("~/Scripts/clipboard.min.js")); - - bundles.Add(new StyleBundle("~/Content/bundledCss") - .Include("~/Content/components/pure/pure-min.css", new CssRewriteUrlTransformWrapper()) - .Include("~/Content/components/font-awesome/css/font-awesome.min.css", new CssRewriteUrlTransformWrapper()) - .Include("~/Content/components/highlight/styles/github.css") - .Include("~/Content/fonts.css", "~/Content/site.css")); - } - } -} \ No newline at end of file diff --git a/Bonobo.Git.Server/App_Start/RouteConfig.cs b/Bonobo.Git.Server/App_Start/RouteConfig.cs index fafd1d6be..6f13791d6 100644 --- a/Bonobo.Git.Server/App_Start/RouteConfig.cs +++ b/Bonobo.Git.Server/App_Start/RouteConfig.cs @@ -1,32 +1,32 @@ -using System; -using System.Web.Mvc; -using System.Web.Routing; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Routing; +using Microsoft.AspNetCore.Routing.Constraints; namespace Bonobo.Git.Server.App_Start { public class RouteConfig { - public static void RegisterRoutes(RouteCollection routes) + public static IRouteBuilder RegisterRoutes(IRouteBuilder routes) { routes.MapRoute("SecureInfoRefs", "{repositoryName}.git/info/refs", new { controller = "Git", action = "SecureGetInfoRefs" }, - new { method = new HttpMethodConstraint("GET") }); + new { method = new HttpMethodRouteConstraint("GET") }); routes.MapRoute("SecureUploadPack", "{repositoryName}.git/git-upload-pack", new { controller = "Git", action = "SecureUploadPack" }, - new { method = new HttpMethodConstraint("POST") }); + new { method = new HttpMethodRouteConstraint("POST") }); routes.MapRoute("SecureReceivePack", "{repositoryName}.git/git-receive-pack", new { controller = "Git", action = "SecureReceivePack" }, - new { method = new HttpMethodConstraint("POST") }); + new { method = new HttpMethodRouteConstraint("POST") }); routes.MapRoute("GitBaseUrl", "{repositoryName}.git", new { controller = "Git", action = "GitUrl" }, - new { method = new HttpMethodConstraint("GET") }); + new { method = new HttpMethodRouteConstraint("GET") }); routes.MapRoute("IndexRoute", "{controller}/Index/", @@ -71,34 +71,37 @@ public static void RegisterRoutes(RouteCollection routes) new { id = @"\d+" }); routes.MapRoute("Repository", - "Repository/{id}/{action}/{reponame}", - new { controller = "Repository", action = "Detail", reponame = UrlParameter.Optional }, + "Repository/{id}/{action}/{reponame?}", + new { controller = "Repository", action = "Detail" }, new { id = @"\d+" }); routes.MapRoute("Account", - "Account/{id}/{action}/{username}", - new { controller = "Account", action = "Detail", username = UrlParameter.Optional }, + "Account/{id}/{action}/{username?}", + new { controller = "Account", action = "Detail" }, new { id = @"\d+" }); routes.MapRoute("Team", - "Team/{id}/{action}/{teamname}", - new { controller = "Team", action = "Detail", teamname = UrlParameter.Optional }, + "Team/{id}/{action}/{teamname?}", + new { controller = "Team", action = "Detail" }, new { id = @"\d+" }); - routes.MapRoute("Validation", "Validation/{action}", new { controller = "Validation", action = String.Empty }); + routes.MapRoute("Validation", "Validation/{action}", + new {controller = "Validation", action = string.Empty}); routes.MapRoute("RepoCommits", - "Repository/Commits/{id}", - new { controller = "Repository", action = "Commits", id = string.Empty}); + "Repository/Commits/{id?}", + new { controller = "Repository", action = "Commits"}); routes.MapRoute("Default", - "{controller}/{action}/{id}", - new { controller = "Home", action = "Index", id = String.Empty }); + "{controller}/{action}/{id?}", + new { controller = "Home", action = "Index" }); - routes.IgnoreRoute("{*favicon}", new { favicon = @"(.*/)?favicon.ico(/.*)?" }); + //routes.IgnoreRoute("{*favicon}", new { favicon = @"(.*/)?favicon.ico(/.*)?" }); - routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); + //routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); + + return routes; } } } \ No newline at end of file diff --git a/Bonobo.Git.Server/Attributes/AllViewsAttribute.cs b/Bonobo.Git.Server/Attributes/AllViewsAttribute.cs index 63477e8d6..088453231 100644 --- a/Bonobo.Git.Server/Attributes/AllViewsAttribute.cs +++ b/Bonobo.Git.Server/Attributes/AllViewsAttribute.cs @@ -1,11 +1,14 @@ using Bonobo.Git.Server.App_GlobalResources; using Bonobo.Git.Server.Models; using Bonobo.Git.Server.Security; -using Microsoft.Practices.Unity; using System; using System.Collections.Generic; using System.Linq; -using System.Web.Mvc; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.AspNetCore.Mvc.Infrastructure; +using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.AspNetCore.Mvc.Routing; namespace Bonobo.Git.Server.Attributes { @@ -33,15 +36,24 @@ public int GetHashCode(T obj) public class AllViewsFilter : ActionFilterAttribute { - [Dependency] public IRepositoryPermissionService RepoPermissions { get; set; } + private readonly IActionContextAccessor _actionContextAccessor; + + public AllViewsFilter(IRepositoryPermissionService repoPermissions, IActionContextAccessor actionContextAccessor) + { + RepoPermissions = repoPermissions; + _actionContextAccessor = actionContextAccessor; + } + public override void OnActionExecuting(ActionExecutingContext filterContext) { - filterContext.Controller.ViewBag.PermittedRepositories = PopulateRepoGoToList(filterContext.HttpContext.User.Id(), filterContext.Controller.ControllerContext); + Controller controler = filterContext.Controller as Controller; + if (controler == null) return; + controler.ViewBag.PermittedRepositories = PopulateRepoGoToList(filterContext.HttpContext.User.Id()); } - private List PopulateRepoGoToList(Guid id, ControllerContext ControllerContext) + private List PopulateRepoGoToList(Guid id) { var pullList = RepoPermissions.GetAllPermittedRepositories(id, RepositoryAccessLevel.Pull); var adminList = RepoPermissions.GetAllPermittedRepositories(id, RepositoryAccessLevel.Administer); @@ -49,7 +61,7 @@ private List PopulateRepoGoToList(Guid id, ControllerContext Con .OrderBy(x => x.Name.ToLowerInvariant()) .GroupBy(x => x.Group == null ? Resources.Repository_No_Group : x.Group); List items = new List(); - var u = new UrlHelper(ControllerContext.RequestContext); + var u = new UrlHelper(_actionContextAccessor.ActionContext); var groups = new Dictionary(); foreach (var grouped in firstList) { diff --git a/Bonobo.Git.Server/Attributes/FileExtensionsCustom.cs b/Bonobo.Git.Server/Attributes/FileExtensionsCustom.cs index 4346662b3..0d577cb45 100644 --- a/Bonobo.Git.Server/Attributes/FileExtensionsCustom.cs +++ b/Bonobo.Git.Server/Attributes/FileExtensionsCustom.cs @@ -6,6 +6,7 @@ using System.IO; using System.Linq; using System.Web; +using Microsoft.AspNetCore.Http; namespace Bonobo.Git.Server.Attributes { @@ -74,7 +75,7 @@ public override bool IsValid(object value) return true; } - HttpPostedFileBase valueAsString = value as HttpPostedFileBase; + IFormFile valueAsString = value as IFormFile; if (valueAsString != null) { diff --git a/Bonobo.Git.Server/Attributes/GitAuthorizeAttribute.cs b/Bonobo.Git.Server/Attributes/GitAuthorizeAttribute.cs index f0b547206..4a0e0a68a 100644 --- a/Bonobo.Git.Server/Attributes/GitAuthorizeAttribute.cs +++ b/Bonobo.Git.Server/Attributes/GitAuthorizeAttribute.cs @@ -1,92 +1,45 @@ using System; -using System.Net; using System.Security.Claims; using System.Text; -using System.Web; -using System.Web.Mvc; +using System.Threading.Tasks; using Bonobo.Git.Server.Data; using Bonobo.Git.Server.Security; -using Microsoft.Practices.Unity; using Bonobo.Git.Server.Helpers; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; using Serilog; namespace Bonobo.Git.Server { - public class GitAuthorizeAttribute : AuthorizeAttribute + public class GitRequirement : IAuthorizationRequirement + { } + + public class GitAuthorizationHandler : AuthorizationHandler { - [Dependency] + private readonly IHttpContextAccessor _httpContextAccessor; public IMembershipService MembershipService { get; set; } - - [Dependency] public IAuthenticationProvider AuthenticationProvider { get; set; } - - [Dependency] public IRepositoryPermissionService RepositoryPermissionService { get; set; } - - [Dependency] public IRepositoryRepository RepositoryRepository { get; set; } - public static string GetRepoPath(string path, string applicationPath) + public GitAuthorizationHandler(IHttpContextAccessor httpContextAccessor, IMembershipService membershipService, + IAuthenticationProvider authenticationProvider, IRepositoryPermissionService repositoryPermissionService, + IRepositoryRepository repositoryRepository) { - var repo = path.Replace(applicationPath, "").Replace("/",""); - return repo.Substring(0, repo.IndexOf(".git")); + _httpContextAccessor = httpContextAccessor; + MembershipService = membershipService; + AuthenticationProvider = authenticationProvider; + RepositoryPermissionService = repositoryPermissionService; + RepositoryRepository = repositoryRepository; } - public override void OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext) + public static string GetRepoPath(string path, string applicationPath) { - if (filterContext == null) - { - throw new ArgumentNullException("filterContext"); - } - - HttpContextBase httpContext = filterContext.HttpContext; - - string incomingRepoName = GetRepoPath(httpContext.Request.Path, httpContext.Request.ApplicationPath); - string repoName = Repository.NormalizeRepositoryName(incomingRepoName, RepositoryRepository); - - // Add header to prevent redirection to login page even if we fail auth later (see IAuthenticationProvider.Configure) - // If we don't fail auth later, then this is benign - httpContext.Request.Headers.Add("AuthNoRedirect", "1"); - - if (httpContext.Request.IsAuthenticated && httpContext.User != null && httpContext.User.Identity is System.Security.Claims.ClaimsIdentity) - { - // We already have a claims id, we don't need to worry about the rest of these checks - Log.Verbose("GitAuth: User {username} already has identity", httpContext.User.DisplayName()); - return; - } - - string authHeader = httpContext.Request.Headers["Authorization"]; - - if (String.IsNullOrEmpty(authHeader)) - { - // We don't have an auth header, but if we're doing an anonymous operation, that's OK - if (RepositoryPermissionService.HasPermission(Guid.Empty, repoName, RepositoryAccessLevel.Pull)) - { - // Allow this through. If it turns out they're actually trying to do an anon push and that's not allowed for this repo - // then the GitController will reject them in there - Log.Information("GitAuth: No auth header, anon operation may be allowed"); - return; - } - else - { - // If we're not even allowed to do an anonymous pull, then we should bounce this now, - // and tell the other end to try again with an auth header included next time - httpContext.Response.Headers.Add("WWW-Authenticate", "Basic realm=\"Bonobo Git\""); - filterContext.Result = new HttpStatusCodeResult(HttpStatusCode.Unauthorized); - - Log.Warning("GitAuth: No auth header, anon operations not allowed"); - return; - } - } - - // Process the auth header and see if we've been given valid credentials - if (!IsUserAuthorized(authHeader, httpContext)) - { - filterContext.Result = new HttpStatusCodeResult(HttpStatusCode.Unauthorized); - } + var repo = path.Replace(applicationPath, "").Replace("/",""); + return repo.Substring(0, repo.IndexOf(".git")); } - private bool IsUserAuthorized(string authHeader, HttpContextBase httpContext) + private bool IsUserAuthorized(string authHeader, HttpContext httpContext) { byte[] encodedDataAsBytes = Convert.FromBase64String(authHeader.Replace("Basic ", String.Empty)); string value = Encoding.ASCII.GetString(encodedDataAsBytes); @@ -135,5 +88,63 @@ private bool IsUserAuthorized(string authHeader, HttpContextBase httpContext) Log.Warning("GitAuth: User {username} not authorized", username); return false; } + + protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, GitRequirement requirement) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + HttpContext httpContext = _httpContextAccessor.HttpContext; + + string incomingRepoName = GetRepoPath(httpContext.Request.Path, httpContext.Request.PathBase); + string repoName = Repository.NormalizeRepositoryName(incomingRepoName, RepositoryRepository); + + // Add header to prevent redirection to login page even if we fail auth later (see IAuthenticationProvider.Configure) + // If we don't fail auth later, then this is benign + httpContext.Request.Headers.Add("AuthNoRedirect", "1"); + + if (context.User != null && context.User.Identity.IsAuthenticated && context.User.Identity is ClaimsIdentity) + { + // We already have a claims id, we don't need to worry about the rest of these checks + Log.Verbose("GitAuth: User {username} already has identity", httpContext.User.DisplayName()); + context.Succeed(requirement); + return Task.FromResult(0); + } + + string authHeader = httpContext.Request.Headers["Authorization"]; + + if (String.IsNullOrEmpty(authHeader)) + { + // We don't have an auth header, but if we're doing an anonymous operation, that's OK + if (RepositoryPermissionService.HasPermission(Guid.Empty, repoName, RepositoryAccessLevel.Pull)) + { + // Allow this through. If it turns out they're actually trying to do an anon push and that's not allowed for this repo + // then the GitController will reject them in there + Log.Information("GitAuth: No auth header, anon operation may be allowed"); + context.Succeed(requirement); + return Task.FromResult(0); + } + else + { + // If we're not even allowed to do an anonymous pull, then we should bounce this now, + // and tell the other end to try again with an auth header included next time + httpContext.Response.Headers.Add("WWW-Authenticate", "Basic realm=\"Bonobo Git\""); + context.Fail(); + + Log.Warning("GitAuth: No auth header, anon operations not allowed"); + return Task.FromResult(0); + } + } + + // Process the auth header and see if we've been given valid credentials + if (!IsUserAuthorized(authHeader, httpContext)) + { + context.Fail(); + } + + return Task.FromResult(0); + } } } \ No newline at end of file diff --git a/Bonobo.Git.Server/Attributes/IsValidRegexAttribute.cs b/Bonobo.Git.Server/Attributes/IsValidRegexAttribute.cs index 3bbbd6b56..1afa672ed 100644 --- a/Bonobo.Git.Server/Attributes/IsValidRegexAttribute.cs +++ b/Bonobo.Git.Server/Attributes/IsValidRegexAttribute.cs @@ -1,14 +1,7 @@ -using Bonobo.Git.Server.Data; -using Bonobo.Git.Server.App_GlobalResources; -using Microsoft.Practices.Unity; +using Bonobo.Git.Server.App_GlobalResources; using System; -using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Web; -using System.Web.Mvc; -using Bonobo.Git.Server.Models; using System.Text.RegularExpressions; namespace Bonobo.Git.Server.Attributes diff --git a/Bonobo.Git.Server/Attributes/RepositoryNameNormalizerAttribute.cs b/Bonobo.Git.Server/Attributes/RepositoryNameNormalizerAttribute.cs index f79b4a884..8acc0a701 100644 --- a/Bonobo.Git.Server/Attributes/RepositoryNameNormalizerAttribute.cs +++ b/Bonobo.Git.Server/Attributes/RepositoryNameNormalizerAttribute.cs @@ -1,6 +1,5 @@ -using System.Web.Mvc; using Bonobo.Git.Server.Data; -using Microsoft.Practices.Unity; +using Microsoft.AspNetCore.Mvc.Filters; namespace Bonobo.Git.Server { @@ -13,27 +12,28 @@ namespace Bonobo.Git.Server /// public class RepositoryNameNormalizerAttribute : ActionFilterAttribute { + public IRepositoryRepository RepositoryRepository { get; set; } + private readonly string _repositoryNameParameterName; - public RepositoryNameNormalizerAttribute(string repositoryNameParameterName) + public RepositoryNameNormalizerAttribute(IRepositoryRepository repositoryRepository, string repositoryNameParameterName) { + RepositoryRepository = repositoryRepository; _repositoryNameParameterName = repositoryNameParameterName; } - [Dependency] - public IRepositoryRepository RepositoryRepository { get; set; } public override void OnActionExecuting(ActionExecutingContext filterContext) { object incomingRepositoryNameParameter; - if(filterContext.ActionParameters.TryGetValue(_repositoryNameParameterName, out incomingRepositoryNameParameter)) + if(filterContext.ActionArguments.TryGetValue(_repositoryNameParameterName, out incomingRepositoryNameParameter)) { var incomingRepositoryName = (string)incomingRepositoryNameParameter; var normalizedName = Repository.NormalizeRepositoryName(incomingRepositoryName, RepositoryRepository); if (normalizedName != incomingRepositoryName) { // We've had to correct the incoming repository name - filterContext.ActionParameters[_repositoryNameParameterName] = normalizedName; + filterContext.ActionArguments[_repositoryNameParameterName] = normalizedName; } } } diff --git a/Bonobo.Git.Server/Attributes/UniqueRepoNameAttribute.cs b/Bonobo.Git.Server/Attributes/UniqueRepoNameAttribute.cs index 2b642ba26..1986ecd8e 100644 --- a/Bonobo.Git.Server/Attributes/UniqueRepoNameAttribute.cs +++ b/Bonobo.Git.Server/Attributes/UniqueRepoNameAttribute.cs @@ -1,14 +1,9 @@ using Bonobo.Git.Server.Data; using Bonobo.Git.Server.App_GlobalResources; -using Microsoft.Practices.Unity; -using System; -using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Web; -using System.Web.Mvc; using Bonobo.Git.Server.Models; +using Microsoft.Extensions.DependencyInjection; namespace Bonobo.Git.Server.Attributes { @@ -22,7 +17,7 @@ protected override ValidationResult IsValid(object value, ValidationContext cont return new ValidationResult("empty repo name?"); } - IRepositoryRepository RepositoryRepository = DependencyResolver.Current.GetService(); + IRepositoryRepository RepositoryRepository = context.GetService(); if (RepositoryRepository.NameIsUnique(value.ToString(), ((RepositoryDetailModel)context.ObjectInstance).Id)) { return ValidationResult.Success; diff --git a/Bonobo.Git.Server/Attributes/WebAuthorizeAttribute.cs b/Bonobo.Git.Server/Attributes/WebAuthorizeAttribute.cs index e19075752..4e271b93d 100644 --- a/Bonobo.Git.Server/Attributes/WebAuthorizeAttribute.cs +++ b/Bonobo.Git.Server/Attributes/WebAuthorizeAttribute.cs @@ -1,14 +1,27 @@ using System; using System.Linq; -using System.Web.Mvc; -using System.Web.Routing; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; namespace Bonobo.Git.Server { - [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] - public class WebAuthorizeAttribute : AuthorizeAttribute + public class WebRequirement : IAuthorizationRequirement { - public new string Roles + + } + + public class WebAuthorizationHandler : AuthorizationHandler + { + private string[] roles; + + public WebAuthorizationHandler() + { + + } + + public string Roles { get { @@ -20,24 +33,25 @@ public class WebAuthorizeAttribute : AuthorizeAttribute } } - private string[] roles; - - public override void OnAuthorization(AuthorizationContext filterContext) + protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, WebRequirement requirement) { - base.OnAuthorization(filterContext); + var redirectContext = context.Resource as AuthorizationFilterContext; + if (!context.User.IsInRole(Definitions.Roles.Member) && !context.User.Identity.IsAuthenticated) + { + context.Fail(); + redirectContext.Result = new RedirectToActionResult("Unauthorized", "Home", null); + return Task.CompletedTask; + } - if (!(filterContext.Result is HttpUnauthorizedResult)) + if (roles != null && roles.Length != 0 && !context.User.Roles().Any(x => roles.Contains(x))) { - if (!filterContext.HttpContext.User.IsInRole(Definitions.Roles.Member) && !filterContext.HttpContext.User.Identity.IsAuthenticated) - { - filterContext.Result = new RedirectResult("~/Home/Unauthorized"); - } - - if (roles != null && roles.Length != 0 && !filterContext.HttpContext.User.Roles().Any(x => roles.Contains(x))) - { - filterContext.Result = new RedirectResult("~/Home/Unauthorized"); - } + context.Fail(); + redirectContext.Result = new RedirectToActionResult("Unauthorized", "Home", null); + return Task.CompletedTask; } + + context.Succeed(requirement); + return Task.CompletedTask; } } } \ No newline at end of file diff --git a/Bonobo.Git.Server/Attributes/WebAuthorizeRepositoryAttribute.cs b/Bonobo.Git.Server/Attributes/WebAuthorizeRepositoryAttribute.cs index 687a6b72f..df6f9f390 100644 --- a/Bonobo.Git.Server/Attributes/WebAuthorizeRepositoryAttribute.cs +++ b/Bonobo.Git.Server/Attributes/WebAuthorizeRepositoryAttribute.cs @@ -1,59 +1,63 @@ -using System.Web.Mvc; -using System.Web.Routing; -using Bonobo.Git.Server.Data; -using Bonobo.Git.Server.Security; +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Routing; -using Microsoft.Practices.Unity; -using System; +using Bonobo.Git.Server.Security; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc.Infrastructure; namespace Bonobo.Git.Server { - public class WebAuthorizeRepositoryAttribute : WebAuthorizeAttribute + public class WebRepositoryAuthorizationHandler : WebAuthorizationHandler { - [Dependency] + private readonly IActionContextAccessor _actionContextAccessor; public IRepositoryPermissionService RepositoryPermissionService { get; set; } public bool RequiresRepositoryAdministrator { get; set; } - public override void OnAuthorization(AuthorizationContext filterContext) + public WebRepositoryAuthorizationHandler(IActionContextAccessor actionContextAccessor, IRepositoryPermissionService repositoryPermissionService) { - base.OnAuthorization(filterContext); + _actionContextAccessor = actionContextAccessor; + RepositoryPermissionService = repositoryPermissionService; + } - if (!(filterContext.Result is HttpUnauthorizedResult)) + protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, WebRequirement requirement) + { + Guid repoId; + var urlhelper = new UrlHelper(_actionContextAccessor.ActionContext); + if (Guid.TryParse(_actionContextAccessor.ActionContext.RouteData.Values["id"].ToString(), out repoId)) { - Guid repoId; - var urlhelper = new UrlHelper(filterContext.RequestContext); - if (Guid.TryParse(filterContext.Controller.ControllerContext.RouteData.Values["id"].ToString(), out repoId)) - { - Guid userId = filterContext.HttpContext.User.Id(); + Guid userId = context.User.Id(); - var requiredAccess = RequiresRepositoryAdministrator - ? RepositoryAccessLevel.Administer - : RepositoryAccessLevel.Push; + var requiredAccess = RequiresRepositoryAdministrator + ? RepositoryAccessLevel.Administer + : RepositoryAccessLevel.Push; - if (RepositoryPermissionService.HasPermission(userId, repoId, requiredAccess)) - { - return; - } + if (RepositoryPermissionService.HasPermission(userId, repoId, requiredAccess)) + { + context.Succeed(requirement); + return Task.FromResult(0); + } - filterContext.Result = new RedirectResult(urlhelper.Action("Unauthorized", "Home")); + //filterContext.Result = new RedirectResult(urlhelper.Action("Unauthorized", "Home")); + } + else + { + var rd = _actionContextAccessor.ActionContext.RouteData; + rd.Values.TryGetValue("action", out var action); + rd.Values.TryGetValue("controller", out var controller); + if (((string)action).Equals("index", StringComparison.OrdinalIgnoreCase) && ((string)controller).Equals("repository", StringComparison.OrdinalIgnoreCase)) + { + //filterContext.Result = new RedirectResult(urlhelper.Action("Unauthorized", "Home")); } else { - var rd = filterContext.RequestContext.RouteData; - var action = rd.GetRequiredString("action"); - var controller = rd.GetRequiredString("controller"); - if (action.Equals("index", StringComparison.OrdinalIgnoreCase) && controller.Equals("repository", StringComparison.OrdinalIgnoreCase)) - { - filterContext.Result = new RedirectResult(urlhelper.Action("Unauthorized", "Home")); - } - else - { - filterContext.Controller.TempData["RepositoryNotFound"] = true; - filterContext.Result = new RedirectResult(urlhelper.Action("Index", "Repository")); - } + //filterContext.Controller.TempData["RepositoryNotFound"] = true; + //filterContext.Result = new RedirectResult(urlhelper.Action("Index", "Repository")); } } + return Task.FromResult(0); } } } diff --git a/Bonobo.Git.Server/Bonobo.Git.Server.csproj b/Bonobo.Git.Server/Bonobo.Git.Server.csproj index ff55b58b6..49a60a6e6 100644 --- a/Bonobo.Git.Server/Bonobo.Git.Server.csproj +++ b/Bonobo.Git.Server/Bonobo.Git.Server.csproj @@ -1,775 +1,75 @@ - - - - - - - + + - Debug - AnyCPU - - - 2.0 - {6129B3FE-B282-4F6F-8836-8AF66602F8DA} - {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - Bonobo.Git.Server - Bonobo.Git.Server - v4.6 - false - - true - - - 4.0 - - - - 4.0 - - enabled - enabled - false - ..\ - true - true - - + netcoreapp2.2 - - true - full - false - bin\ - DEBUG;TRACE - prompt - 4 - false - - - pdbonly - true - bin\ - TRACE - prompt - 4 - true - false - true - false - false - - - - ..\packages\Antlr.3.5.0.2\lib\Antlr3.Runtime.dll - True - - - ..\packages\CommonMark.NET.0.15.1\lib\net45\CommonMark.dll - True - - - ..\packages\DotNetZip.1.10.1\lib\net20\DotNetZip.dll - True - - - ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll - True - - - ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll - True - - - ..\packages\LibGit2Sharp.0.23.1\lib\net40\LibGit2Sharp.dll - True - - - ..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.5\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll - - - - ..\packages\Microsoft.IdentityModel.Logging.1.1.3\lib\net451\Microsoft.IdentityModel.Logging.dll - True - - - ..\packages\Microsoft.IdentityModel.Protocol.Extensions.1.0.4.403061554\lib\net45\Microsoft.IdentityModel.Protocol.Extensions.dll - True - - - ..\packages\Microsoft.IdentityModel.Tokens.5.1.3\lib\net451\Microsoft.IdentityModel.Tokens.dll - True - - - ..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll - True - - - ..\packages\Microsoft.Owin.Host.SystemWeb.3.0.1\lib\net45\Microsoft.Owin.Host.SystemWeb.dll - True - - - ..\packages\Microsoft.Owin.Security.3.0.1\lib\net45\Microsoft.Owin.Security.dll - True - - - ..\packages\Microsoft.Owin.Security.Cookies.3.0.1\lib\net45\Microsoft.Owin.Security.Cookies.dll - True - - - ..\packages\Microsoft.Owin.Security.WsFederation.3.0.1\lib\net45\Microsoft.Owin.Security.WsFederation.dll - True - - - ..\packages\CommonServiceLocator.1.3\lib\portable-net4+sl5+netcore45+wpa81+wp8\Microsoft.Practices.ServiceLocation.dll - True - - - ..\packages\Unity.4.0.1\lib\net45\Microsoft.Practices.Unity.dll - True - - - ..\packages\Unity.4.0.1\lib\net45\Microsoft.Practices.Unity.Configuration.dll - True - - - ..\packages\Unity.Mvc.4.0.1\lib\net45\Microsoft.Practices.Unity.Mvc.dll - True - - - ..\packages\Unity.4.0.1\lib\net45\Microsoft.Practices.Unity.RegistrationByConvention.dll - True - - - - ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll - True - - - ..\packages\MediaTypeMap.2.1.0.0\lib\net40\MimeTypeMap.dll - True - - - ..\packages\MvcCheckBoxList.1.4.5\lib\net45\MvcCheckBoxList.dll - True - - - ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll - True - - - ..\packages\Owin.1.0\lib\net40\Owin.dll - True - - - ..\packages\Serilog.2.4.0\lib\net46\Serilog.dll - True - - - ..\packages\Serilog.Settings.AppSettings.2.1.0\lib\net45\Serilog.Settings.AppSettings.dll - True - - - ..\packages\Serilog.Sinks.File.3.2.0\lib\net45\Serilog.Sinks.File.dll - True - - - ..\packages\Serilog.Sinks.RollingFile.3.3.0\lib\net45\Serilog.Sinks.RollingFile.dll - True - - - - - ..\packages\System.Data.SQLite.Core.1.0.104.0\lib\net46\System.Data.SQLite.dll - True - - - ..\packages\System.Data.SQLite.EF6.1.0.104.0\lib\net46\System.Data.SQLite.EF6.dll - True - - - ..\packages\System.Data.SQLite.Linq.1.0.104.0\lib\net46\System.Data.SQLite.Linq.dll - True - - - - - - 3.5 - - - - ..\packages\System.IdentityModel.Tokens.Jwt.4.0.4.403061554\lib\net45\System.IdentityModel.Tokens.Jwt.dll - True - - - - - - - - - - - - - - - - - False - - - ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll - True - - - ..\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll - True - - - ..\packages\Microsoft.AspNet.Web.Optimization.1.1.3\lib\net40\System.Web.Optimization.dll - True - - - ..\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll - True - - - False - - - ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.dll - True - - - ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Deployment.dll - True - - - ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll - True - - - - - - - - ..\packages\UDE.CSharp.1.1.0\lib\Ude.dll - True - - - ..\packages\WebActivatorEx.2.2.0\lib\net40\WebActivatorEx.dll - True - - - ..\packages\WebGrease.1.6.0\lib\WebGrease.dll - True - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Global.asax - - - - - - - - - - - + + + false + 7 + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Resources.af-ZA.designer.cs - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Designer - - - - Designer - - - - - - - Designer - - - changelog.md - - - license.md - - - readme.md - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Web.config - - - Web.config - - - Web.config - Designer - + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - True + True + True Resources.resx - + + + + PublicResXFileCodeGenerator Resources.Designer.cs - Designer - - - - - - - - - - - - - - - - - - - - 10.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - true - bin\ - DEBUG;TRACE - full - AnyCPU - prompt - MinimumRecommendedRules.ruleset - - - - - - - - - - - - - True - - - - - - - - - - - if not exist "$(TargetDir)NativeBinaries" md "$(TargetDir)NativeBinaries" -if not exist "$(TargetDir)NativeBinaries\x86" md "$(TargetDir)NativeBinaries\x86" -xcopy /s /y /d "$(SolutionDir)packages\LibGit2Sharp.0.21.0.176\lib\net40\NativeBinaries\x86\*.*" "$(TargetDir)NativeBinaries\x86\" -if not exist "$(TargetDir)NativeBinaries\amd64" md "$(TargetDir)NativeBinaries\amd64" -xcopy/s /y /d "$(SolutionDir)packages\LibGit2Sharp.0.21.0.176\lib\net40\NativeBinaries\amd64\*.*" "$(TargetDir)NativeBinaries\amd64\" - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - - \ No newline at end of file + + diff --git a/Bonobo.Git.Server/Bonobo.Git.Server.csproj.DotSettings b/Bonobo.Git.Server/Bonobo.Git.Server.csproj.DotSettings deleted file mode 100644 index 73e96563f..000000000 --- a/Bonobo.Git.Server/Bonobo.Git.Server.csproj.DotSettings +++ /dev/null @@ -1,2 +0,0 @@ - - CSharp60 \ No newline at end of file diff --git a/Bonobo.Git.Server/Configuration/ActiveDirectorySettings.cs b/Bonobo.Git.Server/Configuration/ActiveDirectorySettings.cs index 81f473473..c69f3e5e9 100644 --- a/Bonobo.Git.Server/Configuration/ActiveDirectorySettings.cs +++ b/Bonobo.Git.Server/Configuration/ActiveDirectorySettings.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; using System.Configuration; -using System.Linq; -using System.Web; namespace Bonobo.Git.Server.Configuration { diff --git a/Bonobo.Git.Server/Configuration/ConfigurationEntry.cs b/Bonobo.Git.Server/Configuration/ConfigurationEntry.cs index e8843e324..6b016f806 100644 --- a/Bonobo.Git.Server/Configuration/ConfigurationEntry.cs +++ b/Bonobo.Git.Server/Configuration/ConfigurationEntry.cs @@ -1,20 +1,20 @@ using System.Configuration; using System.IO; -using System.Web; -using System.Web.Hosting; using System.Xml.Serialization; +using Bonobo.Git.Server.Extensions; +using Microsoft.AspNetCore.Hosting; namespace Bonobo.Git.Server.Configuration { public abstract class ConfigurationEntry where Entry : ConfigurationEntry, new() { private static Entry _current = null; + protected static IHostingEnvironment hostingEnvironment; private static readonly object _sync = new object(); private static readonly XmlSerializer _serializer = new XmlSerializer(typeof(Entry)); - private static readonly string _configPath = Path.IsPathRooted(ConfigurationManager.AppSettings["UserConfiguration"]) - ? ConfigurationManager.AppSettings["UserConfiguration"] - : HostingEnvironment.MapPath(ConfigurationManager.AppSettings["UserConfiguration"]); - + private static string ConfigPath => Path.IsPathRooted(ConfigurationManager.AppSettings["UserConfiguration"]) + ? ConfigurationManager.AppSettings["UserConfiguration"] + : hostingEnvironment.MapPath(ConfigurationManager.AppSettings["UserConfiguration"]); public static Entry Current { get { return _current ?? Load(); } } @@ -27,7 +27,7 @@ private static Entry Load() { try { - using (var stream = File.Open(_configPath, FileMode.Open)) + using (var stream = File.Open(ConfigPath, FileMode.Open)) { _current = _serializer.Deserialize(stream) as Entry; } @@ -48,7 +48,7 @@ public void Save() { if (_current != null) { - using (var stream = File.Open(_configPath, FileMode.Create)) + using (var stream = File.Open(ConfigPath, FileMode.Create)) { _serializer.Serialize(stream, _current); } diff --git a/Bonobo.Git.Server/Configuration/DiagnosticReporter.cs b/Bonobo.Git.Server/Configuration/DiagnosticReporter.cs index 706d7f8aa..f3f4880a7 100644 --- a/Bonobo.Git.Server/Configuration/DiagnosticReporter.cs +++ b/Bonobo.Git.Server/Configuration/DiagnosticReporter.cs @@ -4,9 +4,11 @@ using System.Linq; using System.Net; using System.Text; -using System.Web.Hosting; using Bonobo.Git.Server.Data; +using Bonobo.Git.Server.Extensions; using Bonobo.Git.Server.Security; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; namespace Bonobo.Git.Server.Configuration { @@ -18,16 +20,22 @@ namespace Bonobo.Git.Server.Configuration /// public class DiagnosticReporter { + private readonly IHostingEnvironment _hostingEnvironment; private readonly StringBuilder _report = new StringBuilder(); private readonly UserConfiguration _userConfig = UserConfiguration.Current; - public string GetVerificationReport() + public DiagnosticReporter(IHostingEnvironment hostingEnvironment) { - RunReport(); + _hostingEnvironment = hostingEnvironment; + } + + public string GetVerificationReport(IServiceProvider serviceProvider) + { + RunReport(serviceProvider); return _report.ToString(); } - private void RunReport() + private void RunReport(IServiceProvider serviceProvider) { DumpAppSettings(); CheckUserConfigurationFile(); @@ -35,7 +43,7 @@ private void RunReport() CheckGitSettings(); CheckFederatedAuth(); CheckADMembership(); - CheckInternalMembership(); + CheckInternalMembership(serviceProvider); ExceptionLog(); } @@ -180,13 +188,15 @@ private bool DirectoryIsWritable(string directory) } } - private void CheckInternalMembership() + private void CheckInternalMembership(IServiceProvider serviceProvider) { _report.AppendLine("Internal Membership"); if (AppSetting("MembershipService") == "Internal") { - SafelyReport("User count", () => new EFMembershipService { CreateContext = () => new BonoboGitServerContext() }.GetAllUsers().Count); + SafelyReport("User count", + () => new EFMembershipService(serviceProvider.GetService) + .GetAllUsers().Count); } else { @@ -203,7 +213,7 @@ private void ExceptionLog() _report.AppendLine("Exception Log"); SafelyRun(() => { - var nameFormat = MvcApplication.GetLogFileNameFormat(); + var nameFormat = Startup.GetLogFileNameFormat(_hostingEnvironment); var todayLogFileName = nameFormat.Replace("{Date}", DateTime.Now.ToString("yyyyMMdd")); SafelyReport("LogFileName: ", () => todayLogFileName); var chunkSize = 10000; @@ -263,7 +273,7 @@ private void SafelyReport(string tag, Func func) private string MapPath(string path) { - return Path.IsPathRooted(path) ? path : HostingEnvironment.MapPath(path); + return Path.IsPathRooted(path) ? path : _hostingEnvironment.MapPath(path); } private string AppSetting(string name) diff --git a/Bonobo.Git.Server/Configuration/UserConfiguration.cs b/Bonobo.Git.Server/Configuration/UserConfiguration.cs index f6db21795..704c0ebed 100644 --- a/Bonobo.Git.Server/Configuration/UserConfiguration.cs +++ b/Bonobo.Git.Server/Configuration/UserConfiguration.cs @@ -1,13 +1,13 @@ using System; using System.Configuration; using System.IO; -using System.Web; using System.Xml.Serialization; +using Bonobo.Git.Server.Extensions; +using Microsoft.AspNetCore.Hosting; namespace Bonobo.Git.Server.Configuration { using Bonobo.Git.Server.App_GlobalResources; - using System.Web.Hosting; [XmlRootAttribute(ElementName = "Configuration", IsNullable = false)] public class UserConfiguration : ConfigurationEntry @@ -33,7 +33,7 @@ public string Repositories { return Path.IsPathRooted(RepositoryPath) ? RepositoryPath - : HostingEnvironment.MapPath(RepositoryPath); + : hostingEnvironment.MapPath(RepositoryPath); } } @@ -71,8 +71,9 @@ public string GetSiteTitle() return !string.IsNullOrWhiteSpace(this.SiteTitle) ? this.SiteTitle : Resources.Layout_Title; } - public static void Initialize() + public static void Initialize(IHostingEnvironment hostingEnvironment) { + UserConfiguration.hostingEnvironment = hostingEnvironment; if (IsInitialized()) return; diff --git a/Bonobo.Git.Server/Controllers/AccountController.cs b/Bonobo.Git.Server/Controllers/AccountController.cs index 72b1d847d..9096baf07 100644 --- a/Bonobo.Git.Server/Controllers/AccountController.cs +++ b/Bonobo.Git.Server/Controllers/AccountController.cs @@ -1,39 +1,33 @@ using System; -using System.Collections.Generic; -using System.Globalization; using System.Linq; using System.Security.Claims; -using System.Web; -using System.Web.Mvc; -using System.Web.Security; +using Microsoft.AspNetCore.Mvc; using Bonobo.Git.Server.App_GlobalResources; using Bonobo.Git.Server.Configuration; -using Bonobo.Git.Server.Extensions; +using Bonobo.Git.Server.Helpers; using Bonobo.Git.Server.Models; using Bonobo.Git.Server.Security; - -using Bonobo.Git.Server.Helpers; -using System.DirectoryServices.AccountManagement; - -using Microsoft.Practices.Unity; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authorization; using Serilog; -using Microsoft.Owin.Security; namespace Bonobo.Git.Server.Controllers { public class AccountController : Controller { - [Dependency] public IMembershipService MembershipService { get; set; } - - [Dependency] public IRoleProvider RoleProvider { get; set; } - - [Dependency] public IAuthenticationProvider AuthenticationProvider { get; set; } - [WebAuthorize] + public AccountController(IMembershipService membershipService, IRoleProvider roleProvider, IAuthenticationProvider authenticationProvider) + { + MembershipService = membershipService; + RoleProvider = roleProvider; + AuthenticationProvider = authenticationProvider; + } + + [Authorize(Policy = "Web")] public ActionResult Detail(Guid id) { UserModel user = MembershipService.GetUserModel(id); @@ -54,7 +48,7 @@ public ActionResult Detail(Guid id) return View(); } - [WebAuthorize(Roles = Definitions.Roles.Administrator)] + [Authorize(Policy = "Web", Roles = Definitions.Roles.Administrator)] public ActionResult Delete(Guid id) { var user = MembershipService.GetUserModel(id); @@ -68,7 +62,7 @@ public ActionResult Delete(Guid id) [HttpPost] [ValidateAntiForgeryToken] - [WebAuthorize(Roles = Definitions.Roles.Administrator)] + [Authorize(Policy = "Web", Roles = Definitions.Roles.Administrator)] public ActionResult Delete(UserDetailModel model) { if (model != null && model.Id != null) @@ -87,13 +81,13 @@ public ActionResult Delete(UserDetailModel model) return RedirectToAction("Index"); } - [WebAuthorize(Roles = Definitions.Roles.Administrator)] + [Authorize(Policy = "Web", Roles = Definitions.Roles.Administrator)] public ActionResult Index() { return View(GetDetailUsers()); } - [WebAuthorize] + [Authorize(Policy = "Web")] public ActionResult Edit(Guid id) { if (id != User.Id() && !User.IsInRole(Definitions.Roles.Administrator)) @@ -125,7 +119,7 @@ public ActionResult Edit(Guid id) } [HttpPost] - [WebAuthorize] + [Authorize(Policy = "Web")] [ValidateAntiForgeryToken] public ActionResult Edit(UserEditModel model) { @@ -187,11 +181,11 @@ public ActionResult Edit(UserEditModel model) public ActionResult CreateADUser() { var efms = MembershipService as EFMembershipService; - - if ((!Request.IsAuthenticated) || efms == null) + + if ((!Request.HttpContext.User.Identity.IsAuthenticated) || efms == null) { - Log.Warning("CreateADUser: can't run IsAuth: {IsAuth}, MemServ {MemServ}", - Request.IsAuthenticated, + Log.Warning("CreateADUser: can't run IsAuth: {IsAuth}, MemServ {MemServ}", + Request.HttpContext.User.Identity.IsAuthenticated, MembershipService.GetType()); return RedirectToAction("Unauthorized", "Home"); } @@ -209,13 +203,12 @@ public ActionResult CreateADUser() Log.Information("Making AD user {User} into an admin", credentials); var id = MembershipService.GetUserModel(credentials).Id; - RoleProvider.AddUserToRoles(id, new[] {Definitions.Roles.Administrator}); + RoleProvider.AddUserToRoles(id, new[] { Definitions.Roles.Administrator }); // Add the administrator role to the Identity/cookie var Identity = (ClaimsIdentity)User.Identity; Identity.AddClaim(new Claim(ClaimTypes.Role, Definitions.Roles.Administrator)); - var AuthenticationManager = HttpContext.GetOwinContext().Authentication; - AuthenticationManager.AuthenticationResponseGrant = new AuthenticationResponseGrant(new ClaimsPrincipal(Identity), new AuthenticationProperties { IsPersistent = true }); + HttpContext.SignInAsync(new ClaimsPrincipal(Identity)); } return RedirectToAction("Index", "Repository"); @@ -234,7 +227,7 @@ public ActionResult CreateADUser() public ActionResult Create() { - if ((Request.IsAuthenticated && !User.IsInRole(Definitions.Roles.Administrator)) || (!Request.IsAuthenticated && !UserConfiguration.Current.AllowAnonymousRegistration)) + if ((Request.HttpContext.User.Identity.IsAuthenticated && !User.IsInRole(Definitions.Roles.Administrator)) || (!Request.HttpContext.User.Identity.IsAuthenticated && !UserConfiguration.Current.AllowAnonymousRegistration)) { return RedirectToAction("Unauthorized", "Home"); } @@ -246,7 +239,7 @@ public ActionResult Create() [ValidateAntiForgeryToken] public ActionResult Create(UserCreateModel model) { - if ((Request.IsAuthenticated && !User.IsInRole(Definitions.Roles.Administrator)) || (!Request.IsAuthenticated && !UserConfiguration.Current.AllowAnonymousRegistration)) + if ((Request.HttpContext.User.Identity.IsAuthenticated && !User.IsInRole(Definitions.Roles.Administrator)) || (!Request.HttpContext.User.Identity.IsAuthenticated && !UserConfiguration.Current.AllowAnonymousRegistration)) { return RedirectToAction("Unauthorized", "Home"); } @@ -301,6 +294,5 @@ private UserDetailModelList GetDetailUsers() } return model; } - } -} +} \ No newline at end of file diff --git a/Bonobo.Git.Server/Controllers/GitController.cs b/Bonobo.Git.Server/Controllers/GitController.cs index 91bd95566..8131f4fde 100644 --- a/Bonobo.Git.Server/Controllers/GitController.cs +++ b/Bonobo.Git.Server/Controllers/GitController.cs @@ -1,7 +1,6 @@ using System; using System.IO; -using System.Net; -using System.Web.Mvc; +using Microsoft.AspNetCore.Mvc; using Bonobo.Git.Server.Configuration; using Bonobo.Git.Server.Data; using Bonobo.Git.Server.Git; @@ -9,28 +8,34 @@ using Bonobo.Git.Server.Models; using Bonobo.Git.Server.Security; using Ionic.Zlib; -using Microsoft.Practices.Unity; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features; +using Microsoft.AspNetCore.Mvc.Filters; using Serilog; using Repository = LibGit2Sharp.Repository; namespace Bonobo.Git.Server.Controllers { - [GitAuthorize] - [RepositoryNameNormalizer("repositoryName")] + [Authorize(Policy = "Git")] + [GitControllerExceptionFilter] + [TypeFilter(typeof(RepositoryNameNormalizerAttribute), Arguments = new object[] { "repositoryName" })] public class GitController : Controller { - [Dependency] public IRepositoryPermissionService RepositoryPermissionService { get; set; } - - [Dependency] public IRepositoryRepository RepositoryRepository { get; set; } - - [Dependency] public IMembershipService MembershipService { get; set; } - - [Dependency] public IGitService GitService { get; set; } + public GitController(IRepositoryPermissionService repositoryPermissionService, + IRepositoryRepository repositoryRepository, IMembershipService membershipService, IGitService gitService) + { + RepositoryPermissionService = repositoryPermissionService; + RepositoryRepository = repositoryRepository; + MembershipService = membershipService; + GitService = gitService; + } + public ActionResult SecureGetInfoRefs(String repositoryName, String service) { bool isPush = String.Equals("git-receive-pack", service, StringComparison.OrdinalIgnoreCase); @@ -52,7 +57,7 @@ public ActionResult SecureGetInfoRefs(String repositoryName, String service) } else { - return new HttpNotFoundResult(); + return new NotFoundResult(); } } @@ -76,7 +81,7 @@ public ActionResult SecureUploadPack(String repositoryName) { if (!RepositoryIsValid(repositoryName)) { - return new HttpNotFoundResult(); + return new NotFoundResult(); } if (RepositoryPermissionService.HasPermission(User.Id(), repositoryName, RepositoryAccessLevel.Pull)) @@ -94,7 +99,7 @@ public ActionResult SecureReceivePack(String repositoryName) { if (!RepositoryIsValid(repositoryName)) { - return new HttpNotFoundResult(); + return new NotFoundResult(); } if (RepositoryPermissionService.HasPermission(User.Id(), repositoryName, RepositoryAccessLevel.Push)) @@ -150,6 +155,7 @@ public ActionResult GitUrl(string repositoryName) return RedirectPermanent(Url.Action("Detail", "Repository", new { id = repositoryName})); } + [DisableRequestSizeLimit] private ActionResult ExecuteReceivePack(string repositoryName) { return new GitCmdResult( @@ -204,10 +210,10 @@ private ActionResult GetInfoRefs(String repositoryName, String service) private ActionResult UnauthorizedResult() { - Response.Clear(); - Response.AddHeader("WWW-Authenticate", "Basic realm=\"Bonobo Git\""); + Response.Body = new MemoryStream(); + Response.Headers.Add("WWW-Authenticate", "Basic realm=\"Bonobo Git\""); - return new HttpStatusCodeResult(401); + return new StatusCodeResult(401); } private static String FormatMessage(String input) @@ -240,27 +246,28 @@ private Stream GetInputStream(bool disableBuffer = false) { // For really large uploads we need to get a bufferless input stream and disable the max // request length. - Stream requestStream = disableBuffer ? - Request.GetBufferlessInputStream(disableMaxRequestLength: true) : - Request.GetBufferedInputStream(); + Stream requestStream = Request.Body; return Request.Headers["Content-Encoding"] == "gzip" ? new GZipStream(requestStream, CompressionMode.Decompress) : requestStream; } - protected override void OnException(ExceptionContext filterContext) + public class GitControllerExceptionFilterAttribute : ExceptionFilterAttribute { - Exception exception = filterContext.Exception; - Log.Error(exception, "Error caught in GitController"); - filterContext.Result = new ContentResult { Content = exception.ToString() }; + public override void OnException(ExceptionContext filterContext) + { + Exception exception = filterContext.Exception; + Log.Error(exception, "Error caught in GitController"); + filterContext.Result = new ContentResult { Content = exception.ToString() }; - filterContext.ExceptionHandled = true; + filterContext.ExceptionHandled = true; - filterContext.HttpContext.Response.Clear(); - filterContext.HttpContext.Response.StatusCode = 500; - filterContext.HttpContext.Response.StatusDescription = "Exception in GitController"; - filterContext.HttpContext.Response.TrySkipIisCustomErrors = true; + filterContext.HttpContext.Response.Clear(); + filterContext.HttpContext.Response.StatusCode = 500; + filterContext.HttpContext.Features.Get().ReasonPhrase = "Exception in GitController"; + //filterContext.HttpContext.Response.TrySkipIisCustomErrors = true; + } } } } diff --git a/Bonobo.Git.Server/Controllers/HomeController.cs b/Bonobo.Git.Server/Controllers/HomeController.cs index ae02c5a8b..6905f79b1 100644 --- a/Bonobo.Git.Server/Controllers/HomeController.cs +++ b/Bonobo.Git.Server/Controllers/HomeController.cs @@ -1,12 +1,9 @@ using System; -using System.Collections.Generic; using System.Globalization; using System.Linq; -using System.Security.Claims; using System.Text; using System.Web; -using System.Web.Caching; -using System.Web.Mvc; +using Microsoft.AspNetCore.Mvc; using Bonobo.Git.Server.App_GlobalResources; using Bonobo.Git.Server.Configuration; @@ -15,26 +12,36 @@ using Bonobo.Git.Server.Models; using Bonobo.Git.Server.Security; -using Microsoft.Owin.Security; -using Microsoft.Owin.Security.Cookies; -using Microsoft.Practices.Unity; using Bonobo.Git.Server.Owin.Windows; using System.Configuration; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Extensions; +using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json; +using Serilog; namespace Bonobo.Git.Server.Controllers { public class HomeController : Controller { - [Dependency] + private readonly BonoboGitServerContext _context; public IMembershipService MembershipService { get; set; } - - [Dependency] public IAuthenticationProvider AuthenticationProvider { get; set; } - - [Dependency] public IDatabaseResetManager ResetManager { get; set; } - [WebAuthorize] + public HomeController(IMembershipService membershipService, IAuthenticationProvider authenticationProvider, + IDatabaseResetManager resetManager, BonoboGitServerContext context) + { + MembershipService = membershipService; + AuthenticationProvider = authenticationProvider; + ResetManager = resetManager; + _context = context; + } + + [Authorize(Policy = "Web")] public ActionResult Index() { return RedirectToAction("Index", "Repository"); @@ -57,7 +64,7 @@ public ActionResult Error() private string CheckForPasswordResetUsername(string digest) { - var cacheObj = MvcApplication.Cache[HttpUtility.UrlDecode(digest)]; + var cacheObj = Program.Cache[HttpUtility.UrlDecode(digest)]; if (cacheObj == null) { return null; @@ -70,15 +77,12 @@ public ActionResult ResetPassword(string digest) string username = CheckForPasswordResetUsername(digest); if (username != null ) { - using (var db = new BonoboGitServerContext()) + var user = _context.Users.FirstOrDefault(x => x.Username.Equals(username, StringComparison.OrdinalIgnoreCase)); + if (user == null) { - var user = db.Users.FirstOrDefault(x => x.Username.Equals(username, StringComparison.OrdinalIgnoreCase)); - if (user == null) - { - throw new UnauthorizedAccessException("Unknown user " + username); - } - return View(new ResetPasswordModel { Username = username, Digest = digest}); + throw new UnauthorizedAccessException("Unknown user " + username); } + return View(new ResetPasswordModel { Username = username, Digest = digest}); } else { @@ -98,19 +102,16 @@ public ActionResult ResetPassword(ResetPasswordModel model) { throw new UnauthorizedAccessException("Invalid password reset form"); } - using (var db = new BonoboGitServerContext()) + var user = _context.Users.FirstOrDefault(x => x.Username.Equals(model.Username, StringComparison.OrdinalIgnoreCase)); + if (user == null) + { + TempData["ResetSuccess"] = false; + Log.Warning("FAILURE"); + } + else { - var user = db.Users.FirstOrDefault(x => x.Username.Equals(model.Username, StringComparison.OrdinalIgnoreCase)); - if (user == null) - { - TempData["ResetSuccess"] = false; - Response.AppendToLog("FAILURE"); - } - else - { - MembershipService.UpdateUser(user.Id, null, null, null, null, model.Password); - TempData["ResetSuccess"] = true; - } + MembershipService.UpdateUser(user.Id, null, null, null, null, model.Password); + TempData["ResetSuccess"] = true; } } return View(model); @@ -131,15 +132,15 @@ public ActionResult ForgotPassword(ForgotPasswordModel model) if (user == null) { ModelState.AddModelError("", Resources.Home_ForgotPassword_UserNameFailure); - Response.AppendToLog("FAILURE"); + Log.Warning("FAILURE"); } else { string token = MembershipService.GenerateResetToken(user.Username); - MvcApplication.Cache.Add(token, model.Username, DateTimeOffset.Now.AddHours(1)); + Program.Cache.Add(token, model.Username, DateTimeOffset.Now.AddHours(1)); // Passing Requust.Url.Scheme to Url.Action forces it to generate a full URL - var resetUrl = Url.Action("ResetPassword", "Home", new {digest = HttpUtility.UrlEncode(Encoding.UTF8.GetBytes(token))},Request.Url.Scheme); + var resetUrl = Url.Action("ResetPassword", "Home", new {digest = HttpUtility.UrlEncode(Encoding.UTF8.GetBytes(token))},Request.Scheme); TempData["SendSuccess"] = MembershipHelper.SendForgotPasswordEmail(user, resetUrl); } @@ -158,7 +159,7 @@ public ActionResult WindowsLogin(string returnUrl) RedirectUri = returnUrl }; - Request.GetOwinContext().Authentication.Challenge(authenticationProperties, WindowsAuthenticationDefaults.AuthenticationType); + HttpContext.ChallengeAsync(WindowsAuthenticationDefaults.AuthenticationType, authenticationProperties); return new EmptyResult(); } @@ -186,8 +187,8 @@ public ActionResult LogOn(LogOnModel model) { case ValidationResult.Success: AuthenticationProvider.SignIn(model.Username, Url.IsLocalUrl(model.ReturnUrl) ? model.ReturnUrl : Url.Action("Index", "Home"), model.RememberMe); - Response.AppendToLog("SUCCESS"); - if (Request.IsLocal && model.DatabaseResetCode > 0 && model.Username == "admin" && ConfigurationManager.AppSettings["AllowDBReset"] == "true" ) + Log.Information("SUCCESS"); + if (Url.IsLocalUrl(Request.GetEncodedUrl()) && model.DatabaseResetCode > 0 && model.Username == "admin" && ConfigurationManager.AppSettings["AllowDBReset"] == "true" ) { ResetManager.DoReset(model.DatabaseResetCode); } @@ -196,7 +197,7 @@ public ActionResult LogOn(LogOnModel model) return new RedirectResult("~/Home/Unauthorized"); default: ModelState.AddModelError("", Resources.Home_LogOn_UsernamePasswordIncorrect); - Response.AppendToLog("FAILURE"); + Log.Warning("FAILURE"); break; } } @@ -210,23 +211,23 @@ public ActionResult LogOff() return RedirectToAction("Index", "Home"); } - public ActionResult Unauthorized() + public new ActionResult Unauthorized() { return View(); } public ActionResult ChangeCulture(string lang, string returnUrl) { - Session["Culture"] = new CultureInfo(lang); + HttpContext.Session.SetString("Culture", JsonConvert.SerializeObject(new CultureInfo(lang))); return Redirect(returnUrl); } public ActionResult Diagnostics() { - if (Request.IsLocal) + if (Url.IsLocalUrl(Request.GetEncodedUrl())) { - var verifier = new DiagnosticReporter(); - return Content(verifier.GetVerificationReport(), "text/plain", Encoding.UTF8); + var verifier = new DiagnosticReporter(HttpContext.RequestServices.GetService()); + return Content(verifier.GetVerificationReport(HttpContext.RequestServices), "text/plain", Encoding.UTF8); } else { diff --git a/Bonobo.Git.Server/Controllers/RepositoryController.cs b/Bonobo.Git.Server/Controllers/RepositoryController.cs index a4d52ee3b..f2da0f41b 100644 --- a/Bonobo.Git.Server/Controllers/RepositoryController.cs +++ b/Bonobo.Git.Server/Controllers/RepositoryController.cs @@ -4,7 +4,7 @@ using System.Linq; using System.Text; using System.Text.RegularExpressions; -using System.Web.Mvc; +using Microsoft.AspNetCore.Mvc; using Bonobo.Git.Server.App_GlobalResources; using Bonobo.Git.Server.Configuration; using Bonobo.Git.Server.Data; @@ -13,30 +13,33 @@ using Bonobo.Git.Server.Models; using Bonobo.Git.Server.Security; using Ionic.Zip; -using Microsoft.Practices.Unity; using MimeTypes; using System.Security.Principal; +using Bonobo.Git.Server.Extensions; +using Microsoft.AspNetCore.Authorization; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; namespace Bonobo.Git.Server.Controllers { public class RepositoryController : Controller { - [Dependency] public ITeamRepository TeamRepository { get; set; } - - [Dependency] public IRepositoryRepository RepositoryRepository { get; set; } - - [Dependency] public IMembershipService MembershipService { get; set; } - - [Dependency] public IRepositoryPermissionService RepositoryPermissionService { get; set; } - - [Dependency] public IAuthenticationProvider AuthenticationProvider { get; set; } - [WebAuthorize] + public RepositoryController(ITeamRepository teamRepository, IRepositoryRepository repositoryRepository, + IMembershipService membershipService, IRepositoryPermissionService repositoryPermissionService) + { + TeamRepository = teamRepository; + RepositoryRepository = repositoryRepository; + MembershipService = membershipService; + RepositoryPermissionService = repositoryPermissionService; + } + + [Authorize(Policy = "Web")] public ActionResult Index(string sortGroup = null, string searchString = null) { var firstList = this.GetIndexModel(); @@ -60,7 +63,7 @@ public ActionResult Index(string sortGroup = null, string searchString = null) return View(list); } - [WebAuthorizeRepository(RequiresRepositoryAdministrator = true)] + [Authorize(Policy = "WebRepository", Roles = "RepositoryAdministrator")] public ActionResult Edit(Guid id) { var model = ConvertRepositoryModel(RepositoryRepository.GetRepository(id), User); @@ -70,7 +73,7 @@ public ActionResult Edit(Guid id) [HttpPost] [ValidateAntiForgeryToken] - [WebAuthorizeRepository(RequiresRepositoryAdministrator = true)] + [Authorize(Policy = "WebRepository", Roles = "RepositoryAdministrator")] public ActionResult Edit(RepositoryDetailModel model) { if (ModelState.IsValid) @@ -85,7 +88,7 @@ public ActionResult Edit(RepositoryDetailModel model) { RepositoryRepository.Update(repoModel); } - catch (System.Data.Entity.Infrastructure.DbUpdateException) + catch (DbUpdateException) { MoveRepo(repoModel, existingRepo); } @@ -117,7 +120,7 @@ private void MoveRepo(RepositoryModel oldRepo, RepositoryModel newRepo) } } - [WebAuthorize] + [Authorize(Policy = "Web")] public ActionResult Create() { if (!RepositoryPermissionService.HasCreatePermission(User.Id())) @@ -134,7 +137,7 @@ public ActionResult Create() } [HttpPost] - [WebAuthorize] + [Authorize(Policy = "Web")] [ValidateAntiForgeryToken] public ActionResult Create(RepositoryDetailModel model) { @@ -182,7 +185,7 @@ public ActionResult Create(RepositoryDetailModel model) return View(model); } - [WebAuthorizeRepository(RequiresRepositoryAdministrator = true)] + [Authorize(Policy = "WebRepository", Roles = "RepositoryAdministrator")] public ActionResult Delete(Guid id) { return View(ConvertRepositoryModel(RepositoryRepository.GetRepository(id), User)); @@ -190,7 +193,7 @@ public ActionResult Delete(Guid id) [HttpPost] [ValidateAntiForgeryToken] - [WebAuthorizeRepository(RequiresRepositoryAdministrator = true)] + [Authorize(Policy = "WebRepository", Roles = "RepositoryAdministrator")] public ActionResult Delete(RepositoryDetailModel model) { if (model != null) @@ -207,7 +210,7 @@ public ActionResult Delete(RepositoryDetailModel model) return RedirectToAction("Index"); } - [WebAuthorizeRepository] + [Authorize(Policy = "WebRepository")] public ActionResult Detail(Guid id) { ViewBag.ID = id; @@ -235,11 +238,10 @@ public ActionResult Detail(Guid id) void SetGitUrls(RepositoryDetailModel model) { string serverAddress = System.Configuration.ConfigurationManager.AppSettings["GitServerPath"] - ?? string.Format("{0}://{1}{2}{3}/", - Request.Url.Scheme, - Request.Url.Host, - (Request.Url.IsDefaultPort ? "" : (":" + Request.Url.Port)), - Request.ApplicationPath == "/" ? "" : Request.ApplicationPath + ?? string.Format("{0}://{1}{2}/", + Request.Scheme, + Request.Host, + Request.Path == "/" ? "" : (string)Request.Path ); model.GitUrl = String.Concat(serverAddress, model.Name, ".git"); @@ -250,7 +252,7 @@ void SetGitUrls(RepositoryDetailModel model) } } - [WebAuthorizeRepository] + [Authorize(Policy = "WebRepository")] public ActionResult Tree(Guid id, string encodedName, string encodedPath) { bool includeDetails = Request.IsAjaxRequest(); @@ -286,7 +288,7 @@ public ActionResult Tree(Guid id, string encodedName, string encodedPath) if (includeDetails) { - return Json(model, JsonRequestBehavior.AllowGet); + return Json(model); } else { @@ -297,7 +299,7 @@ public ActionResult Tree(Guid id, string encodedName, string encodedPath) } } - [WebAuthorizeRepository] + [Authorize(Policy = "WebRepository")] public ActionResult Blob(Guid id, string encodedName, string encodedPath) { ViewBag.ID = id; @@ -316,7 +318,7 @@ public ActionResult Blob(Guid id, string encodedName, string encodedPath) } } - [WebAuthorizeRepository] + [Authorize(Policy = "WebRepository")] public ActionResult Raw(Guid id, string encodedName, string encodedPath, bool display = false) { ViewBag.ID = id; @@ -344,10 +346,10 @@ public ActionResult Raw(Guid id, string encodedName, string encodedPath, bool di } } - return HttpNotFound(); + return NotFound(); } - [WebAuthorizeRepository] + [Authorize(Policy = "WebRepository")] public ActionResult Blame(Guid id, string encodedName, string encodedPath) { ViewBag.ID = id; @@ -367,19 +369,19 @@ public ActionResult Blame(Guid id, string encodedName, string encodedPath) } } - [WebAuthorizeRepository] + [Authorize(Policy = "WebRepository")] public ActionResult Download(Guid id, string encodedName, string encodedPath) { var name = PathEncoder.Decode(encodedName); var path = PathEncoder.Decode(encodedPath); - Response.BufferOutput = false; - Response.Charset = ""; + //Response.BufferOutput = false; + //Response.Charset = ""; Response.ContentType = "application/zip"; var repo = RepositoryRepository.GetRepository(id); string headerValue = ContentDispositionUtil.GetHeaderValue((name ?? repo.Name) + ".zip"); - Response.AddHeader("Content-Disposition", headerValue); + Response.Headers.Add("Content-Disposition", headerValue); using (var outputZip = new ZipFile()) { @@ -392,7 +394,7 @@ public ActionResult Download(Guid id, string encodedName, string encodedPath) AddTreeToZip(browser, name, path, outputZip); } - outputZip.Save(Response.OutputStream); + outputZip.Save(Response.Body); return new EmptyResult(); } @@ -423,7 +425,7 @@ private static void AddTreeToZip(RepositoryBrowser browser, string name, string } } - [WebAuthorizeRepository] + [Authorize(Policy = "WebRepository")] public ActionResult Tags(Guid id, string encodedName, int page = 1) { page = page >= 1 ? page : 1; @@ -447,7 +449,7 @@ public ActionResult Tags(Guid id, string encodedName, int page = 1) } } - [WebAuthorizeRepository] + [Authorize(Policy = "WebRepository")] public ActionResult Commits(Guid id, string encodedName, int? page = null) { page = page >= 1 ? page : 1; @@ -508,7 +510,7 @@ public ActionResult Commits(Guid id, string encodedName, int? page = null) } } - [WebAuthorizeRepository] + [Authorize(Policy = "WebRepository")] public ActionResult Commit(Guid id, string commit) { ViewBag.ID = id; @@ -523,7 +525,7 @@ public ActionResult Commit(Guid id, string commit) } } - [WebAuthorize] + [Authorize(Policy = "Web")] public ActionResult Clone(Guid id) { if (!RepositoryPermissionService.HasCreatePermission(User.Id())) @@ -539,8 +541,8 @@ public ActionResult Clone(Guid id) } [HttpPost] - [WebAuthorize] - [WebAuthorizeRepository] + [Authorize(Policy = "Web")] + [Authorize(Policy = "WebRepository")] [ValidateAntiForgeryToken] public ActionResult Clone(Guid id, RepositoryDetailModel model) { @@ -605,7 +607,7 @@ public ActionResult Clone(Guid id, RepositoryDetailModel model) return View(model); } - [WebAuthorizeRepository] + [Authorize(Policy = "WebRepository")] public ActionResult History(Guid id, string encodedPath, string encodedName) { ViewBag.ID = id; @@ -649,12 +651,12 @@ private void PopulateCheckboxListData(ref RepositoryDetailModel model) } [HttpPost] - [WebAuthorize(Roles = Definitions.Roles.Administrator)] + [Authorize(Policy = "Web", Roles = Definitions.Roles.Administrator)] // This takes an irrelevant ID, because there isn't a good route // to RepositoryController for anything without an Id which isn't the Index action public ActionResult Rescan(string id) { - new RepositorySynchronizer().Run(); + new RepositorySynchronizer(HttpContext.RequestServices.GetService()).Run(); return RedirectToAction("Index"); } diff --git a/Bonobo.Git.Server/Controllers/SettingsController.cs b/Bonobo.Git.Server/Controllers/SettingsController.cs index 54a9b9616..c8ea831dc 100644 --- a/Bonobo.Git.Server/Controllers/SettingsController.cs +++ b/Bonobo.Git.Server/Controllers/SettingsController.cs @@ -1,21 +1,27 @@ using System; -using System.Collections.Generic; -using System.Configuration; using System.Globalization; using System.IO; -using System.Linq; -using System.Web; -using System.Web.Configuration; -using System.Web.Mvc; +using Microsoft.AspNetCore.Mvc; using Bonobo.Git.Server.App_GlobalResources; using Bonobo.Git.Server.Configuration; using Bonobo.Git.Server.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Newtonsoft.Json; namespace Bonobo.Git.Server.Controllers { public class SettingsController : Controller { - [WebAuthorize(Roles = Definitions.Roles.Administrator)] + private readonly IHostingEnvironment hostingEnvironment; + + public SettingsController(IHostingEnvironment hostingEnvironment) + { + this.hostingEnvironment = hostingEnvironment; + } + + [Authorize(Policy = "Web", Roles = Definitions.Roles.Administrator)] public ActionResult Index() { return View(new GlobalSettingsModel @@ -38,7 +44,7 @@ public ActionResult Index() [HttpPost] [ValidateAntiForgeryToken] - [WebAuthorize(Roles = Definitions.Roles.Administrator)] + [Authorize(Policy = "Web", Roles = Definitions.Roles.Administrator)] public ActionResult Index(GlobalSettingsModel model) { if (AuthenticationSettings.DemoModeActive) @@ -52,7 +58,7 @@ public ActionResult Index(GlobalSettingsModel model) { if (Directory.Exists(Path.IsPathRooted(model.RepositoryPath) ? model.RepositoryPath - : HttpContext.Server.MapPath(model.RepositoryPath))) + : Path.Combine(hostingEnvironment.ContentRootPath, model.RepositoryPath))) { UserConfiguration.Current.AllowAnonymousPush = model.AllowAnonymousPush; UserConfiguration.Current.RepositoryPath = model.RepositoryPath; @@ -69,7 +75,7 @@ public ActionResult Index(GlobalSettingsModel model) UserConfiguration.Current.LinksUrl = model.LinksUrl; UserConfiguration.Current.Save(); - this.Session["Culture"] = new CultureInfo(model.DefaultLanguage); + HttpContext.Session.SetString("Culture", JsonConvert.SerializeObject(new CultureInfo(model.DefaultLanguage))); TempData["UpdateSuccess"] = true; return RedirectToAction("Index"); diff --git a/Bonobo.Git.Server/Controllers/TeamController.cs b/Bonobo.Git.Server/Controllers/TeamController.cs index 057303feb..93180800c 100644 --- a/Bonobo.Git.Server/Controllers/TeamController.cs +++ b/Bonobo.Git.Server/Controllers/TeamController.cs @@ -1,35 +1,37 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Web.Mvc; +using Microsoft.AspNetCore.Mvc; using Bonobo.Git.Server.Data; using Bonobo.Git.Server.Models; using Bonobo.Git.Server.Security; using Bonobo.Git.Server.App_GlobalResources; - -using Microsoft.Practices.Unity; +using Microsoft.AspNetCore.Authorization; namespace Bonobo.Git.Server.Controllers { public class TeamController : Controller { - [Dependency] public IMembershipService MembershipService { get; set; } - - [Dependency] public IRepositoryRepository RepositoryRepository { get; set; } - - [Dependency] public ITeamRepository TeamRepository { get; set; } - [WebAuthorize(Roles = Definitions.Roles.Administrator)] + public TeamController(IMembershipService membershipService, IRepositoryRepository repositoryRepository, + ITeamRepository teamRepository) + { + MembershipService = membershipService; + RepositoryRepository = repositoryRepository; + TeamRepository = teamRepository; + } + + [Authorize(Policy = "Web", Roles = Definitions.Roles.Administrator)] public ActionResult Index() { return View(ConvertTeamModels(TeamRepository.GetAllTeams())); } - [WebAuthorize(Roles = Definitions.Roles.Administrator)] + [Authorize(Policy = "Web", Roles = Definitions.Roles.Administrator)] public ActionResult Edit(Guid id) { var model = ConvertEditTeamModel(TeamRepository.GetTeam(id)); @@ -38,7 +40,7 @@ public ActionResult Edit(Guid id) [HttpPost] [ValidateAntiForgeryToken] - [WebAuthorize(Roles = Definitions.Roles.Administrator)] + [Authorize(Policy = "Web", Roles = Definitions.Roles.Administrator)] public ActionResult Edit(TeamEditModel model) { if (ModelState.IsValid) @@ -50,7 +52,7 @@ public ActionResult Edit(TeamEditModel model) return View(model); } - [WebAuthorize(Roles = Definitions.Roles.Administrator)] + [Authorize(Policy = "Web", Roles = Definitions.Roles.Administrator)] public ActionResult Create() { var model = new TeamEditModel @@ -63,7 +65,7 @@ public ActionResult Create() [HttpPost] [ValidateAntiForgeryToken] - [WebAuthorize(Roles = Definitions.Roles.Administrator)] + [Authorize(Policy = "Web", Roles = Definitions.Roles.Administrator)] public ActionResult Create(TeamEditModel model) { while (!String.IsNullOrEmpty(model.Name) && model.Name.Last() == ' ') @@ -89,7 +91,7 @@ public ActionResult Create(TeamEditModel model) return View(model); } - [WebAuthorize(Roles = Definitions.Roles.Administrator)] + [Authorize(Policy = "Web", Roles = Definitions.Roles.Administrator)] public ActionResult Delete(Guid id) { return View(ConvertEditTeamModel(TeamRepository.GetTeam(id))); @@ -97,7 +99,7 @@ public ActionResult Delete(Guid id) [HttpPost] [ValidateAntiForgeryToken] - [WebAuthorize(Roles = Definitions.Roles.Administrator)] + [Authorize(Policy = "Web", Roles = Definitions.Roles.Administrator)] public ActionResult Delete(TeamEditModel model) { if (model != null && model.Id != null) @@ -110,7 +112,7 @@ public ActionResult Delete(TeamEditModel model) return RedirectToAction("Index"); } - [WebAuthorize] + [Authorize(Policy = "Web")] public ActionResult Detail(Guid id) { return View(ConvertDetailTeamModel(TeamRepository.GetTeam(id))); diff --git a/Bonobo.Git.Server/Controllers/ValidationController.cs b/Bonobo.Git.Server/Controllers/ValidationController.cs index 569003fce..60926bcf3 100644 --- a/Bonobo.Git.Server/Controllers/ValidationController.cs +++ b/Bonobo.Git.Server/Controllers/ValidationController.cs @@ -1,37 +1,42 @@ using Bonobo.Git.Server.Attributes; using Bonobo.Git.Server.Data; using Bonobo.Git.Server.Security; -using Microsoft.Practices.Unity; using System; using System.ComponentModel.DataAnnotations; -using System.Web.Mvc; -using System.Web.UI; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Infrastructure; namespace Bonobo.Git.Server.Controllers { - [OutputCache(Location = OutputCacheLocation.None, NoStore = true)] + [ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)] public class ValidationController : Controller { - [Dependency] public IRepositoryRepository RepoRepo { get; set; } - - [Dependency] public IMembershipService MembershipService { get; set; } - - [Dependency] public ITeamRepository TeamRepo { get; set; } + private readonly IActionContextAccessor actionContextAccessor; + + public ValidationController(IRepositoryRepository repoRepo, IMembershipService membershipService, + ITeamRepository teamRepository, IActionContextAccessor actionContextAccessor) + { + RepoRepo = repoRepo; + MembershipService = membershipService; + TeamRepo = teamRepository; + this.actionContextAccessor = actionContextAccessor; + } + public ActionResult UniqueNameRepo(string name, Guid? id) { bool isUnique = RepoRepo.NameIsUnique(name, id ?? Guid.Empty); - return Json(isUnique, JsonRequestBehavior.AllowGet); + return Json(isUnique); } public ActionResult UniqueNameUser(string Username, Guid? id) { var possibly_existent_user = MembershipService.GetUserModel(Username); bool exists = (possibly_existent_user != null) && (id != possibly_existent_user.Id); - return Json(!exists, JsonRequestBehavior.AllowGet); + return Json(!exists); } public ActionResult UniqueNameTeam(string name, Guid? id) @@ -39,19 +44,19 @@ public ActionResult UniqueNameTeam(string name, Guid? id) var possibly_existing_team = TeamRepo.GetTeam(name); bool exists = (possibly_existing_team != null) && (id != possibly_existing_team.Id); // false when repo exists! - return Json(!exists, JsonRequestBehavior.AllowGet); + return Json(!exists); } public ActionResult IsValidRegex(string LinksRegex) { - var validationContext = new ValidationContext(Request.RequestContext); + var validationContext = new ValidationContext(actionContextAccessor.ActionContext); var isvalidregexattr = new IsValidRegexAttribute(); var result = isvalidregexattr.GetValidationResult(LinksRegex, validationContext); if (result == System.ComponentModel.DataAnnotations.ValidationResult.Success) { - return Json(true, JsonRequestBehavior.AllowGet); + return Json(true); } - return Json(result.ErrorMessage, JsonRequestBehavior.AllowGet); + return Json(result.ErrorMessage); } } } \ No newline at end of file diff --git a/Bonobo.Git.Server/Data/ADBackend.cs b/Bonobo.Git.Server/Data/ADBackend.cs index 74ac59e57..fc1b806c4 100644 --- a/Bonobo.Git.Server/Data/ADBackend.cs +++ b/Bonobo.Git.Server/Data/ADBackend.cs @@ -1,23 +1,22 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Web; using Bonobo.Git.Server.Models; using System.DirectoryServices.AccountManagement; -using System.Threading.Tasks; using Bonobo.Git.Server.Configuration; using Bonobo.Git.Server.Security; using System.Threading; -using Microsoft.Practices.Unity; using Bonobo.Git.Server.Helpers; +using Microsoft.AspNetCore.Hosting; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.Extensions.DependencyInjection; using Serilog; namespace Bonobo.Git.Server.Data { public sealed class ADBackend { - [Dependency] + public IHostingEnvironment HostingEnvironment { get; set; } public IMembershipService MembershipService { get; set; } public ADBackendStore Repositories { get { return repositories.Value; } } @@ -63,25 +62,13 @@ public static void ResetSingletonWithAutomaticUpdate() } } - private Lazy> repositories = new Lazy>(() => - { - return new ADBackendStore(ActiveDirectorySettings.BackendPath, "Repos"); - }); + private Lazy> repositories; - private Lazy> teams = new Lazy>(() => - { - return new ADBackendStore(ActiveDirectorySettings.BackendPath, "Teams"); - }); + private Lazy> teams; - private Lazy> users = new Lazy>(() => - { - return new ADBackendStore(ActiveDirectorySettings.BackendPath, "Users"); - }); + private Lazy> users; - private Lazy> roles = new Lazy>(() => - { - return new ADBackendStore(ActiveDirectorySettings.BackendPath, "Roles"); - }); + private Lazy> roles; private static volatile ADBackend instance; private static object instanceLock = new object(); @@ -94,6 +81,26 @@ private ADBackend(bool enableAutoUpdate) { updateTimer = new Timer(Update, null, TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(180)); } + + repositories = new Lazy>(() => + { + return new ADBackendStore(HostingEnvironment, ActiveDirectorySettings.BackendPath, "Repos"); + }); + + teams = new Lazy>(() => + { + return new ADBackendStore(HostingEnvironment, ActiveDirectorySettings.BackendPath, "Teams"); + }); + + users = new Lazy>(() => + { + return new ADBackendStore(HostingEnvironment, ActiveDirectorySettings.BackendPath, "Users"); + }); + + roles = new Lazy>(() => + { + return new ADBackendStore(HostingEnvironment, ActiveDirectorySettings.BackendPath, "Roles"); + }); } private void Update(object state) diff --git a/Bonobo.Git.Server/Data/ADBackendStore.cs b/Bonobo.Git.Server/Data/ADBackendStore.cs index d49045a06..3b577af74 100644 --- a/Bonobo.Git.Server/Data/ADBackendStore.cs +++ b/Bonobo.Git.Server/Data/ADBackendStore.cs @@ -2,16 +2,10 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; -using System.Configuration; using System.IO; -using System.Linq; -using System.Security.Cryptography; -using System.Text; -using System.Web; using System.Collections; -using System.Web.Hosting; -using Bonobo.Git.Server.Configuration; using Bonobo.Git.Server.Helpers; +using Microsoft.AspNetCore.Hosting; using Serilog; namespace Bonobo.Git.Server.Data @@ -38,9 +32,9 @@ public T this[Guid key] private readonly string _storagePath; private readonly ConcurrentDictionary _content; - public ADBackendStore(string rootpath, string name) + public ADBackendStore(IHostingEnvironment hostingEnvironment, string rootpath, string name) { - _storagePath = Path.Combine(PathEncoder.GetRootPath(rootpath), name); + _storagePath = Path.Combine(PathEncoder.GetRootPath(hostingEnvironment, rootpath), name); _content = LoadContent(); } diff --git a/Bonobo.Git.Server/Data/BonoboGitServerContext.cs b/Bonobo.Git.Server/Data/BonoboGitServerContext.cs index d01e0d8c6..f7545f8fc 100644 --- a/Bonobo.Git.Server/Data/BonoboGitServerContext.cs +++ b/Bonobo.Git.Server/Data/BonoboGitServerContext.cs @@ -1,44 +1,113 @@ -using System.Data.Common; +using Bonobo.Git.Server.Data.ManyToMany; using Bonobo.Git.Server.Data.Mapping; -using System.Data.Entity; -using Microsoft.Practices.Unity; +using Bonobo.Git.Server.Data.Update.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace Bonobo.Git.Server.Data { - public partial class BonoboGitServerContext : DbContext + public class BonoboGitServerContext : DbContext { public DbSet Repositories { get; set; } public DbSet Roles { get; set; } public DbSet Teams { get; set; } public DbSet Users { get; set; } - - static BonoboGitServerContext() + public BonoboGitServerContext(DbContextOptions options) : base(options) { - Database.SetInitializer(null); } - public BonoboGitServerContext() - : base("Name=BonoboGitServerContext") + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { + optionsBuilder.UseLazyLoadingProxies(); } - // Don't make this public because it confuses Unity - private BonoboGitServerContext(DbConnection databaseConnection) : base(databaseConnection, false) + protected override void OnModelCreating(ModelBuilder modelBuilder) { - } + ValueConverter primaryKeyConverter = null; + if (Database.IsSqlite()) + { + primaryKeyConverter = new GuidToStringConverter(); + } - public static BonoboGitServerContext FromDatabase(DbConnection databaseConnection) - { - return new BonoboGitServerContext(databaseConnection); - } + modelBuilder.ApplyConfiguration(new RepositoryMap(primaryKeyConverter)); + modelBuilder.ApplyConfiguration(new RoleMap(primaryKeyConverter)); + modelBuilder.ApplyConfiguration(new TeamMap(primaryKeyConverter)); + modelBuilder.ApplyConfiguration(new UserMap(primaryKeyConverter)); - protected override void OnModelCreating(DbModelBuilder modelBuilder) - { - modelBuilder.Configurations.Add(new RepositoryMap()); - modelBuilder.Configurations.Add(new RoleMap()); - modelBuilder.Configurations.Add(new TeamMap()); - modelBuilder.Configurations.Add(new UserMap()); + modelBuilder.Query(); + modelBuilder.Query(); + modelBuilder.Query(); + + var builder1 = modelBuilder.Entity(); + builder1.Property(x => x.TeamId).HasColumnName("Team_Id").HasConversion(primaryKeyConverter); + builder1.Property(x => x.RepositoryId).HasColumnName("Repository_Id").HasConversion(primaryKeyConverter); + builder1.HasKey(x => new { x.RepositoryId, x.TeamId }); + + builder1.HasOne(x => x.Repository) + .WithMany(r => r.Teams) + .HasForeignKey(x => x.RepositoryId); + + builder1.HasOne(x => x.Team) + .WithMany(t => t.Repositories) + .HasForeignKey(x => x.TeamId); + + + var builder2 = modelBuilder.Entity(); + builder2.Property(x => x.UserId).HasColumnName("User_Id").HasConversion(primaryKeyConverter); + builder2.Property(x => x.RepositoryId).HasColumnName("Repository_Id").HasConversion(primaryKeyConverter); + builder2.HasKey(x => new {x.RepositoryId, x.UserId}); + + builder2.HasOne(x => x.User) + .WithMany(u => u.AdministratedRepositories) + .HasForeignKey(x => x.UserId); + + builder2.HasOne(x => x.Repository) + .WithMany(r => r.Administrators) + .HasForeignKey(x => x.RepositoryId); + + + var builder3 = modelBuilder.Entity(); + builder3.Property(x => x.UserId).HasColumnName("User_Id").HasConversion(primaryKeyConverter); + builder3.Property(x => x.RepositoryId).HasColumnName("Repository_Id").HasConversion(primaryKeyConverter); + builder3.HasKey(x => new {x.RepositoryId, x.UserId}); + + builder3.HasOne(x => x.User) + .WithMany(u => u.Repositories) + .HasForeignKey(x => x.UserId); + + builder3.HasOne(x => x.Repository) + .WithMany(r => r.Users) + .HasForeignKey(x => x.RepositoryId); + + var builder4 = modelBuilder.Entity(); + builder4.Property(x => x.UserId).HasColumnName("User_Id").HasConversion(primaryKeyConverter); + builder4.Property(x => x.RoleId).HasColumnName("Role_Id").HasConversion(primaryKeyConverter); + builder4.HasKey(x => new {x.RoleId, x.UserId}); + + builder4.HasOne(x => x.User) + .WithMany(u => u.Roles) + .HasForeignKey(x => x.UserId) + .OnDelete(DeleteBehavior.Cascade); + + builder4.HasOne(x => x.Role) + .WithMany(r => r.Users) + .HasForeignKey(x => x.RoleId) + .OnDelete(DeleteBehavior.Cascade); + + + var builder5 = modelBuilder.Entity(); + builder5.Property(x => x.UserId).HasColumnName("User_Id").HasConversion(primaryKeyConverter); + builder5.Property(x => x.TeamId).HasColumnName("Team_Id").HasConversion(primaryKeyConverter); + builder5.HasKey(x => new {x.TeamId, x.UserId}); + + builder5.HasOne(x => x.User) + .WithMany(u => u.Teams) + .HasForeignKey(x => x.UserId); + + builder5.HasOne(x => x.Team) + .WithMany(t => t.Users) + .HasForeignKey(x => x.TeamId); } } } diff --git a/Bonobo.Git.Server/Data/DatabaseResetManager.cs b/Bonobo.Git.Server/Data/DatabaseResetManager.cs index 3684bc1c9..1df6f0793 100644 --- a/Bonobo.Git.Server/Data/DatabaseResetManager.cs +++ b/Bonobo.Git.Server/Data/DatabaseResetManager.cs @@ -1,7 +1,5 @@ using System; -using System.Runtime.Remoting.Messaging; using Bonobo.Git.Server.Security; -using Microsoft.Practices.Unity; using System.Configuration; using Serilog; @@ -17,18 +15,23 @@ public interface IDatabaseResetManager /// public class DatabaseResetManager : IDatabaseResetManager { - [Dependency] public IRepositoryRepository Repository { get; set; } - [Dependency] public IRoleProvider RoleProvider { get; set; } - [Dependency] public ITeamRepository TeamRepository { get; set; } - [Dependency] public IMembershipService Users { get; set; } + public DatabaseResetManager(IRepositoryRepository repositoryRepository, IRoleProvider roleProvider, + ITeamRepository teamRepository, IMembershipService users) + { + Repository = repositoryRepository; + RoleProvider = roleProvider; + TeamRepository = teamRepository; + Users = users; + } + public void DoReset(int mode) { Log.Information("Reset mode {mode}", mode); diff --git a/Bonobo.Git.Server/Data/EFRepositoryRepository.cs b/Bonobo.Git.Server/Data/EFRepositoryRepository.cs index a9ed1ce48..dc683564d 100644 --- a/Bonobo.Git.Server/Data/EFRepositoryRepository.cs +++ b/Bonobo.Git.Server/Data/EFRepositoryRepository.cs @@ -1,52 +1,29 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.CompilerServices; +using Bonobo.Git.Server.Data.ManyToMany; using Bonobo.Git.Server.Models; -using System.Data.Entity.Core; -using System.Data.Entity.Infrastructure; -using Microsoft.Practices.Unity; +using Microsoft.EntityFrameworkCore; using Serilog; namespace Bonobo.Git.Server.Data { public class EFRepositoryRepository : IRepositoryRepository { - [Dependency] public Func CreateContext { get; set; } + public EFRepositoryRepository(Func createContext) + { + CreateContext = createContext; + } + public IList GetAllRepositories() { using (var db = CreateContext()) { - var dbrepos = db.Repositories.Select(repo => new - { - Id = repo.Id, - Name = repo.Name, - Group = repo.Group, - Description = repo.Description, - AnonymousAccess = repo.Anonymous, - Users = repo.Users, - Teams = repo.Teams, - Administrators = repo.Administrators, - AuditPushUser = repo.AuditPushUser, - AllowAnonPush = repo.AllowAnonymousPush, - Logo = repo.Logo - }).ToList(); - - return dbrepos.Select(repo => new RepositoryModel - { - Id = repo.Id, - Name = repo.Name, - Group = repo.Group, - Description = repo.Description, - AnonymousAccess = repo.AnonymousAccess, - Users = repo.Users.Select(user => user.ToModel()).ToArray(), - Teams = repo.Teams.Select(TeamToTeamModel).ToArray(), - Administrators = repo.Administrators.Select(user => user.ToModel()).ToArray(), - AuditPushUser = repo.AuditPushUser, - AllowAnonymousPush = repo.AllowAnonPush, - Logo = repo.Logo - }).ToList(); + var dbrepos = db.Repositories.ToList(); + return dbrepos.Select(ConvertToModel).ToList(); } } @@ -133,10 +110,6 @@ public bool Create(RepositoryModel model) Log.Error(ex, "Failed to create repo {RepoName}", model.Name); return false; } - catch (UpdateException) - { - return false; - } return true; } } @@ -187,7 +160,7 @@ private TeamModel TeamToTeamModel(Team t) Id = t.Id, Name = t.Name, Description = t.Description, - Members = t.Users.Select(user => user.ToModel()).ToArray() + Members = t.Users.Select(user => user.User.ToModel()).ToArray() }; } @@ -205,16 +178,15 @@ private RepositoryModel ConvertToModel(Repository item) Group = item.Group, Description = item.Description, AnonymousAccess = item.Anonymous, - Users = item.Users.Select(user => user.ToModel()).ToArray(), - Teams = item.Teams.Select(TeamToTeamModel).ToArray(), - Administrators = item.Administrators.Select(user => user.ToModel()).ToArray(), + Users = item.Users.Select(user => user.User.ToModel()).ToArray(), + Teams = item.Teams.Select(x => TeamToTeamModel(x.Team)).ToArray(), + Administrators = item.Administrators.Select(user => user.User.ToModel()).ToArray(), AuditPushUser = item.AuditPushUser, AllowAnonymousPush = item.AllowAnonymousPush, Logo = item.Logo, LinksRegex = item.LinksRegex, LinksUrl = item.LinksUrl, LinksUseGlobal = item.LinksUseGlobal - }; } @@ -225,7 +197,11 @@ private void AddMembers(IEnumerable users, IEnumerable admins, IEnum var administrators = database.Users.Where(i => admins.Contains(i.Id)); foreach (var item in administrators) { - repo.Administrators.Add(item); + repo.Administrators.Add(new UserRepository_Administrator + { + Repository = repo, + User = item + }); } } @@ -234,7 +210,11 @@ private void AddMembers(IEnumerable users, IEnumerable admins, IEnum var permittedUsers = database.Users.Where(i => users.Contains(i.Id)); foreach (var item in permittedUsers) { - repo.Users.Add(item); + repo.Users.Add(new UserRepository_Permission + { + Repository = repo, + User = item + }); } } @@ -243,7 +223,12 @@ private void AddMembers(IEnumerable users, IEnumerable admins, IEnum var permittedTeams = database.Teams.Where(i => teams.Contains(i.Id)); foreach (var item in permittedTeams) { - repo.Teams.Add(item); + if (repo.Teams == null) repo.Teams = new List(); + repo.Teams.Add(new TeamRepository_Permission + { + Repository = repo, + Team = item + }); } } } diff --git a/Bonobo.Git.Server/Data/EFTeamRepository.cs b/Bonobo.Git.Server/Data/EFTeamRepository.cs index b6d0a4852..abfd0c181 100644 --- a/Bonobo.Git.Server/Data/EFTeamRepository.cs +++ b/Bonobo.Git.Server/Data/EFTeamRepository.cs @@ -1,18 +1,21 @@ using System; using System.Collections.Generic; using System.Linq; +using Bonobo.Git.Server.Data.ManyToMany; using Bonobo.Git.Server.Models; -using System.Data.Entity.Core; -using System.Data.Entity.Infrastructure; -using Microsoft.Practices.Unity; +using Microsoft.EntityFrameworkCore; namespace Bonobo.Git.Server.Data { public class EFTeamRepository : ITeamRepository { - [Dependency] public Func CreateContext { get; set; } + public EFTeamRepository(Func createContext) + { + CreateContext = createContext; + } + public IList GetAllTeams() { using (var db = CreateContext()) @@ -22,8 +25,8 @@ public IList GetAllTeams() Id = team.Id, Name = team.Name, Description = team.Description, - Members = team.Users, - Repositories = team.Repositories.Select(m => m.Name), + Members = team.Users.Select(user => user.User.ToModel()).ToArray(), + Repositories = team.Repositories.Select(m => m.Repository.Name), }).ToList(); return dbTeams.Select(item => new TeamModel @@ -31,7 +34,7 @@ public IList GetAllTeams() Id = item.Id, Name = item.Name, Description = item.Description, - Members = item.Members.Select(user => user.ToModel()).ToArray(), + Members = item.Members, }).ToList(); } } @@ -48,7 +51,7 @@ private TeamModel GetTeamModel(Team team) Id = team.Id, Name = team.Name, Description = team.Description, - Members = team.Users.Select(user => user.ToModel()).ToArray(), + Members = team.Users.Select(user => user.User.ToModel()).ToArray(), }; } @@ -117,11 +120,6 @@ public bool Create(TeamModel model) { return false; } - catch (UpdateException) - { - // Not sure when this exception happens - DbUpdateException is what you get for adding a duplicate teamname - return false; - } } return true; @@ -154,7 +152,11 @@ private void AddMembers(IEnumerable members, Team team, BonoboGitServerCon var users = database.Users.Where(user => members.Contains(user.Id)); foreach (var item in users) { - team.Users.Add(item); + team.Users.Add(new UserTeam_Member + { + Team = team, + User = item + }); } } @@ -171,7 +173,11 @@ public void UpdateUserTeams(Guid userId, List newTeams) var teams = db.Teams.Where(t => newTeams.Contains(t.Name)); foreach (var team in teams) { - user.Teams.Add(team); + user.Teams.Add(new UserTeam_Member + { + User = user, + Team = team + }); } db.SaveChanges(); } diff --git a/Bonobo.Git.Server/Data/IRepositoryRepository.cs b/Bonobo.Git.Server/Data/IRepositoryRepository.cs index c5d166c97..8a184f778 100644 --- a/Bonobo.Git.Server/Data/IRepositoryRepository.cs +++ b/Bonobo.Git.Server/Data/IRepositoryRepository.cs @@ -1,7 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Web; using Bonobo.Git.Server.Models; namespace Bonobo.Git.Server.Data diff --git a/Bonobo.Git.Server/Data/ManyToMany/TeamRepository_Permission.cs b/Bonobo.Git.Server/Data/ManyToMany/TeamRepository_Permission.cs new file mode 100644 index 000000000..1501bb880 --- /dev/null +++ b/Bonobo.Git.Server/Data/ManyToMany/TeamRepository_Permission.cs @@ -0,0 +1,13 @@ +using System; + +namespace Bonobo.Git.Server.Data.ManyToMany +{ + public class TeamRepository_Permission + { + public Guid RepositoryId { get; set; } + public Guid TeamId { get; set; } + + public virtual Repository Repository { get; set; } + public virtual Team Team { get; set; } + } +} diff --git a/Bonobo.Git.Server/Data/ManyToMany/UserRepository_Administrator.cs b/Bonobo.Git.Server/Data/ManyToMany/UserRepository_Administrator.cs new file mode 100644 index 000000000..f316e58c6 --- /dev/null +++ b/Bonobo.Git.Server/Data/ManyToMany/UserRepository_Administrator.cs @@ -0,0 +1,13 @@ +using System; + +namespace Bonobo.Git.Server.Data.ManyToMany +{ + public class UserRepository_Administrator + { + public Guid RepositoryId { get; set; } + public Guid UserId { get; set; } + + public virtual Repository Repository { get; set; } + public virtual User User { get; set; } + } +} diff --git a/Bonobo.Git.Server/Data/ManyToMany/UserRepository_Permission.cs b/Bonobo.Git.Server/Data/ManyToMany/UserRepository_Permission.cs new file mode 100644 index 000000000..2f3f37ea6 --- /dev/null +++ b/Bonobo.Git.Server/Data/ManyToMany/UserRepository_Permission.cs @@ -0,0 +1,13 @@ +using System; + +namespace Bonobo.Git.Server.Data.ManyToMany +{ + public class UserRepository_Permission + { + public Guid RepositoryId { get; set; } + public Guid UserId { get; set; } + + public virtual Repository Repository { get; set; } + public virtual User User { get; set; } + } +} diff --git a/Bonobo.Git.Server/Data/ManyToMany/UserRole_InRole.cs b/Bonobo.Git.Server/Data/ManyToMany/UserRole_InRole.cs new file mode 100644 index 000000000..f58282e62 --- /dev/null +++ b/Bonobo.Git.Server/Data/ManyToMany/UserRole_InRole.cs @@ -0,0 +1,13 @@ +using System; + +namespace Bonobo.Git.Server.Data.ManyToMany +{ + public class UserRole_InRole + { + public Guid RoleId { get; set; } + public Guid UserId { get; set; } + + public virtual Role Role { get; set; } + public virtual User User { get; set; } + } +} diff --git a/Bonobo.Git.Server/Data/ManyToMany/UserTeam_Member.cs b/Bonobo.Git.Server/Data/ManyToMany/UserTeam_Member.cs new file mode 100644 index 000000000..ec469126e --- /dev/null +++ b/Bonobo.Git.Server/Data/ManyToMany/UserTeam_Member.cs @@ -0,0 +1,13 @@ +using System; + +namespace Bonobo.Git.Server.Data.ManyToMany +{ + public class UserTeam_Member + { + public Guid TeamId { get; set; } + public Guid UserId { get; set; } + + public virtual Team Team { get; set; } + public virtual User User { get; set; } + } +} diff --git a/Bonobo.Git.Server/Data/Mapping/RepositoryMap.cs b/Bonobo.Git.Server/Data/Mapping/RepositoryMap.cs index b176cbb8b..d9f8095ea 100644 --- a/Bonobo.Git.Server/Data/Mapping/RepositoryMap.cs +++ b/Bonobo.Git.Server/Data/Mapping/RepositoryMap.cs @@ -1,79 +1,87 @@ -using System.ComponentModel.DataAnnotations.Schema; -using System.Data.Entity.ModelConfiguration; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace Bonobo.Git.Server.Data.Mapping { - public class RepositoryMap : EntityTypeConfiguration + public class RepositoryMap : IEntityTypeConfiguration { - public RepositoryMap() + private readonly ValueConverter _primaryKeyConverter; + + public RepositoryMap(ValueConverter primaryKeyConverter) + { + _primaryKeyConverter = primaryKeyConverter; + } + + public void Configure(EntityTypeBuilder builder) { - SetPrimaryKey(); - SetProperties(); - SetTableAndColumnMappings(); - SetRelationships(); + SetPrimaryKey(builder); + SetProperties(builder); + SetTableAndColumnMappings(builder); + SetRelationships(builder); } - private void SetRelationships() + private void SetRelationships(EntityTypeBuilder builder) { - HasMany(t => t.Teams) - .WithMany(t => t.Repositories) - .Map(m => - { - m.ToTable("TeamRepository_Permission"); - m.MapLeftKey("Repository_Id"); - m.MapRightKey("Team_Id"); - }); + //builder.HasMany(t => t.Teams) + // .WithMany(t => t.Repositories) + // .Map(m => + // { + // m.ToTable("TeamRepository_Permission"); + // m.MapLeftKey("Repository_Id"); + // m.MapRightKey("Team_Id"); + // }); - HasMany(t => t.Administrators) - .WithMany(t => t.AdministratedRepositories) - .Map(m => - { - m.ToTable("UserRepository_Administrator"); - m.MapLeftKey("Repository_Id"); - m.MapRightKey("User_Id"); - }); + //builder.HasMany(t => t.Administrators) + // .WithMany(t => t.AdministratedRepositories) + // .Map(m => + // { + // m.ToTable("UserRepository_Administrator"); + // m.MapLeftKey("Repository_Id"); + // m.MapRightKey("User_Id"); + // }); - HasMany(t => t.Users) - .WithMany(t => t.Repositories) - .Map(m => - { - m.ToTable("UserRepository_Permission"); - m.MapLeftKey("Repository_Id"); - m.MapRightKey("User_Id"); - }); + //builder.HasMany(t => t.Users) + // .WithMany(t => t.Repositories) + // .Map(m => + // { + // m.ToTable("UserRepository_Permission"); + // m.MapLeftKey("Repository_Id"); + // m.MapRightKey("User_Id"); + // }); } - private void SetTableAndColumnMappings() + private void SetTableAndColumnMappings(EntityTypeBuilder builder) { - ToTable("Repository"); - Property(t => t.Id).HasColumnName("Id"); - Property(t => t.Name).HasColumnName("Name"); - Property(t => t.Group).HasColumnName("Group"); - Property(t => t.Description).HasColumnName("Description"); - Property(t => t.Anonymous).HasColumnName("Anonymous"); - Property(t => t.AuditPushUser).HasColumnName("AuditPushUser"); - Property(t => t.AllowAnonymousPush).HasColumnName("AllowAnonymousPush"); - Property(t => t.LinksRegex).HasColumnName("LinksRegex"); - Property(t => t.LinksUrl).HasColumnName("LinksUrl"); - Property(t => t.LinksUseGlobal).HasColumnName("LinksUseGlobal"); + builder.ToTable("Repository"); + builder.Property(t => t.Id).HasColumnName("Id").HasConversion(_primaryKeyConverter); + builder.Property(t => t.Name).HasColumnName("Name"); + builder.Property(t => t.Group).HasColumnName("Group"); + builder.Property(t => t.Description).HasColumnName("Description"); + builder.Property(t => t.Anonymous).HasColumnName("Anonymous"); + builder.Property(t => t.AuditPushUser).HasColumnName("AuditPushUser"); + builder.Property(t => t.AllowAnonymousPush).HasColumnName("AllowAnonymousPush"); + builder.Property(t => t.LinksRegex).HasColumnName("LinksRegex"); + builder.Property(t => t.LinksUrl).HasColumnName("LinksUrl"); + builder.Property(t => t.LinksUseGlobal).HasColumnName("LinksUseGlobal"); } - private void SetProperties() + private void SetProperties(EntityTypeBuilder builder) { - Property(t => t.Name) + builder.Property(t => t.Name) .IsRequired() .HasMaxLength(255); - Property(t => t.Group) + builder.Property(t => t.Group) .HasMaxLength(255); - Property(t => t.Description) + builder.Property(t => t.Description) .HasMaxLength(255); } - private void SetPrimaryKey() + private void SetPrimaryKey(EntityTypeBuilder builder) { - HasKey(t => t.Id); + builder.HasKey(t => t.Id); } } } diff --git a/Bonobo.Git.Server/Data/Mapping/RoleMap.cs b/Bonobo.Git.Server/Data/Mapping/RoleMap.cs index 29fcd069b..94a681683 100644 --- a/Bonobo.Git.Server/Data/Mapping/RoleMap.cs +++ b/Bonobo.Git.Server/Data/Mapping/RoleMap.cs @@ -1,52 +1,61 @@ -using System.ComponentModel.DataAnnotations.Schema; -using System.Data.Entity.ModelConfiguration; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace Bonobo.Git.Server.Data.Mapping { - public class RoleMap : EntityTypeConfiguration + public class RoleMap : IEntityTypeConfiguration { - public RoleMap() + private readonly ValueConverter _primaryKeyConverter; + + public RoleMap(ValueConverter primaryKeyConverter) { - SetPrimaryKey(); - SetProperties(); - SetTableAndColumnMappings(); - SetRelationships(); + _primaryKeyConverter = primaryKeyConverter; } + public void Configure(EntityTypeBuilder builder) + { + SetPrimaryKey(builder); + SetProperties(builder); + SetTableAndColumnMappings(builder); + SetRelationships(builder); + } - private void SetRelationships() + private void SetRelationships(EntityTypeBuilder builder) { - HasMany(t => t.Users) - .WithMany(t => t.Roles) - .Map(m => - { - m.ToTable("UserRole_InRole"); - m.MapLeftKey("Role_Id"); - m.MapRightKey("User_Id"); - }); + //builder.HasMany(t => t.Users) + // .WithMany(t => t.Roles) + // .Map(m => + // { + // m.ToTable("UserRole_InRole"); + // m.MapLeftKey("Role_Id"); + // m.MapRightKey("User_Id"); + // }); } - private void SetTableAndColumnMappings() + private void SetTableAndColumnMappings(EntityTypeBuilder builder) { - ToTable("Role"); - Property(t => t.Id).HasColumnName("Id"); - Property(t => t.Name).HasColumnName("Name"); - Property(t => t.Description).HasColumnName("Description"); + builder.ToTable("Role"); + builder.Property(t => t.Id).HasColumnName("Id").HasConversion(_primaryKeyConverter); + builder.Property(t => t.Name).HasColumnName("Name"); + builder.Property(t => t.Description).HasColumnName("Description"); } - private void SetProperties() + private void SetProperties(EntityTypeBuilder builder) { - Property(t => t.Name) + builder.Property(t => t.Name) .IsRequired() .HasMaxLength(255); - Property(t => t.Description) + builder.Property(t => t.Description) .HasMaxLength(255); } - private void SetPrimaryKey() + private void SetPrimaryKey(EntityTypeBuilder builder) { - HasKey(t => t.Id); + builder.HasKey(t => t.Id); } + + } } diff --git a/Bonobo.Git.Server/Data/Mapping/TeamMap.cs b/Bonobo.Git.Server/Data/Mapping/TeamMap.cs index cefdb18ed..2682541e4 100644 --- a/Bonobo.Git.Server/Data/Mapping/TeamMap.cs +++ b/Bonobo.Git.Server/Data/Mapping/TeamMap.cs @@ -1,52 +1,59 @@ -using System.ComponentModel.DataAnnotations.Schema; -using System.Data.Entity.ModelConfiguration; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace Bonobo.Git.Server.Data.Mapping { - public class TeamMap : EntityTypeConfiguration + public class TeamMap : IEntityTypeConfiguration { - public TeamMap() + private readonly ValueConverter _primaryKeyConverter; + + public TeamMap(ValueConverter primaryKeyConverter) { - SetPrimaryKey(); - SetProperties(); - SetTableAndColumnMappings(); - SetRelationships(); + _primaryKeyConverter = primaryKeyConverter; } + public void Configure(EntityTypeBuilder builder) + { + SetPrimaryKey(builder); + SetProperties(builder); + SetTableAndColumnMappings(builder); + SetRelationships(builder); + } - private void SetRelationships() + private void SetRelationships(EntityTypeBuilder builder) { - HasMany(t => t.Users) - .WithMany(t => t.Teams) - .Map(m => - { - m.ToTable("UserTeam_Member"); - m.MapLeftKey("Team_Id"); - m.MapRightKey("User_Id"); - }); + //builder.HasMany(t => t.Users) + // .WithMany(t => t.Teams) + // .Map(m => + // { + // m.ToTable("UserTeam_Member"); + // m.MapLeftKey("Team_Id"); + // m.MapRightKey("User_Id"); + // }); } - private void SetTableAndColumnMappings() + private void SetTableAndColumnMappings(EntityTypeBuilder builder) { - ToTable("Team"); - Property(t => t.Id).HasColumnName("Id"); - Property(t => t.Name).HasColumnName("Name"); - Property(t => t.Description).HasColumnName("Description"); + builder.ToTable("Team"); + builder.Property(t => t.Id).HasColumnName("Id").HasConversion(_primaryKeyConverter); + builder.Property(t => t.Name).HasColumnName("Name"); + builder.Property(t => t.Description).HasColumnName("Description"); } - private void SetProperties() + private void SetProperties(EntityTypeBuilder builder) { - Property(t => t.Name) + builder.Property(t => t.Name) .IsRequired() .HasMaxLength(255); - Property(t => t.Description) + builder.Property(t => t.Description) .HasMaxLength(255); } - private void SetPrimaryKey() + private void SetPrimaryKey(EntityTypeBuilder builder) { - HasKey(t => t.Id); + builder.HasKey(t => t.Id); } } } diff --git a/Bonobo.Git.Server/Data/Mapping/UserMap.cs b/Bonobo.Git.Server/Data/Mapping/UserMap.cs index dcd1addb8..9cbdfc28f 100644 --- a/Bonobo.Git.Server/Data/Mapping/UserMap.cs +++ b/Bonobo.Git.Server/Data/Mapping/UserMap.cs @@ -1,56 +1,63 @@ -using System.ComponentModel.DataAnnotations.Schema; -using System.Data.Entity.ModelConfiguration; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace Bonobo.Git.Server.Data.Mapping { - public class UserMap : EntityTypeConfiguration + public class UserMap : IEntityTypeConfiguration { - public UserMap() + private readonly ValueConverter _primaryKeyConverter; + + public UserMap(ValueConverter primaryKeyConverter) { - SetPrimaryKey(); - SetProperties(); - SetTableAndColumnMappings(); + _primaryKeyConverter = primaryKeyConverter; } + public void Configure(EntityTypeBuilder builder) + { + SetPrimaryKey(builder); + SetProperties(builder); + SetTableAndColumnMappings(builder); + } - private void SetTableAndColumnMappings() + private void SetTableAndColumnMappings(EntityTypeBuilder builder) { - ToTable("User"); - Property(t => t.Id).HasColumnName("Id"); - Property(t => t.GivenName).HasColumnName("Name"); - Property(t => t.Surname).HasColumnName("Surname"); - Property(t => t.Username).HasColumnName("Username"); - Property(t => t.Password).HasColumnName("Password"); - Property(t => t.PasswordSalt).HasColumnName("PasswordSalt"); - Property(t => t.Email).HasColumnName("Email"); + builder.ToTable("User"); + builder.Property(t => t.Id).HasColumnName("Id").HasConversion(_primaryKeyConverter); + builder.Property(t => t.GivenName).HasColumnName("Name"); + builder.Property(t => t.Surname).HasColumnName("Surname"); + builder.Property(t => t.Username).HasColumnName("Username"); + builder.Property(t => t.Password).HasColumnName("Password"); + builder.Property(t => t.PasswordSalt).HasColumnName("PasswordSalt"); + builder.Property(t => t.Email).HasColumnName("Email"); } - private void SetProperties() + private void SetProperties(EntityTypeBuilder builder) { - Property(t => t.GivenName) + builder.Property(t => t.GivenName) .IsRequired() .HasMaxLength(255); - Property(t => t.Surname) + builder.Property(t => t.Surname) .IsRequired() .HasMaxLength(255); - Property(t => t.Username) + builder.Property(t => t.Username) .IsRequired() .HasMaxLength(255); - Property(t => t.Password) + builder.Property(t => t.Password) .IsRequired() .HasMaxLength(255); - Property(t => t.Email) + builder.Property(t => t.Email) .IsRequired() .HasMaxLength(255); } - private void SetPrimaryKey() + private void SetPrimaryKey(EntityTypeBuilder builder) { - HasKey(t => t.Id); + builder.HasKey(t => t.Id); } } } diff --git a/Bonobo.Git.Server/Data/Repository.cs b/Bonobo.Git.Server/Data/Repository.cs index 49b958c80..efb16fe86 100644 --- a/Bonobo.Git.Server/Data/Repository.cs +++ b/Bonobo.Git.Server/Data/Repository.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; +using Bonobo.Git.Server.Data.ManyToMany; namespace Bonobo.Git.Server.Data { @@ -18,9 +19,9 @@ public enum RepositoryPushMode public partial class Repository { - private ICollection _teams; - private ICollection _administrators; - private ICollection _users; + private ICollection _teams; + private ICollection _administrators; + private ICollection _users; public Guid Id { get; set; } public string Name { get; set; } @@ -30,11 +31,11 @@ public partial class Repository public byte[] Logo { get; set; } public RepositoryPushMode AllowAnonymousPush { get; set; } - public virtual ICollection Teams + public virtual ICollection Teams { get { - return _teams ?? (_teams = new List()); + return _teams ?? (_teams = new List()); } set { @@ -42,11 +43,11 @@ public virtual ICollection Teams } } - public virtual ICollection Administrators + public virtual ICollection Administrators { get { - return _administrators ?? (_administrators = new List()); + return _administrators ?? (_administrators = new List()); } set { @@ -54,11 +55,11 @@ public virtual ICollection Administrators } } - public virtual ICollection Users + public virtual ICollection Users { get { - return _users ?? (_users = new List()); + return _users ?? (_users = new List()); } set { diff --git a/Bonobo.Git.Server/Data/RepositoryRepositoryBase.cs b/Bonobo.Git.Server/Data/RepositoryRepositoryBase.cs index 5cf80d203..24ddc9dad 100644 --- a/Bonobo.Git.Server/Data/RepositoryRepositoryBase.cs +++ b/Bonobo.Git.Server/Data/RepositoryRepositoryBase.cs @@ -27,11 +27,17 @@ public virtual IList GetAdministratedRepositories(Guid userId) return GetAllRepositories().Where(x => x.Administrators.Any(y => y.Id == userId)).ToList(); } + public RepositoryModel GetRepository(string Name) + { + return GetRepository(Name, StringComparison.OrdinalIgnoreCase); + } + public abstract RepositoryModel GetRepository(Guid id); - public abstract RepositoryModel GetRepository(string Name, StringComparison compType = StringComparison.OrdinalIgnoreCase); + public abstract RepositoryModel GetRepository(string Name, StringComparison compType); public abstract bool Create(RepositoryModel repository); public abstract void Update(RepositoryModel repository); public abstract void Delete(Guid id); + public abstract bool NameIsUnique(string newName, Guid ignoreRepoId); public abstract IList GetAllRepositories(); } } \ No newline at end of file diff --git a/Bonobo.Git.Server/Data/Role.cs b/Bonobo.Git.Server/Data/Role.cs index e584315e1..80474c968 100644 --- a/Bonobo.Git.Server/Data/Role.cs +++ b/Bonobo.Git.Server/Data/Role.cs @@ -1,21 +1,22 @@ using System; using System.Collections.Generic; +using Bonobo.Git.Server.Data.ManyToMany; namespace Bonobo.Git.Server.Data { public partial class Role { - private ICollection _users; + private ICollection _users; public Guid Id { get; set; } public string Name { get; set; } public string Description { get; set; } - public virtual ICollection Users + public virtual ICollection Users { get { - return _users ?? (_users = new List()); + return _users ?? (_users = new List()); } set { diff --git a/Bonobo.Git.Server/Data/Team.cs b/Bonobo.Git.Server/Data/Team.cs index 5c0bb3db8..11a701118 100644 --- a/Bonobo.Git.Server/Data/Team.cs +++ b/Bonobo.Git.Server/Data/Team.cs @@ -1,23 +1,24 @@ using System; using System.Collections.Generic; +using Bonobo.Git.Server.Data.ManyToMany; namespace Bonobo.Git.Server.Data { public partial class Team { - private ICollection _repositories; - private ICollection _users; + private ICollection _repositories; + private ICollection _users; public Guid Id { get; set; } public string Name { get; set; } public string Description { get; set; } - public virtual ICollection Repositories + public virtual ICollection Repositories { get { - return _repositories ?? (_repositories = new List()); + return _repositories ?? (_repositories = new List()); } set { @@ -25,11 +26,11 @@ public virtual ICollection Repositories } } - public virtual ICollection Users + public virtual ICollection Users { get { - return _users ?? (_users = new List()); + return _users ?? (_users = new List()); } set { diff --git a/Bonobo.Git.Server/Data/Update/ADBackend/UpdateADBackend.cs b/Bonobo.Git.Server/Data/Update/ADBackend/UpdateADBackend.cs index c289c121f..eb443d41c 100644 --- a/Bonobo.Git.Server/Data/Update/ADBackend/UpdateADBackend.cs +++ b/Bonobo.Git.Server/Data/Update/ADBackend/UpdateADBackend.cs @@ -7,8 +7,7 @@ using System; using System.Threading; using System.Linq; -using Bonobo.Git.Server.Data; -using Microsoft.VisualBasic.FileIO; +using Microsoft.AspNetCore.Hosting; using Newtonsoft.Json; using Serilog; @@ -17,12 +16,13 @@ namespace Bonobo.Git.Server.Data.Update.ADBackendUpdate public class Pre600UpdateTo600 { // Before 6.0.0 the mapping was done via the name property. After that the Guid is used. - public static void UpdateADBackend() + public static void UpdateADBackend(IHostingEnvironment hostingEnvironment) { // Make a copy of the current backendfolder if it exists, so we can use the modern models for saving // it all to the correct location directly - var backendDirectory = PathEncoder.GetRootPath(ActiveDirectorySettings.BackendPath); - var backupDirectory = PathEncoder.GetRootPath(ActiveDirectorySettings.BackendPath + "_pre6.0.0_" + DateTime.UtcNow.ToString("yyyyMMdd_HHmmss")); + var backendDirectory = PathEncoder.GetRootPath(hostingEnvironment, ActiveDirectorySettings.BackendPath); + var backupDirectory = PathEncoder.GetRootPath(hostingEnvironment, + ActiveDirectorySettings.BackendPath + "_pre6.0.0_" + DateTime.UtcNow.ToString("yyyyMMdd_HHmmss")); if (Directory.Exists(backendDirectory) && BackEndNeedsUpgrade(backendDirectory)) { MakeBackupOfBackendDirectory(backendDirectory, backupDirectory); @@ -98,7 +98,7 @@ private static bool BackendSubDirectoryNeedsUpdating(string backendDirectory, private static void MakeBackupOfBackendDirectory(string backendDirectory, string backupDirectory) { - FileSystem.CopyDirectory(backendDirectory, backupDirectory); + CopyDirectory(backendDirectory, backupDirectory); int attemptsRemaining = 5; while (attemptsRemaining-- > 0) { @@ -122,6 +122,40 @@ private static void MakeBackupOfBackendDirectory(string backendDirectory, string } } + private static void CopyDirectory(string sourceDirName, string destDirName) + { + // Get the subdirectories for the specified directory. + DirectoryInfo dir = new DirectoryInfo(sourceDirName); + + if (!dir.Exists) + { + throw new DirectoryNotFoundException( + "Source directory does not exist or could not be found: " + + sourceDirName); + } + + DirectoryInfo[] dirs = dir.GetDirectories(); + // If the destination directory doesn't exist, create it. + if (!Directory.Exists(destDirName)) + { + Directory.CreateDirectory(destDirName); + } + + // Get the files in the directory and copy them to the new location. + FileInfo[] files = dir.GetFiles(); + foreach (FileInfo file in files) + { + string temppath = Path.Combine(destDirName, file.Name); + file.CopyTo(temppath, false); + } + + foreach (DirectoryInfo subdir in dirs) + { + string temppath = Path.Combine(destDirName, subdir.Name); + CopyDirectory(subdir.FullName, temppath); + } + } + private static void UpdateRepos(string dir, Dictionary users, Dictionary teams) { var repos = Pre600Functions.LoadContent(dir); diff --git a/Bonobo.Git.Server/Data/Update/AutomaticUpdater.cs b/Bonobo.Git.Server/Data/Update/AutomaticUpdater.cs index 69de89876..7a19c0311 100644 --- a/Bonobo.Git.Server/Data/Update/AutomaticUpdater.cs +++ b/Bonobo.Git.Server/Data/Update/AutomaticUpdater.cs @@ -1,57 +1,48 @@ using Bonobo.Git.Server.Configuration; using Bonobo.Git.Server.Data.Update.ADBackendUpdate; using System; -using System.Data.Entity.Infrastructure; -using System.Linq; +using Bonobo.Git.Server.Extensions; +using Bonobo.Git.Server.Security; +using Microsoft.AspNetCore.Hosting; +using Microsoft.EntityFrameworkCore; using Serilog; namespace Bonobo.Git.Server.Data.Update { public class AutomaticUpdater { - public void Run() + public void Run(BonoboGitServerContext context, IAuthenticationProvider authenticationProvider, IHostingEnvironment hostingEnvironment) { if (AuthenticationSettings.MembershipService.ToLowerInvariant() == "activedirectory") { - Pre600UpdateTo600.UpdateADBackend(); + Pre600UpdateTo600.UpdateADBackend(hostingEnvironment); } else { - UpdateDatabase(); + RunWithContext(context, authenticationProvider); } } - public void RunWithContext(BonoboGitServerContext context) + public void RunWithContext(BonoboGitServerContext context, IAuthenticationProvider authenticationProvider) { - DoUpdate(context); + DoUpdate(context, authenticationProvider); } - private void UpdateDatabase() + private void DoUpdate(BonoboGitServerContext ctx, IAuthenticationProvider authenticationProvider) { - using (var ctx = new BonoboGitServerContext()) - { - DoUpdate(ctx); - } - } - - private void DoUpdate(BonoboGitServerContext ctx) - { - IObjectContextAdapter ctxAdapter = ctx; - var connectiontype = ctx.Database.Connection.GetType().Name; - - foreach (var item in UpdateScriptRepository.GetScriptsBySqlProviderName(connectiontype)) + foreach (var item in UpdateScriptRepository.GetScriptsBySqlProviderName(ctx.Database.ProviderName, authenticationProvider)) { if (!string.IsNullOrEmpty(item.Precondition)) { try { - var preConditionResult = ctxAdapter.ObjectContext.ExecuteStoreQuery(item.Precondition).Single(); + var preConditionResult = Convert.ToInt32(ctx.Database.ExecuteScalar(item.Precondition)); if (preConditionResult == 0) { continue; } } - catch (Exception) + catch (Exception e) { // consider failures in pre-conditions as an indication that // store ecommand should be executed @@ -62,7 +53,7 @@ private void DoUpdate(BonoboGitServerContext ctx) { try { - ctxAdapter.ObjectContext.ExecuteStoreCommand(item.Command); + ctx.Database.ExecuteSqlCommand(item.Command); } catch (Exception ex) { diff --git a/Bonobo.Git.Server/Data/Update/Data/NameDesc.cs b/Bonobo.Git.Server/Data/Update/Data/NameDesc.cs new file mode 100644 index 000000000..2e7e4aea1 --- /dev/null +++ b/Bonobo.Git.Server/Data/Update/Data/NameDesc.cs @@ -0,0 +1,8 @@ +namespace Bonobo.Git.Server.Data.Update.Data +{ + public class NameDesc + { + public string Name { get; set; } + public string Description { get; set; } + } +} diff --git a/Bonobo.Git.Server/Data/Update/Data/OldRepo.cs b/Bonobo.Git.Server/Data/Update/Data/OldRepo.cs new file mode 100644 index 000000000..aafb5c3e6 --- /dev/null +++ b/Bonobo.Git.Server/Data/Update/Data/OldRepo.cs @@ -0,0 +1,12 @@ +namespace Bonobo.Git.Server.Data.Update.Data +{ + public class OldRepo + { + public string Name { get; set; } + public string Description { get; set; } + public bool Anonymous { get; set; } + public bool AuditPushUser { get; set; } + public string Group { get; set; } + public byte[] Logo { get; set; } + } +} diff --git a/Bonobo.Git.Server/Data/Update/Data/OldUser.cs b/Bonobo.Git.Server/Data/Update/Data/OldUser.cs new file mode 100644 index 000000000..a42df6e6b --- /dev/null +++ b/Bonobo.Git.Server/Data/Update/Data/OldUser.cs @@ -0,0 +1,11 @@ +namespace Bonobo.Git.Server.Data.Update.Data +{ + public class OldUser + { + public string Name { get; set; } + public string Surname { get; set; } + public string Username { get; set; } + public string Password { get; set; } + public string Email { get; set; } + } +} diff --git a/Bonobo.Git.Server/Data/Update/RepositorySynchronizer.cs b/Bonobo.Git.Server/Data/Update/RepositorySynchronizer.cs index 08fec60f4..ac890825e 100644 --- a/Bonobo.Git.Server/Data/Update/RepositorySynchronizer.cs +++ b/Bonobo.Git.Server/Data/Update/RepositorySynchronizer.cs @@ -1,18 +1,21 @@ using Bonobo.Git.Server.Configuration; using Bonobo.Git.Server.Models; -using LibGit2Sharp; using System; using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Text; -using System.Web.Mvc; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; namespace Bonobo.Git.Server.Data.Update { public class RepositorySynchronizer { - IRepositoryRepository _repositoryRepository = DependencyResolver.Current.GetService(); + private readonly IRepositoryRepository _repositoryRepository; + + public RepositorySynchronizer(IRepositoryRepository repositoryRepository) + { + _repositoryRepository = repositoryRepository; + } public virtual void Run() { diff --git a/Bonobo.Git.Server/Data/Update/SqlServer/AddGuidColumn.cs b/Bonobo.Git.Server/Data/Update/SqlServer/AddGuidColumn.cs index 36608703a..556ccebf8 100644 --- a/Bonobo.Git.Server/Data/Update/SqlServer/AddGuidColumn.cs +++ b/Bonobo.Git.Server/Data/Update/SqlServer/AddGuidColumn.cs @@ -1,12 +1,13 @@ -using Bonobo.Git.Server.Security; +using System; using System.DirectoryServices.AccountManagement; -using System.Web.Mvc; -using System.Collections.Generic; -using System; -using System.Data.Entity; using System.Data.SqlClient; -using System.Linq; +using Bonobo.Git.Server.Data.Update.Data; +using Bonobo.Git.Server.Extensions; +using Microsoft.EntityFrameworkCore.Infrastructure; + using Bonobo.Git.Server.Helpers; +using Bonobo.Git.Server.Security; +using Microsoft.EntityFrameworkCore; namespace Bonobo.Git.Server.Data.Update.SqlServer { @@ -14,18 +15,18 @@ public class AddGuidColumn : IUpdateScript { private readonly IAuthenticationProvider AuthProvider; - private Database _db; + private DatabaseFacade _db; - public AddGuidColumn() + public AddGuidColumn(IAuthenticationProvider authProvider) { - AuthProvider = DependencyResolver.Current.GetService(); + AuthProvider = authProvider; } public void CodeAction(BonoboGitServerContext context) { _db = context.Database; - if (UpgradeHasAlreadyBeenRun()) + if (UpgradeHasAlreadyBeenRun(context)) { return; } @@ -36,7 +37,7 @@ public void CodeAction(BonoboGitServerContext context) { RenameTables(); CreateTables(); - CopyData(); + CopyData(context); AddRelations(); DropRenamedTables(); trans.Commit(); @@ -49,17 +50,17 @@ public void CodeAction(BonoboGitServerContext context) } } - private bool UpgradeHasAlreadyBeenRun() + private bool UpgradeHasAlreadyBeenRun(BonoboGitServerContext context) { try { - var result = _db.SqlQuery(@" + var result = Convert.ToInt32(context.Database.ExecuteScalar(@" IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'User' AND COLUMN_NAME = 'Id') SELECT 1 ELSE SELECT 0 - "); - return result.SingleAsync().GetAwaiter().GetResult() == 1; + ")); + return result == 1; } catch (SqlException) { @@ -228,42 +229,17 @@ REFERENCES Repository (Id) "); } - class OldUser - { - public string Name { get; set; } - public string Surname { get; set; } - public string Username { get; set; } - public string Password { get; set; } - public string Email { get; set; } - } - - class NameDesc - { - public string Name { get; set; } - public string Description { get; set; } - } - - class OldRepo - { - public string Name { get; set; } - public string Description { get; set; } - public bool Anonymous { get; set; } - public bool AuditPushUser { get; set; } - public string Group { get; set; } - public byte[] Logo { get; set; } - } - - private void CopyData() + private void CopyData(BonoboGitServerContext context) { - CopyUsers(); - CopyTeams(); - CopyRoles(); - CopyRepositories(); + CopyUsers(context); + CopyTeams(context); + CopyRoles(context); + CopyRepositories(context); } - private void CopyUsers() + private void CopyUsers(BonoboGitServerContext context) { - var users = _db.SqlQuery("Select * from oUser;").ToList(); + var users = context.Query().FromSql("Select * from oUser;"); foreach (var entry in users) { Guid guid = Guid.NewGuid(); @@ -308,9 +284,9 @@ private void CopyUsers() } } - private void CopyTeams() + private void CopyTeams(BonoboGitServerContext context) { - var teams = _db.SqlQuery("Select * from oTeam").ToList(); + var teams = context.Query().FromSql("Select * from oTeam"); foreach (var team in teams) { _db.ExecuteSqlCommand("INSERT INTO Team VALUES ({0}, {1}, {2})", @@ -318,9 +294,9 @@ private void CopyTeams() } } - private void CopyRoles() + private void CopyRoles(BonoboGitServerContext context) { - var roles = _db.SqlQuery("Select * from oRole").ToList(); + var roles = context.Query().FromSql("Select * from oRole"); foreach (var role in roles) { _db.ExecuteSqlCommand("INSERT INTO Role VALUES ({0}, {1}, {2})", @@ -330,9 +306,9 @@ private void CopyRoles() } } - private void CopyRepositories() + private void CopyRepositories(BonoboGitServerContext context) { - var repos = _db.SqlQuery("SELECT * FROM oRepo").ToList(); + var repos = context.Query().FromSql("SELECT * FROM oRepo"); foreach (var repo in repos) { _db.ExecuteSqlCommand("INSERT INTO Repository VALUES ({0}, {1}, {2}, {3}, {4}, {5}, {6})", diff --git a/Bonobo.Git.Server/Data/Update/Sqlite/AddGuidColumn.cs b/Bonobo.Git.Server/Data/Update/Sqlite/AddGuidColumn.cs index 76f8b4c0e..07e75bf91 100644 --- a/Bonobo.Git.Server/Data/Update/Sqlite/AddGuidColumn.cs +++ b/Bonobo.Git.Server/Data/Update/Sqlite/AddGuidColumn.cs @@ -1,22 +1,21 @@ -using Bonobo.Git.Server.Security; -using System.DirectoryServices.AccountManagement; -using System.Web.Mvc; -using System.Collections.Generic; -using System; -using System.Data.Entity; -using System.Data.SQLite; +using System; +using System.Data.Common; +using Bonobo.Git.Server.Data.Update.Data; +using Bonobo.Git.Server.Security; using Bonobo.Git.Server.Helpers; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; namespace Bonobo.Git.Server.Data.Update.Sqlite { public class AddGuidColumn : IUpdateScript { private readonly IAuthenticationProvider AuthProvider; - private Database _db; + private DatabaseFacade _db; - public AddGuidColumn() + public AddGuidColumn(IAuthenticationProvider authProvider) { - AuthProvider = DependencyResolver.Current.GetService(); + AuthProvider = authProvider; } public void CodeAction(BonoboGitServerContext context) @@ -34,7 +33,7 @@ public void CodeAction(BonoboGitServerContext context) { RenameTables(); CreateTables(); - CopyData(); + CopyData(context); AddRelations(); DropRenamedTables(); trans.Commit(); @@ -55,7 +54,7 @@ private bool UpgradeHasAlreadyBeenRun() _db.ExecuteSqlCommand("SELECT Count([Id]) = -1 FROM User"); return true; } - catch (SQLiteException) + catch (DbException) { // the column does not exist! return false; @@ -223,42 +222,17 @@ REFERENCES Repository (Id) "); } - class OldUser + private void CopyData(BonoboGitServerContext context) { - public string Name { get; set; } - public string Surname { get; set; } - public string Username { get; set; } - public string Password { get; set; } - public string Email { get; set; } + CopyUsers(context); + CopyTeams(context); + CopyRoles(context); + CopyRepositories(context); } - class NameDesc + private void CopyUsers(BonoboGitServerContext context) { - public string Name { get; set; } - public string Description { get; set; } - } - - class OldRepo - { - public string Name { get; set; } - public string Description { get; set; } - public bool Anonymous { get; set; } - public bool AuditPushUser { get; set; } - public string Group { get; set; } - public byte[] Logo { get; set; } - } - - private void CopyData() - { - CopyUsers(); - CopyTeams(); - CopyRoles(); - CopyRepositories(); - } - - private void CopyUsers() - { - var users = _db.SqlQuery("Select * from oUser;"); + var users = context.Query().FromSql("Select * from oUser;"); foreach (var entry in users) { Guid guid = Guid.NewGuid(); @@ -303,9 +277,9 @@ private void CopyUsers() } } - private void CopyTeams() + private void CopyTeams(BonoboGitServerContext context) { - var teams = _db.SqlQuery("Select * from oTeam"); + var teams = context.Query().FromSql("Select * from oTeam"); foreach (var team in teams) { _db.ExecuteSqlCommand("INSERT INTO Team VALUES ({0}, {1}, {2})", @@ -313,9 +287,9 @@ private void CopyTeams() } } - private void CopyRoles() + private void CopyRoles(BonoboGitServerContext context) { - var roles = _db.SqlQuery("Select * from oRole"); + var roles = context.Query().FromSql("Select * from oRole"); foreach (var role in roles) { _db.ExecuteSqlCommand("INSERT INTO Role VALUES ({0}, {1}, {2})", @@ -325,9 +299,9 @@ private void CopyRoles() } } - private void CopyRepositories() + private void CopyRepositories(BonoboGitServerContext context) { - var repos = _db.SqlQuery("SELECT * FROM oRepo"); + var repos = context.Query().FromSql("SELECT * FROM oRepo"); foreach (var repo in repos) { _db.ExecuteSqlCommand("INSERT INTO Repository VALUES ({0}, {1}, {2}, {3}, {4}, {5}, {6})", diff --git a/Bonobo.Git.Server/Data/Update/UpdateScriptRepository.cs b/Bonobo.Git.Server/Data/Update/UpdateScriptRepository.cs index 49344947b..0eccae5be 100644 --- a/Bonobo.Git.Server/Data/Update/UpdateScriptRepository.cs +++ b/Bonobo.Git.Server/Data/Update/UpdateScriptRepository.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Bonobo.Git.Server.Security; namespace Bonobo.Git.Server.Data.Update { @@ -8,11 +9,11 @@ public static class UpdateScriptRepository /// /// Creates the list of scripts that should be executed on app start. Ordering matters! /// - public static IEnumerable GetScriptsBySqlProviderName(string sqlProvider) + public static IEnumerable GetScriptsBySqlProviderName(string sqlProvider, IAuthenticationProvider authenticationProvider) { switch (sqlProvider) { - case "SQLiteConnection": + case "Microsoft.EntityFrameworkCore.Sqlite": return new List { new Sqlite.InitialCreateScript(), @@ -20,12 +21,12 @@ public static IEnumerable GetScriptsBySqlProviderName(string sqlP new Sqlite.AddAuditPushUser(), new Sqlite.AddGroup(), new Sqlite.AddRepositoryLogo(), - new Sqlite.AddGuidColumn(), + new Sqlite.AddGuidColumn(authenticationProvider), new Sqlite.AddRepoPushColumn(), new Sqlite.AddRepoLinksColumn(), new Sqlite.InsertDefaultData() }; - case "SqlConnection": + case "Microsoft.EntityFrameworkCore.SqlServer": return new List { new SqlServer.InitialCreateScript(), @@ -33,7 +34,7 @@ public static IEnumerable GetScriptsBySqlProviderName(string sqlP new SqlServer.AddAuditPushUser(), new SqlServer.AddGroup(), new SqlServer.AddRepositoryLogo(), - new SqlServer.AddGuidColumn(), + new SqlServer.AddGuidColumn(authenticationProvider), new SqlServer.AddRepoPushColumn(), new SqlServer.AddRepoLinksColumn(), new SqlServer.InsertDefaultData() diff --git a/Bonobo.Git.Server/Data/User.cs b/Bonobo.Git.Server/Data/User.cs index 2eabb984b..fc3eac110 100644 --- a/Bonobo.Git.Server/Data/User.cs +++ b/Bonobo.Git.Server/Data/User.cs @@ -1,15 +1,16 @@ using System; using System.Collections.Generic; +using Bonobo.Git.Server.Data.ManyToMany; using Bonobo.Git.Server.Models; namespace Bonobo.Git.Server.Data { public partial class User { - private ICollection _administratedRepositories; - private ICollection _repositories; - private ICollection _roles; - private ICollection _teams; + private ICollection _administratedRepositories; + private ICollection _repositories; + private ICollection _roles; + private ICollection _teams; public Guid Id { get; set; } public string GivenName { get; set; } @@ -19,11 +20,11 @@ public partial class User public string PasswordSalt { get; set; } public string Email { get; set; } - public virtual ICollection AdministratedRepositories + public virtual ICollection AdministratedRepositories { get { - return _administratedRepositories ?? (_administratedRepositories = new List()); + return _administratedRepositories ?? (_administratedRepositories = new List()); } set { @@ -31,11 +32,11 @@ public virtual ICollection AdministratedRepositories } } - public virtual ICollection Repositories + public virtual ICollection Repositories { get { - return _repositories ?? (_repositories = new List()); + return _repositories ?? (_repositories = new List()); } set { @@ -43,11 +44,11 @@ public virtual ICollection Repositories } } - public virtual ICollection Roles + public virtual ICollection Roles { get { - return _roles ?? (_roles = new List()); + return _roles ?? (_roles = new List()); } set { @@ -55,11 +56,11 @@ public virtual ICollection Roles } } - public virtual ICollection Teams + public virtual ICollection Teams { get { - return _teams ?? (_teams = new List()); + return _teams ?? (_teams = new List()); } set { diff --git a/Bonobo.Git.Server/Extensions/DatabaseFacadeExtensions.cs b/Bonobo.Git.Server/Extensions/DatabaseFacadeExtensions.cs new file mode 100644 index 000000000..5de9a72f4 --- /dev/null +++ b/Bonobo.Git.Server/Extensions/DatabaseFacadeExtensions.cs @@ -0,0 +1,21 @@ +using System.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; + +namespace Bonobo.Git.Server.Extensions +{ + public static class DatabaseFacadeExtensions + { + public static object ExecuteScalar(this DatabaseFacade facade, string command) + { + using (var conn = facade.GetDbConnection().CreateCommand()) + { + conn.CommandText = command; + conn.CommandType = CommandType.Text; + + facade.OpenConnection(); + return conn.ExecuteScalar(); + } + } + } +} diff --git a/Bonobo.Git.Server/Extensions/HttpRequestExtensions.cs b/Bonobo.Git.Server/Extensions/HttpRequestExtensions.cs new file mode 100644 index 000000000..745984740 --- /dev/null +++ b/Bonobo.Git.Server/Extensions/HttpRequestExtensions.cs @@ -0,0 +1,26 @@ +using System; +using Microsoft.AspNetCore.Http; + +namespace Bonobo.Git.Server.Extensions +{ + public static class HttpRequestExtensions + { + /// + /// Determines whether the specified HTTP request is an AJAX request. + /// + /// + /// + /// true if the specified HTTP request is an AJAX request; otherwise, false. + /// + /// The HTTP request.The parameter is null (Nothing in Visual Basic). + public static bool IsAjaxRequest(this HttpRequest request) + { + if (request == null) + throw new ArgumentNullException(nameof(request)); + + if (request.Headers != null) + return request.Headers["X-Requested-With"] == "XMLHttpRequest"; + return false; + } + } +} diff --git a/Bonobo.Git.Server/Extensions/IHostingEnvironmentExtensions.cs b/Bonobo.Git.Server/Extensions/IHostingEnvironmentExtensions.cs new file mode 100644 index 000000000..98410d606 --- /dev/null +++ b/Bonobo.Git.Server/Extensions/IHostingEnvironmentExtensions.cs @@ -0,0 +1,29 @@ +using System.IO; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Hosting.Internal; + +namespace Bonobo.Git.Server.Extensions +{ + public static class HostingEnvironmentExtensions + { + public static string MapPath(this IHostingEnvironment @this, string path) + { + if (path[0] == '~') + { + return Path.Combine(@this.ContentRootPath, path.Substring(1)); + } + + if (path[0] == '/') + { + return Path.Combine(@this.WebRootPath, path.Substring(1)); + } + + return Path.GetFullPath(path); + } + + public static string MapPath(this HostingEnvironment @this, string path) + { + return ((IHostingEnvironment) @this).MapPath(path); + } + } +} diff --git a/Bonobo.Git.Server/Extensions/IQueryableExtensons.cs b/Bonobo.Git.Server/Extensions/IQueryableExtensons.cs new file mode 100644 index 000000000..98b2e600f --- /dev/null +++ b/Bonobo.Git.Server/Extensions/IQueryableExtensons.cs @@ -0,0 +1,36 @@ +using System.Linq; +using System.Reflection; +using Microsoft.EntityFrameworkCore.Query; +using Microsoft.EntityFrameworkCore.Query.Internal; +using Microsoft.EntityFrameworkCore.Storage; + +namespace Bonobo.Git.Server.Extensions +{ + public static class IQueryableExtensions + { + private static readonly TypeInfo QueryCompilerTypeInfo = typeof(QueryCompiler).GetTypeInfo(); + + private static readonly FieldInfo QueryCompilerField = typeof(EntityQueryProvider).GetTypeInfo().DeclaredFields.First(x => x.Name == "_queryCompiler"); + + private static readonly FieldInfo QueryModelGeneratorField = QueryCompilerTypeInfo.DeclaredFields.First(x => x.Name == "_queryModelGenerator"); + + private static readonly FieldInfo DataBaseField = QueryCompilerTypeInfo.DeclaredFields.Single(x => x.Name == "_database"); + + private static readonly PropertyInfo DatabaseDependenciesField = typeof(Database).GetTypeInfo().DeclaredProperties.Single(x => x.Name == "Dependencies"); + + public static string ToSql(this IQueryable query) where TEntity : class + { + var queryCompiler = (QueryCompiler)QueryCompilerField.GetValue(query.Provider); + var modelGenerator = (QueryModelGenerator)QueryModelGeneratorField.GetValue(queryCompiler); + var queryModel = modelGenerator.ParseQuery(query.Expression); + var database = (IDatabase)DataBaseField.GetValue(queryCompiler); + var databaseDependencies = (DatabaseDependencies)DatabaseDependenciesField.GetValue(database); + var queryCompilationContext = databaseDependencies.QueryCompilationContextFactory.Create(false); + var modelVisitor = (RelationalQueryModelVisitor)queryCompilationContext.CreateQueryModelVisitor(); + modelVisitor.CreateQueryExecutor(queryModel); + var sql = modelVisitor.Queries.First().ToString(); + + return sql; + } + } +} diff --git a/Bonobo.Git.Server/Extensions/TagBuilderExtensions.cs b/Bonobo.Git.Server/Extensions/TagBuilderExtensions.cs new file mode 100644 index 000000000..11c0a1216 --- /dev/null +++ b/Bonobo.Git.Server/Extensions/TagBuilderExtensions.cs @@ -0,0 +1,17 @@ +using System.IO; +using System.Text.Encodings.Web; +using Microsoft.AspNetCore.Mvc.Rendering; + +namespace Bonobo.Git.Server.Extensions +{ + internal static class TagBuilderExtensions + { + public static string ToString(this TagBuilder @this, TagRenderMode renderMode) + { + @this.TagRenderMode = renderMode; + var strWriter = new StringWriter(); + @this.WriteTo(strWriter, HtmlEncoder.Default); + return strWriter.ToString(); + } + } +} diff --git a/Bonobo.Git.Server/FileActionResult.cs b/Bonobo.Git.Server/FileActionResult.cs index d4e8fc909..2e28ecbc8 100644 --- a/Bonobo.Git.Server/FileActionResult.cs +++ b/Bonobo.Git.Server/FileActionResult.cs @@ -1,8 +1,6 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.Mvc; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; namespace Bonobo.Git.Server { @@ -18,14 +16,14 @@ public FileResult(string data, string name) } - public override void ExecuteResult(ControllerContext context) + public override void ExecuteResult(ActionContext context) { - if (!String.IsNullOrEmpty(_name)) + if (!string.IsNullOrEmpty(_name)) { - context.HttpContext.Response.AddHeader("content-disposition", "attachment; filename=" + _name); + context.HttpContext.Response.Headers.Add("content-disposition", "attachment; filename=" + _name); } - context.HttpContext.Response.Write(_data); + context.HttpContext.Response.WriteAsync(_data).RunSynchronously(); } } } \ No newline at end of file diff --git a/Bonobo.Git.Server/FileDisplayHandler.cs b/Bonobo.Git.Server/FileDisplayHandler.cs index b70946c5a..dace55694 100644 --- a/Bonobo.Git.Server/FileDisplayHandler.cs +++ b/Bonobo.Git.Server/FileDisplayHandler.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Web; -using System.Web.Mvc; +using Microsoft.AspNetCore.Mvc; using System.Text; using System.IO; using System.Xml; diff --git a/Bonobo.Git.Server/FilterProviders/UnityFilterAttributeFilterProvider.cs b/Bonobo.Git.Server/FilterProviders/UnityFilterAttributeFilterProvider.cs deleted file mode 100644 index 0bec6818f..000000000 --- a/Bonobo.Git.Server/FilterProviders/UnityFilterAttributeFilterProvider.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Web.Mvc; -using Microsoft.Practices.Unity; - -public class UnityFilterAttributeFilterProvider : FilterAttributeFilterProvider -{ - private readonly IUnityContainer _container; - - public UnityFilterAttributeFilterProvider(IUnityContainer container) - { - _container = container; - } - - protected override IEnumerable GetControllerAttributes(ControllerContext controllerContext, ActionDescriptor actionDescriptor) - { - var attributes = base.GetControllerAttributes(controllerContext, actionDescriptor).ToList(); - foreach (var attribute in attributes) - { - _container.BuildUp(attribute.GetType(), attribute); - } - - return attributes; - } - - protected override IEnumerable GetActionAttributes(ControllerContext controllerContext, ActionDescriptor actionDescriptor) - { - var attributes = base.GetActionAttributes(controllerContext, actionDescriptor).ToList(); - foreach (var attribute in attributes) - { - _container.BuildUp(attribute.GetType(), attribute); - } - - return attributes; - } -} \ No newline at end of file diff --git a/Bonobo.Git.Server/Git/GitCmdResult.cs b/Bonobo.Git.Server/Git/GitCmdResult.cs index 1d871be5a..bf62a6d07 100644 --- a/Bonobo.Git.Server/Git/GitCmdResult.cs +++ b/Bonobo.Git.Server/Git/GitCmdResult.cs @@ -1,9 +1,8 @@ using System; using System.IO; -using System.IO.Compression; -using System.Web; -using System.Web.Mvc; -using Bonobo.Git.Server.Configuration; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; + namespace Bonobo.Git.Server.Git { @@ -25,28 +24,28 @@ public GitCmdResult(string contentType, Action executeGitCommand, string this.executeGitCommand = executeGitCommand; } - public override void ExecuteResult(ControllerContext context) + public override void ExecuteResult(ActionContext context) { if (context == null) - throw new ArgumentNullException("context"); + throw new ArgumentNullException(nameof(context)); var response = context.HttpContext.Response; if (advertiseRefsContent != null) { - response.Write(advertiseRefsContent); + response.WriteAsync(advertiseRefsContent).RunSynchronously(); } // SetNoCache - response.AddHeader("Expires", "Fri, 01 Jan 1980 00:00:00 GMT"); - response.AddHeader("Pragma", "no-cache"); - response.AddHeader("Cache-Control", "no-cache, max-age=0, must-revalidate"); + response.Headers.Add("Expires", "Fri, 01 Jan 1980 00:00:00 GMT"); + response.Headers.Add("Pragma", "no-cache"); + response.Headers.Add("Cache-Control", "no-cache, max-age=0, must-revalidate"); - response.BufferOutput = false; - response.Charset = ""; + //response.BufferOutput = false; + //response.Charset = ""; response.ContentType = contentType; - executeGitCommand(response.OutputStream); + executeGitCommand(response.Body); } } } \ No newline at end of file diff --git a/Bonobo.Git.Server/Git/GitService/GitServiceExecutor.cs b/Bonobo.Git.Server/Git/GitService/GitServiceExecutor.cs index 746a2acf7..3e244e55b 100644 --- a/Bonobo.Git.Server/Git/GitService/GitServiceExecutor.cs +++ b/Bonobo.Git.Server/Git/GitService/GitServiceExecutor.cs @@ -1,12 +1,11 @@ using Bonobo.Git.Server.Data; using Bonobo.Git.Server.Security; using System.IO; -using System.Web; -using System.Web.Mvc; using System.Linq; using System; -using System.Collections.Generic; using System.Diagnostics; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; namespace Bonobo.Git.Server.Git.GitService { @@ -28,13 +27,15 @@ public class GitServiceExecutor : IGitService private readonly string gitHomePath; private readonly string repositoriesDirPath; private readonly IGitRepositoryLocator repoLocator; + private readonly IServiceProvider serviceProvider; - public GitServiceExecutor(GitServiceExecutorParams parameters, IGitRepositoryLocator repoLocator) + public GitServiceExecutor(GitServiceExecutorParams parameters, IGitRepositoryLocator repoLocator, IServiceProvider serviceProvider) { this.gitPath = parameters.GitPath; this.gitHomePath = parameters.GitHomePath; this.repositoriesDirPath = parameters.RepositoriesDirPath; this.repoLocator = repoLocator; + this.serviceProvider = serviceProvider; } public void ExecuteServiceByName( @@ -66,20 +67,20 @@ public void ExecuteServiceByName( SetHomePath(info); - var username = HttpContext.Current.User.Username(); + var username = serviceProvider.GetService().HttpContext.User.Username(); var teamsstr = ""; var rolesstr = ""; var displayname = ""; if(!string.IsNullOrEmpty(username)){ - ITeamRepository tr = DependencyResolver.Current.GetService(); - var userId = HttpContext.Current.User.Id(); + ITeamRepository tr = serviceProvider.GetService(); + var userId = serviceProvider.GetService().HttpContext.User.Id(); var teams = tr.GetTeams(userId); teamsstr = UserExtensions.StringlistToEscapedStringForEnvVar(teams.Select(x => x.Name)); - IRoleProvider rp = DependencyResolver.Current.GetService(); + IRoleProvider rp = serviceProvider.GetService(); rolesstr = UserExtensions.StringlistToEscapedStringForEnvVar(rp.GetRolesForUser(userId)); - IMembershipService ms = DependencyResolver.Current.GetService(); + IMembershipService ms = serviceProvider.GetService(); displayname = ms.GetUserModel(userId).DisplayName; } diff --git a/Bonobo.Git.Server/Git/GitService/ReceivePackHook/Durability/NamedArguments.cs b/Bonobo.Git.Server/Git/GitService/ReceivePackHook/Durability/NamedArguments.cs index 1ceced5e1..db45470da 100644 --- a/Bonobo.Git.Server/Git/GitService/ReceivePackHook/Durability/NamedArguments.cs +++ b/Bonobo.Git.Server/Git/GitService/ReceivePackHook/Durability/NamedArguments.cs @@ -10,15 +10,6 @@ namespace Bonobo.Git.Server.Git.GitService.ReceivePackHook.Durability /// public class NamedArguments { - public class FailedPackWaitTimeBeforeExecution - { - public FailedPackWaitTimeBeforeExecution(TimeSpan timeSpan) - { - this.Value = timeSpan; - } - public TimeSpan Value { get; private set; } - } - public class ReceivePackRecoveryDirectory { public ReceivePackRecoveryDirectory(string receivePackRecoveryDirectory) diff --git a/Bonobo.Git.Server/Git/GitService/ReceivePackHook/Durability/ReceivePackRecovery.cs b/Bonobo.Git.Server/Git/GitService/ReceivePackHook/Durability/ReceivePackRecovery.cs index 73de9d208..e9e45dfbf 100644 --- a/Bonobo.Git.Server/Git/GitService/ReceivePackHook/Durability/ReceivePackRecovery.cs +++ b/Bonobo.Git.Server/Git/GitService/ReceivePackHook/Durability/ReceivePackRecovery.cs @@ -1,11 +1,8 @@ -using Bonobo.Git.Server.Data; -using Bonobo.Git.Server.Git.GitService.ReceivePackHook; -using Newtonsoft.Json; +using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Web; namespace Bonobo.Git.Server.Git.GitService.ReceivePackHook.Durability { @@ -14,27 +11,24 @@ namespace Bonobo.Git.Server.Git.GitService.ReceivePackHook.Durability /// public class ReceivePackRecovery : IHookReceivePack { - private readonly TimeSpan failedPackWaitTimeBeforeExecution; - private readonly IHookReceivePack next; - private readonly IRecoveryFilePathBuilder recoveryFilePathBuilder; - private readonly GitServiceResultParser resultFileParser; + private readonly IHookReceivePack _next; + private readonly IRecoveryFilePathBuilder _recoveryFilePathBuilder; + private readonly GitServiceResultParser _resultFileParser; public ReceivePackRecovery( IHookReceivePack next, - NamedArguments.FailedPackWaitTimeBeforeExecution failedPackWaitTimeBeforeExecution, IRecoveryFilePathBuilder recoveryFilePathBuilder, GitServiceResultParser resultFileParser) { - this.next = next; - this.failedPackWaitTimeBeforeExecution = failedPackWaitTimeBeforeExecution.Value; - this.recoveryFilePathBuilder = recoveryFilePathBuilder; - this.resultFileParser = resultFileParser; + _next = next; + _recoveryFilePathBuilder = recoveryFilePathBuilder; + _resultFileParser = resultFileParser; } public void PrePackReceive(ParsedReceivePack receivePack) { - File.WriteAllText(recoveryFilePathBuilder.GetPathToPackFile(receivePack), JsonConvert.SerializeObject(receivePack)); - next.PrePackReceive(receivePack); + File.WriteAllText(_recoveryFilePathBuilder.GetPathToPackFile(receivePack), JsonConvert.SerializeObject(receivePack)); + _next.PrePackReceive(receivePack); } public void PostPackReceive(ParsedReceivePack receivePack, GitExecutionResult result) @@ -45,9 +39,9 @@ public void PostPackReceive(ParsedReceivePack receivePack, GitExecutionResult re private void ProcessOnePack(ParsedReceivePack receivePack, GitExecutionResult result) { - next.PostPackReceive(receivePack, result); + _next.PostPackReceive(receivePack, result); - var packFilePath = recoveryFilePathBuilder.GetPathToPackFile(receivePack); + var packFilePath = _recoveryFilePathBuilder.GetPathToPackFile(receivePack); if (File.Exists(packFilePath)) { File.Delete(packFilePath); @@ -55,10 +49,15 @@ private void ProcessOnePack(ParsedReceivePack receivePack, GitExecutionResult re } public void RecoverAll() + { + RecoverAll(TimeSpan.FromSeconds(5 * 60)); + } + + public void RecoverAll(TimeSpan failedPackWaitTimeBeforeExecution) { var waitingReceivePacks = new List(); - foreach (var packDir in recoveryFilePathBuilder.GetPathToPackDirectory()) + foreach (var packDir in _recoveryFilePathBuilder.GetPathToPackDirectory()) { foreach (var packFilePath in Directory.GetFiles(packDir)) { @@ -77,12 +76,12 @@ public void RecoverAll() { // re-parse result file and execute "post" hooks // if result file is no longer there then move on - var failedPackResultFilePath = recoveryFilePathBuilder.GetPathToResultFile(pack.PackId, pack.RepositoryName, "receive-pack"); + var failedPackResultFilePath = _recoveryFilePathBuilder.GetPathToResultFile(pack.PackId, pack.RepositoryName, "receive-pack"); if (File.Exists(failedPackResultFilePath)) { using (var resultFileStream = File.OpenRead(failedPackResultFilePath)) { - var failedPackResult = resultFileParser.ParseResult(resultFileStream); + var failedPackResult = _resultFileParser.ParseResult(resultFileStream); ProcessOnePack(pack, failedPackResult); } File.Delete(failedPackResultFilePath); diff --git a/Bonobo.Git.Server/Git/GitService/ReceivePackHook/ReceivePackParser.cs b/Bonobo.Git.Server/Git/GitService/ReceivePackHook/ReceivePackParser.cs index 2ffd894cf..87a6e6ea0 100644 --- a/Bonobo.Git.Server/Git/GitService/ReceivePackHook/ReceivePackParser.cs +++ b/Bonobo.Git.Server/Git/GitService/ReceivePackHook/ReceivePackParser.cs @@ -8,17 +8,20 @@ using System.Security.Cryptography; using System.Text; using System.Web; +using Microsoft.AspNetCore.Http; namespace Bonobo.Git.Server.Git.GitService.ReceivePackHook { public class ReceivePackParser : IGitService { + private readonly IHttpContextAccessor httpContextAccessor; private readonly IGitService gitService; private readonly IHookReceivePack receivePackHandler; private readonly GitServiceResultParser resultParser; - public ReceivePackParser(IGitService gitService, IHookReceivePack receivePackHandler, GitServiceResultParser resultParser) + public ReceivePackParser(IHttpContextAccessor httpContextAccessor, IGitService gitService, IHookReceivePack receivePackHandler, GitServiceResultParser resultParser) { + this.httpContextAccessor = httpContextAccessor; this.gitService = gitService; this.receivePackHandler = receivePackHandler; this.resultParser = resultParser; @@ -164,7 +167,7 @@ public void ExecuteServiceByName(string correlationId, string repositoryName, st } // ------------------- - var user = HttpContext.Current.User.Username(); + var user = httpContextAccessor.HttpContext.User.Username(); receivedPack = new ParsedReceivePack(correlationId, repositoryName, pktLines, user, DateTime.Now, packCommits); inStream.Seek(0, SeekOrigin.Begin); diff --git a/Bonobo.Git.Server/Global.asax b/Bonobo.Git.Server/Global.asax deleted file mode 100644 index 04dd94369..000000000 --- a/Bonobo.Git.Server/Global.asax +++ /dev/null @@ -1 +0,0 @@ -<%@ Application Codebehind="Global.asax.cs" Inherits="Bonobo.Git.Server.MvcApplication" Language="C#" %> diff --git a/Bonobo.Git.Server/Global.asax.cs b/Bonobo.Git.Server/Global.asax.cs deleted file mode 100644 index 025442966..000000000 --- a/Bonobo.Git.Server/Global.asax.cs +++ /dev/null @@ -1,313 +0,0 @@ -using System; -using System.Configuration; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Security.Principal; -using System.Threading; -using System.Web; -using System.Web.Mvc; -using System.Web.Optimization; -using System.Web.Routing; -using System.Web.Security; -using Bonobo.Git.Server.App_Start; -using Bonobo.Git.Server.Configuration; -using Bonobo.Git.Server.Controllers; -using Bonobo.Git.Server.Data; -using Bonobo.Git.Server.Data.Update; -using Bonobo.Git.Server.Git; -using Bonobo.Git.Server.Git.GitService; -using Bonobo.Git.Server.Git.GitService.ReceivePackHook; -using Bonobo.Git.Server.Git.GitService.ReceivePackHook.Durability; -using Bonobo.Git.Server.Git.GitService.ReceivePackHook.Hooks; -using Bonobo.Git.Server.Security; -using Microsoft.Practices.Unity; -using System.Runtime.Caching; -using Bonobo.Git.Server.Attributes; -using Microsoft.Practices.Unity.Mvc; -using System.Web.Configuration; -using System.Security.Claims; -using System.Web.Helpers; -using System.Web.Hosting; -using Serilog; - -namespace Bonobo.Git.Server -{ - public class MvcApplication : HttpApplication - { - public static ObjectCache Cache = MemoryCache.Default; - - protected void Application_AcquireRequestState(object sender, EventArgs e) - { - if (HttpContext.Current.Session == null) - { - return; - } - - var culture = (CultureInfo)Session["Culture"]; - if (culture == null) - { - culture = !String.IsNullOrEmpty(UserConfiguration.Current.DefaultLanguage) - ? new CultureInfo(UserConfiguration.Current.DefaultLanguage) - : null; - - if (culture == null) - { - string langName = "en"; - - if (HttpContext.Current.Request.UserLanguages != null && - HttpContext.Current.Request.UserLanguages.Length != 0 && - HttpContext.Current.Request.UserLanguages[0].Length > 2) - { - langName = HttpContext.Current.Request.UserLanguages[0].Substring(0, 2); - } - - culture = new CultureInfo(langName); - Session["Culture"] = culture; - } - } - - Thread.CurrentThread.CurrentUICulture = culture; - Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(culture.Name); - } - - protected void Application_Start() - { - ConfigureLogging(); - Log.Information("Bonobo starting"); - - AreaRegistration.RegisterAllAreas(); - BundleConfig.RegisterBundles(BundleTable.Bundles); - RouteConfig.RegisterRoutes(RouteTable.Routes); - UserConfiguration.Initialize(); - RegisterDependencyResolver(); - GlobalFilters.Filters.Add((AllViewsFilter)DependencyResolver.Current.GetService()); - - var connectionstring = WebConfigurationManager.ConnectionStrings["BonoboGitServerContext"]; - if (connectionstring.ProviderName.ToLowerInvariant() == "system.data.sqlite") - { - if(!connectionstring.ConnectionString.ToLowerInvariant().Contains("binaryguid=false")) - { - Log.Error("Please ensure that the sqlite connection string contains 'BinaryGUID=false;'."); - throw new ConfigurationErrorsException("Please ensure that the sqlite connection string contains 'BinaryGUID=false;'."); - } - } - - try - { - AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier; - - new AutomaticUpdater().Run(); - new RepositorySynchronizer().Run(); - } - catch (Exception ex) - { - Log.Error(ex, "Startup exception"); - throw; - } - } - - private void ConfigureLogging() - { - Log.Logger = new LoggerConfiguration() - .ReadFrom.AppSettings() - .WriteTo.RollingFile(GetLogFileNameFormat()) - .CreateLogger(); - } - - public static string GetLogFileNameFormat() - { - string logDirectory = ConfigurationManager.AppSettings["LogDirectory"]; - if (string.IsNullOrEmpty(logDirectory)) - { - logDirectory = @"~\App_Data\Logs"; - } - return Path.Combine(HostingEnvironment.MapPath(logDirectory), "log-{Date}.txt"); - } - - private static void RegisterDependencyResolver() - { - var container = new UnityContainer(); - - /* - The UnityDecoratorContainerExtension breaks resolving named type registrations, like: - - container.RegisterType("ActiveDirectory"); - container.RegisterType("Internal"); - IMembershipService membershipService = container.Resolve(AuthenticationSettings.MembershipService); - - Until this issue is resolved, the following two switch hacks will have to do - */ - - switch (AuthenticationSettings.MembershipService.ToLowerInvariant()) - { - case "activedirectory": - container.RegisterType(); - container.RegisterType(); - container.RegisterType(); - container.RegisterType(); - container.RegisterType(); - break; - case "internal": - container.RegisterType(); - container.RegisterType(); - container.RegisterType(); - container.RegisterType(); - container.RegisterType(); - break; - default: - throw new ArgumentException("Missing declaration in web.config", "MembershipService"); - } - - switch (AuthenticationSettings.AuthenticationProvider.ToLowerInvariant()) - { - case "windows": - container.RegisterType(); - break; - case "cookies": - container.RegisterType(); - break; - case "federation": - container.RegisterType(); - break; - default: - throw new ArgumentException("Missing declaration in web.config", "AuthenticationProvider"); - } - - container.RegisterType( - new InjectionFactory((ctr, type, name) => { - return new ConfigurationBasedRepositoryLocator(UserConfiguration.Current.Repositories); - }) - ); - - container.RegisterInstance( - new GitServiceExecutorParams() - { - GitPath = GetRootPath(ConfigurationManager.AppSettings["GitPath"]), - GitHomePath = GetRootPath(ConfigurationManager.AppSettings["GitHomePath"]), - RepositoriesDirPath = UserConfiguration.Current.Repositories, - }); - - container.RegisterType(); - - if (AppSettings.IsPushAuditEnabled) - { - EnablePushAuditAnalysis(container); - } - - container.RegisterType(); - - DependencyResolver.SetResolver(new UnityDependencyResolver(container)); - - var oldProvider = FilterProviders.Providers.Single(f => f is FilterAttributeFilterProvider); - FilterProviders.Providers.Remove(oldProvider); - - var provider = new UnityFilterAttributeFilterProvider(container); - FilterProviders.Providers.Add(provider); - } - - private static void EnablePushAuditAnalysis(IUnityContainer container) - { - var isReceivePackRecoveryProcessEnabled = !string.IsNullOrEmpty(ConfigurationManager.AppSettings["RecoveryDataPath"]); - - if (isReceivePackRecoveryProcessEnabled) - { - // git service execution durability registrations to enable receive-pack hook execution after failures - container.RegisterType(); - container.RegisterType(); - container.RegisterType(); - container.RegisterType(); - container.RegisterInstance(new NamedArguments.FailedPackWaitTimeBeforeExecution(TimeSpan.FromSeconds(5 * 60))); - - container.RegisterInstance(new NamedArguments.ReceivePackRecoveryDirectory( - Path.IsPathRooted(ConfigurationManager.AppSettings["RecoveryDataPath"]) ? - ConfigurationManager.AppSettings["RecoveryDataPath"] : - HttpContext.Current.Server.MapPath(ConfigurationManager.AppSettings["RecoveryDataPath"]))); - } - - // base git service executor - container.RegisterType(); - container.RegisterType(); - - // receive pack hooks - container.RegisterType(); - container.RegisterType(); - - // run receive-pack recovery if possible - if (isReceivePackRecoveryProcessEnabled) - { - var recoveryProcess = container.Resolve( - new ParameterOverride( - "failedPackWaitTimeBeforeExecution", - new NamedArguments.FailedPackWaitTimeBeforeExecution(TimeSpan.FromSeconds(0)))); // on start up set time to wait = 0 so that recovery for all waiting packs is attempted - - try - { - recoveryProcess.RecoverAll(); - } - catch - { - // don't let a failed recovery attempt stop start-up process - } - finally - { - if (recoveryProcess != null) - { - container.Teardown(recoveryProcess); - } - } - } - } - - - protected void Application_Error(object sender, EventArgs e) - { - Exception exception = Server.GetLastError(); - if (exception != null) - { - Response.Clear(); - HttpException httpException = exception as HttpException; - - RouteData routeData = new RouteData(); - routeData.Values.Add("controller", "Home"); - if (httpException == null) - { - routeData.Values.Add("action", "Error"); - if (exception != null) - { - Log.Error(exception, "Exception caught in Global.asax1"); - } - } - else - { - switch (httpException.GetHttpCode()) - { - case 404: - routeData.Values.Add("action", "PageNotFound"); - break; - case 500: - routeData.Values.Add("action", "ServerError"); - Log.Error(exception, "500 Exception caught in Global.asax"); - break; - default: - routeData.Values.Add("action", "Error"); - Log.Error(exception, "Exception caught in Global.asax (code {Code})", httpException.GetHttpCode()); - break; - } - } - Server.ClearError(); - Response.TrySkipIisCustomErrors = true; - IController errorController = new HomeController(); - errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData)); - } - } - - private static string GetRootPath(string path) - { - return Path.IsPathRooted(path) ? - path : - HttpContext.Current.Server.MapPath(path); - } - - } -} diff --git a/Bonobo.Git.Server/Helpers/CssRewriteUrlTransformWrapper.cs b/Bonobo.Git.Server/Helpers/CssRewriteUrlTransformWrapper.cs deleted file mode 100644 index f487ab2e1..000000000 --- a/Bonobo.Git.Server/Helpers/CssRewriteUrlTransformWrapper.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Web; -using System.Web.Optimization; - -namespace Bonobo.Git.Server.Helpers -{ - public class CssRewriteUrlTransformWrapper : IItemTransform - { - public string Process(string includedVirtualPath, string input) - { - return new CssRewriteUrlTransform().Process( - "~" + VirtualPathUtility.ToAbsolute(includedVirtualPath), - input); - } - } -} \ No newline at end of file diff --git a/Bonobo.Git.Server/Helpers/CustomHtmlHelpers.cs b/Bonobo.Git.Server/Helpers/CustomHtmlHelpers.cs index b663bc227..bca71ba30 100644 --- a/Bonobo.Git.Server/Helpers/CustomHtmlHelpers.cs +++ b/Bonobo.Git.Server/Helpers/CustomHtmlHelpers.cs @@ -1,33 +1,41 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Web; -using System.Web.Mvc; -using System.Web.Mvc.Html; using System.Reflection; -using System.Text; -using System.Web.Routing; -using System.Linq.Expressions; -using Bonobo.Git.Server.Models; using System.ComponentModel.DataAnnotations; +using System.Data; +using System.Linq.Expressions; +using System.Text; +using Bonobo.Git.Server.Extensions; +using Microsoft.AspNetCore.Html; +using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.AspNetCore.Mvc.ViewFeatures; +using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal; namespace Bonobo.Git.Server.Helpers { public static class CustomHtmlHelpers { - public static IHtmlString AssemblyVersion(this HtmlHelper helper) + private static readonly string NoDataMessage = "No Records..."; + + private static readonly string EmptyModelMessage = + "View Model cannot be null! Please make sure your View Model is created and passed to this View"; + + private static readonly string EmptyNameMessage = "Name of the CheckBoxList cannot be null or empty"; + + public static IHtmlContent AssemblyVersion(this IHtmlHelper helper) { - return MvcHtmlString.Create(Assembly.GetExecutingAssembly().GetName().Version.ToString()); + return new HtmlString(Assembly.GetExecutingAssembly().GetName().Version.ToString()); } - public static IHtmlString MarkdownToHtml(this HtmlHelper helper, string markdownText) + public static IHtmlContent MarkdownToHtml(this IHtmlHelper helper, string markdownText) { - return MvcHtmlString.Create(CommonMark.CommonMarkConverter.Convert(markdownText)); + return new HtmlString(CommonMark.CommonMarkConverter.Convert(markdownText)); } - public static MvcHtmlString DisplayEnum(this HtmlHelper helper, Enum e) + public static HtmlString DisplayEnum(this IHtmlHelper helper, Enum e) { - string result = "[[" + e.ToString() + "]]"; + string result = "[[" + e + "]]"; var memberInfo = e.GetType().GetMember(e.ToString()).FirstOrDefault(); if (memberInfo != null) { @@ -41,7 +49,96 @@ public static MvcHtmlString DisplayEnum(this HtmlHelper helper, Enum e) } } - return MvcHtmlString.Create(result); + return new HtmlString(result); + } + + // Originally from https://github.com/mikhail-tsennykh/MvcCheckBoxList + public static IHtmlContent CheckBoxListFor( + this IHtmlHelper htmlHelper, + Expression> listNameExpr, + Expression>> sourceDataExpr, + Expression> valueExpr, + Expression> textToDisplayExpr, + Expression>> selectedValuesExpr) + { + var listName = ExpressionHelper.GetExpressionText(listNameExpr); + + if (sourceDataExpr == null || sourceDataExpr.Body.ToString() == "null") + return new HtmlString(NoDataMessage); + if (htmlHelper.ViewData.Model == null) throw new NoNullAllowedException(EmptyModelMessage); + if (string.IsNullOrEmpty(listName)) throw new ArgumentException(EmptyNameMessage, nameof(listNameExpr)); + + var model = htmlHelper.ViewData.Model; + var sourceData = sourceDataExpr.Compile()(model).ToList(); + var valueFunc = valueExpr.Compile(); + var textToDisplayFunc = textToDisplayExpr.Compile(); + var selectedItems = new List(); + var selectedItemsTemp = selectedValuesExpr?.Compile()(model); + if (selectedItemsTemp != null) selectedItems = selectedItemsTemp.ToList(); + var selectedValues = selectedItems.Select(s => valueFunc(s).ToString()).ToList(); + + if (!sourceData.Any()) return new HtmlString(NoDataMessage); + + var sb = new StringBuilder(); + var linkedLabelCounter = 0; + + foreach (var item in sourceData) + { + var itemValue = valueFunc(item).ToString(); + var itemText = textToDisplayFunc(item).ToString(); + + linkedLabelCounter = GenerateCheckBoxListElement(sb, linkedLabelCounter, htmlHelper, + selectedValues, listName, itemValue, + itemText); + } + + return new HtmlString(sb.ToString()); + } + + private static int GenerateCheckBoxListElement(StringBuilder sb, + int linkedLabelCounter, IHtmlHelper htmlHelper, + List selectedValues, string name, string itemValue, string itemText) + { + var fullName = htmlHelper.ViewData.TemplateInfo.GetFullHtmlFieldName(name); + + var checkboxBuilder = new TagBuilder("input"); + + if (selectedValues.Any(value => value == itemValue)) checkboxBuilder.MergeAttribute("checked", "checked"); + + checkboxBuilder.MergeAttribute("type", "checkbox"); + checkboxBuilder.MergeAttribute("value", itemValue); + checkboxBuilder.MergeAttribute("name", fullName); + + var linkId = htmlHelper.GenerateIdFromName(htmlHelper.ViewData.TemplateInfo.GetFullHtmlFieldName(name)) + + linkedLabelCounter++; + checkboxBuilder.GenerateId(linkId, "?"); + var linkedLabelBuilder = new TagBuilder("label"); + linkedLabelBuilder.MergeAttribute("for", linkId); + linkedLabelBuilder.InnerHtml.Clear(); + linkedLabelBuilder.InnerHtml.Append(itemText); + + // if there are any errors for a named field, we add the css attribute + if (htmlHelper.ViewData.ModelState.TryGetValue(fullName, out var modelStateEntry)) + { + if (modelStateEntry.Errors.Count > 0) + { + checkboxBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName); + } + } + + var modelExplorer = + ExpressionMetadataProvider.FromStringExpression(name, htmlHelper.ViewData, htmlHelper.MetadataProvider); + var validationAttributeProvider = + htmlHelper.ViewContext.HttpContext.RequestServices.GetService(typeof(ValidationHtmlAttributeProvider)) + as ValidationHtmlAttributeProvider; + validationAttributeProvider?.AddAndTrackValidationAttributes(htmlHelper.ViewContext, modelExplorer, name, + checkboxBuilder.Attributes); + + sb.Append(checkboxBuilder.ToString(TagRenderMode.SelfClosing)); + sb.Append(linkedLabelBuilder.ToString(TagRenderMode.Normal)); + sb.Append("
"); + + return linkedLabelCounter; } } -} +} \ No newline at end of file diff --git a/Bonobo.Git.Server/Helpers/PathEncoder.cs b/Bonobo.Git.Server/Helpers/PathEncoder.cs index 91fa0f167..9e86c14e3 100644 --- a/Bonobo.Git.Server/Helpers/PathEncoder.cs +++ b/Bonobo.Git.Server/Helpers/PathEncoder.cs @@ -3,7 +3,8 @@ using System.Globalization; using System.IO; using System.Text; -using System.Web.Hosting; +using Bonobo.Git.Server.Extensions; +using Microsoft.AspNetCore.Hosting; namespace Bonobo.Git.Server.Helpers { @@ -118,9 +119,9 @@ public static string Decode(string encodedPath) return Encoding.UTF8.GetString(bytes.ToArray()); } - public static string GetRootPath(string path) + public static string GetRootPath(IHostingEnvironment hostingEnvironment, string path) { - return Path.IsPathRooted(path) ? path : HostingEnvironment.MapPath(path); + return Path.IsPathRooted(path) ? path : hostingEnvironment.MapPath(path); } } } diff --git a/Bonobo.Git.Server/Helpers/RepositoryCommitModelHelpers.cs b/Bonobo.Git.Server/Helpers/RepositoryCommitModelHelpers.cs index 220d55249..3601f757e 100644 --- a/Bonobo.Git.Server/Helpers/RepositoryCommitModelHelpers.cs +++ b/Bonobo.Git.Server/Helpers/RepositoryCommitModelHelpers.cs @@ -1,7 +1,6 @@ using Bonobo.Git.Server.Models; using System.Collections.Generic; using System.Linq; -using System.Web.Mvc; namespace Bonobo.Git.Server.Helpers { diff --git a/Bonobo.Git.Server/Models/AccountModels.cs b/Bonobo.Git.Server/Models/AccountModels.cs index 86d505443..adc977670 100644 --- a/Bonobo.Git.Server/Models/AccountModels.cs +++ b/Bonobo.Git.Server/Models/AccountModels.cs @@ -1,12 +1,7 @@ using System; using System.Collections.Generic; -using System.ComponentModel; using System.ComponentModel.DataAnnotations; -using System.Globalization; -using System.Linq; -using System.Web; -using System.Web.Mvc; -using System.Web.Security; +using Microsoft.AspNetCore.Mvc; using Bonobo.Git.Server.App_GlobalResources; using Bonobo.Git.Server.Data; diff --git a/Bonobo.Git.Server/Models/HomeModels.cs b/Bonobo.Git.Server/Models/HomeModels.cs index 9fe456c4d..87d6f3d16 100644 --- a/Bonobo.Git.Server/Models/HomeModels.cs +++ b/Bonobo.Git.Server/Models/HomeModels.cs @@ -1,10 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; using Bonobo.Git.Server.App_GlobalResources; -using System.Web.Mvc; +using Microsoft.AspNetCore.Mvc; namespace Bonobo.Git.Server.Models { diff --git a/Bonobo.Git.Server/Models/RepositoryModels.cs b/Bonobo.Git.Server/Models/RepositoryModels.cs index ae815bedc..db817325d 100644 --- a/Bonobo.Git.Server/Models/RepositoryModels.cs +++ b/Bonobo.Git.Server/Models/RepositoryModels.cs @@ -3,18 +3,17 @@ using System.ComponentModel.DataAnnotations; using System.Drawing; using System.Drawing.Imaging; -using System.Globalization; using System.IO; using System.Text; using System.Text.RegularExpressions; -using System.Web; +using Microsoft.AspNetCore.Mvc; using Bonobo.Git.Server.App_GlobalResources; using Bonobo.Git.Server.Attributes; using Bonobo.Git.Server.Data; using LibGit2Sharp; -using System.Web.Mvc; +using Microsoft.AspNetCore.Http; namespace Bonobo.Git.Server.Models { @@ -101,12 +100,10 @@ public RepositoryDetailModel() [Display(ResourceType = typeof(Resources), Name = "Repository_Detail_Name")] public string Name { get; set; } - [AllowHtml] [Display(ResourceType = typeof(Resources), Name = "Repository_Detail_Group")] [StringLength(255, ErrorMessageResourceType = typeof(Resources), ErrorMessageResourceName = "Validation_StringLength")] public string Group { get; set; } - [AllowHtml] [Display(ResourceType = typeof(Resources), Name = "Repository_Detail_Description")] [StringLength(255, ErrorMessageResourceType = typeof(Resources), ErrorMessageResourceName = "Validation_StringLength")] public string Description { get; set; } @@ -329,7 +326,7 @@ public RepositoryLogoDetailModel(byte[] data) [FileUploadExtensions(Extensions = "PNG,JPG,JPEG,GIF")] [Display(ResourceType = typeof(Resources), Name = "Repository_Detail_Logo_PostedFile")] - public HttpPostedFileWrapper PostedFile { get; set; } + public IFormFile PostedFile { get; set; } [Display(ResourceType = typeof(Resources), Name = "Repository_Detail_RemoveLogo")] public bool RemoveLogo { get; set; } @@ -349,8 +346,9 @@ public byte[] BinaryData if (_data == null && PostedFile != null) { using (MemoryStream ms = new MemoryStream()) + using (Stream fs = PostedFile.OpenReadStream()) { - Image originalImage = Image.FromStream(PostedFile.InputStream, true, true); + Image originalImage = Image.FromStream(fs, true, true); int logoWidth = originalImage.Width >= 72 ? 72 : 36; diff --git a/Bonobo.Git.Server/Models/SettingsModels.cs b/Bonobo.Git.Server/Models/SettingsModels.cs index 2a45ee04b..68289f582 100644 --- a/Bonobo.Git.Server/Models/SettingsModels.cs +++ b/Bonobo.Git.Server/Models/SettingsModels.cs @@ -1,11 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; using Bonobo.Git.Server.App_GlobalResources; using Bonobo.Git.Server.Attributes; -using System.Web.Mvc; +using Microsoft.AspNetCore.Mvc; namespace Bonobo.Git.Server.Models { diff --git a/Bonobo.Git.Server/Models/TeamModels.cs b/Bonobo.Git.Server/Models/TeamModels.cs index 08ebb4b7e..7446c1cd0 100644 --- a/Bonobo.Git.Server/Models/TeamModels.cs +++ b/Bonobo.Git.Server/Models/TeamModels.cs @@ -1,17 +1,13 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Web; using System.ComponentModel.DataAnnotations; +using Microsoft.AspNetCore.Mvc; using Bonobo.Git.Server.App_GlobalResources; using Bonobo.Git.Server.Data; namespace Bonobo.Git.Server.Models { - using IdName = Tuple; - using System.Web.Mvc; - public class TeamModel : INameProperty { public Guid Id { get; set; } @@ -32,13 +28,11 @@ public class TeamEditModel public Guid Id { get; set; } [Remote("UniqueNameTeam", "Validation", AdditionalFields="Id", ErrorMessageResourceType = typeof(Resources), ErrorMessageResourceName = "Validation_Duplicate_Name")] - [AllowHtml] [Required(ErrorMessageResourceType = typeof(Resources), ErrorMessageResourceName = "Validation_Required")] [StringLength(50, ErrorMessageResourceType = typeof(Resources), ErrorMessageResourceName = "Validation_StringLength")] [Display(ResourceType = typeof(Resources), Name = "Team_Detail_Name")] public string Name { get; set; } - [AllowHtml] [Display(ResourceType = typeof(Resources), Name = "Team_Detail_Description")] public string Description { get; set; } diff --git a/Bonobo.Git.Server/Owin/WindowsAuthenticationExtensions.cs b/Bonobo.Git.Server/Owin/WindowsAuthenticationExtensions.cs index dfab18d46..509c763e9 100644 --- a/Bonobo.Git.Server/Owin/WindowsAuthenticationExtensions.cs +++ b/Bonobo.Git.Server/Owin/WindowsAuthenticationExtensions.cs @@ -1,18 +1,14 @@ -using Microsoft.Owin.Extensions; -using Owin; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; +using System; +using Microsoft.AspNetCore.Authentication; namespace Bonobo.Git.Server.Owin.Windows { public static class WindowsAuthenticationExtensions { - public static IAppBuilder UseWindowsAuthentication(this IAppBuilder app, WindowsAuthenticationOptions options) + public static AuthenticationBuilder AddWindows(this AuthenticationBuilder builder, Action configureOptions) { - app.Use(typeof(WindowsAuthenticationMiddleware), app, options); - return app.UseStageMarker(PipelineStage.Authenticate); + return builder.AddScheme( + WindowsAuthenticationDefaults.AuthenticationType, configureOptions); } } } \ No newline at end of file diff --git a/Bonobo.Git.Server/Owin/WindowsAuthenticationHandler.cs b/Bonobo.Git.Server/Owin/WindowsAuthenticationHandler.cs index 0a46f595d..f13fd0382 100644 --- a/Bonobo.Git.Server/Owin/WindowsAuthenticationHandler.cs +++ b/Bonobo.Git.Server/Owin/WindowsAuthenticationHandler.cs @@ -1,25 +1,85 @@ using System; -using System.Linq; using System.Security.Claims; using System.Threading.Tasks; using System.Collections.Generic; -using Microsoft.Owin.Infrastructure; -using Microsoft.Owin.Security; -using Microsoft.Owin.Security.Infrastructure; -using System.Security.Cryptography; -using System.Text; using System.DirectoryServices.AccountManagement; - -using Bonobo.Git.Server.Security; -using Bonobo.Git.Server.Helpers; +using System.Linq; +using System.Text.Encodings.Web; +using Microsoft.AspNetCore.Authentication; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Serilog; namespace Bonobo.Git.Server.Owin.Windows { internal class WindowsAuthenticationHandler : AuthenticationHandler { - protected override Task AuthenticateCoreAsync() + public WindowsAuthenticationHandler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock) + { + } + + protected override Task HandleChallengeAsync(AuthenticationProperties properties) + { + //if (Response.StatusCode == 401 && Response.Headers.ContainsKey("WWW-Authenticate") == false) + //{ + // var challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode); + + // if (challenge != null) + // { + // AuthenticationProperties challengeProperties = challenge.Properties; + + // if (string.IsNullOrEmpty(challengeProperties.RedirectUri)) + // { + // throw new ArgumentNullException("RedirectUri"); + // } + + // string protectedProperties = Options.StateDataFormat.Protect(challengeProperties); + // string handshakeId = Guid.NewGuid().ToString(); + + // WindowsAuthenticationHandshake handshake = new WindowsAuthenticationHandshake() + // { + // AuthenticationProperties = challengeProperties + // }; + + // Options.Handshakes.Add(handshakeId, handshake); + // Response.Redirect(WebUtilities.AddQueryString(Request.PathBase + Options.CallbackPath.Value, "id", handshakeId)); + // } + //} + + return Task.Delay(0); + } + + //public override async Task InvokeAsync() + //{ + // bool result = false; + + // if (Options.CallbackPath.HasValue && Options.CallbackPath == Request.Path) + // { + // AuthenticateResult ticket = await AuthenticateAsync(); + // if (ticket != null && ticket.Identity != null) + // { + // Context.SignInAsync(ticket.Properties, ticket.Identity); + // if(!ticket.Properties.RedirectUri.StartsWith(Request.PathBase.Value)) + // { + // ticket.Properties.RedirectUri = Request.PathBase.Value + ticket.Properties.RedirectUri; + // } + // Response.Redirect(ticket.Properties.RedirectUri); + // result = true; + // } + + // if (Response.Headers.ContainsKey("WWW-Authenticate")) + // { + // result = true; + // } + // } + + // return result; + //} + + + + protected override Task HandleAuthenticateAsync() { AuthenticationProperties properties = null; WindowsAuthenticationHandshake handshake = null; @@ -39,7 +99,8 @@ protected override Task AuthenticateCoreAsync() Response.Headers.Add("WWW-Authenticate", new[] { string.Concat("NTLM ", token.Challenge) }); Response.StatusCode = 401; - return Task.FromResult(new AuthenticationTicket(null, properties)); + return Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(null, properties, + WindowsAuthenticationDefaults.AuthenticationType))); } break; case AuthenticationStage.Response: @@ -51,7 +112,7 @@ protected override Task AuthenticateCoreAsync() Log.Verbose("WinAuth: Valid response for uid {UserId}", uid); - if (claimdelegate == null) + if (claimdelegate == null) { string domainName = handshake.AuthenticatedUsername.GetDomain(); @@ -65,7 +126,7 @@ protected override Task AuthenticateCoreAsync() { Log.Error("DC for domain {DomainName} has returned null for username {UserName} - failing auth", domainName, handshake.AuthenticatedUsername); Response.StatusCode = 401; - return Task.FromResult(new AuthenticationTicket(null, null)); + return Task.FromResult(AuthenticateResult.Fail("DC for domain {DomainName} has returned null for username {UserName}")); } Log.Verbose("WinAuth: DC returned adUser {ADUser}", adUser.GivenName); @@ -91,10 +152,9 @@ protected override Task AuthenticateCoreAsync() Options.Handshakes.TryRemove(handshakeId); Log.Verbose("WinAuth: New user - about to redirect to CreateADUser"); - // user does not exist! Redirect to create page. properties.RedirectUri = "/Account/CreateADUser"; - return Task.FromResult(new AuthenticationTicket(identity, properties)); + return Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(new ClaimsPrincipal(identity), properties, WindowsAuthenticationDefaults.AuthenticationType))); } else { @@ -109,7 +169,7 @@ protected override Task AuthenticateCoreAsync() Log.Verbose("WinAuth: Returning id auth ticket, claims: {Claims}", claims); - return Task.FromResult(new AuthenticationTicket(identity, properties)); + return Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(new ClaimsPrincipal(identity), properties, WindowsAuthenticationDefaults.AuthenticationType))); } } } @@ -118,66 +178,7 @@ protected override Task AuthenticateCoreAsync() Response.Headers.Add("WWW-Authenticate", new[] { "NTLM" }); Response.StatusCode = 401; } - return Task.FromResult(new AuthenticationTicket(null, properties)); - } - - protected override Task ApplyResponseChallengeAsync() - { - if (Response.StatusCode == 401 && Response.Headers.ContainsKey("WWW-Authenticate") == false) - { - var challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode); - - if (challenge != null) - { - AuthenticationProperties challengeProperties = challenge.Properties; - - if (string.IsNullOrEmpty(challengeProperties.RedirectUri)) - { - throw new ArgumentNullException("RedirectUri"); - } - - string protectedProperties = Options.StateDataFormat.Protect(challengeProperties); - string handshakeId = Guid.NewGuid().ToString(); - - WindowsAuthenticationHandshake handshake = new WindowsAuthenticationHandshake() - { - AuthenticationProperties = challengeProperties - }; - - Options.Handshakes.Add(handshakeId, handshake); - Response.Redirect(WebUtilities.AddQueryString(Request.PathBase + Options.CallbackPath.Value, "id", handshakeId)); - } - } - - return Task.Delay(0); - } - - public override async Task InvokeAsync() - { - bool result = false; - - if (Options.CallbackPath.HasValue && Options.CallbackPath == Request.Path) - { - AuthenticationTicket ticket = await AuthenticateAsync(); - if (ticket != null && ticket.Identity != null) - { - - Context.Authentication.SignIn(ticket.Properties, ticket.Identity); - if(!ticket.Properties.RedirectUri.StartsWith(Request.PathBase.Value)) - { - ticket.Properties.RedirectUri = Request.PathBase.Value + ticket.Properties.RedirectUri; - } - Response.Redirect(ticket.Properties.RedirectUri); - result = true; - } - - if (Response.Headers.ContainsKey("WWW-Authenticate")) - { - result = true; - } - } - - return result; + return Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(null, properties, WindowsAuthenticationDefaults.AuthenticationType))); } } } diff --git a/Bonobo.Git.Server/Owin/WindowsAuthenticationHandshake.cs b/Bonobo.Git.Server/Owin/WindowsAuthenticationHandshake.cs index 4b0b5fe4e..e09489868 100644 --- a/Bonobo.Git.Server/Owin/WindowsAuthenticationHandshake.cs +++ b/Bonobo.Git.Server/Owin/WindowsAuthenticationHandshake.cs @@ -1,9 +1,6 @@ -using Microsoft.Owin.Security; -using System; -using System.Collections.Generic; -using System.Linq; +using System; using System.Security.Principal; -using System.Web; +using Microsoft.AspNetCore.Authentication; namespace Bonobo.Git.Server.Owin.Windows { diff --git a/Bonobo.Git.Server/Owin/WindowsAuthenticationMiddleware.cs b/Bonobo.Git.Server/Owin/WindowsAuthenticationMiddleware.cs index f1b25b564..4ab88e688 100644 --- a/Bonobo.Git.Server/Owin/WindowsAuthenticationMiddleware.cs +++ b/Bonobo.Git.Server/Owin/WindowsAuthenticationMiddleware.cs @@ -1,35 +1,23 @@ using System; - -using Microsoft.Owin; -using Microsoft.Owin.Security; -using Microsoft.Owin.Security.DataHandler; -using Microsoft.Owin.Security.DataProtection; -using Microsoft.Owin.Security.Infrastructure; - -using Owin; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.DataProtection; namespace Bonobo.Git.Server.Owin.Windows { - public class WindowsAuthenticationMiddleware : AuthenticationMiddleware + public class WindowsAuthenticationMiddleware { - public WindowsAuthenticationMiddleware(OwinMiddleware next, IAppBuilder app, WindowsAuthenticationOptions options) : base(next, options) - { - if (String.IsNullOrEmpty(Options.SignInAsAuthenticationType)) - { - options.SignInAsAuthenticationType = app.GetDefaultSignInAsAuthenticationType(); - } - - if (options.StateDataFormat == null) - { - IDataProtector dataProtector = app.CreateDataProtector(typeof(WindowsAuthenticationMiddleware).FullName, options.AuthenticationType); - options.StateDataFormat = new PropertiesDataFormat(dataProtector); - } - } - - protected override AuthenticationHandler CreateHandler() - { - return new WindowsAuthenticationHandler(); - } + //public WindowsAuthenticationMiddleware(OwinMiddleware next, IAppBuilder app, WindowsAuthenticationOptions options) : base(next, options) + //{ + // if (String.IsNullOrEmpty(options.SignInAsAuthenticationType)) + // { + // options.SignInAsAuthenticationType = app.GetDefaultSignInAsAuthenticationType(); + // } + // if (options.StateDataFormat == null) + // { + // IDataProtector dataProtector = app.CreateDataProtector(typeof(WindowsAuthenticationMiddleware).FullName, options.AuthenticationType); + // options.StateDataFormat = new PropertiesDataFormat(dataProtector); + // } + //} } } diff --git a/Bonobo.Git.Server/Owin/WindowsAuthenticationOptions.cs b/Bonobo.Git.Server/Owin/WindowsAuthenticationOptions.cs index a91bbd8b0..1addf2f49 100644 --- a/Bonobo.Git.Server/Owin/WindowsAuthenticationOptions.cs +++ b/Bonobo.Git.Server/Owin/WindowsAuthenticationOptions.cs @@ -2,13 +2,12 @@ using System.Collections.Generic; using System.Security.Claims; -using Microsoft.Owin; -using Microsoft.Owin.Security; -using System.Collections.Concurrent; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Http; namespace Bonobo.Git.Server.Owin.Windows { - public class WindowsAuthenticationOptions : AuthenticationOptions + public class WindowsAuthenticationOptions : AuthenticationSchemeOptions { internal static readonly PathString DefaultRedirectPath = new PathString("/windowsAuthCallback"); @@ -20,11 +19,11 @@ public class WindowsAuthenticationOptions : AuthenticationOptions public string SignInAsAuthenticationType { get; set; } public ISecureDataFormat StateDataFormat { get; set; } - public WindowsAuthenticationOptions() : base(WindowsAuthenticationDefaults.AuthenticationType) + public WindowsAuthenticationOptions() { - Description.Caption = WindowsAuthenticationDefaults.AuthenticationType; + //Description.Caption = WindowsAuthenticationDefaults.AuthenticationType; CallbackPath = DefaultRedirectPath; - AuthenticationMode = AuthenticationMode.Passive; + //AuthenticationMode = AuthenticationMode.Passive; Handshakes = new WindowsAuthenticationHandshakeCache("WindowsHandshakeCache"); } } diff --git a/Bonobo.Git.Server/Owin/WindowsAuthenticationToken.cs b/Bonobo.Git.Server/Owin/WindowsAuthenticationToken.cs index 8aa34ebda..4046dcaad 100644 --- a/Bonobo.Git.Server/Owin/WindowsAuthenticationToken.cs +++ b/Bonobo.Git.Server/Owin/WindowsAuthenticationToken.cs @@ -1,8 +1,4 @@ -using Microsoft.Owin.Security; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; +using System; namespace Bonobo.Git.Server.Owin.Windows { diff --git a/Bonobo.Git.Server/Program.cs b/Bonobo.Git.Server/Program.cs new file mode 100644 index 000000000..da5431442 --- /dev/null +++ b/Bonobo.Git.Server/Program.cs @@ -0,0 +1,20 @@ +using System.Runtime.Caching; +using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Hosting; + +namespace Bonobo.Git.Server +{ + public class Program + { + public static ObjectCache Cache = MemoryCache.Default; + + public static void Main(string[] args) + { + CreateWebHostBuilder(args).Build().Run(); + } + + public static IWebHostBuilder CreateWebHostBuilder(string[] args) => + WebHost.CreateDefaultBuilder(args) + .UseStartup(); + } +} diff --git a/Bonobo.Git.Server/Properties/launchSettings.json b/Bonobo.Git.Server/Properties/launchSettings.json new file mode 100644 index 000000000..eef61d20c --- /dev/null +++ b/Bonobo.Git.Server/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:49376", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Bonobo.Git.Server": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "http://localhost:5000", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} \ No newline at end of file diff --git a/Bonobo.Git.Server/Security/ADMembershipService.cs b/Bonobo.Git.Server/Security/ADMembershipService.cs index 6871a8e9f..0a1a7ae51 100644 --- a/Bonobo.Git.Server/Security/ADMembershipService.cs +++ b/Bonobo.Git.Server/Security/ADMembershipService.cs @@ -1,19 +1,9 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Data; -using System.DirectoryServices; using System.DirectoryServices.AccountManagement; -using System.Security.Cryptography; -using System.IO; -using System.Text; -using System.Data.Entity.Core; -using System.Diagnostics; using Bonobo.Git.Server.Data; using Bonobo.Git.Server.Models; -using System.Web.Security; -using System.Security.Principal; -using Bonobo.Git.Server.Configuration; using Bonobo.Git.Server.Helpers; using Serilog; diff --git a/Bonobo.Git.Server/Security/AuthenticationProvider.cs b/Bonobo.Git.Server/Security/AuthenticationProvider.cs index ca273bc4e..b9fd8e2e5 100644 --- a/Bonobo.Git.Server/Security/AuthenticationProvider.cs +++ b/Bonobo.Git.Server/Security/AuthenticationProvider.cs @@ -1,25 +1,28 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Security.Claims; using System.Linq; - using Bonobo.Git.Server.Models; - -using Microsoft.Practices.Unity; - -using Owin; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; namespace Bonobo.Git.Server.Security { public abstract class AuthenticationProvider : IAuthenticationProvider { - [Dependency] public IMembershipService MembershipService { get; set; } - - [Dependency] public IRoleProvider RoleProvider { get; set; } - public abstract void Configure(IAppBuilder app); + protected readonly IHttpContextAccessor httpContextAccessor; + + protected AuthenticationProvider(IHttpContextAccessor httpContextAccessor, IMembershipService membershipService, + IRoleProvider roleProvider) + { + this.httpContextAccessor = httpContextAccessor; + MembershipService = membershipService; + RoleProvider = roleProvider; + } + + public abstract void Configure(IServiceCollection services); public abstract void SignIn(string username, string returnUrl, bool rememberMe); public abstract void SignOut(); diff --git a/Bonobo.Git.Server/Security/CookieAuthenticationProvider.cs b/Bonobo.Git.Server/Security/CookieAuthenticationProvider.cs index 801041612..a336bb500 100644 --- a/Bonobo.Git.Server/Security/CookieAuthenticationProvider.cs +++ b/Bonobo.Git.Server/Security/CookieAuthenticationProvider.cs @@ -1,58 +1,44 @@ -using System; -using System.Collections.Generic; -using System.Linq; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; +using System; using System.Security.Claims; -using System.Web; - -using Bonobo.Git.Server.Models; - -using Microsoft.Owin; -using Microsoft.Owin.Security; -using Microsoft.Owin.Security.Cookies; -using Microsoft.Practices.Unity; - -using Owin; namespace Bonobo.Git.Server.Security { public class CookieAuthenticationProvider : AuthenticationProvider { - public override void Configure(IAppBuilder app) + public CookieAuthenticationProvider(IHttpContextAccessor httpContextAccessor, IMembershipService membershipService, IRoleProvider roleProvider) : base(httpContextAccessor, membershipService, roleProvider) { - app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType); - app.UseCookieAuthentication(new CookieAuthenticationOptions - { - AuthenticationType = CookieAuthenticationDefaults.AuthenticationType, - LoginPath = new PathString("/Home/LogOn"), - ExpireTimeSpan = TimeSpan.FromDays(3), - SlidingExpiration = true, - Provider = new Microsoft.Owin.Security.Cookies.CookieAuthenticationProvider + } + + public override void Configure(IServiceCollection services) + { + services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) + .AddCookie(options => { - OnApplyRedirect = context => - { - if (!context.Request.Headers.ContainsKey("AuthNoRedirect")) - { - context.Response.Redirect(context.RedirectUri); - } - } - }, - }); + options.LoginPath = new PathString("/Home/LogOn"); + options.ExpireTimeSpan = TimeSpan.FromDays(3); + options.SlidingExpiration = true; + }); } public override void SignIn(string username, string returnUrl = null, bool rememberMe = false) { - ClaimsIdentity identity = new ClaimsIdentity(GetClaimsForUser(username), CookieAuthenticationDefaults.AuthenticationType); + ClaimsIdentity identity = new ClaimsIdentity(GetClaimsForUser(username), CookieAuthenticationDefaults.AuthenticationScheme); + ClaimsPrincipal principal = new ClaimsPrincipal(identity); var authprop = new AuthenticationProperties { IsPersistent = rememberMe, RedirectUri = returnUrl }; - HttpContext.Current.GetOwinContext().Authentication.SignIn(authprop, identity); + httpContextAccessor.HttpContext.SignInAsync(principal, authprop).Wait(); if (!String.IsNullOrEmpty(returnUrl)) { - HttpContext.Current.Response.Redirect(returnUrl, false); + httpContextAccessor.HttpContext.Response.Redirect(returnUrl, false); } } public override void SignOut() { - HttpContext.Current.GetOwinContext().Authentication.SignOut(CookieAuthenticationDefaults.AuthenticationType); + httpContextAccessor.HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); } } } diff --git a/Bonobo.Git.Server/Security/EFMembershipService.cs b/Bonobo.Git.Server/Security/EFMembershipService.cs index 5e197703e..b321eb9fd 100644 --- a/Bonobo.Git.Server/Security/EFMembershipService.cs +++ b/Bonobo.Git.Server/Security/EFMembershipService.cs @@ -4,21 +4,21 @@ using Bonobo.Git.Server.Data; using Bonobo.Git.Server.Models; using System.Security.Cryptography; -using System.Data.Entity.Core; -using Microsoft.Practices.Unity; +using System.Runtime.CompilerServices; +using Microsoft.EntityFrameworkCore; using Serilog; namespace Bonobo.Git.Server.Security { public class EFMembershipService : IMembershipService { - [Dependency] public Func CreateContext { get; set; } private readonly IPasswordService _passwordService; - public EFMembershipService() + public EFMembershipService(Func createContext) { + CreateContext = createContext; // set up dependencies Action updateUserPasswordHook = (username, password) => @@ -98,7 +98,7 @@ public bool CreateUser(string username, string password, string givenName, strin { database.SaveChanges(); } - catch (UpdateException) + catch (DbUpdateException) { return false; } diff --git a/Bonobo.Git.Server/Security/EFRoleProvider.cs b/Bonobo.Git.Server/Security/EFRoleProvider.cs index 9b0fba330..329bbe753 100644 --- a/Bonobo.Git.Server/Security/EFRoleProvider.cs +++ b/Bonobo.Git.Server/Security/EFRoleProvider.cs @@ -1,15 +1,20 @@ using System; using System.Linq; using Bonobo.Git.Server.Data; -using Microsoft.Practices.Unity; +using Bonobo.Git.Server.Data.ManyToMany; +using Bonobo.Git.Server.Extensions; namespace Bonobo.Git.Server.Security { public class EFRoleProvider : IRoleProvider { - [Dependency] public Func CreateContext { get; set; } + public EFRoleProvider(Func createContext) + { + CreateContext = createContext; + } + public void AddUserToRoles(Guid userId, string[] roleNames) { AddUsersToRoles(new Guid[] { userId }, roleNames); @@ -26,7 +31,11 @@ public void AddUsersToRoles(Guid[] userIds, string[] roleNames) { foreach (var user in users) { - role.Users.Add(user); + role.Users.Add(new UserRole_InRole + { + Role = role, + User = user + }); } } @@ -56,7 +65,7 @@ public bool DeleteRole(string roleName, bool throwOnPopulatedRole) { if (throwOnPopulatedRole) { - if (role.Users.Count > 0) + if (role.Users.Any()) { throw new InvalidOperationException("Can't delete role with members."); } @@ -76,7 +85,7 @@ public string[] FindUsersInRole(string roleName, string usernameToMatch) using (var database = CreateContext()) { var users = database.Users - .Where(us => us.Username.Contains(usernameToMatch) && us.Roles.Any(role => role.Name == roleName)) + .Where(us => us.Username.Contains(usernameToMatch) && us.Roles.Any(role => role.Role.Name == roleName)) .Select(us => us.Username) .ToArray(); return users; @@ -95,8 +104,12 @@ public string[] GetRolesForUser(Guid userId) { using (var database = CreateContext()) { + var sql = database.Roles + .Where(role => role.Users.Any(us => us.UserId == userId)) + .Select(role => role.Name).ToSql(); + var roles = database.Roles - .Where(role => role.Users.Any(us => us.Id == userId)) + .Where(role => role.Users.Any(us => us.UserId == userId)) .Select(role => role.Name) .ToArray(); return roles; @@ -108,7 +121,7 @@ public Guid[] GetUsersInRole(string roleName) using (var database = CreateContext()) { var users = database.Users - .Where(us => us.Roles.Any(role => role.Name == roleName)) + .Where(us => us.Roles.Any(role => role.Role.Name == roleName)) .Select(us => us.Id) .ToArray(); return users; @@ -119,7 +132,7 @@ public bool IsUserInRole(Guid userId, string roleName) { using (var database = CreateContext()) { - return database.Roles.Any(role => role.Name == roleName && role.Users.Any(us => us.Id == userId)); + return database.Roles.Any(role => role.Name == roleName && role.Users.Any(us => us.User.Id == userId)); } } @@ -138,7 +151,11 @@ public void RemoveUsersFromRoles(Guid[] userIds, string[] roleNames) { foreach (var user in users) { - role.Users.Remove(user); + database.Remove(new UserRole_InRole + { + RoleId = role.Id, + UserId = user.Id + }); } } database.SaveChanges(); diff --git a/Bonobo.Git.Server/Security/FederationAuthenticationProvider.cs b/Bonobo.Git.Server/Security/FederationAuthenticationProvider.cs index 99e747e89..af002d259 100644 --- a/Bonobo.Git.Server/Security/FederationAuthenticationProvider.cs +++ b/Bonobo.Git.Server/Security/FederationAuthenticationProvider.cs @@ -1,23 +1,25 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; using Bonobo.Git.Server.Configuration; -using Microsoft.Owin.Security; -using Microsoft.Owin.Security.Cookies; -using Microsoft.Owin.Security.WsFederation; +using Microsoft.AspNetCore.Authentication.WsFederation; -using Owin; using System.Net; using System.Threading.Tasks; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; namespace Bonobo.Git.Server.Security { public class FederationAuthenticationProvider : AuthenticationProvider { - public override void Configure(IAppBuilder app) + public FederationAuthenticationProvider(IHttpContextAccessor httpContextAccessor, IMembershipService membershipService, IRoleProvider roleProvider) : base(httpContextAccessor, membershipService, roleProvider) + { + } + + public override void Configure(IServiceCollection services) { if (String.IsNullOrEmpty(FederationSettings.MetadataAddress)) { @@ -30,40 +32,42 @@ public override void Configure(IAppBuilder app) } - app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType); - app.UseCookieAuthentication(new CookieAuthenticationOptions()); - app.UseWsFederationAuthentication(new WsFederationAuthenticationOptions - { - MetadataAddress = FederationSettings.MetadataAddress, - Wtrealm = FederationSettings.Realm, - Notifications = new WsFederationAuthenticationNotifications() + services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) + .AddCookie() + .AddWsFederation(options => { - RedirectToIdentityProvider = (context) => + options.MetadataAddress = FederationSettings.MetadataAddress; + options.Wtrealm = FederationSettings.Realm; + options.Events = new WsFederationEvents { - if (context.OwinContext.Response.StatusCode == (int)HttpStatusCode.Unauthorized && context.Request.Headers.ContainsKey("AuthNoRedirect")) + OnRedirectToIdentityProvider = (context) => { - context.HandleResponse(); - } + if (context.Response.StatusCode == (int) HttpStatusCode.Unauthorized && + context.Request.Headers.ContainsKey("AuthNoRedirect")) + { + context.HandleResponse(); + } - return Task.FromResult(0); - } - } - }); + return Task.FromResult(0); + } + }; + }); } public override void SignIn(string username, string returnUrl, bool rememberMe) { var authprop = new AuthenticationProperties { IsPersistent = rememberMe, RedirectUri = returnUrl }; - HttpContext.Current.GetOwinContext().Authentication.Challenge(authprop, WsFederationAuthenticationDefaults.AuthenticationType); + httpContextAccessor.HttpContext.ChallengeAsync(WsFederationDefaults.AuthenticationScheme, authprop); if (!String.IsNullOrEmpty(returnUrl)) { - HttpContext.Current.Response.Redirect(returnUrl, false); + httpContextAccessor.HttpContext.Response.Redirect(returnUrl, false); } } public override void SignOut() { - HttpContext.Current.GetOwinContext().Authentication.SignOut(WsFederationAuthenticationDefaults.AuthenticationType, CookieAuthenticationDefaults.AuthenticationType); + httpContextAccessor.HttpContext.SignOutAsync(WsFederationDefaults.AuthenticationScheme); + httpContextAccessor.HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); } } } \ No newline at end of file diff --git a/Bonobo.Git.Server/Security/IAuthenticationProvider.cs b/Bonobo.Git.Server/Security/IAuthenticationProvider.cs index ea89d4151..3025a2a2f 100644 --- a/Bonobo.Git.Server/Security/IAuthenticationProvider.cs +++ b/Bonobo.Git.Server/Security/IAuthenticationProvider.cs @@ -1,13 +1,12 @@ using System.Collections.Generic; using System.Security.Claims; - -using Owin; +using Microsoft.Extensions.DependencyInjection; namespace Bonobo.Git.Server.Security { public interface IAuthenticationProvider { - void Configure(IAppBuilder app); + void Configure(IServiceCollection services); void SignIn(string username, string returnUrl, bool rememberMe); void SignOut(); IEnumerable GetClaimsForUser(string username); diff --git a/Bonobo.Git.Server/Security/RepositoryPermissionService.cs b/Bonobo.Git.Server/Security/RepositoryPermissionService.cs index 5989708a9..ccbd30002 100644 --- a/Bonobo.Git.Server/Security/RepositoryPermissionService.cs +++ b/Bonobo.Git.Server/Security/RepositoryPermissionService.cs @@ -4,22 +4,24 @@ using System.Collections.Generic; using Bonobo.Git.Server.Configuration; using Bonobo.Git.Server.Models; -using Microsoft.Practices.Unity; using Serilog; namespace Bonobo.Git.Server.Security { public class RepositoryPermissionService : IRepositoryPermissionService { - [Dependency] public IRepositoryRepository Repository { get; set; } - - [Dependency] public IRoleProvider RoleProvider { get; set; } - - [Dependency] public ITeamRepository TeamRepository { get; set; } - + + public RepositoryPermissionService(IRepositoryRepository repository, IRoleProvider roleProvider, + ITeamRepository teamRepository) + { + Repository = repository; + RoleProvider = roleProvider; + TeamRepository = teamRepository; + } + public bool HasPermission(Guid userId, string repositoryName, RepositoryAccessLevel requiredLevel) { var repository = Repository.GetRepository(repositoryName); diff --git a/Bonobo.Git.Server/Security/WindowsAuthenticationProvider.cs b/Bonobo.Git.Server/Security/WindowsAuthenticationProvider.cs index ec8cc6317..ad8a87a7e 100644 --- a/Bonobo.Git.Server/Security/WindowsAuthenticationProvider.cs +++ b/Bonobo.Git.Server/Security/WindowsAuthenticationProvider.cs @@ -1,65 +1,41 @@ using System; -using System.Collections.Generic; -using System.Linq; using System.Security.Claims; -using System.Web; - -using Bonobo.Git.Server.Models; - -using Microsoft.Owin; -using Microsoft.Owin.Security; -using Microsoft.Owin.Security.Cookies; -using Microsoft.Practices.Unity; - -using Owin; using Bonobo.Git.Server.Owin.Windows; -using Microsoft.Owin.Extensions; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Server.IISIntegration; +using Microsoft.Extensions.DependencyInjection; namespace Bonobo.Git.Server.Security { public class WindowsAuthenticationProvider : AuthenticationProvider { - public override void Configure(IAppBuilder app) + public WindowsAuthenticationProvider(IHttpContextAccessor httpContextAccessor, IMembershipService membershipService, IRoleProvider roleProvider) : base(httpContextAccessor, membershipService, roleProvider) { - app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType); - app.UseCookieAuthentication(new CookieAuthenticationOptions() - { - AuthenticationType = CookieAuthenticationDefaults.AuthenticationType, - LoginPath = new PathString("/Home/WindowsLogin"), - Provider = new Microsoft.Owin.Security.Cookies.CookieAuthenticationProvider() - { - OnApplyRedirect = context => - { - if (context.Request.Path != WindowsAuthenticationOptions.DefaultRedirectPath && !context.Request.Headers.ContainsKey("AuthNoRedirect")) - { - context.Response.Redirect(context.RedirectUri); - } - } - } - }); - app.UseWindowsAuthentication(new WindowsAuthenticationOptions - { - GetClaimsForUser = username => - { - return GetClaimsForUser(username); - } - }); + } + + public override void Configure(IServiceCollection services) + { + services.AddAuthentication(IISDefaults.AuthenticationScheme); } public override void SignIn(string username, string returnUrl = null, bool rememberMe = false) { ClaimsIdentity identity = new ClaimsIdentity(GetClaimsForUser(username), WindowsAuthenticationDefaults.AuthenticationType); + ClaimsPrincipal principal = new ClaimsPrincipal(identity); var authprop = new AuthenticationProperties { IsPersistent = rememberMe, RedirectUri = returnUrl }; - HttpContext.Current.GetOwinContext().Authentication.SignIn(authprop, identity); + httpContextAccessor.HttpContext.SignInAsync(principal, authprop); if (!String.IsNullOrEmpty(returnUrl)) { - HttpContext.Current.Response.Redirect(returnUrl, false); + httpContextAccessor.HttpContext.Response.Redirect(returnUrl, false); } } public override void SignOut() { - HttpContext.Current.GetOwinContext().Authentication.SignOut(WindowsAuthenticationDefaults.AuthenticationType); + httpContextAccessor.HttpContext.SignOutAsync(WindowsAuthenticationDefaults.AuthenticationType); } } } \ No newline at end of file diff --git a/Bonobo.Git.Server/Startup.cs b/Bonobo.Git.Server/Startup.cs index 4f05d7b27..c0d2952aa 100644 --- a/Bonobo.Git.Server/Startup.cs +++ b/Bonobo.Git.Server/Startup.cs @@ -1,20 +1,318 @@ using System; -using System.Web.Mvc; - -using Microsoft.Owin; - -using Owin; +using System.Configuration; +using System.Globalization; +using System.IO; +using System.Threading; +using Bonobo.Git.Server.App_Start; +using Bonobo.Git.Server.Configuration; +using Bonobo.Git.Server.Data; +using Bonobo.Git.Server.Data.Update; +using Bonobo.Git.Server.Extensions; +using Bonobo.Git.Server.Git; +using Bonobo.Git.Server.Git.GitService; +using Bonobo.Git.Server.Git.GitService.ReceivePackHook; +using Bonobo.Git.Server.Git.GitService.ReceivePackHook.Durability; +using Bonobo.Git.Server.Git.GitService.ReceivePackHook.Hooks; using Bonobo.Git.Server.Security; - -[assembly: OwinStartup(typeof(Bonobo.Git.Server.Startup))] +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Diagnostics; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Localization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json; +using Serilog; namespace Bonobo.Git.Server { public class Startup { - public void Configuration(IAppBuilder app) + private readonly IHostingEnvironment hostingEnvironment; + + public Startup(IHostingEnvironment hostingEnvironment) + { + this.hostingEnvironment = hostingEnvironment; + } + + // This method gets called by the runtime. Use this method to add services to the container. + // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 + public void ConfigureServices(IServiceCollection services) + { + ConfigureLogging(hostingEnvironment); + Log.Information("Bonobo starting"); + + UserConfiguration.Initialize(hostingEnvironment); + //GlobalFilters.Filters.Add((AllViewsFilter)DependencyResolver.Current.GetService()); + + var connectionstring = ConfigurationManager.ConnectionStrings["BonoboGitServerContext"]; + if (connectionstring.ProviderName.ToLowerInvariant() == "system.data.sqlite") + { + if (!connectionstring.ConnectionString.ToLowerInvariant().Contains("binaryguid=false")) + { + Log.Error("Please ensure that the sqlite connection string contains 'BinaryGUID=false;'."); + throw new ConfigurationErrorsException("Please ensure that the sqlite connection string contains 'BinaryGUID=false;'."); + } + } + + services.AddDbContextPool(options => + options.UseSqlite(connectionstring.ConnectionString)); + + services.AddMvc(); + + services.AddHttpContextAccessor(); + + services.AddAntiforgery(); + + services.AddAuthorization(options => + { + options.AddPolicy("Web", builder => builder.Requirements.Add(new WebRequirement())); + options.AddPolicy("WebRepository", builder => builder.Requirements.Add(new WebRequirement())); + options.AddPolicy("Git", builder => builder.Requirements.Add(new GitRequirement())); + }); + + services.AddSingleton(); + //services.AddSingleton(); + //services.AddSingleton(); + + switch (AuthenticationSettings.MembershipService.ToLowerInvariant()) + { + case "activedirectory": + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + break; + case "internal": + var sp = services.BuildServiceProvider(); + services.AddTransient(x => new EFMembershipService(() => sp.GetService())); + services.AddTransient(x => new EFRoleProvider(() => sp.GetService())); + services.AddTransient(x => new EFTeamRepository(() => sp.GetService())); + services.AddTransient(x => new EFRepositoryRepository(() => sp.GetService())); + services.AddTransient(); + break; + default: + throw new ArgumentException("Missing declaration in web.config", "MembershipService"); + } + + switch (AuthenticationSettings.AuthenticationProvider.ToLowerInvariant()) + { + case "windows": + services.AddTransient(); + break; + case "cookies": + services.AddTransient(); + break; + case "federation": + services.AddTransient(); + break; + default: + throw new ArgumentException("Missing declaration in web.config", "AuthenticationProvider"); + } + services.BuildServiceProvider().GetService().Configure(services); + + services.AddTransient(serviceProvider => + new ConfigurationBasedRepositoryLocator(UserConfiguration.Current.Repositories) + ); + + services.AddSingleton( + new GitServiceExecutorParams + { + GitPath = GetRootPath(hostingEnvironment, ConfigurationManager.AppSettings["GitPath"]), + GitHomePath = GetRootPath(hostingEnvironment, ConfigurationManager.AppSettings["GitHomePath"]), + RepositoriesDirPath = UserConfiguration.Current.Repositories, + }); + + services.AddTransient(); + + if (AppSettings.IsPushAuditEnabled) + { + EnablePushAuditAnalysis(services); + } + + services.AddTransient(); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseStaticFiles(); + app.UseAuthentication(); + app.UseMvc(builder => RouteConfig.RegisterRoutes(builder)); + + if (AppSettings.IsPushAuditEnabled) + { + var isReceivePackRecoveryProcessEnabled = !string.IsNullOrEmpty(ConfigurationManager.AppSettings["RecoveryDataPath"]); + // run receive-pack recovery if possible + if (isReceivePackRecoveryProcessEnabled) + { + var recoveryProcess = serviceProvider.GetService(); // on start up set time to wait = 0 so that recovery for all waiting packs is attempted + + try + { + recoveryProcess.RecoverAll(TimeSpan.FromSeconds(0)); + } + catch + { + // don't let a failed recovery attempt stop start-up process + } + } + } + + //app.Use(async (context, next) => + //{ + // SetThreadCultureForRequest(context); + // await next.Invoke(); + //}); + + try + { + //AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier; + + new AutomaticUpdater().Run(serviceProvider.GetService(), serviceProvider.GetService(), env); + new RepositorySynchronizer(serviceProvider.GetService()).Run(); + } + catch (Exception ex) + { + Log.Error(ex, "Startup exception"); + throw; + } + } + + protected void SetThreadCultureForRequest(HttpContext context) + { + if (context.Session == null) + { + return; + } + + var culture = (CultureInfo)JsonConvert.DeserializeObject(context.Session.GetString("Culture")); + if (culture == null) + { + culture = !String.IsNullOrEmpty(UserConfiguration.Current.DefaultLanguage) + ? new CultureInfo(UserConfiguration.Current.DefaultLanguage) + : null; + + if (culture == null) + { + string langName = "en"; + + var requestCultureFeature = context.Features.Get(); + + //if (context.Request.UserLanguages != null && + // context.Request.UserLanguages.Length != 0 && + // context.Request.UserLanguages[0].Length > 2) + //{ + // langName = context.Request.UserLanguages[0].Substring(0, 2); + //} + + culture = new CultureInfo(langName); + context.Session.SetString("Culture", JsonConvert.SerializeObject(culture)); + } + } + + Thread.CurrentThread.CurrentUICulture = culture; + Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(culture.Name); + } + + private void ConfigureLogging(IHostingEnvironment hostingEnvironment) + { + Log.Logger = new LoggerConfiguration() + .ReadFrom.AppSettings() + .WriteTo.RollingFile(GetLogFileNameFormat(hostingEnvironment)) + .CreateLogger(); + } + + public static string GetLogFileNameFormat(IHostingEnvironment hostingEnvironment) + { + string logDirectory = ConfigurationManager.AppSettings["LogDirectory"]; + if (string.IsNullOrEmpty(logDirectory)) + { + logDirectory = @"~\App_Data\Logs"; + } + return Path.Combine(hostingEnvironment.MapPath(logDirectory), "log-{Date}.txt"); + } + + private static void EnablePushAuditAnalysis(IServiceCollection services) + { + var isReceivePackRecoveryProcessEnabled = !string.IsNullOrEmpty(ConfigurationManager.AppSettings["RecoveryDataPath"]); + + if (isReceivePackRecoveryProcessEnabled) + { + // git service execution durability registrations to enable receive-pack hook execution after failures + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + + //services.AddSingleton(new NamedArguments.ReceivePackRecoveryDirectory( + // Path.IsPathRooted(ConfigurationManager.AppSettings["RecoveryDataPath"]) ? + // ConfigurationManager.AppSettings["RecoveryDataPath"] : + // HttpContext.Current.Server.MapPath(ConfigurationManager.AppSettings["RecoveryDataPath"]))); + } + + // base git service executor + services.AddTransient(); + services.AddTransient(); + + // receive pack hooks + services.AddTransient(); + services.AddTransient(); + } + + + protected void ConfigureExceptionHandler(IApplicationBuilder app) + { + app.UseExceptionHandler(errorApp => { errorApp.Run(async context => + { + var exceptionHandlerPathFeature = + context.Features.Get(); + Exception exception = exceptionHandlerPathFeature?.Error; + if (exception != null) + { + context.Response.Clear(); + + RouteData routeData = new RouteData(); + routeData.Values.Add("controller", "Home"); + switch (context.Response.StatusCode) + { + case 404: + routeData.Values.Add("action", "PageNotFound"); + break; + case 500: + routeData.Values.Add("action", "ServerError"); + Log.Error(exception, "500 Exception caught in Global.asax"); + break; + default: + routeData.Values.Add("action", "Error"); + Log.Error(exception, "Exception caught in Startup.cs (code {Code})", + context.Response.StatusCode); + break; + } + + // Server.ClearError(); + // context.Response.TrySkipIisCustomErrors = true; + //Controller errorController = new HomeController(); + //errorController.Execute(new RequestContext(new HttpContextWrapper(HostingApplication.Context), + // routeData)); + } + }); }); + } + + private static string GetRootPath(IHostingEnvironment hostingEnvironment, string path) { - DependencyResolver.Current.GetService().Configure(app); + return Path.IsPathRooted(path) ? + path : + hostingEnvironment.MapPath(path); } } } diff --git a/Bonobo.Git.Server/Views/Account/Create.cshtml b/Bonobo.Git.Server/Views/Account/Create.cshtml index 31b2b8a35..50d1d304c 100644 --- a/Bonobo.Git.Server/Views/Account/Create.cshtml +++ b/Bonobo.Git.Server/Views/Account/Create.cshtml @@ -1,4 +1,5 @@ -@model Bonobo.Git.Server.Models.UserCreateModel +@using Bonobo.Git.Server.App_GlobalResources +@model Bonobo.Git.Server.Models.UserCreateModel @{ ViewBag.Title = Resources.Account_Create_Title; } diff --git a/Bonobo.Git.Server/Views/Account/Delete.cshtml b/Bonobo.Git.Server/Views/Account/Delete.cshtml index 777a3ccc3..689487999 100644 --- a/Bonobo.Git.Server/Views/Account/Delete.cshtml +++ b/Bonobo.Git.Server/Views/Account/Delete.cshtml @@ -1,4 +1,5 @@ -@model Bonobo.Git.Server.Models.UserModel +@using Bonobo.Git.Server.App_GlobalResources +@model Bonobo.Git.Server.Models.UserModel @{ ViewBag.Title = Resources.Delete_Title; } diff --git a/Bonobo.Git.Server/Views/Account/Detail.cshtml b/Bonobo.Git.Server/Views/Account/Detail.cshtml index cbe406cb4..5de635b1b 100644 --- a/Bonobo.Git.Server/Views/Account/Detail.cshtml +++ b/Bonobo.Git.Server/Views/Account/Detail.cshtml @@ -1,10 +1,12 @@ -@model Bonobo.Git.Server.Models.UserDetailModel +@using Bonobo.Git.Server +@using Bonobo.Git.Server.App_GlobalResources +@model Bonobo.Git.Server.Models.UserDetailModel @{ ViewBag.Title = @Resources.Account_Detail_Title; } @if (Model == null) { - @Html.Partial("~/Views/Shared/_ItemNotFound.cshtml") + @await Html.PartialAsync("~/Views/Shared/_ItemNotFound.cshtml") } else { diff --git a/Bonobo.Git.Server/Views/Account/Edit.cshtml b/Bonobo.Git.Server/Views/Account/Edit.cshtml index ce4bf6f42..7617aed43 100644 --- a/Bonobo.Git.Server/Views/Account/Edit.cshtml +++ b/Bonobo.Git.Server/Views/Account/Edit.cshtml @@ -1,11 +1,13 @@ -@using MvcCheckBoxList.Model +@using Bonobo.Git.Server +@using Bonobo.Git.Server.Helpers +@using Bonobo.Git.Server.App_GlobalResources @model Bonobo.Git.Server.Models.UserEditModel @{ ViewBag.Title = Resources.Account_Edit_Title; } @if (Model == null) { - @Html.Partial("~/Views/Shared/_ItemNotFound.cshtml") + @await Html.PartialAsync("~/Views/Shared/_ItemNotFound.cshtml") } else { @@ -72,7 +74,7 @@ else
@Html.LabelFor(m => m.Roles) - @Html.CheckBoxListFor(m => m.PostedSelectedRoles, m => m.Roles, m => m, m => m, m => m.SelectedRoles, Position.Vertical) + @Html.CheckBoxListFor(m => m.PostedSelectedRoles, m => m.Roles, m => m, m => m, m => m.SelectedRoles)
diff --git a/Bonobo.Git.Server/Views/Account/Index.cshtml b/Bonobo.Git.Server/Views/Account/Index.cshtml index 27e7f78cc..b02f781ae 100644 --- a/Bonobo.Git.Server/Views/Account/Index.cshtml +++ b/Bonobo.Git.Server/Views/Account/Index.cshtml @@ -1,5 +1,11 @@ -@using Bonobo.Git.Server.Extensions; -@model UserDetailModelList +@using AndreyKurdiumov.AspNetCore.Helpers +@using Bonobo.Git.Server +@using Bonobo.Git.Server.App_GlobalResources +@using Bonobo.Git.Server.Extensions; +@using Bonobo.Git.Server.Models +@using Microsoft.AspNetCore.Http +@model Bonobo.Git.Server.Models.UserDetailModelList +@inject IHttpContextAccessor HttpContextAccessor @{ ViewBag.Title = Resources.Account_Index_Title; } @@ -41,7 +47,7 @@ @{ - var grid = new WebGrid(source: Model, defaultSort: "Username", rowsPerPage: 15); + var grid = new WebGrid(HttpContextAccessor, source: Model, defaultSort: "Username", rowsPerPage: 15); @grid.GetHtml( tableStyle: "pure-table users", columns: grid.Columns( diff --git a/Bonobo.Git.Server/Views/Home/Error.cshtml b/Bonobo.Git.Server/Views/Home/Error.cshtml index 903f99d7d..a0ca3a2e2 100644 --- a/Bonobo.Git.Server/Views/Home/Error.cshtml +++ b/Bonobo.Git.Server/Views/Home/Error.cshtml @@ -1,4 +1,5 @@ -@{ +@using Bonobo.Git.Server.App_GlobalResources +@{ ViewBag.Title = Resources.Home_Error_Title; } diff --git a/Bonobo.Git.Server/Views/Home/ForgotPassword.cshtml b/Bonobo.Git.Server/Views/Home/ForgotPassword.cshtml index b5e42e547..3e997a141 100644 --- a/Bonobo.Git.Server/Views/Home/ForgotPassword.cshtml +++ b/Bonobo.Git.Server/Views/Home/ForgotPassword.cshtml @@ -1,4 +1,5 @@ -@model Bonobo.Git.Server.Models.ForgotPasswordModel +@using Bonobo.Git.Server.App_GlobalResources +@model Bonobo.Git.Server.Models.ForgotPasswordModel @{ ViewBag.Title = Resources.Home_ForgotPassword_Title; diff --git a/Bonobo.Git.Server/Views/Home/LogOn.cshtml b/Bonobo.Git.Server/Views/Home/LogOn.cshtml index 1a2e844e8..8e5816558 100644 --- a/Bonobo.Git.Server/Views/Home/LogOn.cshtml +++ b/Bonobo.Git.Server/Views/Home/LogOn.cshtml @@ -1,4 +1,5 @@ @using System.Collections.Concurrent +@using Bonobo.Git.Server.App_GlobalResources @model Bonobo.Git.Server.Models.LogOnModel @{ ViewBag.Title = @Resources.Home_LogOn_Title; diff --git a/Bonobo.Git.Server/Views/Home/PageNotFound.cshtml b/Bonobo.Git.Server/Views/Home/PageNotFound.cshtml index a21a4e013..684ea7278 100644 --- a/Bonobo.Git.Server/Views/Home/PageNotFound.cshtml +++ b/Bonobo.Git.Server/Views/Home/PageNotFound.cshtml @@ -1,4 +1,5 @@ -@{ +@using Bonobo.Git.Server.App_GlobalResources +@{ ViewBag.Title = Resources.Home_PageNotFound_Title; } diff --git a/Bonobo.Git.Server/Views/Home/ResetPassword.cshtml b/Bonobo.Git.Server/Views/Home/ResetPassword.cshtml index dd8f3f0f0..6e97c2a16 100644 --- a/Bonobo.Git.Server/Views/Home/ResetPassword.cshtml +++ b/Bonobo.Git.Server/Views/Home/ResetPassword.cshtml @@ -1,4 +1,5 @@ -@model Bonobo.Git.Server.Models.ResetPasswordModel +@using Bonobo.Git.Server.App_GlobalResources +@model Bonobo.Git.Server.Models.ResetPasswordModel @{ ViewBag.Title = Resources.Home_ResetPassword_Title; diff --git a/Bonobo.Git.Server/Views/Home/ServerError.cshtml b/Bonobo.Git.Server/Views/Home/ServerError.cshtml index 84d2a08a2..d334134f2 100644 --- a/Bonobo.Git.Server/Views/Home/ServerError.cshtml +++ b/Bonobo.Git.Server/Views/Home/ServerError.cshtml @@ -1,4 +1,5 @@ -@{ +@using Bonobo.Git.Server.App_GlobalResources +@{ ViewBag.Title = Resources.Home_ServerError_Title; } diff --git a/Bonobo.Git.Server/Views/Home/Unauthorized.cshtml b/Bonobo.Git.Server/Views/Home/Unauthorized.cshtml index 85b33008b..bd8632800 100644 --- a/Bonobo.Git.Server/Views/Home/Unauthorized.cshtml +++ b/Bonobo.Git.Server/Views/Home/Unauthorized.cshtml @@ -1,4 +1,5 @@ -@{ +@using Bonobo.Git.Server.App_GlobalResources +@{ ViewBag.Title = Resources.Home_Unauthorized_Title; } diff --git a/Bonobo.Git.Server/Views/Repository/Blame.cshtml b/Bonobo.Git.Server/Views/Repository/Blame.cshtml index e041fb96f..677b9c141 100644 --- a/Bonobo.Git.Server/Views/Repository/Blame.cshtml +++ b/Bonobo.Git.Server/Views/Repository/Blame.cshtml @@ -1,13 +1,15 @@ -@using Bonobo.Git.Server.Extensions -@model RepositoryBlameModel +@using Bonobo.Git.Server +@using Bonobo.Git.Server.App_GlobalResources +@using Bonobo.Git.Server.Helpers +@model Bonobo.Git.Server.Models.RepositoryBlameModel @{ Layout = "~/Views/Repository/_RepositoryLayout.cshtml"; ViewBag.Title = Resources.Repository_Blame_Title; } @if (Model != null) { - @Html.Partial("_BranchSwitcher") - @Html.Partial("_AddressBar") + @await Html.PartialAsync("_BranchSwitcher") + @await Html.PartialAsync("_AddressBar")
@{ @@ -36,7 +38,7 @@ @if (i == 0) { - @Html.Partial("_Commit", hunk.Commit) + @await Html.PartialAsync("_Commit", hunk.Commit) } diff --git a/Bonobo.Git.Server/Views/Repository/Blob.cshtml b/Bonobo.Git.Server/Views/Repository/Blob.cshtml index ed5763cbe..36f264098 100644 --- a/Bonobo.Git.Server/Views/Repository/Blob.cshtml +++ b/Bonobo.Git.Server/Views/Repository/Blob.cshtml @@ -1,13 +1,16 @@ -@using Bonobo.Git.Server.Extensions -@model RepositoryTreeDetailModel +@using Bonobo.Git.Server +@using Bonobo.Git.Server.App_GlobalResources +@using Bonobo.Git.Server.Extensions +@using Bonobo.Git.Server.Helpers +@model Bonobo.Git.Server.Models.RepositoryTreeDetailModel @{ Layout = "~/Views/Repository/_RepositoryLayout.cshtml"; ViewBag.Title = Resources.Repository_Tree_Title; } @if (Model != null) { - @Html.Partial("_BranchSwitcher") - @Html.Partial("_AddressBar") + @await Html.PartialAsync("_BranchSwitcher") + @await Html.PartialAsync("_AddressBar")
@{ diff --git a/Bonobo.Git.Server/Views/Repository/Clone.cshtml b/Bonobo.Git.Server/Views/Repository/Clone.cshtml index c6b60d744..dd7626739 100644 --- a/Bonobo.Git.Server/Views/Repository/Clone.cshtml +++ b/Bonobo.Git.Server/Views/Repository/Clone.cshtml @@ -1,15 +1,16 @@ -@using MvcCheckBoxList.Model -@model RepositoryDetailModel +@using Bonobo.Git.Server.App_GlobalResources +@using Bonobo.Git.Server.Helpers +@model Bonobo.Git.Server.Models.RepositoryDetailModel @{ ViewBag.Title = Resources.Repository_Clone_Title; }

@Resources.Repository_Clone_Title

-@using (Html.BeginForm("Clone", "Repository", new { id = ViewBag.ID }, FormMethod.Post, new { @class = "pure-form pure-form-aligned" })) -{ +@using (Html.BeginForm("Clone", "Repository", new { id = ViewBag.ID }, FormMethod.Post, true, new { @class = "pure-form pure-form-aligned" })) +{ @Html.AntiForgeryToken() @Html.ValidationSummary(false, Resources.Repository_Clone_Fail) - +
@Html.LabelFor(m => m.Name) @@ -32,7 +33,7 @@
@Html.LabelFor(m => m.Users) - @Html.CheckBoxListFor(m => m.PostedSelectedUsers, mm => mm.AllUsers, mm => mm.Id, mm => mm.DisplayName, mm => mm.Users, Position.Vertical) + @Html.CheckBoxListFor(m => m.PostedSelectedUsers, mm => mm.AllUsers, mm => mm.Id, mm => mm.DisplayName, mm => mm.Users)
@@ -40,7 +41,7 @@
@Html.LabelFor(m => m.Administrators) - @Html.CheckBoxListFor(m => m.PostedSelectedAdministrators, mm => mm.AllAdministrators, mm => mm.Id, mm => mm.DisplayName, mm => mm.Administrators, Position.Vertical) + @Html.CheckBoxListFor(m => m.PostedSelectedAdministrators, mm => mm.AllAdministrators, mm => mm.Id, mm => mm.DisplayName, mm => mm.Administrators) @Html.ValidationMessageFor(m => m.Administrators) @@ -49,7 +50,7 @@
@Html.LabelFor(m => m.Teams) - @Html.CheckBoxListFor(m => m.PostedSelectedTeams, mm => mm.AllTeams, mm => mm.Id, mm => mm.DisplayName, mm => mm.Teams, Position.Vertical) + @Html.CheckBoxListFor(m => m.PostedSelectedTeams, mm => mm.AllTeams, mm => mm.Id, mm => mm.DisplayName, mm => mm.Teams)
diff --git a/Bonobo.Git.Server/Views/Repository/Commit.cshtml b/Bonobo.Git.Server/Views/Repository/Commit.cshtml index ae3a2f075..ad4e56cac 100644 --- a/Bonobo.Git.Server/Views/Repository/Commit.cshtml +++ b/Bonobo.Git.Server/Views/Repository/Commit.cshtml @@ -1,56 +1,60 @@ -@model RepositoryCommitModel +@model Bonobo.Git.Server.Models.RepositoryCommitModel +@using Bonobo.Git.Server.App_GlobalResources @using Bonobo.Git.Server.Extensions +@using Bonobo.Git.Server.Helpers +@using Bonobo.Git.Server.Models +@using Microsoft.AspNetCore.Html @{ ViewBag.Title = Resources.Repository_Commit_Detail; Layout = "~/Views/Repository/_RepositoryLayout.cshtml"; } -@helper HeaderForDiff(RepositoryCommitChangeModel item) -{ -
-

- - @if (item.Status == LibGit2Sharp.ChangeKind.Added) - { - - } - else if (item.Status == LibGit2Sharp.ChangeKind.Modified) - { - - } - else if (item.Status == LibGit2Sharp.ChangeKind.Deleted) - { - - } - else if (item.Status == LibGit2Sharp.ChangeKind.Renamed) - { - - } - else if (item.Status == LibGit2Sharp.ChangeKind.Copied) - { - - } - else if (item.Status == LibGit2Sharp.ChangeKind.TypeChanged) - { - - } - @if (item.Status != LibGit2Sharp.ChangeKind.Deleted) - { - @Html.ActionLink(item.Path, "Blob", new { id = ViewBag.ID, encodedPath = PathEncoder.Encode(item.Path, allowSlash: true), encodedName = PathEncoder.Encode(Model.ID) }) - } - else - { - @item.Path - } - @item.LinesChanged(+@item.LinesAdded -@item.LinesDeleted) +@{ + Func HeaderForDiff = + @

+

+ + @if (item.Status == LibGit2Sharp.ChangeKind.Added) + { + + } + else if (item.Status == LibGit2Sharp.ChangeKind.Modified) + { + + } + else if (item.Status == LibGit2Sharp.ChangeKind.Deleted) + { + + } + else if (item.Status == LibGit2Sharp.ChangeKind.Renamed) + { + + } + else if (item.Status == LibGit2Sharp.ChangeKind.Copied) + { + + } + else if (item.Status == LibGit2Sharp.ChangeKind.TypeChanged) + { + + } + @if (item.Status != LibGit2Sharp.ChangeKind.Deleted) + { + @Html.ActionLink(item.Path, "Blob", new { id = ViewBag.ID, encodedPath = PathEncoder.Encode(item.Path, allowSlash: true), encodedName = PathEncoder.Encode(Model.ID) }) + } + else + { + @item.Path + } + @item.LinesChanged(+@item.LinesAdded -@item.LinesDeleted) -

-
+

+
; } @if (Model != null) {
- @Html.Partial("_Commit", Model) + @await Html.PartialAsync("_Commit", Model)

@Model.GetType().GetDisplayValue("Changes")

diff --git a/Bonobo.Git.Server/Views/Repository/Commits.cshtml b/Bonobo.Git.Server/Views/Repository/Commits.cshtml index 5608a4b64..cbb1ced55 100644 --- a/Bonobo.Git.Server/Views/Repository/Commits.cshtml +++ b/Bonobo.Git.Server/Views/Repository/Commits.cshtml @@ -1,5 +1,9 @@ -@using Bonobo.Git.Server.Extensions -@model RepositoryCommitsModel +@using AndreyKurdiumov.AspNetCore.Helpers +@using Bonobo.Git.Server.App_GlobalResources +@using Bonobo.Git.Server.Models +@using Microsoft.AspNetCore.Http +@model Bonobo.Git.Server.Models.RepositoryCommitsModel +@inject IHttpContextAccessor HttpContextAccessor @{ Layout = "~/Views/Repository/_RepositoryLayout.cshtml"; ViewBag.Title = Resources.Repository_Commits_Title; @@ -10,7 +14,7 @@ @Html.Partial("_BranchSwitcher") @if (Model.Commits != null) { - var grid = new WebGrid(rowsPerPage: 10, canPage:true, canSort:false); + var grid = new WebGrid(HttpContextAccessor, rowsPerPage: 10, canPage:true, canSort:false); grid.Bind(Model.Commits, null, false, (int)(ViewBag.TotalCount ?? 0)); @grid.GetHtml(displayHeader: false, mode: WebGridPagerModes.All, columns: grid.Columns( diff --git a/Bonobo.Git.Server/Views/Repository/Create.cshtml b/Bonobo.Git.Server/Views/Repository/Create.cshtml index fcd08ba83..c1b405a19 100644 --- a/Bonobo.Git.Server/Views/Repository/Create.cshtml +++ b/Bonobo.Git.Server/Views/Repository/Create.cshtml @@ -1,5 +1,6 @@ -@using Bonobo.Git.Server.Extensions -@using MvcCheckBoxList.Model +@using Bonobo.Git.Server.App_GlobalResources +@using Bonobo.Git.Server.Extensions +@using Bonobo.Git.Server.Helpers @model Bonobo.Git.Server.Models.RepositoryDetailModel @{ ViewBag.Title = Resources.Repository_Create_Title; @@ -10,11 +11,11 @@ { @Html.AntiForgeryToken() @Html.ValidationSummary(false, Resources.Repository_Create_Fail) - +
@Html.LabelFor(m => m.Name) - @Html.TextBoxFor(m => m.Name, new {autofocus = ""})* + @Html.TextBoxFor(m => m.Name, new { autofocus = "" })* @Html.ValidationMessageFor(m => m.Name)
@@ -31,23 +32,24 @@ .png, .jpg, .jpeg, .gif
-
- @Html.LabelFor(m => m.AllowAnonymous) - @Html.CheckBoxFor(m => m.AllowAnonymous, new { @onClick = "document.getElementById('AllowAnonymousPush').disabled = !this.checked" }) - -
+
+ @Html.LabelFor(m => m.AllowAnonymous) + @Html.CheckBoxFor(m => m.AllowAnonymous, new { @onClick = "document.getElementById('AllowAnonymousPush').disabled = !this.checked" }) + +
-
- @Html.LabelFor(m => m.AllowAnonymousPush) - @{ - object attribs = new { @id = "AllowAnonymousPush" }; - if (!Model.AllowAnonymous){ - attribs = new { @id = "AllowAnonymousPush", @disabled = "" }; - } +
+ @Html.LabelFor(m => m.AllowAnonymousPush) + @{ + object attribs = new { @id = "AllowAnonymousPush" }; + if (!Model.AllowAnonymous) + { + attribs = new { @id = "AllowAnonymousPush", @disabled = "" }; } - @Html.EnumDropDownListFor(m => m.AllowAnonymousPush, attribs) - -
+ } + @Html.DropDownListFor(m => m.AllowAnonymousPush, Html.GetEnumSelectList(Model.AllowAnonymousPush.GetType()), attribs) + +
@Html.LabelFor(m => m.LinksUseGlobal) @Html.CheckBoxFor(m => m.LinksUseGlobal, new { @onClick = "document.getElementById('LinksRegex').disabled = this.checked; document.getElementById('LinksUrl').disabled = this.checked" }) @@ -56,7 +58,8 @@ @Html.LabelFor(m => m.LinksRegex) @{ attribs = new { @class = "medium" }; - if (Model.LinksUseGlobal){ + if (Model.LinksUseGlobal) + { attribs = new { @class = "medium", disabled = "" }; } @Html.TextBoxFor(m => m.LinksRegex, attribs); @@ -68,36 +71,36 @@ @Html.TextBoxFor(m => m.LinksUrl, attribs)
-
- @Html.LabelFor(m => m.Users) - - @Html.CheckBoxListFor(m => m.PostedSelectedUsers, mm => mm.AllUsers, mm => mm.Id, mm => mm.DisplayName, mm => mm.Users, Position.Vertical) - - -
+
+ @Html.LabelFor(m => m.Users) + + @Html.CheckBoxListFor(m => m.PostedSelectedUsers, mm => mm.AllUsers, mm => mm.Id, mm => mm.DisplayName, mm => mm.Users) + + +
-
- @Html.LabelFor(m => m.Administrators) - - @Html.CheckBoxListFor(m => m.PostedSelectedAdministrators, mm => mm.AllAdministrators, mm => mm.Id, mm => mm.DisplayName, mm => mm.Administrators, Position.Vertical) - - @Html.ValidationMessageFor(m => m.Administrators) - -
+
+ @Html.LabelFor(m => m.Administrators) + + @Html.CheckBoxListFor(m => m.PostedSelectedAdministrators, mm => mm.AllAdministrators, mm => mm.Id, mm => mm.DisplayName, mm => mm.Administrators) + + @Html.ValidationMessageFor(m => m.Administrators) + +
-
- @Html.LabelFor(m => m.Teams) - - @Html.CheckBoxListFor(m => m.PostedSelectedTeams, mm => mm.AllTeams, mm => mm.Id, mm => mm.DisplayName, mm => mm.Teams, Position.Vertical) - - -
+
+ @Html.LabelFor(m => m.Teams) + + @Html.CheckBoxListFor(m => m.PostedSelectedTeams, mm => mm.AllTeams, mm => mm.Id, mm => mm.DisplayName, mm => mm.Teams) + + +
-
- @Resources.Repository_Back - -
-
+
+ @Resources.Repository_Back + +
+
} diff --git a/Bonobo.Git.Server/Views/Repository/Delete.cshtml b/Bonobo.Git.Server/Views/Repository/Delete.cshtml index 1795ad478..91e094b29 100644 --- a/Bonobo.Git.Server/Views/Repository/Delete.cshtml +++ b/Bonobo.Git.Server/Views/Repository/Delete.cshtml @@ -1,4 +1,5 @@ -@model Bonobo.Git.Server.Models.RepositoryDetailModel +@using Bonobo.Git.Server.App_GlobalResources +@model Bonobo.Git.Server.Models.RepositoryDetailModel @{ ViewBag.Title = Resources.Delete_Title; } diff --git a/Bonobo.Git.Server/Views/Repository/Detail.cshtml b/Bonobo.Git.Server/Views/Repository/Detail.cshtml index bece77225..2e09a0f0d 100644 --- a/Bonobo.Git.Server/Views/Repository/Detail.cshtml +++ b/Bonobo.Git.Server/Views/Repository/Detail.cshtml @@ -1,4 +1,7 @@ -@model Bonobo.Git.Server.Models.RepositoryDetailModel +@using Bonobo.Git.Server.App_GlobalResources +@using Bonobo.Git.Server.Configuration +@using Bonobo.Git.Server.Models +@model Bonobo.Git.Server.Models.RepositoryDetailModel @{ Layout = "~/Views/Repository/_RepositoryLayout.cshtml"; ViewBag.Title = Resources.Repository_Detail_Title; @@ -60,7 +63,7 @@
@Html.LabelFor(m => m.AllowAnonymousPush) - @Html.DisplayEnum(Model.AllowAnonymousPush) + @Html.DisplayFor(m => m.AllowAnonymousPush)
diff --git a/Bonobo.Git.Server/Views/Repository/Edit.cshtml b/Bonobo.Git.Server/Views/Repository/Edit.cshtml index 2c3d32337..33bfc5f1e 100644 --- a/Bonobo.Git.Server/Views/Repository/Edit.cshtml +++ b/Bonobo.Git.Server/Views/Repository/Edit.cshtml @@ -1,5 +1,6 @@ -@using Bonobo.Git.Server.Extensions -@using MvcCheckBoxList.Model +@using Bonobo.Git.Server.App_GlobalResources +@using Bonobo.Git.Server.Configuration +@using Bonobo.Git.Server.Helpers @model Bonobo.Git.Server.Models.RepositoryDetailModel @{ @@ -8,7 +9,7 @@ @if (Model == null) { - @Html.Partial("~/Views/Shared/_ItemNotFound.cshtml") + @await Html.PartialAsync("~/Views/Shared/_ItemNotFound.cshtml") } else { @@ -70,7 +71,7 @@ else attribs = new { @id = "AllowAnonymousPush", @disabled = "" }; } } - @Html.EnumDropDownListFor(m => m.AllowAnonymousPush, attribs) + @Html.DropDownListFor(m => m.AllowAnonymousPush, Html.GetEnumSelectList(Model.AllowAnonymousPush.GetType()), attribs)
@@ -105,7 +106,7 @@ else
@Html.LabelFor(m => m.Users) - @Html.CheckBoxListFor(m => m.PostedSelectedUsers, m => m.AllUsers, m => m.Id, m => m.DisplayName, m => m.Users, Position.Vertical) + @Html.CheckBoxListFor(m => m.PostedSelectedUsers, m => m.AllUsers, m => m.Id, m => m.DisplayName, m => m.Users)
@@ -115,7 +116,7 @@ else
@Html.LabelFor(m => m.Administrators) - @Html.CheckBoxListFor(m => m.PostedSelectedAdministrators, m => m.AllAdministrators, m => m.Id, m => m.DisplayName, m => m.Administrators, Position.Vertical) + @Html.CheckBoxListFor(m => m.PostedSelectedAdministrators, m => m.AllAdministrators, m => m.Id, m => m.DisplayName, m => m.Administrators) @Html.ValidationMessageFor(m => m.Administrators) @@ -124,7 +125,7 @@ else
@Html.LabelFor(m => m.Teams) - @Html.CheckBoxListFor(m => m.PostedSelectedTeams, m => m.AllTeams, mm => mm.Id, mm => mm.DisplayName, mm => mm.Teams, Position.Vertical) + @Html.CheckBoxListFor(m => m.PostedSelectedTeams, m => m.AllTeams, mm => mm.Id, mm => mm.DisplayName, mm => mm.Teams)
diff --git a/Bonobo.Git.Server/Views/Repository/History.cshtml b/Bonobo.Git.Server/Views/Repository/History.cshtml index 4cfc6f452..2f534af76 100644 --- a/Bonobo.Git.Server/Views/Repository/History.cshtml +++ b/Bonobo.Git.Server/Views/Repository/History.cshtml @@ -1,5 +1,9 @@ -@using Bonobo.Git.Server.Extensions -@model RepositoryCommitsModel +@using AndreyKurdiumov.AspNetCore.Helpers +@using Bonobo.Git.Server.App_GlobalResources +@using Bonobo.Git.Server.Models +@using Microsoft.AspNetCore.Http +@model Bonobo.Git.Server.Models.RepositoryCommitsModel +@inject IHttpContextAccessor HttpContextAccessor @{ Layout = "~/Views/Repository/_RepositoryLayout.cshtml"; ViewBag.Title = Resources.Repository_History_Title; @@ -9,7 +13,7 @@
@if (Model.Commits != null) { - var grid = new WebGrid(source: Model.Commits, rowsPerPage: 10, canPage: true, canSort: false); + var grid = new WebGrid(HttpContextAccessor, source: Model.Commits, rowsPerPage: 10, canPage: true, canSort: false); @grid.GetHtml(displayHeader: false, mode: WebGridPagerModes.All, columns: grid.Columns( grid.Column(format: item => Html.Partial("_Commit", (RepositoryCommitModel)item.Value)) diff --git a/Bonobo.Git.Server/Views/Repository/Index.cshtml b/Bonobo.Git.Server/Views/Repository/Index.cshtml index cf827367b..4f81aa793 100644 --- a/Bonobo.Git.Server/Views/Repository/Index.cshtml +++ b/Bonobo.Git.Server/Views/Repository/Index.cshtml @@ -1,7 +1,13 @@ -@using Bonobo.Git.Server.Extensions -@using System.Web.Mvc.Html +@using System.Web.WebPages +@using AndreyKurdiumov.AspNetCore.Helpers +@using Bonobo.Git.Server +@using Bonobo.Git.Server.App_GlobalResources +@using Bonobo.Git.Server.Configuration +@using Bonobo.Git.Server.Extensions @using Bonobo.Git.Server.Models @using Bonobo.Git.Server.Data +@using Microsoft.AspNetCore.Http +@inject IHttpContextAccessor HttpContextAccessor @model Dictionary @{ @@ -35,7 +41,7 @@
@{ - var sortGroupQuery = Request.QueryString["sortGroup"]; + var sortGroupQuery = HttpContextAccessor.HttpContext.Request.Query["sortGroup"]; var sortGroup = new { @@ -66,7 +72,7 @@ if (RepoNotFound) {
- @Html.Partial("~/Views/Shared/_ItemNotFound.cshtml") + @await Html.PartialAsync("~/Views/Shared/_ItemNotFound.cshtml")
} } @@ -90,13 +96,13 @@
} -@using (Html.BeginForm(null, null, FormMethod.Post, new { @class = "pure-form" })) -{ +

@Html.TextBox("SearchString")

-} +
+
@{ @@ -116,7 +122,7 @@ // https://dusted.codes/making-font-awesome-awesome-using-icons-without-i-tags
@{ - var permitted = new WebGrid(source: model.Value, defaultSort: "Name", rowsPerPage: 15); + var permitted = new WebGrid(HttpContextAccessor, source: model.Value, defaultSort: "Name", rowsPerPage: 15); var columns = new List(); @@ -141,9 +147,9 @@ if (User.IsInRole(Definitions.Roles.Administrator)) { columns.Add(permitted.Column( - format: (item) => + format: (itemm) => { - var repo = (RepositoryDetailModel)item.Value; + var repo = (RepositoryDetailModel)itemm.Value; var anonColor = repo.AllowAnonymous ? "rgba(0, 120, 230, 1)" : "lightblue"; var anonTitle = Resources.Repository_Detail_Anonymous + ": " + (repo.AllowAnonymous ? Resources.Yes : Resources.No); @@ -165,8 +171,8 @@ } columns.Add(permitted.Column("Description", typeof(RepositoryDetailModel).GetDisplayValue("Description"), format: (item) => ((item.Description != null && ((string)item.Description).Length > 100)) ? ((string)item.Description).Substring(0, 100) + " ... " : item.Description, style: "description")); - columns.Add(permitted.Column(format: (item) => Html.Raw(""), style: "action")); - columns.Add(permitted.Column(format: (item) => Html.Raw(""), style: "action")); + columns.Add(permitted.Column(format: (item) => Html.Raw(""), style: "action")); + columns.Add(permitted.Column(format: (item) => Html.Raw(""), style: "action")); columns.Add(permitted.Column(format: (item) => Html.ActionLink(" ", "Edit", new { id = item.Id }, new { @class = "edit", title = Resources.Grid_Edit }), style: "action")); columns.Add(permitted.Column(format: (item) => Html.ActionLink(" ", "Delete", new { id = item.Id }, new { @class = "delete", title = Resources.Grid_Delete }), style: "action")); diff --git a/Bonobo.Git.Server/Views/Repository/Tags.cshtml b/Bonobo.Git.Server/Views/Repository/Tags.cshtml index e1b27c714..063075679 100644 --- a/Bonobo.Git.Server/Views/Repository/Tags.cshtml +++ b/Bonobo.Git.Server/Views/Repository/Tags.cshtml @@ -1,5 +1,9 @@ -@using Bonobo.Git.Server.Extensions -@model RepositoryCommitsModel +@using AndreyKurdiumov.AspNetCore.Helpers +@using Bonobo.Git.Server.App_GlobalResources +@using Bonobo.Git.Server.Models +@using Microsoft.AspNetCore.Http +@model Bonobo.Git.Server.Models.RepositoryCommitsModel +@inject IHttpContextAccessor HttpContextAccessor @{ Layout = "~/Views/Repository/_RepositoryLayout.cshtml"; ViewBag.Title = Resources.Repository_Tags_Title; @@ -7,10 +11,10 @@ @if (Model != null) {
- @Html.Partial("_BranchSwitcher") + @await Html.PartialAsync("_BranchSwitcher") @if (Model.Commits != null) { - var grid = new WebGrid(rowsPerPage: 10, canPage:true, canSort:false); + var grid = new WebGrid(HttpContextAccessor, rowsPerPage: 10, canPage:true, canSort:false); grid.Bind(Model.Commits, null, false, (int)(ViewBag.TotalCount ?? 0)); @grid.GetHtml(displayHeader: false, mode: WebGridPagerModes.All, columns: grid.Columns( diff --git a/Bonobo.Git.Server/Views/Repository/Tree.cshtml b/Bonobo.Git.Server/Views/Repository/Tree.cshtml index 300ab598c..58a46853e 100644 --- a/Bonobo.Git.Server/Views/Repository/Tree.cshtml +++ b/Bonobo.Git.Server/Views/Repository/Tree.cshtml @@ -1,5 +1,8 @@ -@using Bonobo.Git.Server.Extensions -@model RepositoryTreeModel +@using Bonobo.Git.Server.App_GlobalResources +@using Bonobo.Git.Server.Extensions +@using Bonobo.Git.Server.Helpers +@using Bonobo.Git.Server.Models +@model Bonobo.Git.Server.Models.RepositoryTreeModel @{ Layout = "~/Views/Repository/_RepositoryLayout.cshtml"; ViewBag.Title = Resources.Repository_Tree_Title; @@ -7,8 +10,8 @@ @if (Model != null) {
- @Html.Partial("_BranchSwitcher") - @Html.Partial("_AddressBar") + @await Html.PartialAsync("_BranchSwitcher") + @await Html.PartialAsync("_AddressBar") diff --git a/Bonobo.Git.Server/Views/Repository/_AddressBar.cshtml b/Bonobo.Git.Server/Views/Repository/_AddressBar.cshtml index b7e2635c9..5615297ec 100644 --- a/Bonobo.Git.Server/Views/Repository/_AddressBar.cshtml +++ b/Bonobo.Git.Server/Views/Repository/_AddressBar.cshtml @@ -1,4 +1,6 @@ -@{ +@using Bonobo.Git.Server.App_GlobalResources +@using Bonobo.Git.Server.Helpers +@{ var path = ViewData["path"] as string;

diff --git a/Bonobo.Git.Server/Views/Repository/_RepositoryLayout.cshtml b/Bonobo.Git.Server/Views/Repository/_RepositoryLayout.cshtml index 624c8916a..ffc33539e 100644 --- a/Bonobo.Git.Server/Views/Repository/_RepositoryLayout.cshtml +++ b/Bonobo.Git.Server/Views/Repository/_RepositoryLayout.cshtml @@ -1,9 +1,10 @@ -@{ +@using Bonobo.Git.Server.App_GlobalResources +@{ Layout = "~/Views/Shared/_Layout.cshtml"; } @if (Model == null) { - @Html.Partial("~/Views/Shared/_ItemNotFound.cshtml") + @await Html.PartialAsync("~/Views/Shared/_ItemNotFound.cshtml") } else { diff --git a/Bonobo.Git.Server/Views/Repository/_Tag.cshtml b/Bonobo.Git.Server/Views/Repository/_Tag.cshtml index 5275ad315..1a7edfa87 100644 --- a/Bonobo.Git.Server/Views/Repository/_Tag.cshtml +++ b/Bonobo.Git.Server/Views/Repository/_Tag.cshtml @@ -1,6 +1,7 @@ -@model RepositoryCommitModel -@using System.Globalization +@model Bonobo.Git.Server.Models.RepositoryCommitModel +@using Bonobo.Git.Server.Configuration @using Bonobo.Git.Server.Extensions +@using Bonobo.Git.Server.Helpers
@foreach (var stag in Model.Tags) { diff --git a/Bonobo.Git.Server/Views/Settings/Index.cshtml b/Bonobo.Git.Server/Views/Settings/Index.cshtml index d3f40fddd..53e6c128c 100644 --- a/Bonobo.Git.Server/Views/Settings/Index.cshtml +++ b/Bonobo.Git.Server/Views/Settings/Index.cshtml @@ -1,4 +1,5 @@ @using System.Globalization +@using Bonobo.Git.Server.App_GlobalResources @using Bonobo.Git.Server.Extensions @model Bonobo.Git.Server.Models.GlobalSettingsModel @{ diff --git a/Bonobo.Git.Server/Views/Shared/_ItemNotFound.cshtml b/Bonobo.Git.Server/Views/Shared/_ItemNotFound.cshtml index 276a53bea..4d23ce3dd 100644 --- a/Bonobo.Git.Server/Views/Shared/_ItemNotFound.cshtml +++ b/Bonobo.Git.Server/Views/Shared/_ItemNotFound.cshtml @@ -1,4 +1,5 @@ -

@Resources.Item_NotFound

+@using Bonobo.Git.Server.App_GlobalResources +

@Resources.Item_NotFound

@Resources.Item_NotFound_Text

diff --git a/Bonobo.Git.Server/Views/Shared/_Layout.cshtml b/Bonobo.Git.Server/Views/Shared/_Layout.cshtml index 3faa30a1d..bd3acc50b 100644 --- a/Bonobo.Git.Server/Views/Shared/_Layout.cshtml +++ b/Bonobo.Git.Server/Views/Shared/_Layout.cshtml @@ -1,34 +1,41 @@ - +@using Bonobo.Git.Server +@using Bonobo.Git.Server.Helpers +@using Bonobo.Git.Server.App_GlobalResources +@using Bonobo.Git.Server.Configuration +@using Microsoft.AspNetCore.Http +@using Microsoft.AspNetCore.Routing +@inject IHttpContextAccessor HttpContextAccessor + @ViewBag.Title :: @UserConfiguration.Current.GetSiteTitle() - @Styles.Render("~/Content/bundledCss") + @if (UserConfiguration.Current.HasCustomSiteCss) { } @if (UserConfiguration.Current.HasCustomSiteLogo) { - + } - +
- @Scripts.Render("~/bundledJs") + @RenderSection("scripts", required: false) diff --git a/Bonobo.Git.Server/Views/Team/Create.cshtml b/Bonobo.Git.Server/Views/Team/Create.cshtml index e719000f0..23ab9b64f 100644 --- a/Bonobo.Git.Server/Views/Team/Create.cshtml +++ b/Bonobo.Git.Server/Views/Team/Create.cshtml @@ -1,6 +1,7 @@ -@using MvcCheckBoxList.Model +@using Bonobo.Git.Server.App_GlobalResources +@using Bonobo.Git.Server.Helpers @model Bonobo.Git.Server.Models.TeamEditModel -@{ +@{ ViewBag.Title = Resources.Team_Create_Title; }

@Resources.Team_Create_Title

@@ -9,21 +10,21 @@ { @Html.AntiForgeryToken() @Html.ValidationSummary(false, Resources.Team_Create_Fail) - +
@Html.LabelFor(m => m.Name) @Html.TextBoxFor(m => m.Name, new { autofocus = "" })* @Html.ValidationMessageFor(m => m.Name) -
+
@Html.LabelFor(m => m.Description) @Html.TextAreaFor(m => m.Description, new { @class = "medium" }) -
+
@Html.LabelFor(m => m.AllUsers) - @Html.CheckBoxListFor(m => m.PostedSelectedUsers, m => m.AllUsers, m => m.Id, m => m.DisplayName, m => m.SelectedUsers, Position.Vertical) + @Html.CheckBoxListFor(m => m.PostedSelectedUsers, m => m.AllUsers, m => m.Id, m => m.DisplayName, m => m.SelectedUsers)
@@ -31,5 +32,5 @@ @Resources.Team_Create_Back

- + } diff --git a/Bonobo.Git.Server/Views/Team/Delete.cshtml b/Bonobo.Git.Server/Views/Team/Delete.cshtml index 031558187..d6faf4f12 100644 --- a/Bonobo.Git.Server/Views/Team/Delete.cshtml +++ b/Bonobo.Git.Server/Views/Team/Delete.cshtml @@ -1,4 +1,5 @@ -@model Bonobo.Git.Server.Models.TeamEditModel +@using Bonobo.Git.Server.App_GlobalResources +@model Bonobo.Git.Server.Models.TeamEditModel @{ ViewBag.Title = Resources.Delete_Title; } diff --git a/Bonobo.Git.Server/Views/Team/Detail.cshtml b/Bonobo.Git.Server/Views/Team/Detail.cshtml index cfd8b7898..0e7871846 100644 --- a/Bonobo.Git.Server/Views/Team/Detail.cshtml +++ b/Bonobo.Git.Server/Views/Team/Detail.cshtml @@ -1,10 +1,12 @@ -@model Bonobo.Git.Server.Models.TeamDetailModel +@using Bonobo.Git.Server +@using Bonobo.Git.Server.App_GlobalResources +@model Bonobo.Git.Server.Models.TeamDetailModel @{ ViewBag.Title = Resources.Team_Detail_Title; } @if (Model == null) { - @Html.Partial("~/Views/Shared/_ItemNotFound.cshtml") + @await Html.PartialAsync("~/Views/Shared/_ItemNotFound.cshtml") } else { diff --git a/Bonobo.Git.Server/Views/Team/Edit.cshtml b/Bonobo.Git.Server/Views/Team/Edit.cshtml index 4621c8653..a803e4386 100644 --- a/Bonobo.Git.Server/Views/Team/Edit.cshtml +++ b/Bonobo.Git.Server/Views/Team/Edit.cshtml @@ -1,51 +1,52 @@ -@using MvcCheckBoxList.Model +@using Bonobo.Git.Server.App_GlobalResources +@using Bonobo.Git.Server.Helpers @model Bonobo.Git.Server.Models.TeamEditModel @{ ViewBag.Title = Resources.Team_Edit_Title; } @if (Model == null) -{ - @Html.Partial("~/Views/Shared/_ItemNotFound.cshtml") +{ + @await Html.PartialAsync("~/Views/Shared/_ItemNotFound.cshtml") } else { -

@Model.Name

- - @if (ViewBag.UpdateSuccess != null && ViewBag.UpdateSuccess) - { -
-

@Resources.Team_Edit_UpdateSuccess

-
- } +

@Model.Name

- @using (Html.BeginForm("Edit", "Team", FormMethod.Post, new { @class = "pure-form pure-form-aligned" })) - { - @Html.AntiForgeryToken() - @Html.ValidationSummary(false, Resources.Team_Edit_Failure) - @Html.HiddenFor(m => m.Id) - -
-
- @Html.LabelFor(m => m.Name) - @Html.TextBoxFor(m => m.Name, new { @class = "textInput medium", autofocus = ""})* - @Html.ValidationMessageFor(m => m.Name) -
-
- @Html.LabelFor(m => m.Description) - @Html.TextAreaFor(m => m.Description, new { @class = "textInput medium", autofocus = "" }) -
-
- @Html.LabelFor(m => m.AllUsers) - - @Html.CheckBoxListFor(m => m.PostedSelectedUsers, m => m.AllUsers, m => m.Id, m => m.DisplayName, m => m.SelectedUsers, Position.Vertical) - + @if (ViewBag.UpdateSuccess != null && ViewBag.UpdateSuccess) + { +
+

@Resources.Team_Edit_UpdateSuccess

-
- @Resources.Team_Edit_Back - -
-
- } + } + + @using (Html.BeginForm("Edit", "Team", FormMethod.Post, new { @class = "pure-form pure-form-aligned" })) + { + @Html.AntiForgeryToken() + @Html.ValidationSummary(false, Resources.Team_Edit_Failure) + @Html.HiddenFor(m => m.Id) + +
+
+ @Html.LabelFor(m => m.Name) + @Html.TextBoxFor(m => m.Name, new { @class = "textInput medium", autofocus = "" })* + @Html.ValidationMessageFor(m => m.Name) +
+
+ @Html.LabelFor(m => m.Description) + @Html.TextAreaFor(m => m.Description, new { @class = "textInput medium", autofocus = "" }) +
+
+ @Html.LabelFor(m => m.AllUsers) + + @Html.CheckBoxListFor(m => m.PostedSelectedUsers, m => m.AllUsers, m => m.Id, m => m.DisplayName, m => m.SelectedUsers) + +
+
+ @Resources.Team_Edit_Back + +
+
+ }
} diff --git a/Bonobo.Git.Server/Views/Team/Index.cshtml b/Bonobo.Git.Server/Views/Team/Index.cshtml index 79bff4ade..c016a0a6d 100644 --- a/Bonobo.Git.Server/Views/Team/Index.cshtml +++ b/Bonobo.Git.Server/Views/Team/Index.cshtml @@ -1,5 +1,10 @@ -@using Bonobo.Git.Server.Extensions; -@model TeamDetailModelList +@using AndreyKurdiumov.AspNetCore.Helpers +@using Bonobo.Git.Server.App_GlobalResources +@using Bonobo.Git.Server.Extensions; +@using Bonobo.Git.Server.Models +@using Microsoft.AspNetCore.Http +@model Bonobo.Git.Server.Models.TeamDetailModelList +@inject IHttpContextAccessor HttpContextAccessor @{ ViewBag.Title = Resources.Team_Index_Title; } @@ -30,7 +35,7 @@ } @{ - var grid = new WebGrid(source: Model, defaultSort: "Name", rowsPerPage: 15); + var grid = new WebGrid(HttpContextAccessor, source: Model, defaultSort: "Name", rowsPerPage: 15); }
diff --git a/Bonobo.Git.Server/bundleconfig.json b/Bonobo.Git.Server/bundleconfig.json new file mode 100644 index 000000000..08dd3ae0b --- /dev/null +++ b/Bonobo.Git.Server/bundleconfig.json @@ -0,0 +1,22 @@ +[ + { + "outputFileName": "wwwroot/bundle.js", + "inputFiles": [ + "Scripts/jquery-1.12.4.js", + "Scripts/jquery.validate.js", + "Content/uni/js/uni-form-validation.jquery.js", + "Scripts/MicrosoftAjax.js", + "Scripts/MicrosoftMvcAjax.js" + ] + }, + { + "outputFileName": "wwwroot/bundle.css", + "inputFiles": [ + "Content/components/pure/pure-min.css", + "Content/components/font-awesome/css/font-awesome.min.css", + "Content/components/highlight/styles/github.css", + "Content/fonts.css", + "Content/site.css" + ] + } +] \ No newline at end of file diff --git a/Bonobo.Git.Server/packages.config b/Bonobo.Git.Server/packages.config deleted file mode 100644 index 3fb6f6e4b..000000000 --- a/Bonobo.Git.Server/packages.config +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Bonobo.Git.Server/web.config b/Bonobo.Git.Server/web.config index c41892d6a..b6519a425 100644 --- a/Bonobo.Git.Server/web.config +++ b/Bonobo.Git.Server/web.config @@ -4,42 +4,6 @@
- - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -61,6 +25,7 @@ + @@ -77,6 +42,7 @@ + @@ -130,15 +96,4 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/Bonobo.Git.Server/favicon.ico b/Bonobo.Git.Server/wwwroot/favicon.ico similarity index 100% rename from Bonobo.Git.Server/favicon.ico rename to Bonobo.Git.Server/wwwroot/favicon.ico diff --git a/appveyor.yml b/appveyor.yml index 51f3ce853..e30e80d25 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,6 +1,7 @@ version: '{build}' configuration: Release platform: Any CPU +image: Visual Studio 2017 cache: - packages -> **\packages.config