/** * personium.io * Copyright 2014 FUJITSU LIMITED * * 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.fujitsu.dc.test.jersey.cell.ctl; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Calendar; import org.apache.http.HttpHeaders; import org.apache.http.HttpStatus; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.junit.After; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.experimental.categories.Category; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fujitsu.dc.common.auth.token.AbstractOAuth2Token.TokenDsigException; import com.fujitsu.dc.common.auth.token.AbstractOAuth2Token.TokenParseException; import com.fujitsu.dc.common.auth.token.AbstractOAuth2Token.TokenRootCrtException; import com.fujitsu.dc.common.auth.token.TransCellAccessToken; import com.fujitsu.dc.core.model.Box; import com.fujitsu.dc.test.categories.Integration; import com.fujitsu.dc.test.categories.Regression; import com.fujitsu.dc.test.categories.Unit; import com.fujitsu.dc.test.jersey.AbstractCase; import com.fujitsu.dc.test.jersey.DcRequest; import com.fujitsu.dc.test.jersey.DcResponse; import com.fujitsu.dc.test.jersey.ODataCommon; import com.fujitsu.dc.test.unit.core.UrlUtils; import com.fujitsu.dc.test.utils.AccountUtils; import com.fujitsu.dc.test.utils.Http; import com.fujitsu.dc.test.utils.ResourceUtils; import com.fujitsu.dc.test.utils.RoleUtils; import com.fujitsu.dc.test.utils.TResponse; /** * Accountの作成のIT. */ @Category({Unit.class, Integration.class, Regression.class }) public class AccountTest extends ODataCommon { /** * ログ用オブジェクト. */ private static Logger log = LoggerFactory.getLogger(AccountTest.class); static String cellName = "cellname"; /** * コンストラクタ. テスト対象のパッケージをsuperに渡す必要がある */ public AccountTest() { super("com.fujitsu.dc.core.rs"); } /** * すべてのテストで必ず1度実行される処理. */ @BeforeClass public static void beforeClass() { // DBサーバーを共有した際、同時にテストを行うと、同じCell名では409となってしまうため、一意にするため、Cell名に時間をセット cellName = cellName + Long.toString(Calendar.getInstance().getTimeInMillis()); log.debug(AccountTest.class.toString() + " BeforeClass:cellName=" + cellName); } /** * すべてのテスト毎に1度実行される処理. */ @Before public void before() { Http.request("cell-create.txt") .with("token", AbstractCase.BEARER_MASTER_TOKEN) .with("cellPath", cellName) .returns(); super.setResponse(null); } /** * すべてのテスト毎に1度実行される処理. */ @After public void after() { } /** * 以下の流れを確認する. Account追加=>参照=>更新. Role追加=>参照=>更新. Account・Role紐付け追加=>参照=>更新. 紐付け削除=>Role削除=>Account削除. * @throws TokenParseException TokenParseException * @throws TokenRootCrtException TokenRootCrtException * @throws TokenDsigException TokenDsigException */ @Test public final void crud() throws TokenParseException, TokenDsigException, TokenRootCrtException { String testAccountName = "test_account"; String testAccountPass = "password"; String accUrl = this.createAccount(testAccountName, testAccountPass); log.debug(accUrl); String testRoleName = "testRole"; String roleUrl = this.createRole(testRoleName); log.debug(roleUrl); // アカウント・ロールの紐付けC Http.request("link-account-role.txt") .with("token", AbstractCase.MASTER_TOKEN_NAME) .with("cellPath", cellName) .with("username", testAccountName) .with("roleUrl", roleUrl) .returns() .statusCode(HttpStatus.SC_NO_CONTENT); // DcRequest req = DcRequest.post(UrlUtils.accountLinks(cellName, testAccountName)); // req.header(HttpHeaders.AUTHORIZATION, MASTER_TOKEN).addJsonBody("uri", roleUrl); // DcResponse res = request(req); // assertEquals(HttpStatus.SC_NO_CONTENT, res.getStatusCode()); // アカウント・ロールの紐付けのR(全件取得) // TODO 一件取得が無いのはバグ。 log.debug("koooooooo"); DcRequest req = DcRequest.get(UrlUtils.accountLinks(cellName, testAccountName)) .header(HttpHeaders.AUTHORIZATION, BEARER_MASTER_TOKEN).header(HttpHeaders.ACCEPT, "application/json"); DcResponse res = request(req); assertEquals(HttpStatus.SC_OK, res.getStatusCode()); JSONObject linkJson = res.bodyAsJson(); JSONArray linksResults = getResultsFromEntitysResponse(linkJson); JSONObject linkJson2 = (JSONObject) linksResults.get(0); assertEquals(roleUrl, linkJson2.get("uri")); // アカウント・ロールの紐付けのU // TODO UPDATEは未実装のためいずれ。。。 // BOX作成 String boxName = "testbox"; String boxSchema = "https://example.com/hogecell/"; createBox2(boxName, boxSchema); // パスワード認証。セルトークン取得。 // grant_type=password&username={username}&password={password} req = DcRequest.post(UrlUtils.auth(cellName)); String authBody = String.format("grant_type=password&username=%s&password=%s", testAccountName, testAccountPass); req.header(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded").addStringBody(authBody); res = request(req); assertEquals(HttpStatus.SC_OK, res.getStatusCode()); JSONObject token = res.bodyAsJson(); assertNotNull(token); // パスワード認証。トランスセルトークン取得 req = DcRequest.post(UrlUtils.auth(cellName)); authBody = String.format("grant_type=password&username=%s&password=%s&dc_target=%s", testAccountName, testAccountPass, "https://example.com/testcell"); req.header(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded").addStringBody(authBody); res = request(req); assertEquals(HttpStatus.SC_OK, res.getStatusCode()); token = res.bodyAsJson(); assertNotNull(token); String accessToken = null; accessToken = (String) token.get("access_token"); assertNotNull(accessToken); TransCellAccessToken tcat = TransCellAccessToken.parse(accessToken); String url = UrlUtils.cellRoot(cellName); assertEquals(testRoleName, tcat.getRoles().get(0).getName()); assertEquals(url + "__role/__/" + testRoleName, tcat.getRoles().get(0).schemeCreateUrl(url)); assertEquals(url, tcat.getIssuer()); assertEquals(url + "#" + testAccountName, tcat.getSubject()); // アカウント・ロールの紐付けのD String roleId = roleUrl.substring(roleUrl.indexOf("'") + 1); roleId = roleId.substring(0, roleId.indexOf("'")); req = DcRequest.delete(UrlUtils.accountLink(cellName, testAccountName, roleId)) .header(HttpHeaders.AUTHORIZATION, BEARER_MASTER_TOKEN); res = request(req); assertEquals(HttpStatus.SC_NO_CONTENT, res.getStatusCode()); // RoleのD req = DcRequest.delete(roleUrl) .header(HttpHeaders.AUTHORIZATION, BEARER_MASTER_TOKEN) .header(HttpHeaders.IF_MATCH, "*"); res = request(req); assertEquals(HttpStatus.SC_NO_CONTENT, res.getStatusCode()); // AccountのD req = DcRequest.delete(accUrl) .header(HttpHeaders.AUTHORIZATION, BEARER_MASTER_TOKEN) .header(HttpHeaders.IF_MATCH, "*"); res = request(req); assertEquals(HttpStatus.SC_NO_CONTENT, res.getStatusCode()); } /** * RoleとLinkされているAccountを削除するとresponseが409であること. */ @Test public final void RoleとLinkされているAccountを削除するとresponseが409であること() { String token = AbstractCase.MASTER_TOKEN_NAME; String accountName = "account"; String pass = "password"; String roleName = "role"; String boxName = null; try { // 準備。アカウント、ロール作ってリンクさせる。 AccountUtils.create(token, cellName, accountName, pass, HttpStatus.SC_CREATED); RoleUtils.create(cellName, token, boxName, roleName, HttpStatus.SC_CREATED); ResourceUtils.linkAccountRole(cellName, token, accountName, boxName, roleName, HttpStatus.SC_NO_CONTENT); // 削除できないことの確認 AccountUtils.delete(cellName, token, accountName, HttpStatus.SC_CONFLICT); // リンクを解除し、削除できるようになることの確認 ResourceUtils.linkAccountRollDelete(cellName, token, accountName, boxName, roleName); AccountUtils.delete(cellName, token, accountName, HttpStatus.SC_NO_CONTENT); } finally { ResourceUtils.linkAccountRollDelete(cellName, token, accountName, boxName, roleName); RoleUtils.delete(accountName, token, boxName, roleName, -1); AccountUtils.delete(cellName, token, accountName, -1); } } /** * アカウントのテスト. * @param name アカウント名 * @param pass パスワード * @return 作成されたAccountのURL */ String createAccount(final String name, final String pass) { // AccountのC TResponse res = Http.request("account-create.txt") .with("token", AbstractCase.MASTER_TOKEN_NAME) .with("cellPath", cellName) .with("username", name) .with("password", pass) .returns(); String accLocHeader = res.getLocationHeader(); String etag = res.getHeader(HttpHeaders.ETAG); // AccountのR res = Http.request("account-retrieve.txt") .with("token", AbstractCase.MASTER_TOKEN_NAME) .with("cellPath", cellName) .with("username", name) .returns() .statusCode(HttpStatus.SC_OK) .contentType("application/json"); JSONObject accountJson = res.bodyAsJson(); accountJson = getResultsFromEntityResponse(accountJson); assertEquals(name, accountJson.get("Name")); assertNotNull(accountJson.get("__published")); assertNotNull(accountJson.get("__updated")); assertEquals(etag, ((JSONObject) accountJson.get("__metadata")).get("etag")); // AccountのU // TODO UPDATEは未実装のためいずれ。。。 return accLocHeader; } /** * ロールを作成するテスト. * @param testRoleName * @return 作成されたRoleのId */ @SuppressWarnings("unchecked") String createRole(final String testRoleName) { // RoleのC JSONObject body = new JSONObject(); body.put("Name", testRoleName); body.put("_Box.Name", null); TResponse res = Http.request("role-create.txt") .with("token", AbstractCase.MASTER_TOKEN_NAME) .with("cellPath", cellName) .with("body", body.toString()) .returns() .statusCode(HttpStatus.SC_CREATED) .inspect(new TResponse.Inspector() { public void inspect(TResponse resp) { } }); String roleLocHeader = res.getLocationHeader(); assertNotNull(roleLocHeader); // RoleのR res = Http.request("role-retrieve.txt") .with("cellPath", cellName) .with("rolename", testRoleName) .with("boxname", "null") .with("token", AbstractCase.MASTER_TOKEN_NAME) .returns() .statusCode(HttpStatus.SC_OK) .contentType("application/json"); JSONObject roleJson = res.bodyAsJson(); roleJson = getResultsFromEntityResponse(roleJson); assertEquals(testRoleName, roleJson.get("Name")); assertNull(roleJson.get("_Box.Name")); assertNotNull(roleJson.get("__published")); assertNotNull(roleJson.get("__updated")); // assertEquals(etag, ((JSONObject) roleJson.get("__metadata")).get("etag")); // RoleのU // TODO UPDATEは未実装のためいずれ。。。 return roleLocHeader; } /** * BOX作成テスト. * @param boxName ボックス名 * @param boxSchema ボックススキーマ * @return boxURL */ protected String createBox2(final String boxName, final String boxSchema) { // BOXのC DcRequest req = DcRequest.post(UrlUtils.cellCtl(cellName, Box.EDM_TYPE_NAME)); req.header(HttpHeaders.AUTHORIZATION, BEARER_MASTER_TOKEN).addJsonBody("Name", boxName); if (boxSchema != null) { req.addJsonBody("Schema", boxSchema); } DcResponse res = request(req); assertEquals(HttpStatus.SC_CREATED, res.getStatusCode()); String url = res.getFirstHeader(HttpHeaders.LOCATION); assertNotNull(url); return url; } /** * ファイルのすべてを読み込む. * @param inputStream 読み込むストリーム * @return バイト配列 */ public byte[] readAll(InputStream inputStream) { ByteArrayOutputStream bout = new ByteArrayOutputStream(); try { byte[] buffer = new byte[1024]; while (true) { int len = inputStream.read(buffer); if (len < 0) { break; } bout.write(buffer, 0, len); } } catch (IOException e) { throw new RuntimeException(e); } return bout.toByteArray(); } /** * @param body * @return results配下のJSONオブジェクト */ private JSONObject getResultsFromEntityResponse(JSONObject body) { assertNotNull(body); JSONObject d = (JSONObject) body.get("d"); assertNotNull(d); JSONObject results = (JSONObject) d.get("results"); assertNotNull(results); return results; } /** * @param body * @return results配下のJSONオブジェクト */ private JSONArray getResultsFromEntitysResponse(JSONObject body) { assertNotNull(body); JSONObject d = (JSONObject) body.get("d"); assertNotNull(d); JSONArray results = (JSONArray) d.get("results"); assertNotNull(results); return results; } }