Merge branch '4.19' into 4.20

This commit is contained in:
Daan Hoogland 2024-12-04 13:04:18 +01:00
commit 5ee61c226a
8 changed files with 161 additions and 1 deletions

View File

@ -47,6 +47,8 @@ public interface ProjectAccountDao extends GenericDao<ProjectAccountVO, Long> {
void removeAccountFromProjects(long accountId);
void removeUserFromProjects(long userId);
boolean canUserModifyProject(long projectId, long accountId, long userId);
List<ProjectAccountVO> listUsersOrAccountsByRole(long id);

View File

@ -192,6 +192,17 @@ public class ProjectAccountDaoImpl extends GenericDaoBase<ProjectAccountVO, Long
}
}
@Override
public void removeUserFromProjects(long userId) {
SearchCriteria<ProjectAccountVO> sc = AllFieldsSearch.create();
sc.setParameters("userId", userId);
int removedCount = remove(sc);
if (removedCount > 0) {
logger.debug(String.format("Removed user [%s] from %s project(s).", userId, removedCount));
}
}
@Override
public boolean canUserModifyProject(long projectId, long accountId, long userId) {
SearchCriteria<ProjectAccountVO> sc = AllFieldsSearch.create();

View File

@ -0,0 +1,66 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.upgrade.dao;
import com.cloud.utils.exception.CloudRuntimeException;
import java.io.InputStream;
import java.sql.Connection;
public class Upgrade41910to41920 implements DbUpgrade {
@Override
public String[] getUpgradableVersionRange() {
return new String[]{"4.19.1.0", "4.19.2.0"};
}
@Override
public String getUpgradedVersion() {
return "4.19.2.0";
}
@Override
public boolean supportsRollingUpgrade() {
return false;
}
@Override
public InputStream[] getPrepareScripts() {
final String scriptFile = "META-INF/db/schema-41910to41920.sql";
final InputStream script = Thread.currentThread().getContextClassLoader().getResourceAsStream(scriptFile);
if (script == null) {
throw new CloudRuntimeException("Unable to find " + scriptFile);
}
return new InputStream[]{script};
}
@Override
public void performDataMigration(Connection conn) {
}
@Override
public InputStream[] getCleanupScripts() {
final String scriptFile = "META-INF/db/schema-41910to41920-cleanup.sql";
final InputStream script = Thread.currentThread().getContextClassLoader().getResourceAsStream(scriptFile);
if (script == null) {
throw new CloudRuntimeException("Unable to find " + scriptFile);
}
return new InputStream[]{script};
}
}

View File

@ -0,0 +1,23 @@
-- Licensed to the Apache Software Foundation (ASF) under one
-- or more contributor license agreements. See the NOTICE file
-- distributed with this work for additional information
-- regarding copyright ownership. The ASF licenses this file
-- to you under the Apache License, Version 2.0 (the
-- "License"); you may not use this file except in compliance
-- with the License. You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing,
-- software distributed under the License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-- KIND, either express or implied. See the License for the
-- specific language governing permissions and limitations
-- under the License.
--;
-- Schema upgrade cleanup from 4.19.1.0 to 4.19.2.0
--;
-- Delete `project_account` entries for users that were removed
DELETE FROM `cloud`.`project_account` WHERE `user_id` IN (SELECT `id` FROM `cloud`.`user` WHERE `removed`);

View File

@ -0,0 +1,20 @@
-- Licensed to the Apache Software Foundation (ASF) under one
-- or more contributor license agreements. See the NOTICE file
-- distributed with this work for additional information
-- regarding copyright ownership. The ASF licenses this file
-- to you under the Apache License, Version 2.0 (the
-- "License"); you may not use this file except in compliance
-- with the License. You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing,
-- software distributed under the License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-- KIND, either express or implied. See the License for the
-- specific language governing permissions and limitations
-- under the License.
--;
-- Schema upgrade from 4.19.1.0 to 4.19.2.0
--;

View File

@ -656,7 +656,7 @@ public class EncryptionSecretKeyChanger {
String sqlTemplateDeployAsIsDetails = "SELECT template_deploy_as_is_details.value " +
"FROM template_deploy_as_is_details JOIN vm_instance " +
"WHERE template_deploy_as_is_details.template_id = vm_instance.vm_template_id " +
"vm_instance.id = %s AND template_deploy_as_is_details.name = '%s' LIMIT 1";
"AND vm_instance.id = %s AND template_deploy_as_is_details.name = '%s' LIMIT 1";
try (PreparedStatement selectPstmt = conn.prepareStatement("SELECT id, vm_id, name, value FROM user_vm_deploy_as_is_details");
ResultSet rs = selectPstmt.executeQuery();
PreparedStatement updatePstmt = conn.prepareStatement("UPDATE user_vm_deploy_as_is_details SET value=? WHERE id=?")

View File

@ -1500,6 +1500,8 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
* <ul>
* <li> If 'password' is blank, we throw an {@link InvalidParameterValueException};
* <li> If 'current password' is not provided and user is not an Admin, we throw an {@link InvalidParameterValueException};
* <li> If the user whose password is being changed has a source equal to {@link User.Source#SAML2}, {@link User.Source#SAML2DISABLED} or {@link User.Source#LDAP},
* we throw an {@link InvalidParameterValueException};
* <li> If a normal user is calling this method, we use {@link #validateCurrentPassword(UserVO, String)} to check if the provided old password matches the database one;
* </ul>
*
@ -1514,6 +1516,12 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
throw new InvalidParameterValueException("Password cannot be empty or blank.");
}
User.Source userSource = user.getSource();
if (userSource == User.Source.SAML2 || userSource == User.Source.SAML2DISABLED || userSource == User.Source.LDAP) {
logger.warn(String.format("Unable to update the password for user [%d], as its source is [%s].", user.getId(), user.getSource().toString()));
throw new InvalidParameterValueException("CloudStack does not support updating passwords for SAML or LDAP users. Please contact your cloud administrator for assistance.");
}
passwordPolicy.verifyIfPasswordCompliesWithPasswordPolicies(newPassword, user.getUsername(), getAccount(user.getAccountId()).getDomainId());
Account callingAccount = getCurrentCallingAccount();

View File

@ -874,6 +874,36 @@ public class AccountManagerImplTest extends AccountManagetImplTestBase {
accountManagerImpl.validateUserPasswordAndUpdateIfNeeded(newPassword, userVoMock, currentPassword, false);
}
@Test(expected = InvalidParameterValueException.class)
public void validateUserPasswordAndUpdateIfNeededTestSaml2UserShouldNotBeAllowedToUpdateTheirPassword() {
String newPassword = "newPassword";
String currentPassword = "theCurrentPassword";
Mockito.when(userVoMock.getSource()).thenReturn(User.Source.SAML2);
accountManagerImpl.validateUserPasswordAndUpdateIfNeeded(newPassword, userVoMock, currentPassword, false);
}
@Test(expected = InvalidParameterValueException.class)
public void validateUserPasswordAndUpdateIfNeededTestSaml2DisabledUserShouldNotBeAllowedToUpdateTheirPassword() {
String newPassword = "newPassword";
String currentPassword = "theCurrentPassword";
Mockito.when(userVoMock.getSource()).thenReturn(User.Source.SAML2DISABLED);
accountManagerImpl.validateUserPasswordAndUpdateIfNeeded(newPassword, userVoMock, currentPassword, false);
}
@Test(expected = InvalidParameterValueException.class)
public void validateUserPasswordAndUpdateIfNeededTestLdapUserShouldNotBeAllowedToUpdateTheirPassword() {
String newPassword = "newPassword";
String currentPassword = "theCurrentPassword";
Mockito.when(userVoMock.getSource()).thenReturn(User.Source.LDAP);
accountManagerImpl.validateUserPasswordAndUpdateIfNeeded(newPassword, userVoMock, currentPassword, false);
}
private String configureUserMockAuthenticators(String newPassword) {
accountManagerImpl._userPasswordEncoders = new ArrayList<>();
UserAuthenticator authenticatorMock1 = Mockito.mock(UserAuthenticator.class);