Skip to content
Snippets Groups Projects
Select Git revision
  • fa35ed45d8fa7df3f1f6cbe1039aee4fc29ae50d
  • master default protected
  • gitkeep
  • dev protected
  • Issue/2309-docs
  • devops-aczepiel
  • Issue/2158-emailServicedesk
  • Issue/1938-internalHandling
  • Hotfix/2097-fixTimeFormat
  • Hotfix/2087-efNet6
  • Issue/1910-MigrationtoNET6.0
  • Issue/1826-versioning
  • Sprint/2022-01
  • Hotfix/1917-vocabCheck
  • Issue/1804-fixedValueFix
  • Hotfix/xxxx-notExposedGraphs
  • Sprint/2021-23
  • Issue/1746-ApplicationProfileStoringMethod
  • Hotfix/82-updateDepsOfAPIs
  • Product/1549-speedupQuerying
  • Topic/1598-speedupQuerying
  • v3.2.3
  • v3.2.2
  • v3.2.1
  • v3.2.0
  • v3.1.2
  • v3.1.1
  • v3.1.0
  • v3.0.2
  • v3.0.1
  • v3.0.0
  • v2.2.1
  • v2.2.0
  • v2.1.1
  • v2.1.0
  • v2.0.4
  • v2.0.3
  • v2.0.2
  • v2.0.1
  • v2.0.0
  • v1.7.1
41 results

MetadataController.cs

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    MetadataController.cs 9.30 KiB
    using Coscine.Action;
    using Coscine.Action.EventArgs;
    using Coscine.Api.Metadata.ParameterObjects;
    using Coscine.ApiCommons;
    using Coscine.ApiCommons.Exceptions;
    using Coscine.Configuration;
    using Coscine.Database.Models;
    using Coscine.Database.Util;
    using Coscine.Metadata;
    using GitLabApiClient;
    using GitLabApiClient.Models.Branches.Requests;
    using GitLabApiClient.Models.Commits.Requests.CreateCommitRequest;
    using GitLabApiClient.Models.MergeRequests.Requests;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Mvc;
    using Newtonsoft.Json.Linq;
    using System;
    using System.Collections.Generic;
    using System.Net;
    using System.Threading.Tasks;
    using System.Web;
    using VDS.RDF;
    using VDS.RDF.Writing;
    
    namespace Coscine.Api.Metadata.Controllers
    {
        /// <summary>
        /// This controller represents the actions which can be performed with a Metadata storage.
        /// </summary>
        [Authorize]
        public class MetadataController : Controller
        {
            private readonly Authenticator _authenticator;
            private readonly Emitter _emitter;
            private readonly IConfiguration _configuration;
            private readonly ResourceModel _resourceModel;
            private readonly RdfStoreConnector _rdfStoreConnector;
            private static readonly string HostUrl = "https://git.rwth-aachen.de/";
            private readonly string ApplicationProfileUrl = "https://purl.org/coscine/ap/";
            private static readonly string ApplicationProfileProjectURL = HttpUtility.UrlEncode("coscine/graphs/applicationprofiles");
    
            /// <summary>
            /// MetadataController constructor specifying an authenticator and a ResourceModel.
            /// </summary>
            public MetadataController()
            {
                _configuration = Program.Configuration;
                _authenticator = new Authenticator(this, _configuration);
                _resourceModel = new ResourceModel();
                _rdfStoreConnector = new RdfStoreConnector(_configuration.GetStringAndWait("coscine/local/virtuoso/additional/url"));
                _emitter = new Emitter(_configuration);
            }
    
            /// <summary>
            /// This method returns all application profiles.
            /// </summary>
            /// <returns>profiles</returns>
            [HttpGet("[controller]/profiles/")]
            [AllowAnonymous]
            public IActionResult GetProfiles()
            {
                var applicationProfiles = _rdfStoreConnector.GetApplicationProfiles();
                return Json(new JArray(applicationProfiles));
            }
    
            /// <summary>
            /// This method returns the application profile for the given profileUrl.
            /// </summary>
            /// <param name="profile">Url of the application profile</param>
            /// <returns>Json with the application profile</returns>
            [HttpGet("[controller]/profiles/{profile}")]
            [AllowAnonymous]
            public IActionResult GetProfile(string profile)
            {
                var profileUrl = profile.StartsWith("http") ? HttpUtility.UrlDecode(profile) : $"{ApplicationProfileUrl}{profile}/";
    
                if (!profileUrl.StartsWith(ApplicationProfileUrl))
                {
                    return StatusCode((int)HttpStatusCode.Forbidden, $"Profile has to start with {ApplicationProfileUrl}!");
                }
    
                var graph = _rdfStoreConnector.GetGraph(profileUrl);
    
                var tripleStore = new TripleStore();
                tripleStore.Add(graph);
    
                var outStoreJson = StringWriter.Write(tripleStore, new JsonLdWriter());
    
                var json = JToken.Parse(outStoreJson);
    
                return Ok(json);
            }
    
            /// <summary>
            /// This method returns a list of all vocabularies.
            /// </summary>
            /// <throws>Exception for the code that has not been implemented</throws>
            [HttpGet("[controller]/vocabularies/")]
            [AllowAnonymous]
            public IActionResult GetVocabularies()
            {
                throw new NotImplementedException();
            }
    
            /// <summary>
            /// This method returns a specific vocabulary.
            /// </summary>
            /// <param name="path">Url of the vocabulary</param>
            /// <returns>JSON with the requested vocabulary</returns>
            [HttpGet("[controller]/vocabularies/{path}")]
            [AllowAnonymous]
            public ActionResult<BilingualLabels> GetVocabulary(string path)
            {
                var graph = _rdfStoreConnector.GetGraph(HttpUtility.UrlDecode(path));
    
                var bilingualLabels = RetrieveBilingualLabels(graph);
    
                return Ok(bilingualLabels);
            }
    
            /// <summary>
            /// This method returns instances.
            /// </summary>
            /// <param name="className">class name</param>
            /// <returns>instances as Json, or throw an Exception if the user has not beed authorized</returns>
            [HttpGet("[controller]/instances/{className}")]
            [AllowAnonymous]
            public ActionResult<BilingualLabels> GetClassInstances(string className)
            {
                if (!Uri.TryCreate(HttpUtility.UrlDecode(className), UriKind.Absolute, out Uri uri))
                {
                    return BadRequest("ClassName is not a valid Uri.");
                }
                var graph = _rdfStoreConnector.GetClassGraph(uri);
    
                var bilingualLabels = RetrieveBilingualLabels(graph);
    
                return Ok(bilingualLabels);
            }
    
            /// <summary>
            /// Helper method which converts a graph to the described labels
            /// </summary>
            /// <param name="graph">RDF graph with labels</param>
            /// <returns>BilingualLabels</returns>
            private BilingualLabels RetrieveBilingualLabels(IGraph graph)
            {
                var bilingualLabels = new BilingualLabels();
    
                foreach (var kv in _rdfStoreConnector.GetVocabularyLabels(graph, "de"))
                {
                    var label = new Label
                    {
                        Value = kv.Key,
                        Name = kv.Value
                    };
                    bilingualLabels.De.Add(label);
                }
    
                foreach (var kv in _rdfStoreConnector.GetVocabularyLabels(graph, "en"))
                {
                    var label = new Label
                    {
                        Value = kv.Key,
                        Name = kv.Value
                    };
                    bilingualLabels.En.Add(label);
                }
    
                return bilingualLabels;
            }
    
            /// <summary>
            /// Create a request for storing a given application profile.
            /// </summary>
            /// <param name="applicationProfile">Object describing the application profile</param>
            /// <returns>NoContent</returns>
            [HttpPut("[controller]/profiles/")]
            public async Task<IActionResult> SaveApplicationProfileAsync([FromBody] ApplicationProfile applicationProfile)
            {
                var user = _authenticator.GetUser();
    
                if (string.IsNullOrWhiteSpace(user.EmailAddress))
                {
                    return BadRequest("The user's email has to be set!");
                }
    
                var token = _configuration.GetStringAndWait("coscine/global/gitlabtoken");
                var gitLabClient = new GitLabClient(HostUrl, token);
    
                var newBranchName = "Request/" + Guid.NewGuid().ToString();
    
                if (!applicationProfile.BaseURL.StartsWith(ApplicationProfileUrl))
                {
                    return BadRequest($"The Application Profile URL has to start with {ApplicationProfileUrl}.");
                }
                if (applicationProfile.MimeType.ToLower().Trim() != "text/turtle")
                {
                    return BadRequest("The mime type has to be text/turtle");
                }
    
                await gitLabClient.Branches.CreateAsync(ApplicationProfileProjectURL, new CreateBranchRequest(newBranchName, "master"));
    
                var folderName = applicationProfile.BaseURL.Replace(ApplicationProfileUrl, "");
                if (folderName.EndsWith("/"))
                {
                    folderName = folderName[..(folderName.Length - 1)];
                }
    
                var actions = new List<CreateCommitRequestAction>
                {
                    new CreateCommitRequestAction(
                        new CreateCommitRequestActionType(), 
                        $"profiles/{folderName}/index.ttl") { 
                            Content = applicationProfile.Definition 
                        }
                };
    
                var commitRequest = new CreateCommitRequest(newBranchName, $"{user.DisplayName} requests new application profile {applicationProfile.Name}", actions)
                {
                    AuthorEmail = user.EmailAddress,
                    AuthorName = user.DisplayName
                };
    
                await gitLabClient.Commits.CreateAsync(ApplicationProfileProjectURL, commitRequest, false);
    
                var newMergeRequest = await gitLabClient.MergeRequests.CreateAsync(ApplicationProfileProjectURL,
                    new CreateMergeRequest(newBranchName, "master", $"Merge request for new application profile {applicationProfile.Name}")
                    {
                        Description = $"Merge request created by {user.DisplayName}, {user.EmailAddress}, created at {DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss tt")}"
                    });
    
                _emitter.EmitApplicationProfileRequest(new ApplicationProfileEventArgs(_configuration)
                {
                    RequestOwner = user,
                    ApplicationProfileName = applicationProfile.Name,
                    MergeRequestURL = newMergeRequest.WebUrl
                });
    
                return NoContent();
            }
        }
    }