Files
server/src/Admin/Controllers/OrganizationsController.cs
Thomas Rittson 3573aee2ef [AC-1512] Feature: Secrets Manager Billing - round 2 (#3119)
* [AC-1423] Add AddonProduct and BitwardenProduct properties to BillingSubscriptionItem (#3037)

* [AC-1423] Add AddonProduct and BitwardenProduct properties to BillingSubscriptionItem

- Add a helper method to determine the appropriate addon type based on the subscription items StripeId

* [AC-1423] Add helper to StaticStore.cs to find a Plan by StripePlanId

* [AC-1423] Use the helper method to set SubscriptionInfo.BitwardenProduct

* Add SecretsManagerBilling feature flag to Constants

* [AC 1409] Secrets Manager Subscription Stripe Integration  (#3019)

* Adding the Secret manager to the Plan List

* Adding the unit test for the StaticStoreTests class

* Fix whitespace formatting

* Fix whitespace formatting

* Price update

* Resolving the PR comments

* Resolving PR comments

* Fixing the whitespace

* only password manager plans are return for now

* format whitespace

* Resolve the test issue

* Fixing the failing test

* Refactoring the Plan separation

* add a unit test for SingleOrDefault

* Fix the whitespace format

* Separate the PM and SM plans

* Fixing the whitespace

* Remove unnecessary directive

* Fix imports ordering

* Fix imports ordering

* Resolve imports ordering

* Fixing imports ordering

* Fix response model, add MaxProjects

* Fix filename

* Fix format

* Fix: seat price should match annual/monthly

* Fix service account annual pricing

* Changes for secret manager signup and upgradeplan

* Changes for secrets manager signup and upgrade

* refactoring the code

* Format whitespace

* remove unnecessary using directive

* Resolve the PR comment on Subscription creation

* Resolve PR comment

* Add password manager to the error message

* Add UseSecretsManager to the event log

* Resolve PR comment on plan validation

* Resolving pr comments for service account count

* Resolving pr comments for service account count

* Resolve the pr comments

* Remove the store procedure that is no-longer needed

* Rename a property properly

* Resolving the PR comment

* Resolve PR comments

* Resolving PR comments

* Resolving the Pr comments

* Resolving some PR comments

* Resolving the PR comments

* Resolving the build identity build

* Add additional Validation

* Resolve the Lint issues

* remove unnecessary using directive

* Remove the white spaces

* Adding unit test for the stripe payment

* Remove the incomplete test

* Fixing the failing test

* Fix the failing test

* Fix the fail test on organization service

* Fix the failing unit test

* Fix the whitespace format

* Fix the failing test

* Fix the whitespace format

* resolve pr comments

* Fix the lint message

* Resolve the PR comments

* resolve pr comments

* Resolve pr comments

* Resolve the pr comments

* remove unused code

* Added for sm validation test

* Fix the whitespace format issues

---------

Co-authored-by: Thomas Rittson <trittson@bitwarden.com>
Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com>

* SM-802: Add SecretsManagerBetaColumn SQL migration and Org table update

* SM-802: Run EF Migrations for SecretsManagerBeta

* SM-802: Update the two Org procs and View, and move data migration to a separate file

* SM-802: Add missing comma to Organization_Create

* [AC-1418] Add missing SecretsManagerPlan property to OrganizationResponseModel (#3055)

* SM-802: Remove extra GO statement from data migration script

* [AC 1460] Update Stripe Configuration (#3070)

* change the stripeseat id

* change service accountId to align with new product

* make all the Id name for consistent

* SM-802: Add SecretsManagerBeta to OrganizationResponseModel

* SM-802: Move SecretsManagerBeta from OrganizationResponseModel to OrganizationSubscriptionResponseModel. Use sp_refreshview instead of sp_refreshsqlmodule in the migration script.

* SM-802: Remove OrganizationUserOrganizationDetailsView.sql changes

* [AC 1410] Secrets Manager subscription adjustment back-end changes (#3036)

* Create UpgradeSecretsManagerSubscription command

---------

Co-authored-by: Thomas Rittson <trittson@bitwarden.com>

* SM-802: Remove SecretsManagerBetaColumn migration

* SM-802: Add SecretsManagerBetaColumn migration

* SM-802: Remove OrganizationUserOrganizationDetailsView update

* [AC-1495] Extract UpgradePlanAsync into a command (#3081)

* This is a pure lift & shift with no refactors

* Only register subscription commands in Api

---------

Co-authored-by: cyprain-okeke <cokeke@bitwarden.com>

* [AC-1503] Fix Stripe integration on organization upgrade (#3084)

* Fix SM parameters not being passed to Stripe

* Fix flaky test

* Fix error message

* [AC-1504] Allow SM max autoscale limits to be disabled (#3085)

* [AC-1488] Changed SM Signup and Upgrade paths to set SmServiceAccounts to include the plan BaseServiceAccount (#3086)

* [AC-1510] Enable access to Secrets Manager to Organization owner for new Subscription (#3089)

* Revert changes to ReferenceEvent code (#3091)

* Revert changes to ReferenceEvent code

This will be done in AC-1481

* Revert ReferenceEventType change

* Move NoopServiceAccountRepository to SM and update namespace

* [AC-1462] Add secrets manager service accounts autoscaling commands (#3059)

* Adding the Secret manager to the Plan List

* Adding the unit test for the StaticStoreTests class

* Fix whitespace formatting

* Fix whitespace formatting

* Price update

* Resolving the PR comments

* Resolving PR comments

* Fixing the whitespace

* only password manager plans are return for now

* format whitespace

* Resolve the test issue

* Fixing the failing test

* Refactoring the Plan separation

* add a unit test for SingleOrDefault

* Fix the whitespace format

* Separate the PM and SM plans

* Fixing the whitespace

* Remove unnecessary directive

* Fix imports ordering

* Fix imports ordering

* Resolve imports ordering

* Fixing imports ordering

* Fix response model, add MaxProjects

* Fix filename

* Fix format

* Fix: seat price should match annual/monthly

* Fix service account annual pricing

* Changes for secret manager signup and upgradeplan

* Changes for secrets manager signup and upgrade

* refactoring the code

* Format whitespace

* remove unnecessary using directive

* Changes for subscription Update

* Update the seatAdjustment and update

* Resolve the PR comment on Subscription creation

* Resolve PR comment

* Add password manager to the error message

* Add UseSecretsManager to the event log

* Resolve PR comment on plan validation

* Resolving pr comments for service account count

* Resolving pr comments for service account count

* Resolve the pr comments

* Remove the store procedure that is no-longer needed

* Add a new class for update subscription

* Modify the Update subscription for sm

* Add the missing property

* Rename a property properly

* Resolving the PR comment

* Resolve PR comments

* Resolving PR comments

* Resolving the Pr comments

* Resolving some PR comments

* Resolving the PR comments

* Resolving the build identity build

* Add additional Validation

* Resolve the Lint issues

* remove unnecessary using directive

* Remove the white spaces

* Adding unit test for the stripe payment

* Remove the incomplete test

* Fixing the failing test

* Fix the failing test

* Fix the fail test on organization service

* Fix the failing unit test

* Fix the whitespace format

* Fix the failing test

* Fix the whitespace format

* resolve pr comments

* Fix the lint message

* refactor the code

* Fix the failing Test

* adding a new endpoint

* Remove the unwanted code

* Changes for Command and Queries

* changes for command and queries

* Fix the Lint issues

* Fix imports ordering

* Resolve the PR comments

* resolve pr comments

* Resolve pr comments

* Fix the failing test on adjustSeatscommandtests

* Fix the failing test

* Fix the whitespaces

* resolve failing test

* rename a property

* Resolve the pr comments

* refactoring the existing implementation

* Resolve the whitespaces format issue

* Resolve the pr comments

* [AC-1462] Created IAvailableServiceAccountsQuery along its implementation and with unit tests

* [AC-1462] Renamed ICountNewServiceAccountSlotsRequiredQuery

* [AC-1462] Added IAutoscaleServiceAccountsCommand and implementation

* Add more unit testing

* fix the whitespaces issues

* [AC-1462] Added unit tests for AutoscaleServiceAccountsCommand

* Add more unit test

* Remove unnecessary directive

* Resolve some pr comments

* Adding more unit test

* adding more test

* add more test

* Resolving some pr comments

* Resolving some pr comments

* Resolving some pr comments

* resolve some pr comments

* Resolving pr comments

* remove whitespaces

* remove white spaces

* Resolving pr comments

* resolving pr comments and fixing white spaces

* resolving the lint error

* Run dotnet format

* resolving the pr comments

* Add a missing properties to plan response model

* Add the email sender for sm seat and service acct

* Add the email sender for sm seat and service acct

* Fix the failing test after email sender changes

* Add staticstorewrapper to properly test the plans

* Add more test and validate the existing test

* Fix the white spaces issues

* Remove staticstorewrapper and fix the test

* fix a null issue on autoscaling

* Suggestion: do all seat calculations in update model

* Resolve some pr comments

* resolving some pr comments

* Return value is unnecessary

* Resolve the failing test

* resolve pr comments

* Resolve the pr comments

* Resolving admin api failure and adding more test

* Resolve the issue failing admin project

* Fixing the failed test

* Clarify naming and add comments

* Clarify naming conventions

* Dotnet format

* Fix the failing dependency

* remove similar test

* [AC-1462] Rewrote AutoscaleServiceAccountsCommand to use UpdateSecretsManagerSubscriptionCommand which has the same logic

* [AC-1462] Deleted IAutoscaleServiceAccountsCommand as the logic will be moved to UpdateSecretsManagerSubscriptionCommand

* [AC-1462] Created method AdjustSecretsManagerServiceAccountsAsync

* [AC-1462] Changed SecretsManagerSubscriptionUpdate to only be set by its constructor

* [AC-1462] Added check to CountNewServiceAccountSlotsRequiredQuery and revised unit tests

* [AC-1462] Revised logic for CountNewServiceAccountSlotsRequiredQuery and fixed unit tests

* [AC-1462] Changed SecretsManagerSubscriptionUpdate to receive Organization as a parameter and fixed the unit tests

* [AC-1462] Renamed IUpdateSecretsManagerSubscriptionCommand methods UpdateSubscriptionAsync and AdjustServiceAccountsAsync

* [AC-1462] Rewrote unit test UpdateSubscriptionAsync_ValidInput_Passes

* [AC-1462] Registered CountNewServiceAccountSlotsRequiredQuery for dependency injection

* [AC-1462] Added parameter names to SecretsManagerSubscriptionUpdateRequestModel

* [AC-1462] Updated SecretsManagerSubscriptionUpdate logic to handle null parameters. Revised the unit tests to test null values

---------

Co-authored-by: cyprain-okeke <cokeke@bitwarden.com>
Co-authored-by: Thomas Rittson <trittson@bitwarden.com>
Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com>

* Add UsePasswordManager to sync data (#3114)

* [AC-1522] Fix service account check on upgrading (#3111)

* Resolved the checkmarx issues

* [AC-1521] Address checkmarx security feedback (#3124)

* Reinstate target attribute but add noopener noreferrer

* Update date on migration script

* Remove unused constant

* Revert "Remove unused constant"

This reverts commit 4fcb9da4d6.

This is required to make feature flags work on the client

* [AC-1458] Add Endpoint And Service Logic for secrets manager to existing subscription (#3087)

---------

Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com>
Co-authored-by: Thomas Rittson <trittson@bitwarden.com>

* Remove duplicate migrations from incorrectly resolved merge

* [AC-1468] Modified CountNewServiceAccountSlotsRequiredQuery to return zero if organization has SecretsManagerBeta == true (#3112)

Co-authored-by: Thomas Rittson <trittson@bitwarden.com>

* [Ac 1563] Unable to load billing and subscription related pages for non-enterprise organizations (#3138)

* Resolve the failing family plan

* resolve issues

* Resolve code related pr comments

* Resolve test related comments

* Resolving or comments

* [SM-809] Add service account slot limit check (#3093)

* Add service account slot limit check

* Add query to DI

* [AC-1462] Registered CountNewServiceAccountSlotsRequiredQuery for dependency injection

* remove duplicate DI entry

* Update unit tests

* Remove comment

* Code review updates

---------

Co-authored-by: cyprain-okeke <cokeke@bitwarden.com>
Co-authored-by: Thomas Rittson <trittson@bitwarden.com>
Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com>
Co-authored-by: Rui Tome <rtome@bitwarden.com>

* [AC-1461] Secrets manager seat autoscaling (#3121)

* Add autoscaling code to invite user, save user, and bulk enable SM
  flows

* Add tests

* Delete command for BulkEnableSecretsManager

* circular dependency between OrganizationService and
  UpdateSecretsManagerSubscriptionCommand - fixed by temporarily
  duplicating ReplaceAndUpdateCache

* Unresolvable dependencies in other services - fixed by temporarily
  registering noop services and moving around some DI code

All should be resolved in PM-1880

* Refactor: improve the update object and use it to adjust values,
  remove excess interfaces on the command

* Handle autoscaling-specific errors

---------

Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>

* Move bitwarden_license include reference into conditional block

* [AC 1526]Show current SM seat and service account usage in Bitwarden Portal (#3142)

* changes base on the tickets request

* Code refactoring

* Removed the unwanted method

* Add implementation to the new method

* Resolve some pr comments

* resolve lint issue

* resolve pr comments

* add the new noop files

* Add new noop file and resolve some pr comments

* resolve pr comments

* removed unused method

---------

Co-authored-by: Shane Melton <smelton@bitwarden.com>
Co-authored-by: cyprain-okeke <108260115+cyprain-okeke@users.noreply.github.com>
Co-authored-by: Colton Hurst <colton@coltonhurst.com>
Co-authored-by: cyprain-okeke <cokeke@bitwarden.com>
Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
Co-authored-by: Conner Turnbull <cturnbull@bitwarden.com>
Co-authored-by: Rui Tome <rtome@bitwarden.com>
Co-authored-by: Thomas Avery <43214426+Thomas-Avery@users.noreply.github.com>
2023-08-04 21:51:12 +00:00

340 lines
15 KiB
C#

using Bit.Admin.Enums;
using Bit.Admin.Models;
using Bit.Admin.Services;
using Bit.Admin.Utilities;
using Bit.Core.Context;
using Bit.Core.Entities;
using Bit.Core.Enums;
using Bit.Core.Models.OrganizationConnectionConfigs;
using Bit.Core.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnterprise.Interfaces;
using Bit.Core.Repositories;
using Bit.Core.SecretsManager.Repositories;
using Bit.Core.Services;
using Bit.Core.Settings;
using Bit.Core.Tools.Enums;
using Bit.Core.Tools.Models.Business;
using Bit.Core.Tools.Services;
using Bit.Core.Utilities;
using Bit.Core.Vault.Repositories;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Bit.Admin.Controllers;
[Authorize]
public class OrganizationsController : Controller
{
private readonly IOrganizationService _organizationService;
private readonly IOrganizationRepository _organizationRepository;
private readonly IOrganizationUserRepository _organizationUserRepository;
private readonly IOrganizationConnectionRepository _organizationConnectionRepository;
private readonly ISelfHostedSyncSponsorshipsCommand _syncSponsorshipsCommand;
private readonly ICipherRepository _cipherRepository;
private readonly ICollectionRepository _collectionRepository;
private readonly IGroupRepository _groupRepository;
private readonly IPolicyRepository _policyRepository;
private readonly IPaymentService _paymentService;
private readonly ILicensingService _licensingService;
private readonly IApplicationCacheService _applicationCacheService;
private readonly GlobalSettings _globalSettings;
private readonly IReferenceEventService _referenceEventService;
private readonly IUserService _userService;
private readonly IProviderRepository _providerRepository;
private readonly ILogger<OrganizationsController> _logger;
private readonly IAccessControlService _accessControlService;
private readonly ICurrentContext _currentContext;
private readonly ISecretRepository _secretRepository;
private readonly IProjectRepository _projectRepository;
private readonly IServiceAccountRepository _serviceAccountRepository;
public OrganizationsController(
IOrganizationService organizationService,
IOrganizationRepository organizationRepository,
IOrganizationUserRepository organizationUserRepository,
IOrganizationConnectionRepository organizationConnectionRepository,
ISelfHostedSyncSponsorshipsCommand syncSponsorshipsCommand,
ICipherRepository cipherRepository,
ICollectionRepository collectionRepository,
IGroupRepository groupRepository,
IPolicyRepository policyRepository,
IPaymentService paymentService,
ILicensingService licensingService,
IApplicationCacheService applicationCacheService,
GlobalSettings globalSettings,
IReferenceEventService referenceEventService,
IUserService userService,
IProviderRepository providerRepository,
ILogger<OrganizationsController> logger,
IAccessControlService accessControlService,
ICurrentContext currentContext,
ISecretRepository secretRepository,
IProjectRepository projectRepository,
IServiceAccountRepository serviceAccountRepository)
{
_organizationService = organizationService;
_organizationRepository = organizationRepository;
_organizationUserRepository = organizationUserRepository;
_organizationConnectionRepository = organizationConnectionRepository;
_syncSponsorshipsCommand = syncSponsorshipsCommand;
_cipherRepository = cipherRepository;
_collectionRepository = collectionRepository;
_groupRepository = groupRepository;
_policyRepository = policyRepository;
_paymentService = paymentService;
_licensingService = licensingService;
_applicationCacheService = applicationCacheService;
_globalSettings = globalSettings;
_referenceEventService = referenceEventService;
_userService = userService;
_providerRepository = providerRepository;
_logger = logger;
_accessControlService = accessControlService;
_currentContext = currentContext;
_secretRepository = secretRepository;
_projectRepository = projectRepository;
_serviceAccountRepository = serviceAccountRepository;
}
[RequirePermission(Permission.Org_List_View)]
public async Task<IActionResult> Index(string name = null, string userEmail = null, bool? paid = null,
int page = 1, int count = 25)
{
if (page < 1)
{
page = 1;
}
if (count < 1)
{
count = 1;
}
var skip = (page - 1) * count;
var organizations = await _organizationRepository.SearchAsync(name, userEmail, paid, skip, count);
return View(new OrganizationsModel
{
Items = organizations as List<Organization>,
Name = string.IsNullOrWhiteSpace(name) ? null : name,
UserEmail = string.IsNullOrWhiteSpace(userEmail) ? null : userEmail,
Paid = paid,
Page = page,
Count = count,
Action = _globalSettings.SelfHosted ? "View" : "Edit",
SelfHosted = _globalSettings.SelfHosted
});
}
public async Task<IActionResult> View(Guid id)
{
var organization = await _organizationRepository.GetByIdAsync(id);
if (organization == null)
{
return RedirectToAction("Index");
}
var provider = await _providerRepository.GetByOrganizationIdAsync(id);
var ciphers = await _cipherRepository.GetManyByOrganizationIdAsync(id);
var collections = await _collectionRepository.GetManyByOrganizationIdAsync(id);
IEnumerable<Group> groups = null;
if (organization.UseGroups)
{
groups = await _groupRepository.GetManyByOrganizationIdAsync(id);
}
IEnumerable<Policy> policies = null;
if (organization.UsePolicies)
{
policies = await _policyRepository.GetManyByOrganizationIdAsync(id);
}
var users = await _organizationUserRepository.GetManyDetailsByOrganizationAsync(id);
var billingSyncConnection = _globalSettings.EnableCloudCommunication ? await _organizationConnectionRepository.GetByOrganizationIdTypeAsync(id, OrganizationConnectionType.CloudBillingSync) : null;
var secrets = organization.UseSecretsManager ? await _secretRepository.GetSecretsCountByOrganizationIdAsync(id) : -1;
var projects = organization.UseSecretsManager ? await _projectRepository.GetProjectCountByOrganizationIdAsync(id) : -1;
var serviceAccounts = organization.UseSecretsManager ? await _serviceAccountRepository.GetServiceAccountCountByOrganizationIdAsync(id) : -1;
var smSeats = organization.UseSecretsManager
? await _organizationUserRepository.GetOccupiedSmSeatCountByOrganizationIdAsync(organization.Id)
: -1;
return View(new OrganizationViewModel(organization, provider, billingSyncConnection, users, ciphers, collections, groups, policies,
secrets, projects, serviceAccounts, smSeats));
}
[SelfHosted(NotSelfHostedOnly = true)]
public async Task<IActionResult> Edit(Guid id)
{
var organization = await _organizationRepository.GetByIdAsync(id);
if (organization == null)
{
return RedirectToAction("Index");
}
var provider = await _providerRepository.GetByOrganizationIdAsync(id);
var ciphers = await _cipherRepository.GetManyByOrganizationIdAsync(id);
var collections = await _collectionRepository.GetManyByOrganizationIdAsync(id);
IEnumerable<Group> groups = null;
if (organization.UseGroups)
{
groups = await _groupRepository.GetManyByOrganizationIdAsync(id);
}
IEnumerable<Policy> policies = null;
if (organization.UsePolicies)
{
policies = await _policyRepository.GetManyByOrganizationIdAsync(id);
}
var users = await _organizationUserRepository.GetManyDetailsByOrganizationAsync(id);
var billingInfo = await _paymentService.GetBillingAsync(organization);
var billingSyncConnection = _globalSettings.EnableCloudCommunication ? await _organizationConnectionRepository.GetByOrganizationIdTypeAsync(id, OrganizationConnectionType.CloudBillingSync) : null;
var secrets = organization.UseSecretsManager ? await _secretRepository.GetSecretsCountByOrganizationIdAsync(id) : -1;
var projects = organization.UseSecretsManager ? await _projectRepository.GetProjectCountByOrganizationIdAsync(id) : -1;
var serviceAccounts = organization.UseSecretsManager ? await _serviceAccountRepository.GetServiceAccountCountByOrganizationIdAsync(id) : -1;
var smSeats = organization.UseSecretsManager
? await _organizationUserRepository.GetOccupiedSmSeatCountByOrganizationIdAsync(organization.Id)
: -1;
return View(new OrganizationEditModel(organization, provider, users, ciphers, collections, groups, policies,
billingInfo, billingSyncConnection, _globalSettings, secrets, projects, serviceAccounts, smSeats));
}
[HttpPost]
[ValidateAntiForgeryToken]
[SelfHosted(NotSelfHostedOnly = true)]
public async Task<IActionResult> Edit(Guid id, OrganizationEditModel model)
{
var organization = await GetOrganization(id, model);
await _organizationRepository.ReplaceAsync(organization);
await _applicationCacheService.UpsertOrganizationAbilityAsync(organization);
await _referenceEventService.RaiseEventAsync(new ReferenceEvent(ReferenceEventType.OrganizationEditedByAdmin, organization, _currentContext)
{
EventRaisedByUser = _userService.GetUserName(User),
SalesAssistedTrialStarted = model.SalesAssistedTrialStarted,
});
return RedirectToAction("Edit", new { id });
}
[HttpPost]
[ValidateAntiForgeryToken]
[RequirePermission(Permission.Org_Delete)]
public async Task<IActionResult> Delete(Guid id)
{
var organization = await _organizationRepository.GetByIdAsync(id);
if (organization != null)
{
await _organizationRepository.DeleteAsync(organization);
await _applicationCacheService.DeleteOrganizationAbilityAsync(organization.Id);
}
return RedirectToAction("Index");
}
public async Task<IActionResult> TriggerBillingSync(Guid id)
{
var organization = await _organizationRepository.GetByIdAsync(id);
if (organization == null)
{
return RedirectToAction("Index");
}
var connection = (await _organizationConnectionRepository.GetEnabledByOrganizationIdTypeAsync(id, OrganizationConnectionType.CloudBillingSync)).FirstOrDefault();
if (connection != null)
{
try
{
var config = connection.GetConfig<BillingSyncConfig>();
await _syncSponsorshipsCommand.SyncOrganization(id, config.CloudOrganizationId, connection);
TempData["ConnectionActivated"] = id;
TempData["ConnectionError"] = null;
}
catch (Exception ex)
{
TempData["ConnectionError"] = ex.Message;
_logger.LogWarning(ex, "Error while attempting to do billing sync for organization with id '{OrganizationId}'", id);
}
if (_globalSettings.SelfHosted)
{
return RedirectToAction("View", new { id });
}
else
{
return RedirectToAction("Edit", new { id });
}
}
return RedirectToAction("Index");
}
[HttpPost]
public async Task<IActionResult> ResendOwnerInvite(Guid id)
{
var organization = await _organizationRepository.GetByIdAsync(id);
if (organization == null)
{
return RedirectToAction("Index");
}
var organizationUsers = await _organizationUserRepository.GetManyByOrganizationAsync(id, OrganizationUserType.Owner);
foreach (var organizationUser in organizationUsers)
{
await _organizationService.ResendInviteAsync(id, null, organizationUser.Id, true);
}
return Json(null);
}
private async Task<Organization> GetOrganization(Guid id, OrganizationEditModel model)
{
var organization = await _organizationRepository.GetByIdAsync(id);
if (_accessControlService.UserHasPermission(Permission.Org_CheckEnabledBox))
{
organization.Enabled = model.Enabled;
}
if (_accessControlService.UserHasPermission(Permission.Org_Plan_Edit))
{
organization.PlanType = model.PlanType.Value;
organization.Plan = model.Plan;
organization.Seats = model.Seats;
organization.MaxAutoscaleSeats = model.MaxAutoscaleSeats;
organization.MaxCollections = model.MaxCollections;
organization.MaxStorageGb = model.MaxStorageGb;
//features
organization.SelfHost = model.SelfHost;
organization.Use2fa = model.Use2fa;
organization.UseApi = model.UseApi;
organization.UseGroups = model.UseGroups;
organization.UsePolicies = model.UsePolicies;
organization.UseSso = model.UseSso;
organization.UseKeyConnector = model.UseKeyConnector;
organization.UseScim = model.UseScim;
organization.UseDirectory = model.UseDirectory;
organization.UseEvents = model.UseEvents;
organization.UseResetPassword = model.UseResetPassword;
organization.UseCustomPermissions = model.UseCustomPermissions;
organization.UseTotp = model.UseTotp;
organization.UsersGetPremium = model.UsersGetPremium;
organization.UseSecretsManager = model.UseSecretsManager;
organization.SecretsManagerBeta = model.SecretsManagerBeta;
//secrets
organization.SmSeats = model.SmSeats;
organization.MaxAutoscaleSmSeats = model.MaxAutoscaleSmSeats;
organization.SmServiceAccounts = model.SmServiceAccounts;
organization.MaxAutoscaleSmServiceAccounts = model.MaxAutoscaleSmServiceAccounts;
}
if (_accessControlService.UserHasPermission(Permission.Org_Licensing_Edit))
{
organization.LicenseKey = model.LicenseKey;
organization.ExpirationDate = model.ExpirationDate;
}
if (_accessControlService.UserHasPermission(Permission.Org_Billing_Edit))
{
organization.BillingEmail = model.BillingEmail?.ToLowerInvariant()?.Trim();
organization.Gateway = model.Gateway;
organization.GatewayCustomerId = model.GatewayCustomerId;
organization.GatewaySubscriptionId = model.GatewaySubscriptionId;
}
return organization;
}
}