Skip to content

Commit b3fed9c

Browse files
author
Jerjou Cheng
committed
More firetactoe tests. Enforce login in web.xml
1 parent a905ee8 commit b3fed9c

File tree

9 files changed

+483
-43
lines changed

9 files changed

+483
-43
lines changed

appengine/firebase-tictactoe/src/main/java/com/example/appengine/firetactoe/DeleteServlet.java

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ public void doPost(HttpServletRequest request, HttpServletResponse response)
4141
UserService userService = UserServiceFactory.getUserService();
4242
String currentUserId = userService.getCurrentUser().getUserId();
4343

44+
// TODO(you): In practice, first validate that the user has permission to delete the Game
4445
game.deleteChannel(currentUserId);
4546
}
4647
}

appengine/firebase-tictactoe/src/main/java/com/example/appengine/firetactoe/MoveServlet.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public void doPost(HttpServletRequest request, HttpServletResponse response)
4444

4545
int cell = new Integer(request.getParameter("cell"));
4646
if (!game.makeMove(cell, currentUserId)) {
47-
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
47+
response.sendError(HttpServletResponse.SC_FORBIDDEN);
4848
} else {
4949
ofy.save().entity(game).now();
5050
}

appengine/firebase-tictactoe/src/main/java/com/example/appengine/firetactoe/OpenedServlet.java

+3-13
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
package com.example.appengine.firetactoe;
1818

19-
import com.googlecode.objectify.NotFoundException;
2019
import com.googlecode.objectify.Objectify;
2120
import com.googlecode.objectify.ObjectifyService;
2221

@@ -32,19 +31,10 @@ public class OpenedServlet extends HttpServlet {
3231
@Override
3332
public void doPost(HttpServletRequest request, HttpServletResponse response)
3433
throws IOException {
34+
// TODO(you): In practice, you should validate the user has permission to post to the given Game
3535
String gameId = request.getParameter("gameKey");
3636
Objectify ofy = ObjectifyService.ofy();
37-
try {
38-
Game game = ofy.load().type(Game.class).id(gameId).safe();
39-
if (gameId != null && request.getUserPrincipal() != null) {
40-
game.sendUpdateToClients();
41-
response.setContentType("text/plain");
42-
response.getWriter().println("ok");
43-
} else {
44-
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
45-
}
46-
} catch (NotFoundException e) {
47-
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
48-
}
37+
Game game = ofy.load().type(Game.class).id(gameId).safe();
38+
game.sendUpdateToClients();
4939
}
5040
}

appengine/firebase-tictactoe/src/main/java/com/example/appengine/firetactoe/TicTacToeServlet.java

+1-8
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
package com.example.appengine.firetactoe;
1818

19-
import com.google.appengine.api.users.UserService;
2019
import com.google.appengine.api.users.UserServiceFactory;
2120
import com.google.gson.Gson;
2221
import com.googlecode.objectify.Objectify;
@@ -60,18 +59,12 @@ private String getGameUriWithGameParam(HttpServletRequest request, String gameKe
6059
@Override
6160
public void doGet(HttpServletRequest request, HttpServletResponse response)
6261
throws ServletException, IOException {
63-
final UserService userService = UserServiceFactory.getUserService();
6462
String gameKey = request.getParameter("gameKey");
65-
if (userService.getCurrentUser() == null) {
66-
response.getWriter().println("<p>Please <a href=\"" + userService.createLoginURL(
67-
getGameUriWithGameParam(request, gameKey)) + "\">sign in</a>.</p>");
68-
return;
69-
}
7063

7164
// 1. Create or fetch a Game object from the datastore
7265
Objectify ofy = ObjectifyService.ofy();
7366
Game game = null;
74-
String userId = userService.getCurrentUser().getUserId();
67+
String userId = UserServiceFactory.getUserService().getCurrentUser().getUserId();
7568
if (gameKey != null) {
7669
game = ofy.load().type(Game.class).id(gameKey).now();
7770
if (null == game) {

appengine/firebase-tictactoe/src/main/webapp/WEB-INF/web.xml

+9
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,15 @@ http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
2121
<welcome-file-list>
2222
<welcome-file>index</welcome-file>
2323
</welcome-file-list>
24+
<security-constraint>
25+
<web-resource-collection>
26+
<web-resource-name>entire-app</web-resource-name>
27+
<url-pattern>/*</url-pattern>
28+
</web-resource-collection>
29+
<auth-constraint>
30+
<role-name>*</role-name>
31+
</auth-constraint>
32+
</security-constraint>
2433
<servlet>
2534
<servlet-name>TicTacToeServlet</servlet-name>
2635
<servlet-class>com.example.appengine.firetactoe.TicTacToeServlet</servlet-class>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
/*
2+
* Copyright 2016 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.appengine.firetactoe;
18+
19+
import static com.google.common.truth.Truth.assertThat;
20+
import static org.junit.Assert.fail;
21+
import static org.mockito.Mockito.eq;
22+
import static org.mockito.Mockito.spy;
23+
import static org.mockito.Mockito.times;
24+
import static org.mockito.Mockito.verify;
25+
import static org.mockito.Mockito.when;
26+
27+
import com.google.api.client.http.LowLevelHttpRequest;
28+
import com.google.api.client.http.LowLevelHttpResponse;
29+
import com.google.api.client.testing.http.MockHttpTransport;
30+
import com.google.api.client.testing.http.MockLowLevelHttpRequest;
31+
import com.google.api.client.testing.http.MockLowLevelHttpResponse;
32+
import com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig;
33+
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
34+
import com.google.appengine.tools.development.testing.LocalURLFetchServiceTestConfig;
35+
import com.google.appengine.tools.development.testing.LocalUserServiceTestConfig;
36+
import com.google.common.collect.ImmutableMap;
37+
import com.googlecode.objectify.Objectify;
38+
import com.googlecode.objectify.ObjectifyFactory;
39+
import com.googlecode.objectify.ObjectifyService;
40+
import com.googlecode.objectify.util.Closeable;
41+
import org.junit.After;
42+
import org.junit.Before;
43+
import org.junit.BeforeClass;
44+
import org.junit.Test;
45+
import org.junit.runner.RunWith;
46+
import org.junit.runners.JUnit4;
47+
import org.mockito.Matchers;
48+
import org.mockito.Mock;
49+
import org.mockito.MockitoAnnotations;
50+
51+
import java.io.ByteArrayInputStream;
52+
import java.io.IOException;
53+
import java.util.HashMap;
54+
import javax.servlet.http.HttpServletRequest;
55+
import javax.servlet.http.HttpServletResponse;
56+
57+
/**
58+
* Unit tests for {@link DeleteServlet}.
59+
*/
60+
@RunWith(JUnit4.class)
61+
public class DeleteServletTest {
62+
private static final String USER_EMAIL = "[email protected]";
63+
private static final String USER_ID = "whiskytangofoxtrot";
64+
private static final String FIREBASE_DB_URL = "http://firebase.com/dburl";
65+
66+
private final LocalServiceTestHelper helper =
67+
new LocalServiceTestHelper(
68+
// Set no eventual consistency, that way queries return all results.
69+
// http://g.co/cloud/appengine/docs/java/tools/localunittesting#Java_Writing_High_Replication_Datastore_tests
70+
new LocalDatastoreServiceTestConfig().setDefaultHighRepJobPolicyUnappliedJobPercentage(0),
71+
new LocalUserServiceTestConfig(),
72+
new LocalURLFetchServiceTestConfig()
73+
)
74+
.setEnvEmail(USER_EMAIL)
75+
.setEnvAuthDomain("gmail.com")
76+
.setEnvAttributes(new HashMap(
77+
ImmutableMap.of("com.google.appengine.api.users.UserService.user_id_key", USER_ID)));
78+
79+
@Mock private HttpServletRequest mockRequest;
80+
@Mock private HttpServletResponse mockResponse;
81+
protected Closeable dbSession;
82+
83+
private DeleteServlet servletUnderTest;
84+
85+
@BeforeClass
86+
public static void setUpBeforeClass() {
87+
// Reset the Factory so that all translators work properly.
88+
ObjectifyService.setFactory(new ObjectifyFactory());
89+
ObjectifyService.register(Game.class);
90+
// Mock out the firebase config
91+
FirebaseChannel.firebaseConfigStream = new ByteArrayInputStream(
92+
String.format("databaseURL: \"%s\"", FIREBASE_DB_URL).getBytes());
93+
}
94+
95+
@Before
96+
public void setUp() throws Exception {
97+
MockitoAnnotations.initMocks(this);
98+
helper.setUp();
99+
dbSession = ObjectifyService.begin();
100+
101+
servletUnderTest = new DeleteServlet();
102+
103+
helper.setEnvIsLoggedIn(true);
104+
// Make sure there are no firebase requests if we don't expect it
105+
FirebaseChannel.getInstance().httpTransport = null;
106+
}
107+
108+
@After
109+
public void tearDown() {
110+
dbSession.close();
111+
helper.tearDown();
112+
}
113+
114+
@Test
115+
public void doPost_noGameKey() throws Exception {
116+
try {
117+
servletUnderTest.doPost(mockRequest, mockResponse);
118+
fail("Should not succeed with no gameKey specified.");
119+
} catch (IllegalArgumentException e) {
120+
assertThat(e.getMessage()).startsWith("id 'null'");
121+
}
122+
}
123+
124+
@Test
125+
public void doPost_deleteGame() throws Exception {
126+
// Insert a game
127+
Objectify ofy = ObjectifyService.ofy();
128+
Game game = new Game(USER_ID, "my-opponent", " ", true);
129+
ofy.save().entity(game).now();
130+
String gameKey = game.getId();
131+
when(mockRequest.getParameter("gameKey")).thenReturn(gameKey);
132+
133+
// Mock out the firebase response. See
134+
// http://g.co/dv/api-client-library/java/google-http-java-client/unit-testing
135+
MockHttpTransport mockHttpTransport = spy(new MockHttpTransport() {
136+
@Override
137+
public LowLevelHttpRequest buildRequest(String method, String url) throws IOException {
138+
return new MockLowLevelHttpRequest() {
139+
@Override
140+
public LowLevelHttpResponse execute() throws IOException {
141+
MockLowLevelHttpResponse response = new MockLowLevelHttpResponse();
142+
response.setStatusCode(200);
143+
return response;
144+
}
145+
};
146+
}
147+
});
148+
FirebaseChannel.getInstance().httpTransport = mockHttpTransport;
149+
150+
servletUnderTest.doPost(mockRequest, mockResponse);
151+
152+
verify(mockHttpTransport, times(1)).buildRequest(
153+
eq("DELETE"), Matchers.matches(FIREBASE_DB_URL + "/channels/[\\w-]+.json$"));
154+
}
155+
}

0 commit comments

Comments
 (0)