Commits

Anonymous committed 69572c0 Merge

merge

Comments (0)

Files changed (4)

client_lib/jiak.py

         if Resp.status == Status:
             return json.loads(Resp.read())
         raise JiakException(Resp.status, Resp.reason, Resp.read())
-    def set_bucket_schema(self, Bucket, allowed_fields, required_fields,
-                                        write_mask, read_mask):
+    def set_bucket_schema(self, Bucket, allowed_fields,
+                write_mask=None, read_mask=None, required_fields=None):
+        if required_fields == None: required_fields = []
+        if write_mask == None: write_mask = allowed_fields
+        if read_mask == None: read_mask = allowed_fields
         Body = json.dumps({'schema': {'allowed_fields': allowed_fields,
                                       'required_fields': required_fields,
                                       'write_mask': write_mask,

src/jiak_object.erl

             [{M,V}] -> {M,V};
             Multiple ->
                 Bucket = riak_object:bucket(RiakObject),
-                Bucket:merge_siblings(Multiple)
+                BucketMod = jiak_util:jiak_module_for_bucket(Bucket),
+                BucketMod:merge_siblings(Multiple)
         end,
     {struct, J0} = new(riak_object:bucket(RiakObject),
                        riak_object:key(RiakObject),

src/jiak_resource.erl

 %%            a new, server-generated key.  Response will be empty (unless
 %%            returnbody=true is specified in the query parameters) with
 %%            the Location header set to the new object's URI.
+%%
+%%</dd><dt> PUT /JiakBase/Bucket
+%%</dt><dd>   Create or update the schema for a bucket.  The request body 
+%%            must be a JSON object of the form:
+%%            {"schema":{
+%%                      "allowed_fields":["FieldName1","FieldName2",...],
+%%                      "required_fields":["FieldName1",...],
+%%                      "write_mask":["FieldName1",...],
+%%                      "read_mask":["FieldName1",...]
+%%                     }
+%%            }
 %%</dd></dl>
 -module(jiak_resource).
 
          apply_read_mask/1,
          pretty_print/2]).
 
--define(JIAK_REQUIRED_PROPS, [allowed_fields, required_fields, read_mask,
-                              write_mask]).
-
 %% @type context() = term()
 %% @type jiak_module() = atom()|{jiak_default, list()}
 -record(ctx, {bucket,       %% atom() - Bucket name (from uri)
               key=proplists:get_value(key_type, Props),
               jiak_client=JiakClient}}.
 
-default_jiak_module(BucketName) when is_atom(BucketName) ->
-    BucketProps = riak_bucket:get_bucket(BucketName),
-    case lists:filter(
-           fun(I) -> 
-                   proplists:get_value(I, BucketProps) =:= undefined
-           end, 
-           ?JIAK_REQUIRED_PROPS) of
-        [] ->
-            jiak_default:new(BucketProps);
-        _ ->
-            undefined
-    end.
-
-get_jiak_module(ReqData) ->
-    case bucket_from_uri(ReqData) of
-        {ok, Bucket} when is_atom(Bucket) ->
-            jiak_module_for_bucket(Bucket);
-        {error, no_such_bucket} -> 
-            undefined
-    end.
-
-jiak_module_for_bucket(Bucket) when is_atom(Bucket) ->
-    case code:which(Bucket) of
-        non_existing ->
-            case default_jiak_module(Bucket) of
-                undefined -> undefined;
-                Mod when is_tuple(Mod) -> Mod
-            end;
-        ModPath when is_list(ModPath) -> Bucket
-    end.
-
 %% @spec service_available(webmachine:wrq(), context()) -> 
 %%           {boolean, webmachine:wrq(), context()}
 %% @doc Ensure that a Jiak module for the requested bucket is available. 
                 Mod = jiak_default:new([]),
                 {true, Context#ctx{module=Mod, key=schema}};
             _ ->
-                case get_jiak_module(ReqData) of
+                case jiak_util:get_jiak_module(ReqData) of
                     undefined -> {false, Context#ctx{module=no_module_found}};
                     Module -> {true, Context#ctx{module=Module}}
                 end
     {ServiceAvailable, ReqData, NewCtx};
 service_available(ReqData, Context) ->
     {ServiceAvailable, NewCtx} = 
-        case get_jiak_module(ReqData) of
+        case jiak_util:get_jiak_module(ReqData) of
             undefined -> {false, Context#ctx{module=no_module_found}};
             Module -> {true, Context#ctx{module=Module}}
         end,
 %%          {[http_method()], webmachine:wrq(), context()}
 %% @type http_method() = 'HEAD'|'GET'|'POST'|'PUT'|'DELETE'
 %% @doc Determine the list of HTTP methods that can be used on this
-%%      resource.  Should be HEAD/GET/POST for buckets and
+%%      resource.  Should be HEAD/GET/POST/PUT for buckets and
 %%      HEAD/GET/POST/PUT/DELETE for objects.
 %%      Exception: HEAD/GET is returned for an "unknown" bucket.
 allowed_methods(RD, Ctx0=#ctx{module=Mod}) ->
               schema -> schema;
               _         -> list_to_binary(wrq:path_info(key, RD))
           end,
-    case bucket_from_uri(RD) of
+    case jiak_util:bucket_from_uri(RD) of
         {ok, Bucket} ->
             {ok, JC} = Mod:init(Key, jiak_context:new(not_diffed_yet, [])),
             Ctx = Ctx0#ctx{bucket=Bucket, key=Key, jiak_context=JC},
             {['HEAD', 'GET', 'PUT'], RD, Ctx0#ctx{bucket={error, no_such_bucket}}}
     end.
 
-%% @spec bucket_from_uri(webmachine:wrq()) ->
-%%         {ok, atom()}|{error, no_such_bucket}
-%% @doc Extract the bucket name, as an atom, from the request URI.
-%%      The bucket name must be an existing atom, or this function
-%%      will return {error, no_such_bucket}
-bucket_from_uri(RD) ->
-    try {ok, list_to_existing_atom(wrq:path_info(bucket, RD))}
-    catch _:_ -> {error, no_such_bucket} end.
-
 %% @spec malformed_request(webmachine:wrq(), context()) ->
 %%          {boolean(), webmachine:wrq(), context()}
 %% @doc Determine whether the request is propertly constructed.
 %%          bucket component of the URI
 %%        - the "key" field of the object does not match the
 %%          key component of the URI
-
+%%        - when PUTing to a bucket schema, the schema is not of the
+%%          form described above. 
 malformed_request(ReqData, Context=#ctx{key=schema}) ->
     case decode_object(wrq:req_body(ReqData)) of
         {ok, _SchemaObj={struct, SchemaPL0}} ->
             ReqProps = [list_to_binary(atom_to_list(P)) || 
-                           P <- ?JIAK_REQUIRED_PROPS],
+                           P <- jiak_util:jiak_required_props()],
             {struct, SchemaPL} = proplists:get_value(<<"schema">>,SchemaPL0),
             case lists:filter(
                    fun(I) -> 
 %% @doc For an object GET/PUT/POST or a bucket POST, check to see
 %%      whether the write request violates the write mask of the
 %%      bucket.  For a bucket GET, check to see whether the keys of
-%%      the bucket are listable.
+%%      the bucket are listable.  PUT requests to bucket schemas are
+%%      always accepted.
 forbidden(ReqData, Context=#ctx{key=schema}) ->
     %% PUTs to container are for setting schemas and therefore always
     %% allowed
 %%      calls apply_read_mask/2.
 apply_read_mask(JiakObject={struct,_}) ->
     Bucket = jiak_object:bucket(JiakObject),
-    apply_read_mask(jiak_module_for_bucket(Bucket), JiakObject).
+    apply_read_mask(jiak_util:jiak_module_for_bucket(Bucket), JiakObject).
 
 %% @spec apply_read_mask(jiak_module(), jiak_object()) -> jiak_object()
 %% @doc Remove fields from the jiak object that are not in the

src/jiak_util.erl

+-module(jiak_util).
+-export([jiak_required_props/0,
+         jiak_module_for_bucket/1, 
+         get_jiak_module/1, 
+         default_jiak_module/1,
+         bucket_from_uri/1]).
+
+%% @private
+jiak_required_props() -> [allowed_fields,required_fields,read_mask,write_mask].
+
+%% @private
+default_jiak_module(BucketName) when is_atom(BucketName) ->
+    BucketProps = riak_bucket:get_bucket(BucketName),
+    case lists:filter(
+           fun(I) -> 
+                   proplists:get_value(I, BucketProps) =:= undefined
+           end, 
+           jiak_required_props()) of
+        [] ->
+            jiak_default:new(BucketProps);
+        _ ->
+            undefined
+    end.
+
+%% @private
+get_jiak_module(ReqData) ->
+    case bucket_from_uri(ReqData) of
+        {ok, Bucket} when is_atom(Bucket) ->
+            jiak_module_for_bucket(Bucket);
+        {error, no_such_bucket} -> 
+            undefined
+    end.
+
+%% @private
+jiak_module_for_bucket(Bucket) when is_atom(Bucket) ->
+    case code:which(Bucket) of
+        non_existing ->
+            case default_jiak_module(Bucket) of
+                undefined -> undefined;
+                Mod when is_tuple(Mod) -> Mod
+            end;
+        ModPath when is_list(ModPath) -> Bucket
+    end.
+
+%% @spec bucket_from_uri(webmachine:wrq()) ->
+%%         {ok, atom()}|{error, no_such_bucket}
+%% @doc Extract the bucket name, as an atom, from the request URI.
+%%      The bucket name must be an existing atom, or this function
+%%      will return {error, no_such_bucket}
+bucket_from_uri(RD) ->
+    try {ok, list_to_existing_atom(wrq:path_info(bucket, RD))}
+    catch _:_ -> {error, no_such_bucket} end.