diff --git a/appengine-java21/ee8/users/README.md b/appengine-java21/ee8/users/README.md new file mode 100644 index 00000000000..e8a3c04aa60 --- /dev/null +++ b/appengine-java21/ee8/users/README.md @@ -0,0 +1,23 @@ +# Users Authentication sample for Google App Engine + + +Open in Cloud Shell + +This sample demonstrates how to use the [Users API][appid] on [Google App +Engine][ae-docs]. + +[appid]: https://cloud.google.com/appengine/docs/java/users/ +[ae-docs]: https://cloud.google.com/appengine/docs/java/ + +## Running locally +This example uses the +[Maven gcloud plugin](https://cloud.google.com/appengine/docs/legacy/standard/java/using-maven). +To run this sample locally: + + $ mvn appengine:run + +## Deploying +In the following command, replace YOUR-PROJECT-ID with your +[Google Cloud Project ID](https://developers.google.com/console/help/new/#projectnumber). + + $ mvn clean package appengine:deploy diff --git a/appengine-java21/ee8/users/pom.xml b/appengine-java21/ee8/users/pom.xml new file mode 100644 index 00000000000..3c65115463e --- /dev/null +++ b/appengine-java21/ee8/users/pom.xml @@ -0,0 +1,133 @@ + + + + 4.0.0 + war + 1.0-SNAPSHOT + com.example.appengine + appengine-users-j21 + + + + com.google.cloud.samples + shared-configuration + 1.2.0 + + + 21 + 21 + + + + + + libraries-bom + com.google.cloud + import + pom + 26.28.0 + + + + + + + com.google.appengine + appengine-api-1.0-sdk + 2.0.39 + + + + jakarta.servlet + jakarta.servlet-api + 4.0.4 + jar + provided + + + + + junit + junit + 4.13.2 + test + + + org.mockito + mockito-core + 4.11.0 + test + + + com.google.appengine + appengine-testing + 2.0.39 + test + + + com.google.appengine + appengine-api-stubs + 2.0.39 + test + + + com.google.appengine + appengine-tools-sdk + 2.0.39 + test + + + com.google.truth + truth + 1.4.4 + test + + + + + + ${project.build.directory}/${project.build.finalName}/WEB-INF/classes + + + org.apache.maven.plugins + maven-war-plugin + 3.4.0 + + + org.jacoco + jacoco-maven-plugin + 0.8.13 + + + com.google.cloud.tools + appengine-maven-plugin + 2.5.0 + + GCLOUD_CONFIG + GCLOUD_CONFIG + true + true + + + + + diff --git a/appengine-java21/ee8/users/src/main/java/com/example/appengine/users/UsersServlet.java b/appengine-java21/ee8/users/src/main/java/com/example/appengine/users/UsersServlet.java new file mode 100644 index 00000000000..11a5aafd91b --- /dev/null +++ b/appengine-java21/ee8/users/src/main/java/com/example/appengine/users/UsersServlet.java @@ -0,0 +1,58 @@ +/* Copyright 2016 Google LLC + * + * 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. + */ + +// [START gae_java21_users_api] + +package com.example.appengine.users; + +import com.google.appengine.api.users.UserService; +import com.google.appengine.api.users.UserServiceFactory; +import java.io.IOException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +// With @WebServlet annotation the webapp/WEB-INF/web.xml is no longer required. +@WebServlet( + name = "UserAPI", + description = "UserAPI: Login / Logout with UserService", + urlPatterns = "/userapi" +) +public class UsersServlet extends HttpServlet { + + @Override + public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { + UserService userService = UserServiceFactory.getUserService(); + + String thisUrl = req.getRequestURI(); + + resp.setContentType("text/html"); + if (req.getUserPrincipal() != null) { + resp.getWriter() + .println( + "

Hello, " + + req.getUserPrincipal().getName() + + "! You can sign out.

"); + } else { + resp.getWriter() + .println( + "

Please sign in.

"); + } + } +} +// [END gae_java21_users_api] diff --git a/appengine-java21/ee8/users/src/main/webapp/WEB-INF/appengine-web.xml b/appengine-java21/ee8/users/src/main/webapp/WEB-INF/appengine-web.xml new file mode 100644 index 00000000000..71f00b07474 --- /dev/null +++ b/appengine-java21/ee8/users/src/main/webapp/WEB-INF/appengine-web.xml @@ -0,0 +1,8 @@ + + + java21 + + + + true + diff --git a/appengine-java21/ee8/users/src/main/webapp/WEB-INF/web.xml b/appengine-java21/ee8/users/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000000..5fece3ce81b --- /dev/null +++ b/appengine-java21/ee8/users/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,26 @@ + + + + + userapi + + true + diff --git a/appengine-java21/ee8/users/src/test/java/com/example/appengine/users/UsersServletTest.java b/appengine-java21/ee8/users/src/test/java/com/example/appengine/users/UsersServletTest.java new file mode 100644 index 00000000000..e7195d3f2f2 --- /dev/null +++ b/appengine-java21/ee8/users/src/test/java/com/example/appengine/users/UsersServletTest.java @@ -0,0 +1,109 @@ +/* + * Copyright 2015 Google LLC + * + * 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 com.example.appengine.users; + +import static com.google.common.truth.Truth.assertWithMessage; +import static org.mockito.Mockito.when; + +import com.google.appengine.tools.development.testing.LocalServiceTestHelper; +import java.io.PrintWriter; +import java.io.StringWriter; +import javax.management.remote.JMXPrincipal; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** + * Unit tests for {@link UsersServlet}. + */ +@RunWith(JUnit4.class) +public class UsersServletTest { + + private static final String FAKE_URL = "fakey.fake.fak"; + private static final String FAKE_NAME = "Fake"; + // Set up a helper so that the ApiProxy returns a valid environment for local testing. + private final LocalServiceTestHelper helper = new LocalServiceTestHelper(); + + @Mock + private HttpServletRequest mockRequestNotLoggedIn; + @Mock + private HttpServletRequest mockRequestLoggedIn; + @Mock + private HttpServletResponse mockResponse; + private StringWriter responseWriter; + private UsersServlet servletUnderTest; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.openMocks(this); + helper.setUp(); + + // Set up some fake HTTP requests + // If the user isn't logged in, use this request + when(mockRequestNotLoggedIn.getRequestURI()).thenReturn(FAKE_URL); + when(mockRequestNotLoggedIn.getUserPrincipal()).thenReturn(null); + + // If the user is logged in, use this request + when(mockRequestLoggedIn.getRequestURI()).thenReturn(FAKE_URL); + // Most of the classes that implement Principal have been + // deprecated. JMXPrincipal seems like a safe choice. + when(mockRequestLoggedIn.getUserPrincipal()).thenReturn(new JMXPrincipal(FAKE_NAME)); + + // Set up a fake HTTP response. + responseWriter = new StringWriter(); + when(mockResponse.getWriter()).thenReturn(new PrintWriter(responseWriter)); + + servletUnderTest = new UsersServlet(); + } + + @After + public void tearDown() { + helper.tearDown(); + } + + @Test + public void doGet_userNotLoggedIn_writesResponse() throws Exception { + servletUnderTest.doGet(mockRequestNotLoggedIn, mockResponse); + + // If a user isn't logged in, we expect a prompt + // to login to be returned. + assertWithMessage("UsersServlet response") + .that(responseWriter.toString()) + .contains("

Please .

"); + } + + @Test + public void doGet_userLoggedIn_writesResponse() throws Exception { + servletUnderTest.doGet(mockRequestLoggedIn, mockResponse); + + // If a user is logged in, we expect a prompt + // to logout to be returned. + assertWithMessage("UsersServlet response") + .that(responseWriter.toString()) + .contains("

Hello, " + FAKE_NAME + "!"); + assertWithMessage("UsersServlet response").that(responseWriter.toString()).contains("sign out"); + } +}