Commit f2933aea authored by Benedikt Heinrichs's avatar Benedikt Heinrichs

New: Working tests and library

parent e402e2c8
......@@ -35,6 +35,16 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Castle.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
<HintPath>..\packages\Castle.Core.4.4.0\lib\net45\Castle.Core.dll</HintPath>
</Reference>
<Reference Include="Consul, Version=0.7.2.6, Culture=neutral, PublicKeyToken=20a6ad9a81df1d95, processorArchitecture=MSIL">
<HintPath>..\packages\Consul.0.7.2.6\lib\net45\Consul.dll</HintPath>
</Reference>
<Reference Include="Coscine.Configuration, Version=1.4.0.0, Culture=neutral, PublicKeyToken=ce3d7a32d7dc1e5a, processorArchitecture=MSIL">
<HintPath>..\packages\Coscine.Configuration.1.4.0\lib\net461\Coscine.Configuration.dll</HintPath>
</Reference>
<Reference Include="Coscine.Database, Version=1.2.0.0, Culture=neutral, PublicKeyToken=767d77427707b70a" />
<Reference Include="Microsoft.AspNetCore.Antiforgery, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNetCore.Antiforgery.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Antiforgery.dll</HintPath>
</Reference>
......@@ -161,6 +171,9 @@
<Reference Include="Microsoft.Win32.Registry, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Win32.Registry.4.5.0\lib\net461\Microsoft.Win32.Registry.dll</HintPath>
</Reference>
<Reference Include="Moq, Version=4.12.0.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
<HintPath>..\packages\Moq.4.12.0\lib\net45\Moq.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
......@@ -178,6 +191,7 @@
<HintPath>..\packages\System.ComponentModel.Annotations.4.5.0\lib\net461\System.ComponentModel.Annotations.dll</HintPath>
</Reference>
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Data.OracleClient" />
<Reference Include="System.Diagnostics.DiagnosticSource, Version=4.0.3.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
......@@ -188,6 +202,7 @@
<HintPath>..\packages\System.Memory.4.5.2\lib\netstandard2.0\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Net" />
<Reference Include="System.Net.Http.WebRequest" />
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
......@@ -221,6 +236,7 @@
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.5.2\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Transactions" />
<Reference Include="System.Web" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
......
......@@ -2,6 +2,13 @@
using Coscine.Api.Project.Controllers;
using Microsoft.AspNetCore.Mvc;
using static Coscine.Api.Project.Controllers.ProjectController;
using Coscine.Api.Project.Models;
using System.Collections.Generic;
using Coscine.Database.Model;
using System.Linq;
using Moq;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
namespace Coscine.Api.Project.Tests
{
......@@ -11,18 +18,109 @@ namespace Coscine.Api.Project.Tests
{
private readonly ProjectController _projectController = new ProjectController();
private List<Coscine.Database.Model.Project> projects = new List<Coscine.Database.Model.Project>();
private List<User> users = new List<User>();
private int previous;
[OneTimeSetUp]
public void Setup()
{
ProjectModel projectModel = new ProjectModel();
previous = projectModel.GetAll().ToArray().Length;
UserModel userModel = new UserModel();
var user = new User();
userModel.Insert(user);
users.Add(user);
var request = new Mock<HttpRequest>();
JWTHandler jwtHandler = new JWTHandler(Program.Configuration);
Dictionary<string, string> values = new Dictionary<string, string>();
values.Add("UserId", user.Id.ToString());
// Not working - IsAjaxRequest() is static extension method and cannot be mocked
// request.Setup(x => x.IsAjaxRequest()).Returns(true /* or false */);
// use this
request.SetupGet(x => x.Headers).Returns(
new HeaderDictionary {
{"X-Requested-With", "XMLHttpRequest"},
{"bearer", jwtHandler.GenerateJwtToken(values)}
});
var context = new Mock<HttpContext>();
context.SetupGet(x => x.Request).Returns(request.Object);
// _projectController.ControllerContext = new ControllerContext(new ActionContext(context.Object, new RouteData(), _projectController.ControllerContext.));
var project = new Coscine.Database.Model.Project()
{
Description = "Description",
Organization = "Organization",
DisplayName = "TestProject"
};
projectModel.Insert(project);
projectModel.SetOwner(project, user);
projects.Add(projectModel.GetById(project.Id));
var project2 = new Coscine.Database.Model.Project()
{
Description = "Description2",
Organization = "Organization2",
DisplayName = "TestProject2"
};
projectModel.Insert(project2);
projects.Add(projectModel.GetById(project2.Id));
}
[OneTimeTearDown]
public void End()
{
ProjectModel projectModel = new ProjectModel();
foreach (var project in projects)
{
projectModel.Delete(project);
}
UserModel userModel = new UserModel();
foreach (var user in users)
{
userModel.Delete(user);
}
}
[Test]
public void IndexTest()
public void OwnsTest()
{
var answer = "Hello World from a controller";
ProjectModel projectModel = new ProjectModel();
Assert.IsTrue(projectModel.OwnsProject(users[0], projects[0]));
Assert.IsFalse(projectModel.OwnsProject(users[0], projects[1]));
var result = _projectController.Index();
Assert.IsInstanceOf<OkObjectResult>(result);
var okResult = (OkObjectResult)result;
var all = projectModel.GetAllWhere((project) =>
(from projectRole in project.ProjectRolesProjectIdIds
where projectRole.User == users[0]
&& projectRole.Role.DisplayName == "Owner"
select projectRole).Any()
);
Assert.IsTrue(all.ToArray().Length == 1);
}
/*
[Test]
public void TestController()
{
var actionResult = _projectController.Index();
var task = actionResult.ExecuteResultAsync(_projectController.ControllerContext);
task.Wait();
}*/
Assert.IsInstanceOf<string>(okResult.Value);
var answerFromController = (string)okResult.Value;
Assert.IsTrue(answerFromController == answer);
[Test]
public void CountTest()
{
ProjectModel projectModel = new ProjectModel();
Assert.IsTrue(previous == projectModel.GetAll().ToArray().Length - projects.Count);
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Castle.Core" version="4.4.0" targetFramework="net472" />
<package id="Consul" version="0.7.2.6" targetFramework="net472" />
<package id="Coscine.Configuration" version="1.4.0" targetFramework="net472" />
<package id="Microsoft.AspNetCore.Antiforgery" version="2.2.0" targetFramework="net472" />
<package id="Microsoft.AspNetCore.Authentication.Abstractions" version="2.2.0" targetFramework="net472" />
<package id="Microsoft.AspNetCore.Authentication.Core" version="2.2.0" targetFramework="net472" />
......@@ -43,6 +46,7 @@
<package id="Microsoft.Extensions.WebEncoders" version="2.2.0" targetFramework="net472" />
<package id="Microsoft.Net.Http.Headers" version="2.2.0" targetFramework="net472" />
<package id="Microsoft.Win32.Registry" version="4.5.0" targetFramework="net472" />
<package id="Moq" version="4.12.0" targetFramework="net472" />
<package id="Newtonsoft.Json" version="12.0.2" targetFramework="net472" />
<package id="Newtonsoft.Json.Bson" version="1.0.2" targetFramework="net472" />
<package id="NUnit" version="3.11.0" targetFramework="net472" />
......
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
......@@ -87,4 +91,14 @@
</dependentAssembly>
</assemblyBinding>
</runtime>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
</configuration>
\ No newline at end of file
......@@ -36,7 +36,7 @@ namespace Coscine.Api.Project
var bearer = _controller.Request.Headers["bearer"];
if (!string.IsNullOrWhiteSpace(bearer))
{
JWTHandler jwtHandler = new JWTHandler(Program.Configurator.Configuration);
JWTHandler jwtHandler = new JWTHandler(Program.Configuration);
var claims = jwtHandler.GetContents(bearer);
var userClaim = (from claimObj in claims
where claimObj.Type == "UserId"
......
......@@ -10,9 +10,9 @@ namespace Coscine.Api.Project
public ApplicationInformation ApplicationInformation { get; set; } = new ApplicationInformation();
public IConfiguration Configuration { get; set; }
public Configurator(ApplicationInformation applicationInforamtion, IConfiguration configuration)
public Configurator(ApplicationInformation applicationInformation, IConfiguration configuration)
{
ApplicationInformation = applicationInforamtion;
ApplicationInformation = applicationInformation;
Configuration = configuration;
}
public Configurator(IConfiguration configuration)
......
......@@ -23,13 +23,12 @@ namespace Coscine.Api.Project.Controllers
return Ok(_authenticator.ValidateAndExecute((user) =>
{
ProjectModel projectModel = new ProjectModel();
return projectModel.GetAllWhere((project) =>
{
return (from projectRole in project.ProjectRolesProjectIdIds
return projectModel.GetAllWhere((project) =>
(from projectRole in project.ProjectRolesProjectIdIds
where projectRole.User == user
&& projectRole.Role.DisplayName == "Owner"
select projectRole).Any();
}).Select((project) =>
select projectRole).Any()
).Select((project) =>
{
return new ProjectObject(project.Id, project.Description, project.DisplayName, project.Organization);
});
......
......@@ -19,22 +19,21 @@ namespace Coscine.Api.Project.Controllers
{
_authenticator = new Authenticator(this);
}
[Route("[controller]")]
public IActionResult Index()
{
return Ok(_authenticator.ValidateAndExecute((user) =>
{
ResourceModel resourceModel = new ResourceModel(); ;
return resourceModel.GetAllWhere((resource) =>
{
return (from projectResource in resource.ProjectResourceResourceIdIds
ResourceModel resourceModel = new ResourceModel();
return resourceModel.GetAllWhere((resource) =>
(from projectResource in resource.ProjectResourceResourceIdIds
where (from projectRole in projectResource.Project.ProjectRolesProjectIdIds
where projectRole.User == user
&& projectRole.Role.DisplayName == "Owner"
select projectRole).Any()
select projectResource).Any();
}).Select((resource) =>
select projectResource).Any()
).Select((resource) =>
{
return new ResourceObject(resource.Id, resource.ExternalId, resource.Url, new ResourceTypeObject(resource.Type.Id, resource.Type.DisplayName));
});
......
......@@ -24,7 +24,7 @@ namespace Coscine.Api.Project
public bool ValidToken(string token)
{
string secretKey = _configuration.GetString("coscine/global/jwtsecret");
string secretKey = _configuration.GetStringAndWait("coscine/global/jwtsecret");
if (secretKey == null)
{
......@@ -60,5 +60,26 @@ namespace Coscine.Api.Project
}
}
public string GenerateJwtToken(IReadOnlyDictionary<string, string> payloadContents, string encryptionAlgorithm = "HS256")
{
string secretKey = _configuration.GetStringAndWait("coscine/global/jwtsecret");
if (secretKey == null)
{
throw new ArgumentNullException("JWT Secret Configuration value is not set!");
}
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey));
var signingCredentials = new SigningCredentials(securityKey, encryptionAlgorithm);
var payloadClaims = payloadContents.Select(c => new Claim(c.Key, c.Value));
var payload = new JwtPayload(payloadClaims);
var header = new JwtHeader(signingCredentials);
var securityToken = new JwtSecurityToken(header, payload);
return _jwtSecurityTokenHandler.WriteToken(securityToken);
}
}
}
using Coscine.Configuration;
using Coscine.Database.Model;
using LinqKit;
using LinqToDB;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
......@@ -18,27 +20,32 @@ namespace Coscine.Api.Project.Models
DatabaseConnection = new DatabaseConnection(configuration);
}
public abstract Guid GetIdFromObject(T databaseObject);
public abstract Expression<Func<T, Guid>> GetIdFromObject();
public abstract void SetObjectId(T databaseObject, Guid Id);
public abstract ITable<T> GetITableFromDatabase(CoscineDB db);
// GetById utilizes the Expression functionality since Linq2Sql does not support method calls
// This is therefore a workaround for getting the Id parameter
public T GetById(Guid id)
{
Expression<Func<T, Guid>> expression = GetIdFromObject();
return DatabaseConnection.ConnectToDatabase((db) =>
{
return
(from tableEntry in GetITableFromDatabase(db)
where GetIdFromObject(tableEntry) == id
(from tableEntry in GetITableFromDatabase(db).AsExpandable()
where expression.Invoke(tableEntry) == id
select tableEntry).First();
});
}
public T GetWhere(Func<T, bool> whereClause)
public T GetWhere(Expression<Func<T, bool>> whereClause)
{
return DatabaseConnection.ConnectToDatabase((db) =>
{
return
(from tableEntry in GetITableFromDatabase(db)
(from tableEntry in GetITableFromDatabase(db).AsExpandable()
where whereClause.Invoke(tableEntry)
select tableEntry).First();
});
......@@ -54,12 +61,12 @@ namespace Coscine.Api.Project.Models
});
}
public IEnumerable<T> GetAllWhere(Func<T, bool> whereClause)
public IEnumerable<T> GetAllWhere(Expression<Func<T, bool>> whereClause)
{
return DatabaseConnection.ConnectToDatabase((db) =>
{
return
(from tableEntry in GetITableFromDatabase(db)
(from tableEntry in GetITableFromDatabase(db).AsExpandable()
where whereClause.Invoke(tableEntry)
select tableEntry).ToList();
});
......@@ -75,11 +82,24 @@ namespace Coscine.Api.Project.Models
public int Insert(T databaseObject)
{
if(GetIdFromObject().Invoke(databaseObject) == new Guid("00000000-0000-0000-0000-000000000000"))
{
SetObjectId(databaseObject, Guid.NewGuid());
}
return DatabaseConnection.ConnectToDatabase((db) =>
{
return db.Insert(databaseObject);
});
}
public int Delete(T databaseObject)
{
return DatabaseConnection.ConnectToDatabase((db) =>
{
return db.Delete(databaseObject);
});
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using Coscine.Api.Project.Exceptions;
......@@ -13,7 +14,7 @@ namespace Coscine.Api.Project.Models
public class ProjectModel : DatabaseModel<Coscine.Database.Model.Project>
{
public ProjectModel() : base(Program.Configurator.Configuration)
public ProjectModel() : base(Program.Configuration)
{
}
......@@ -32,16 +33,16 @@ namespace Coscine.Api.Project.Models
public void SetOwner(Coscine.Database.Model.Project project, User user)
{
project.ProjectRolesProjectIdIds.Append(new ProjectRole()
ProjectRoleModel projectRoleModel = new ProjectRoleModel();
ProjectRole projectRole = new ProjectRole()
{
Project = project,
User = user,
Role = new RoleModel().GetWhere((role) =>
{
return role.DisplayName == "Owner";
})
});
Update(project);
RelationId = Guid.NewGuid(),
ProjectId = project.Id,
UserId = user.Id,
RoleId = new RoleModel().GetWhere((x) => x.DisplayName == "Owner").Id
};
projectRoleModel.Insert(projectRole);
}
public bool OwnsProject(User user, Coscine.Database.Model.Project project)
......@@ -69,14 +70,19 @@ namespace Coscine.Api.Project.Models
Update(project);
}
public override Guid GetIdFromObject(Database.Model.Project databaseObject)
public override Expression<Func<Database.Model.Project, Guid>> GetIdFromObject()
{
return databaseObject.Id;
return databaseObject => databaseObject.Id;
}
public override ITable<Database.Model.Project> GetITableFromDatabase(CoscineDB db)
{
return db.Projects;
}
public override void SetObjectId(Database.Model.Project databaseObject, Guid Id)
{
databaseObject.Id = Id;
}
}
}
using Coscine.Database.Model;
using LinqToDB;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
namespace Coscine.Api.Project.Models
{
public class ProjectRoleModel : DatabaseModel<ProjectRole>
{
public ProjectRoleModel() : base(Program.Configuration)
{
}
public override Expression<Func<ProjectRole, Guid>> GetIdFromObject()
{
return databaseObject => databaseObject.RelationId;
}
public override ITable<ProjectRole> GetITableFromDatabase(CoscineDB db)
{
return db.ProjectRoles;
}
public override void SetObjectId(ProjectRole databaseObject, Guid Id)
{
databaseObject.RelationId = Id;
}
}
}
......@@ -4,6 +4,7 @@ using LinqToDB;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
......@@ -11,7 +12,7 @@ namespace Coscine.Api.Project.Models
{
public class ResourceModel : DatabaseModel<Resource>
{
public ResourceModel() : base(Program.Configurator.Configuration)
public ResourceModel() : base(Program.Configuration)
{
}
......@@ -41,14 +42,19 @@ namespace Coscine.Api.Project.Models
});
}
public override Guid GetIdFromObject(Resource databaseObject)
public override Expression<Func<Resource, Guid>> GetIdFromObject()
{
return databaseObject.Id;
return databaseObject => databaseObject.Id;
}
public override ITable<Resource> GetITableFromDatabase(CoscineDB db)
{
return db.Resources;
}
public override void SetObjectId(Resource databaseObject, Guid Id)
{
databaseObject.Id = Id;
}
}
}
......@@ -3,6 +3,7 @@ using LinqToDB;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
......@@ -10,19 +11,24 @@ namespace Coscine.Api.Project.Models
{
public class ResourceTypeModel : DatabaseModel<ResourceType>
{
public ResourceTypeModel() : base(Program.Configurator.Configuration)
public ResourceTypeModel() : base(Program.Configuration)
{
}
public override Guid GetIdFromObject(ResourceType databaseObject)
public override Expression<Func<ResourceType, Guid>> GetIdFromObject()
{
return databaseObject.Id;
return databaseObject => databaseObject.Id;
}
public override ITable<ResourceType> GetITableFromDatabase(CoscineDB db)
{
return db.ResourceTypes;
}
public override void SetObjectId(ResourceType databaseObject, Guid Id)
{
databaseObject.Id = Id;
}
}
}
......@@ -3,6 +3,7 @@ using LinqToDB;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
......@@ -11,19 +12,35 @@ namespace Coscine.Api.Project.Models
public class RoleModel : DatabaseModel<Role>
{
public RoleModel() : base(Program.Configurator.Configuration)
public RoleModel() : base(Program.Configuration)
{
}
public override Guid GetIdFromObject(Role databaseObject)
public override Expression<Func<Role, Guid>> GetIdFromObject()
{
return databaseObject.Id;
return databaseObject => databaseObject.Id;
}
public override ITable<Role> GetITableFromDatabase(CoscineDB db)
{
return db.Roles;
}
public override void SetObjectId(Role databaseObject, Guid Id)
{
databaseObject.Id = Id;
}