Commits (8)
{
"version": 1,
"isRoot": true,
"tools": {
"gitversion.tool": {
"version": "5.6.6",
"commands": [
"dotnet-gitversion"
]
},
"dotnet-version-cli": {
"version": "2.1.1",
"commands": [
"dotnet-version"
]
}
}
}
\ No newline at end of file
......@@ -267,4 +267,7 @@ tools/*
dist/
#linq2db
src/.tools/*
\ No newline at end of file
src/.tools/*
# Dotnet Tool Manifest
.config/*
\ No newline at end of file
......@@ -28,4 +28,4 @@ The project will be build and tested.
* [Commit convention](docs/ESLintConvention.md)
* [Everything possible with markup](docs/testdoc.md)
* [Adding NUnit tests](docs/nunit.md)
\ No newline at end of file
* [Adding NUnit tests](docs/nunit.md)
\ No newline at end of file
......@@ -37,10 +37,10 @@ namespace Coscine.Api.Tree.Controllers
private readonly ProjectRoleModel _projectRoleModel;
private readonly ProjectResourceModel _projectResourceModel;
private readonly CoscineLogger _coscineLogger;
private readonly AnalyticsLogObject _analyticsLogObject;
private readonly string _blobApiLink;
private readonly string _prefix;
private readonly IConfiguration _configuration;
private readonly string _shaclPropertyUrl = "http://www.w3.org/ns/shacl#property";
/// <summary>
/// Tree controller constructor
......@@ -56,11 +56,10 @@ namespace Coscine.Api.Tree.Controllers
_projectResourceModel = new ProjectResourceModel();
_coscineLogger = new CoscineLogger(logger);
_analyticsLogObject = new AnalyticsLogObject();
var rule = _configuration.GetStringAndWait("traefik/frontends/Coscine.Api.Blob/routes/Coscine.Api.Blob/rule");
var host = rule.Substring("Host:".Length, rule.IndexOf(";") - "Host:".Length);
var path = rule.Substring(rule.IndexOf("/"));
var host = rule["Host:".Length..rule.IndexOf(";")];
var path = rule[rule.IndexOf("/")..];
_blobApiLink = $"https://{host}{path}/blob/";
_prefix = _configuration.GetStringAndWait("coscine/global/epic/prefix");
}
......@@ -94,6 +93,11 @@ namespace Coscine.Api.Tree.Controllers
var user = _authenticator.GetUser();
var check = CheckResourceIdAndPath(resourceId, path, out Resource resource);
if (resource.ApplicationProfile[^1] != '/')
{
resource.ApplicationProfile += '/';
}
if (user == null || !_resourceModel.HasAccess(user, resource, UserRoles.Owner, UserRoles.Member))
{
return Forbid("User has no Access to this resource.");
......@@ -115,13 +119,14 @@ namespace Coscine.Api.Tree.Controllers
var infos = await resourceTypeDefinition.ListEntries(resourceId, path, resourceTypeOptions);
var graphs = new List<JToken>();
int metadataCount = 0;
foreach (var info in infos)
{
var id = GenerateId(resourceId, info.Key);
if (_rdfStoreConnector.HasGraph(id.AbsoluteUri))
{
var graph = _rdfStoreConnector.GetGraph(id);
metadataCount = graph.Triples.Count;
graphs.Add(JToken.Parse(VDS.RDF.Writing.StringWriter.Write(graph, new RdfJsonWriter())));
}
}
......@@ -133,10 +138,10 @@ namespace Coscine.Api.Tree.Controllers
{
var objectMetaInfo = new ObjectMetaInfo
{
Name = x.Key.Substring(x.Key.LastIndexOf("/") + 1),
Name = x.Key[(x.Key.LastIndexOf("/") + 1)..],
Path = x.Key,
Size = (int)x.BodyBytes,
Kind = x.Key.Substring(x.Key.LastIndexOf(".") + 1),
Kind = x.Key[(x.Key.LastIndexOf(".") + 1)..],
Provider = resource.Type.DisplayName
};
var objectMetaInfoReturnObject = new ObjectMetaInfoReturnObject(objectMetaInfo, _blobApiLink, resource.Id.ToString());
......@@ -170,10 +175,14 @@ namespace Coscine.Api.Tree.Controllers
};
return result;
})))
))
);
))
);
if (CoscineLoggerConfiguration.IsLogLevelActivated(LogType.Analytics) && path != "/")
{
LogAnalyticsViewMd(_projectResourceModel.GetProjectForResource(resource.Id).Value, resource.Id, path, user, GetMetadataCompleteness(metadataCount, resource));
}
LogAnalytics("View MD", resourceId, path, user);
return Json(jObject);
}
catch
......@@ -213,10 +222,11 @@ namespace Coscine.Api.Tree.Controllers
return Forbid("User is no project member!");
}
if (resource.ApplicationProfile[resource.ApplicationProfile.Length - 1] != '/')
if (resource.ApplicationProfile[^1] != '/')
{
resource.ApplicationProfile += '/';
}
json[graphNameUri.AbsoluteUri]["http://www.w3.org/1999/02/22-rdf-syntax-ns#type"] = new JArray
{
new JObject
......@@ -282,16 +292,25 @@ namespace Coscine.Api.Tree.Controllers
{
return BadRequest("Data has the wrong format!");
}
// store the data
if (_rdfStoreConnector.HasGraph(graphNameUri))
{
_rdfStoreConnector.ClearGraph(graphNameUri);
LogAnalytics("Update MD", resourceId, path, user);
if (CoscineLoggerConfiguration.IsLogLevelActivated(LogType.Analytics))
{
LogAnalyticsUpdateMd(_projectResourceModel.GetProjectForResource(resource.Id).Value, resource.Id, path, user, GetMetadataCompleteness(graph.Triples.Count, resource));
}
}
else
{
_rdfStoreConnector.CreateNamedGraph(graphNameUri);
LogAnalytics("Upload MD", resourceId, path, user);
if (CoscineLoggerConfiguration.IsLogLevelActivated(LogType.Analytics))
{
LogAnalyticsUploadMd(_projectResourceModel.GetProjectForResource(resource.Id).Value, resource.Id, path, user, GetMetadataCompleteness(graph.Triples.Count, resource));
}
}
// BaseUri must be set for the sparql query
......@@ -351,25 +370,67 @@ namespace Coscine.Api.Tree.Controllers
return null;
}
/// <summary>
/// Log analytics
/// </summary>
/// <param name="operation">Operation</param>
/// <param name="resourceId">Resource of the id</param>
/// <param name="filename">Name of the file</param>
/// <param name="user">User object</param>
private void LogAnalytics(string operation, string resourceId, string filename, User user)
private void LogAnalyticsViewMd(Guid projectId, Guid resourceId, string filename, User user, string metadataCompletness)
{
if (CoscineLoggerConfiguration.IsLogLevelActivated(LogType.Analytics))
var analyticsLogObject = new AnalyticsLogObject
{
_analyticsLogObject.Type = "Action";
_analyticsLogObject.Operation = operation;
_analyticsLogObject.FileId = resourceId + "/" + HttpUtility.UrlDecode(filename).Substring(1);
_analyticsLogObject.ResourceId = resourceId;
_analyticsLogObject.ProjectId = _projectResourceModel.GetProjectForResource(new Guid(resourceId)).ToString();
_analyticsLogObject.RoleId = _projectRoleModel.GetGetUserRoleForProject(new Guid(_analyticsLogObject.ProjectId), user.Id).ToString();
_coscineLogger.AnalyticsLog(_analyticsLogObject);
}
Type = "Action",
Operation = "View MD",
RoleId = _projectRoleModel.GetGetUserRoleForProject(projectId, user.Id).ToString(),
ProjectId = projectId.ToString(),
ResourceId = resourceId.ToString(),
FileId = resourceId.ToString() + "/" + HttpUtility.UrlDecode(filename)[1..],
ApplicationsProfile = _resourceModel.CreateReturnObjectFromDatabaseObject(_resourceModel.GetById(resourceId)).ApplicationProfile,
MetadataCompleteness = metadataCompletness,
};
_coscineLogger.AnalyticsLog(analyticsLogObject);
}
private void LogAnalyticsUploadMd(Guid projectId, Guid resourceId, string filename, User user, string metadataCompletness)
{
var analyticsLogObject = new AnalyticsLogObject
{
Type = "Action",
Operation = "Upload MD",
RoleId = _projectRoleModel.GetGetUserRoleForProject(projectId, user.Id).ToString(),
ProjectId = projectId.ToString(),
ResourceId = resourceId.ToString(),
FileId = resourceId.ToString() + "/" + HttpUtility.UrlDecode(filename)[1..],
ApplicationsProfile = _resourceModel.CreateReturnObjectFromDatabaseObject(_resourceModel.GetById(resourceId)).ApplicationProfile,
MetadataCompleteness = metadataCompletness,
};
_coscineLogger.AnalyticsLog(analyticsLogObject);
}
private void LogAnalyticsUpdateMd(Guid projectId, Guid resourceId, string filename, User user, string metadataCompletness)
{
var analyticsLogObject = new AnalyticsLogObject
{
Type = "Action",
Operation = "Update MD",
RoleId = _projectRoleModel.GetGetUserRoleForProject(projectId, user.Id).ToString(),
ProjectId = projectId.ToString(),
ResourceId = resourceId.ToString(),
FileId = resourceId.ToString() + "/" + HttpUtility.UrlDecode(filename)[1..],
ApplicationsProfile = _resourceModel.CreateReturnObjectFromDatabaseObject(_resourceModel.GetById(resourceId)).ApplicationProfile,
MetadataCompleteness = metadataCompletness,
};
_coscineLogger.AnalyticsLog(analyticsLogObject);
}
private string GetMetadataCompleteness(int metadataCount, Resource resource)
{
var shapesGraph = _rdfStoreConnector.GetGraph(resource.ApplicationProfile);
var nodeFactory = new NodeFactory();
var uriNode = (UriNode)nodeFactory.CreateUriNode(new Uri(_shaclPropertyUrl));
var total = shapesGraph.GetTriplesWithPredicate(uriNode).Count();
var present = metadataCount;
return $"{present}/{total}";
}
}
}
......@@ -3,8 +3,9 @@
<OutputType>Exe</OutputType>
<RootNamespace>Coscine.Api.Tree</RootNamespace>
<AssemblyName>Coscine.Api.Tree</AssemblyName>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<TargetFramework>net5.0</TargetFramework>
<Version>2.0.1</Version>
<Version>2.1.0</Version>
</PropertyGroup>
<PropertyGroup>
<Authors>RWTH Aachen University</Authors>
......@@ -17,6 +18,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Coscine.ApiCommons" Version="2.*-*" />
<PackageReference Include="Coscine.Database" Version="2.*-*" />
<PackageReference Include="Coscine.Logging" Version="2.*-*" />
<PackageReference Include="Coscine.Metadata" Version="2.*-*" />
<PackageReference Include="Coscine.ResourceLoader" Version="2.*-*" />
<PackageReference Include="Coscine.WaterbutlerHelper" Version="2.*-*" />
......