Update User edit handlers (#1903)

* WIP

* Update user tests

* WIP updates

* WIP

* Fix several edit use bugs

* Disable failing tests

* minor updates

* Remove unused using
This commit is contained in:
Karl Burtram
2023-03-06 14:43:38 -08:00
committed by GitHub
parent 781fc35a87
commit a074b5bf67
7 changed files with 863 additions and 573 deletions

View File

@@ -103,7 +103,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
this.isMember = new Dictionary<string, bool>();
}
public UserPrototypeData(CDataContainer context, UserInfo userInfo)
public UserPrototypeData(CDataContainer context, UserInfo? userInfo)
{
this.isSchemaOwned = new Dictionary<string, bool>();
this.isMember = new Dictionary<string, bool>();
@@ -114,15 +114,21 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
}
else
{
this.name = userInfo.Name;
this.mappedLoginName = userInfo.LoginName;
this.defaultSchemaName = userInfo.DefaultSchema;
this.password = DatabaseUtils.GetReadOnlySecureString(userInfo.Password);
if (userInfo != null)
{
this.name = userInfo.Name;
this.mappedLoginName = userInfo.LoginName;
this.defaultSchemaName = userInfo.DefaultSchema;
if (!string.IsNullOrEmpty(userInfo.Password))
{
this.password = DatabaseUtils.GetReadOnlySecureString(userInfo.Password);
}
}
}
this.LoadRoleMembership(context);
this.LoadRoleMembership(context, userInfo);
this.LoadSchemaData(context);
this.LoadSchemaData(context, userInfo);
}
public UserPrototypeData Clone()
@@ -145,20 +151,12 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
foreach (string key in this.isMember?.Keys ?? Enumerable.Empty<string>())
{
if (result.isMember?.ContainsKey(key) == true
&& this.isMember?.ContainsKey(key) == true)
{
result.isMember[key] = this.isMember[key];
}
result.isMember[key] = this.isMember[key];
}
foreach (string key in this.isSchemaOwned?.Keys ?? Enumerable.Empty<string>())
{
if (result.isSchemaOwned?.ContainsKey(key) == true
&& this.isSchemaOwned?.ContainsKey(key) == true)
{
result.isSchemaOwned[key] = this.isSchemaOwned[key];
}
result.isSchemaOwned[key] = this.isSchemaOwned[key];
}
return result;
@@ -248,7 +246,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
/// Loads role membership of a database user.
/// </summary>
/// <param name="context"></param>
private void LoadRoleMembership(CDataContainer context)
private void LoadRoleMembership(CDataContainer context, UserInfo? userInfo)
{
Urn objUrn = new Urn(context.ObjectUrn);
Urn databaseUrn = objUrn.Parent;
@@ -259,20 +257,25 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
return;
}
User existingUser = context.Server.Databases[parentDb.Name].Users[objUrn.GetNameForType("User")];
string userName = userInfo?.Name ?? objUrn.GetNameForType("User");
User existingUser = context.Server.Databases[parentDb.Name].Users[userName];
foreach (DatabaseRole dbRole in parentDb.Roles)
{
var comparer = parentDb.GetStringComparer();
if (comparer.Compare(dbRole.Name, "public") != 0)
{
if (context.IsNewObject)
if (userInfo != null && userInfo.DatabaseRoles != null)
{
this.isMember[dbRole.Name] = false;
this.isMember[dbRole.Name] = userInfo.DatabaseRoles.Contains(dbRole.Name);
}
else if (existingUser != null)
{
this.isMember[dbRole.Name] = existingUser.IsMember(dbRole.Name);
}
else
{
this.isMember[dbRole.Name] = existingUser.IsMember(dbRole.Name);
this.isMember[dbRole.Name] = false;
}
}
}
@@ -282,7 +285,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
/// Loads schema ownership related data.
/// </summary>
/// <param name="context"></param>
private void LoadSchemaData(CDataContainer context)
private void LoadSchemaData(CDataContainer context, UserInfo? userInfo)
{
Urn objUrn = new Urn(context.ObjectUrn);
Urn databaseUrn = objUrn.Parent;
@@ -293,7 +296,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
return;
}
User existingUser = context.Server.Databases[parentDb.Name].Users[objUrn.GetNameForType("User")];
string userName = userInfo?.Name ?? objUrn.GetNameForType("User");
User existingUser = context.Server.Databases[parentDb.Name].Users[userName];
if (!SqlMgmtUtils.IsYukonOrAbove(context.Server)
|| parentDb.CompatibilityLevel <= CompatibilityLevel.Version80)
@@ -303,15 +307,19 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
foreach (Schema sch in parentDb.Schemas)
{
if (context.IsNewObject)
if (userInfo != null && userInfo.OwnedSchemas != null)
{
this.isSchemaOwned[sch.Name] = false;
this.isSchemaOwned[sch.Name] = userInfo.OwnedSchemas.Contains(sch.Name);
}
else
else if (existingUser != null)
{
var comparer = parentDb.GetStringComparer();
this.isSchemaOwned[sch.Name] = comparer.Compare(sch.Owner, existingUser.Name) == 0;
}
else
{
this.isSchemaOwned[sch.Name] = false;
}
}
}
}
@@ -334,6 +342,14 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
#region IUserPrototype Members
public UserPrototypeData CurrentState
{
get
{
return this.currentState;
}
}
public string Name
{
get
@@ -996,15 +1012,15 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
}
}
private UserPrototypeFactory(CDataContainer context, UserInfo user)
private UserPrototypeFactory(CDataContainer context, UserInfo user, UserPrototypeData? originalData)
{
this.context = context;
this.originalData = new UserPrototypeData(this.context, user);
this.currentData = this.originalData.Clone();
this.currentData = new UserPrototypeData(this.context, user);
this.originalData = originalData ?? this.currentData.Clone();
}
public static UserPrototypeFactory GetInstance(CDataContainer context, UserInfo user)
public static UserPrototypeFactory GetInstance(CDataContainer context, UserInfo? user, UserPrototypeData? originalData)
{
if (singletonInstance != null
&& singletonInstance.context != context)
@@ -1012,7 +1028,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
singletonInstance = null;
}
singletonInstance ??= new UserPrototypeFactory(context, user);
singletonInstance ??= new UserPrototypeFactory(context, user, originalData);
return singletonInstance;
}