using Coscine.Api.Project.ReturnObjects; using Coscine.ApiCommons.Models; using Coscine.Configuration; using Coscine.Database.Model; using LinqToDB; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; namespace Coscine.Api.Project.Models { public class ResourceModel : DatabaseModel { private readonly IConfiguration _configuration; public ResourceModel() : base(Program.Configuration) { _configuration = Program.Configuration; } public Resource StoreFromObject(ResourceObject resourceObject) { if (resourceObject.Disciplines.Count() == 0 || resourceObject.ResourceTypeOption == null) { throw new ArgumentException("Discipline and ResourceTypeOption are necessary!"); } Resource resource = new Resource() { DisplayName = resourceObject.DisplayName, ResourceName = resourceObject.ResourceName, Description = resourceObject.Description, Keywords = resourceObject.Keywords, UsageRights = resourceObject.UsageRights, TypeId = resourceObject.Type.Id, Type = new ResourceTypeModel().GetById(resourceObject.Type.Id), VisibilityId = resourceObject.Visibility.Id, ApplicationProfile = resourceObject.ApplicationProfile, FixedValues = resourceObject.FixedValues != null ? resourceObject.FixedValues.ToString() :"{}", Creator = resourceObject.Creator }; if(resourceObject.License != null) { resource.LicenseId = resourceObject.License.Id; } Insert(resource); try { SetDisciplines(resource, resourceObject.Disciplines); SetResourceTypeObject(resource, resourceObject.ResourceTypeOption); } catch (Exception e) { Delete(resource); throw e; } return resource; } public int DeleteResource(Resource resource) { ProjectResourceModel projectResourceModel = new ProjectResourceModel(); foreach (var projectResource in projectResourceModel.GetAllWhere((projectResource) => projectResource.ResourceId == resource.Id)) { projectResourceModel.Delete(projectResource); } ResourceDisciplineModel resourceDisciplineModel = new ResourceDisciplineModel(); foreach (var resourceDiscipline in resourceDisciplineModel.GetAllWhere((resourceDicipline) => resourceDicipline.ResourceId == resource.Id)) { resourceDisciplineModel.Delete(resourceDiscipline); } DeleteResourceTypeObject(resource); return Delete(resource); } private void SetResourceTypeObject(Resource resource, JObject resourceTypeOption) { if (resource.Type.DisplayName == "rds") { RDSResourceTypeObject rdsResourceTypeObject = resourceTypeOption.ToObject(); RDSResourceTypeModel rdsResourceTypeModel = new RDSResourceTypeModel(); if (resource.ResourceTypeOptionId != null) { RDSResourceType rdsResourceType = rdsResourceTypeModel.GetById(resource.ResourceTypeOptionId.Value); rdsResourceTypeModel.Update(rdsResourceType); } else { RDSResourceType rdsResourceType = new RDSResourceType() { BucketName = GetRDSBucketName(), Size = rdsResourceTypeObject.Size, }; rdsResourceTypeModel.Insert(rdsResourceType); resource.ResourceTypeOptionId = rdsResourceType.Id; Update(resource); } } else if (resource.Type.DisplayName == "s3") { S3ResourceTypeObject s3ResourceTypeObject = resourceTypeOption.ToObject(); S3ResourceTypeModel s3ResourceTypeModel = new S3ResourceTypeModel(); if (resource.ResourceTypeOptionId != null) { S3ResourceType s3ResourceType = s3ResourceTypeModel.GetById(resource.ResourceTypeOptionId.Value); s3ResourceType.BucketName = s3ResourceTypeObject.BucketName; s3ResourceType.AccessKey = s3ResourceTypeObject.AccessKey ?? s3ResourceType.AccessKey; s3ResourceType.SecretKey = s3ResourceTypeObject.SecretKey ?? s3ResourceType.SecretKey; s3ResourceTypeModel.Update(s3ResourceType); } else { S3ResourceType s3ResourceType = new S3ResourceType() { BucketName = s3ResourceTypeObject.BucketName, AccessKey = s3ResourceTypeObject.AccessKey, SecretKey = s3ResourceTypeObject.SecretKey }; s3ResourceTypeModel.Insert(s3ResourceType); resource.ResourceTypeOptionId = s3ResourceType.Id; Update(resource); } } else if (resource.Type.DisplayName == "gitlab") { GitlabResourceTypeObject gitlabResourceTypeObject = resourceTypeOption.ToObject(); GitlabResourceTypeModel gitlabResourceTypeModel = new GitlabResourceTypeModel(); if (resource.ResourceTypeOptionId != null) { GitlabResourceType gitlabResourceType = gitlabResourceTypeModel.GetById(resource.ResourceTypeOptionId.Value); gitlabResourceType.RepositoryNumber = gitlabResourceTypeObject.RepositoryNumber; gitlabResourceType.RepositoryUrl = gitlabResourceTypeObject.RepositoryUrl; gitlabResourceType.Token = gitlabResourceTypeObject.Token ?? gitlabResourceType.Token; gitlabResourceTypeModel.Update(gitlabResourceType); } else { GitlabResourceType gitlabResourceType = new GitlabResourceType() { RepositoryNumber = gitlabResourceTypeObject.RepositoryNumber, RepositoryUrl = gitlabResourceTypeObject.RepositoryUrl, Token = gitlabResourceTypeObject.Token }; gitlabResourceTypeModel.Insert(gitlabResourceType); resource.ResourceTypeOptionId = gitlabResourceType.Id; Update(resource); } } else { throw new ArgumentException("Not supported resource type!"); } } private string GetRDSBucketName() { var prefix = _configuration.GetStringAndWait("coscine/global/buckets/prefix"); var number = Int32.Parse(_configuration.GetStringAndWait("coscine/global/buckets/currentid")); var maxNumber = Int32.Parse(_configuration.GetStringAndWait("coscine/global/buckets/highestid")); var newNumber = number % maxNumber == 0 ? 1 : number + 1; _configuration.Put("coscine/global/buckets/currentid", "" + newNumber); return String.Format("{0}{1,3:000}", prefix, number); } private void SetDisciplines(Resource resource, IEnumerable disciplines) { ResourceDisciplineModel resourceDisciplineModel = new ResourceDisciplineModel(); foreach (var oldDiscipline in resourceDisciplineModel.GetAllWhere((resourceDiscipline) => resourceDiscipline.ResourceId == resource.Id)) { resourceDisciplineModel.Delete(oldDiscipline); } foreach (var discipline in disciplines) { ResourceDiscipline resourceDiscipline = new ResourceDiscipline() { DisciplineId = discipline.Id, ResourceId = resource.Id }; resourceDisciplineModel.Insert(resourceDiscipline); } } public bool HasAccess(User user, Database.Model.Resource resource, params string[] allowedAccess) { IEnumerable allowedAccessLabels = allowedAccess.Select(x => x.ToLower().Trim()).ToList(); return DatabaseConnection.ConnectToDatabase((db) => (from relation in db.ProjectRoles where relation.Project.ProjectResourceProjectIdIds != null && relation.Project.ProjectResourceProjectIdIds .Any((projectResource) => projectResource.Resource.Id == resource.Id) && relation.User.Id == user.Id && allowedAccessLabels.Contains(relation.Role.DisplayName.ToLower()) select relation).Any()); } public int UpdateByObject(Resource resource, ResourceObject resourceObject) { if (resourceObject.Disciplines.Count() == 0 || resourceObject.ResourceTypeOption == null) { throw new ArgumentException("Discipline and ResourceTypeOption are necessary!"); } if (resource.TypeId != resourceObject.Type.Id) { DeleteResourceTypeObject(resource); } resource.DisplayName = resourceObject.DisplayName; resource.ResourceName = resourceObject.ResourceName; resource.Description = resourceObject.Description; resource.Keywords = resourceObject.Keywords; resource.UsageRights = resourceObject.UsageRights; resource.TypeId = resourceObject.Type.Id; resource.Type = new ResourceTypeModel().GetById(resourceObject.Type.Id); resource.VisibilityId = resourceObject.Visibility.Id; if(resourceObject.License != null) { resource.LicenseId = resourceObject.License.Id; } // the application profile can not be altered after creation // resource.ApplicationProfile = resourceObject.ApplicationProfile; resource.FixedValues = resourceObject.FixedValues != null ? resourceObject.FixedValues.ToString() : "{}"; // the resource creator can not be altered after creation // resource.Creator = resourceObject.Creator; SetDisciplines(resource, resourceObject.Disciplines); SetResourceTypeObject(resource, resourceObject.ResourceTypeOption); return Update(resource); } // TODO: Find out why resource.Type is not set public void SetType(Resource resource) { if (resource.Type == null) { ResourceTypeModel resourceTypeModel = new ResourceTypeModel(); resource.Type = resourceTypeModel.GetById(resource.TypeId); } } public void DeleteResourceTypeObject(Resource resource) { SetType(resource); if (resource.Type.DisplayName == "rds" && resource.ResourceTypeOptionId != null) { RDSResourceTypeModel rdsResourceTypeModel = new RDSResourceTypeModel(); rdsResourceTypeModel.Delete(rdsResourceTypeModel.GetById(resource.ResourceTypeOptionId.Value)); } else if (resource.Type.DisplayName == "s3" && resource.ResourceTypeOptionId != null) { S3ResourceTypeModel s3ResourceTypeModel = new S3ResourceTypeModel(); s3ResourceTypeModel.Delete(s3ResourceTypeModel.GetById(resource.ResourceTypeOptionId.Value)); } else if (resource.Type.DisplayName == "gitlab" && resource.ResourceTypeOptionId != null) { GitlabResourceTypeModel gitlabResourceTypeModel = new GitlabResourceTypeModel(); gitlabResourceTypeModel.Delete(gitlabResourceTypeModel.GetById(resource.ResourceTypeOptionId.Value)); } } public ResourceObject CreateReturnObjectFromDatabaseObject(Resource resource) { SetType(resource); DisciplineModel disciplineModel = new DisciplineModel(); var disciplines = disciplineModel.GetAllWhere((discipline) => (from relation in discipline.ResourceDisciplineDisciplineIdIds where relation.ResourceId == resource.Id select relation).Any()) .Select((discipline) => new DisciplineObject(discipline.Id, discipline.Url, discipline.DisplayNameDe, discipline.DisplayNameEn)); if (resource.Visibility == null && resource.VisibilityId != null) { VisibilityModel visibilityModel = new VisibilityModel(); resource.Visibility = visibilityModel.GetById(resource.VisibilityId.Value); } if (resource.License == null && resource.LicenseId != null) { LicenseModel licenseModel = new LicenseModel(); resource.License = licenseModel.GetById(resource.LicenseId.Value); } ResourceTypeOptionObject resourceTypeOptionObject = null; if(resource.Type.DisplayName == "rds" && resource.ResourceTypeOptionId != null) { RDSResourceTypeModel rdsResourceTypeModel = new RDSResourceTypeModel(); var rdsResourceType = rdsResourceTypeModel.GetById(resource.ResourceTypeOptionId.Value); resourceTypeOptionObject = new RDSResourceTypeObject(rdsResourceType.Id, rdsResourceType.BucketName, (int)rdsResourceType.Size); } else if (resource.Type.DisplayName == "s3" && resource.ResourceTypeOptionId != null) { S3ResourceTypeModel s3ResourceTypeModel = new S3ResourceTypeModel(); var s3ResourceType = s3ResourceTypeModel.GetById(resource.ResourceTypeOptionId.Value); resourceTypeOptionObject = new S3ResourceTypeObject(s3ResourceType.Id, s3ResourceType.BucketName, null, null); } else if(resource.Type.DisplayName == "gitlab" && resource.ResourceTypeOptionId != null) { GitlabResourceTypeModel gitlabResourceTypeModel = new GitlabResourceTypeModel(); var gitlabResourceType = gitlabResourceTypeModel.GetById(resource.ResourceTypeOptionId.Value); resourceTypeOptionObject = new GitlabResourceTypeObject(gitlabResourceType.Id, gitlabResourceType.RepositoryNumber, gitlabResourceType.RepositoryUrl, null); } return new ResourceObject( resource.Id, resource.DisplayName, resource.ResourceName, resource.Description, resource.Keywords, resource.UsageRights, new ResourceTypeObject(resource.Type.Id, resource.Type.DisplayName, resource.Type.Enabled), disciplines, (resource.Visibility != null) ? new VisibilityObject(resource.Visibility.Id, resource.Visibility.DisplayName) : null, (resource.License != null) ? new LicenseObject(resource.License.Id, resource.License.DisplayName) : null, JObject.FromObject(resourceTypeOptionObject), resource.ApplicationProfile, JToken.Parse(resource.FixedValues == null ? "{}": resource.FixedValues ), (resource.Creator != null) ? resource.Creator : null ); } public override Expression> GetIdFromObject() { return databaseObject => databaseObject.Id; } public override ITable GetITableFromDatabase(CoscineDB db) { return db.Resources; } public override void SetObjectId(Resource databaseObject, Guid id) { databaseObject.Id = id; } } }