using System; using System.Collections.Generic; using System.Linq; using System.Security.Principal; using System.Threading; using System.Threading.Tasks; using BO.AppServer.Business.Exceptions; using BO.AppServer.Business.Mapper; using BO.AppServer.Business.Services.Base; using BO.AppServer.Data.Entity; using BO.AppServer.Data.Repository; using BO.AppServer.Metadata.Configuration; using BO.AppServer.Metadata.Dto; using BO.AppServer.Metadata.Enums; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Quadarax.Foundation.Core.Data; using Quadarax.Foundation.Core.Data.Interface; using Quadarax.Foundation.Core.Data.Interface.Entity.Dto; using Quadarax.Foundation.Core.Exceptions; namespace BO.AppServer.Business.Services { public class WorkspaceService: UserContextService { #region *** Private fields *** private readonly WorkspaceRepo _repoWorkspace; private readonly BillingPlanRepo _repoBillingPlan; private readonly WorkspaceBillingRepo _repoWorkspaceBilling; #endregion #region *** Constructor *** public WorkspaceService(WorkspaceRepo repoWorkspace, BillingPlanRepo repoBillingPlan, WorkspaceBillingRepo repoWorkspaceBilling, IOptions config, UserRepo repoUser, UserManager userManager, IPrincipal currentPrincipal, ILoggerFactory logger) : base(config, repoUser, userManager, currentPrincipal, logger) { _repoWorkspace = repoWorkspace ?? throw new ArgumentNullException(nameof(repoWorkspace)); _repoBillingPlan = repoBillingPlan ?? throw new ArgumentNullException(nameof(repoBillingPlan)); _repoWorkspaceBilling = repoWorkspaceBilling ?? throw new ArgumentNullException(nameof(repoWorkspaceBilling)); } #endregion #region *** Public Operations *** public async Task> CreateWorkspaceAsync(WorkspaceCDto workspace) { var billingPlan = _repoBillingPlan.GetByCode(workspace.BillingPlanCode); if (billingPlan == null) { var exc = new EntityNotExistsException(typeof(BillingPlan), workspace.BillingPlanCode, 0); Log.LogWarning(exc.Message); throw exc; } var owner = _repoUser.GetByName(workspace.AssignedUserName); if (owner == null) { var exc = new EntityNotExistsException(typeof(User), workspace.AssignedUserName, 0); Log.LogWarning(exc.Message); throw exc; } var current = GetCurrentUser(); var newWorkspace = _repoWorkspace.CreateWorkspace(workspace.Name, billingPlan, workspace.Apipassword, true, owner,current); _repoWorkspace.Commit(); Log.LogInformation($"Workspace '{newWorkspace.Name}' [API-KEY:{newWorkspace.Apikey}] created and appends to users: {string.Join(",", newWorkspace.UserWorkspaces.Select(x=>x.User.Name))}"); return new ResultValueDto(newWorkspace.Map()); } public async Task> GetWorkspacesAsync(WorkspaceScopeEnums scope, PagingDto paging,string ownerUserName) { List workspaces = null; switch (scope) { case WorkspaceScopeEnums.All: workspaces = _repoWorkspace.Query(paging).ToList(); break; case WorkspaceScopeEnums.Empty: workspaces = _repoWorkspace.GetAllEmpty(paging).ToList(); break; case WorkspaceScopeEnums.NotEmpty: workspaces = _repoWorkspace.GetAllNonEmpty(paging).ToList(); break; case WorkspaceScopeEnums.My: var owner = _repoUser.GetByName(ownerUserName); if (owner == null) { var exc = new EntityNotExistsException(typeof(User), ownerUserName, 0); Log.LogWarning(exc.Message); throw exc; } workspaces = _repoWorkspace.GetAllByOwner(owner, paging).ToList(); break; case WorkspaceScopeEnums.MyDefault: owner = _repoUser.GetByName(ownerUserName); if (owner == null) { var exc = new EntityNotExistsException(typeof(User), ownerUserName, 0); Log.LogWarning(exc.Message); throw exc; } var workspace = _repoWorkspace.GetDefaultByOwner(owner); if (workspace == null) { var exc = new CodeException(1410,$"User '{ownerUserName}' has any default workspace set!"); Log.LogWarning(exc.Message); throw exc; } workspaces = new List(new[] { workspace }); break; } return new ResultsValueDto(workspaces.MapList()); } public async Task GetWorkspaceIdByAPIAccess(string apiKey, string apiPassword, string currentUserName) { var owner = string.IsNullOrEmpty(currentUserName) ? GetCurrentUser() : _repoUser.GetByName(currentUserName); if (owner == null) { var exc = new EntityNotExistsException(typeof(User), currentUserName, 0); Log.LogWarning(exc.Message); throw exc; } if (!Guid.TryParse(apiKey, out var apiKeyGuid)) apiKeyGuid = Guid.Empty; Workspace workspace = null; if (await HasUserElevation(currentUserName)) { // if elevated user and system user workspace = _repoWorkspace.GetByApiKey(apiKey); if (workspace.Apipassword != apiPassword) workspace = null; } else { // for rest workspace = _repoWorkspace.GetAllByOwner(owner, new Paging()) .FirstOrDefault(x => x.Apikey == apiKeyGuid && x.Apipassword == apiPassword); } if (workspace == null) { var exc = new CodeException(1400, $"Workspace with APIKey '{apiKey}' not exists or API password is not valid!"); Log.LogWarning(exc.Message + $"\nUser Context:'{owner.Name}' [{owner.Id}]"); throw exc; } return workspace.Id; } public async Task> GetWorkspace(WorkspaceIdentificationTypeEnum identificationType, string identificationValue) { var workspace = identificationType == WorkspaceIdentificationTypeEnum.Id ? _repoWorkspace.Get(ArgumentAsLong(nameof(identificationValue), identificationValue)) : identificationType == WorkspaceIdentificationTypeEnum.ApiKey ? _repoWorkspace.GetByApiKey(identificationValue) : _repoWorkspace.GetByName(identificationValue); if (workspace == null) throw new NoDataException(); var currentBillingPlan = GetCurrentWorkspaceBillingOrCreate(workspace.Id); // gather rest of data var result = new ResultValueDto(workspace.Map()); result.Value.CreditAmount = currentBillingPlan.ValueNumber; result.Value.BillingPlanCode = currentBillingPlan.BillingPlan.Code; return result; } public async Task ExistsWorkspace(WorkspaceIdentificationTypeEnum identificationType, string identificationValue) { var workspace = identificationType == WorkspaceIdentificationTypeEnum.Id ? _repoWorkspace.Get(ArgumentAsLong(nameof(identificationValue), identificationValue)) : identificationType == WorkspaceIdentificationTypeEnum.ApiKey ? _repoWorkspace.GetByApiKey(identificationValue) : _repoWorkspace.GetByName(identificationValue); return workspace != null; } #endregion #region *** Private Operations *** private WorkspaceBilling GetCurrentWorkspaceBillingOrCreate(long workspaceId) { var currentBillingPlan = _repoWorkspaceBilling.GetByCurrentForWorkspace(workspaceId); if (currentBillingPlan == null) { currentBillingPlan = _repoWorkspaceBilling.CreateForWorkspace(workspaceId, _repoBillingPlan.GetByCode(_configuration.Business.DefaultBillingPlanCode)); _repoWorkspaceBilling.Commit(); Log.LogWarning($"Default billing plan was not set for workspace [{workspaceId}]. Set default billing plan '{currentBillingPlan.BillingPlan.Code}'."); } return currentBillingPlan; } #endregion } }