diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs
index 977e16e9..13638cff 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs
@@ -9877,6 +9877,582 @@ namespace Microsoft.SqlTools.ServiceLayer
}
}
+ public static string objectType_functionTable_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_functionTable_plural);
+ }
+ }
+
+ public static string objectType_externalDataSource_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_externalDataSource_singular);
+ }
+ }
+
+ public static string objectType_serverRole_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_serverRole_singular);
+ }
+ }
+
+ public static string objectType_xmlSchemaCollection_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_xmlSchemaCollection_singular);
+ }
+ }
+
+ public static string objectType_storedProcedure_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_storedProcedure_plural);
+ }
+ }
+
+ public static string objectType_endpoint_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_endpoint_plural);
+ }
+ }
+
+ public static string objectType_sequence_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_sequence_singular);
+ }
+ }
+
+ public static string objectType_userDefinedDataType_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_userDefinedDataType_singular);
+ }
+ }
+
+ public static string objectType_fullTextCatalog_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_fullTextCatalog_plural);
+ }
+ }
+
+ public static string objectType_credential_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_credential_singular);
+ }
+ }
+
+ public static string objectType_databaseRole_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_databaseRole_plural);
+ }
+ }
+
+ public static string objectType_endpoint_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_endpoint_singular);
+ }
+ }
+
+ public static string objectType_view_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_view_plural);
+ }
+ }
+
+ public static string objectType_assembly_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_assembly_singular);
+ }
+ }
+
+ public static string objectType_functionScalar_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_functionScalar_singular);
+ }
+ }
+
+ public static string objectType_server_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_server_plural);
+ }
+ }
+
+ public static string objectType_table_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_table_singular);
+ }
+ }
+
+ public static string objectType_serviceQueue_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_serviceQueue_singular);
+ }
+ }
+
+ public static string objectType_login_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_login_plural);
+ }
+ }
+
+ public static string objectType_storedProcedure_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_storedProcedure_singular);
+ }
+ }
+
+ public static string objectType_default_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_default_plural);
+ }
+ }
+
+ public static string objectType_symmetricKey_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_symmetricKey_singular);
+ }
+ }
+
+ public static string objectType_userDefinedTableType_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_userDefinedTableType_singular);
+ }
+ }
+
+ public static string objectType_functionInline_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_functionInline_singular);
+ }
+ }
+
+ public static string objectType_serverRole_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_serverRole_plural);
+ }
+ }
+
+ public static string objectType_agentjob_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_agentjob_singular);
+ }
+ }
+
+ public static string objectType_databaseRole_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_databaseRole_singular);
+ }
+ }
+
+ public static string objectType_synonym_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_synonym_singular);
+ }
+ }
+
+ public static string objectType_AvailabilityGroup_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_AvailabilityGroup_singular);
+ }
+ }
+
+ public static string objectType_externalFileFormat_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_externalFileFormat_plural);
+ }
+ }
+
+ public static string objectType_database_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_database_singular);
+ }
+ }
+
+ public static string objectType_symmetricKey_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_symmetricKey_plural);
+ }
+ }
+
+ public static string objectType_securityPolicy_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_securityPolicy_singular);
+ }
+ }
+
+ public static string objectType_externalFileFormat_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_externalFileFormat_singular);
+ }
+ }
+
+ public static string objectType_applicationRole_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_applicationRole_singular);
+ }
+ }
+
+ public static string objectType_assembly_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_assembly_plural);
+ }
+ }
+
+ public static string objectType_sequence_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_sequence_plural);
+ }
+ }
+
+ public static string objectType_userDefinedDataType_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_userDefinedDataType_plural);
+ }
+ }
+
+ public static string objectType_server_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_server_singular);
+ }
+ }
+
+ public static string objectType_aggregateFunction_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_aggregateFunction_singular);
+ }
+ }
+
+ public static string objectType_fullTextCatalog_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_fullTextCatalog_singular);
+ }
+ }
+
+ public static string objectType_certificate_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_certificate_plural);
+ }
+ }
+
+ public static string objectType_AvailabilityGroup_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_AvailabilityGroup_plural);
+ }
+ }
+
+ public static string objectType_database_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_database_plural);
+ }
+ }
+
+ public static string objectType_view_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_view_singular);
+ }
+ }
+
+ public static string objectType_schema_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_schema_plural);
+ }
+ }
+
+ public static string objectType_rule_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_rule_plural);
+ }
+ }
+
+ public static string objectType_certificate_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_certificate_singular);
+ }
+ }
+
+ public static string objectType_user_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_user_singular);
+ }
+ }
+
+ public static string objectType_agentjob_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_agentjob_plural);
+ }
+ }
+
+ public static string objectType_synonym_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_synonym_plural);
+ }
+ }
+
+ public static string objectType_aggregateFunction_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_aggregateFunction_plural);
+ }
+ }
+
+ public static string objectType_functionTable_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_functionTable_singular);
+ }
+ }
+
+ public static string objectType_rule_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_rule_singular);
+ }
+ }
+
+ public static string objectType_serviceQueue_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_serviceQueue_plural);
+ }
+ }
+
+ public static string objectType_asymmetricKey_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_asymmetricKey_plural);
+ }
+ }
+
+ public static string objectType_applicationRole_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_applicationRole_plural);
+ }
+ }
+
+ public static string objectType_extendedStoredProcedure_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_extendedStoredProcedure_singular);
+ }
+ }
+
+ public static string objectType_login_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_login_singular);
+ }
+ }
+
+ public static string objectType_functionInline_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_functionInline_plural);
+ }
+ }
+
+ public static string objectType_user_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_user_plural);
+ }
+ }
+
+ public static string objectType_externalDataSource_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_externalDataSource_plural);
+ }
+ }
+
+ public static string objectType_functionScalar_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_functionScalar_plural);
+ }
+ }
+
+ public static string objectType_table_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_table_plural);
+ }
+ }
+
+ public static string objectType_credential_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_credential_plural);
+ }
+ }
+
+ public static string objectType_schema_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_schema_singular);
+ }
+ }
+
+ public static string objectType_userDefinedTableType_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_userDefinedTableType_plural);
+ }
+ }
+
+ public static string objectType_securityPolicy_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_securityPolicy_plural);
+ }
+ }
+
+ public static string objectType_xmlSchemaCollection_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_xmlSchemaCollection_plural);
+ }
+ }
+
+ public static string objectType_extendedStoredProcedure_plural
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_extendedStoredProcedure_plural);
+ }
+ }
+
+ public static string objectType_asymmetricKey_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_asymmetricKey_singular);
+ }
+ }
+
+ public static string objectType_default_singular
+ {
+ get
+ {
+ return Keys.GetString(Keys.objectType_default_singular);
+ }
+ }
+
public static string Permission_Alter
{
get
@@ -15159,6 +15735,222 @@ namespace Microsoft.SqlTools.ServiceLayer
public const string ResetPasswordWhileUnlocking = "ResetPasswordWhileUnlocking";
+ public const string objectType_functionTable_plural = "objectType_functionTable_plural";
+
+
+ public const string objectType_externalDataSource_singular = "objectType_externalDataSource_singular";
+
+
+ public const string objectType_serverRole_singular = "objectType_serverRole_singular";
+
+
+ public const string objectType_xmlSchemaCollection_singular = "objectType_xmlSchemaCollection_singular";
+
+
+ public const string objectType_storedProcedure_plural = "objectType_storedProcedure_plural";
+
+
+ public const string objectType_endpoint_plural = "objectType_endpoint_plural";
+
+
+ public const string objectType_sequence_singular = "objectType_sequence_singular";
+
+
+ public const string objectType_userDefinedDataType_singular = "objectType_userDefinedDataType_singular";
+
+
+ public const string objectType_fullTextCatalog_plural = "objectType_fullTextCatalog_plural";
+
+
+ public const string objectType_credential_singular = "objectType_credential_singular";
+
+
+ public const string objectType_databaseRole_plural = "objectType_databaseRole_plural";
+
+
+ public const string objectType_endpoint_singular = "objectType_endpoint_singular";
+
+
+ public const string objectType_view_plural = "objectType_view_plural";
+
+
+ public const string objectType_assembly_singular = "objectType_assembly_singular";
+
+
+ public const string objectType_functionScalar_singular = "objectType_functionScalar_singular";
+
+
+ public const string objectType_server_plural = "objectType_server_plural";
+
+
+ public const string objectType_table_singular = "objectType_table_singular";
+
+
+ public const string objectType_serviceQueue_singular = "objectType_serviceQueue_singular";
+
+
+ public const string objectType_login_plural = "objectType_login_plural";
+
+
+ public const string objectType_storedProcedure_singular = "objectType_storedProcedure_singular";
+
+
+ public const string objectType_default_plural = "objectType_default_plural";
+
+
+ public const string objectType_symmetricKey_singular = "objectType_symmetricKey_singular";
+
+
+ public const string objectType_userDefinedTableType_singular = "objectType_userDefinedTableType_singular";
+
+
+ public const string objectType_functionInline_singular = "objectType_functionInline_singular";
+
+
+ public const string objectType_serverRole_plural = "objectType_serverRole_plural";
+
+
+ public const string objectType_agentjob_singular = "objectType_agentjob_singular";
+
+
+ public const string objectType_databaseRole_singular = "objectType_databaseRole_singular";
+
+
+ public const string objectType_synonym_singular = "objectType_synonym_singular";
+
+
+ public const string objectType_AvailabilityGroup_singular = "objectType_AvailabilityGroup_singular";
+
+
+ public const string objectType_externalFileFormat_plural = "objectType_externalFileFormat_plural";
+
+
+ public const string objectType_database_singular = "objectType_database_singular";
+
+
+ public const string objectType_symmetricKey_plural = "objectType_symmetricKey_plural";
+
+
+ public const string objectType_securityPolicy_singular = "objectType_securityPolicy_singular";
+
+
+ public const string objectType_externalFileFormat_singular = "objectType_externalFileFormat_singular";
+
+
+ public const string objectType_applicationRole_singular = "objectType_applicationRole_singular";
+
+
+ public const string objectType_assembly_plural = "objectType_assembly_plural";
+
+
+ public const string objectType_sequence_plural = "objectType_sequence_plural";
+
+
+ public const string objectType_userDefinedDataType_plural = "objectType_userDefinedDataType_plural";
+
+
+ public const string objectType_server_singular = "objectType_server_singular";
+
+
+ public const string objectType_aggregateFunction_singular = "objectType_aggregateFunction_singular";
+
+
+ public const string objectType_fullTextCatalog_singular = "objectType_fullTextCatalog_singular";
+
+
+ public const string objectType_certificate_plural = "objectType_certificate_plural";
+
+
+ public const string objectType_AvailabilityGroup_plural = "objectType_AvailabilityGroup_plural";
+
+
+ public const string objectType_database_plural = "objectType_database_plural";
+
+
+ public const string objectType_view_singular = "objectType_view_singular";
+
+
+ public const string objectType_schema_plural = "objectType_schema_plural";
+
+
+ public const string objectType_rule_plural = "objectType_rule_plural";
+
+
+ public const string objectType_certificate_singular = "objectType_certificate_singular";
+
+
+ public const string objectType_user_singular = "objectType_user_singular";
+
+
+ public const string objectType_agentjob_plural = "objectType_agentjob_plural";
+
+
+ public const string objectType_synonym_plural = "objectType_synonym_plural";
+
+
+ public const string objectType_aggregateFunction_plural = "objectType_aggregateFunction_plural";
+
+
+ public const string objectType_functionTable_singular = "objectType_functionTable_singular";
+
+
+ public const string objectType_rule_singular = "objectType_rule_singular";
+
+
+ public const string objectType_serviceQueue_plural = "objectType_serviceQueue_plural";
+
+
+ public const string objectType_asymmetricKey_plural = "objectType_asymmetricKey_plural";
+
+
+ public const string objectType_applicationRole_plural = "objectType_applicationRole_plural";
+
+
+ public const string objectType_extendedStoredProcedure_singular = "objectType_extendedStoredProcedure_singular";
+
+
+ public const string objectType_login_singular = "objectType_login_singular";
+
+
+ public const string objectType_functionInline_plural = "objectType_functionInline_plural";
+
+
+ public const string objectType_user_plural = "objectType_user_plural";
+
+
+ public const string objectType_externalDataSource_plural = "objectType_externalDataSource_plural";
+
+
+ public const string objectType_functionScalar_plural = "objectType_functionScalar_plural";
+
+
+ public const string objectType_table_plural = "objectType_table_plural";
+
+
+ public const string objectType_credential_plural = "objectType_credential_plural";
+
+
+ public const string objectType_schema_singular = "objectType_schema_singular";
+
+
+ public const string objectType_userDefinedTableType_plural = "objectType_userDefinedTableType_plural";
+
+
+ public const string objectType_securityPolicy_plural = "objectType_securityPolicy_plural";
+
+
+ public const string objectType_xmlSchemaCollection_plural = "objectType_xmlSchemaCollection_plural";
+
+
+ public const string objectType_extendedStoredProcedure_plural = "objectType_extendedStoredProcedure_plural";
+
+
+ public const string objectType_asymmetricKey_singular = "objectType_asymmetricKey_singular";
+
+
+ public const string objectType_default_singular = "objectType_default_singular";
+
+
public const string Permission_Alter = "Permission_Alter";
diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx
index b03d90b1..026379e7 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx
+++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx
@@ -5475,6 +5475,294 @@ The Query Processor estimates that implementing the following index could improv
Reset password for the login while unlocking.
+
+ Table-valued functions
+
+
+
+ External Data Source
+
+
+
+ Server role
+
+
+
+ XML schema collection
+
+
+
+ Stored procedures
+
+
+
+ Endpoints
+
+
+
+ Sequence
+
+
+
+ User-defined data type
+
+
+
+ Full-text catalogs
+
+
+
+ Credential
+
+
+
+ Database roles
+
+
+
+ Endpoint
+
+
+
+ Views
+
+
+
+ Assembly
+
+
+
+ Scalar function
+
+
+
+ Servers
+
+
+
+ Table
+
+
+
+ Queue
+
+
+
+ Logins
+
+
+
+ Stored procedure
+
+
+
+ Defaults
+
+
+
+ Symmetric key
+
+
+
+ User-defined table type
+
+
+
+ Inline function
+
+
+
+ Server roles
+
+
+
+ Agent job
+
+
+
+ Database role
+
+
+
+ Synonym
+
+
+
+ Availability Group
+
+
+
+ External File Formats
+
+
+
+ Database
+
+
+
+ Symmetric keys
+
+
+
+ Security Policy
+
+
+
+ External File Format
+
+
+
+ Application role
+
+
+
+ Assemblies
+
+
+
+ Sequences
+
+
+
+ User-defined data types
+
+
+
+ Server
+
+
+
+ Aggregate function
+
+
+
+ Full-text catalog
+
+
+
+ Certificates
+
+
+
+ Availability Groups
+
+
+
+ Databases
+
+
+
+ View
+
+
+
+ Schemas
+
+
+
+ Rules
+
+
+
+ Certificate
+
+
+
+ User
+
+
+
+ Agent jobs
+
+
+
+ Synonyms
+
+
+
+ Aggregate functions
+
+
+
+ Table-valued function
+
+
+
+ Rule
+
+
+
+ Queues
+
+
+
+ Asymmetric keys
+
+
+
+ Application roles
+
+
+
+ Extended stored procedure
+
+
+
+ Login
+
+
+
+ Inline functions
+
+
+
+ Users
+
+
+
+ External Data Sources
+
+
+
+ Scalar functions
+
+
+
+ Tables
+
+
+
+ Credentials
+
+
+
+ Schema
+
+
+
+ User-defined table types
+
+
+
+ Security Policies
+
+
+
+ XML schema collections
+
+
+
+ Extended stored procedures
+
+
+
+ Asymmetric key
+
+
+
+ Default
+
+
Alter
diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings
index 12d0fa38..225b4928 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings
+++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings
@@ -2470,6 +2470,80 @@ ObjectNotRenamable(string urn) = The object could not be renamed. URN: '{0}'.
DefaultLanguagePlaceholder =
ResetPasswordWhileUnlocking = Reset password for the login while unlocking.
+#Search
+objectType_functionTable_plural = Table-valued functions
+objectType_externalDataSource_singular = External Data Source
+objectType_serverRole_singular = Server role
+objectType_xmlSchemaCollection_singular = XML schema collection
+objectType_storedProcedure_plural = Stored procedures
+objectType_endpoint_plural = Endpoints
+objectType_sequence_singular = Sequence
+objectType_userDefinedDataType_singular = User-defined data type
+objectType_fullTextCatalog_plural = Full-text catalogs
+objectType_credential_singular = Credential
+objectType_databaseRole_plural = Database roles
+objectType_endpoint_singular = Endpoint
+objectType_view_plural = Views
+objectType_assembly_singular = Assembly
+objectType_functionScalar_singular = Scalar function
+objectType_server_plural = Servers
+objectType_table_singular = Table
+objectType_serviceQueue_singular = Queue
+objectType_login_plural = Logins
+objectType_storedProcedure_singular = Stored procedure
+objectType_default_plural = Defaults
+objectType_symmetricKey_singular = Symmetric key
+objectType_userDefinedTableType_singular = User-defined table type
+objectType_functionInline_singular = Inline function
+objectType_serverRole_plural = Server roles
+objectType_agentjob_singular = Agent job
+objectType_databaseRole_singular = Database role
+objectType_synonym_singular = Synonym
+objectType_AvailabilityGroup_singular = Availability Group
+objectType_externalFileFormat_plural = External File Formats
+objectType_database_singular = Database
+objectType_symmetricKey_plural = Symmetric keys
+objectType_securityPolicy_singular = Security Policy
+objectType_externalFileFormat_singular = External File Format
+objectType_applicationRole_singular = Application role
+objectType_assembly_plural = Assemblies
+objectType_sequence_plural = Sequences
+objectType_userDefinedDataType_plural = User-defined data types
+objectType_server_singular = Server
+objectType_aggregateFunction_singular = Aggregate function
+objectType_fullTextCatalog_singular = Full-text catalog
+objectType_certificate_plural = Certificates
+objectType_AvailabilityGroup_plural = Availability Groups
+objectType_database_plural = Databases
+objectType_view_singular = View
+objectType_schema_plural = Schemas
+objectType_rule_plural = Rules
+objectType_certificate_singular = Certificate
+objectType_user_singular = User
+objectType_agentjob_plural = Agent jobs
+objectType_synonym_plural = Synonyms
+objectType_aggregateFunction_plural = Aggregate functions
+objectType_functionTable_singular = Table-valued function
+objectType_rule_singular = Rule
+objectType_serviceQueue_plural = Queues
+objectType_asymmetricKey_plural = Asymmetric keys
+objectType_applicationRole_plural = Application roles
+objectType_extendedStoredProcedure_singular = Extended stored procedure
+objectType_login_singular = Login
+objectType_functionInline_plural = Inline functions
+objectType_user_plural = Users
+objectType_externalDataSource_plural = External Data Sources
+objectType_functionScalar_plural = Scalar functions
+objectType_table_plural = Tables
+objectType_credential_plural = Credentials
+objectType_schema_singular = Schema
+objectType_userDefinedTableType_plural = User-defined table types
+objectType_securityPolicy_plural = Security Policies
+objectType_xmlSchemaCollection_plural = XML schema collections
+objectType_extendedStoredProcedure_plural = Extended stored procedures
+objectType_asymmetricKey_singular = Asymmetric key
+objectType_default_singular = Default
+
#Object permission names
Permission_Alter = Alter
Permission_Connect = Connect
diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf
index 233d9961..51e74413 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf
+++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.xlf
@@ -7217,6 +7217,365 @@ The Query Processor estimates that implementing the following index could improv
Service {0} was not found in the service provider
+
+ Table-valued functions
+ Table-valued functions
+
+
+
+ External Data Source
+ External Data Source
+
+
+
+ Server role
+ Server role
+
+
+
+ XML schema collection
+ XML schema collection
+
+
+
+ Stored procedures
+ Stored procedures
+
+
+
+ Endpoints
+ Endpoints
+
+
+
+ Sequence
+ Sequence
+
+
+
+ User-defined data type
+ User-defined data type
+
+
+
+ Full-text catalogs
+ Full-text catalogs
+
+
+
+ Credential
+ Credential
+
+
+
+ Database roles
+ Database roles
+
+
+
+ Endpoint
+ Endpoint
+
+
+
+ Views
+ Views
+
+
+
+ Assembly
+ Assembly
+
+
+
+ Scalar function
+ Scalar function
+
+
+
+ Servers
+ Servers
+
+
+
+ Table
+ Table
+
+
+
+ Queue
+ Queue
+
+
+
+ Logins
+ Logins
+
+
+
+ Stored procedure
+ Stored procedure
+
+
+
+ Defaults
+ Defaults
+
+
+
+ Symmetric key
+ Symmetric key
+
+
+
+ User-defined table type
+ User-defined table type
+
+
+
+ Inline function
+ Inline function
+
+
+
+ Server roles
+ Server roles
+
+
+
+ Agent job
+ Agent job
+
+
+
+ Database role
+ Database role
+
+
+
+ Synonym
+ Synonym
+
+
+
+ Availability Group
+ Availability Group
+
+
+
+ External File Formats
+ External File Formats
+
+
+
+ Database
+ Database
+
+
+
+ Symmetric keys
+ Symmetric keys
+
+
+
+ Security Policy
+ Security Policy
+
+
+
+ External File Format
+ External File Format
+
+
+
+ Application role
+ Application role
+
+
+
+ Assemblies
+ Assemblies
+
+
+
+ Sequences
+ Sequences
+
+
+
+ User-defined data types
+ User-defined data types
+
+
+
+ Server
+ Server
+
+
+
+ Aggregate function
+ Aggregate function
+
+
+
+ Full-text catalog
+ Full-text catalog
+
+
+
+ Certificates
+ Certificates
+
+
+
+ Availability Groups
+ Availability Groups
+
+
+
+ Databases
+ Databases
+
+
+
+ View
+ View
+
+
+
+ Schemas
+ Schemas
+
+
+
+ Rules
+ Rules
+
+
+
+ Certificate
+ Certificate
+
+
+
+ User
+ User
+
+
+
+ Agent jobs
+ Agent jobs
+
+
+
+ Synonyms
+ Synonyms
+
+
+
+ Aggregate functions
+ Aggregate functions
+
+
+
+ Table-valued function
+ Table-valued function
+
+
+
+ Rule
+ Rule
+
+
+
+ Queues
+ Queues
+
+
+
+ Asymmetric keys
+ Asymmetric keys
+
+
+
+ Application roles
+ Application roles
+
+
+
+ Extended stored procedure
+ Extended stored procedure
+
+
+
+ Login
+ Login
+
+
+
+ Inline functions
+ Inline functions
+
+
+
+ Users
+ Users
+
+
+
+ External Data Sources
+ External Data Sources
+
+
+
+ Scalar functions
+ Scalar functions
+
+
+
+ Tables
+ Tables
+
+
+
+ Credentials
+ Credentials
+
+
+
+ Schema
+ Schema
+
+
+
+ User-defined table types
+ User-defined table types
+
+
+
+ Security Policies
+ Security Policies
+
+
+
+ XML schema collections
+ XML schema collections
+
+
+
+ Extended stored procedures
+ Extended stored procedures
+
+
+
+ Asymmetric key
+ Asymmetric key
+
+
+
+ Default
+ Default
+
In Primary Key
In Primary Key
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/Contracts/SearchRequest.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/Contracts/SearchRequest.cs
new file mode 100644
index 00000000..73cdaeb6
--- /dev/null
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/Contracts/SearchRequest.cs
@@ -0,0 +1,36 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using Microsoft.SqlTools.Hosting.Protocol.Contracts;
+using Microsoft.SqlTools.Utility;
+
+namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement.Contracts
+{
+ public class SearchRequestParams : GeneralRequestDetails
+ {
+ ///
+ /// The context id.
+ ///
+ public string? ContextId { get; set; }
+
+ public string[]? ObjectTypes { get; set; }
+
+ public string? SearchText { get; set; }
+ public string? Schema { get; set; }
+ public string? Database { get; set; }
+ }
+
+ public class SearchResultItem
+ {
+ public string? Name { get; set; }
+ public string? Schema { get; set; }
+ public string? Type { get; set; }
+ }
+
+ public class SearchRequest
+ {
+ public static readonly RequestType Type = RequestType.Create("objectManagement/search");
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectManagementService.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectManagementService.cs
index f6f21927..cc954d49 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectManagementService.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectManagementService.cs
@@ -11,6 +11,7 @@ using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.ObjectManagement.Contracts;
using System.Collections.Generic;
using System.Collections.Concurrent;
+using Microsoft.SqlTools.ServiceLayer.Management;
namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
{
@@ -64,6 +65,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
this.serviceHost.SetRequestHandler(SaveObjectRequest.Type, HandleSaveObjectRequest, true);
this.serviceHost.SetRequestHandler(ScriptObjectRequest.Type, HandleScriptObjectRequest, true);
this.serviceHost.SetRequestHandler(DisposeViewRequest.Type, HandleDisposeViewRequest, true);
+ this.serviceHost.SetRequestHandler(SearchRequest.Type, HandleSearchRequest, true);
}
internal async Task HandleRenameRequest(RenameRequestParams requestParams, RequestContext requestContext)
@@ -116,6 +118,68 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
await requestContext.SendResult(new DisposeViewRequestResponse());
}
+ internal async Task HandleSearchRequest(SearchRequestParams requestParams, RequestContext requestContext)
+ {
+ var context = this.GetContext(requestParams.ContextId);
+ ConnectionInfo connInfo;
+ ConnectionService.Instance.TryFindConnection(context.Parameters.ConnectionUri, out connInfo);
+ if (connInfo == null)
+ {
+ throw new ArgumentException("Invalid ConnectionUri");
+ }
+
+ CDataContainer dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists: true);
+
+ List res = new List();
+
+ foreach (string type in requestParams.ObjectTypes)
+ {
+ SearchableObjectCollection result = new SearchableObjectCollection();
+ SearchableObjectType searchableObjectType = SecurableUtils.ConvertPotentialSqlObjectTypeToSearchableObjectType(type);
+
+ if (searchableObjectType == SearchableObjectType.LastType)
+ {
+ continue;
+ }
+
+ SearchableObjectTypeDescription desc = SearchableObjectTypeDescription.GetDescription(searchableObjectType);
+
+ if (requestParams.SearchText != null)
+ {
+ if (desc.IsDatabaseObject)
+ {
+ SearchableObject.Search(result, searchableObjectType, dataContainer.ConnectionInfo, context.Parameters.Database, requestParams.SearchText, false, true);
+ }
+ else
+ {
+ SearchableObject.Search(result, searchableObjectType, dataContainer.ConnectionInfo, requestParams.SearchText, false, true);
+ }
+ }
+ else
+ {
+ if (desc.IsDatabaseObject)
+ {
+ SearchableObject.Search(result, searchableObjectType, dataContainer.ConnectionInfo, context.Parameters.Database, true);
+ }
+ else
+ {
+ SearchableObject.Search(result, searchableObjectType, dataContainer.ConnectionInfo, true);
+ }
+
+ }
+
+ foreach (SearchableObject obj in result)
+ {
+ res.Add(new SearchResultItem
+ {
+ Name = obj.Name,
+ Type = type
+ });
+ }
+ }
+ await requestContext.SendResult(res.ToArray());
+ }
+
private IObjectTypeHandler GetObjectTypeHandler(SqlObjectType objectType)
{
foreach (var handler in objectTypeHandlers)
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/AppRole/AppRoleHandler.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/AppRole/AppRoleHandler.cs
index 3fc9d3e9..e0d69011 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/AppRole/AppRoleHandler.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/AppRole/AppRoleHandler.cs
@@ -75,12 +75,14 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
Value = item.Value
}).ToArray(),
OwnedSchemas = prototype.SchemasOwned,
+ SecurablePermissions = prototype.SecurablePermissions
};
var viewInfo = new AppRoleViewInfo()
{
ObjectInfo = appRoleInfo,
- Schemas = prototype.Schemas
+ Schemas = prototype.Schemas,
+ SupportedSecurableTypes = SecurableUtils.GetSecurableTypeMetadata(SqlObjectType.ApplicationRole, dataContainer.Server.Version, parameters.Database, dataContainer.Server.DatabaseEngineType, dataContainer.Server.DatabaseEngineEdition)
};
var context = new AppRoleViewContext(parameters, dataContainer.ServerConnection);
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/AppRole/AppRoleInfo.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/AppRole/AppRoleInfo.cs
index c60882d0..2b64bfc1 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/AppRole/AppRoleInfo.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/AppRole/AppRoleInfo.cs
@@ -8,7 +8,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
///
/// a class for storing various application role properties
///
- public class AppRoleInfo : SqlObject
+ public class AppRoleInfo : SecurityPrincipalObject
{
public string? DefaultSchema { get; set; }
public string? Password { get; set; }
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/AppRole/AppRoleViewInfo.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/AppRole/AppRoleViewInfo.cs
index 42456615..829ffbf6 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/AppRole/AppRoleViewInfo.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/AppRole/AppRoleViewInfo.cs
@@ -8,7 +8,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
///
/// a class for storing various application role view properties
///
- public class AppRoleViewInfo : SqlObjectViewInfo
+ public class AppRoleViewInfo : SecurityPrincipalViewInfo
{
public string[]? Schemas { get; set; }
}
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/DatabaseRole/DatabaseRoleHandler.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/DatabaseRole/DatabaseRoleHandler.cs
index 28519cb9..5bb42d69 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/DatabaseRole/DatabaseRoleHandler.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/DatabaseRole/DatabaseRoleHandler.cs
@@ -74,12 +74,14 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
}).ToArray(),
Members = prototype.Members.ToArray(),
OwnedSchemas = prototype.SchemasOwned.ToArray(),
+ SecurablePermissions = prototype.SecurablePermissions
};
var viewInfo = new DatabaseRoleViewInfo()
{
ObjectInfo = DatabaseRoleInfo,
- Schemas = prototype.Schemas
+ Schemas = prototype.Schemas,
+ SupportedSecurableTypes = SecurableUtils.GetSecurableTypeMetadata(SqlObjectType.DatabaseRole, dataContainer.Server.Version, parameters.Database, dataContainer.Server.DatabaseEngineType, dataContainer.Server.DatabaseEngineEdition)
};
var context = new DatabaseRoleViewContext(parameters, dataContainer.ServerConnection);
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/DatabaseRole/DatabaseRoleInfo.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/DatabaseRole/DatabaseRoleInfo.cs
index 9f733367..bff6263e 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/DatabaseRole/DatabaseRoleInfo.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/DatabaseRole/DatabaseRoleInfo.cs
@@ -8,7 +8,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
///
/// a class for storing various database role properties
///
- public class DatabaseRoleInfo : SqlObject
+ public class DatabaseRoleInfo : SecurityPrincipalObject
{
public string? Owner { get; set; }
public string[]? OwnedSchemas { get; set; }
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/DatabaseRole/DatabaseRoleViewInfo.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/DatabaseRole/DatabaseRoleViewInfo.cs
index 7ac14dad..0abd67a9 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/DatabaseRole/DatabaseRoleViewInfo.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/DatabaseRole/DatabaseRoleViewInfo.cs
@@ -8,7 +8,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
///
/// a class for storing various database role view properties
///
- public class DatabaseRoleViewInfo : SqlObjectViewInfo
+ public class DatabaseRoleViewInfo : SecurityPrincipalViewInfo
{
public string[]? Schemas { get; set; }
}
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Login/LoginHandler.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Login/LoginHandler.cs
index 3b3c4860..27b01a7f 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Login/LoginHandler.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Login/LoginHandler.cs
@@ -55,8 +55,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
}
string[] languages = languageOptionsList.ToArray();
LoginPrototype prototype = parameters.IsNewObject
- ? new LoginPrototype(dataContainer.Server)
- : new LoginPrototype(dataContainer.Server, dataContainer.Server.GetSmoObject(parameters.ObjectUrn) as Login);
+ ? new LoginPrototype(dataContainer)
+ : new LoginPrototype(dataContainer, dataContainer.Server.GetSmoObject(parameters.ObjectUrn) as Login);
List loginServerRoles = new List();
foreach (string role in prototype.ServerRoles.ServerRoleNames)
@@ -82,7 +82,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
ConnectPermission = prototype.WindowsGrantAccess,
IsEnabled = !prototype.IsDisabled,
IsLockedOut = prototype.IsLockedOut,
- UserMapping = new ServerLoginDatabaseUserMapping[0]
+ UserMapping = new ServerLoginDatabaseUserMapping[0],
+ SecurablePermissions = prototype.SecurablePermissions
};
var supportedAuthTypes = new List();
@@ -104,7 +105,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
Languages = languages,
ServerRoles = prototype.ServerRoles.ServerRoleNames,
SupportAdvancedPasswordOptions = dataContainer.Server.DatabaseEngineType == DatabaseEngineType.Standalone || dataContainer.Server.DatabaseEngineEdition == DatabaseEngineEdition.SqlDataWarehouse,
- SupportAdvancedOptions = dataContainer.Server.DatabaseEngineType == DatabaseEngineType.Standalone || dataContainer.Server.DatabaseEngineEdition == DatabaseEngineEdition.SqlManagedInstance
+ SupportAdvancedOptions = dataContainer.Server.DatabaseEngineType == DatabaseEngineType.Standalone || dataContainer.Server.DatabaseEngineEdition == DatabaseEngineEdition.SqlManagedInstance,
+ SupportedSecurableTypes = SecurableUtils.GetSecurableTypeMetadata(SqlObjectType.ServerLevelLogin, dataContainer.Server.Version, "", dataContainer.Server.DatabaseEngineType, dataContainer.Server.DatabaseEngineEdition)
};
var context = new LoginViewContext(parameters);
return Task.FromResult(new InitializeViewResult()
@@ -189,7 +191,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
}
CDataContainer dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists: true);
- LoginPrototype prototype = new LoginPrototype(dataContainer.Server, dataContainer.Server.Logins[login.Name]);
+ LoginPrototype prototype = new LoginPrototype(dataContainer, dataContainer.Server.Logins[login.Name]);
prototype.SqlPassword = login.Password;
if (0 != string.Compare(login.DefaultLanguage, SR.DefaultLanguagePlaceholder, StringComparison.Ordinal))
@@ -207,6 +209,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
prototype.IsDisabled = !login.IsEnabled;
prototype.MustChange = login.EnforcePasswordPolicy ? login.MustChangePassword : false;
prototype.WindowsGrantAccess = login.ConnectPermission;
+ prototype.SecurablePermissions = login.SecurablePermissions;
if (prototype.LoginType == SqlServer.Management.Smo.LoginType.SqlLogin)
{
@@ -256,7 +259,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
}
CDataContainer dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists: true);
- LoginPrototype prototype = new LoginPrototype(dataContainer.Server, login);
+ LoginPrototype prototype = new LoginPrototype(dataContainer, login);
if (prototype.LoginType == SqlServer.Management.Smo.LoginType.SqlLogin)
{
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Login/LoginInfo.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Login/LoginInfo.cs
index 82c80856..63b51062 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Login/LoginInfo.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Login/LoginInfo.cs
@@ -35,7 +35,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
///
/// a class for storing various login properties
///
- public class LoginInfo : SqlObject
+ public class LoginInfo : SecurityPrincipalObject
{
public LoginAuthenticationType AuthenticationType { get; set; }
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Login/LoginViewInfo.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Login/LoginViewInfo.cs
index 62678012..ba43d9f0 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Login/LoginViewInfo.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Login/LoginViewInfo.cs
@@ -6,7 +6,7 @@
namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
{
- public class LoginViewInfo : SqlObjectViewInfo
+ public class LoginViewInfo : SecurityPrincipalViewInfo
{
public LoginAuthenticationType[] AuthenticationTypes { get; set; }
public bool CanEditLockedOutState { get; set; }
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/AppRoleData.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/AppRoleData.cs
index c089d7d8..cfe63ce2 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/AppRoleData.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/AppRoleData.cs
@@ -12,6 +12,7 @@ using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.Management;
using System.Collections.Generic;
using System.Linq;
+using Microsoft.SqlTools.ServiceLayer.ObjectManagement.PermissionsData;
namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
{
@@ -32,7 +33,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
private bool exists;
private AppRolePrototypeData currentState;
private AppRolePrototypeData originalState;
-
+ private SecurablePermissions[] securablePermissions = null;
+ private Principal principal = null;
#endregion
#region Trace support
@@ -139,6 +141,18 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
this.currentState.ExtendedProperties = value;
}
}
+
+ public SecurablePermissions[] SecurablePermissions
+ {
+ get
+ {
+ return this.securablePermissions;
+ }
+ set
+ {
+ this.securablePermissions = value;
+ }
+ }
#endregion
#region Constructors / Dispose
@@ -149,6 +163,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
this.dataContainer = context;
this.currentState = new AppRolePrototypeData(context, database);
this.originalState = (AppRolePrototypeData)this.currentState.Clone();
+ this.securablePermissions = new SecurablePermissions[0];
}
///
@@ -161,6 +176,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
this.databaseName = database;
this.currentState = new AppRolePrototypeData(context, database);
this.originalState = (AppRolePrototypeData)this.currentState.Clone();
+ this.principal = SecurableUtils.CreatePrincipal(false, PrincipalType.ApplicationRole, null, roleInfo.Name, context, database);
this.ApplyInfoToPrototype(roleInfo);
}
@@ -175,6 +191,9 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
this.databaseName = database;
this.currentState = new AppRolePrototypeData(context, database, role);
this.originalState = (AppRolePrototypeData)this.currentState.Clone();
+ this.securablePermissions = SecurableUtils.GetSecurablePermissions(true, PrincipalType.ApplicationRole, role, context);
+ this.principal = SecurableUtils.CreatePrincipal(true, PrincipalType.ApplicationRole, role, null, context, database);
+ this.principal.AddExistingSecurables();
}
#endregion
@@ -223,6 +242,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
SendToServerSchemaOwnershipChanges(db, approle);
SendToServerExtendedPropertiesChange();
+ SecurableUtils.SendToServerPermissionChanges(this.exists, this.Name, this.SecurablePermissions, this.principal, this.dataContainer, this.databaseName);
}
else // not in properties mode -> create role
{
@@ -236,6 +256,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
SendToServerSchemaOwnershipChanges(db, approle);
SendToServerExtendedPropertiesChange();
+ SecurableUtils.SendToServerPermissionChanges(this.exists, this.Name, this.SecurablePermissions, this.principal, this.dataContainer, this.databaseName);
}
}
@@ -327,6 +348,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
this.SchemasOwned = roleInfo.OwnedSchemas.ToArray();
this.Password = roleInfo.Password;
this.ExtendedProperties = roleInfo.ExtendedProperties.Select(ep => new KeyValuePair(ep.Name, ep.Value)).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
+ this.securablePermissions = roleInfo.SecurablePermissions;
}
private class AppRolePrototypeData : ICloneable
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/DatabaseRoleData.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/DatabaseRoleData.cs
index 1c4f51e5..9c792c7b 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/DatabaseRoleData.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/DatabaseRoleData.cs
@@ -12,6 +12,7 @@ using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.Management;
using System.Collections.Generic;
using System.Linq;
+using Microsoft.SqlTools.ServiceLayer.ObjectManagement.PermissionsData;
namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
{
@@ -32,7 +33,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
private bool exists;
private DatabaseRolePrototypeData currentState;
private DatabaseRolePrototypeData originalState;
-
+ private SecurablePermissions[] securablePermissions = null;
+ private Principal principal = null;
#endregion
#region Trace support
@@ -138,6 +140,18 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
return this.dataContainer.Server.VersionMajor >= 9;
}
}
+
+ public SecurablePermissions[] SecurablePermissions
+ {
+ get
+ {
+ return this.securablePermissions;
+ }
+ set
+ {
+ this.securablePermissions = value;
+ }
+ }
#endregion
#region Constructors / Dispose
@@ -148,6 +162,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
this.dataContainer = context;
this.currentState = new DatabaseRolePrototypeData(context, database);
this.originalState = (DatabaseRolePrototypeData)this.currentState.Clone();
+ this.securablePermissions = new SecurablePermissions[0];
}
///
@@ -160,6 +175,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
this.dataContainer = context;
this.currentState = new DatabaseRolePrototypeData(context, database);
this.originalState = (DatabaseRolePrototypeData)this.currentState.Clone();
+ this.principal = SecurableUtils.CreatePrincipal(false, PrincipalType.DatabaseRole, null, roleInfo.Name, context, database);
this.ApplyInfoToPrototype(roleInfo);
}
@@ -174,6 +190,9 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
this.dataContainer = context;
this.currentState = new DatabaseRolePrototypeData(context, database, role);
this.originalState = (DatabaseRolePrototypeData)this.currentState.Clone();
+ this.principal = SecurableUtils.CreatePrincipal(true, PrincipalType.DatabaseRole, role, null, context, database);
+ this.principal.AddExistingSecurables();
+ this.securablePermissions = SecurableUtils.GetSecurablePermissions(true, PrincipalType.DatabaseRole, role, context);
}
#endregion
@@ -219,6 +238,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
}
SendToServerSchemaOwnershipChanges(db, databaseRole);
SendToServerExtendedPropertiesChange();
+ SecurableUtils.SendToServerPermissionChanges(this.exists, this.Name, this.SecurablePermissions, this.principal, this.dataContainer, this.databaseName);
}
#endregion
@@ -341,6 +361,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
this.Members = roleInfo.Members.ToList();
this.SchemasOwned = roleInfo.OwnedSchemas.ToArray();
this.ExtendedProperties = roleInfo.ExtendedProperties.Select(ep => new KeyValuePair(ep.Name, ep.Value)).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
+ this.securablePermissions = roleInfo.SecurablePermissions;
}
private class DatabaseRolePrototypeData : ICloneable
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/EffectivePermissionsData.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/EffectivePermissionsData.cs
new file mode 100644
index 00000000..901cffcc
--- /dev/null
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/EffectivePermissionsData.cs
@@ -0,0 +1,200 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using System;
+using System.Data;
+using System.Globalization;
+using Microsoft.SqlServer.Management.Sdk.Sfc;
+using Microsoft.SqlServer.Management.Common;
+using Microsoft.SqlTools.ServiceLayer.Management;
+
+namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
+{
+ ///
+ /// Data model for the EffectivePermmisions UI
+ ///
+ internal class EffectivePermissionsData
+ {
+ #region fields
+ private CDataContainer dataContainer;
+ // urn we are targetting
+ private Urn urn;
+ // securable we are targetting
+ private SupportedSecurable securable;
+ // the principal we will execute as
+ private string principalName = string.Empty;
+ // indicates whether or not we should execute as a login or user
+ private bool executeAsLogin;
+ #endregion
+
+ #region properties
+ ///
+ /// True if the query for this principal will return column information
+ ///
+ public bool HasColumnInformation
+ {
+ get
+ {
+ // STrace.Assert(this.securable != null, "invalid object state");
+ return this.securable.HasColumnInformation;
+ }
+ }
+ ///
+ /// The name of the principal we are checking permissions for
+ ///
+ public string PrincipalName
+ {
+ get
+ {
+ return this.principalName;
+ }
+ }
+ ///
+ /// the display name of the securable we are querying. If the securable has a schema it will be
+ /// schema.securable, otherwise just securable
+ ///
+ public string SecurableDisplayName
+ {
+ get
+ {
+ // STrace.Assert(this.securable != null, "invalid object state");
+ string displayName;
+ if (this.securable.Schema.Length > 0)
+ {
+ displayName = String.Format(CultureInfo.CurrentCulture
+ , "{0}.{1}"
+ , this.securable.Schema
+ , this.securable.Name);
+ }
+ else
+ {
+ displayName = this.securable.Name;
+ }
+ return displayName;
+ }
+ }
+ #endregion
+
+ #region constructors
+ ///
+ /// Construct an EffectivePermissionsData object
+ ///
+ /// CDataContainer that represents the principal we are querying
+ public EffectivePermissionsData(CDataContainer dataContainer)
+ {
+ if (dataContainer == null)
+ {
+ throw new ArgumentNullException("dataContainer");
+ }
+
+ this.dataContainer = dataContainer;
+
+ Initialize();
+ }
+ #endregion
+
+ #region public methods
+ ///
+ /// Query the effective permissions for principal against the securable
+ ///
+ /// Dataset representing the permissions
+ public DataSet QueryEffectivePermissions()
+ {
+ // get a connection
+ ServerConnection serverConnection = this.dataContainer.ServerConnection;
+
+ // see if we need to set the context to a particular db
+ string databaseName = GetDatabaseName(this.urn);
+
+ if (databaseName.Length > 0)
+ {
+ serverConnection.ExecuteNonQuery(
+ String.Format(CultureInfo.InvariantCulture
+ , "USE [{0}]"
+ , SecurableUtils.EscapeString(databaseName, "]")));
+ }
+
+ // get the securable query
+ string securableQuery = this.securable.GetPermissionsForSecurableSyntax();
+
+ // merge the securableQuery with the EXECUTE AS context
+ string sqlQuery =
+ String.Format(CultureInfo.InvariantCulture,
+ @"EXECUTE AS {0} = N'{1}';
+{2}
+REVERT;"
+ , this.executeAsLogin ? "LOGIN" : "USER"
+ , Urn.EscapeString(this.principalName)
+ , securableQuery);
+
+ return serverConnection.ExecuteWithResults(sqlQuery);
+ }
+ #endregion
+
+ #region implementation
+ ///
+ /// Initialize the object
+ ///
+ private void Initialize()
+ {
+ // STrace.Assert(this.dataContainer != null);
+
+ STParameters parameters = new STParameters(this.dataContainer.Document);
+
+ // get the Urn of the securable. This must be set
+ string securableUrn = string.Empty;
+ parameters.GetParam("urn", ref securableUrn);
+
+ // cannot proceed if there is no object to work on
+ if (securableUrn == null || securableUrn.Length == 0)
+ {
+ throw new InvalidOperationException();
+ }
+
+ this.urn = new Urn(securableUrn);
+
+ // get a supported securable for this object
+ this.securable = new SupportedSecurable(this.urn, this.dataContainer.Server);
+
+ // get the user we will be executing as
+ parameters.GetParam("executeas", ref this.principalName);
+ string executeAsType = String.Empty;
+ parameters.GetParam("executetype", ref executeAsType);
+
+ this.executeAsLogin = (executeAsType == "login");
+
+ // if no override is supplied then we will just execute as self
+ if (this.principalName == null || this.principalName.Length == 0)
+ {
+ // STrace.Assert(false, "Principal was not supplied. Defaulting to login");
+ this.principalName = this.dataContainer.ServerConnection.TrueLogin;
+ this.executeAsLogin = true;
+ }
+ }
+ ///
+ /// Get the database name if any that contains the securable
+ ///
+ /// Securable
+ /// Database name that contains the securable, or an empty string if this is a server
+ /// scoped object
+ private string GetDatabaseName(Urn urn)
+ {
+ String databaseName = string.Empty;
+ // otherwise try and find the database
+ while (urn != null && urn.Type != "Database")
+ {
+ urn = urn.Parent;
+ }
+
+ if (urn != null)
+ {
+ databaseName = urn.GetAttribute("Name");
+ }
+
+ return databaseName;
+ }
+ #endregion
+ }
+}
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/LoginActions.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/LoginActions.cs
index 0fb39022..4916d562 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/LoginActions.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/LoginActions.cs
@@ -31,9 +31,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
{
if (this.configAction != ConfigAction.Drop)
{
- prototype.ApplyGeneralChanges(this.DataContainer.Server);
- prototype.ApplyServerRoleChanges(this.DataContainer.Server);
- prototype.ApplyDatabaseRoleChanges(this.DataContainer.Server);
+ prototype.SendChangeToServer();
}
}
}
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/LoginData.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/LoginData.cs
index 7a99d672..adedb9e9 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/LoginData.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/LoginData.cs
@@ -16,6 +16,7 @@ using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Sdk.Sfc;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.Management;
+using Microsoft.SqlTools.ServiceLayer.ObjectManagement.PermissionsData;
namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
{
@@ -1547,11 +1548,14 @@ INNER JOIN sys.sql_logins AS sql_logins
}
private bool exists;
+ private CDataContainer context;
private string machineName;
private LoginPrototypeData currentState;
private LoginPrototypeData originalState;
private bool mapToCredential;
+ private SecurablePermissions[] securablePermissions = null;
+ private Principal principal = null;
public bool MapToCredential
{
set
@@ -1905,6 +1909,18 @@ INNER JOIN sys.sql_logins AS sql_logins
}
}
+ public SecurablePermissions[] SecurablePermissions
+ {
+ get
+ {
+ return securablePermissions;
+ }
+ set
+ {
+ securablePermissions = value;
+ }
+ }
+
///
/// Get the database roles collection for the user in a particular database
///
@@ -2056,13 +2072,16 @@ INNER JOIN sys.sql_logins AS sql_logins
/// constructor
///
/// The server on which we are creating a login
- public LoginPrototype(Microsoft.SqlServer.Management.Smo.Server server)
+ public LoginPrototype(CDataContainer context)
{
+ this.context = context;
+ var server = context.Server;
this.exists = false;
this.machineName = server.ConnectionContext.TrueName.ToUpperInvariant();
this.currentState = new LoginPrototypeData(server);
this.originalState = (LoginPrototypeData) this.currentState.Clone();
this.comparer = new SqlCollationSensitiveStringComparer(server.Information.Collation);
+ this.securablePermissions = new SecurablePermissions[0];
}
///
@@ -2070,21 +2089,28 @@ INNER JOIN sys.sql_logins AS sql_logins
///
/// The server on which we are modifying a login
/// The login we are modifying
- public LoginPrototype(Microsoft.SqlServer.Management.Smo.Server server, Login login)
+ public LoginPrototype(CDataContainer context, Login login)
{
+ this.context = context;
+ var server = context.Server;
this.exists = true;
this.machineName = server.ConnectionContext.TrueName.ToUpperInvariant();
this.currentState = new LoginPrototypeData(server, login);
this.originalState = (LoginPrototypeData) this.currentState.Clone();
this.comparer = new SqlCollationSensitiveStringComparer(server.Information.Collation);
+ this.securablePermissions = SecurableUtils.GetSecurablePermissions(this.exists, PrincipalType.Login, login, context);
+ this.principal = SecurableUtils.CreatePrincipal(true, PrincipalType.Login, login, null, context);
+ this.principal.AddExistingSecurables();
}
///
/// constructor
///
/// The server on which we are creating a login
- public LoginPrototype(Microsoft.SqlServer.Management.Smo.Server server, LoginInfo login)
+ public LoginPrototype(CDataContainer context, LoginInfo login)
{
+ this.context = context;
+ var server = context.Server;
this.exists = false;
this.machineName = server.ConnectionContext.TrueName.ToUpperInvariant();
this.currentState = new LoginPrototypeData(server);
@@ -2112,6 +2138,8 @@ INNER JOIN sys.sql_logins AS sql_logins
this.IsDisabled = !login.IsEnabled;
this.MustChange = login.EnforcePasswordPolicy ? login.MustChangePassword : false;
this.WindowsGrantAccess = login.ConnectPermission;
+ this.securablePermissions = login.SecurablePermissions;
+ this.principal = SecurableUtils.CreatePrincipal(false, PrincipalType.Login, null, login.Name, context);
}
private LoginType GetLoginType(LoginInfo loginInfo)
@@ -2154,6 +2182,14 @@ INNER JOIN sys.sql_logins AS sql_logins
}
+ public void SendChangeToServer()
+ {
+ ApplyGeneralChanges(this.context.Server);
+ ApplyServerRoleChanges(this.context.Server);
+ ApplyDatabaseRoleChanges(this.context.Server);
+ SecurableUtils.SendToServerPermissionChanges(this.exists, this.LoginName, this.SecurablePermissions, this.principal, this.context, null);
+ }
+
///
/// Create the login or modify the login's access type, default database, default language,
/// and password
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/ServerRoleData.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/ServerRoleData.cs
index 8ea8f364..4c955dfc 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/ServerRoleData.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/ServerRoleData.cs
@@ -10,6 +10,7 @@ using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.Management;
using System.Collections.Generic;
using System.Linq;
+using Microsoft.SqlTools.ServiceLayer.ObjectManagement.PermissionsData;
namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
{
@@ -26,6 +27,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
/// as a hash table where one can manipulate custom data
///
private CDataContainer dataContainer = null;
+ private Principal principal = null;
+ private SecurablePermissions[] securablePermissions = null;
private bool exists;
private ServerRolePrototypeData currentState;
@@ -109,6 +112,18 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
return this.currentState.IsFixedRole;
}
}
+
+ public SecurablePermissions[] SecurablePermissions
+ {
+ get
+ {
+ return securablePermissions;
+ }
+ set
+ {
+ securablePermissions = value;
+ }
+ }
#endregion
#region Constructors / Dispose
@@ -118,6 +133,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
this.dataContainer = context;
this.currentState = new ServerRolePrototypeData(context);
this.originalState = (ServerRolePrototypeData)this.currentState.Clone();
+ this.securablePermissions = new SecurablePermissions[0];
}
///
@@ -129,6 +145,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
this.dataContainer = context;
this.currentState = new ServerRolePrototypeData(context);
this.originalState = (ServerRolePrototypeData)this.currentState.Clone();
+ this.principal = SecurableUtils.CreatePrincipal(false, PrincipalType.ServerRole, null, roleInfo.Name, context);
this.ApplyInfoToPrototype(roleInfo);
}
@@ -142,6 +159,9 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
this.dataContainer = context;
this.currentState = new ServerRolePrototypeData(context, role);
this.originalState = (ServerRolePrototypeData)this.currentState.Clone();
+ this.principal = SecurableUtils.CreatePrincipal(true, PrincipalType.ServerRole, role, null, context);
+ this.principal.AddExistingSecurables();
+ this.securablePermissions = SecurableUtils.GetSecurablePermissions(this.exists, PrincipalType.ServerRole, role, this.dataContainer);
}
#endregion
@@ -183,6 +203,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
SendToServerMemberChanges(serverRole);
SendToServerMembershipChanges(serverRole);
+ SecurableUtils.SendToServerPermissionChanges(this.exists, this.Name, this.SecurablePermissions, this.principal, this.dataContainer, null);
}
#endregion
@@ -250,13 +271,13 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
}
}
-
public void ApplyInfoToPrototype(ServerRoleInfo roleInfo)
{
this.Name = roleInfo.Name;
this.Owner = roleInfo.Owner;
this.Members = roleInfo.Members.ToList();
this.Memberships = roleInfo.Memberships.ToList();
+ this.SecurablePermissions = roleInfo.SecurablePermissions;
}
private class ServerRolePrototypeData : ICloneable
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/SqlObjectSearchData.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/SqlObjectSearchData.cs
index ed9a0dca..d7c69228 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/SqlObjectSearchData.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/SqlObjectSearchData.cs
@@ -9,7 +9,6 @@ using System;
using System.Collections;
using System.Collections.Specialized;
using System.Data;
-using System.Resources;
using System.Text;
using System.Globalization;
using Microsoft.SqlServer.Management.Smo;
@@ -281,7 +280,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
/// Constructor
///
/// Bitmap for the object type
- /// The key to look up localized type names, e.g. "objectType.functionTable"
+ /// The key to look up localized type names, e.g. "objectType_functionTable"
/// The URN object type substring, e.g. "UserDefinedFunction"
/// Any special clauses needed for the URN, e.g. "@FunctionType='2'"
/// Clause to restrict selection to non-system objects, e.g. "@IsSystemObject='false'"
@@ -294,8 +293,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
string specialRestrictions,
string disallowSystemObjectsRestriction,
bool isDatabaseObject,
- bool isSchemaObject,
- ResourceManager resourceManager)
+ bool isSchemaObject)
{
// STrace.Assert(image != null, "image is null");
// STrace.Assert((typeNameKey != null) && (typeNameKey.Length != 0), "typeNameKey is null or empty");
@@ -309,9 +307,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
this.disallowSystemObjectsRestriction = disallowSystemObjectsRestriction;
this.isDatabaseObject = isDatabaseObject;
this.isSchemaObject = isSchemaObject;
-
- this.typeNamePlural = resourceManager.GetString(String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}.plural", typeNameKey));
- this.typeNameSingular = resourceManager.GetString(String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}.singular", typeNameKey));
+ this.typeNamePlural = SR.Keys.GetString(string.Format("{0}_plural", typeNameKey));
+ this.typeNameSingular = SR.Keys.GetString(string.Format("{0}_singular", typeNameKey));
// STrace.Assert((this.typeNamePlural != null) && (this.typeNamePlural.Length != 0), "could not get plural type name");
// STrace.Assert((this.typeNameSingular != null) && (this.typeNameSingular.Length != 0), "could not get singular type name");
@@ -321,7 +318,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
/// Constructor
///
/// Bitmap for the object type
- /// The key to look up localized type names, e.g. "objectType.functionTable"
+ /// The key to look up localized type names, e.g. "objectType_functionTable"
/// The URN object type substring, e.g. "UserDefinedFunction"
/// Whether the object is contained by a database
/// Whether the object is contained byt a schema
@@ -330,8 +327,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
string typeNameKey,
string urnObjectType,
bool isDatabaseObject,
- bool isSchemaObject,
- ResourceManager resourceManager)
+ bool isSchemaObject)
{
// STrace.Assert(image != null, "image is null");
// STrace.Assert((typeNameKey != null) && (typeNameKey.Length != 0), "typeNameKey is null or empty");
@@ -344,8 +340,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
this.isDatabaseObject = isDatabaseObject;
this.isSchemaObject = isSchemaObject;
- this.typeNamePlural = resourceManager.GetString(String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}.plural", typeNameKey));
- this.typeNameSingular = resourceManager.GetString(String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}.singular", typeNameKey));
+ this.typeNamePlural = SR.Keys.GetString(string.Format("{0}_plural", typeNameKey));
+ this.typeNameSingular = SR.Keys.GetString(string.Format("{0}_singular", typeNameKey));
// STrace.Assert((this.typeNamePlural != null) && (this.typeNamePlural.Length != 0), "could not get plural type name");
// STrace.Assert((this.typeNameSingular != null) && (this.typeNameSingular.Length != 0), "could not get singular type name");
@@ -620,14 +616,11 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
{
if (SearchableObjectTypeDescription.firstVersionSpecificTypeInfoUpdate)
{
- ResourceManager resourceManager = new ResourceManager("Microsoft.SqlServer.Management.SqlMgmt.SqlObjectSearchStrings", typeof(SearchableObjectTypeDescription).Assembly);
- // Color transparent = ResourceUtils.StandardBitmapTransparentColor;
-
//Re-writing the value of SearchableObjectType.ServerRole in the Dictionary.
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.ServerRole] =
new SearchableObjectTypeDescription(
// // DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("Flexible_server_role.ico")).ToBitmap(),
- "objectType.serverRole",
+ "objectType_serverRole",
"Role",
string.Empty,
Utils.IsSql11OrLater(serverVersion.Major)
@@ -636,8 +629,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
? "@ID=2" //Public server role's ID is 2.
: string.Empty,
false,
- false,
- resourceManager);
+ false);
firstVersionSpecificTypeInfoUpdate = false;
}
@@ -653,364 +645,324 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
SearchableObjectTypeDescription.typeToDescription = new HybridDictionary(25);
}
- ResourceManager resourceManager = new ResourceManager("Microsoft.SqlServer.Management.SqlMgmt.SqlObjectSearchStrings", typeof(SearchableObjectTypeDescription).Assembly);
- // Color transparent = ResourceUtils.StandardBitmapTransparentColor;
-
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.AggregateFunction] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("ScalarValuedFunction.ico")).ToBitmap(),
- "objectType.aggregateFunction",
+ "objectType_aggregateFunction",
"UserDefinedAggregate",
true,
- true,
- resourceManager);
+ true);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.ApplicationRole] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("application_role_16x.ico")).ToBitmap(),
- "objectType.applicationRole",
+ "objectType_applicationRole",
"ApplicationRole",
true,
- false,
- resourceManager);
+ false);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.Assembly] =
new SearchableObjectTypeDescription(
// // DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("assemblies.ico")).ToBitmap(),
- "objectType.assembly",
+ "objectType_assembly",
"SqlAssembly",
true,
- false,
- resourceManager);
+ false);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.AsymmetricKey] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("asymmetric_key.ico")).ToBitmap(),
- "objectType.asymmetricKey",
+ "objectType_asymmetricKey",
"AsymmetricKey",
true,
- false,
- resourceManager);
+ false);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.Certificate] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("certificate.ico")).ToBitmap(),
- "objectType.certificate",
+ "objectType_certificate",
"Certificate",
true,
- false,
- resourceManager);
+ false);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.Database] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("database.ico")).ToBitmap(),
- "objectType.database",
+ "objectType_database",
"Database",
String.Empty,
"@IsSystemObject=false()",
false,
- false,
- resourceManager);
+ false);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.AgentJob] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("jobs.ico")).ToBitmap(),
- "objectType.agentjob",
+ "objectType_agentjob",
"JobServer/Job",
false,
- false,
- resourceManager);
+ false);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.DatabaseRole] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("database_roles_16x.ico")).ToBitmap(),
- "objectType.databaseRole",
+ "objectType_databaseRole",
"Role",
String.Empty,
"@IsFixedRole=false()",
true,
- false,
- resourceManager);
+ false);
//Without version info, we can't have system object Urn as it differs with version.
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.ServerRole] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("Flexible_server_role.ico")).ToBitmap(),
- "objectType.serverRole",
+ "objectType_serverRole",
"Role",
false,
- false,
- resourceManager);
+ false);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.Endpoint] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("endpoint.ico")).ToBitmap(),
- "objectType.endpoint",
+ "objectType_endpoint",
"Endpoint",
false,
- false,
- resourceManager);
+ false);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.ExtendedStoredProcedure] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("user_extended_stored_proc.ico")).ToBitmap(),
- "objectType.extendedStoredProcedure",
+ "objectType_extendedStoredProcedure",
"ExtendedStoredProcedure",
String.Empty,
"@IsSystemObject=false()",
true,
- true,
- resourceManager);
+ true);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.ExternalDataSource] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("ExternalDataSource.ico")).ToBitmap(),
- "objectType.externalDataSource",
+ "objectType_externalDataSource",
"ExternalDataSource",
true,
- false,
- resourceManager);
+ false);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.ExternalFileFormat] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("ExternalFileFormat.ico")).ToBitmap(),
- "objectType.externalFileFormat",
+ "objectType_externalFileFormat",
"ExternalFileFormat",
true,
- false,
- resourceManager);
+ false);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.FullTextCatalog] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("full_text_catalog.ico")).ToBitmap(),
- "objectType.fullTextCatalog",
+ "objectType_fullTextCatalog",
"FullTextCatalog",
true,
- false,
- resourceManager);
+ false);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.FunctionInline] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("table_valued_function.ico")).ToBitmap(),
- "objectType.functionInline",
+ "objectType_functionInline",
"UserDefinedFunction",
String.Format(System.Globalization.CultureInfo.InvariantCulture, "@FunctionType='{0}'", (int)UserDefinedFunctionType.Inline),
"@IsSystemObject=false()",
true,
- true,
- resourceManager);
+ true);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.FunctionScalar] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("ScalarValuedFunction.ico")).ToBitmap(),
- "objectType.functionScalar",
+ "objectType_functionScalar",
"UserDefinedFunction",
String.Format(System.Globalization.CultureInfo.InvariantCulture, "@FunctionType='{0}'", (int)UserDefinedFunctionType.Scalar),
"@IsSystemObject=false()",
true,
- true,
- resourceManager);
+ true);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.FunctionTable] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("table_valued_function.ico")).ToBitmap(),
- "objectType.functionTable",
+ "objectType_functionTable",
"UserDefinedFunction",
String.Format(System.Globalization.CultureInfo.InvariantCulture, "@FunctionType='{0}'", (int)UserDefinedFunctionType.Table),
"@IsSystemObject=false()",
true,
- true,
- resourceManager);
+ true);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.Login] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("log_in_16x.ico")).ToBitmap(),
- "objectType.login",
+ "objectType_login",
"Login",
String.Empty,
"@IsSystemObject=false()",
false,
- false,
- resourceManager);
+ false);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.LoginOnly] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("log_in_16x.ico")).ToBitmap(),
- "objectType.login",
+ "objectType_login",
"Login",
"@LoginType = 2 or @LoginType = 0",
"@IsSystemObject=false()",
false,
- false,
- resourceManager);
+ false);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.Schema] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("database_schema.ico")).ToBitmap(),
- "objectType.schema",
+ "objectType_schema",
"Schema",
true,
- false,
- resourceManager);
+ false);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.Server] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("server.ico")).ToBitmap(),
- "objectType.server",
+ "objectType_server",
String.Empty,
false,
- false,
- resourceManager);
+ false);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.SecurityPolicy] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("securitypolicy.ico")).ToBitmap(),
- "objectType.securityPolicy",
+ "objectType_securityPolicy",
"SecurityPolicy",
true,
- true,
- resourceManager);
+ true);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.ServiceQueue] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("queue.ico")).ToBitmap(),
- "objectType.serviceQueue",
+ "objectType_serviceQueue",
"ServiceBroker/ServiceQueue",
true,
- true,
- resourceManager);
+ true);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.StoredProcedure] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("stored_procedure.ico")).ToBitmap(),
- "objectType.storedProcedure",
+ "objectType_storedProcedure",
"StoredProcedure",
String.Empty,
"@IsSystemObject=false()",
true,
- true,
- resourceManager);
+ true);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.Synonym] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("synonym.ico")).ToBitmap(),
- "objectType.synonym",
+ "objectType_synonym",
"Synonym",
true,
- true,
- resourceManager);
+ true);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.Sequence] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("sequence.ico")).ToBitmap(),
- "objectType.sequence",
+ "objectType_sequence",
"Sequence",
true,
- true,
- resourceManager);
+ true);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.Table] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("table.ico")).ToBitmap(),
- "objectType.table",
+ "objectType_table",
"Table",
String.Empty,
"@IsSystemObject=false()",
true,
- true,
- resourceManager);
+ true);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.User] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("user_16x.ico")).ToBitmap(),
- "objectType.user",
+ "objectType_user",
"User",
String.Empty,
"(@IsSystemObject=false() or @Name='guest')",
true,
- false,
- resourceManager);
+ false);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.UserDefinedDataType] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("user_defined_data_type.ico")).ToBitmap(),
- "objectType.userDefinedDataType",
+ "objectType_userDefinedDataType",
"UserDefinedDataType",
true,
- true,
- resourceManager);
+ true);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.View] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("view.ico")).ToBitmap(),
- "objectType.view",
+ "objectType_view",
"View",
String.Empty,
"@IsSystemObject=false()",
true,
- true,
- resourceManager);
+ true);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.XmlSchemaCollection] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("XML_schemas.ico")).ToBitmap(),
- "objectType.xmlSchemaCollection",
+ "objectType_xmlSchemaCollection",
"XmlSchemaCollection",
true,
- true,
- resourceManager);
+ true);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.Rule] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("rule.ico")).ToBitmap(),
- "objectType.rule",
+ "objectType_rule",
"Rule",
true,
- true,
- resourceManager);
+ true);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.Default] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("defaults_16x.ico")).ToBitmap(),
- "objectType.default",
+ "objectType_default",
"Default",
true,
- true,
- resourceManager);
+ true);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.Credential] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("credential.ico")).ToBitmap(),
- "objectType.credential",
+ "objectType_credential",
"Credential",
false,
- false,
- resourceManager);
+ false);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.SymmetricKey] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("symmetric_key.ico")).ToBitmap(),
- "objectType.symmetricKey",
+ "objectType_symmetricKey",
"SymmetricKey",
true,
- false,
- resourceManager);
+ false);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.UserDefinedTableType] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("table.ico")).ToBitmap(),
- "objectType.userDefinedTableType",
+ "objectType_userDefinedTableType",
"UserDefinedTableType",
true,
- true,
- resourceManager);
+ true);
SearchableObjectTypeDescription.typeToDescription[SearchableObjectType.AvailabilityGroup] =
new SearchableObjectTypeDescription(
// DpiUtil.GetScaledIcon(ResourceUtils.LoadIcon("Availability_Group.ico")).ToBitmap(),
- "objectType.AvailabilityGroup",
+ "objectType_AvailabilityGroup",
"AvailabilityGroup",
false,
- false,
- resourceManager);
+ false);
}
///
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/SupportedSecurable.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/SupportedSecurable.cs
new file mode 100644
index 00000000..1a9c0c27
--- /dev/null
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/SupportedSecurable.cs
@@ -0,0 +1,296 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using System;
+using System.Globalization;
+using Microsoft.SqlServer.Management.Sdk.Sfc;
+using Microsoft.SqlServer.Management.Smo;
+
+namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
+{
+ ///
+ /// Represents a Securable in SQL that can generate the TSQL to list
+ /// its permissions.
+ ///
+ internal class SupportedSecurable
+ {
+ #region constants
+ private const string queryWithColumn = @"SELECT
+ permission_name AS [Permission]
+ ,subentity_name AS [Column]
+FROM fn_my_permissions(N'{0}', N'{1}')
+ORDER BY permission_name, subentity_name;";
+ private const string queryWithoutColumn = @"SELECT
+ permission_name AS [Permission]
+FROM fn_my_permissions(N'{0}', N'{1}')
+ORDER BY permission_name;";
+ private const string queryWithoutSecurableName = @"SELECT
+ permission_name AS [Permission]
+FROM fn_my_permissions(NULL, N'{1}')
+ORDER BY permission_name;";
+ #endregion
+
+ #region fields
+ ///
+ /// SMO server we are targetting. This is needed so we can generate the correct
+ /// query against Table valued functions
+ ///
+ private SqlServer.Management.Smo.Server server;
+ ///
+ /// Securable we are targetting
+ ///
+ private Urn securable;
+ ///
+ /// Name of the securable
+ ///
+ private string securableName;
+ ///
+ /// Schema of the securable. If the securable does not have a schema this will be an Empty string
+ ///
+ private string securableSchema;
+ ///
+ /// The SMO type of the securable.
+ ///
+ private string securableType;
+ #endregion
+
+ #region public properties
+ ///
+ /// Indicates whether or not the securable will return column information or just a
+ /// list of permissions
+ ///
+ public bool HasColumnInformation
+ {
+ get
+ {
+ bool hasColumnInformation = false;
+ if (securable.Type == "Table" || securable.Type == "View")
+ {
+ hasColumnInformation = true;
+ }
+ else if (securable.Type == "UserDefinedFunction" && this.server != null)
+ {
+ UserDefinedFunction function = server.GetSmoObject(this.securable) as UserDefinedFunction;
+ // STrace.Assert(function != null, "Could not get correct SMO object");
+ hasColumnInformation = (function != null && function.FunctionType == UserDefinedFunctionType.Table);
+ }
+ return hasColumnInformation;
+ }
+ }
+ ///
+ /// name of the securable
+ ///
+ public string Name
+ {
+ get
+ {
+ return this.securableName;
+ }
+ }
+ ///
+ /// schema of the securable
+ ///
+ public string Schema
+ {
+ get
+ {
+ return this.securableSchema;
+ }
+ }
+ #endregion
+
+ #region Construction
+ ///
+ /// Create a new SupportedSecurable object.
+ ///
+ /// The securable we are targetting
+ /// The server where the securable resides. Can be null
+ public SupportedSecurable(Urn securable, SqlServer.Management.Smo.Server server)
+ {
+ if (securable == null)
+ {
+ throw new ArgumentNullException("securable");
+ }
+
+ this.securable = securable;
+ this.server = server;
+
+ // get the name
+ this.securableName = this.securable.GetAttribute("Name");
+ // get the schema from the urn
+ this.securableSchema = this.securable.GetAttribute("Schema");
+ // convert null to string.empty
+ this.securableSchema ??= String.Empty;
+ // get the type
+ this.securableType = this.securable.Type;
+ // check that we were passed good information
+ // STrace.Assert(this.securableName != null && this.securableName.Length > 0, "No usable object name available");
+ // STrace.Assert(this.securableType != null && this.securableType.Length > 0, "No usable object type available");
+ }
+ #endregion
+
+ #region public methods
+ ///
+ /// Generate a SQL query that would query the permissions on this securable
+ ///
+ /// a string that represents the query
+ public string GetPermissionsForSecurableSyntax()
+ {
+ string sqlQuery;
+ string fullSecurableName = null;
+
+ // get the class we will pass
+ string securableClass = GetSecurableClassForUrn(this.securable);
+
+ // Do not pass securable name for SERVER securables
+ if (securableClass == "SERVER")
+ {
+ sqlQuery = queryWithoutSecurableName;
+ }
+ else
+ {
+ if (this.HasColumnInformation)
+ {
+ sqlQuery = queryWithColumn;
+ }
+ else
+ {
+ sqlQuery = queryWithoutColumn;
+ }
+
+ if (this.securableSchema.Length > 0)
+ {
+ fullSecurableName = String.Format(CultureInfo.InvariantCulture, "[{0}].[{1}]"
+ , SecurableUtils.EscapeString(SecurableUtils.EscapeString(this.securableSchema, "]"), "'")
+ , SecurableUtils.EscapeString(SecurableUtils.EscapeString(this.securableName, "]"), "'"));
+ }
+ else
+ {
+ fullSecurableName = String.Format(CultureInfo.InvariantCulture, "[{0}]"
+ , SecurableUtils.EscapeString(SecurableUtils.EscapeString(this.securableName, "]"), "'"));
+ }
+ }
+
+ // return the select query
+ return String.Format(CultureInfo.InvariantCulture, sqlQuery, fullSecurableName, securableClass);
+ }
+ #endregion
+
+ #region implementation
+ ///
+ /// Finds a type for a Urn that can be passed to fn_my_permissions
+ ///
+ /// Urn
+ /// tsql type
+ private static string GetSecurableClassForUrn(Urn securable)
+ {
+ string securableType;
+
+ // just use a simple switch. If we wanted to be more sophisticated we could use a
+ // chain-of-responsibility pattern
+ switch (securable.Type)
+ {
+ case "ApplicationRole":
+ securableType = "APPLICATION ROLE";
+ break;
+ case "SqlAssembly":
+ securableType = "ASSEMBLY";
+ break;
+ case "AsymmetricKey":
+ securableType = "ASYMMETRIC KEY";
+ break;
+ case "Certificate":
+ securableType = "CERTIFICATE";
+ break;
+ case "ServiceContract":
+ securableType = "CONTRACT";
+ break;
+ case "Database":
+ securableType = "DATABASE";
+ break;
+ case "Endpoint":
+ securableType = "ENDPOINT";
+ break;
+ case "ExternalDataSource":
+ securableType = "EXTERNAL DATA SOURCE";
+ break;
+ case "ExternalFileFormat":
+ securableType = "EXTERNAL FILE FORMAT";
+ break;
+ case "FullTextCatalog":
+ securableType = "FULLTEXT CATALOG";
+ break;
+ case "Login":
+ securableType = "LOGIN";
+ break;
+ case "MessageType":
+ securableType = "MESSAGE TYPE";
+ break;
+ case "AvailabilityGroup":
+ securableType = "AVAILABILITY GROUP";
+ break;
+ // the following types map to OBJECT
+ case "UserDefinedAggregate":
+ case "Check":
+ case "Default":
+ case "ForeignKey":
+ // index is for index and primary key constraints
+ case "Index":
+ case "StoredProcedure":
+ case "UserDefinedFunction":
+ case "Rule":
+ case "Synonym":
+ case "Sequence":
+ case "ServiceQueue":
+ case "Trigger":
+ case "DdlTrigger":
+ case "Table":
+ case "View":
+ case "ExtendedStoredProcedure":
+ securableType = "OBJECT";
+ break;
+ case "RemoteServiceBinding":
+ securableType = "REMOTE SERVICE BINDING";
+ break;
+ case "Role":
+ securableType = (securable.Parent.Type == "Database") ? "ROLE" : "SERVER ROLE";
+ break;
+ case "ServiceRoute":
+ securableType = "ROUTE";
+ break;
+ case "Schema":
+ securableType = "SCHEMA";
+ break;
+ case "SecurityPolicy":
+ securableType = "SECURITY POLICY";
+ break;
+ case "Server":
+ securableType = "SERVER";
+ break;
+ case "BrokerService":
+ securableType = "SERVICE";
+ break;
+ case "SymmetricKey":
+ securableType = "SYMMETRIC KEY";
+ break;
+ case "UserDefinedDataType":
+ securableType = "TYPE";
+ break;
+ case "User":
+ securableType = "USER";
+ break;
+ case "XmlSchemaCollection":
+ securableType = "XML SCHEMA COLLECTION";
+ break;
+ default:
+ // throw if we don't know about something
+ throw new InvalidOperationException();
+ }
+
+ return securableType;
+ }
+ #endregion
+ }
+}
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/UserActions.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/UserActions.cs
index 7320c156..467687c1 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/UserActions.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/UserActions.cs
@@ -40,7 +40,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
currentUserType = UserActions.GetCurrentUserTypeForExistingUser(dataContainer.Server.GetSmoObject(dataContainer.ObjectUrn) as User);
}
- this.userPrototype = UserPrototypeFactory.GetUserPrototype(dataContainer, user, originalData, currentUserType);
+ this.userPrototype = UserPrototypeFactory.GetUserPrototype(dataContainer, user, originalData, currentUserType, dataContainer.IsNewObject);
}
// ///
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/UserData.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/UserData.cs
index 96c5bfa7..9bf3c81e 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/UserData.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Security/UserData.cs
@@ -12,6 +12,7 @@ using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Sdk.Sfc;
using Microsoft.SqlTools.ServiceLayer.Management;
using Microsoft.SqlTools.ServiceLayer.Utility;
+using Microsoft.SqlTools.ServiceLayer.ObjectManagement.PermissionsData;
namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
{
@@ -93,6 +94,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
public SecureString passwordConfirm = new SecureString();
public SecureString oldPassword = new SecureString();
public bool isOldPasswordRequired = false;
+ public bool isNewObject = false;
///
/// Used for creating clone of a UserPrototypeData.
@@ -363,6 +365,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
private bool exists = false;
private Database parent;
private CDataContainer context;
+ private SecurablePermissions[] securablePermissions = new SecurablePermissions[0];
+ private Principal principal = null;
public bool IsRoleMembershipChangesApplied { get; set; } //default is false
public bool IsSchemaOwnershipChangesApplied { get; set; } //default is false
@@ -483,6 +487,18 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
this.currentState.isMember[roleName] = isMember;
}
+ public SecurablePermissions[] SecurablePermissions
+ {
+ get
+ {
+ return this.securablePermissions;
+ }
+ set
+ {
+ this.securablePermissions = value;
+ }
+ }
+
#endregion
///
@@ -501,6 +517,19 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
Database? parent = context.Server.GetSmoObject(new Urn(context.ParentUrn)) as Database ?? throw new ArgumentException("Context ParentUrn is invalid");
this.parent = parent;
+ var userName = this.currentState.name;
+ if (current.isNewObject)
+ {
+ this.securablePermissions = new SecurablePermissions[0];
+ this.principal = SecurableUtils.CreatePrincipal(false, PrincipalType.DatabaseRole, null, userName, context, parent.Name);
+ }
+ else
+ {
+ this.securablePermissions = SecurableUtils.GetSecurablePermissions(true, PrincipalType.User, parent.Users[userName], context);
+ this.principal = SecurableUtils.CreatePrincipal(true, PrincipalType.User, parent.Users[userName], null, context, parent.Name);
+ this.principal.AddExistingSecurables();
+ }
+
this.roleNames = this.PopulateRoles();
this.schemaNames = this.PopulateSchemas();
}
@@ -564,6 +593,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
this.ApplyRoleMembershipChanges(parentDb, user);
this.IsRoleMembershipChangesApplied = true;
+
+ SecurableUtils.SendToServerPermissionChanges(!string.IsNullOrEmpty(this.currentState.name), this.Name, this.SecurablePermissions, this.principal, context, parentDb.Name);
}
return user;
@@ -1031,10 +1062,11 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
{
public static UserPrototype GetUserPrototype(
CDataContainer context, UserInfo? user,
- UserPrototypeData? originalData, ExhaustiveUserTypes userType)
+ UserPrototypeData? originalData, ExhaustiveUserTypes userType, bool isNewObject)
{
UserPrototype currentPrototype = null;
UserPrototypeData currentData = new UserPrototypeData(context, user);
+ currentData.isNewObject = isNewObject;
switch (userType)
{
case ExhaustiveUserTypes.AsymmetricKeyMappedUser:
@@ -1067,6 +1099,10 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
currentPrototype = null;
break;
}
+ if (user != null && user.SecurablePermissions != null)
+ {
+ currentPrototype.SecurablePermissions = user.SecurablePermissions;
+ }
return currentPrototype;
}
}
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/ServerRole/ServerRoleHandler.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/ServerRole/ServerRoleHandler.cs
index c483559d..9f00cffa 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/ServerRole/ServerRoleHandler.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/ServerRole/ServerRoleHandler.cs
@@ -56,14 +56,16 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
Name = prototype.Name,
Owner = prototype.Owner,
Members = prototype.Members.ToArray(),
- Memberships = prototype.Memberships.ToArray()
+ Memberships = prototype.Memberships.ToArray(),
+ SecurablePermissions = prototype.SecurablePermissions
};
var viewInfo = new ServerRoleViewInfo()
{
ObjectInfo = ServerRoleInfo,
IsFixedRole = prototype.IsFixedRole,
- ServerRoles = serverRoles.ToArray()
+ ServerRoles = serverRoles.ToArray(),
+ SupportedSecurableTypes = SecurableUtils.GetSecurableTypeMetadata(SqlObjectType.ServerRole, dataContainer.Server.Version, "", dataContainer.Server.DatabaseEngineType, dataContainer.Server.DatabaseEngineEdition)
};
var context = new ServerRoleViewContext(parameters);
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/ServerRole/ServerRoleInfo.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/ServerRole/ServerRoleInfo.cs
index e4b63c3a..0900290f 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/ServerRole/ServerRoleInfo.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/ServerRole/ServerRoleInfo.cs
@@ -8,7 +8,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
///
/// a class for storing various server role properties
///
- public class ServerRoleInfo : SqlObject
+ public class ServerRoleInfo : SecurityPrincipalObject
{
public string? Owner { get; set; }
public string[]? Members { get; set; }
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/ServerRole/ServerRoleViewInfo.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/ServerRole/ServerRoleViewInfo.cs
index e62407d4..9bad8137 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/ServerRole/ServerRoleViewInfo.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/ServerRole/ServerRoleViewInfo.cs
@@ -8,7 +8,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
///
/// a class for storing various server role view properties
///
- public class ServerRoleViewInfo : SqlObjectViewInfo
+ public class ServerRoleViewInfo : SecurityPrincipalViewInfo
{
public bool IsFixedRole { get; set; }
public string[]? ServerRoles { get; set; }
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/User/UserHandler.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/User/UserHandler.cs
index ee5a9d57..81a5544f 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/User/UserHandler.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/User/UserHandler.cs
@@ -98,7 +98,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
}
// generate a user prototype
- UserPrototype currentUserPrototype = UserPrototypeFactory.GetUserPrototype(dataContainer, userInfo, originalData: null, userType);
+ UserPrototype currentUserPrototype = UserPrototypeFactory.GetUserPrototype(dataContainer, userInfo, originalData: null, userType, parameters.IsNewObject);
// get the default schema if available
string defaultSchema = null;
@@ -212,13 +212,15 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
DefaultSchema = defaultSchema,
OwnedSchemas = schemaNames.ToArray(),
DatabaseRoles = databaseRoles.ToArray(),
- DefaultLanguage = defaultLanguage
+ DefaultLanguage = defaultLanguage,
+ SecurablePermissions = currentUserPrototype.SecurablePermissions
},
UserTypes = supportedUserTypes.ToArray(),
Languages = languageOptionsList.ToArray(),
Schemas = currentUserPrototype.SchemaNames.ToArray(),
Logins = logins,
- DatabaseRoles = currentUserPrototype.DatabaseRoleNames.ToArray()
+ DatabaseRoles = currentUserPrototype.DatabaseRoleNames.ToArray(),
+ SupportedSecurableTypes = SecurableUtils.GetSecurableTypeMetadata(SqlObjectType.User, dataContainer.Server.Version, parameters.Database, dataContainer.Server.DatabaseEngineType, dataContainer.Server.DatabaseEngineEdition)
};
var context = new UserViewContext(parameters, dataContainer.ServerConnection, currentUserPrototype.CurrentState);
return new InitializeViewResult { ViewInfo = userViewInfo, Context = context };
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/User/UserInfo.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/User/UserInfo.cs
index 10465c89..aa01678e 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/User/UserInfo.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/User/UserInfo.cs
@@ -33,7 +33,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
///
/// a class for storing various user properties
///
- public class UserInfo : SqlObject
+ public class UserInfo : SecurityPrincipalObject
{
public DatabaseUserType? Type { get; set; }
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/User/UserViewInfo.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/User/UserViewInfo.cs
index 99a4a66f..631b45ac 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/User/UserViewInfo.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/User/UserViewInfo.cs
@@ -8,7 +8,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
///
/// The information required to render the user view.
///
- public class UserViewInfo : SqlObjectViewInfo
+ public class UserViewInfo : SecurityPrincipalViewInfo
{
public DatabaseUserType[]? UserTypes { get; set; }
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/PermissionMetadata.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/PermissionMetadata.cs
new file mode 100644
index 00000000..20e75ca8
--- /dev/null
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/PermissionMetadata.cs
@@ -0,0 +1,13 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
+{
+ public class PermissionMetadata
+ {
+ public string? Name { get; set; }
+ public string? DisplayName { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/SecurablePermissions.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/SecurablePermissions.cs
new file mode 100644
index 00000000..72d13ed1
--- /dev/null
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/SecurablePermissions.cs
@@ -0,0 +1,24 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
+{
+ public class SecurablePermissionItem
+ {
+ public string? Permission { get; set; }
+ public string? Grantor { get; set; }
+ public bool? Grant { get; set; }
+ public bool? WithGrant { get; set; }
+ }
+
+ public class SecurablePermissions
+ {
+ public string? Name { get; set; }
+ public string? Schema { get; set; }
+ public string? Type { get; set; }
+ public string[]? EffectivePermissions { get; set; }
+ public SecurablePermissionItem[]? Permissions { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/SecurableTypeMetadata.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/SecurableTypeMetadata.cs
new file mode 100644
index 00000000..b0cb2be7
--- /dev/null
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/SecurableTypeMetadata.cs
@@ -0,0 +1,14 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
+{
+ public class SecurableTypeMetadata
+ {
+ public string? Name { get; set; }
+ public string? DisplayName { get; set; }
+ public PermissionMetadata[]? Permissions { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/SecurableUtils.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/SecurableUtils.cs
new file mode 100644
index 00000000..0d741a18
--- /dev/null
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/SecurableUtils.cs
@@ -0,0 +1,530 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Xml;
+using Microsoft.SqlServer.Management.Common;
+using Microsoft.SqlServer.Management.Smo;
+using Microsoft.SqlTools.ServiceLayer.Management;
+using Microsoft.SqlTools.ServiceLayer.ObjectManagement.PermissionsData;
+using Newtonsoft.Json;
+
+namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
+{
+ public class SecurableUtils
+ {
+ private static readonly SearchableObjectType[] securableTypesForServerLevel = new SearchableObjectType[] {
+ SearchableObjectType.AvailabilityGroup,
+ SearchableObjectType.Endpoint,
+ SearchableObjectType.Login,
+ SearchableObjectType.ServerRole,
+ SearchableObjectType.Server
+ };
+
+ private static readonly SearchableObjectType[] securableTypesForDbLevel = new SearchableObjectType[] {
+ SearchableObjectType.AggregateFunction,
+ SearchableObjectType.ApplicationRole,
+ SearchableObjectType.Assembly,
+ SearchableObjectType.AsymmetricKey,
+ SearchableObjectType.Certificate,
+ SearchableObjectType.Database,
+ SearchableObjectType.DatabaseRole,
+ SearchableObjectType.ExternalDataSource,
+ SearchableObjectType.ExternalFileFormat,
+ SearchableObjectType.FullTextCatalog,
+ SearchableObjectType.FunctionInline,
+ SearchableObjectType.ServiceQueue,
+ SearchableObjectType.FunctionScalar,
+ SearchableObjectType.Schema,
+ SearchableObjectType.SecurityPolicy,
+ SearchableObjectType.Sequence,
+ SearchableObjectType.StoredProcedure,
+ SearchableObjectType.SymmetricKey,
+ SearchableObjectType.Synonym,
+ SearchableObjectType.Table,
+ SearchableObjectType.FunctionTable,
+ SearchableObjectType.UserDefinedDataType,
+ SearchableObjectType.UserDefinedTableType,
+ SearchableObjectType.User,
+ SearchableObjectType.View,
+ SearchableObjectType.XmlSchemaCollection
+ };
+
+ static internal string launchEffectivePermissions = @"
+
+
+
+ sql
+
+
+
+
+
+ sqlmgmt.dll
+
+";
+
+ public static SecurableTypeMetadata[] GetSecurableTypeMetadata(SqlObjectType objectType, Version serverVersion, string databaseName,DatabaseEngineType databaseEngineType, DatabaseEngineEdition engineEdition)
+ {
+ List res = new List();
+ switch (objectType)
+ {
+ case SqlObjectType.ServerLevelLogin:
+ case SqlObjectType.ServerRole:
+ AddSecurableTypeMetadata(res, securableTypesForServerLevel, null, serverVersion, databaseName, databaseEngineType, engineEdition);
+ break;
+ case SqlObjectType.ApplicationRole:
+ case SqlObjectType.DatabaseRole:
+ case SqlObjectType.User:
+ AddSecurableTypeMetadata(res, securableTypesForDbLevel, null, serverVersion, databaseName, databaseEngineType, engineEdition);
+ break;
+ default:
+ break;
+ }
+ return res.ToArray();
+ }
+
+ private static void AddSecurableTypeMetadata(List res, SearchableObjectType[] supportedTypes, SearchableObjectType[] excludeList, Version serverVersion, string databaseName,DatabaseEngineType databaseEngineType, DatabaseEngineEdition engineEdition)
+ {
+ foreach(SearchableObjectType t in supportedTypes)
+ {
+ if (t == SearchableObjectType.LastType || (excludeList != null && excludeList.Contains(t)))
+ {
+ continue;
+ }
+ SecurableType secType = PermissionsData.Securable.GetSecurableType(t);
+ SearchableObjectTypeDescription desc = SearchableObjectTypeDescription.GetDescription(t);
+ var pList = PermissionsData.Securable.GetRelevantPermissions(secType, serverVersion, databaseName, databaseEngineType, engineEdition);
+ var permissions = new PermissionMetadata[pList.Count];
+ for (int i = 0; i < pList.Count; i++)
+ {
+ var p = (Permission)pList[i];
+ permissions[i] = new PermissionMetadata()
+ {
+ Name = p?.Name,
+ DisplayName = p?.Name
+ };
+ }
+
+ SecurableTypeMetadata metadata = new SecurableTypeMetadata()
+ {
+ Name = desc.DisplayTypeNameSingular,
+ DisplayName = desc.DisplayTypeNamePlural,
+ Permissions = permissions
+ };
+ res.Add(metadata);
+ }
+ res.Sort((x, y) => string.Compare(x.Name, y.Name, StringComparison.InvariantCulture));
+ }
+
+ public static SecurablePermissions[] GetSecurablePermissions(bool principalExists, PrincipalType principalType, SqlSmoObject o, CDataContainer dataContainer)
+ {
+ List res = new List();
+ Principal principal;
+
+ try
+ {
+ principal = CreatePrincipal(principalExists, principalType, o, null, dataContainer);
+ }
+ catch(Exception)
+ {
+ return new SecurablePermissions[0];
+ }
+
+ principal.AddExistingSecurables();
+
+ var securables = principal.GetSecurables(new SecurableComparer(SecurableComparer.DefaultSortingOrder, true));
+ foreach (Securable s in securables)
+ {
+ var permissionStates = principal.GetPermissionStates(s);
+ Dictionary permissionItemsDict = new Dictionary();
+ for (int i = 0; i < permissionStates.Count; i++)
+ {
+ var p = permissionStates[i];
+ string key = p?.Permission.Name ?? string.Empty;
+ if (!permissionItemsDict.ContainsKey(key) || string.IsNullOrEmpty(permissionItemsDict[key].Grantor))
+ {
+ var permissionItem = new SecurablePermissionItem()
+ {
+ Permission = p?.Permission.Name,
+ Grantor = p?.Grantor,
+ Grant = p?.State == PermissionStatus.Revoke ? null : p?.State == PermissionStatus.Grant || p?.State == PermissionStatus.WithGrant,
+ WithGrant = p?.State == PermissionStatus.Revoke ? null : p?.State == PermissionStatus.WithGrant,
+ };
+ permissionItemsDict[key] = permissionItem;
+ }
+ }
+
+ var permissions = permissionItemsDict.Values.OrderBy(x => x.Permission, StringComparer.InvariantCulture).ToArray();
+
+ SecurablePermissions secPerm = new SecurablePermissions()
+ {
+ Name = s.Name,
+ Schema = s.Schema,
+ Type = s.TypeName,
+ Permissions = permissions,
+ EffectivePermissions = CanHaveEffectivePermissions(principalType) ? GetEffectivePermissions(dataContainer, s, principal) : new string[0]
+ };
+ res.Add(secPerm);
+ }
+
+ return res.ToArray();
+ }
+
+ public static bool CanHaveEffectivePermissions(PrincipalType principalType)
+ {
+ if (principalType == PrincipalType.ServerRole || principalType == PrincipalType.DatabaseRole || principalType == PrincipalType.ApplicationRole)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ internal static string[] GetEffectivePermissions(CDataContainer dataContainer, Securable securable, Principal principal)
+ {
+ var doc = ReadEffectivePermissionsXml(securable, principal);
+ dataContainer.Document = doc;
+ var dataModel = new EffectivePermissionsData(dataContainer);
+ List res = new List();
+ DataSet data = dataModel.QueryEffectivePermissions();
+ // STrace.Assert(data.Tables.Count == 1, "Unknown number of tables returned");
+
+ if (data.Tables.Count > 0)
+ {
+ DataTable table = data.Tables[0];
+
+ // STrace.Assert(table.Columns.Count >= 1 && table.Columns.Count <= 2, "Too many columns returned");
+
+ bool hasColumnInformation = dataModel.HasColumnInformation;
+
+ // loop through and add rows
+ foreach (DataRow row in table.Rows)
+ {
+ res.Add(row[0].ToString());
+ }
+ }
+ return res.ToArray();
+ }
+
+ ///
+ /// Form the xml to query effective permissions data
+ ///
+ ///
+ private static XmlDocument ReadEffectivePermissionsXml(Securable securable, Principal principal )
+ {
+ if (securable != null && principal != null)
+ {
+ string executeas = null;
+ string executetype = null;
+ GetPrincipalToExecuteAs(principal,
+ securable.DatabaseName,
+ securable.ConnectionInfo,
+ out executeas,
+ out executetype);
+
+ // build a document
+ XmlDocument xml = new XmlDocument();
+ xml.LoadXml(launchEffectivePermissions);
+ xml.SelectSingleNode("/formdescription/params/urn").InnerText = securable.Urn;
+ xml.SelectSingleNode("/formdescription/params/servername").InnerText = ((SqlConnectionInfo)securable.ConnectionInfo).ServerName;
+ xml.SelectSingleNode("/formdescription/params/database").InnerText = securable.DatabaseName;
+ xml.SelectSingleNode("/formdescription/params/executeas").InnerText = executeas;
+ xml.SelectSingleNode("/formdescription/params/executetype").InnerText = executetype;
+
+ return xml;
+ }
+
+ return null;
+ }
+
+ ///
+ /// Create principal object for server level principals
+ ///
+ internal static Principal CreatePrincipal(bool principalExists, PrincipalType principalType, SqlSmoObject o, string? objectName, CDataContainer dataContainer)
+ {
+ if (principalExists)
+ {
+ NamedSmoObject obj = (NamedSmoObject) o;
+ return new Principal(obj, dataContainer.ConnectionInfo);
+ }
+ else
+ {
+ Version serverVersion = Securable.GetServerVersion(dataContainer.ConnectionInfo);
+
+ return new Principal(
+ objectName,
+ principalType,
+ principalExists,
+ dataContainer.ConnectionInfo,
+ serverVersion);
+ }
+ }
+
+ ///
+ /// Create principal object for database level principals
+ ///
+ internal static Principal CreatePrincipal(bool principalExists, PrincipalType principalType, SqlSmoObject o, string? objectName, CDataContainer dataContainer, string databaseName)
+ {
+ if (principalExists)
+ {
+ NamedSmoObject obj = (NamedSmoObject)o;
+ return new Principal(obj, dataContainer.ConnectionInfo);
+ }
+ else
+ {
+ Version serverVersion = Securable.GetServerVersion(dataContainer.ConnectionInfo);
+ DatabaseEngineType databaseEngineType = Securable.GetDatabaseEngineType(dataContainer.ConnectionInfo);
+ DatabaseEngineEdition databaseEngineEdition = Securable.GetDatabaseEngineEdition(dataContainer.ConnectionInfo);
+ return new Principal(
+ objectName,
+ databaseName,
+ principalType,
+ principalExists,
+ dataContainer.ConnectionInfo,
+ serverVersion,
+ databaseEngineType,
+ databaseEngineEdition);
+ }
+ }
+
+ public static String EscapeString(String s, string esc)
+ {
+ if (null == s)
+ {
+ return null;
+ }
+ string replace = esc + esc;
+ StringBuilder sb = new StringBuilder(s);
+ sb.Replace(esc, replace);
+ return sb.ToString();
+ }
+
+ internal static SearchableObjectType ConvertPotentialSqlObjectTypeToSearchableObjectType(string typeStr)
+ {
+ if (typeStr == ConvertSqlObjectTypeToStringValue(SqlObjectType.ApplicationRole))
+ {
+ return SearchableObjectType.ApplicationRole;
+ }
+ else if (typeStr == ConvertSqlObjectTypeToStringValue(SqlObjectType.Credential))
+ {
+ return SearchableObjectType.Credential;
+ }
+ else if (typeStr == ConvertSqlObjectTypeToStringValue(SqlObjectType.DatabaseRole))
+ {
+ return SearchableObjectType.DatabaseRole;
+ }
+ else if (typeStr == ConvertSqlObjectTypeToStringValue(SqlObjectType.ServerLevelLogin))
+ {
+ return SearchableObjectType.Login;
+ }
+ else if (typeStr == ConvertSqlObjectTypeToStringValue(SqlObjectType.ServerRole))
+ {
+ return SearchableObjectType.ServerRole;
+ }
+ else if (typeStr == ConvertSqlObjectTypeToStringValue(SqlObjectType.Table))
+ {
+ return SearchableObjectType.Table;
+ }
+ else if (typeStr == ConvertSqlObjectTypeToStringValue(SqlObjectType.User))
+ {
+ return SearchableObjectType.User;
+ }
+ else if (typeStr == ConvertSqlObjectTypeToStringValue(SqlObjectType.View))
+ {
+ return SearchableObjectType.View;
+ }
+ else
+ {
+ return ConvertStringToSearchableObjectType(typeStr);
+ }
+ }
+
+ private static string ConvertSqlObjectTypeToStringValue(SqlObjectType objectType)
+ {
+ return JsonConvert.SerializeObject(objectType).Replace("\"", "");
+ }
+
+ private static SearchableObjectType ConvertStringToSearchableObjectType(string typeStr)
+ {
+ foreach(SearchableObjectType t in Enum.GetValues(typeof(SearchableObjectType)))
+ {
+ if (t == SearchableObjectType.LastType)
+ {
+ continue;
+ }
+ SecurableType secType = PermissionsData.Securable.GetSecurableType(t);
+ SearchableObjectTypeDescription desc = SearchableObjectTypeDescription.GetDescription(t);
+ if (desc.DisplayTypeNameSingular == typeStr || desc.DisplayTypeNamePlural == typeStr)
+ {
+ return t;
+ }
+ }
+ return SearchableObjectType.LastType;
+ }
+
+ internal static void GetPrincipalToExecuteAs(Principal principal,
+ string databaseName,
+ object connectionInfo,
+ out string executeas,
+ out string executetype)
+ {
+ executeas = null;
+ executetype = null;
+
+ //
+ // IF we are a user AND we are mapped to a login,
+ // then we actually want to calculate effective
+ // permissions as the login, and not as the user.
+ // why? because that's the only way the server
+ // level perms will be taken into account.
+ //
+ if (principal.PrincipalType == PrincipalType.User &&
+ !string.IsNullOrEmpty(databaseName))
+ {
+ SqlConnectionInfoWithConnection ci = connectionInfo as SqlConnectionInfoWithConnection;
+ if (ci != null && ci.ServerConnection != null)
+ {
+ Server server = new Server(ci.ServerConnection);
+ if (server != null)
+ {
+ Database db = server.Databases[databaseName];
+ if (db != null)
+ {
+ User u = db.Users[principal.Name];
+
+ //
+ // if the the user is mapped to a certificate or
+ // or asymmetric key, we should execute as user.
+ //
+ if (u != null &&
+ (u.LoginType == LoginType.SqlLogin ||
+ u.LoginType == LoginType.WindowsUser ||
+ u.LoginType == LoginType.WindowsGroup) &&
+ !string.IsNullOrEmpty(u.Login))
+ {
+ executeas = u.Login;
+ executetype = "login";
+ }
+ }
+ }
+ }
+ }
+
+ //
+ // if we couldn't determine what type of user the principal was,
+ // or if the user is mapped to a certificate or asymmetric key, or if
+ // the principal was a login, we will default to executing as whatever
+ // principal type we are (either login or user).
+ //
+ if (string.IsNullOrEmpty(executeas) || string.IsNullOrEmpty(executetype))
+ {
+ executeas = principal.Name;
+ executetype = (principal.PrincipalType == PrincipalType.Login) ? "login" : "user";
+ }
+ }
+
+ internal static SearchableObject ConvertFromSecurableNameToSearchableObject(string securableName, string type, string database, object connectionInfo)
+ {
+ SearchableObjectType searchableObjectType = ConvertPotentialSqlObjectTypeToSearchableObjectType(type);
+
+ SearchableObjectTypeDescription desc = SearchableObjectTypeDescription.GetDescription(searchableObjectType);
+ var urn = desc.GetSearchUrn(securableName, true, true);
+ return SearchableObject.GetSearchableObject(searchableObjectType, connectionInfo, database, securableName);
+ }
+
+ internal static void SendToServerPermissionChanges(bool exists, string name, SecurablePermissions[] securablePermissions, Principal principal, CDataContainer dataContainer, string database)
+ {
+ if (securablePermissions == null)
+ {
+ return;
+ }
+
+ if (!exists)
+ {
+ foreach (SecurablePermissions secPerm in securablePermissions)
+ {
+ var securable = principal.AddSecurable(SecurableUtils.ConvertFromSecurableNameToSearchableObject(secPerm.Name, secPerm.Type, database, dataContainer.ConnectionInfo));
+ var states = principal.GetPermissionStates(securable);
+ ApplyPermissionStates(secPerm.Permissions, states);
+ }
+ }
+ else
+ {
+ var securables = principal.GetSecurables(new SecurableComparer(SecurableComparer.DefaultSortingOrder, true));
+ foreach (SecurablePermissions secPerm in securablePermissions)
+ {
+ var securable = FindMatchedSecurable(securables, secPerm.Name) ?? principal.AddSecurable(SecurableUtils.ConvertFromSecurableNameToSearchableObject(secPerm.Name, secPerm.Type, database, dataContainer.ConnectionInfo));
+ var states = principal.GetPermissionStates(securable);
+ ApplyPermissionStates(secPerm.Permissions, states);
+ }
+
+ var newSecurableNames = securablePermissions.Select(s => s.Name).ToHashSet();
+ foreach (Securable securable in securables)
+ {
+ if (!newSecurableNames.Contains(securable.Name))
+ {
+ var states = principal.GetPermissionStates(securable);
+ for (int i = 0; i < states.Count; i++)
+ {
+ states[i].Revoke();
+ }
+ principal.RemoveSecurable(securable);
+ }
+ }
+ }
+ principal.ApplyChanges(name, dataContainer.Server);
+ }
+
+ private static Securable FindMatchedSecurable(SecurableList securableList, string name)
+ {
+ foreach (Securable securable in securableList)
+ {
+ if (securable.Name == name)
+ {
+ return securable;
+ }
+ }
+ return null;
+ }
+
+ private static void ApplyPermissionStates(SecurablePermissionItem[] items, PermissionStateCollection states)
+ {
+ foreach (var p in items)
+ {
+ var key = p.Permission + p.Grantor;
+ if (p.WithGrant == true)
+ {
+ states[key].State = PermissionStatus.WithGrant;
+ }
+ else if (p.Grant == true)
+ {
+ states[key].State = PermissionStatus.Grant;
+ }
+ else if (p.Grant == false)
+ {
+ states[key].State = PermissionStatus.Deny;
+ }
+ else if (p.Grant == null)
+ {
+ states[key].State = PermissionStatus.Revoke;
+ }
+ }
+ var itemNames = items.Select(item => item.Permission).ToHashSet();
+
+ for (int i = 0; i < states.Count; i++)
+ {
+ var state = states[i];
+ if (!itemNames.Contains(state.Permission.Name))
+ {
+ state.State = PermissionStatus.Revoke;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/SecurityPrincipalObject.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/SecurityPrincipalObject.cs
new file mode 100644
index 00000000..599c996b
--- /dev/null
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/SecurityPrincipalObject.cs
@@ -0,0 +1,12 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
+{
+ public abstract class SecurityPrincipalObject : SqlObject
+ {
+ public SecurablePermissions[]? SecurablePermissions { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/SecurityPrincipalViewInfo.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/SecurityPrincipalViewInfo.cs
new file mode 100644
index 00000000..ccf1cca1
--- /dev/null
+++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/SecurityPrincipalViewInfo.cs
@@ -0,0 +1,12 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
+{
+ public abstract class SecurityPrincipalViewInfo : SqlObjectViewInfo
+ {
+ public SecurableTypeMetadata[]? SupportedSecurableTypes { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/ObjectManagement/ObjectManagementTestUtils.cs b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/ObjectManagement/ObjectManagementTestUtils.cs
index b1008234..d2244fea 100644
--- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/ObjectManagement/ObjectManagementTestUtils.cs
+++ b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/ObjectManagement/ObjectManagementTestUtils.cs
@@ -71,7 +71,8 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectManagement
Password = "placeholder" + new Random().NextInt64(10000000, 90000000).ToString() + "!*PLACEHOLDER",
OldPassword = "placeholder" + new Random().NextInt64(10000000, 90000000).ToString() + "!*PLACEHOLDER",
DefaultLanguage = "English - us_english",
- DefaultDatabase = "master"
+ DefaultDatabase = "master",
+ SecurablePermissions = new SecurablePermissions[0]
};
}
@@ -84,7 +85,8 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectManagement
LoginName = loginName,
Password = "placeholder" + new Random().NextInt64(10000000, 90000000).ToString() + "!*PLACEHOLDER",
DefaultSchema = "dbo",
- OwnedSchemas = new string[] { "" }
+ OwnedSchemas = new string[] { "" },
+ SecurablePermissions = new SecurablePermissions[0]
};
}