Example #1
0
 private static void ValidateGroupMemberList(ServiceBE groupService, UserBE[] potentialMembers)
 {
     //Groups belonging to built-in auth service are allowed to contain users from remote services
     if (!ServiceBL.IsLocalAuthService(groupService))
     {
         foreach (UserBE u in potentialMembers)
         {
             if (u.ServiceId != groupService.Id)
             {
                 throw new GroupMembersRequireSameAuthInvalidOperationException();
             }
         }
     }
 }
Example #2
0
        public static ServiceBE PostServiceFromXml(XDoc serviceDoc, ServiceBE serviceToProcess)
        {
            uint?               serviceId;
            string              SID, description, uri;
            bool?               statusEnabled;
            bool?               localInit;
            ServiceType?        type;
            NameValueCollection config, preferences;

            ParseServiceXml(serviceDoc, out serviceId, out SID, out description, out statusEnabled, out localInit, out type, out uri, out config, out preferences);

            //new service
            if (serviceToProcess == null && (serviceId == null || serviceId == 0))
            {
                //convert XML input to a service object
                serviceToProcess = NewServiceFromXml(serviceDoc, SID, description, statusEnabled, localInit, type, uri, config, preferences);

                //insert the service
                serviceId = DbUtils.CurrentSession.Services_Insert(serviceToProcess);

                // reload the service
                serviceToProcess = DbUtils.CurrentSession.Services_GetById(serviceId.Value);
            }
            else
            {
                //Validate logic of given xml
                if (ServiceBL.IsLocalAuthService(serviceToProcess))
                {
                    throw new ServiceCannotModifyBuiltInAuthInvalidOperationException();
                }

                if (((uri ?? string.Empty) != string.Empty) && (localInit ?? false))
                {
                    throw new ServiceCannotSetLocalUriInvalidOperationException();
                }

                //Stop the service before making any changes
                serviceToProcess = StopService(serviceToProcess);

                //convert XML input to a service object.
                serviceToProcess = UpdateServiceFromParsedXml(serviceToProcess, SID, description, statusEnabled, localInit, type, uri, config, preferences);

                //Update existing service
                serviceToProcess = UpdateService(serviceToProcess);
            }

            return(serviceToProcess);
        }
Example #3
0
        private static UserBE RenameUser(UserBE user, string newUserName, string newFullName)
        {
            //Renaming requires admin rights.
            PermissionsBL.CheckUserAllowed(DekiContext.Current.User, Permissions.ADMIN);

            if (!ServiceBL.IsLocalAuthService(user.ServiceId))
            {
                //TODO MaxM: allow renaming of external users
                throw new ExternalUserRenameNotImplementedExceptionException();
            }

            //Check for already existing user with same name
            UserBE existingUser = DbUtils.CurrentSession.Users_GetByName(newUserName);

            if (existingUser != null)
            {
                throw new UserWithIdExistsConflictException(existingUser.Name, existingUser.ID);
            }

            PageBE existingTargetUserHomePage = PageBL.GetPageByTitle(Title.FromUIUsername(newUserName));

            if (existingTargetUserHomePage != null && existingTargetUserHomePage.ID != 0 && !existingTargetUserHomePage.IsRedirect)
            {
                throw new UserHomepageRenameConflictException();
            }

            //Try to move the homepage.
            PageBE userHomePage = GetHomePage(user);

            if (userHomePage != null && userHomePage.ID != 0)
            {
                Title newTitle = Title.FromUIUsername(newUserName);

                // new user homepage displayname is the user's full name or rebuilt from the username
                newTitle.DisplayName = !string.IsNullOrEmpty(newFullName) ? newFullName : newTitle.AsUserFriendlyDisplayName();
                PageBL.MovePage(userHomePage, newTitle, true);
            }

            //Rename the user
            user.Name = newUserName;
            UserBL.UpdateUser(user);
            return(user);
        }
Example #4
0
        public static UserBE CreateOrUpdateUser(UserBE user, string newPassword)
        {
            if (user.ID > 0)
            {
                UpdateUser(user);
            }
            else
            {
                //TODO consider logic here to confirm that the user does not yet exist.

                user = CreateNewUser(user);
            }

            if (!string.IsNullOrEmpty(newPassword) && ServiceBL.IsLocalAuthService(user.ServiceId))
            {
                user = UserBL.SetPassword(user, newPassword, false);
                DekiContext.Current.Instance.EventSink.UserChangePassword(DekiContext.Current.Now, user);
            }

            return(user);
        }
Example #5
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);
        }
Example #6
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);
        }
        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);
        }
Example #8
0
        private static UserBE UpdateUserFromXml(UserBE userToUpdate, XDoc userDoc, string username, string email, string fullname, ServiceBE authservice, RoleBE role, bool?active, string externalusername, string externalpassword, string language, string timezone, out List <GroupBE> externalGroups)
        {
            externalGroups = null;
            if (userToUpdate.Name != username && !string.IsNullOrEmpty(username))
            {
                if (UserBL.IsAnonymous(userToUpdate))
                {
                    throw new UserAnonymousEditInvalidOperationException();
                }
                userToUpdate = RenameUser(userToUpdate, username, fullname ?? userToUpdate.RealName);
            }

            //Modify a user's authentication service
            if (authservice != null && authservice.Id != userToUpdate.ServiceId)
            {
                if (UserBL.IsAnonymous(userToUpdate))
                {
                    throw new UserAnonymousEditInvalidOperationException();
                }

                if (ServiceBL.IsLocalAuthService(authservice))
                {
                    //external to local
                    userToUpdate.ExternalName = null;
                    userToUpdate.ServiceId    = authservice.Id;
                }
                else
                {
                    //(local or external) to external
                    userToUpdate = ExternalServiceSA.BuildUserFromAuthService(authservice, userToUpdate, userToUpdate.Name, true, externalusername, externalpassword, out externalGroups);
                    if (userToUpdate == null)
                    {
                        throw new UserAuthChangeFatalException();
                    }

                    //Does the external account already exist?
                    UserBE matchingExternalAccount = DbUtils.CurrentSession.Users_GetByExternalName(userToUpdate.ExternalName, userToUpdate.ServiceId);
                    if (matchingExternalAccount != null)
                    {
                        throw new ExternalUserExistsConflictException(matchingExternalAccount.Name, matchingExternalAccount.ExternalName, matchingExternalAccount.ServiceId);
                    }
                }
            }

            if (email != null)
            {
                if (UserBL.IsAnonymous(userToUpdate) && email != userToUpdate.Email)
                {
                    throw new UserAnonymousEditInvalidOperationException();
                }

                userToUpdate.Email = email;
            }

            if (!string.IsNullOrEmpty(fullname))
            {
                userToUpdate.RealName = fullname;
            }

            if (active != null)
            {
                // disabling user
                if (userToUpdate.UserActive && !active.Value)
                {
                    // cannot disable anonymous user
                    if (UserBL.IsAnonymous(userToUpdate))
                    {
                        throw new UserAnonymousDeactivationInvalidOperationException();
                    }

                    // cannot disable owner
                    if (DekiContext.Current.LicenseManager.GetSiteOwnerUserId().GetValueOrDefault(0) == userToUpdate.ID)
                    {
                        throw new UserOwnerDeactivationConflict();
                    }
                }

                //throw exception if licensing does not allow activating a user
                if (!userToUpdate.UserActive && active.Value)
                {
                    DekiContext.Current.LicenseManager.IsUserCreationAllowed(true);
                }

                userToUpdate.UserActive = active.Value;
            }

            if (role != null && role.ID != userToUpdate.RoleId)
            {
                PermissionsBL.CheckUserAllowed(DekiContext.Current.User, Permissions.ADMIN);
                userToUpdate.RoleId = role.ID;
            }

            if (language != null)
            {
                userToUpdate.Language = language;
            }

            if (timezone != null)
            {
                userToUpdate.Timezone = timezone;
            }

            return(userToUpdate);
        }
Example #9
0
        public static UserBE PostUserFromXml(XDoc userDoc, UserBE userToProcess, string accountpassword, string externalusername, string externalpassword)
        {
            List <GroupBE> externalGroups = null;
            uint?          id;
            bool?          active;
            string         username, fullname, email, language, timezone;
            ServiceBE      authService;
            RoleBE         role;

            // parse the standard user XML doc
            ParseUserXml(userDoc, out id, out username, out email, out fullname, out authService, out role, out active, out language, out timezone);

            // new user
            if ((userToProcess == null) && ((id == null) || (id == 0)))
            {
                userToProcess = ReadUserXml(userDoc, username, email, fullname, authService, role, language, timezone);

                // external accounts should be confirmed, username normalized, groups retrieved
                if ((authService != null) && !ServiceBL.IsLocalAuthService(authService))
                {
                    // check if a local-account password was provided
                    if (!string.IsNullOrEmpty(accountpassword))
                    {
                        throw new ExternalUserPasswordInvalidOperationException();
                    }

                    // only admins can create external accounts for others. Anyone can create their own external account
                    if (externalusername != userToProcess.Name || externalusername == string.Empty)
                    {
                        PermissionsBL.CheckUserAllowed(DekiContext.Current.User, Permissions.ADMIN);
                    }

                    // username+password from request query params are used here
                    userToProcess = ExternalServiceSA.BuildUserFromAuthService(authService, userToProcess, username, true, externalusername, externalpassword, out externalGroups);
                    if (userToProcess == null)
                    {
                        throw new ExternalUserNotFoundException(username);
                    }

                    // does the external account already exist?
                    UserBE matchingExternalAccount = DbUtils.CurrentSession.Users_GetByExternalName(userToProcess.ExternalName, userToProcess.ServiceId);
                    if (matchingExternalAccount != null)
                    {
                        throw new ExternalUserExistsConflictException(matchingExternalAccount.Name, userToProcess.ExternalName, userToProcess.ServiceId);
                    }
                }
                else
                {
                    // creating local account
                    // user creation requires admin rights unless the config flag allows it
                    // anonymous users are not allowed to set role
                    if (!DekiContext.Current.Instance.AllowAnonymousLocalAccountCreation || role != null)
                    {
                        PermissionsBL.CheckUserAllowed(DekiContext.Current.User, Permissions.ADMIN);
                    }
                }

                // sanity check for already existing user
                UserBE existingUser = DbUtils.CurrentSession.Users_GetByName(userToProcess.Name);
                if (existingUser != null)
                {
                    throw new UserWithIdExistsConflictException(existingUser.Name, existingUser.ID);
                }

                //if (UserDA.RetrieveUserRegistrations(userToProcess.Name)) {
                //    throw new DreamAbortException(DreamMessage.Conflict(string.Format("User '{0}' has been reserved", userToProcess.Name)));
                //}

                userToProcess = CreateOrUpdateUser(userToProcess, accountpassword);
                if (null != externalGroups)
                {
                    UpdateUsersGroups(userToProcess, externalGroups.ToArray());
                }
            }
            else
            {
                // update existing user
                if (userToProcess == null)
                {
                    userToProcess = GetUserById(id.Value);
                    if (userToProcess == null)
                    {
                        throw new UserIdNotFoundException(id.Value);
                    }
                }

                // TODO (steveb): either this needs to go or the definition for PUT:user/{userid} should not mention the 'accountpassword' parameter
                if (!string.IsNullOrEmpty(accountpassword))
                {
                    throw new UserUsePutToChangePasswordInvalidOperationException();
                }

                // permission check if not modifying self
                if (userToProcess.ID != DekiContext.Current.User.ID)
                {
                    PermissionsBL.CheckUserAllowed(DekiContext.Current.User, Permissions.ADMIN);
                }
                userToProcess = UpdateUserFromXml(userToProcess, userDoc, username, email, fullname, authService, role, active, externalusername, externalpassword, language, timezone, out externalGroups);
                userToProcess = CreateOrUpdateUser(userToProcess);
                if (null != externalGroups)
                {
                    UpdateUsersGroups(userToProcess, externalGroups.ToArray());
                }
                if (IsAnonymous(userToProcess) && DekiContext.Current.Instance.CacheAnonymousOutput)
                {
                    DekiContext.Current.Deki.EmptyResponseCacheInternal();
                }
                try {
                    if (!userToProcess.UserActive && userToProcess.LicenseSeat && DekiContext.Current.LicenseManager.IsSeatLicensingEnabled())
                    {
                        DekiContext.Current.LicenseManager.RemoveSeatFromUser(userToProcess);
                    }
                } catch (Exception x) {
                    _log.WarnExceptionFormat(x, "Unable to remove license seat for disabled user. user id: {0}", userToProcess.ID);
                }
            }
            return(userToProcess);
        }
Example #10
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);
        }