Esempio n. 1
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. 2
0
        private static void ParseGroupXml(XDoc groupDoc, out uint?id, out string name, out ServiceBE authService, out RoleBE role, out UserBE[] userList)
        {
            name = groupDoc["groupname"].AsText ?? groupDoc["name"].AsText;
            string authserviceidstr = groupDoc["service.authentication/@id"].AsText;
            string rolestr          = groupDoc["permissions.group/role"].AsText;

            authService = null;
            role        = null;
            id          = null;


            if (!groupDoc["@id"].IsEmpty)
            {
                uint id_temp;
                if (!uint.TryParse(groupDoc["@id"].Contents, out id_temp))
                {
                    throw new GroupIdAttributeInvalidArgumentException();
                }
                id = id_temp;
            }

            if (!string.IsNullOrEmpty(authserviceidstr))
            {
                uint serviceid;
                if (!uint.TryParse(authserviceidstr, out serviceid))
                {
                    throw new ServiceAuthIdAttrInvalidArgumentException();
                }

                authService = ServiceBL.GetServiceById(serviceid);
                if (authService == null)
                {
                    throw new ServiceDoesNotExistInvalidArgumentException(serviceid);
                }
            }

            if (!string.IsNullOrEmpty(rolestr))
            {
                role = PermissionsBL.GetRoleByName(rolestr);
                if (role == null)
                {
                    throw new RoleDoesNotExistInvalidArgumentException(rolestr);
                }
            }
            else
            {
                role = PermissionsBL.RetrieveDefaultRoleForNewAccounts();
            }
            if (!groupDoc["users"].IsEmpty)
            {
                userList = ReadUserListXml(groupDoc["users"]);
            }
            else
            {
                userList = new UserBE[] { }
            };
        }
Esempio n. 3
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. 4
0
        //--- Class Methods ---
        public static UserBE Authenticate(DreamContext context, DreamMessage request, uint serviceId, bool autoCreateExternalUser, bool allowAnon, out bool altPassword)
        {
            UserBE user = null;

            altPassword = false;

            // Case 1: username/fullname, password, provider (login window)
            //      1. Validate & retrieve fullname using credentials
            //          Failed -> return null
            //      2. Populate user object
            //          A. Populates user info
            //          B. Populates group info in user object
            //      3. Does fullname exist?
            //          Yes -> Update user (email, fullname, ...)
            //          No  -> Create user
            //      4. Update Group information
            //      5. return user object
            //
            // Case 2: fullname, password (http, api, ...)
            //      1. Lookup full name, exist?
            //          Yes -> return user
            //          No -> return null
            //
            // Case 3: auth-token (header auth)
            //      0. Valid auth token?
            //          No -> return null
            //      1. Lookup user by name
            //          Found -> return user
            //          Else  -> return null

            string    userName      = null;
            string    password      = null;
            UserBE    userFromToken = null;
            ServiceBE authService   = null;

            // Extract authtoken and impersonation authtoken from request.
            // AllowAnon is false when in GET/POST: users/authenticate or when ?authenticate=true.
            // Standard user authtokens are ignored when AllowAnon=false but impersonation tokens are accepted.
            bool impersonationOnly = !allowAnon;

            userFromToken = UserFromAuthTokenInRequest(context, impersonationOnly);

            if (userFromToken == null)
            {
                HttpUtil.GetAuthentication(context.Uri.ToUri(), request.Headers, out userName, out password);
            }

            // check if we need to retrieve authentication service information
            if (serviceId > 0)
            {
                authService = ServiceBL.GetServiceById(serviceId);
                if (authService == null)
                {
                    throw new AuthServiceIdInvalidArgumentException(serviceId);
                }
                if (authService.Type != ServiceType.AUTH)
                {
                    throw new AuthNotAnAuthServiceInvalidArgumentException(serviceId);
                }
            }

            // check if a username was provided
            if (!string.IsNullOrEmpty(userName))
            {
                //Case 2: Given username + password
                if (authService == null)
                {
                    //Assuming local user or existing external account
                    user = DbUtils.CurrentSession.Users_GetByName(userName);
                    if (user != null)
                    {
                        serviceId   = user.ServiceId;
                        authService = ServiceBL.GetServiceById(serviceId);
                    }
                    else
                    {
                        LoginAccessDenied(context, request, userName, null, password);
                    }
                }
                if (authService == null)
                {
                    throw new AuthServiceIdInvalidArgumentException(serviceId);
                }
                if (authService.Type != ServiceType.AUTH)
                {
                    throw new AuthNotAnAuthServiceInvalidArgumentException(serviceId);
                }
                if (user == null)
                {
                    //Performing auth on local account
                    if (ServiceBL.IsLocalAuthService(authService))
                    {
                        user = DbUtils.CurrentSession.Users_GetByName(userName);
                    }
                    else
                    {
                        //Performing external auth. Lookup by external user name
                        user = DbUtils.CurrentSession.Users_GetByExternalName(userName, authService.Id);
                    }
                    if (user != null && user.ServiceId != authService.Id)
                    {
                        ServiceBE currentUsersAuthService = ServiceBL.GetServiceById(user.ServiceId);
                        if (currentUsersAuthService != null)
                        {
                            throw new AuthLoginExternalUserConflictException(currentUsersAuthService.Description);
                        }
                        throw new LoginExternalUserUnknownConflictException();
                    }
                }

                //Local account in the db.
                if (user != null && ServiceBL.IsLocalAuthService(authService))
                {
                    //Validate password for local account or validate the apikey
                    if (!IsValidAuthenticationForLocalUser(user, password, out altPassword))
                    {
                        // try impersonation using the ApiKey
                        if (string.IsNullOrEmpty(password) && PermissionsBL.ValidateRequestApiKey())
                        {
                            DekiContext.Current.Instance.Log.InfoFormat("user '{0}' authenticated via apikey impersonation", userName);
                        }
                        else
                        {
                            LoginAccessDenied(context, request, userName, user.ID, password);
                        }
                    }
                }

                // User was not found in the db and not being asked to create it.
                if (user == null && !autoCreateExternalUser)
                {
                    LoginAccessDenied(context, request, userName, null, password);
                }

                // Creating local account if apikey checks out and our authservice is local
                if (user == null && string.IsNullOrEmpty(password) && PermissionsBL.ValidateRequestApiKey() && ServiceBL.IsLocalAuthService(authService))
                {
                    XDoc newUserDoc = new XDoc("user")
                                      .Elem("username", userName);
                    DreamMessage newUserResponse = DekiContext.Current.ApiPlug.At("users")
                                                   .With("apikey", DreamContext.Current.GetParam("apikey", string.Empty))
                                                   .Post(newUserDoc);
                    user = UserBL.GetUserById(newUserResponse.ToDocument()["/user/@id"].AsUInt ?? 0);
                    if (user != null && !string.IsNullOrEmpty(password))
                    {
                        user = UserBL.SetPassword(user, password, false);
                    }
                }

                // Got an external account
                // Passing in the user object from db if it was found.
                List <GroupBE> externalGroups = null;
                if (!ServiceBL.IsLocalAuthService(authService))
                {
                    bool   bypassAuthentication = false;
                    string externalName;
                    if (user == null || string.IsNullOrEmpty(user.ExternalName))
                    {
                        externalName = userName;
                    }
                    else
                    {
                        externalName = user.ExternalName;
                    }

                    // If apikey is valid, try to bypass auth with the external provider
                    // and only lookup user/group details.
                    if (string.IsNullOrEmpty(password) && PermissionsBL.ValidateRequestApiKey())
                    {
                        DekiContext.Current.Instance.Log.InfoFormat("user '{0}' authenticating being bypassed via apikey impersonation", userName);
                        bypassAuthentication = true;
                    }

                    user = ExternalServiceSA.BuildUserFromAuthService(authService, user, userName, bypassAuthentication, externalName, password, out externalGroups);
                }

                // User was not found or did not authenticate with external provider
                if (user == null)
                {
                    LoginAccessDenied(context, request, userName, null, password);
                }
                else
                {
                    //New user creation from external provider
                    if (user.ID == 0)
                    {
                        if (!autoCreateExternalUser)
                        {
                            LoginAccessDenied(context, request, userName, null, password);
                        }
                    }
                    else
                    {
                        //user exists
                        // TODO (steveb): ???
                    }
                    if (user.UserActive)
                    {
                        user = UserBL.CreateOrUpdateUser(user);
                        if (externalGroups != null)
                        {
                            UserBL.UpdateUsersGroups(user, externalGroups.ToArray());
                        }
                    }
                }
            }
            else if (userFromToken != null)
            {
                // valid token exists that resolved to a user
                user = userFromToken;
            }
            else if (allowAnon)
            {
                // Anonymous user
                user = DbUtils.CurrentSession.Users_GetByName(DekiWikiService.ANON_USERNAME);
            }
            if (user == null)
            {
                //No credentials. Or token not provided or is invalid.
                LoginAccessDenied(context, request, null, null, password);
            }
            else if (!user.UserActive && !PermissionsBL.ValidateRequestApiKey())
            {
                //If a valid api key is provided, override the disabled account flag
                throw new AuthUserDisabledForbiddenException(user.Name);
            }
            return(user);
        }
Esempio n. 5
0
        public static XDoc GetUserXmlVerbose(UserBE user, string relationAttr, bool showPrivateInfo, bool showGroups, bool showProperties)
        {
            XDoc userXml = GetUserXml(user, relationAttr, showPrivateInfo);

            userXml.Elem("date.created", user.CreateTimestamp);

            if (!IsAnonymous(user))
            {
                PageBE homePage = GetHomePage(user);
                if (homePage != null && homePage.ID != 0)
                {
                    userXml.Add(PageBL.GetPageXml(homePage, "home"));
                }
            }

            userXml.Start("status").Value(user.UserActive ? "active" : "inactive").End();
            userXml.Start("date.lastlogin").Value(user.Touched).End();
            userXml.Start("language").Value(user.Language).End();
            userXml.Start("timezone").Value(user.Timezone).End();

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

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

            //Permissions for the user from user role
            userXml.Add(PermissionsBL.GetRoleXml(PermissionsBL.GetRoleById(user.RoleId), "user"));

            ulong effectivePermissions = PermissionsBL.CalculateEffectiveUserRights(user);

            //Effective permissions for the user from the role + group roles.
            userXml.Add(PermissionsBL.GetPermissionXml(effectivePermissions, "effective"));

            // Set of permissions revoked from the user
            userXml.Add(PermissionsBL.GetPermissionsRevokedXml(user));

            // check if groups should be included
            if (showGroups)
            {
                userXml.Start("groups");
                IList <GroupBE> groups = DbUtils.CurrentSession.Groups_GetByUser(user.ID);
                if (null != groups)
                {
                    foreach (GroupBE g in groups)
                    {
                        userXml.Add(GroupBL.GetGroupXmlVerbose(g, null));
                    }
                }
                userXml.End();
            }

            // retrieve properties for current user while providing an href for other users.
            if (showProperties && (DekiContext.Current != null && DekiContext.Current.User != null && DekiContext.Current.User.ID == user.ID))
            {
                IList <ResourceBE> props = PropertyBL.Instance.GetUserProperties(user.ID);
                userXml = PropertyBL.Instance.GetPropertyXml(props, GetUri(user), null, null, userXml);
            }
            else
            {
                userXml.Start("properties").Attr("href", GetUri(user).At("properties")).End();
            }

            // TODO Max: get <subscriptions> (watchlist) not implemented
            return(userXml);
        }
Esempio n. 6
0
        private static void ParseUserXml(XDoc userDoc, out uint?id, out string username, out string email, out string fullname, out ServiceBE authService, out RoleBE role, out bool?active, out string language, out string timezone)
        {
            username = userDoc["username"].AsText;
            email    = userDoc["email"].AsText;
            fullname = userDoc["fullname"].AsText;
            language = userDoc["language"].AsText;
            timezone = userDoc["timezone"].AsText;
            string authserviceidstr = userDoc["service.authentication/@id"].AsText;
            string rolestr          = userDoc["permissions.user/role"].AsText;
            string statusStr        = userDoc["status"].AsText;

            authService = null;
            role        = null;

            id = null;

            if (!userDoc["@id"].IsEmpty)
            {
                uint id_temp;
                if (!uint.TryParse(userDoc["@id"].Contents, out id_temp))
                {
                    throw new UserIdAttrInvalidArgumentException();
                }
                id = id_temp;
            }

            if (!string.IsNullOrEmpty(authserviceidstr))
            {
                uint serviceid;
                if (!uint.TryParse(authserviceidstr, out serviceid))
                {
                    throw new ServiceAuthIdAttrInvalidArgumentException();
                }

                authService = ServiceBL.GetServiceById(serviceid);
                if (authService == null)
                {
                    throw new ServiceDoesNotExistInvalidArgumentException(serviceid);
                }
            }

            if (!string.IsNullOrEmpty(rolestr))
            {
                role = PermissionsBL.GetRoleByName(rolestr);
                if (role == null)
                {
                    throw new RoleDoesNotExistInvalidArgumentException(rolestr);
                }
            }

            if (!string.IsNullOrEmpty(statusStr))
            {
                switch (statusStr.ToLowerInvariant())
                {
                case "active":
                    active = true;
                    break;

                case "inactive":
                    active = false;
                    break;

                default:
                    throw new UserStatusAttrInvalidArgumentException();
                }
            }
            else
            {
                active = null;
            }

            if (!string.IsNullOrEmpty(timezone))
            {
                if (!timeZoneRegex.Match(timezone).Success)
                {
                    throw new UserTimezoneInvalidArgumentException();
                }
            }

            if (!string.IsNullOrEmpty(language))
            {
                string[] validLanguages = DekiContext.Current.Instance.Languages.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                string   tempLanguage   = language;
                if (!Array.Exists(validLanguages, delegate(string temp) { return(temp.EqualsInvariantIgnoreCase(tempLanguage)); }))
                {
                    throw new UserInvalidLanguageException();
                }
            }
        }