Esempio n. 1
0
        public Yield GetGroupUsers(DreamContext context, DreamMessage request, Result <DreamMessage> response)
        {
            PermissionsBL.CheckUserAllowed(DekiContext.Current.User, Permissions.READ);
            GroupBE      group       = GetGroupFromUrl();
            DreamMessage responseMsg = null;

            uint totalCount;
            uint queryCount;
            var  usersInGroup = UserBL.GetUsersByQuery(context, group.Id, out totalCount, out queryCount);

            XDoc ret = new XDoc("users");

            ret.Attr("count", usersInGroup.Count());
            ret.Attr("querycount", queryCount);
            ret.Attr("totalcount", totalCount);
            ret.Attr("href", DekiContext.Current.ApiUri.At("groups", group.Id.ToString(), "users"));

            foreach (UserBE member in usersInGroup)
            {
                ret.Add(UserBL.GetUserXml(member, null, Utils.ShowPrivateUserInfo(member)));
            }

            responseMsg = DreamMessage.Ok(ret);

            response.Return(responseMsg);
            yield break;
        }
Esempio n. 2
0
        public static XDoc GetGroupXmlVerbose(GroupBE group, string relation)
        {
            XDoc groupXml = GetGroupXml(group, relation);

            ServiceBE authService = ServiceBL.GetServiceById(group.ServiceId);

            if (authService != null)
            {
                groupXml.Add(ServiceBL.GetServiceXml(authService, "authentication"));
            }

            groupXml.Start("users");
            if (group.UserIdsList != null)
            {
                groupXml.Attr("count", group.UserIdsList.Length);
            }

            groupXml.Attr("href", DekiContext.Current.ApiUri.At("groups", group.Id.ToString(), "users"));
            groupXml.End();

            //Permissions for the group
            RoleBE role = PermissionsBL.GetRoleById(group.RoleId);

            groupXml.Add(PermissionsBL.GetRoleXml(role, "group"));
            return(groupXml);
        }
Esempio n. 3
0
        public static GroupBE SetGroupMembers(GroupBE group, XDoc userList)
        {
            UserBE[] members = ProcessGroupMemberInput(group, userList);
            DbUtils.CurrentSession.GroupMembers_UpdateUsersInGroup(group.Id, members.Select(e => e.ID).ToList(), DateTime.UtcNow);

            // reload the group to ensure group members are set
            return(GetGroupById(group.Id));
        }
Esempio n. 4
0
        public Yield DeleteGroup(DreamContext context, DreamMessage request, Result <DreamMessage> response)
        {
            PermissionsBL.CheckUserAllowed(DekiContext.Current.User, Permissions.ADMIN);
            GroupBE group = GetGroupFromUrl();

            DbUtils.CurrentSession.Groups_Delete(group.Id);
            response.Return(DreamMessage.Ok());
            yield break;
        }
Esempio n. 5
0
        public Yield PostGroupUsers(DreamContext context, DreamMessage request, Result <DreamMessage> response)
        {
            PermissionsBL.CheckUserAllowed(DekiContext.Current.User, Permissions.ADMIN);
            GroupBE group = GetGroupFromUrl();

            group = GroupBL.AddGroupMembers(group, request.ToDocument());
            response.Return(DreamMessage.Ok(GroupBL.GetGroupXmlVerbose(group, null)));
            yield break;
        }
Esempio n. 6
0
        public Yield GetGroup(DreamContext context, DreamMessage request, Result <DreamMessage> response)
        {
            PermissionsBL.CheckUserAllowed(DekiContext.Current.User, Permissions.READ);
            GroupBE      group       = GetGroupFromUrl();
            DreamMessage responseMsg = DreamMessage.Ok(GroupBL.GetGroupXmlVerbose(group, null));

            response.Return(responseMsg);
            yield break;
        }
Esempio n. 7
0
        public static XDoc GetGroupXml(GroupBE group, string relation)
        {
            XDoc groupXml = new XDoc(string.IsNullOrEmpty(relation) ? "group" : "group." + relation);

            groupXml.Attr("id", group.Id);
            groupXml.Attr("href", DekiContext.Current.ApiUri.At("groups", group.Id.ToString()));
            groupXml.Start("groupname").Value(group.Name).End();

            return(groupXml);
        }
Esempio n. 8
0
        public Yield PostGroup(DreamContext context, DreamMessage request, Result <DreamMessage> response)
        {
            PermissionsBL.CheckUserAllowed(DekiContext.Current.User, Permissions.ADMIN);
            DreamMessage responseMsg = null;
            GroupBE      group       = GroupBL.PostGroupFromXml(request.ToDocument(), null, context.GetParam("authusername", null), context.GetParam("authpassword", null));

            responseMsg = DreamMessage.Ok(GroupBL.GetGroupXmlVerbose(group, null));
            response.Return(responseMsg);
            yield break;
        }
Esempio n. 9
0
        public Yield DeleteGroupUser(DreamContext context, DreamMessage request, Result <DreamMessage> response)
        {
            PermissionsBL.CheckUserAllowed(DekiContext.Current.User, Permissions.ADMIN);
            GroupBE group = GetGroupFromUrl();
            UserBE  user  = GetUserFromUrlMustExist();

            group = GroupBL.RemoveGroupMember(group, user);
            response.Return(DreamMessage.Ok(GroupBL.GetGroupXmlVerbose(group, null)));
            yield break;
        }
Esempio n. 10
0
        private IList <GroupBE> Groups_GetInternal(string where, string functionDescription, bool lookupCount, uint?limit, uint?offset, out uint totalCount, out uint queryCount)
        {
            totalCount = queryCount = 0;
            uint           totalCountTemp = 0, queryCountTemp = 0;
            List <GroupBE> groups           = new List <GroupBE>();
            string         totalCountQuery  = lookupCount ? "select count(*) as totalcount from groups" : string.Empty;
            string         queryCountQuery  = lookupCount ? "select count(*) as querycount from groups " + where : string.Empty;
            string         limitOffsetQuery = string.Empty;

            if (limit != null || offset != null)
            {
                limitOffsetQuery = string.Format("limit {0} offset {1}", limit ?? int.MaxValue, offset ?? 0);
            }

            string query = string.Format(@" /* GroupDA::{0} */
SET group_concat_max_len = @@max_allowed_packet;

select groups.*,
	(   select cast(group_concat( user_groups.user_id, '') as char)
		from user_groups
		join users on users.user_id = user_groups.user_id
		where user_groups.group_id = groups.group_id
		group by user_groups.group_id
	) as group_userids
from groups
{1}
{2};
{3};
{4};
", functionDescription, where.TrimEnd(new char[] { ';' }), limitOffsetQuery, totalCountQuery, queryCountQuery);

            Catalog.NewQuery(query)
            .Execute(delegate(IDataReader dr) {
                while (dr.Read())
                {
                    GroupBE group = Groups_Populate(dr);
                    groups.Add(group);
                }

                if (dr.NextResult() && dr.Read())
                {
                    totalCountTemp = DbUtils.Convert.To <uint>(dr["totalcount"], 0);
                }

                if (dr.NextResult() && dr.Read())
                {
                    queryCountTemp = DbUtils.Convert.To <uint>(dr["querycount"], 0);
                }
            });
            totalCount = totalCountTemp;
            queryCount = queryCountTemp;
            return(groups);
        }
Esempio n. 11
0
        public void Groups_Update(GroupBE group)
        {
            Catalog.NewQuery(@" /* Groups_Update */
UPDATE groups set 
group_role_id = ?ROLEID,
group_name = ?NAME
where group_id = ?GROUPID;")
            .With("GROUPID", group.Id)
            .With("ROLEID", group.RoleId)
            .With("NAME", group.Name)
            .Execute();
        }
Esempio n. 12
0
        private GroupBE Groups_Populate(IDataReader dr)
        {
            GroupBE group = new GroupBE();

            group.CreatorUserId = dr.Read <uint>("group_creator_user_id");
            group.Id            = dr.Read <uint>("group_id");
            group.Name          = dr.Read <string>("group_name");
            group.RoleId        = dr.Read <uint>("group_role_id");
            group.ServiceId     = dr.Read <uint>("group_service_id");
            group.TimeStamp     = dr.Read <DateTime>("group_last_edit");
            group.UserIds       = dr.Read <string>("group_userids");
            return(group);
        }
Esempio n. 13
0
        public uint Groups_Insert(GroupBE group)
        {
            uint groupId = Catalog.NewQuery(@" /* Groups_Insert */
insert IGNORE into `groups` (`group_name`, `group_role_id`, `group_service_id`, `group_creator_user_id`, `group_last_edit`) 
values (?NAME, ?ROLEID, ?SERVICEID, ?CREATORUSERID, ?TIMESTAMP);
select LAST_INSERT_ID();")
                           .With("NAME", group.Name)
                           .With("ROLEID", group.RoleId)
                           .With("SERVICEID", group.ServiceId)
                           .With("CREATORUSERID", group.CreatorUserId)
                           .With("TIMESTAMP", group.TimeStamp)
                           .ReadAsUInt() ?? 0;

            return(groupId);
        }
Esempio n. 14
0
        public static GroupBE AddGroupMembers(GroupBE group, XDoc userList)
        {
            UserBE[] newMembers = ProcessGroupMemberInput(group, userList);
            if (ArrayUtil.IsNullOrEmpty(newMembers))
            {
                return(group);
            }

            var members = GetMemberUsers(group).ToList();

            members.AddRange(newMembers);

            DbUtils.CurrentSession.GroupMembers_UpdateUsersInGroup(group.Id, members.Select(e => e.ID).ToList(), DateTime.UtcNow);
            return(GetGroupById(group.Id));
        }
Esempio n. 15
0
        public static GroupBE RemoveGroupMember(GroupBE group, UserBE user)
        {
            List <UserBE> members = new List <UserBE>();

            foreach (UserBE u in GetMemberUsers(group))
            {
                if (u.ID != user.ID)
                {
                    members.Add(u);
                }
            }

            DbUtils.CurrentSession.GroupMembers_UpdateUsersInGroup(group.Id, members.Select(e => e.ID).ToList(), DateTime.UtcNow);
            return(GetGroupById(group.Id));
        }
Esempio n. 16
0
        private static UserBE[] ProcessGroupMemberInput(GroupBE group, XDoc userList)
        {
            if (!userList.HasName("users"))
            {
                throw new GroupExpectedUserRootNodeInvalidArgumentException();
            }

            ServiceBE service = ServiceBL.GetServiceById(group.ServiceId);

            if (service == null)
            {
                throw new GroupServiceNotFoundFatalException(group.ServiceId, group.Name);
            }

            //Changing members of an external group is not supported. You may modify members in the external provider instead.
            if (!ServiceBL.IsLocalAuthService(service))
            {
                throw new ExternalGroupMemberInvalidOperationException();
            }

            UserBE[] members = ReadUserListXml(userList);
            ValidateGroupMemberList(service, members);
            return(members);
        }
Esempio n. 17
0
 private GroupBE Groups_Populate(IDataReader dr) {
     GroupBE group = new GroupBE();
     group.CreatorUserId = dr.Read<uint>("group_creator_user_id");
     group.Id = dr.Read<uint>("group_id");
     group.Name = dr.Read<string>("group_name");
     group.RoleId = dr.Read<uint>("group_role_id");
     group.ServiceId = dr.Read<uint>("group_service_id");
     group.TimeStamp = dr.Read<DateTime>("group_last_edit");
     group.UserIds = dr.Read<string>("group_userids");
     return group;
 }
Esempio n. 18
0
        public void Groups_Update(GroupBE group) {
            Catalog.NewQuery(@" /* Groups_Update */
UPDATE groups set 
group_role_id = ?ROLEID,
group_name = ?NAME
where group_id = ?GROUPID;")
               .With("GROUPID", group.Id)
               .With("ROLEID", group.RoleId)
               .With("NAME", group.Name)
               .Execute();
        }
Esempio n. 19
0
        public uint Groups_Insert(GroupBE group) {
            uint groupId = Catalog.NewQuery(@" /* Groups_Insert */
insert IGNORE into `groups` (`group_name`, `group_role_id`, `group_service_id`, `group_creator_user_id`, `group_last_edit`) 
values (?NAME, ?ROLEID, ?SERVICEID, ?CREATORUSERID, ?TIMESTAMP);
select LAST_INSERT_ID();")
                .With("NAME", group.Name)
                .With("ROLEID", group.RoleId)
                .With("SERVICEID", group.ServiceId)
                .With("CREATORUSERID", group.CreatorUserId)
                .With("TIMESTAMP", group.TimeStamp)
                .ReadAsUInt() ?? 0;
            return groupId;
        }
Esempio n. 20
0
 private static IEnumerable <UserBE> GetMemberUsers(GroupBE group)
 {
     return((group.UserIdsList == null || !group.UserIdsList.Any())
         ? new UserBE[0]
         : DbUtils.CurrentSession.Users_GetByIds(group.UserIdsList));
 }
Esempio n. 21
0
        public static GroupBE PostGroupFromXml(XDoc groupDoc, GroupBE groupToProcess, string externalusername, string externalpassword)
        {
            GroupBE   group        = null;
            string    groupName    = string.Empty;
            ServiceBE groupService = null;
            RoleBE    groupRole    = null;

            UserBE[] groupMembers = null;
            uint?    groupId      = null;

            ParseGroupXml(groupDoc, out groupId, out groupName, out groupService, out groupRole, out groupMembers);

            //Create new group
            if (groupToProcess == null && (groupId == null || groupId == 0))
            {
                if (groupService == null)
                {
                    groupService = ServiceBL.RetrieveLocalAuthService();
                }

                //External groups should be confirmed with the auth provider
                if (groupService != null && !ServiceBL.IsLocalAuthService(groupService))
                {
                    //username+password from request query params are used here
                    group = ExternalServiceSA.BuildGroupFromAuthService(groupService, groupToProcess, groupName, externalusername, externalpassword);

                    if (group == null)
                    {
                        throw new ExternalGroupNotFoundException(groupName);
                    }
                }

                //Does this group already exist?
                GroupBE tempGroup = GetGroupByName(groupName);
                if (tempGroup != null)
                {
                    throw new GroupExistsWithServiceConflictException(groupName, tempGroup.ServiceId);
                }

                ValidateGroupMemberList(groupService, groupMembers);

                // Insert the group
                GroupBE newGroup = new GroupBE();
                newGroup.Name          = groupName;
                newGroup.RoleId        = groupRole.ID;
                newGroup.ServiceId     = groupService.Id;
                newGroup.CreatorUserId = DekiContext.Current.User.ID;
                newGroup.TimeStamp     = DateTime.UtcNow;
                uint newGroupId = DbUtils.CurrentSession.Groups_Insert(newGroup);
                if (newGroupId == 0)
                {
                    group = null;
                }
                else
                {
                    DbUtils.CurrentSession.GroupMembers_UpdateUsersInGroup(newGroupId, groupMembers.Select(e => e.ID).ToList(), newGroup.TimeStamp);

                    // reload the group to ensure group members are set
                    group = GetGroupById(newGroupId);
                }
            }
            //Edit existing group
            else
            {
                if (groupId != null)
                {
                    groupToProcess = GetGroupById(groupId.Value);
                }

                if (groupToProcess == null)
                {
                    throw new GroupIdNotFoundException(groupId);
                }

                group = groupToProcess;

                //Change the role?
                if (group.RoleId != groupRole.ID)
                {
                    group.RoleId = groupRole.ID;
                }

                //Rename the group?
                if (group.Name != groupName && !string.IsNullOrEmpty(groupName))
                {
                    GroupBE tempGroup = GetGroupByName(groupName);

                    if (tempGroup != null)
                    {
                        throw new GroupExistsWithServiceConflictException(groupName, tempGroup.ServiceId);
                    }

                    if (!ServiceBL.IsLocalAuthService(group.ServiceId))
                    {
                        //TODO MaxM: allow renaming of external groups
                        throw new ExternalGroupRenameNotImplementedException();
                    }

                    //Set the new name of the group.
                    group.Name = groupName;
                }

                DbUtils.CurrentSession.Groups_Update(group);
                //TODO (MaxM): Update group list as well?
                group = GetGroupById(group.Id);
            }

            if (group == null)
            {
                throw new GroupCreateUpdateFatalException();
            }

            return(group);
        }
Esempio n. 22
0
        public static UserBE BuildUserFromAuthService(ServiceBE serviceInfo, UserBE knownUser, string usernameToBuild, bool bypassAuthentication, string authusername, string password, out List <GroupBE> externalGroups)
        {
            externalGroups = null;
            if (serviceInfo == null || string.IsNullOrEmpty(usernameToBuild))
            {
                return(null);
            }

            //Dont perform external lookup for disabled users
            if (knownUser != null && !knownUser.UserActive)
            {
                return(knownUser);
            }

            var errMsg = DekiResources.UNABLE_TO_AUTH_WITH_SERVICE(serviceInfo.Type, serviceInfo.SID, serviceInfo.Uri);

            if (knownUser != null && !string.IsNullOrEmpty(knownUser.ExternalName))
            {
                usernameToBuild = knownUser.ExternalName;
            }

            UserBE       ret      = null;
            DreamMessage response = null;

            if (serviceInfo.Uri == null)
            {
                throw new ExternalServiceNotStartedFatalException(serviceInfo.Type, serviceInfo.SID);
            }
            try {
                Plug dekiExternalAuthPlug;

                //bypassAuthentication is used when you only need user details but not to necessarily authenticate
                if (bypassAuthentication)
                {
                    //An external auth service's GET: user/{username} does not necessarily require authentication to lookup users but it may. It's up to the service
                    //to decide if anon requests are allowed.
                    dekiExternalAuthPlug = Plug.New(serviceInfo.Uri).At(USER_INFO).At(XUri.Encode(usernameToBuild));
                }
                else
                {
                    //Credentials are always needed for GET: authenticate. The user details of the auth'd user is returned with same format as GET: user/{username}
                    dekiExternalAuthPlug = Plug.New(serviceInfo.Uri).At(AUTHENTICATE_PATH);
                }

                //Always include credentials with the request if they're supplied
                if (!string.IsNullOrEmpty(authusername))
                {
                    dekiExternalAuthPlug = dekiExternalAuthPlug.WithCredentials(authusername, password ?? string.Empty);
                }

                response = dekiExternalAuthPlug.GetAsync().Wait();
            } catch (Exception x) {
                throw new ExternalServiceResponseException(errMsg, DreamMessage.InternalError(x));
            }

            if (response.IsSuccessful)
            {
                XDoc userXml = response.ToDocument();

                if (userXml == null || userXml.IsEmpty)
                {
                    throw new ExternalAuthResponseFatalException();
                }

                string nameFromAuthProvider = userXml["@name"].Contents;
                if (!nameFromAuthProvider.EqualsInvariantIgnoreCase(usernameToBuild))
                {
                    throw new ExternalServiceUnexpecteUsernameFatalException(userXml["@name"].AsText, usernameToBuild);
                }
                ret       = knownUser ?? new UserBE();
                ret.Email = string.IsNullOrEmpty(userXml["email"].AsText) ? (ret.Email ?? string.Empty) : userXml["email"].AsText;

                //Build the realname (exposed as 'fullname' in user xml) by saving it as '{firstname} {lastname}'
                string externalFirstName = userXml["firstname"].AsText ?? string.Empty;
                string externalLastName  = userXml["lastname"].AsText ?? string.Empty;
                string separator         = externalLastName.Length > 0 && externalFirstName.Length > 0 ? ", " : string.Empty;

                // NOTE (maxm): Fullname sync is disabled for now. Refer to bug 7855
#if !DISABLE_REAL_NAME_SYNCHRONIZATION
                ret.RealName = string.Format("{0}{1}{2}", externalLastName, separator, externalFirstName);
#endif

                ret.ServiceId = serviceInfo.Id;
                ret.Touched   = DateTime.UtcNow;

                ret.ExternalName = string.IsNullOrEmpty(ret.ExternalName) ? nameFromAuthProvider : ret.ExternalName;
                ret.Name         = string.IsNullOrEmpty(ret.Name) ? nameFromAuthProvider : ret.Name;

                //For new users, the name must be normalized and unique
                if (ret.ID == 0)
                {
                    string nameFromExternalName = string.Empty;

                    //Allow using a displayname from an external provider only for new accounts
                    if (!userXml["@displayname"].IsEmpty)
                    {
                        nameFromExternalName = userXml["@displayname"].AsText;
                    }
                    else
                    {
                        nameFromExternalName = ret.ExternalName;
                    }

                    ret.Name = UserBL.NormalizeExternalNameToWikiUsername(nameFromExternalName);
                }

                //Build group objects out of the user's group membership list
                externalGroups = new List <GroupBE>();
                IList <GroupBE> userGroups = DbUtils.CurrentSession.Groups_GetByUser(ret.ID);

                //Preserve local groups for existing users
                if (ret.ID != 0 && userGroups != null)
                {
                    foreach (GroupBE g in userGroups)
                    {
                        if (ServiceBL.IsLocalAuthService(g.ServiceId))
                        {
                            externalGroups.Add(g);
                        }
                    }
                }

                foreach (XDoc group in userXml["groups/group"])
                {
                    GroupBE g = new GroupBE();
                    g.Name      = group["@name"].AsText;
                    g.ServiceId = serviceInfo.Id;
                    if (!string.IsNullOrEmpty(g.Name))
                    {
                        externalGroups.Add(g);
                    }
                }
            }
            else
            {
                switch (response.Status)
                {
                case DreamStatus.Unauthorized:
                    if (bypassAuthentication)
                    {
                        DekiContext.Current.Instance.Log.Warn(string.Format("Attempted to lookup user info on auth provider '{0}' but failed since it required credentials", serviceInfo.Id));
                    }

                    throw new ExternalServiceAuthenticationDeniedException(DekiWikiService.AUTHREALM, serviceInfo.Description);

                default:
                    throw new ExternalServiceResponseException(errMsg, response);
                }
            }

            return(ret);
        }
Esempio n. 23
0
        public static GroupBE BuildGroupFromAuthService(ServiceBE serviceInfo, GroupBE knownGroup, string groupNameToBuild, string authusername, string password)
        {
            if (serviceInfo == null || string.IsNullOrEmpty(groupNameToBuild))
            {
                return(null);
            }

            GroupBE      ret      = null;
            DreamMessage response = null;

            if (serviceInfo.Uri == null)
            {
                throw new ExternalServiceNotStartedFatalException(serviceInfo.Type, serviceInfo.SID);
            }
            var errMsg = DekiResources.GROUP_DETAILS_LOOKUP_FAILED(groupNameToBuild);

            try {
                Plug dekiExternalAuthPlug = Plug.New(serviceInfo.Uri).At(GROUP_INFO).At(XUri.Encode(groupNameToBuild));

                //Always include credentials with the request if they're supplied
                if (!string.IsNullOrEmpty(authusername))
                {
                    dekiExternalAuthPlug = dekiExternalAuthPlug.WithCredentials(authusername, password ?? string.Empty);
                }

                response = dekiExternalAuthPlug.GetAsync().Wait();
            } catch (Exception x) {
                throw new ExternalServiceResponseException(errMsg, DreamMessage.InternalError(x));
            }

            if (response.IsSuccessful)
            {
                XDoc groupXml = response.ToDocument();
                if (groupXml.HasName("group") && groupXml["@name"].Contents.EqualsInvariant(groupNameToBuild))
                {
                    if (knownGroup == null)
                    {
                        ret = new GroupBE();
                    }
                    else
                    {
                        ret = knownGroup;
                    }

                    ret.Name      = string.IsNullOrEmpty(ret.Name) ? groupNameToBuild : ret.Name;
                    ret.ServiceId = serviceInfo.Id;
                }

                //TODO (MaxM): Consider looking up existing wiki users and associating them here.
            }
            else
            {
                switch (response.Status)
                {
                case DreamStatus.Unauthorized:
                    throw new ExternalServiceAuthenticationDeniedException(DekiWikiService.AUTHREALM, serviceInfo.Description);

                case DreamStatus.InternalError:
                case DreamStatus.Forbidden:
                default:
                    throw new ExternalServiceResponseException(errMsg, response);
                }
            }

            return(ret);
        }