/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed 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 samples;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static samples.test.SecurityRequestPostProcessors.csrf;
import static samples.test.SecurityRequestPostProcessors.user;
import java.util.List;
import javax.servlet.Filter;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import sample.config.RootConfiguration;
import sample.data.Message;
import sample.data.User;
import sample.mvc.config.WebMvcConfiguration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.ResultMatcher;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
/**
* @author Rob Winch
*
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { RootConfiguration.class,
WebMvcConfiguration.class })
@WebAppConfiguration
public class SecurityTests {
@Autowired
private WebApplicationContext context;
@Autowired
private Filter springSecurityFilterChain;
private User rob;
private MockMvc mvc;
@Before
public void setup() {
// NOTE: Could also load rob from UserRepository if we wanted
rob = new User();
rob.setId(0L);
rob.setEmail("rob@example.com");
rob.setFirstName("Rob");
rob.setLastName("Winch");
mvc = MockMvcBuilders
.webAppContextSetup(context)
.addFilters(springSecurityFilterChain)
.build();
}
@Test
public void inboxRequiresLogin() throws Exception {
mvc
.perform(get("/"))
.andExpect(loginPage());
}
@Test
public void inboxShowsOnlyRobsMessages() throws Exception {
RequestBuilder request = get("/")
.with(user(rob).roles("USER"));
mvc
.perform(request)
.andExpect(model().attribute("messages", new BaseMatcher<List<Message>>() {
@Override
public boolean matches(Object other) {
@SuppressWarnings("unchecked")
List<Message> messages = (List<Message>) other;
return messages.size() == 1 && messages.get(0).getId() == 100;
}
@Override
public void describeTo(Description d) {
}
}));
}
@Test
public void invalidUsernamePassword() throws Exception {
RequestBuilder request = post("/login")
.param("username", "rob@example.com")
.param("password", "invalid")
.with(csrf());
mvc
.perform(request)
.andExpect(invalidLogin());
}
@Test
public void validUsernamePassword() throws Exception {
RequestBuilder request = post("/login")
.param("username", "rob@example.com")
.param("password", "password")
.with(csrf());
mvc
.perform(request)
.andExpect(redirectedUrl("/"));
}
@Test
public void composeRequiresCsrf() throws Exception {
RequestBuilder request = post("/")
.with(user(rob).roles("USER"));
mvc
.perform(request)
.andExpect(invalidCsrf());
}
@Test
public void robCannotAccessLukesMessage() throws Exception {
RequestBuilder request = get("/110")
.with(user(rob).roles("USER"));
mvc
.perform(request)
.andExpect(status().isForbidden());
}
@Test
public void robCanAccessOwnMessage() throws Exception {
RequestBuilder request = get("/100")
.with(user(rob).roles("USER"));
mvc
.perform(request)
.andExpect(status().isOk());
}
private static ResultMatcher loginPage() {
return new ResultMatcher() {
@Override
public void match(MvcResult result) throws Exception {
status().isMovedTemporarily().match(result);
redirectedUrl("http://localhost/login").match(result);
}
};
}
private static ResultMatcher invalidLogin() {
return new ResultMatcher() {
@Override
public void match(MvcResult result) throws Exception {
status().isMovedTemporarily().match(result);
redirectedUrl("/login?error").match(result);
}
};
}
private static ResultMatcher invalidCsrf() {
return new ResultMatcher() {
@Override
public void match(MvcResult result) throws Exception {
status().isForbidden().match(result);
}
};
}
}