<commit_before>%% -*- erlang-indent-level: 4;indent-tabs-mode: nil; fill-column: 92-*-
%% ex: ts=4 sw=4 et
%% @author <NAME> <<EMAIL>>
%% Copyright 2012 Opscode, Inc. All Rights Reserved.
%%
%% This file is provided to you 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.
%%


-module(chef_wm_named_user).

-include("chef_wm.hrl").

-mixin([{chef_wm_base, [content_types_accepted/2,
                        content_types_provided/2,
                        finish_request/2,
                        malformed_request/2,
                        ping/2,
                        post_is_create/2]}]).

-mixin([{?BASE_RESOURCE, [forbidden/2,
                          is_authorized/2,
                          service_available/2]}]).

%% chef_wm behaviour callbacks
-behaviour(chef_wm).
-export([
         auth_info/2,
         init/1,
         init_resource_state/1,
         malformed_request_message/3,
         request_type/0,
         validate_request/3
        ]).

-export([
         allowed_methods/2,
         delete_resource/2,
         from_json/2,
         to_json/2
       ]).

init(Config) ->
    chef_wm_base:init(?MODULE, Config).

init_resource_state(_Config) ->
    {ok, #user_state{}}.

request_type() ->
  "users".

allowed_methods(Req, State) ->
    {['GET', 'PUT', 'DELETE'], Req, State}.

validate_request(Method, Req, State) when Method == 'GET';
                                          Method == 'DELETE' ->
    {Req, State};
validate_request('PUT', Req, #base_state{resource_state = UserState} = State) ->
    %% Name = chef_wm_util:object_name(user, Req),
    Body = wrq:req_body(Req),
    %% FIXME: need to validate no name change since we aren't going to support rename for
    %% users.
    {ok, User} = chef_user:parse_binary_json(Body),
    {Req, State#base_state{resource_state = UserState#user_state{user_data = User}}}.

auth_info(Req, #base_state{chef_db_context = DbContext,
                           resource_state = UserState}=State) ->
    UserName = chef_wm_util:object_name(user, Req),
    case chef_db:fetch_user(DbContext, UserName) of
        not_found ->
            Message = chef_wm_util:not_found_message(user, UserName),
            Req1 = chef_wm_util:set_json_body(Req, Message),
            {{halt, 404}, Req1, State#base_state{log_msg = user_not_found}};
        #chef_user{authz_id = AuthzId} = User ->
            UserState1 = UserState#user_state{chef_user = User},
            State1 = State#base_state{resource_state = UserState1},
            {{object, AuthzId}, Req, State1}
    end.

from_json(Req, #base_state{reqid = RequestId,
                           resource_state =
                               #user_state{chef_user = User,
                                           user_data = UserData}} = State) ->
    UserData1 = maybe_generate_key_pair(UserData, RequestId),
    %% FIXME:
    %% error({implement_me}).
    chef_wm_base:update_from_json(Req, State, User, UserData1).

to_json(Req, #base_state{resource_state =
                             #user_state{chef_user = User},
                         organization_name = OrgName} = State) ->
    EJson = chef_user:assemble_user_ejson(User, OrgName),
    Json = ejson:encode(EJson),
    {Json, Req, State}.

delete_resource(Req, #base_state{chef_db_context = DbContext,
                                 requestor_id = RequestorId,
                                 resource_state = #user_state{
                                   chef_user = User},
                                 organization_name = OrgName} = State) ->
    ok = chef_object_db:delete(DbContext, User, RequestorId),
    EJson = chef_user:assemble_user_ejson(User, OrgName),
    Req1 = chef_wm_util:set_json_body(Req, EJson),
    {true, Req1, State}.

%% If the request contains "private_key":true, then we will generate a new key pair. In
%% this case, we'll add the new public and private keys into the EJSON since
%% update_from_json will use it to set the response.
maybe_generate_key_pair(UserData, RequestId) ->
    Name = ej:get({<<"name">>}, UserData),
    case ej:get({<<"private_key">>}, UserData) of
        true -><commit_msg>[OC-4074] Cleanup comments<commit_after>%% -*- erlang-indent-level: 4;indent-tabs-mode: nil; fill-column: 92-*-
%% ex: ts=4 sw=4 et
%% @author <NAME> <<EMAIL>>
%% Copyright 2012 Opscode, Inc. All Rights Reserved.
%%
%% This file is provided to you 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.
%%


-module(chef_wm_named_user).

-include("chef_wm.hrl").

-mixin([{chef_wm_base, [content_types_accepted/2,
                        content_types_provided/2,
                        finish_request/2,
                        malformed_request/2,
                        ping/2,
                        post_is_create/2]}]).

-mixin([{?BASE_RESOURCE, [forbidden/2,
                          is_authorized/2,
                          service_available/2]}]).

%% chef_wm behaviour callbacks
-behaviour(chef_wm).
-export([
         auth_info/2,
         init/1,
         init_resource_state/1,
         malformed_request_message/3,
         request_type/0,
         validate_request/3
        ]).

-export([
         allowed_methods/2,
         delete_resource/2,
         from_json/2,
         to_json/2
       ]).

init(Config) ->
    chef_wm_base:init(?MODULE, Config).

init_resource_state(_Config) ->
    {ok, #user_state{}}.

request_type() ->
  "users".

allowed_methods(Req, State) ->
    {['GET', 'PUT', 'DELETE'], Req, State}.

validate_request(Method, Req, State) when Method == 'GET';
                                          Method == 'DELETE' ->
    {Req, State};
validate_request('PUT', Req, #base_state{resource_state = UserState} = State) ->
    %% Name = chef_wm_util:object_name(user, Req),
    Body = wrq:req_body(Req),
    %% FIXME: need to validate no name change since we aren't going to support rename for
    %% users.
    {ok, User} = chef_user:parse_binary_json(Body),
    {Req, State#base_state{resource_state = UserState#user_state{user_data = User}}}.

auth_info(Req, #base_state{chef_db_context = DbContext,
                           resource_state = UserState}=State) ->
    UserName = chef_wm_util:object_name(user, Req),
    case chef_db:fetch_user(DbContext, UserName) of
        not_found ->
            Message = chef_wm_util:not_found_message(user, UserName),
            Req1 = chef_wm_util:set_json_body(Req, Message),
            {{halt, 404}, Req1, State#base_state{log_msg = user_not_found}};
        #chef_user{authz_id = AuthzId} = User ->
            UserState1 = UserState#user_state{chef_user = User},
            State1 = State#base_state{resource_state = UserState1},
            {{object, AuthzId}, Req, State1}
    end.

from_json(Req, #base_state{reqid = RequestId,
                           resource_state =
                               #user_state{chef_user = User,
                                           user_data = UserData}} = State) ->
    UserData1 = maybe_generate_key_pair(UserData, RequestId),
    chef_wm_base:update_from_json(Req, State, User, UserData1).

to_json(Req, #base_state{resource_state =
                             #user_state{chef_user = User},
                         organization_name = OrgName} = State) ->
    EJson = chef_user:assemble_user_ejson(User, OrgName),
    Json = ejson:encode(EJson),
    {Json, Req, State}.

delete_resource(Req, #base_state{chef_db_context = DbContext,
                                 requestor_id = RequestorId,
                                 resource_state = #user_state{
                                   chef_user = User},
                                 organization_name = OrgName} = State) ->
    ok = chef_object_db:delete(DbContext, User, RequestorId),
    EJson = chef_user:assemble_user_ejson(User, OrgName),
    Req1 = chef_wm_util:set_json_body(Req, EJson),
    {true, Req1, State}.

%% If the request contains "private_key":true, then we will generate a new key pair. In
%% this case, we'll add the new public and private keys into the EJSON since
%% update_from_json will use it to set the response.
maybe_generate_key_pair(UserData, RequestId) ->
    Name = ej:get({<<"name">>}, UserData),
    case ej:get({<<"private_key">>}, UserData) of
        true ->
{'fraction_non_alphanumeric': 0.11590588745527486, 'fraction_numerical': 0.010191911525533991, 'mean_word_length': 2.4024345260051643, 'pattern_counts': {'":': 2, '<': 17, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3190353', 'n_tokens_mistral': 2877, 'n_tokens_neox': 2811, 'n_words': 664}