0

I need the auth_token attribute to only be outputted for the current authenticated user.

My User controller has

class Api::V1::UsersController < ApplicationController
  before_action :authenticate_with_token!, only: [:show, :create, :update, :destroy]
  respond_to :json

  def show
    authorize User
    respond_with User.find(params[:id])
  end
...

The serializer:

class UserSerializer < ActiveModel::Serializer
  attributes :id, :email, :created_at, :updated_at, :auth_token
  has_one :role

The http request goes something like: GET http://api.domain.com/users/1 With Headers: Accept, Content-Type and Authorization (Authorization is the auth_token).

What's returned is:

{
  "user": {
    "id": 1,
    "email": "user1@domain.com",
    "created_at": "2015-12-01T07:36:55.276Z",
    "updated_at": "2015-12-01T07:36:55.276Z",
    "auth_token": "8xxoZjZyx313cx2poabz",
    "role": {
      "id": 1,
      "name": "admin",
      "created_at": "2015-12-01T07:36:55.190Z",
      "updated_at": "2015-12-01T07:36:55.190Z"
    }
  }
}

I only want auth_token to be shown if the user that it belongs to requests it or a user with the super role requests it. I have a method in my user model that can check for a role like has_role? :super.

In the serializer I've tried this but it was really just a shot in the dark. I have no idea how to accomplish this:

...
def filter(keys)
  if scope.auth_token == :auth_token
    keys
  else
    keys - [:auth_token]
  end
end

Edit

Using active_model_serializer version 0.9.3

Grug
  • 1,870
  • 5
  • 25
  • 38

2 Answers2

0

Saw this in the source and something clicked in my head.

Changing the filter method above to the following gave me the desired results.

  def filter(keys)
    if (scope == object) or scope.has_role?(:super)
      keys
    else
      keys - [:auth_token]
    end
  end

Hope this helps anyone else using version 0.9.x

Grug
  • 1,870
  • 5
  • 25
  • 38
0

In your serializer, even though :auth_token is a field, you should be able to overwrite it with a method of the same name.

So:

class UserSerializer < ActiveModel::Serializer
  attributes :id, :email, :created_at, :updated_at, :auth_token
  has_one :role

  def auth_token
    object.auth_token == scope.auth_token || scope.has_role?(:super) ? object.auth_token : nil
  end
end
Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
Louis
  • 11
  • 1