package org.rapidoid.http; /* * #%L * rapidoid-integration-tests * %% * Copyright (C) 2014 - 2017 Nikolche Mihajlovski and contributors * %% * 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. * #L% */ import org.junit.Test; import org.rapidoid.annotation.Authors; import org.rapidoid.annotation.Since; import org.rapidoid.commons.Err; import org.rapidoid.commons.Rnd; import org.rapidoid.ctx.Contextual; import org.rapidoid.security.Role; import org.rapidoid.setup.On; import org.rapidoid.u.U; import org.rapidoid.util.Msc; import java.util.List; @Authors("Nikolche Mihajlovski") @Since("5.1.0") public class HttpLoginTest extends IsolatedIntegrationTest { volatile boolean ready = false; @Test public void testLogin() { On.get("/user").json(() -> U.list(Contextual.username(), Contextual.roles())); On.get("/profile").roles(Role.LOGGED_IN).json(Contextual::username); On.post("/mylogin").json((Resp resp, String user, String pass) -> { boolean success = resp.login(user, pass); return U.list(success, Contextual.username(), Contextual.roles()); }); On.post("/mylogout").json((Resp resp, String user, String pass) -> { resp.logout(); return U.list(Contextual.username(), Contextual.roles()); }); ready = true; multiThreaded(150, Msc.normalOrHeavy(1500, 15000), this::randomUserLogin); } private void randomUserLogin() { while (!ready) U.sleep(100); // wait switch (Rnd.rnd(4)) { case 0: loginFlow("foo", "bar", U.list()); break; case 1: loginFlow("abc", "abc", U.list("guest")); break; case 2: loginFlow("chuck", "chuck", U.list("moderator", "restarter")); break; case 3: loginFlow("niko", "easy", U.list("owner", "administrator", "moderator")); break; default: throw Err.notExpected(); } } private void loginFlow(String user, String pass, List<String> expectedRoles) { HttpClient anonymous = HTTP.client().reuseConnections(true); HttpClient client = HTTP.client().keepCookies(true).reuseConnections(true); List<Object> notLoggedIn = U.list(false, null, U.list()); List<Object> loggedIn = U.list(true, user, expectedRoles); eq(client.get(localhost("/user")).parse(), U.list(null, U.list())); verifyAccessDenied(client); eq(client.post(localhost("/mylogin?user=a1&pass=b")).parse(), notLoggedIn); eq(client.post(localhost("/mylogin?user=a2&pass=b")).parse(), notLoggedIn); verifyAccessDenied(client); eq(client.post(localhost(U.frmt("/mylogin?user=%s&pass=%s", user, pass))).parse(), loggedIn); verifyAccessDenied(anonymous); verifyAccessGranted(user, client); eq(client.get(localhost("/user")).parse(), U.list(user, expectedRoles)); verifyAccessDenied(anonymous); verifyAccessGranted(user, client); eq(client.post(localhost("/mylogin?user=a3&pass=b")).parse(), U.list(false, user, expectedRoles)); verifyAccessDenied(anonymous); verifyAccessGranted(user, client); eq(client.get(localhost("/user")).parse(), U.list(user, expectedRoles)); eq(client.post(localhost("/mylogout")).parse(), U.list(null, U.list())); verifyAccessDenied(anonymous); verifyLoggedOut(client); eq(client.get(localhost("/user")).parse(), U.list(null, U.list())); eq(client.get(localhost("/user")).parse(), U.list(null, U.list())); verifyLoggedOut(client); client.close(); anonymous.close(); } private void verifyAccessGranted(String user, HttpClient client) { verify("granted-" + user, fetch(client, "get", "/profile").replaceAll("_token=.*?;", "_token=...;")); } private void verifyAccessDenied(HttpClient client) { verify("denied", fetch(client, "get", "/profile")); } private void verifyLoggedOut(HttpClient client) { verify("logout", fetch(client, "get", "/profile")); } }