<commit_before>module API
  class Members < Grape::API
    before { authenticate! }

    helpers ::API::Helpers::MembersHelpers

    %w[group project].each do |source_type|
      resource source_type.pluralize do
        # Get a list of group/project members viewable by the authenticated user.
        #
        # Parameters:
        #   id (required) - The group/project ID
        #   query         - Query string
        #
        # Example Request:
        #   GET /groups/:id/members
        #   GET /projects/:id/members
        get ":id/members" do
          source = find_source(source_type, params[:id])

          users = source.users
          users = users.merge(User.search(params[:query])) if params[:query]
          users = paginate(users)

          present users, with: Entities::Member, source: source
        end

        # Get a group/project member
        #
        # Parameters:
        #   id (required) - The group/project ID
        #   user_id (required) - The user ID of the member
        #
        # Example Request:
        #   GET /groups/:id/members/:user_id
        #   GET /projects/:id/members/:user_id
        get ":id/members/:user_id" do
          source = find_source(source_type, params[:id])

          members = source.members
          member = members.find_by!(user_id: params[:user_id])

          present member.user, with: Entities::Member, member: member
        end

        # Add a new group/project member
        #
        # Parameters:
        #   id (required) - The group/project ID
        #   user_id (required) - The user ID of the new member
        #   access_level (required) - A valid access level
        #   expires_at (optional) - Date string in the format YEAR-MONTH-DAY
        #
        # Example Request:
        #   POST /groups/:id/members
        #   POST /projects/:id/members
        post ":id/members" do
          source = find_source(source_type, params[:id])
          authorize_admin_source!(source_type, source)
          required_attributes! [:user_id, :access_level]

          member = source.members.find_by(user_id: params[:user_id])

          # This is to ensure back-compatibility but 409 behavior should be used
          # for both project and group members in 9.0!
          conflict!('Member already exists') if source_type == 'group' && member

          access_requester = source.requesters.find_by(user_id: params[:user_id])
          if access_requester
            # We delete a potential access requester before creating the new member.
            # We pass current_user = access_requester so that the requester doesn't
            # receive a "access denied" email.
            ::Members::DestroyService.new(source, access_requester.user, params).execute(:requesters)
          end

          unless member
            member = source.add_user(params[:user_id], params[:access_level], current_user: current_user, expires_at: params[:expires_at])
          end

          if member.persisted? && member.valid?
            present member.user, with: Entities::Member, member: member
          else
            # This is to ensure back-compatibility but 400 behavior should be used
            # for all validation errors in 9.0!
            render_api_error!('Access level is not known', 422) if member.errors.key?(:access_level)
            render_validation_error!(member)
          end
        end

        # Update a group/project member
        #<commit_msg>Remove useless code now that Member#add_user handles it<commit_after>module API
  class Members < Grape::API
    before { authenticate! }

    helpers ::API::Helpers::MembersHelpers

    %w[group project].each do |source_type|
      resource source_type.pluralize do
        # Get a list of group/project members viewable by the authenticated user.
        #
        # Parameters:
        #   id (required) - The group/project ID
        #   query         - Query string
        #
        # Example Request:
        #   GET /groups/:id/members
        #   GET /projects/:id/members
        get ":id/members" do
          source = find_source(source_type, params[:id])

          users = source.users
          users = users.merge(User.search(params[:query])) if params[:query]
          users = paginate(users)

          present users, with: Entities::Member, source: source
        end

        # Get a group/project member
        #
        # Parameters:
        #   id (required) - The group/project ID
        #   user_id (required) - The user ID of the member
        #
        # Example Request:
        #   GET /groups/:id/members/:user_id
        #   GET /projects/:id/members/:user_id
        get ":id/members/:user_id" do
          source = find_source(source_type, params[:id])

          members = source.members
          member = members.find_by!(user_id: params[:user_id])

          present member.user, with: Entities::Member, member: member
        end

        # Add a new group/project member
        #
        # Parameters:
        #   id (required) - The group/project ID
        #   user_id (required) - The user ID of the new member
        #   access_level (required) - A valid access level
        #   expires_at (optional) - Date string in the format YEAR-MONTH-DAY
        #
        # Example Request:
        #   POST /groups/:id/members
        #   POST /projects/:id/members
        post ":id/members" do
          source = find_source(source_type, params[:id])
          authorize_admin_source!(source_type, source)
          required_attributes! [:user_id, :access_level]

          member = source.members.find_by(user_id: params[:user_id])

          # This is to ensure back-compatibility but 409 behavior should be used
          # for both project and group members in 9.0!
          conflict!('Member already exists') if source_type == 'group' && member

          unless member
            member = source.add_user(params[:user_id], params[:access_level], current_user: current_user, expires_at: params[:expires_at])
          end

          if member.persisted? && member.valid?
            present member.user, with: Entities::Member, member: member
          else
            # This is to ensure back-compatibility but 400 behavior should be used
            # for all validation errors in 9.0!
            render_api_error!('Access level is not known', 422) if member.errors.key?(:access_level)
            render_validation_error!(member)
          end
        end

        # Update a group/project member
        #
{'fraction_non_alphanumeric': 0.09149425287356322, 'fraction_numerical': 0.003984674329501916, 'mean_word_length': 2.048108360579169, 'pattern_counts': {'":': 6, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7085764', 'n_tokens_mistral': 1793, 'n_tokens_neox': 1752, 'n_words': 515}