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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
return Keys.GetString(Keys.SqlProjectModelNotFound, projectUri);
|
||||
@@ -16871,6 +16881,12 @@ namespace Microsoft.SqlTools.ServiceLayer
|
||||
public const string TableDesignerConfirmationText = "TableDesignerConfirmationText";
|
||||
|
||||
|
||||
public const string TableDesignerCreateTablePermissionDenied = "TableDesignerCreateTablePermissionDenied";
|
||||
|
||||
|
||||
public const string TableDesignerAlterTablePermissionDenied = "TableDesignerAlterTablePermissionDenied";
|
||||
|
||||
|
||||
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>
|
||||
<comment></comment>
|
||||
</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">
|
||||
<value>Could not find SQL model from project: {0}.</value>
|
||||
<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}.
|
||||
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.
|
||||
TableDesignerCreateTablePermissionDenied(string db) = CREATE TABLE permission denied in database '{0}'.
|
||||
TableDesignerAlterTablePermissionDenied(string table) = ALTER TABLE permission denied for table '{0}'.
|
||||
|
||||
############################################################################
|
||||
# TSql Model
|
||||
|
||||
@@ -8321,6 +8321,17 @@ The Query Processor estimates that implementing the following index could improv
|
||||
<target state="new">None</target>
|
||||
<note></note>
|
||||
</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>
|
||||
</file>
|
||||
</xliff>
|
||||
@@ -18,6 +18,7 @@ using Dac = Microsoft.Data.Tools.Sql.DesignServices.TableDesigner;
|
||||
using STSHost = Microsoft.SqlTools.ServiceLayer.Hosting.ServiceHost;
|
||||
using Microsoft.SqlTools.ServiceLayer.SqlContext;
|
||||
using Microsoft.SqlTools.ServiceLayer.Connection;
|
||||
using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection;
|
||||
|
||||
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 bool disposed = false;
|
||||
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()
|
||||
{
|
||||
@@ -1807,7 +1810,16 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
|
||||
// Set Access Token only when authentication mode is not specified.
|
||||
var accessToken = connectionStringBuilder.Authentication == SqlAuthenticationMethod.NotSpecified
|
||||
? tableInfo.AccessToken : null;
|
||||
tableDesigner = new Dac.TableDesigner(connectionString, accessToken, tableInfo.Schema, tableInfo.Name, tableInfo.IsNewTable, tableDesignerOptions);
|
||||
|
||||
try
|
||||
{
|
||||
tableDesigner = new Dac.TableDesigner(connectionString, accessToken, tableInfo.Schema, tableInfo.Name, tableInfo.IsNewTable, tableDesignerOptions);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
CheckPermissions(tableInfo, connectionString);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1855,6 +1867,55 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
|
||||
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>
|
||||
/// Disposes the table designer Service
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user