simplify drop object request handler (#1953)

* simplify drop object request handler

* fix test cases

* fix issues

* update strings

* fix error

* fix error
This commit is contained in:
Alan Ren
2023-03-20 21:54:34 -07:00
committed by GitHub
parent b4781cf267
commit 692f444ccb
14 changed files with 187 additions and 271 deletions

View File

@@ -10150,6 +10150,11 @@ namespace Microsoft.SqlTools.ServiceLayer
return Keys.GetString(Keys.UnsupportedModelType, type); return Keys.GetString(Keys.UnsupportedModelType, type);
} }
public static string ObjectNotRenamable(string urn)
{
return Keys.GetString(Keys.ObjectNotRenamable, urn);
}
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class Keys public class Keys
{ {
@@ -14043,6 +14048,9 @@ namespace Microsoft.SqlTools.ServiceLayer
public const string ErrorConnectionNotFound = "ErrorConnectionNotFound"; public const string ErrorConnectionNotFound = "ErrorConnectionNotFound";
public const string ObjectNotRenamable = "ObjectNotRenamable";
public const string DefaultLanguagePlaceholder = "DefaultLanguagePlaceholder"; public const string DefaultLanguagePlaceholder = "DefaultLanguagePlaceholder";

View File

@@ -5386,6 +5386,11 @@ The Query Processor estimates that implementing the following index could improv
<value>The connection could not be found</value> <value>The connection could not be found</value>
<comment></comment> <comment></comment>
</data> </data>
<data name="ObjectNotRenamable" xml:space="preserve">
<value>The object could not be renamed. URN: &apos;{0}&apos;.</value>
<comment>.
Parameters: 0 - urn (string) </comment>
</data>
<data name="DefaultLanguagePlaceholder" xml:space="preserve"> <data name="DefaultLanguagePlaceholder" xml:space="preserve">
<value>&lt;default&gt;</value> <value>&lt;default&gt;</value>
<comment></comment> <comment></comment>

View File

@@ -2443,6 +2443,7 @@ GetUserDefinedObjectsFromModelFailed = Failed to get user defined objects from m
#ObjectManagement Service #ObjectManagement Service
ErrorConnectionNotFound = The connection could not be found ErrorConnectionNotFound = The connection could not be found
ObjectNotRenamable(string urn) = The object could not be renamed. URN: '{0}'.
############################################################################ ############################################################################
# Security Service # Security Service

View File

@@ -6576,6 +6576,12 @@ The Query Processor estimates that implementing the following index could improv
<target state="new">Reset password for the login while unlocking.</target> <target state="new">Reset password for the login while unlocking.</target>
<note></note> <note></note>
</trans-unit> </trans-unit>
<trans-unit id="ObjectNotRenamable">
<source>The object could not be renamed. URN: '{0}'.</source>
<target state="new">The object could not be renamed. URN: '{0}'.</target>
<note>.
Parameters: 0 - urn (string) </note>
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View File

@@ -0,0 +1,32 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
#nullable disable
using Microsoft.SqlTools.Hosting.Protocol.Contracts;
using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement.Contracts
{
public class DropRequestParams : GeneralRequestDetails
{
/// <summary>
/// SFC (SMO) URN identifying the object
/// </summary>
public string ObjectUrn { get; set; }
/// <summary>
/// Connection uri
/// </summary>
public string ConnectionUri { get; set; }
/// <summary>
/// Whether to throw an error if the object does not exist. The default value is false.
/// </summary>
public bool ThrowIfNotExist { get; set; } = false;
}
public class DropRequest
{
public static readonly RequestType<DropRequestParams, bool> Type = RequestType<DropRequestParams, bool>.Create("objectManagement/drop");
}
}

View File

@@ -11,7 +11,9 @@ using Microsoft.SqlServer.Management.Sdk.Sfc;
using Microsoft.SqlServer.Management.Smo; using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.Hosting.Protocol; using Microsoft.SqlTools.Hosting.Protocol;
using Microsoft.SqlTools.ServiceLayer.Connection; using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.Management;
using Microsoft.SqlTools.ServiceLayer.ObjectManagement.Contracts; using Microsoft.SqlTools.ServiceLayer.ObjectManagement.Contracts;
using Microsoft.SqlTools.ServiceLayer.Utility;
using Microsoft.SqlTools.Utility; using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
@@ -48,6 +50,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
{ {
this.serviceHost = serviceHost; this.serviceHost = serviceHost;
this.serviceHost.SetRequestHandler(RenameRequest.Type, HandleRenameRequest, true); this.serviceHost.SetRequestHandler(RenameRequest.Type, HandleRenameRequest, true);
this.serviceHost.SetRequestHandler(DropRequest.Type, HandleDropRequest, true);
} }
/// <summary> /// <summary>
@@ -58,40 +61,74 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
/// <returns></returns> /// <returns></returns>
internal async Task HandleRenameRequest(RenameRequestParams requestParams, RequestContext<bool> requestContext) internal async Task HandleRenameRequest(RenameRequestParams requestParams, RequestContext<bool> requestContext)
{ {
Logger.Verbose("Handle Request in HandleProcessRenameEditRequest()"); Logger.Verbose("Handle Request in HandleRenameRequest()");
ConnectionInfo connInfo; ExecuteActionOnObject(requestParams.ConnectionUri, requestParams.ObjectUrn, (dbObject) =>
if (ConnectionServiceInstance.TryFindConnection(
requestParams.ConnectionUri,
out connInfo))
{ {
ServerConnection serverConnection = ConnectionService.OpenServerConnection(connInfo, ObjectManagementServiceApplicationName); var renamable = dbObject as IRenamable;
using (serverConnection.SqlConnectionObject) if (renamable != null)
{ {
IRenamable renameObject = this.GetRenamable(requestParams, serverConnection); renamable.Rename(requestParams.NewName);
renameObject.Rename(requestParams.NewName);
} }
} else
else {
{ throw new Exception(SR.ObjectNotRenamable(requestParams.ObjectUrn));
Logger.Error($"The connection {requestParams.ConnectionUri} could not be found."); }
throw new Exception(SR.ErrorConnectionNotFound); });
}
await requestContext.SendResult(true); await requestContext.SendResult(true);
} }
/// <summary> /// <summary>
/// Method to get the sql object, which should be renamed /// Method to handle the delete object request
/// </summary> /// </summary>
/// <param name="requestParams">parameters which are required for the rename operation</param> /// <param name="requestParams">parameters which are needed to execute deletion operation</param>
/// <param name="connection">the server connection on the server to search for the sqlobject</param> /// <param name="requestContext">Request Context</param>
/// <returns>the sql object if implements the interface IRenamable, so they can be renamed</returns> /// <returns></returns>
private IRenamable GetRenamable(RenameRequestParams requestParams, ServerConnection connection) internal async Task HandleDropRequest(DropRequestParams requestParams, RequestContext<bool> requestContext)
{ {
Server server = new Server(connection); Logger.Verbose("Handle Request in HandleDeleteRequest()");
SqlSmoObject dbObject = server.GetSmoObject(new Urn(requestParams.ObjectUrn)); ConnectionInfo connectionInfo = this.GetConnectionInfo(requestParams.ConnectionUri);
return (IRenamable)dbObject; using (CDataContainer dataContainer = CDataContainer.CreateDataContainer(connectionInfo, databaseExists: true))
{
try
{
dataContainer.SqlDialogSubject = dataContainer.Server?.GetSmoObject(requestParams.ObjectUrn);
DatabaseUtils.DoDropObject(dataContainer);
}
catch (FailedOperationException ex)
{
if (ex.InnerException is MissingObjectException && requestParams.ThrowIfNotExist)
{
throw;
}
}
}
await requestContext.SendResult(true);
}
private ConnectionInfo GetConnectionInfo(string connectionUri)
{
ConnectionInfo connInfo;
if (ConnectionServiceInstance.TryFindConnection(connectionUri, out connInfo))
{
return connInfo;
}
else
{
Logger.Error($"The connection with URI '{connectionUri}' could not be found.");
throw new Exception(SR.ErrorConnectionNotFound);
}
}
private void ExecuteActionOnObject(string connectionUri, string objectUrn, Action<SqlSmoObject> action)
{
ConnectionInfo connInfo = this.GetConnectionInfo(connectionUri);
ServerConnection serverConnection = ConnectionService.OpenServerConnection(connInfo, ObjectManagementServiceApplicationName);
using (serverConnection.SqlConnectionObject)
{
Server server = new Server(serverConnection);
SqlSmoObject dbObject = server.GetSmoObject(new Urn(objectUrn));
action(dbObject);
}
} }
} }
} }

View File

@@ -32,29 +32,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Security.Contracts
RequestType<CreateLoginParams, object>.Create("objectManagement/createLogin"); RequestType<CreateLoginParams, object>.Create("objectManagement/createLogin");
} }
/// <summary>
/// Delete Login params
/// </summary>
public class DeleteLoginParams
{
public string ConnectionUri { get; set; }
public string Name { get; set; }
}
/// <summary>
/// Delete Login request type
/// </summary>
public class DeleteLoginRequest
{
/// <summary>
/// Request definition
/// </summary>
public static readonly
RequestType<DeleteLoginParams, object> Type =
RequestType<DeleteLoginParams, object>.Create("objectManagement/deleteLogin");
}
/// <summary> /// <summary>
/// Update Login params /// Update Login params
/// </summary> /// </summary>

View File

@@ -89,31 +89,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Security.Contracts
RequestType<UpdateUserParams, ResultStatus>.Create("objectManagement/updateUser"); RequestType<UpdateUserParams, ResultStatus>.Create("objectManagement/updateUser");
} }
/// <summary>
/// Delete User params
/// </summary>
public class DeleteUserParams
{
public string? ConnectionUri { get; set; }
public string? Database { get; set; }
public string? Name { get; set; }
}
/// <summary>
/// Delete User request type
/// </summary>
public class DeleteUserRequest
{
/// <summary>
/// Request definition
/// </summary>
public static readonly
RequestType<DeleteUserParams, ResultStatus> Type =
RequestType<DeleteUserParams, ResultStatus>.Create("objectManagement/deleteUser");
}
/// <summary> /// <summary>
/// Update User params /// Update User params
/// </summary> /// </summary>

View File

@@ -88,13 +88,11 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
// Credential request handlers // Credential request handlers
this.ServiceHost.SetRequestHandler(CreateCredentialRequest.Type, HandleCreateCredentialRequest, true); this.ServiceHost.SetRequestHandler(CreateCredentialRequest.Type, HandleCreateCredentialRequest, true);
this.ServiceHost.SetRequestHandler(UpdateCredentialRequest.Type, HandleUpdateCredentialRequest, true); this.ServiceHost.SetRequestHandler(UpdateCredentialRequest.Type, HandleUpdateCredentialRequest, true);
this.ServiceHost.SetRequestHandler(DeleteCredentialRequest.Type, HandleDeleteCredentialRequest, true);
this.ServiceHost.SetRequestHandler(GetCredentialsRequest.Type, HandleGetCredentialsRequest, true); this.ServiceHost.SetRequestHandler(GetCredentialsRequest.Type, HandleGetCredentialsRequest, true);
// Login request handlers // Login request handlers
this.ServiceHost.SetRequestHandler(CreateLoginRequest.Type, HandleCreateLoginRequest, true); this.ServiceHost.SetRequestHandler(CreateLoginRequest.Type, HandleCreateLoginRequest, true);
this.ServiceHost.SetRequestHandler(UpdateLoginRequest.Type, HandleUpdateLoginRequest, true); this.ServiceHost.SetRequestHandler(UpdateLoginRequest.Type, HandleUpdateLoginRequest, true);
this.ServiceHost.SetRequestHandler(DeleteLoginRequest.Type, HandleDeleteLoginRequest, true);
this.ServiceHost.SetRequestHandler(InitializeLoginViewRequest.Type, HandleInitializeLoginViewRequest, true); this.ServiceHost.SetRequestHandler(InitializeLoginViewRequest.Type, HandleInitializeLoginViewRequest, true);
this.ServiceHost.SetRequestHandler(DisposeLoginViewRequest.Type, HandleDisposeLoginViewRequest, true); this.ServiceHost.SetRequestHandler(DisposeLoginViewRequest.Type, HandleDisposeLoginViewRequest, true);
@@ -102,12 +100,11 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
this.ServiceHost.SetRequestHandler(InitializeUserViewRequest.Type, this.userServiceHandler.HandleInitializeUserViewRequest, true); this.ServiceHost.SetRequestHandler(InitializeUserViewRequest.Type, this.userServiceHandler.HandleInitializeUserViewRequest, true);
this.ServiceHost.SetRequestHandler(CreateUserRequest.Type, this.userServiceHandler.HandleCreateUserRequest, true); this.ServiceHost.SetRequestHandler(CreateUserRequest.Type, this.userServiceHandler.HandleCreateUserRequest, true);
this.ServiceHost.SetRequestHandler(UpdateUserRequest.Type, this.userServiceHandler.HandleUpdateUserRequest, true); this.ServiceHost.SetRequestHandler(UpdateUserRequest.Type, this.userServiceHandler.HandleUpdateUserRequest, true);
this.ServiceHost.SetRequestHandler(DeleteUserRequest.Type, this.userServiceHandler.HandleDeleteUserRequest, true);
this.ServiceHost.SetRequestHandler(DisposeUserViewRequest.Type, this.userServiceHandler.HandleDisposeUserViewRequest, true); this.ServiceHost.SetRequestHandler(DisposeUserViewRequest.Type, this.userServiceHandler.HandleDisposeUserViewRequest, true);
} }
#region "Login Handlers" #region "Login Handlers"
/// <summary> /// <summary>
/// Handle request to create a login /// Handle request to create a login
@@ -161,31 +158,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
await requestContext.SendResult(new object()); await requestContext.SendResult(new object());
} }
/// <summary>
/// Handle request to delete a credential
/// </summary>
internal async Task HandleDeleteLoginRequest(DeleteLoginParams parameters, RequestContext<object> requestContext)
{
ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection(parameters.ConnectionUri, out connInfo);
if (connInfo == null)
{
throw new ArgumentException("Invalid ConnectionUri");
}
CDataContainer dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists: true);
Login login = dataContainer.Server?.Logins[parameters.Name];
dataContainer.SqlDialogSubject = login;
DatabaseUtils.DoDropObject(dataContainer);
await requestContext.SendResult(new ResultStatus()
{
Success = true,
ErrorMessage = string.Empty
});
}
internal async Task HandleUpdateLoginRequest(UpdateLoginParams parameters, RequestContext<object> requestContext) internal async Task HandleUpdateLoginRequest(UpdateLoginParams parameters, RequestContext<object> requestContext)
{ {
ConnectionInfo connInfo; ConnectionInfo connInfo;
@@ -418,24 +390,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
}); });
} }
/// <summary>
/// Handle request to delete a credential
/// </summary>
internal async Task HandleDeleteCredentialRequest(DeleteCredentialParams parameters, RequestContext<ResultStatus> requestContext)
{
var result = await ConfigureCredential(parameters.OwnerUri,
parameters.Credential,
ConfigAction.Drop,
RunType.RunNow);
await requestContext.SendResult(new ResultStatus()
{
Success = result.Item1,
ErrorMessage = result.Item2
});
}
/// <summary> /// <summary>
/// Handle request to get all credentials /// Handle request to get all credentials
/// </summary> /// </summary>

View File

@@ -37,7 +37,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
private ConnectionService? connectionService; private ConnectionService? connectionService;
private Dictionary<string, UserViewState> contextIdToViewState = new Dictionary<string, UserViewState>(); private Dictionary<string, UserViewState> contextIdToViewState = new Dictionary<string, UserViewState>();
/// <summary> /// <summary>
/// Internal for testing purposes only /// Internal for testing purposes only
/// </summary> /// </summary>
@@ -122,8 +122,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
} }
UserPrototypeFactory userPrototypeFactory = UserPrototypeFactory.GetInstance(dataContainer, userInfo, originalData: null); UserPrototypeFactory userPrototypeFactory = UserPrototypeFactory.GetInstance(dataContainer, userInfo, originalData: null);
UserPrototype currentUserPrototype = userPrototypeFactory.GetUserPrototype(ExhaustiveUserTypes.LoginMappedUser); UserPrototype currentUserPrototype = userPrototypeFactory.GetUserPrototype(ExhaustiveUserTypes.LoginMappedUser);
IUserPrototypeWithDefaultLanguage defaultLanguagePrototype = currentUserPrototype as IUserPrototypeWithDefaultLanguage; IUserPrototypeWithDefaultLanguage defaultLanguagePrototype = currentUserPrototype as IUserPrototypeWithDefaultLanguage;
string? defaultLanguageAlias = null; string? defaultLanguageAlias = null;
if (defaultLanguagePrototype != null && defaultLanguagePrototype.IsDefaultLanguageSupported) if (defaultLanguagePrototype != null && defaultLanguagePrototype.IsDefaultLanguageSupported)
@@ -209,7 +209,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
}; };
this.contextIdToViewState.Add( this.contextIdToViewState.Add(
parameters.ContextId, parameters.ContextId,
new UserViewState(parameters.Database, currentUserPrototype.CurrentState)); new UserViewState(parameters.Database, currentUserPrototype.CurrentState));
await requestContext.SendResult(userViewInfo); await requestContext.SendResult(userViewInfo);
@@ -282,42 +282,10 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
}); });
} }
/// <summary>
/// Handle request to delete a user
/// </summary>
internal async Task HandleDeleteUserRequest(DeleteUserParams parameters, RequestContext<ResultStatus> requestContext)
{
ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection(parameters.ConnectionUri, out connInfo);
if (connInfo == null)
{
throw new ArgumentException("Invalid ConnectionUri");
}
if (string.IsNullOrWhiteSpace(parameters.Name) || string.IsNullOrWhiteSpace(parameters.Database))
{
throw new ArgumentException("Invalid null parameter");
}
CDataContainer dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists: true);
string dbUrn = "Server/Database[@Name='" + Urn.EscapeString(parameters.Database) + "']";
Database? parent = dataContainer.Server.GetSmoObject(new Urn(dbUrn)) as Database;
User user = parent.Users[parameters.Name];
dataContainer.SqlDialogSubject = user;
CheckForSchemaOwnerships(parent, user);
DatabaseUtils.DoDropObject(dataContainer);
await requestContext.SendResult(new ResultStatus()
{
Success = true,
ErrorMessage = string.Empty
});
}
internal async Task HandleDisposeUserViewRequest(DisposeUserViewRequestParams parameters, RequestContext<ResultStatus> requestContext) internal async Task HandleDisposeUserViewRequest(DisposeUserViewRequestParams parameters, RequestContext<ResultStatus> requestContext)
{ {
this.ConnectionServiceInstance.Disconnect(new DisconnectParams(){ this.ConnectionServiceInstance.Disconnect(new DisconnectParams()
{
OwnerUri = parameters.ContextId, OwnerUri = parameters.ContextId,
Type = null Type = null
}); });
@@ -335,8 +303,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
} }
internal CDataContainer CreateUserDataContainer( internal CDataContainer CreateUserDataContainer(
ConnectionInfo connInfo, ConnectionInfo connInfo,
UserInfo? user, UserInfo? user,
ConfigAction configAction, ConfigAction configAction,
string databaseName) string databaseName)
{ {
@@ -344,7 +312,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
var connectionInfoWithConnection = new SqlConnectionInfoWithConnection(); var connectionInfoWithConnection = new SqlConnectionInfoWithConnection();
connectionInfoWithConnection.ServerConnection = serverConnection; connectionInfoWithConnection.ServerConnection = serverConnection;
string urn = (configAction == ConfigAction.Update && user != null) string urn = (configAction == ConfigAction.Update && user != null)
? string.Format(System.Globalization.CultureInfo.InvariantCulture, ? string.Format(System.Globalization.CultureInfo.InvariantCulture,
"Server/Database[@Name='{0}']/User[@Name='{1}']", "Server/Database[@Name='{0}']/User[@Name='{1}']",
Urn.EscapeString(databaseName), Urn.EscapeString(databaseName),
@@ -361,7 +329,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
containerXml.AddProperty("itemtype", "User"); containerXml.AddProperty("itemtype", "User");
} }
XmlDocument xmlDoc = containerXml.GenerateXmlDocument(); XmlDocument xmlDoc = containerXml.GenerateXmlDocument();
return CDataContainer.CreateDataContainer(connectionInfoWithConnection, xmlDoc); return CDataContainer.CreateDataContainer(connectionInfoWithConnection, xmlDoc);
} }
@@ -393,30 +361,18 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
return new Tuple<bool, string>(true, string.Empty); return new Tuple<bool, string>(true, string.Empty);
} }
private void CheckForSchemaOwnerships(Database parentDb, User existingUser)
{
foreach (Schema sch in parentDb.Schemas)
{
var comparer = parentDb.GetStringComparer();
if (comparer.Compare(sch.Owner, existingUser.Name) == 0)
{
throw new ApplicationException("Cannot drop user since it owns a schema");
}
}
}
} }
internal class UserActions : ManagementActionBase internal class UserActions : ManagementActionBase
{ {
#region Variables #region Variables
//private UserPrototypeData userData; //private UserPrototypeData userData;
private UserPrototype userPrototype; private UserPrototype userPrototype;
private UserInfo? user; private UserInfo? user;
private ConfigAction configAction; private ConfigAction configAction;
#endregion #endregion
#region Constructors / Dispose #region Constructors / Dispose
/// <summary> /// <summary>
/// required when loading from Object Explorer context /// required when loading from Object Explorer context
/// </summary> /// </summary>
@@ -442,7 +398,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
// base.Dispose(disposing); // base.Dispose(disposing);
// } // }
#endregion #endregion
/// <summary> /// <summary>
/// called on background thread by the framework to execute the action /// called on background thread by the framework to execute the action
@@ -462,7 +418,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
this.userPrototype.ApplyChanges(); this.userPrototype.ApplyChanges();
} }
} }
private UserPrototype InitUserPrototype(CDataContainer dataContainer, UserInfo user, UserPrototypeData? originalData) private UserPrototype InitUserPrototype(CDataContainer dataContainer, UserInfo user, UserPrototypeData? originalData)
{ {
ExhaustiveUserTypes currentUserType; ExhaustiveUserTypes currentUserType;
@@ -485,8 +441,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
dataContainer.Server.GetSmoObject(dataContainer.ObjectUrn) as User); dataContainer.Server.GetSmoObject(dataContainer.ObjectUrn) as User);
} }
UserPrototype currentUserPrototype = userPrototypeFactory.GetUserPrototype(currentUserType); UserPrototype currentUserPrototype = userPrototypeFactory.GetUserPrototype(currentUserType);
return currentUserPrototype; return currentUserPrototype;
} }
private ExhaustiveUserTypes GetCurrentUserTypeForExistingUser(User? user) private ExhaustiveUserTypes GetCurrentUserTypeForExistingUser(User? user)
@@ -503,25 +459,20 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
{ {
if (user.AuthenticationType == AuthenticationType.Windows) if (user.AuthenticationType == AuthenticationType.Windows)
{ {
return ExhaustiveUserTypes.WindowsUser; return ExhaustiveUserTypes.WindowsUser;
} }
else if (user.AuthenticationType == AuthenticationType.Database) else if (user.AuthenticationType == AuthenticationType.Database)
{ {
return ExhaustiveUserTypes.SqlUserWithPassword; return ExhaustiveUserTypes.SqlUserWithPassword;
} }
} }
return ExhaustiveUserTypes.LoginMappedUser; return ExhaustiveUserTypes.LoginMappedUser;
case UserType.NoLogin: case UserType.NoLogin:
return ExhaustiveUserTypes.SqlUserWithoutLogin; return ExhaustiveUserTypes.SqlUserWithoutLogin;
case UserType.Certificate: case UserType.Certificate:
return ExhaustiveUserTypes.CertificateMappedUser; return ExhaustiveUserTypes.CertificateMappedUser;
case UserType.AsymmetricKey: case UserType.AsymmetricKey:
return ExhaustiveUserTypes.AsymmetricKeyMappedUser; return ExhaustiveUserTypes.AsymmetricKeyMappedUser;
default: default:
return ExhaustiveUserTypes.Unknown; return ExhaustiveUserTypes.Unknown;
} }

View File

@@ -30,13 +30,13 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Security
var connectionResult = await LiveConnectionHelper.InitLiveConnectionInfoAsync("master", queryTempFile.FilePath); var connectionResult = await LiveConnectionHelper.InitLiveConnectionInfoAsync("master", queryTempFile.FilePath);
var service = new SecurityService(); var service = new SecurityService();
var credential = SecurityTestUtils.GetTestCredentialInfo(); var credential = SecurityTestUtils.GetTestCredentialInfo();
await SecurityTestUtils.DeleteCredential(service, connectionResult, credential); await SecurityTestUtils.DropObject(connectionResult.ConnectionInfo.OwnerUri, SecurityTestUtils.GetCredentialURN(credential.Name));
// test // test
await SecurityTestUtils.CreateCredential(service, connectionResult, credential); await SecurityTestUtils.CreateCredential(service, connectionResult, credential);
// cleanup // cleanup
await SecurityTestUtils.DeleteCredential(service, connectionResult, credential); await SecurityTestUtils.DropObject(connectionResult.ConnectionInfo.OwnerUri, SecurityTestUtils.GetCredentialURN(credential.Name));
} }
} }
@@ -52,14 +52,14 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Security
var connectionResult = await LiveConnectionHelper.InitLiveConnectionInfoAsync("master", queryTempFile.FilePath); var connectionResult = await LiveConnectionHelper.InitLiveConnectionInfoAsync("master", queryTempFile.FilePath);
var service = new SecurityService(); var service = new SecurityService();
var credential = SecurityTestUtils.GetTestCredentialInfo(); var credential = SecurityTestUtils.GetTestCredentialInfo();
await SecurityTestUtils.DeleteCredential(service, connectionResult, credential); await SecurityTestUtils.DropObject(connectionResult.ConnectionInfo.OwnerUri, SecurityTestUtils.GetCredentialURN(credential.Name));
await SecurityTestUtils.CreateCredential(service, connectionResult, credential); await SecurityTestUtils.CreateCredential(service, connectionResult, credential);
// test // test
await SecurityTestUtils.UpdateCredential(service, connectionResult, credential); await SecurityTestUtils.UpdateCredential(service, connectionResult, credential);
// cleanup // cleanup
await SecurityTestUtils.DeleteCredential(service, connectionResult, credential); await SecurityTestUtils.DropObject(connectionResult.ConnectionInfo.OwnerUri, SecurityTestUtils.GetCredentialURN(credential.Name));
} }
} }
@@ -75,11 +75,11 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Security
var connectionResult = await LiveConnectionHelper.InitLiveConnectionInfoAsync("master", queryTempFile.FilePath); var connectionResult = await LiveConnectionHelper.InitLiveConnectionInfoAsync("master", queryTempFile.FilePath);
var service = new SecurityService(); var service = new SecurityService();
var credential = SecurityTestUtils.GetTestCredentialInfo(); var credential = SecurityTestUtils.GetTestCredentialInfo();
await SecurityTestUtils.DeleteCredential(service, connectionResult, credential); await SecurityTestUtils.DropObject(connectionResult.ConnectionInfo.OwnerUri, SecurityTestUtils.GetCredentialURN(credential.Name));
await SecurityTestUtils.CreateCredential(service, connectionResult, credential); await SecurityTestUtils.CreateCredential(service, connectionResult, credential);
// test // test
await SecurityTestUtils.DeleteCredential(service, connectionResult, credential); await SecurityTestUtils.DropObject(connectionResult.ConnectionInfo.OwnerUri, SecurityTestUtils.GetCredentialURN(credential.Name));
} }
} }
} }

View File

@@ -58,19 +58,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Security
await service.HandleInitializeLoginViewRequest(initializeLoginViewRequestParams, initializeLoginViewContext.Object); await service.HandleInitializeLoginViewRequest(initializeLoginViewRequestParams, initializeLoginViewContext.Object);
await service.HandleCreateLoginRequest(loginParams, createLoginContext.Object); await service.HandleCreateLoginRequest(loginParams, createLoginContext.Object);
// cleanup created login await SecurityTestUtils.DropObject(connectionResult.ConnectionInfo.OwnerUri, SecurityTestUtils.GetLoginURN(loginParams.Login.Name));
var deleteParams = new DeleteLoginParams
{
ConnectionUri = connectionResult.ConnectionInfo.OwnerUri,
Name = loginParams.Login.Name
};
var deleteContext = new Mock<RequestContext<object>>();
deleteContext.Setup(x => x.SendResult(It.IsAny<object>()))
.Returns(Task.FromResult(new object()));
// call the create login method
await service.HandleDeleteLoginRequest(deleteParams, deleteContext.Object);
} }
} }
} }

View File

@@ -8,6 +8,8 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.SqlTools.Hosting.Protocol; using Microsoft.SqlTools.Hosting.Protocol;
using Microsoft.SqlTools.ServiceLayer.ObjectManagement;
using Microsoft.SqlTools.ServiceLayer.ObjectManagement.Contracts;
using Microsoft.SqlTools.ServiceLayer.Security; using Microsoft.SqlTools.ServiceLayer.Security;
using Microsoft.SqlTools.ServiceLayer.Security.Contracts; using Microsoft.SqlTools.ServiceLayer.Security.Contracts;
using Microsoft.SqlTools.ServiceLayer.Utility; using Microsoft.SqlTools.ServiceLayer.Utility;
@@ -21,23 +23,38 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Security
public static string TestCredentialName = "Current User"; public static string TestCredentialName = "Current User";
internal static string GetCurrentUserIdentity() internal static string GetCurrentUserIdentity()
{ {
return string.Format(@"{0}\{1}", Environment.UserDomainName, Environment.UserName); return string.Format(@"{0}\{1}", Environment.UserDomainName, Environment.UserName);
} }
internal static string GetLoginURN(string name)
{
return string.Format("Server/Login[@Name='{0}']", name);
}
internal static string GetUserURN(string database, string name)
{
return string.Format("Server/Database[@Name='{0}']/User[@Name='{1}']", database, name);
}
internal static string GetCredentialURN(string name)
{
return string.Format("Server/Credential[@Name = '{0}']", name);
}
internal static LoginInfo GetTestLoginInfo() internal static LoginInfo GetTestLoginInfo()
{ {
return new LoginInfo() return new LoginInfo()
{ {
Name = "TestLoginName_" + new Random().NextInt64(10000000,90000000).ToString(), Name = "TestLoginName_" + new Random().NextInt64(10000000, 90000000).ToString(),
AuthenticationType= LoginAuthenticationType.Sql, AuthenticationType = LoginAuthenticationType.Sql,
WindowsGrantAccess = true, WindowsGrantAccess = true,
MustChangePassword = false, MustChangePassword = false,
IsEnabled = false, IsEnabled = false,
IsLockedOut = false, IsLockedOut = false,
EnforcePasswordPolicy = false, EnforcePasswordPolicy = false,
EnforcePasswordExpiration = false, EnforcePasswordExpiration = false,
Password = "placeholder", Password = "placeholder",
OldPassword = "placeholder", OldPassword = "placeholder",
DefaultLanguage = "English - us_english", DefaultLanguage = "English - us_english",
DefaultDatabase = "master" DefaultDatabase = "master"
@@ -49,7 +66,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Security
return new UserInfo() return new UserInfo()
{ {
Type = DatabaseUserType.WithLogin, Type = DatabaseUserType.WithLogin,
Name = "TestUserName_" + new Random().NextInt64(10000000,90000000).ToString(), Name = "TestUserName_" + new Random().NextInt64(10000000, 90000000).ToString(),
LoginName = loginName, LoginName = loginName,
Password = "placeholder", Password = "placeholder",
DefaultSchema = "dbo", DefaultSchema = "dbo",
@@ -67,7 +84,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Security
} }
internal static async Task CreateCredential( internal static async Task CreateCredential(
SecurityService service, SecurityService service,
TestConnectionResult connectionResult, TestConnectionResult connectionResult,
CredentialInfo credential) CredentialInfo credential)
{ {
@@ -81,7 +98,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Security
} }
internal static async Task UpdateCredential( internal static async Task UpdateCredential(
SecurityService service, SecurityService service,
TestConnectionResult connectionResult, TestConnectionResult connectionResult,
CredentialInfo credential) CredentialInfo credential)
{ {
@@ -94,25 +111,11 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Security
context.VerifyAll(); context.VerifyAll();
} }
internal static async Task DeleteCredential(
SecurityService service,
TestConnectionResult connectionResult,
CredentialInfo credential)
{
var context = new Mock<RequestContext<ResultStatus>>();
await service.HandleDeleteCredentialRequest(new DeleteCredentialParams
{
OwnerUri = connectionResult.ConnectionInfo.OwnerUri,
Credential = credential
}, context.Object);
context.VerifyAll();
}
public static async Task<CredentialInfo> SetupCredential(TestConnectionResult connectionResult) public static async Task<CredentialInfo> SetupCredential(TestConnectionResult connectionResult)
{ {
var service = new SecurityService(); var service = new SecurityService();
var credential = SecurityTestUtils.GetTestCredentialInfo(); var credential = SecurityTestUtils.GetTestCredentialInfo();
await SecurityTestUtils.DeleteCredential(service, connectionResult, credential); await SecurityTestUtils.DropObject(connectionResult.ConnectionInfo.OwnerUri, SecurityTestUtils.GetCredentialURN(credential.Name));
await SecurityTestUtils.CreateCredential(service, connectionResult, credential); await SecurityTestUtils.CreateCredential(service, connectionResult, credential);
return credential; return credential;
} }
@@ -122,7 +125,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Security
CredentialInfo credential) CredentialInfo credential)
{ {
var service = new SecurityService(); var service = new SecurityService();
await SecurityTestUtils.DeleteCredential(service, connectionResult, credential); await SecurityTestUtils.DropObject(connectionResult.ConnectionInfo.OwnerUri, SecurityTestUtils.GetCredentialURN(credential.Name));
} }
internal static async Task<LoginInfo> CreateLogin(SecurityService service, TestConnectionResult connectionResult) internal static async Task<LoginInfo> CreateLogin(SecurityService service, TestConnectionResult connectionResult)
@@ -155,26 +158,9 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Security
return loginParams.Login; return loginParams.Login;
} }
internal static async Task DeleteLogin(SecurityService service, TestConnectionResult connectionResult, LoginInfo login)
{
// cleanup created login
var deleteParams = new DeleteLoginParams
{
ConnectionUri = connectionResult.ConnectionInfo.OwnerUri,
Name = login.Name
};
var deleteContext = new Mock<RequestContext<object>>();
deleteContext.Setup(x => x.SendResult(It.IsAny<object>()))
.Returns(Task.FromResult(new object()));
// call the create login method
await service.HandleDeleteLoginRequest(deleteParams, deleteContext.Object);
}
internal static async Task<UserInfo> CreateUser( internal static async Task<UserInfo> CreateUser(
UserServiceHandlerImpl service, UserServiceHandlerImpl service,
TestConnectionResult connectionResult, TestConnectionResult connectionResult,
LoginInfo login) LoginInfo login)
{ {
string contextId = System.Guid.NewGuid().ToString(); string contextId = System.Guid.NewGuid().ToString();
@@ -220,12 +206,12 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Security
await service.HandleDisposeUserViewRequest(disposeViewRequestParams, disposeUserViewContext.Object); await service.HandleDisposeUserViewRequest(disposeViewRequestParams, disposeUserViewContext.Object);
return userParams.User; return userParams.User;
} }
internal static async Task<UserInfo> UpdateUser( internal static async Task<UserInfo> UpdateUser(
UserServiceHandlerImpl service, UserServiceHandlerImpl service,
TestConnectionResult connectionResult, TestConnectionResult connectionResult,
UserInfo user) UserInfo user)
{ {
string contextId = System.Guid.NewGuid().ToString(); string contextId = System.Guid.NewGuid().ToString();
@@ -257,7 +243,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Security
// verify the result // verify the result
updateUserContext.Verify(x => x.SendResult(It.Is<ResultStatus>(p => p.Success))); updateUserContext.Verify(x => x.SendResult(It.Is<ResultStatus>(p => p.Success)));
var disposeViewRequestParams = new DisposeUserViewRequestParams var disposeViewRequestParams = new DisposeUserViewRequestParams
{ {
ContextId = contextId ContextId = contextId
}; };
@@ -271,24 +257,20 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Security
return updateParams.User; return updateParams.User;
} }
internal static async Task DeleteUser(UserServiceHandlerImpl service, TestConnectionResult connectionResult, UserInfo user) internal static async Task DropObject(string connectionUri, string objectUrn)
{ {
// cleanup created user ObjectManagementService objectManagementService = new ObjectManagementService();
var deleteParams = new DeleteUserParams var dropParams = new DropRequestParams
{ {
ConnectionUri = connectionResult.ConnectionInfo.OwnerUri, ConnectionUri = connectionUri,
Name = user.Name, ObjectUrn = objectUrn
Database = connectionResult.ConnectionInfo.ConnectionDetails.DatabaseName
}; };
var deleteContext = new Mock<RequestContext<ResultStatus>>(); var dropRequestContext = new Mock<RequestContext<bool>>();
deleteContext.Setup(x => x.SendResult(It.IsAny<ResultStatus>())) dropRequestContext.Setup(x => x.SendResult(It.IsAny<bool>()))
.Returns(Task.FromResult(new object())); .Returns(Task.FromResult(true));
// call the create user method await objectManagementService.HandleDropRequest(dropParams, dropRequestContext.Object);
await service.HandleDeleteUserRequest(deleteParams, deleteContext.Object); }
deleteContext.Verify(x => x.SendResult(It.Is<ResultStatus>(p => p.Success)));
}
} }
} }

View File

@@ -28,14 +28,14 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Security
SecurityService service = new SecurityService(); SecurityService service = new SecurityService();
UserServiceHandlerImpl userService = new UserServiceHandlerImpl(); UserServiceHandlerImpl userService = new UserServiceHandlerImpl();
var connectionResult = await LiveConnectionHelper.InitLiveConnectionInfoAsync("master", queryTempFile.FilePath); var connectionResult = await LiveConnectionHelper.InitLiveConnectionInfoAsync("master", queryTempFile.FilePath);
var login = await SecurityTestUtils.CreateLogin(service, connectionResult); var login = await SecurityTestUtils.CreateLogin(service, connectionResult);
var user = await SecurityTestUtils.CreateUser(userService, connectionResult, login); var user = await SecurityTestUtils.CreateUser(userService, connectionResult, login);
await SecurityTestUtils.DeleteUser(userService, connectionResult, user); await SecurityTestUtils.DropObject(connectionResult.ConnectionInfo.OwnerUri, SecurityTestUtils.GetUserURN(connectionResult.ConnectionInfo.ConnectionDetails.DatabaseName, user.Name));
await SecurityTestUtils.DeleteLogin(service, connectionResult, login); await SecurityTestUtils.DropObject(connectionResult.ConnectionInfo.OwnerUri, SecurityTestUtils.GetLoginURN(login.Name));
} }
} }
@@ -58,9 +58,9 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Security
await SecurityTestUtils.UpdateUser(userService, connectionResult, user); await SecurityTestUtils.UpdateUser(userService, connectionResult, user);
await SecurityTestUtils.DeleteUser(userService, connectionResult, user); await SecurityTestUtils.DropObject(connectionResult.ConnectionInfo.OwnerUri, SecurityTestUtils.GetUserURN(connectionResult.ConnectionInfo.ConnectionDetails.DatabaseName, user.Name));
await SecurityTestUtils.DeleteLogin(service, connectionResult, login); await SecurityTestUtils.DropObject(connectionResult.ConnectionInfo.OwnerUri, SecurityTestUtils.GetLoginURN(login.Name));
} }
} }
} }