/** * 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.core.rs.box; import java.io.Reader; import javax.ws.rs.DELETE; import javax.ws.rs.HeaderParam; import javax.ws.rs.HttpMethod; import javax.ws.rs.OPTIONS; import javax.ws.rs.Path; import javax.ws.rs.core.Context; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.Response; import org.apache.wink.webdav.WebDAVMethod; import com.fujitsu.dc.common.utils.DcCoreUtils; import com.fujitsu.dc.core.DcCoreException; import com.fujitsu.dc.core.annotations.ACL; import com.fujitsu.dc.core.auth.AccessContext; import com.fujitsu.dc.core.auth.BoxPrivilege; import com.fujitsu.dc.core.auth.OAuth2Helper.AcceptableAuthScheme; import com.fujitsu.dc.core.auth.Privilege; import com.fujitsu.dc.core.model.DavCmp; import com.fujitsu.dc.core.model.DavMoveResource; import com.fujitsu.dc.core.model.DavRsCmp; import com.fujitsu.dc.core.model.jaxb.Acl; import com.fujitsu.dc.core.rs.odata.ODataResource; /** * ODataSvcResourceを担当するJAX-RSリソース. */ public final class ODataSvcCollectionResource extends ODataResource { // DavCollectionResourceとしての機能を使うためこれをWRAPしておく。 DavRsCmp davRsCmp; /** * constructor. * @param parent DavRsCmp * @param davCmp DavCmp */ public ODataSvcCollectionResource(final DavRsCmp parent, final DavCmp davCmp) { super(parent.getAccessContext(), parent.getUrl() + davCmp.getName() + "/", davCmp.getODataProducer()); this.davRsCmp = new DavRsCmp(parent, davCmp); } /** * PROPFINDの処理. * @param requestBodyXml リクエストボディ * @param depth Depthヘッダ * @param contentLength Content-Length ヘッダ * @param transferEncoding Transfer-Encoding ヘッダ * @return JAX-RS Response */ @WebDAVMethod.PROPFIND public Response propfind(final Reader requestBodyXml, @HeaderParam(DcCoreUtils.HttpHeaders.DEPTH) final String depth, @HeaderParam(HttpHeaders.CONTENT_LENGTH) final Long contentLength, @HeaderParam("Transfer-Encoding") final String transferEncoding) { return this.davRsCmp.doPropfind(requestBodyXml, depth, contentLength, transferEncoding, BoxPrivilege.READ_PROPERTIES, BoxPrivilege.READ_ACL); } /** * PROPPATCHの処理. * @param requestBodyXml リクエストボディ * @return JAX-RS Response */ @WebDAVMethod.PROPPATCH public Response proppatch(final Reader requestBodyXml) { // アクセス制御 this.checkAccessContext( this.davRsCmp.getAccessContext(), BoxPrivilege.WRITE_PROPERTIES); return this.davRsCmp.doProppatch(requestBodyXml); } /** * ACLメソッドの処理. ACLの設定を行う. * @param reader 設定XML * @return JAX-RS Response */ @ACL public Response acl(final Reader reader) { // アクセス制御 this.checkAccessContext(this.getAccessContext(), BoxPrivilege.WRITE_ACL); return this.davRsCmp.getDavCmp().acl(reader).build(); } /** * DELETEメソッドを処理してこのリソースを削除します. * @return JAX-RS応答オブジェクト */ @DELETE public Response delete() { // アクセス制御 // ODataSvcCollectionResourceは必ず親(最上位はBox)を持つため、this.davRsCmp.getParent()の結果がnullになることはない this.davRsCmp.getParent().checkAccessContext(this.getAccessContext(), BoxPrivilege.WRITE); // ODataのスキーマ・データがすでにある場合、処理を失敗させる。 if (!this.davRsCmp.getDavCmp().isEmpty()) { throw DcCoreException.Dav.HAS_CHILDREN; } return this.davRsCmp.getDavCmp().delete(null, false).build(); } /** * OPTIONSメソッド. * @return JAX-RS Response */ @Override @OPTIONS public Response optionsRoot() { // アクセス制御 this.checkAccessContext(this.getAccessContext(), BoxPrivilege.READ); return DcCoreUtils.responseBuilderForOptions( HttpMethod.GET, HttpMethod.DELETE, DcCoreUtils.HttpMethod.MOVE, DcCoreUtils.HttpMethod.PROPFIND, DcCoreUtils.HttpMethod.PROPPATCH, DcCoreUtils.HttpMethod.ACL ).build(); } /** * MOVEメソッドの処理. * @param headers ヘッダ情報 * @return JAX-RS応答オブジェクト */ @WebDAVMethod.MOVE public Response move( @Context HttpHeaders headers) { // 移動元に対するアクセス制御(親の権限をチェックする) this.davRsCmp.getParent().checkAccessContext(this.davRsCmp.getAccessContext(), BoxPrivilege.WRITE); return new DavMoveResource(this.davRsCmp.getParent(), this.davRsCmp.getDavCmp(), headers).doMove(); } @Override public void checkAccessContext(AccessContext ac, Privilege privilege) { this.davRsCmp.checkAccessContext(ac, privilege); } /** * 認証に使用できるAuth Schemeを取得する. * @return 認証に使用できるAuth Scheme */ @Override public AcceptableAuthScheme getAcceptableAuthScheme() { return this.davRsCmp.getAcceptableAuthScheme(); } /** * アクセスコンテキストが$batchしてよい権限を持っているかを返す. * @param ac アクセスコンテキスト * @return true: アクセスコンテキストが$batchしてよい権限を持っている */ @Override public boolean hasPrivilegeForBatch(AccessContext ac) { Acl acl = this.davRsCmp.getDavCmp().getAcl(); String url = this.davRsCmp.getCell().getUrl(); if (ac.requirePrivilege(acl, BoxPrivilege.READ, url)) { return true; } if (ac.requirePrivilege(acl, BoxPrivilege.WRITE, url)) { return true; } return false; } @Override public boolean hasPrivilege(AccessContext ac, Privilege privilege) { return this.davRsCmp.hasPrivilege(ac, privilege); } @Override public void checkSchemaAuth(AccessContext ac) { ac.checkSchemaAccess(this.davRsCmp.getConfidentialLevel(), this.davRsCmp.getBox(), getAcceptableAuthScheme()); } /** * basic認証できるかチェックする. * @param ac アクセスコンテキスト */ public void setBasicAuthenticateEnableInBatchRequest(AccessContext ac) { ac.updateBasicAuthenticationStateForResource(this.davRsCmp.getBox()); } /** * サービスメタデータリクエストに対応する. * @return JAX-RS 応答オブジェクト */ @Path("{first: \\$}metadata") public ODataSvcSchemaResource metadata() { return new ODataSvcSchemaResource(this.davRsCmp, this); } @Override public Privilege getNecessaryReadPrivilege(String entitySetNameStr) { return BoxPrivilege.READ; } @Override public Privilege getNecessaryWritePrivilege(String entitySetNameStr) { return BoxPrivilege.WRITE; } @Override public Privilege getNecessaryOptionsPrivilege() { return BoxPrivilege.READ; } }