1
0
mirror of https://github.com/bitwarden/server.git synced 2024-11-30 13:33:24 +01:00
bitwarden-server/util/Migrator/DbScripts/2022-03-01_00_AddApiKeysTable.sql
Matt Gibson c54c39b28c
Feature/self hosted families for enterprise (#1991)
* Families for enterprise/split up organization sponsorship service (#1829)

* Split OrganizationSponsorshipService into commands

* Use tokenable for token validation

* Use interfaces to set up for DI

* Use commands over services

* Move service tests to command tests

* Value types can't be null

* Run dotnet format

* Update src/Core/OrganizationFeatures/OrganizationSponsorships/FamiliesForEnterprise/CancelSponsorshipCommand.cs

Co-authored-by: Justin Baur <admin@justinbaur.com>

* Fix controller tests

Co-authored-by: Justin Baur <admin@justinbaur.com>

* Families for enterprise/split up organization sponsorship service (#1875)

* Split OrganizationSponsorshipService into commands

* Use tokenable for token validation

* Use interfaces to set up for DI

* Use commands over services

* Move service tests to command tests

* Value types can't be null

* Run dotnet format

* Update src/Core/OrganizationFeatures/OrganizationSponsorships/FamiliesForEnterprise/CancelSponsorshipCommand.cs

Co-authored-by: Justin Baur <admin@justinbaur.com>

* Fix controller tests

* Split create and send sponsorships

* Split up create sponsorship

* Add self hosted commands to dependency injection

* Add field to store cloud billing sync key on self host instances

* Fix typo

* Fix data protector purpose of sponsorship offers

* Split cloud and selfhosted sponsorship offer tokenable

* Generate offer from self hosted with all necessary auth data

* Add Required properties to constructor

* Split up cancel sponsorship command

* Split revoke sponsorship command between cloud and self hosted

* Fix/f4e multiple sponsorships (#1838)

* Use sponosorship from validate to redeem

* Update tests

* Format

* Remove sponsorship service

* Run dotnet format

* Fix self hosted only controller attribute

* Clean up file structure and fixes

* Remove unneeded tokenables

* Remove obsolete commands

* Do not require file/class prefix if unnecessary

* Update Organizaiton sprocs

* Remove unnecessary models

* Fix tests

* Generalize LicenseService path calculation

Use async file read and deserialization

* Use interfaces for testability

* Remove unused usings

* Correct test direction

* Test license reading

* remove unused usings

* Format

Co-authored-by: Justin Baur <admin@justinbaur.com>

* Improve DataProtectorTokenFactory test coverage (#1884)

* Add encstring to server

* Test factory

Co-authored-by: Carlos Muentes <cmuentes@bitwarden.com>

* Format

* Remove SymmetricKeyProtectedString

Not needed

* Set ForcInvalid

Co-authored-by: Carlos Muentes <cmuentes@bitwarden.com>

* Feature/self f4e/api keys (#1896)

* Add in ApiKey

* Work on API Key table

* Work on apikey table

* Fix response model

* Work on information for UI

* Work on last sync date

* Work on sync status

* Work on auth

* Work on tokenable

* Work on merge

* Add custom requirement

* Add policy

* Run formatting

* Work on EF Migrations

* Work on OrganizationConnection

* Work on database

* Work on additional database table

* Run formatting

* Small fixes

* More cleanup

* Cleanup

* Add RevisionDate

* Add GO

* Finish Sql project

* Add newlines

* Fix stored proc file

* Fix sqlproj

* Add newlines

* Fix table

* Add navigation property

* Delete Connections when organization is deleted

* Add connection validation

* Start adding ID column

* Work on ID column

* Work on SQL migration

* Work on migrations

* Run formatting

* Fix test build

* Fix sprocs

* Work on migrations

* Fix Create table

* Fix sproc

* Add prints to migration

* Add default value

* Update EF migrations

* Formatting

* Add to integration tests

* Minor fixes

* Formatting

* Cleanup

* Address PR feedback

* Address more PR feedback

* Fix formatting

* Fix formatting

* Fix

* Address PR feedback

* Remove accidential change

* Fix SQL build

* Run formatting

* Address PR feedback

* Add sync data to OrganizationUserOrgDetails

* Add comments

* Remove OrganizationConnectionService interface

* Remove unused using

* Address PR feedback

* Formatting

* Minor fix

* Feature/self f4e/update db (#1930)

* Fix migration

* Fix TimesRenewed

* Add comments

* Make two properties non-nullable

* Remove need for SponsoredOrg on SH (#1934)

* Remove need for SponsoredOrg on SH

* Add Family prefix

* Add check for enterprise org on BillingSync key (#1936)

* [PS-10] Feature/sponsorships removed at end of term (#1938)

* Rename commands to min unique names

* Inject revoke command based on self hosting

* WIP: Remove/Revoke marks to delete

* Complete WIP

* Improve remove/revoke tests

* PR review

* Fail validation if sponsorship has failed to sync for 6 months

* Feature/do not accept old self host sponsorships (#1939)

* Do not accept >6mo old self-hosted sponsorships

* Give disabled grace period of 3 months

* Fix issues of Sql.proj differing from migration outcome (#1942)

* Fix issues of Sql.proj differing from migration outcome

* Yoink int tests

* Add missing assert helpers

* Feature/org sponsorship sync (#1922)

* Self-hosted side sync first pass

TODO:
* flush out org sponsorship model
* implement cloud side
* process cloud-side response and update self-hosted records

* sync scaffolding second pass

* remove list of Org User ids from sync and begin work on SelfHostedRevokeSponsorship

* allow authenticated http calls from server to return a result

* update models

* add logic for sync and change offer email template

* add billing sync key and hide CreateSponsorship without user

* fix tests

* add job scheduling

* add authorize attributes to endpoints

* separate models into data/model and request/response

* batch sync more, add EnableCloudCommunication for testing

* send emails in bulk

* make userId and sponsorshipType non nullable

* batch more on self hosted side of sync

* remove TODOs and formatting

* changed logic of cloud sync

* let BaseIdentityClientService handle all logging

* call sync from scheduled job on self host

* create bulk db operations for OrganizationSponsorships

* remove SponsoredOrgId from sync, return default from server http call

* validate BillingSyncKey during sync

revert changes to CreateSponsorshipCommand

* revert changes to ICreateSponsorshipCommand

* add some tests

* add DeleteExpiredSponsorshipsJob

* add cloud sync test

* remove extra method

* formatting

* prevent new sponsorships from disabled orgs

* update packages

* - pulled out send sponsorship command dependency from sync on cloud
- don't throw error when sponsorships are empty
- formatting

* formatting models

* more formatting

* remove licensingService dependency from selfhosted sync

* use installation urls and formatting

* create constructor for RequestModel and formatting

* add date parameter to OrganizationSponsorship_DeleteExpired

* add new migration

* formatting

* rename OrganizationCreateSponsorshipRequestModel to OrganizationSponsorshipCreateRequestModel

* prevent whole sync from failing if one sponsorship type is unsupported

* deserialize config and billingsynckey from org connection

* alter log message when sync disabled

* Add grace period to disabled orgs

* return early on self hosted if there are no sponsorships in database

* rename BillingSyncConfig

* send sponsorship offers from controller

* allow config to be a null object

* better exception handling in sync scheduler

* add ef migrations

* formatting

* fix tests

* fix validate test

Co-authored-by: Matt Gibson <mgibson@bitwarden.com>

* Fix OrganizationApiKey issues (#1941)

Co-authored-by: Justin Baur <admin@justinbaur.com>

* Feature/org sponsorship self hosted tests (#1947)

* Self-hosted side sync first pass

TODO:
* flush out org sponsorship model
* implement cloud side
* process cloud-side response and update self-hosted records

* sync scaffolding second pass

* remove list of Org User ids from sync and begin work on SelfHostedRevokeSponsorship

* allow authenticated http calls from server to return a result

* update models

* add logic for sync and change offer email template

* add billing sync key and hide CreateSponsorship without user

* fix tests

* add job scheduling

* add authorize attributes to endpoints

* separate models into data/model and request/response

* batch sync more, add EnableCloudCommunication for testing

* send emails in bulk

* make userId and sponsorshipType non nullable

* batch more on self hosted side of sync

* remove TODOs and formatting

* changed logic of cloud sync

* let BaseIdentityClientService handle all logging

* call sync from scheduled job on self host

* create bulk db operations for OrganizationSponsorships

* remove SponsoredOrgId from sync, return default from server http call

* validate BillingSyncKey during sync

revert changes to CreateSponsorshipCommand

* revert changes to ICreateSponsorshipCommand

* add some tests

* add DeleteExpiredSponsorshipsJob

* add cloud sync test

* remove extra method

* formatting

* prevent new sponsorships from disabled orgs

* update packages

* - pulled out send sponsorship command dependency from sync on cloud
- don't throw error when sponsorships are empty
- formatting

* formatting models

* more formatting

* remove licensingService dependency from selfhosted sync

* use installation urls and formatting

* create constructor for RequestModel and formatting

* add date parameter to OrganizationSponsorship_DeleteExpired

* add new migration

* formatting

* rename OrganizationCreateSponsorshipRequestModel to OrganizationSponsorshipCreateRequestModel

* prevent whole sync from failing if one sponsorship type is unsupported

* deserialize config and billingsynckey from org connection

* add mockHttp nuget package and use httpclientfactory

* fix current tests

* WIP of creating tests

* WIP of new self hosted tests

* WIP self hosted tests

* finish self hosted tests

* formatting

* format of interface

* remove extra config file

* added newlines

Co-authored-by: Matt Gibson <mgibson@bitwarden.com>

* Fix Organization_DeleteById (#1950)

* Fix Organization_Delete

* Fix L

* [PS-4] block enterprise user from sponsoring itself (#1943)

* [PS-248] Feature/add connections enabled endpoint (#1953)

* Move Organization models to sub namespaces

* Add Organization Connection api endpoints

* Get all connections rather than just enabled ones

* Add missing services to DI

* pluralize private api endpoints

* Add type protection to org connection request/response

* Fix route

* Use nullable Id to signify no connection

* Test Get Connections enabled

* Fix data discoverer

* Also drop this sproc for rerunning

* Id is the OUTPUT of create sprocs

* Fix connection config parsing

* Linter fixes

* update sqlproj file name

* Use param xdocs on methods

* Simplify controller path attribute

* Use JsonDocument to avoid escaped json in our response/request strings

* Fix JsonDoc tests

* Linter fixes

* Fix ApiKey Command and add tests (#1949)

* Fix ApiKey command

* Formatting

* Fix test failures introduced in #1943 (#1957)

* Remove "Did you know?" copy from emails. (#1962)

* Remove "Did you know"

* Remove jsonIf helper

* Feature/fix send single sponsorship offer email (#1956)

* Fix sponsorship offer email

* Do not sanitize org name

* PR feedback

* Feature/f4e sync event [PS-75] (#1963)

* Create sponsorship sync event type

* Add InstallationId to Event model

* Add combinatorics-based test case generators

* Log sponsorships sync event on sync

* Linter and test fixes

* Fix failing test

* Migrate sprocs and view

* Remove unused `using`s

* [PS-190] Add manual sync trigger in self hosted (#1955)

* WIP add button to admin project for billing sync

* add connection table to view page

* minor fixes for self hosted side of sync

* fixes number of bugs for cloud side of sync

* deserialize before returning for some reason

* add json attributes to return models

* list of sponsorships parameter is immutable, add secondary list

* change sproc name

* add error handling

* Fix tests

* modify call to connection

* Update src/Admin/Controllers/OrganizationsController.cs

Co-authored-by: Matt Gibson <mgibson@bitwarden.com>

* undo change to sproc name

* simplify logic

* Update src/Core/OrganizationFeatures/OrganizationSponsorships/FamiliesForEnterprise/Cloud/CloudSyncSponsorshipsCommand.cs

Co-authored-by: Matt Gibson <mgibson@bitwarden.com>

* register services despite if self hosted or cloud

* remove json properties

* revert merge conflict

Co-authored-by: Matt Gibson <mgibson@bitwarden.com>

* Update OrganizationSponsorship valid until when updating org expirati… (#1966)

* Update OrganizationSponsorship valid until when updating org expiration date

* Linter fixes

* [PS-7] change revert email copy and add ValidUntil to sponsorship (#1965)

* change revert email copy and add ValidUntil to sponsorship

* add 15 days if no ValidUntil

* Chore/merge/self hosted families for enterprise (#1972)

* Log swallowed HttpRequestExceptions (#1866)

Co-authored-by: Hinton <oscar@oscarhinton.com>

* Allow for utilization of  readonly db connection (#1937)

* Bump the pin of the download-artifacts action to bypass the broken GitHub api (#1952)

* Bumped version to 1.48.0 (#1958)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* [EC-160] Give Provider Users access to all org ciphers and collections (#1959)

* Bumped version to 1.48.1 (#1961)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Avoid sending "user need confirmation" emails when there are no org admins (#1960)

* Remove noncompliant users for new policies (#1951)

* [PS-284] Allow installation clients to not need a user. (#1968)

* Allow installation clients to not need a user.

* Run formatting

Co-authored-by: Andrei <30410186+Manolachi@users.noreply.github.com>
Co-authored-by: Hinton <oscar@oscarhinton.com>
Co-authored-by: sneakernuts <671942+sneakernuts@users.noreply.github.com>
Co-authored-by: Joseph Flinn <58369717+joseph-flinn@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com>
Co-authored-by: Justin Baur <136baur@gmail.com>

* Fix/license file not found (#1974)

* Handle null license

* Throw hint message if license is not found by the admin project.

* Use CloudOrganizationId from Connection config

* Change test to support change

* Fix test

Co-authored-by: Matt Gibson <mgibson@bitwarden.com>

* Feature/f4e selfhosted rename migration to .sql (#1971)

* rename migration to .sql

* format

* Add unit tests to self host F4E (#1975)

* Work on tests

* Added more tests

* Run linting

* Address PR feedback

* Fix AssertRecent

* Linting

* Fixed empty tests

* Fix/misc self hosted f4e (#1973)

* Allow setting of ApiUri

* Return updates sponsorshipsData objects

* Bind arguments by name

* Greedy load sponsorships to email.

When upsert was called, it creates Ids on _all_ records, which meant
that the lazy-evaluation from this call always returned an empty list.

* add scope for sync command DI in job. simplify error logic

* update the sync job to get CloudOrgId from the BillingSyncKey

Co-authored-by: Jacob Fink <jfink@bitwarden.com>

* Chore/merge/self hosted families for enterprise (#1987)

* Log swallowed HttpRequestExceptions (#1866)

Co-authored-by: Hinton <oscar@oscarhinton.com>

* Allow for utilization of  readonly db connection (#1937)

* Bump the pin of the download-artifacts action to bypass the broken GitHub api (#1952)

* Bumped version to 1.48.0 (#1958)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* [EC-160] Give Provider Users access to all org ciphers and collections (#1959)

* Bumped version to 1.48.1 (#1961)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Avoid sending "user need confirmation" emails when there are no org admins (#1960)

* Remove noncompliant users for new policies (#1951)

* [PS-284] Allow installation clients to not need a user. (#1968)

* Allow installation clients to not need a user.

* Run formatting

* Use accept flow for sponsorship offers (#1964)

* PS-82 check send 2FA email for new devices on TwoFactorController send-email-login (#1977)

* [Bug] Skip WebAuthn 2fa event logs during login flow (#1978)

* [Bug] Supress WebAuthn 2fa event logs during login process

* Formatting

* Simplified method call with new paramter input

* Update RealIps Description (#1980)

Describe the syntax of the real_ips configuration key with an example, to prevent type errors in the `setup` container when parsing `config.yml`

* add proper URI validation to duo host (#1984)

* captcha scores (#1967)

* captcha scores

* some api fixes

* check bot on captcha attribute

* Update src/Core/Services/Implementations/HCaptchaValidationService.cs

Co-authored-by: e271828- <e271828-@users.noreply.github.com>

Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com>
Co-authored-by: e271828- <e271828-@users.noreply.github.com>

* ensure no path specific in duo host (#1985)

Co-authored-by: Andrei <30410186+Manolachi@users.noreply.github.com>
Co-authored-by: Hinton <oscar@oscarhinton.com>
Co-authored-by: sneakernuts <671942+sneakernuts@users.noreply.github.com>
Co-authored-by: Joseph Flinn <58369717+joseph-flinn@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com>
Co-authored-by: Justin Baur <136baur@gmail.com>
Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>
Co-authored-by: Vincent Salucci <26154748+vincentsalucci@users.noreply.github.com>
Co-authored-by: Jordan Cooks <notnamed@users.noreply.github.com>
Co-authored-by: Kyle Spearrin <kspearrin@users.noreply.github.com>
Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com>
Co-authored-by: e271828- <e271828-@users.noreply.github.com>

* Address feedback (#1990)

Co-authored-by: Justin Baur <admin@justinbaur.com>
Co-authored-by: Carlos Muentes <cmuentes@bitwarden.com>
Co-authored-by: Jake Fink <jfink@bitwarden.com>
Co-authored-by: Justin Baur <136baur@gmail.com>
Co-authored-by: Andrei <30410186+Manolachi@users.noreply.github.com>
Co-authored-by: Hinton <oscar@oscarhinton.com>
Co-authored-by: sneakernuts <671942+sneakernuts@users.noreply.github.com>
Co-authored-by: Joseph Flinn <58369717+joseph-flinn@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com>
Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>
Co-authored-by: Vincent Salucci <26154748+vincentsalucci@users.noreply.github.com>
Co-authored-by: Jordan Cooks <notnamed@users.noreply.github.com>
Co-authored-by: Kyle Spearrin <kspearrin@users.noreply.github.com>
Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com>
Co-authored-by: e271828- <e271828-@users.noreply.github.com>
2022-05-10 16:12:09 -05:00

1012 lines
24 KiB
Transact-SQL

-- Create Organization ApiKey table
IF OBJECT_ID('[dbo].[OrganizationApiKey]') IS NULL
BEGIN
CREATE TABLE [dbo].[OrganizationApiKey] (
[Id] UNIQUEIDENTIFIER NOT NULL,
[OrganizationId] UNIQUEIDENTIFIER NOT NULL,
[Type] TINYINT NOT NULL,
[ApiKey] VARCHAR(30) NOT NULL,
[RevisionDate] DATETIME2(7) NOT NULL,
CONSTRAINT [PK_OrganizationApiKey] PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_OrganizationApiKey_OrganizationId] FOREIGN KEY ([OrganizationId]) REFERENCES [dbo].[Organization] ([Id])
);
END
GO
-- Create indexes for OrganizationApiKey
IF NOT EXISTS(SELECT name FROM sys.indexes WHERE name = 'IX_OrganizationApiKey_OrganizationId')
BEGIN
CREATE NONCLUSTERED INDEX [IX_OrganizationApiKey_OrganizationId]
ON [dbo].[OrganizationApiKey]([OrganizationId] ASC);
END
GO
IF NOT EXISTS(SELECT name FROM sys.indexes WHERE name = 'IX_OrganizationApiKey_ApiKey')
BEGIN
CREATE NONCLUSTERED INDEX [IX_OrganizationApiKey_ApiKey]
ON [dbo].[OrganizationApiKey]([ApiKey] ASC);
END
GO
IF EXISTS(SELECT * FROM sys.views WHERE [Name] = 'OrganizationApiKeyView')
BEGIN
DROP VIEW [dbo].[OrganizationApiKeyView];
END
GO
CREATE VIEW [dbo].[OrganizationApiKeyView]
AS
SELECT
*
FROM
[dbo].[OrganizationApiKey]
GO
IF OBJECT_ID('[dbo].[OrganizationApiKey_Create]') IS NOT NULL
BEGIN
DROP PROCEDURE [dbo].[OrganizationApiKey_Create]
END
GO
CREATE PROCEDURE [dbo].[OrganizationApiKey_Create]
@Id UNIQUEIDENTIFIER OUTPUT,
@OrganizationId UNIQUEIDENTIFIER,
@ApiKey VARCHAR(30),
@Type TINYINT,
@RevisionDate DATETIME2(7)
AS
BEGIN
SET NOCOUNT ON
INSERT INTO [dbo].[OrganizationApiKey]
(
[Id],
[OrganizationId],
[ApiKey],
[Type],
[RevisionDate]
)
VALUES
(
@Id,
@OrganizationId,
@ApiKey,
@Type,
@RevisionDate
)
END
GO
IF OBJECT_ID('[dbo].[OrganizationApiKey_Update]') IS NOT NULL
BEGIN
DROP PROCEDURE [dbo].[OrganizationApiKey_Update]
END
GO
CREATE PROCEDURE [dbo].[OrganizationApiKey_Update]
@Id UNIQUEIDENTIFIER,
@OrganizationId UNIQUEIDENTIFIER,
@Type TINYINT,
@ApiKey VARCHAR(30),
@RevisionDate DATETIME2(7)
AS
BEGIN
SET NOCOUNT ON
UPDATE
[dbo].[OrganizationApiKey]
SET
[ApiKey] = @ApiKey,
[RevisionDate] = @RevisionDate
WHERE
[Id] = @Id
END
GO
IF OBJECT_ID('[dbo].[OrganizationApiKey_DeleteById]') IS NOT NULL
BEGIN
DROP PROCEDURE [dbo].[OrganizationApiKey_DeleteById]
END
GO
CREATE PROCEDURE [dbo].[OrganizationApiKey_DeleteById]
@Id UNIQUEIDENTIFIER
AS
BEGIN
SET NOCOUNT ON
DELETE FROM [dbo].[OrganizationApiKey]
WHERE [Id] = @Id
END
GO
IF OBJECT_ID('[dbo].[OrganizationApiKey_ReadManyByOrganizationIdType]') IS NOT NULL
BEGIN
DROP PROCEDURE [dbo].[OrganizationApiKey_ReadManyByOrganizationIdType]
END
GO
CREATE PROCEDURE [dbo].[OrganizationApiKey_ReadManyByOrganizationIdType]
@OrganizationId UNIQUEIDENTIFIER,
@Type TINYINT = NULL
AS
BEGIN
SET NOCOUNT ON
SELECT
*
FROM
[dbo].[OrganizationApiKeyView]
WHERE
[OrganizationId] = @OrganizationId AND
(@Type IS NULL OR [Type] = @Type)
END
GO
IF OBJECT_ID('[dbo].[OrganizationApiKey_OrganizationDeleted]') IS NOT NULL
BEGIN
DROP PROCEDURE [dbo].[OrganizationApiKey_OrganizationDeleted]
END
GO
CREATE PROCEDURE [dbo].[OrganizationApiKey_OrganizationDeleted]
@OrganizationId UNIQUEIDENTIFIER
AS
BEGIN
SET NOCOUNT ON
DELETE
FROM
[dbo].[OrganizationApiKey]
WHERE
[OrganizationId] = @OrganizationId
END
GO
PRINT N'Creating GenerateComb Function'
GO
CREATE OR ALTER FUNCTION [dbo].[GenerateComb] (@time DATETIME, @uuid UNIQUEIDENTIFIER)
RETURNS UNIQUEIDENTIFIER
AS
BEGIN
DECLARE @comb UNIQUEIDENTIFIER;
SELECT @comb = CAST(
CAST(@uuid AS BINARY(10)) +
CAST(@time AS BINARY(6))
AS UNIQUEIDENTIFIER);
RETURN @comb
END;
GO
IF COL_LENGTH('[dbo].[Organization]', 'ApiKey') IS NOT NULl
BEGIN
BEGIN TRANSACTION MigrateOrganizationApiKeys
PRINT N'Migrating Organization ApiKeys'
INSERT INTO [dbo].[OrganizationApiKey]
(
[Id],
[OrganizationId],
[ApiKey],
[Type],
[RevisionDate]
)
SELECT
[dbo].[GenerateComb]([CreationDate], NEWID()),
[Id] AS [OrganizationId],
[ApiKey],
0 AS [Type], -- 0 represents 'Default' type
[RevisionDate]
FROM [dbo].[Organization]
PRINT N'Dropping old column'
ALTER TABLE
[dbo].[Organization]
DROP COLUMN
[ApiKey]
COMMIT TRANSACTION MigrateOrganizationApiKeys;
END
GO
DROP FUNCTION [dbo].[GenerateComb];
GO
IF OBJECT_ID('[dbo].[Organization_Create]') IS NOT NULL
BEGIN
DROP PROCEDURE [dbo].[Organization_Create]
END
GO
CREATE PROCEDURE [dbo].[Organization_Create]
@Id UNIQUEIDENTIFIER OUTPUT,
@Identifier NVARCHAR(50),
@Name NVARCHAR(50),
@BusinessName NVARCHAR(50),
@BusinessAddress1 NVARCHAR(50),
@BusinessAddress2 NVARCHAR(50),
@BusinessAddress3 NVARCHAR(50),
@BusinessCountry VARCHAR(2),
@BusinessTaxNumber NVARCHAR(30),
@BillingEmail NVARCHAR(256),
@Plan NVARCHAR(50),
@PlanType TINYINT,
@Seats INT,
@MaxCollections SMALLINT,
@UsePolicies BIT,
@UseSso BIT,
@UseGroups BIT,
@UseDirectory BIT,
@UseEvents BIT,
@UseTotp BIT,
@Use2fa BIT,
@UseApi BIT,
@UseResetPassword BIT,
@SelfHost BIT,
@UsersGetPremium BIT,
@Storage BIGINT,
@MaxStorageGb SMALLINT,
@Gateway TINYINT,
@GatewayCustomerId VARCHAR(50),
@GatewaySubscriptionId VARCHAR(50),
@ReferenceData VARCHAR(MAX),
@Enabled BIT,
@LicenseKey VARCHAR(100),
@PublicKey VARCHAR(MAX),
@PrivateKey VARCHAR(MAX),
@TwoFactorProviders NVARCHAR(MAX),
@ExpirationDate DATETIME2(7),
@CreationDate DATETIME2(7),
@RevisionDate DATETIME2(7),
@OwnersNotifiedOfAutoscaling DATETIME2(7),
@MaxAutoscaleSeats INT,
@UseKeyConnector BIT = 0
AS
BEGIN
SET NOCOUNT ON
INSERT INTO [dbo].[Organization]
(
[Id],
[Identifier],
[Name],
[BusinessName],
[BusinessAddress1],
[BusinessAddress2],
[BusinessAddress3],
[BusinessCountry],
[BusinessTaxNumber],
[BillingEmail],
[Plan],
[PlanType],
[Seats],
[MaxCollections],
[UsePolicies],
[UseSso],
[UseGroups],
[UseDirectory],
[UseEvents],
[UseTotp],
[Use2fa],
[UseApi],
[UseResetPassword],
[SelfHost],
[UsersGetPremium],
[Storage],
[MaxStorageGb],
[Gateway],
[GatewayCustomerId],
[GatewaySubscriptionId],
[ReferenceData],
[Enabled],
[LicenseKey],
[PublicKey],
[PrivateKey],
[TwoFactorProviders],
[ExpirationDate],
[CreationDate],
[RevisionDate],
[OwnersNotifiedOfAutoscaling],
[MaxAutoscaleSeats],
[UseKeyConnector]
)
VALUES
(
@Id,
@Identifier,
@Name,
@BusinessName,
@BusinessAddress1,
@BusinessAddress2,
@BusinessAddress3,
@BusinessCountry,
@BusinessTaxNumber,
@BillingEmail,
@Plan,
@PlanType,
@Seats,
@MaxCollections,
@UsePolicies,
@UseSso,
@UseGroups,
@UseDirectory,
@UseEvents,
@UseTotp,
@Use2fa,
@UseApi,
@UseResetPassword,
@SelfHost,
@UsersGetPremium,
@Storage,
@MaxStorageGb,
@Gateway,
@GatewayCustomerId,
@GatewaySubscriptionId,
@ReferenceData,
@Enabled,
@LicenseKey,
@PublicKey,
@PrivateKey,
@TwoFactorProviders,
@ExpirationDate,
@CreationDate,
@RevisionDate,
@OwnersNotifiedOfAutoscaling,
@MaxAutoscaleSeats,
@UseKeyConnector
)
END
GO
IF OBJECT_ID('[dbo].[Organization_Update]') IS NOT NULL
BEGIN
DROP PROCEDURE [dbo].[Organization_Update]
END
GO
CREATE PROCEDURE [dbo].[Organization_Update]
@Id UNIQUEIDENTIFIER,
@Identifier NVARCHAR(50),
@Name NVARCHAR(50),
@BusinessName NVARCHAR(50),
@BusinessAddress1 NVARCHAR(50),
@BusinessAddress2 NVARCHAR(50),
@BusinessAddress3 NVARCHAR(50),
@BusinessCountry VARCHAR(2),
@BusinessTaxNumber NVARCHAR(30),
@BillingEmail NVARCHAR(256),
@Plan NVARCHAR(50),
@PlanType TINYINT,
@Seats INT,
@MaxCollections SMALLINT,
@UsePolicies BIT,
@UseSso BIT,
@UseGroups BIT,
@UseDirectory BIT,
@UseEvents BIT,
@UseTotp BIT,
@Use2fa BIT,
@UseApi BIT,
@UseResetPassword BIT,
@SelfHost BIT,
@UsersGetPremium BIT,
@Storage BIGINT,
@MaxStorageGb SMALLINT,
@Gateway TINYINT,
@GatewayCustomerId VARCHAR(50),
@GatewaySubscriptionId VARCHAR(50),
@ReferenceData VARCHAR(MAX),
@Enabled BIT,
@LicenseKey VARCHAR(100),
@PublicKey VARCHAR(MAX),
@PrivateKey VARCHAR(MAX),
@TwoFactorProviders NVARCHAR(MAX),
@ExpirationDate DATETIME2(7),
@CreationDate DATETIME2(7),
@RevisionDate DATETIME2(7),
@OwnersNotifiedOfAutoscaling DATETIME2(7),
@MaxAutoscaleSeats INT,
@UseKeyConnector BIT = 0
AS
BEGIN
SET NOCOUNT ON
UPDATE
[dbo].[Organization]
SET
[Identifier] = @Identifier,
[Name] = @Name,
[BusinessName] = @BusinessName,
[BusinessAddress1] = @BusinessAddress1,
[BusinessAddress2] = @BusinessAddress2,
[BusinessAddress3] = @BusinessAddress3,
[BusinessCountry] = @BusinessCountry,
[BusinessTaxNumber] = @BusinessTaxNumber,
[BillingEmail] = @BillingEmail,
[Plan] = @Plan,
[PlanType] = @PlanType,
[Seats] = @Seats,
[MaxCollections] = @MaxCollections,
[UsePolicies] = @UsePolicies,
[UseSso] = @UseSso,
[UseGroups] = @UseGroups,
[UseDirectory] = @UseDirectory,
[UseEvents] = @UseEvents,
[UseTotp] = @UseTotp,
[Use2fa] = @Use2fa,
[UseApi] = @UseApi,
[UseResetPassword] = @UseResetPassword,
[SelfHost] = @SelfHost,
[UsersGetPremium] = @UsersGetPremium,
[Storage] = @Storage,
[MaxStorageGb] = @MaxStorageGb,
[Gateway] = @Gateway,
[GatewayCustomerId] = @GatewayCustomerId,
[GatewaySubscriptionId] = @GatewaySubscriptionId,
[ReferenceData] = @ReferenceData,
[Enabled] = @Enabled,
[LicenseKey] = @LicenseKey,
[PublicKey] = @PublicKey,
[PrivateKey] = @PrivateKey,
[TwoFactorProviders] = @TwoFactorProviders,
[ExpirationDate] = @ExpirationDate,
[CreationDate] = @CreationDate,
[RevisionDate] = @RevisionDate,
[OwnersNotifiedOfAutoscaling] = @OwnersNotifiedOfAutoscaling,
[MaxAutoscaleSeats] = @MaxAutoscaleSeats,
[UseKeyConnector] = @UseKeyConnector
WHERE
[Id] = @Id
END
GO
IF OBJECT_ID('[dbo].[OrganizationView]') IS NOT NULL
BEGIN
DROP VIEW [dbo].[OrganizationView]
END
GO
CREATE VIEW [dbo].[OrganizationView]
AS
SELECT
*
FROM
[dbo].[Organization]
GO
IF OBJECT_ID('[dbo].[OrganizationConnection]') IS NULL
BEGIN
CREATE TABLE [dbo].[OrganizationConnection] (
[Id] UNIQUEIDENTIFIER NOT NULL,
[OrganizationId] UNIQUEIDENTIFIER NOT NULL,
[Type] TINYINT NOT NULL,
[Enabled] BIT NOT NULL,
[Config] NVARCHAR (MAX) NULL,
CONSTRAINT [PK_OrganizationConnection] PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_OrganizationConnection_OrganizationId] FOREIGN KEY ([OrganizationId]) REFERENCES [dbo].[Organization] ([Id])
)
END
-- Create indexes for OrganizationConnection
IF NOT EXISTS(SELECT name FROM sys.indexes WHERE name = 'IX_OrganizationConnection_OrganizationId')
BEGIN
CREATE NONCLUSTERED INDEX [IX_OrganizationConnection_OrganizationId]
ON [dbo].[OrganizationConnection]([OrganizationId] ASC);
END
-- Create View
IF EXISTS(SELECT * FROM sys.views WHERE [Name] = 'OrganizationConnectionView')
BEGIN
DROP VIEW [dbo].[OrganizationConnectionView]
END
GO
CREATE VIEW [dbo].[OrganizationConnectionView]
AS
SELECT
*
FROM
[dbo].[OrganizationConnection]
GO
-- Create Stored Procedures
IF OBJECT_ID('[dbo].[OrganizationConnection_ReadById]') IS NOT NULL
BEGIN
DROP PROCEDURE [dbo].[OrganizationConnection_ReadById];
END
GO
CREATE PROCEDURE [dbo].[OrganizationConnection_ReadById]
@Id UNIQUEIDENTIFIER
AS
BEGIN
SET NOCOUNT ON
SELECT
*
FROM
[dbo].[OrganizationConnectionView]
WHERE
[Id] = @Id
END
GO
IF OBJECT_ID('[dbo].[OrganizationConnection_Create]') IS NOT NULL
BEGIN
DROP PROCEDURE [dbo].[OrganizationConnection_Create]
END
GO
CREATE PROCEDURE [dbo].[OrganizationConnection_Create]
@Id UNIQUEIDENTIFIER,
@OrganizationId UNIQUEIDENTIFIER,
@Type TINYINT,
@Enabled BIT,
@Config NVARCHAR(MAX)
AS
BEGIN
SET NOCOUNT ON
INSERT INTO [dbo].[OrganizationConnection]
(
[Id],
[OrganizationId],
[Type],
[Enabled],
[Config]
)
VALUES
(
@Id,
@OrganizationId,
@Type,
@Enabled,
@Config
)
END
GO
IF OBJECT_ID('[dbo].[OrganizationConnection_Update]') IS NOT NULL
BEGIN
DROP PROCEDURE [dbo].[OrganizationConnection_Update]
END
GO
CREATE PROCEDURE [dbo].[OrganizationConnection_Update]
@Id UNIQUEIDENTIFIER,
@OrganizationId UNIQUEIDENTIFIER,
@Type TINYINT,
@Enabled BIT,
@Config NVARCHAR(MAX)
AS
BEGIN
SET NOCOUNT ON
UPDATE
[dbo].[OrganizationConnection]
SET
[OrganizationId] = @OrganizationId,
[Type] = @Type,
[Enabled] = @Enabled,
[Config] = @Config
WHERE
[Id] = @Id
END
GO
IF OBJECT_ID('[dbo].[OrganizationConnection_DeleteById]') IS NOT NULL
BEGIN
DROP PROCEDURE [dbo].[OrganizationConnection_DeleteById]
END
GO
CREATE PROCEDURE [dbo].[OrganizationConnection_DeleteById]
@Id UNIQUEIDENTIFIER
AS
BEGIN
SET NOCOUNT ON
DELETE FROM
[dbo].[OrganizationConnection]
WHERE
[Id] = @Id
END
GO
IF OBJECT_ID('[dbo].[OrganizationConnection_OrganizationDeleted]') IS NOT NULL
BEGIN
DROP PROCEDURE [dbo].[OrganizationConnection_OrganizationDeleted]
END
GO
CREATE PROCEDURE [dbo].[OrganizationConnection_OrganizationDeleted]
@Id UNIQUEIDENTIFIER
AS
BEGIN
SET NOCOUNT ON
DELETE FROM
[dbo].[OrganizationConnection]
WHERE
[OrganizationId] = @Id
END
GO
IF OBJECT_ID('[dbo].[OrganizationConnection_ReadEnabledByOrganizationIdType]') IS NOT NULL
BEGIN
DROP PROCEDURE [dbo].[OrganizationConnection_ReadEnabledByOrganizationIdType];
END
GO
CREATE PROCEDURE [dbo].[OrganizationConnection_ReadEnabledByOrganizationIdType]
@OrganizationId UNIQUEIDENTIFIER,
@Type TINYINT
AS
BEGIN
SET NOCOUNT ON
SELECT
*
FROM
[dbo].[OrganizationConnectionView]
WHERE
[OrganizationId] = @OrganizationId AND
[Type] = @Type AND
[Enabled] = 1
END
GO
DECLARE @TimesRenewedDefaultConstraint NVARCHAR(MAX) = (SELECT [con].[name]
FROM [sys].[default_constraints] [con]
INNER JOIN sys.objects obj ON obj.object_id = con.parent_object_id AND obj.type = 'U' AND obj.name = 'OrganizationSponsorship'
INNER JOIN sys.columns col ON col.column_id = con.parent_column_id AND col.object_id = obj.object_id AND col.name = 'TimesRenewedWithoutValidation'
INNER JOIN sys.schemas sch ON sch.schema_id = obj.schema_id AND sch.name = 'dbo'
WHERE con.[type] = 'D')
IF @TimesRenewedDefaultConstraint IS NOT NULL
BEGIN
DECLARE @sql NVARCHAR(MAX) = 'ALTER TABLE [dbo].[OrganizationSponsorship] DROP CONSTRAINT ' + @TimesRenewedDefaultConstraint
EXEC sp_executesql @sql
END
GO
IF COL_LENGTH('[dbo].[OrganizationSponsorship]', 'TimesRenewedWithoutValidation') IS NOT NULL
BEGIN
ALTER TABLE [dbo].[OrganizationSponsorship] DROP COLUMN [TimesRenewedWithoutValidation]
END
GO
IF COL_LENGTH('[dbo].[OrganizationSponsorship]', 'SponsorshipLapsedDate') IS NOT NULL
BEGIN
EXEC sp_rename '[dbo].[OrganizationSponsorship].[SponsorshipLapsedDate]', 'ValidUntil'
END
GO
IF COL_LENGTH('[dbo].[OrganizationSponsorship]', 'CloudSponsor') IS NOT NULL
BEGIN
ALTER TABLE [dbo].[OrganizationSponsorship] DROP COLUMN [CloudSponsor]
END
GO
IF COL_LENGTH('[dbo].[OrganizationSponsorship]', 'ToDelete') IS NULL
BEGIN
ALTER TABLE [dbo].[OrganizationSponsorship] ADD [ToDelete] BIT NOT NULL DEFAULT(0)
END
GO
IF EXISTS(SELECT name FROM sys.indexes WHERE name = 'IX_OrganizationSponsorship_InstallationId')
BEGIN
DROP INDEX [IX_OrganizationSponsorship_InstallationId]
ON [dbo].[OrganizationSponsorship]
END
GO
IF EXISTS(SELECT name FROM sys.objects WHERE name = 'FK_OrganizationSponsorship_InstallationId' AND type = 'F')
BEGIN
ALTER TABLE [dbo].[OrganizationSponsorship] DROP CONSTRAINT [FK_OrganizationSponsorship_InstallationId]
END
GO
IF COL_LENGTH('[dbo].[OrganizationSponsorship]', 'InstallationId') IS NOT NULL
BEGIN
ALTER TABLE [dbo].[OrganizationSponsorship] DROP COLUMN [InstallationId]
END
GO
IF COLUMNPROPERTY(OBJECT_ID('[dbo].[OrganizationSponsorship]', 'U'), 'SponsoringOrganizationUserID', 'AllowsNull') = 1
BEGIN
PRINT N'Setting all null SponsoringOrganizationUserID to empty guid'
UPDATE
[dbo].[OrganizationSponsorship]
SET
[SponsoringOrganizationUserID] = '00000000-0000-0000-0000-000000000000'
WHERE
[SponsoringOrganizationUserID] IS NULL;
DROP INDEX [IX_OrganizationSponsorship_SponsoringOrganizationUserId]
ON [dbo].[OrganizationSponsorship]
ALTER TABLE [dbo].[OrganizationSponsorship] ALTER COLUMN [SponsoringOrganizationUserID] UNIQUEIDENTIFIER NOT NULL;
CREATE NONCLUSTERED INDEX [IX_OrganizationSponsorship_SponsoringOrganizationUserId]
ON [dbo].[OrganizationSponsorship]([SponsoringOrganizationUserID] ASC);
END
GO
-- Remake View
IF EXISTS(SELECT * FROM sys.views WHERE [Name] = 'OrganizationSponsorshipView')
BEGIN
DROP VIEW [dbo].[OrganizationSponsorshipView]
END
GO
CREATE VIEW [dbo].[OrganizationSponsorshipView]
AS
SELECT
*
FROM
[dbo].[OrganizationSponsorship]
GO
-- OrganizationSponsorship_Create
IF OBJECT_ID('[dbo].[OrganizationSponsorship_Create]') IS NOT NULL
BEGIN
DROP PROCEDURE [dbo].[OrganizationSponsorship_Create]
END
GO
CREATE PROCEDURE [dbo].[OrganizationSponsorship_Create]
@Id UNIQUEIDENTIFIER OUTPUT,
@SponsoringOrganizationId UNIQUEIDENTIFIER,
@SponsoringOrganizationUserID UNIQUEIDENTIFIER,
@SponsoredOrganizationId UNIQUEIDENTIFIER,
@FriendlyName NVARCHAR(256),
@OfferedToEmail NVARCHAR(256),
@PlanSponsorshipType TINYINT,
@ToDelete BIT,
@LastSyncDate DATETIME2 (7),
@ValidUntil DATETIME2 (7)
AS
BEGIN
SET NOCOUNT ON
INSERT INTO [dbo].[OrganizationSponsorship]
(
[Id],
[SponsoringOrganizationId],
[SponsoringOrganizationUserID],
[SponsoredOrganizationId],
[FriendlyName],
[OfferedToEmail],
[PlanSponsorshipType],
[ToDelete],
[LastSyncDate],
[ValidUntil]
)
VALUES
(
@Id,
@SponsoringOrganizationId,
@SponsoringOrganizationUserID,
@SponsoredOrganizationId,
@FriendlyName,
@OfferedToEmail,
@PlanSponsorshipType,
@ToDelete,
@LastSyncDate,
@ValidUntil
)
END
GO
-- OrganizationSponsorship_Update
IF OBJECT_ID('[dbo].[OrganizationSponsorship_Update]') IS NOT NULL
BEGIN
DROP PROCEDURE [dbo].[OrganizationSponsorship_Update]
END
GO
CREATE PROCEDURE [dbo].[OrganizationSponsorship_Update]
@Id UNIQUEIDENTIFIER,
@SponsoringOrganizationId UNIQUEIDENTIFIER,
@SponsoringOrganizationUserID UNIQUEIDENTIFIER,
@SponsoredOrganizationId UNIQUEIDENTIFIER,
@FriendlyName NVARCHAR(256),
@OfferedToEmail NVARCHAR(256),
@PlanSponsorshipType TINYINT,
@ToDelete BIT,
@LastSyncDate DATETIME2 (7),
@ValidUntil DATETIME2 (7)
AS
BEGIN
SET NOCOUNT ON
UPDATE
[dbo].[OrganizationSponsorship]
SET
[SponsoringOrganizationId] = @SponsoringOrganizationId,
[SponsoringOrganizationUserID] = @SponsoringOrganizationUserID,
[SponsoredOrganizationId] = @SponsoredOrganizationId,
[FriendlyName] = @FriendlyName,
[OfferedToEmail] = @OfferedToEmail,
[PlanSponsorshipType] = @PlanSponsorshipType,
[ToDelete] = @ToDelete,
[LastSyncDate] = @LastSyncDate,
[ValidUntil] = @ValidUntil
WHERE
[Id] = @Id
END
GO
IF OBJECT_ID('[dbo].[OrganizationSponsorship_ReadLatestBySponsoringOrganizationId]') IS NOT NULL
BEGIN
DROP PROCEDURE [dbo].[OrganizationSponsorship_ReadLatestBySponsoringOrganizationId]
END
GO
CREATE PROCEDURE [dbo].[OrganizationSponsorship_ReadLatestBySponsoringOrganizationId]
@SponsoringOrganizationId UNIQUEIDENTIFIER
AS
BEGIN
SELECT TOP 1
[LastSyncDate]
FROM
[dbo].[OrganizationSponsorshipView]
WHERE
[SponsoringOrganizationId] = @SponsoringOrganizationId AND
[LastSyncDate] IS NOT NULL
ORDER BY [LastSyncDate] DESC
END
GO
IF OBJECT_ID('[dbo].[Organization_DeleteById]') IS NOT NULL
BEGIN
DROP PROCEDURE [dbo].[Organization_DeleteById]
END
GO
CREATE PROCEDURE [dbo].[Organization_DeleteById]
@Id UNIQUEIDENTIFIER
AS
BEGIN
SET NOCOUNT ON
EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationId] @Id
DECLARE @BatchSize INT = 100
WHILE @BatchSize > 0
BEGIN
BEGIN TRANSACTION Organization_DeleteById_Ciphers
DELETE TOP(@BatchSize)
FROM
[dbo].[Cipher]
WHERE
[UserId] IS NULL
AND [OrganizationId] = @Id
SET @BatchSize = @@ROWCOUNT
COMMIT TRANSACTION Organization_DeleteById_Ciphers
END
BEGIN TRANSACTION Organization_DeleteById
DELETE
FROM
[dbo].[SsoUser]
WHERE
[OrganizationId] = @Id
DELETE
FROM
[dbo].[SsoConfig]
WHERE
[OrganizationId] = @Id
DELETE CU
FROM
[dbo].[CollectionUser] CU
INNER JOIN
[dbo].[OrganizationUser] OU ON [CU].[OrganizationUserId] = [OU].[Id]
WHERE
[OU].[OrganizationId] = @Id
DELETE
FROM
[dbo].[OrganizationUser]
WHERE
[OrganizationId] = @Id
DELETE
FROM
[dbo].[ProviderOrganization]
WHERE
[OrganizationId] = @Id
EXEC [dbo].[OrganizationApiKey_OrganizationDeleted] @Id
EXEC [dbo].[OrganizationConnection_OrganizationDeleted] @Id
DELETE
FROM
[dbo].[Organization]
WHERE
[Id] = @Id
COMMIT TRANSACTION Organization_DeleteById
END
GO
-- OrganizationSponsorship have a different delete process for whether or not server is SH or not
IF OBJECT_ID('[dbo].[OrganizationSponsorship_OrganizationDeleted]') IS NOT NULL
BEGIN
DROP PROCEDURE [dbo].[OrganizationSponsorship_OrganizationDeleted]
END
GO
IF EXISTS(SELECT * FROM sys.views WHERE [Name] = 'OrganizationUserOrganizationDetailsView')
BEGIN
DROP VIEW [dbo].[OrganizationUserOrganizationDetailsView]
END
GO
CREATE VIEW [dbo].[OrganizationUserOrganizationDetailsView]
AS
SELECT
OU.[UserId],
OU.[OrganizationId],
O.[Name],
O.[Enabled],
O.[PlanType],
O.[UsePolicies],
O.[UseSso],
O.[UseKeyConnector],
O.[UseGroups],
O.[UseDirectory],
O.[UseEvents],
O.[UseTotp],
O.[Use2fa],
O.[UseApi],
O.[UseResetPassword],
O.[SelfHost],
O.[UsersGetPremium],
O.[Seats],
O.[MaxCollections],
O.[MaxStorageGb],
O.[Identifier],
OU.[Key],
OU.[ResetPasswordKey],
O.[PublicKey],
O.[PrivateKey],
OU.[Status],
OU.[Type],
SU.[ExternalId] SsoExternalId,
OU.[Permissions],
PO.[ProviderId],
P.[Name] ProviderName,
SS.[Data] SsoConfig,
OS.[FriendlyName] FamilySponsorshipFriendlyName,
OS.[LastSyncDate] FamilySponsorshipLastSyncDate,
OS.[ToDelete] FamilySponsorshipToDelete,
OS.[ValidUntil] FamilySponsorshipValidUntil
FROM
[dbo].[OrganizationUser] OU
LEFT JOIN
[dbo].[Organization] O ON O.[Id] = OU.[OrganizationId]
LEFT JOIN
[dbo].[SsoUser] SU ON SU.[UserId] = OU.[UserId] AND SU.[OrganizationId] = OU.[OrganizationId]
LEFT JOIN
[dbo].[ProviderOrganization] PO ON PO.[OrganizationId] = O.[Id]
LEFT JOIN
[dbo].[Provider] P ON P.[Id] = PO.[ProviderId]
LEFT JOIN
[dbo].[SsoConfig] SS ON SS.[OrganizationId] = OU.[OrganizationId]
LEFT JOIN
[dbo].[OrganizationSponsorship] OS ON OS.[SponsoringOrganizationUserID] = OU.[Id]
GO