18 using System.Collections.Generic;
26 namespace Deveel.Data.Security {
42 GC.SuppressFinalize(
this);
45 protected virtual void Dispose(
bool disposing) {
46 userGroupsCache = null;
52 var c1 = table.GetResolvedColumnName(0);
56 return t.RowCount > 0;
61 throw new ArgumentNullException(
"userInfo");
62 if (String.IsNullOrEmpty(identifier))
63 throw new ArgumentNullException(
"identifier");
67 var userName = userInfo.
Name;
69 if (UserExists(userName))
70 throw new SecurityException(String.Format(
"User '{0}' is already registered.", userName));
74 var row = table.NewRow();
81 if (method !=
"plain")
82 throw new NotImplementedException(
"Only mechanism implemented right now is plain text (it sucks!)");
86 row.SetValue(0, userName);
87 row.SetValue(1, method);
88 row.SetValue(2, methodArgs);
89 row.SetValue(3, identifier);
94 using (var stream =
new MemoryStream()) {
95 using (var writer =
new BinaryWriter(stream)) {
96 writer.Write(args.Count);
98 foreach (var arg
in args) {
99 writer.Write(arg.Key);
101 if (arg.Value is
bool) {
102 writer.Write((byte)1);
103 writer.Write((
bool) arg.Value);
104 }
else if (arg.Value is
short ||
107 var value = (long) arg.Value;
108 writer.Write((byte)2);
110 }
else if (arg.Value is
string) {
111 writer.Write((byte)3);
112 writer.Write((
string) arg.Value);
117 return stream.ToArray();
123 using (var stream =
new MemoryStream(bytes)) {
124 using (var reader =
new BinaryReader(stream)) {
125 var argCount = reader.ReadInt32();
127 var args =
new Dictionary<string, object>(argCount);
128 for (
int i = 0; i < argCount; i++) {
129 var argName = reader.ReadString();
130 var argType = reader.ReadByte();
133 value = reader.ReadBoolean();
134 }
else if (argType == 2) {
135 value = reader.ReadInt64();
136 }
else if (argType == 3) {
137 value = reader.ReadString();
140 args[argName] = value;
150 var c1 = table.GetResolvedColumnName(0);
154 var groups =
new string[sz];
155 var rowEnum = t.GetEnumerator();
157 while (rowEnum.MoveNext()) {
158 groups[i] = t.GetValue(rowEnum.Current.RowId.RowNumber, 1).Value.ToString();
166 if (userGroupsCache == null) {
171 return userGroupsCache.TryGetValue(userName, out groups);
175 if (userGroupsCache == null)
178 userGroupsCache.Remove(userName);
182 if (userGroupsCache == null)
185 userGroupsCache.Clear();
189 if (userGroupsCache == null)
190 userGroupsCache =
new Dictionary<string, string[]>();
192 userGroupsCache[userName] = groups;
199 RemoveUserFromAllGroups(userName);
209 var c1 = table.GetResolvedColumnName(0);
214 c1 = table.GetResolvedColumnName(0);
216 return table.Delete(t) > 0;
223 var c1 = table.GetResolvedColumnName(0);
226 if (t.RowCount > 0) {
229 ClearUserGroupsCache(username);
234 var userName = userInfo.
Name;
240 var c1 = table.GetResolvedColumnName(0);
243 throw new SecurityException(String.Format(
"User '{0}' was not found.", userName));
252 if (method !=
"plain")
253 throw new NotImplementedException(
"Only mechanism implemented right now is plain text (it sucks!)");
257 var row = table.NewRow();
258 row.SetValue(0, userName);
259 row.SetValue(1, method);
260 row.SetValue(2, methodArgs);
261 row.SetValue(3, identifier);
269 var c1 = table.GetResolvedColumnName(0);
270 var c2 = table.GetResolvedColumnName(1);
276 bool userBelongsToLockGroup = t.RowCount > 0;
278 !userBelongsToLockGroup) {
281 var rdat =
new Row(table);
282 rdat.SetValue(0, userName);
286 userBelongsToLockGroup) {
302 var unameColumn = table.GetResolvedColumnName(0);
303 var methodColumn = table.GetResolvedColumnName(1);
304 var methodArgsColumn = table.GetResolvedColumnName(2);
308 throw new SecurityException(String.Format(
"User '{0}' is not registered.", userName));
310 var method = t.GetValue(0, methodColumn);
311 var methodArgs = t.GetValue(0, methodArgsColumn);
312 var argBytes = ((
SqlBinary) methodArgs.Value).ToByteArray();
313 var args = DeserializeArguments(argBytes);
316 foreach (var arg
in args) {
317 identification.Arguments[arg.Key] = arg.Value;
320 return new UserInfo(userName, identification);
325 var unameColumn = table.GetResolvedColumnName(0);
326 var idColumn = table.GetResolvedColumnName(3);
330 throw new SecurityException(String.Format(
"User '{0}' is not registered.", userName));
332 var stored = t.GetValue(0, idColumn);
333 return stored.Value.ToString().Equals(identifier);
338 if (String.IsNullOrEmpty(groupName))
339 throw new ArgumentNullException(
"groupName");
341 var c = groupName[0];
342 if (c ==
'$' || c ==
'%' || c ==
'@')
343 throw new ArgumentException(String.Format(
"Group name '{0}' starts with an invalid character.", groupName));
347 var row = table.NewRow();
348 row.SetValue(0, groupName);
355 var c1 = table.GetResolvedColumnName(0);
360 if (t.RowCount > 0) {
362 ClearUserGroupsCache();
371 var c1 = table.GetResolvedColumnName(0);
375 return t.RowCount > 0;
379 if (String.IsNullOrEmpty(groupName))
380 throw new ArgumentNullException(
"group");
381 if (String.IsNullOrEmpty(userName))
382 throw new ArgumentNullException(
"username");
384 char c = groupName[0];
385 if (c ==
'@' || c ==
'&' || c ==
'#' || c ==
'$')
386 throw new ArgumentException(String.Format(
"Group name '{0}' is invalid: cannot start with {1}", groupName, c),
"groupName");
388 if (!IsUserInGroup(userName, groupName)) {
390 var row = table.NewRow();
391 row.SetValue(0, userName);
392 row.SetValue(1, groupName);
393 row.SetValue(2, asAdmin);
402 var c1 = table.GetResolvedColumnName(0);
403 var c2 = table.GetResolvedColumnName(1);
413 return t.GetValue(0, 2).AsBoolean();
420 var c1 = table.GetResolvedColumnName(0);
421 var c2 = table.GetResolvedColumnName(1);
429 if (t.RowCount > 0) {
432 ClearUserGroupsCache(userName);
442 if (TryGetUserGroupsFromCache(userName, out userGroups) &&
443 userGroups.Any(x => String.Equals(groupName, x, StringComparison.OrdinalIgnoreCase)))
449 var c1 = table.GetResolvedColumnName(0);
450 var c2 = table.GetResolvedColumnName(1);
457 return t.RowCount > 0;
462 if (!TryGetUserGroupsFromCache(userName, out groups)) {
463 groups = QueryUserGroups(userName);
464 SetUserGroupsInCache(userName, groups);
bool UserExists(string userName)
virtual void Dispose(bool disposing)
const string LockGroup
The name of the lock group.
bool UserGroupExists(string groupName)
UserStatus GetUserStatus(string userName)
UserInfo GetUser(string userName)
UserManager(IQuery queryContext)
Implements a BINARY object that handles a limited number of bytes, not exceding MaxLength.
void CreateUser(UserInfo userInfo, string identifier)
static readonly ObjectName UserTableName
Gets the fully qualified name of the user table.
void ClearUserGroupsCache(string userName)
bool IsUserGroupAdmin(string userName, string groupName)
bool CheckIdentifier(string userName, string identifier)
A single row in a table of a database.
static DataObject String(string s)
static byte[] SerializeArguments(IDictionary< string, object > args)
void ClearUserGroupsCache()
void AddUserToGroup(string userName, string groupName, bool asAdmin)
SqlExpressionType
All the possible type of SqlExpression supported
void AlterUser(UserInfo userInfo, string identifier)
static readonly ObjectName UserGroupTableName
string[] QueryUserGroups(string userName)
Represents a dynamic object that encapsulates a defined SqlType and a compatible constant ISqlObject ...
static readonly ObjectName GroupsTableName
bool RemoveUserFromGroup(string userName, string groupName)
Dictionary< string, string[]> userGroupsCache
Provides utilities and properties for handling the SYSTEN schema of a database.
UserIdentification Identification
void SetUserGroupsInCache(string userName, string[] groups)
static IDictionary< string, object > DeserializeArguments(byte[] bytes)
void CreateUserGroup(string groupName)
bool IsUserInGroup(string userName, string groupName)
Defines the base class for instances that represent SQL expression tree nodes.
static SqlConstantExpression Constant(object value)
IDictionary< string, object > Arguments
bool DropUserGroup(string groupName)
string[] GetUserGroups(string userName)
void RemoveUserFromAllGroups(string username)
bool DropUser(string userName)
bool TryGetUserGroupsFromCache(string userName, out string[] groups)
static readonly ObjectName PasswordTableName
void SetUserStatus(string userName, UserStatus status)