/**
* The MIT License (MIT)
*
* Copyright (c) 2014-2017 Yegor Bugayenko
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.takes.facets.auth.social;
import java.io.IOException;
import java.net.URI;
import java.util.Arrays;
import javax.json.Json;
import org.apache.commons.lang.RandomStringUtils;
import org.hamcrest.CoreMatchers;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.junit.Test;
import org.takes.Request;
import org.takes.Response;
import org.takes.Take;
import org.takes.facets.auth.Identity;
import org.takes.facets.fork.FkRegex;
import org.takes.facets.fork.TkFork;
import org.takes.http.FtRemote;
import org.takes.misc.Href;
import org.takes.rq.RqFake;
import org.takes.rq.RqHref;
import org.takes.rq.RqPrint;
import org.takes.rs.RsJson;
/**
* Test case for {@link PsLinkedin}.
* @author Dmitry Zaytsev (dmitry.zaytsev@gmail.com)
* @version $Id: 19dc1f0771e2f3073eaf4ebe480f2d96d4f75a61 $
* @since 0.16
*/
public final class PsLinkedinTest {
/**
* PsLinkedin can login.
* @throws IOException If some problem inside
*/
@Test
public void logins() throws IOException {
final String tokenpath = "/uas/oauth2/accessToken";
final String firstname = "firstName";
final String lastname = "lastName";
final String frodo = "Frodo";
final String baggins = "Baggins";
// @checkstyle MagicNumber (4 lines)
final String code = RandomStringUtils.randomAlphanumeric(10);
final String lapp = RandomStringUtils.randomAlphanumeric(10);
final String lkey = RandomStringUtils.randomAlphanumeric(10);
final String identifier = RandomStringUtils.randomAlphanumeric(10);
final Take take = new TkFork(
new FkRegex(
tokenpath,
new TokenTake(code, lapp, lkey, tokenpath)
),
new FkRegex(
"/v1/people",
new PeopleTake(identifier, firstname, lastname, frodo, baggins)
)
);
new FtRemote(take).exec(
new LinkedinScript(
code, lapp, lkey, identifier,
firstname, lastname, frodo, baggins
)
);
}
/**
* Take that returns JSON with the authorization token.
* @author Dmitry Zaytsev (dmitry.zaytsev@gmail.com)
* @author Rui Castro (rui.castro@gmail.com)
* @version $Id: 19dc1f0771e2f3073eaf4ebe480f2d96d4f75a61 $
* @since 1.1
*/
private final class TokenTake implements Take {
/**
* Request path pattern for token endpoint.
*/
private final String tokenpath;
/**
* Linkedin authorization code.
*/
private final String code;
/**
* Linkedin app.
*/
private final String lapp;
/**
* Linkedin key.
*/
private final String lkey;
/**
* Ctor.
* @param code Linkedin authorization code
* @param lapp Linkedin app
* @param lkey Linkedin key
* @param tokenpath Request path for token endpoint
* @checkstyle ParameterNumber (4 lines)
*/
TokenTake(final String code, final String lapp, final String lkey,
final String tokenpath) {
this.code = code;
this.lapp = lapp;
this.lkey = lkey;
this.tokenpath = tokenpath;
}
@Override
public Response act(final Request req) throws IOException {
MatcherAssert.assertThat(
new RqPrint(req).printBody(),
Matchers.stringContainsInOrder(
Arrays.asList(
"grant_type=authorization_code",
String.format("client_id=%s", this.lapp),
"redirect_uri=",
String.format("client_secret=%s", this.lkey),
String.format("code=%s", this.code)
)
)
);
MatcherAssert.assertThat(
new RqHref.Base(req).href().toString(),
Matchers.endsWith(this.tokenpath)
);
return new RsJson(
Json.createObjectBuilder()
.add(
"access_token",
// @checkstyle MagicNumber (1 line)
RandomStringUtils.randomAlphanumeric(10)
).build()
);
}
}
/**
* Take that returns JSON with test user data.
* @author Dmitry Zaytsev (dmitry.zaytsev@gmail.com)
* @author Rui Castro (rui.castro@gmail.com)
* @version $Id: 19dc1f0771e2f3073eaf4ebe480f2d96d4f75a61 $
* @since 1.1
*/
private final class PeopleTake implements Take {
/**
* Linkedin user identifier.
*/
private final String identifier;
/**
* Field name for "First name".
*/
private final String firstname;
/**
* Test value for "First name".
*/
private final String frodo;
/**
* Field name for "Last name".
*/
private final String lastname;
/**
* Test value for "Last name".
*/
private final String baggins;
/**
* Ctor.
* @param identifier Linkedin user identifier
* @param firstname Field name for "First name"
* @param lastname Field name for "Last name"
* @param frodo Test value for "First name"
* @param baggins Test value for "Last name"
* @checkstyle ParameterNumberCheck (4 lines)
*/
PeopleTake(final String identifier,
final String firstname, final String lastname,
final String frodo, final String baggins) {
this.identifier = identifier;
this.firstname = firstname;
this.lastname = lastname;
this.frodo = frodo;
this.baggins = baggins;
}
@Override
public Response act(final Request req) throws IOException {
return new RsJson(
Json.createObjectBuilder()
.add("id", this.identifier)
.add(this.firstname, this.frodo)
.add(this.lastname, this.baggins)
.build()
);
}
}
/**
* Script to test Linkedin authorization.
* @author Dmitry Zaytsev (dmitry.zaytsev@gmail.com)
* @author Rui Castro (rui.castro@gmail.com)
* @version $Id: 19dc1f0771e2f3073eaf4ebe480f2d96d4f75a61 $
* @since 1.1
*/
private final class LinkedinScript implements FtRemote.Script {
/**
* Linkedin authorization code.
*/
private final String code;
/**
* Linkedin app.
*/
private final String lapp;
/**
* Linkedin key.
*/
private final String lkey;
/**
* Linkedin user identifier.
*/
private final String identifier;
/**
* Field name for "First name".
*/
private final String firstname;
/**
* Test value for "First name".
*/
private final String frodo;
/**
* Field name for "Last name".
*/
private final String lastname;
/**
* Test value for "Last name".
*/
private final String baggins;
/**
* Ctor.
* @param code Linkedin authorization code
* @param lapp Linkedin app
* @param lkey Linkedin key
* @param identifier Linkedin user identifier
* @param firstname Field name for "First name"
* @param lastname Field name for "Last name"
* @param frodo Test value for "First name"
* @param baggins Test value for "Last name"
* @checkstyle ParameterNumberCheck (4 lines)
*/
LinkedinScript(final String code, final String lapp,
final String lkey, final String identifier,
final String firstname, final String lastname,
final String frodo, final String baggins) {
this.code = code;
this.lapp = lapp;
this.lkey = lkey;
this.identifier = identifier;
this.firstname = firstname;
this.lastname = lastname;
this.frodo = frodo;
this.baggins = baggins;
}
@Override
public void exec(final URI home) throws IOException {
final Identity identity = new PsLinkedin(
new Href(String.format("%s/uas/oauth2/accessToken", home)),
new Href(String.format("%s/v1/people", home)),
this.lapp,
this.lkey
).enter(new RqFake("GET", String.format("?code=%s", this.code)))
.get();
MatcherAssert.assertThat(
identity.urn(),
CoreMatchers.equalTo(
String.format("urn:linkedin:%s", this.identifier)
)
);
MatcherAssert.assertThat(
identity.properties(),
Matchers.allOf(
Matchers.hasEntry(this.firstname, this.frodo),
Matchers.hasEntry(this.lastname, this.baggins)
)
);
}
}
}