mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-13 17:23:02 -05:00
Add explicit CREATE TABLE permission check for table designer (#2128)
This commit is contained in:
@@ -12916,6 +12916,16 @@ namespace Microsoft.SqlTools.ServiceLayer
|
|||||||
return Keys.GetString(Keys.NonClusteredColumnStoreIndexMustHaveColumnsRuleDescription, indexName);
|
return Keys.GetString(Keys.NonClusteredColumnStoreIndexMustHaveColumnsRuleDescription, indexName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string TableDesignerCreateTablePermissionDenied(string db)
|
||||||
|
{
|
||||||
|
return Keys.GetString(Keys.TableDesignerCreateTablePermissionDenied, db);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string TableDesignerAlterTablePermissionDenied(string table)
|
||||||
|
{
|
||||||
|
return Keys.GetString(Keys.TableDesignerAlterTablePermissionDenied, table);
|
||||||
|
}
|
||||||
|
|
||||||
public static string SqlProjectModelNotFound(string projectUri)
|
public static string SqlProjectModelNotFound(string projectUri)
|
||||||
{
|
{
|
||||||
return Keys.GetString(Keys.SqlProjectModelNotFound, projectUri);
|
return Keys.GetString(Keys.SqlProjectModelNotFound, projectUri);
|
||||||
@@ -16871,6 +16881,12 @@ namespace Microsoft.SqlTools.ServiceLayer
|
|||||||
public const string TableDesignerConfirmationText = "TableDesignerConfirmationText";
|
public const string TableDesignerConfirmationText = "TableDesignerConfirmationText";
|
||||||
|
|
||||||
|
|
||||||
|
public const string TableDesignerCreateTablePermissionDenied = "TableDesignerCreateTablePermissionDenied";
|
||||||
|
|
||||||
|
|
||||||
|
public const string TableDesignerAlterTablePermissionDenied = "TableDesignerAlterTablePermissionDenied";
|
||||||
|
|
||||||
|
|
||||||
public const string SqlProjectModelNotFound = "SqlProjectModelNotFound";
|
public const string SqlProjectModelNotFound = "SqlProjectModelNotFound";
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5440,6 +5440,16 @@ The Query Processor estimates that implementing the following index could improv
|
|||||||
<value>I have read the summary and understand the potential risks.</value>
|
<value>I have read the summary and understand the potential risks.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="TableDesignerCreateTablePermissionDenied" xml:space="preserve">
|
||||||
|
<value>CREATE TABLE permission denied in database '{0}'.</value>
|
||||||
|
<comment>.
|
||||||
|
Parameters: 0 - db (string) </comment>
|
||||||
|
</data>
|
||||||
|
<data name="TableDesignerAlterTablePermissionDenied" xml:space="preserve">
|
||||||
|
<value>ALTER TABLE permission denied for table '{0}'.</value>
|
||||||
|
<comment>.
|
||||||
|
Parameters: 0 - table (string) </comment>
|
||||||
|
</data>
|
||||||
<data name="SqlProjectModelNotFound" xml:space="preserve">
|
<data name="SqlProjectModelNotFound" xml:space="preserve">
|
||||||
<value>Could not find SQL model from project: {0}.</value>
|
<value>Could not find SQL model from project: {0}.</value>
|
||||||
<comment>.
|
<comment>.
|
||||||
|
|||||||
@@ -2451,6 +2451,8 @@ HashIndexMustHaveBucketCountRuleDescription(string indexName) = Hash index '{0}'
|
|||||||
ColumnCanOnlyAppearOnceInNonClusteredColumnStoreIndexRuleDescription(string columnName, string indexName, int rowNumber) = Column with name '{0}' has already been added to the non-clustered columnstore index '{1}'. Row number: {2}.
|
ColumnCanOnlyAppearOnceInNonClusteredColumnStoreIndexRuleDescription(string columnName, string indexName, int rowNumber) = Column with name '{0}' has already been added to the non-clustered columnstore index '{1}'. Row number: {2}.
|
||||||
NonClusteredColumnStoreIndexMustHaveColumnsRuleDescription(string indexName) = Non-clustered columnstore index '{0}' does not have any columns associated with it.
|
NonClusteredColumnStoreIndexMustHaveColumnsRuleDescription(string indexName) = Non-clustered columnstore index '{0}' does not have any columns associated with it.
|
||||||
TableDesignerConfirmationText = I have read the summary and understand the potential risks.
|
TableDesignerConfirmationText = I have read the summary and understand the potential risks.
|
||||||
|
TableDesignerCreateTablePermissionDenied(string db) = CREATE TABLE permission denied in database '{0}'.
|
||||||
|
TableDesignerAlterTablePermissionDenied(string table) = ALTER TABLE permission denied for table '{0}'.
|
||||||
|
|
||||||
############################################################################
|
############################################################################
|
||||||
# TSql Model
|
# TSql Model
|
||||||
|
|||||||
@@ -8321,6 +8321,17 @@ The Query Processor estimates that implementing the following index could improv
|
|||||||
<target state="new">None</target>
|
<target state="new">None</target>
|
||||||
<note></note>
|
<note></note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="TableDesignerCreateTablePermissionDenied">
|
||||||
|
<source>CREATE TABLE permission denied in database '{0}'.</source>
|
||||||
|
<target state="new">CREATE TABLE permission denied in database '{0}'.</target>
|
||||||
|
<note></note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="TableDesignerAlterTablePermissionDenied">
|
||||||
|
<source>ALTER TABLE permission denied for table '{0}'.</source>
|
||||||
|
<target state="new">ALTER TABLE permission denied for table '{0}'.</target>
|
||||||
|
<note>.
|
||||||
|
Parameters: 0 - table (string) </note>
|
||||||
|
</trans-unit>
|
||||||
</body>
|
</body>
|
||||||
</file>
|
</file>
|
||||||
</xliff>
|
</xliff>
|
||||||
@@ -18,6 +18,7 @@ using Dac = Microsoft.Data.Tools.Sql.DesignServices.TableDesigner;
|
|||||||
using STSHost = Microsoft.SqlTools.ServiceLayer.Hosting.ServiceHost;
|
using STSHost = Microsoft.SqlTools.ServiceLayer.Hosting.ServiceHost;
|
||||||
using Microsoft.SqlTools.ServiceLayer.SqlContext;
|
using Microsoft.SqlTools.ServiceLayer.SqlContext;
|
||||||
using Microsoft.SqlTools.ServiceLayer.Connection;
|
using Microsoft.SqlTools.ServiceLayer.Connection;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection;
|
||||||
|
|
||||||
namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
|
namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
|
||||||
{
|
{
|
||||||
@@ -31,6 +32,8 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
|
|||||||
private Dictionary<string, Dac.TableDesigner> idTableMap = new Dictionary<string, Dac.TableDesigner>();
|
private Dictionary<string, Dac.TableDesigner> idTableMap = new Dictionary<string, Dac.TableDesigner>();
|
||||||
private bool disposed = false;
|
private bool disposed = false;
|
||||||
private static readonly Lazy<TableDesignerService> instance = new Lazy<TableDesignerService>(() => new TableDesignerService());
|
private static readonly Lazy<TableDesignerService> instance = new Lazy<TableDesignerService>(() => new TableDesignerService());
|
||||||
|
private const string CheckCreateTablePermissionInDbQuery = "SELECT HAS_PERMS_BY_NAME(QUOTENAME(@dbname), 'DATABASE', 'CREATE TABLE')";
|
||||||
|
private const string CheckAlterTablePermissionQuery = "SELECT HAS_PERMS_BY_NAME(QUOTENAME(@schema) + '.' + QUOTENAME(@table), 'OBJECT', 'ALTER')";
|
||||||
|
|
||||||
public TableDesignerService()
|
public TableDesignerService()
|
||||||
{
|
{
|
||||||
@@ -1807,8 +1810,17 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
|
|||||||
// Set Access Token only when authentication mode is not specified.
|
// Set Access Token only when authentication mode is not specified.
|
||||||
var accessToken = connectionStringBuilder.Authentication == SqlAuthenticationMethod.NotSpecified
|
var accessToken = connectionStringBuilder.Authentication == SqlAuthenticationMethod.NotSpecified
|
||||||
? tableInfo.AccessToken : null;
|
? tableInfo.AccessToken : null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
tableDesigner = new Dac.TableDesigner(connectionString, accessToken, tableInfo.Schema, tableInfo.Name, tableInfo.IsNewTable, tableDesignerOptions);
|
tableDesigner = new Dac.TableDesigner(connectionString, accessToken, tableInfo.Schema, tableInfo.Name, tableInfo.IsNewTable, tableDesignerOptions);
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
CheckPermissions(tableInfo, connectionString);
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tableDesigner = new Dac.TableDesigner(tableInfo.ProjectFilePath, tableInfo.TableScriptPath, tableInfo.AllScripts, tableInfo.TargetVersion);
|
tableDesigner = new Dac.TableDesigner(tableInfo.ProjectFilePath, tableInfo.TableScriptPath, tableInfo.AllScripts, tableInfo.TargetVersion);
|
||||||
@@ -1855,6 +1867,55 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
|
|||||||
return metadata;
|
return metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void CheckPermissions(TableInfo tableInfo, string connectionString)
|
||||||
|
{
|
||||||
|
CheckCreateAlterTablePermission(tableInfo, connectionString);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CheckCreateAlterTablePermission(TableInfo tableInfo, string connectionString)
|
||||||
|
{
|
||||||
|
if (tableInfo.IsNewTable)
|
||||||
|
{
|
||||||
|
|
||||||
|
ReliableConnectionHelper.ExecuteReader(connectionString, CheckCreateTablePermissionInDbQuery, (reader) =>
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
if (reader.IsDBNull(0) || (int)reader[0] != 1)
|
||||||
|
{
|
||||||
|
throw new Exception(SR.TableDesignerCreateTablePermissionDenied(tableInfo.Database));
|
||||||
|
}
|
||||||
|
}, (cmd) =>
|
||||||
|
{
|
||||||
|
var dbNameParameter = cmd.CreateParameter();
|
||||||
|
dbNameParameter.ParameterName = "@dbname";
|
||||||
|
dbNameParameter.Value = tableInfo.Database;
|
||||||
|
cmd.Parameters.Add(dbNameParameter);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ReliableConnectionHelper.ExecuteReader(connectionString, CheckAlterTablePermissionQuery, (reader) =>
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
if (reader.IsDBNull(0) || (int)reader[0] != 1)
|
||||||
|
{
|
||||||
|
throw new Exception(SR.TableDesignerAlterTablePermissionDenied(tableInfo.Name));
|
||||||
|
}
|
||||||
|
}, (cmd) =>
|
||||||
|
{
|
||||||
|
var schemaParameter = cmd.CreateParameter();
|
||||||
|
schemaParameter.ParameterName = "@schema";
|
||||||
|
schemaParameter.Value = tableInfo.Schema;
|
||||||
|
cmd.Parameters.Add(schemaParameter);
|
||||||
|
|
||||||
|
var tableParameter = cmd.CreateParameter();
|
||||||
|
tableParameter.ParameterName = "@table";
|
||||||
|
tableParameter.Value = tableInfo.Name;
|
||||||
|
cmd.Parameters.Add(tableParameter);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Disposes the table designer Service
|
/// Disposes the table designer Service
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user