Enable support for Windows users (#1957)

* WIP

* Update for Windows user
This commit is contained in:
Karl Burtram
2023-03-21 19:00:11 -07:00
committed by GitHub
parent d46bb2ce53
commit a104251885
4 changed files with 110 additions and 141 deletions

View File

@@ -60,6 +60,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
/// </summary> /// </summary>
internal async Task HandleInitializeUserViewRequest(InitializeUserViewParams parameters, RequestContext<UserViewInfo> requestContext) internal async Task HandleInitializeUserViewRequest(InitializeUserViewParams parameters, RequestContext<UserViewInfo> requestContext)
{ {
// check input parameters
if (string.IsNullOrWhiteSpace(parameters.Database)) if (string.IsNullOrWhiteSpace(parameters.Database))
{ {
throw new ArgumentNullException("parameters.Database"); throw new ArgumentNullException("parameters.Database");
@@ -70,13 +71,13 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
throw new ArgumentNullException("parameters.ContextId"); throw new ArgumentNullException("parameters.ContextId");
} }
// open a connection for running the user dialog and associated task
ConnectionInfo originalConnInfo; ConnectionInfo originalConnInfo;
ConnectionServiceInstance.TryFindConnection(parameters.ConnectionUri, out originalConnInfo); ConnectionServiceInstance.TryFindConnection(parameters.ConnectionUri, out originalConnInfo);
if (originalConnInfo == null) if (originalConnInfo == null)
{ {
throw new ArgumentException("Invalid connection URI '{0}'", parameters.ConnectionUri); throw new ArgumentException("Invalid connection URI '{0}'", parameters.ConnectionUri);
} }
string originalDatabaseName = originalConnInfo.ConnectionDetails.DatabaseName; string originalDatabaseName = originalConnInfo.ConnectionDetails.DatabaseName;
try try
{ {
@@ -93,26 +94,22 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
{ {
originalConnInfo.ConnectionDetails.DatabaseName = originalDatabaseName; originalConnInfo.ConnectionDetails.DatabaseName = originalDatabaseName;
} }
ConnectionInfo connInfo; ConnectionInfo connInfo;
this.ConnectionServiceInstance.TryFindConnection(parameters.ContextId, out connInfo); this.ConnectionServiceInstance.TryFindConnection(parameters.ContextId, out connInfo);
CDataContainer dataContainer = CreateUserDataContainer(connInfo, null, ConfigAction.Create, parameters.Database);
// create a default user data context and database object
CDataContainer dataContainer = CreateUserDataContainer(connInfo, null, ConfigAction.Create, parameters.Database);
string databaseUrn = string.Format(System.Globalization.CultureInfo.InvariantCulture,
"Server/Database[@Name='{0}']", Urn.EscapeString(parameters.Database));
Database? parentDb = dataContainer.Server.GetSmoObject(databaseUrn) as Database;
// if viewing an exisitng user then populate some properties
UserInfo? userInfo = null; UserInfo? userInfo = null;
ExhaustiveUserTypes userType = ExhaustiveUserTypes.LoginMappedUser;
if (!parameters.IsNewObject) if (!parameters.IsNewObject)
{ {
User? existingUser = null; User? existingUser = dataContainer.Server.Databases[parentDb.Name].Users[parameters.Name];
string databaseUrn = string.Format(System.Globalization.CultureInfo.InvariantCulture, userType = UserActions.GetCurrentUserTypeForExistingUser(existingUser);
"Server/Database[@Name='{0}']",
Urn.EscapeString(parameters.Database));
Database? parentDb = dataContainer.Server.GetSmoObject(databaseUrn) as Database;
existingUser = dataContainer.Server.Databases[parentDb.Name].Users[parameters.Name];
if (string.IsNullOrWhiteSpace(existingUser.Login))
{
throw new ApplicationException("Only 'User with Login' user type supported");
}
userInfo = new UserInfo() userInfo = new UserInfo()
{ {
Name = parameters.Name, Name = parameters.Name,
@@ -121,9 +118,10 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
}; };
} }
UserPrototypeFactory userPrototypeFactory = UserPrototypeFactory.GetInstance(dataContainer, userInfo, originalData: null); // generate a user prototype
UserPrototype currentUserPrototype = userPrototypeFactory.GetUserPrototype(ExhaustiveUserTypes.LoginMappedUser); UserPrototype currentUserPrototype = UserPrototypeFactory.GetUserPrototype(dataContainer, userInfo, originalData: null, userType);
// get the default language if available
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)
@@ -140,12 +138,14 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
} }
} }
// get the default schema if available
string? defaultSchema = null; string? defaultSchema = null;
IUserPrototypeWithDefaultSchema defaultSchemaPrototype = currentUserPrototype as IUserPrototypeWithDefaultSchema; IUserPrototypeWithDefaultSchema defaultSchemaPrototype = currentUserPrototype as IUserPrototypeWithDefaultSchema;
if (defaultSchemaPrototype != null && defaultSchemaPrototype.IsDefaultSchemaSupported) if (defaultSchemaPrototype != null && defaultSchemaPrototype.IsDefaultSchemaSupported)
{ {
defaultSchema = defaultSchemaPrototype.DefaultSchema; defaultSchema = defaultSchemaPrototype.DefaultSchema;
} }
// IUserPrototypeWithPassword userWithPwdPrototype = currentUserPrototype as IUserPrototypeWithPassword; // IUserPrototypeWithPassword userWithPwdPrototype = currentUserPrototype as IUserPrototypeWithPassword;
// if (userWithPwdPrototype != null && !this.DataContainer.IsNewObject) // if (userWithPwdPrototype != null && !this.DataContainer.IsNewObject)
// { // {
@@ -153,6 +153,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
// this.confirmPwdTextBox.Text = FAKE_PASSWORD; // this.confirmPwdTextBox.Text = FAKE_PASSWORD;
// } // }
// get the login name if it exists
string? loginName = null; string? loginName = null;
IUserPrototypeWithMappedLogin mappedLoginPrototype = currentUserPrototype as IUserPrototypeWithMappedLogin; IUserPrototypeWithMappedLogin mappedLoginPrototype = currentUserPrototype as IUserPrototypeWithMappedLogin;
if (mappedLoginPrototype != null) if (mappedLoginPrototype != null)
@@ -160,6 +161,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
loginName = mappedLoginPrototype.LoginName; loginName = mappedLoginPrototype.LoginName;
} }
// populate user's role assignments
List<string> databaseRoles = new List<string>(); List<string> databaseRoles = new List<string>();
foreach (string role in currentUserPrototype.DatabaseRoleNames) foreach (string role in currentUserPrototype.DatabaseRoleNames)
{ {
@@ -169,6 +171,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
} }
} }
// populate user's schema ownerships
List<string> schemaNames = new List<string>(); List<string> schemaNames = new List<string>();
foreach (string schema in currentUserPrototype.SchemaNames) foreach (string schema in currentUserPrototype.SchemaNames)
{ {
@@ -178,12 +181,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
} }
} }
// default to dbo schema, if there isn't already a default
if (string.IsNullOrWhiteSpace(defaultSchema) && currentUserPrototype.SchemaNames.Contains("dbo"))
{
defaultSchema = "dbo";
}
ServerConnection serverConnection = dataContainer.ServerConnection; ServerConnection serverConnection = dataContainer.ServerConnection;
UserViewInfo userViewInfo = new UserViewInfo() UserViewInfo userViewInfo = new UserViewInfo()
{ {
@@ -198,7 +195,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
DatabaseRoles = databaseRoles.ToArray(), DatabaseRoles = databaseRoles.ToArray(),
DefaultLanguage = defaultLanguageAlias DefaultLanguage = defaultLanguageAlias
}, },
SupportContainedUser = false, // support for these will be added later SupportContainedUser = UserActions.IsParentDatabaseContained(parentDb), // support for these will be added later
SupportWindowsAuthentication = false, SupportWindowsAuthentication = false,
SupportAADAuthentication = false, SupportAADAuthentication = false,
SupportSQLAuthentication = true, SupportSQLAuthentication = true,
@@ -349,7 +346,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
} }
CDataContainer dataContainer = CreateUserDataContainer(connInfo, user, configAction, databaseName); CDataContainer dataContainer = CreateUserDataContainer(connInfo, user, configAction, databaseName);
using (var actions = new UserActions(dataContainer, user, configAction, originalData)) using (var actions = new UserActions(dataContainer, configAction, user, originalData))
{ {
var executionHandler = new ExecutonHandler(actions); var executionHandler = new ExecutonHandler(actions);
executionHandler.RunNow(runType, this); executionHandler.RunNow(runType, this);
@@ -379,8 +376,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
/// <param name="context"></param> /// <param name="context"></param>
public UserActions( public UserActions(
CDataContainer context, CDataContainer context,
UserInfo? user,
ConfigAction configAction, ConfigAction configAction,
UserInfo? user,
UserPrototypeData? originalData) UserPrototypeData? originalData)
{ {
this.DataContainer = context; this.DataContainer = context;
@@ -401,19 +398,12 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
#endregion #endregion
/// <summary> /// <summary>
/// called on background thread by the framework to execute the action /// called by the management actions framework to execute the action
/// </summary> /// </summary>
/// <param name="node"></param> /// <param name="node"></param>
public override void OnRunNow(object sender) public override void OnRunNow(object sender)
{ {
if (this.configAction == ConfigAction.Drop) if (this.configAction != ConfigAction.Drop)
{
// if (this.credentialData.Credential != null)
// {
// this.credentialData.Credential.DropIfExists();
// }
}
else
{ {
this.userPrototype.ApplyChanges(); this.userPrototype.ApplyChanges();
} }
@@ -422,30 +412,42 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
private UserPrototype InitUserPrototype(CDataContainer dataContainer, UserInfo user, UserPrototypeData? originalData) private UserPrototype InitUserPrototype(CDataContainer dataContainer, UserInfo user, UserPrototypeData? originalData)
{ {
ExhaustiveUserTypes currentUserType; ExhaustiveUserTypes currentUserType;
UserPrototypeFactory userPrototypeFactory = UserPrototypeFactory.GetInstance(dataContainer, user, originalData);
if (dataContainer.IsNewObject) if (dataContainer.IsNewObject)
{ {
if (dataContainer.Server != null && IsParentDatabaseContained(dataContainer.ParentUrn, dataContainer.Server)) currentUserType = GetUserTypeForUserInfo(user);
{
currentUserType = ExhaustiveUserTypes.SqlUserWithPassword;
} }
else else
{ {
currentUserType = ExhaustiveUserTypes.LoginMappedUser; currentUserType = UserActions.GetCurrentUserTypeForExistingUser(
}
}
else
{
currentUserType = this.GetCurrentUserTypeForExistingUser(
dataContainer.Server.GetSmoObject(dataContainer.ObjectUrn) as User); dataContainer.Server.GetSmoObject(dataContainer.ObjectUrn) as User);
} }
UserPrototype currentUserPrototype = userPrototypeFactory.GetUserPrototype(currentUserType); UserPrototype currentUserPrototype = UserPrototypeFactory.GetUserPrototype(dataContainer, user, originalData, currentUserType);
return currentUserPrototype; return currentUserPrototype;
} }
private ExhaustiveUserTypes GetCurrentUserTypeForExistingUser(User? user) private ExhaustiveUserTypes GetUserTypeForUserInfo(UserInfo user)
{
ExhaustiveUserTypes userType = ExhaustiveUserTypes.LoginMappedUser;
switch (user.Type)
{
case DatabaseUserType.WithLogin:
userType = ExhaustiveUserTypes.LoginMappedUser;
break;
case DatabaseUserType.WithWindowsGroupLogin:
userType = ExhaustiveUserTypes.WindowsUser;
break;
case DatabaseUserType.Contained:
userType = ExhaustiveUserTypes.SqlUserWithPassword;
break;
case DatabaseUserType.NoConnectAccess:
userType = ExhaustiveUserTypes.SqlUserWithoutLogin;
break;
}
return userType;
}
internal static ExhaustiveUserTypes GetCurrentUserTypeForExistingUser(User? user)
{ {
if (user == null) if (user == null)
{ {
@@ -478,18 +480,16 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
} }
} }
private static bool IsParentDatabaseContained(Urn parentDbUrn, Server server) internal static bool IsParentDatabaseContained(Urn parentDbUrn, Server server)
{ {
string parentDbName = parentDbUrn.GetNameForType("Database"); string parentDbName = parentDbUrn.GetNameForType("Database");
Database parentDatabase = server.Databases[parentDbName]; return IsParentDatabaseContained(server.Databases[parentDbName]);
if (parentDatabase.IsSupportedProperty("ContainmentType")
&& parentDatabase.ContainmentType == ContainmentType.Partial)
{
return true;
} }
return false; internal static bool IsParentDatabaseContained(Database parentDatabase)
{
return parentDatabase.IsSupportedProperty("ContainmentType")
&& parentDatabase.ContainmentType == ContainmentType.Partial;
} }
} }
} }

View File

@@ -763,7 +763,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
{ {
base.SaveProperties(user); base.SaveProperties(user);
if (!this.Exists || (user.Login != this.currentState.mappedLoginName)) bool isValidLoginName = !string.IsNullOrWhiteSpace(this.currentState.mappedLoginName);
bool isCreatingOrUpdatingLogin = !this.Exists || user.Login != this.currentState.mappedLoginName;
if (isValidLoginName && isCreatingOrUpdatingLogin)
{ {
user.Login = this.currentState.mappedLoginName; user.Login = this.currentState.mappedLoginName;
} }
@@ -985,107 +987,47 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
/// <summary> /// <summary>
/// Used to create or return required UserPrototype objects for a user type. /// Used to create or return required UserPrototype objects for a user type.
/// This factory class also helps us in maintaining a single set of current data
/// and original data mapped to all UserPrototypes.
///
/// Also this UserPrototypeFactory is a Singleton object for one datacontainer object.
/// Making it Singleton helps us in using same factory object inside other pages too.
/// </summary> /// </summary>
internal class UserPrototypeFactory internal static class UserPrototypeFactory
{ {
private static UserPrototypeFactory? singletonInstance; public static UserPrototype GetUserPrototype(
CDataContainer context, UserInfo? user,
private UserPrototypeData currentData; UserPrototypeData? originalData, ExhaustiveUserTypes userType)
private UserPrototypeData originalData;
private CDataContainer context;
private UserPrototype? asymmetricKeyMappedUser;
private UserPrototype? certificateMappedUser;
private UserPrototype? loginMappedUser;
private UserPrototype? noLoginUser;
private UserPrototype? sqlUserWithPassword;
private UserPrototype? windowsUser;
private UserPrototype? currentPrototype;
public UserPrototype CurrentPrototype
{
get
{
currentPrototype ??= new UserPrototype(this.context,
this.currentData,
this.originalData);
return currentPrototype;
}
}
private UserPrototypeFactory(CDataContainer context, UserInfo user, UserPrototypeData? originalData)
{
this.context = context;
this.currentData = new UserPrototypeData(this.context, user);
this.originalData = originalData ?? this.currentData.Clone();
}
public static UserPrototypeFactory GetInstance(CDataContainer context, UserInfo? user, UserPrototypeData? originalData)
{
if (singletonInstance != null
&& singletonInstance.context != context)
{
singletonInstance = null;
}
singletonInstance ??= new UserPrototypeFactory(context, user, originalData);
return singletonInstance;
}
public UserPrototype GetUserPrototype(ExhaustiveUserTypes userType)
{ {
UserPrototype currentPrototype = null;
UserPrototypeData currentData = new UserPrototypeData(context, user);
switch (userType) switch (userType)
{ {
case ExhaustiveUserTypes.AsymmetricKeyMappedUser: case ExhaustiveUserTypes.AsymmetricKeyMappedUser:
currentData.userType = UserType.AsymmetricKey; currentPrototype ??= new UserPrototype(context, currentData, originalData);
this.asymmetricKeyMappedUser ??= new UserPrototype(this.context, this.currentData, this.originalData);
this.currentPrototype = asymmetricKeyMappedUser;
break; break;
case ExhaustiveUserTypes.CertificateMappedUser: case ExhaustiveUserTypes.CertificateMappedUser:
currentData.userType = UserType.Certificate; currentPrototype ??= new UserPrototype(context, currentData, originalData);
this.certificateMappedUser ??= new UserPrototype(this.context, this.currentData, this.originalData);
this.currentPrototype = certificateMappedUser;
break; break;
case ExhaustiveUserTypes.LoginMappedUser: case ExhaustiveUserTypes.LoginMappedUser:
currentData.userType = UserType.SqlUser; currentPrototype ??= new UserPrototypeForSqlUserWithLogin(context, currentData, originalData);
this.loginMappedUser ??= new UserPrototypeForSqlUserWithLogin(this.context, this.currentData, this.originalData);
this.currentPrototype = loginMappedUser;
break; break;
case ExhaustiveUserTypes.SqlUserWithoutLogin: case ExhaustiveUserTypes.SqlUserWithoutLogin:
currentData.userType = UserType.NoLogin; currentPrototype ??= new UserPrototypeWithDefaultSchema(context, currentData, originalData);
this.noLoginUser ??= new UserPrototypeWithDefaultSchema(this.context, this.currentData, this.originalData);
this.currentPrototype = noLoginUser;
break; break;
case ExhaustiveUserTypes.SqlUserWithPassword: case ExhaustiveUserTypes.SqlUserWithPassword:
currentData.userType = UserType.SqlUser; currentPrototype ??= new UserPrototypeForSqlUserWithPassword(context, currentData, originalData);
this.sqlUserWithPassword ??= new UserPrototypeForSqlUserWithPassword(this.context, this.currentData, this.originalData);
this.currentPrototype = sqlUserWithPassword;
break; break;
case ExhaustiveUserTypes.WindowsUser: case ExhaustiveUserTypes.WindowsUser:
currentData.userType = UserType.SqlUser; currentPrototype ??= new UserPrototypeForWindowsUser(context, currentData, originalData);
this.windowsUser ??= new UserPrototypeForWindowsUser(this.context, this.currentData, this.originalData);
this.currentPrototype = windowsUser;
break; break;
default: default:
System.Diagnostics.Debug.Assert(false, "Unknown UserType provided."); System.Diagnostics.Debug.Assert(false, "Unknown UserType provided.");
this.currentPrototype = null; currentPrototype = null;
break; break;
} }
return this.currentPrototype; return currentPrototype;
} }
} }

View File

@@ -61,12 +61,12 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Security
}; };
} }
internal static UserInfo GetTestUserInfo(string loginName) internal static UserInfo GetTestUserInfo(DatabaseUserType userType, string userName = null, string loginName = null)
{ {
return new UserInfo() return new UserInfo()
{ {
Type = DatabaseUserType.WithLogin, Type = userType,
Name = "TestUserName_" + new Random().NextInt64(10000000, 90000000).ToString(), Name = userName ?? "TestUserName_" + new Random().NextInt64(10000000, 90000000).ToString(),
LoginName = loginName, LoginName = loginName,
Password = "placeholder", Password = "placeholder",
DefaultSchema = "dbo", DefaultSchema = "dbo",
@@ -161,7 +161,9 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Security
internal static async Task<UserInfo> CreateUser( internal static async Task<UserInfo> CreateUser(
UserServiceHandlerImpl service, UserServiceHandlerImpl service,
TestConnectionResult connectionResult, TestConnectionResult connectionResult,
LoginInfo login) DatabaseUserType userType,
string userName = null,
string loginName = null)
{ {
string contextId = System.Guid.NewGuid().ToString(); string contextId = System.Guid.NewGuid().ToString();
var initializeViewRequestParams = new InitializeUserViewParams var initializeViewRequestParams = new InitializeUserViewParams
@@ -181,7 +183,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Security
var userParams = new CreateUserParams var userParams = new CreateUserParams
{ {
ContextId = contextId, ContextId = contextId,
User = SecurityTestUtils.GetTestUserInfo(login.Name) User = SecurityTestUtils.GetTestUserInfo(userType, userName, loginName)
}; };
var createUserContext = new Mock<RequestContext<CreateUserResult>>(); var createUserContext = new Mock<RequestContext<CreateUserResult>>();

View File

@@ -3,9 +3,11 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
// //
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility; using Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility;
using Microsoft.SqlTools.ServiceLayer.Security; using Microsoft.SqlTools.ServiceLayer.Security;
using Microsoft.SqlTools.ServiceLayer.Security.Contracts;
using Microsoft.SqlTools.ServiceLayer.Test.Common; using Microsoft.SqlTools.ServiceLayer.Test.Common;
using NUnit.Framework; using NUnit.Framework;
@@ -31,7 +33,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Security
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, DatabaseUserType.WithLogin, null, login.Name);
await SecurityTestUtils.DropObject(connectionResult.ConnectionInfo.OwnerUri, SecurityTestUtils.GetUserURN(connectionResult.ConnectionInfo.ConnectionDetails.DatabaseName, user.Name)); await SecurityTestUtils.DropObject(connectionResult.ConnectionInfo.OwnerUri, SecurityTestUtils.GetUserURN(connectionResult.ConnectionInfo.ConnectionDetails.DatabaseName, user.Name));
@@ -39,6 +41,29 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Security
} }
} }
/// <summary>
/// Test the basic Create User method handler
/// </summary>
// [Test] - Windows-only
public async Task TestHandleCreateUserWithWindowsGroup()
{
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
{
// setup
SecurityService service = new SecurityService();
UserServiceHandlerImpl userService = new UserServiceHandlerImpl();
var connectionResult = await LiveConnectionHelper.InitLiveConnectionInfoAsync("master", queryTempFile.FilePath);
var user = await SecurityTestUtils.CreateUser(
userService,
connectionResult,
DatabaseUserType.WithWindowsGroupLogin,
$"{Environment.MachineName}\\Administrator");
await SecurityTestUtils.DropObject(connectionResult.ConnectionInfo.OwnerUri, SecurityTestUtils.GetUserURN(connectionResult.ConnectionInfo.ConnectionDetails.DatabaseName, user.Name));
}
}
/// <summary> /// <summary>
/// Test the basic Update User method handler /// Test the basic Update User method handler
/// </summary> /// </summary>
@@ -54,7 +79,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Security
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, DatabaseUserType.WithLogin, null, login.Name);
await SecurityTestUtils.UpdateUser(userService, connectionResult, user); await SecurityTestUtils.UpdateUser(userService, connectionResult, user);