Skip to content

Commit 061f1c9

Browse files
Fix NPE on first LDAP login
Signed-off-by: xujiantop-crypto <265865031+xujiantop-crypto@users.noreply.github.com>
1 parent cddd2c6 commit 061f1c9

2 files changed

Lines changed: 108 additions & 1 deletion

File tree

server/src/main/java/com/cloud/api/auth/DefaultLoginAPIAuthenticatorCmd.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,9 @@ public String authenticate(String command, Map<String, Object[]> params, HttpSes
155155
}
156156
serializedResponse = ApiResponseSerializer.toSerializedString(_apiServer.loginUser(session, username[0], pwd, domainId, domain, remoteAddress, params),
157157
responseType);
158-
userDetailsDao.removeDetail(userAccount.getId(), UserDetailVO.OauthLogin);
158+
if (userAccount != null) {
159+
userDetailsDao.removeDetail(userAccount.getId(), UserDetailVO.OauthLogin);
160+
}
159161
return serializedResponse;
160162
} catch (final CloudAuthenticationException ex) {
161163
ApiServlet.invalidateHttpSession(session, "fall through to API key,");
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
package com.cloud.api.auth;
18+
19+
import com.cloud.domain.Domain;
20+
import com.cloud.user.AccountService;
21+
import com.cloud.user.DomainService;
22+
import org.apache.cloudstack.api.ApiConstants;
23+
import org.apache.cloudstack.api.ApiServerService;
24+
import org.apache.cloudstack.api.response.LoginCmdResponse;
25+
import org.apache.cloudstack.resourcedetail.dao.UserDetailsDao;
26+
import org.junit.Assert;
27+
import org.junit.Before;
28+
import org.junit.Test;
29+
import org.junit.runner.RunWith;
30+
import org.mockito.Mock;
31+
import org.mockito.Mockito;
32+
import org.mockito.junit.MockitoJUnitRunner;
33+
34+
import javax.servlet.http.HttpServletRequest;
35+
import javax.servlet.http.HttpServletResponse;
36+
import javax.servlet.http.HttpSession;
37+
import java.net.InetAddress;
38+
import java.util.HashMap;
39+
import java.util.Map;
40+
41+
@RunWith(MockitoJUnitRunner.class)
42+
public class DefaultLoginAPIAuthenticatorCmdTest {
43+
44+
private static final String USERNAME = "ldap-user";
45+
private static final long DOMAIN_ID = 2L;
46+
47+
@Mock
48+
private ApiServerService apiServer;
49+
50+
@Mock
51+
private AccountService accountService;
52+
53+
@Mock
54+
private DomainService domainService;
55+
56+
@Mock
57+
private UserDetailsDao userDetailsDao;
58+
59+
@Mock
60+
private HttpSession session;
61+
62+
@Mock
63+
private HttpServletRequest request;
64+
65+
@Mock
66+
private HttpServletResponse response;
67+
68+
@Mock
69+
private Domain domain;
70+
71+
private DefaultLoginAPIAuthenticatorCmd command;
72+
73+
@Before
74+
public void setUp() {
75+
command = new DefaultLoginAPIAuthenticatorCmd();
76+
command._apiServer = apiServer;
77+
command._accountService = accountService;
78+
command._domainService = domainService;
79+
command.userDetailsDao = userDetailsDao;
80+
}
81+
82+
@Test
83+
public void testAuthenticateFirstLdapLoginWithoutExistingUser() throws Exception {
84+
Map<String, Object[]> params = new HashMap<>();
85+
params.put(ApiConstants.USERNAME, new String[] {USERNAME});
86+
params.put(ApiConstants.PASSWORD, new String[] {"password"});
87+
LoginCmdResponse loginResponse = new LoginCmdResponse();
88+
loginResponse.setResponseName("loginresponse");
89+
90+
Mockito.when(request.getMethod()).thenReturn("POST");
91+
Mockito.when(apiServer.getDomainId(params)).thenReturn(null);
92+
Mockito.when(domainService.findDomainByIdOrPath(null, null)).thenReturn(domain);
93+
Mockito.when(domain.getId()).thenReturn(DOMAIN_ID);
94+
Mockito.when(accountService.getActiveUserAccount(USERNAME, DOMAIN_ID)).thenReturn(null);
95+
Mockito.when(apiServer.loginUser(Mockito.eq(session), Mockito.eq(USERNAME), Mockito.eq("password"),
96+
Mockito.eq(DOMAIN_ID), Mockito.isNull(), Mockito.any(InetAddress.class), Mockito.eq(params)))
97+
.thenReturn(loginResponse);
98+
99+
String result = command.authenticate("login", params, session, InetAddress.getLoopbackAddress(),
100+
"json", new StringBuilder(), request, response);
101+
102+
Assert.assertEquals("{\"loginresponse\":{}}", result);
103+
Mockito.verify(userDetailsDao, Mockito.never()).removeDetail(Mockito.anyLong(), Mockito.anyString());
104+
}
105+
}

0 commit comments

Comments
 (0)