Feature: Profile API [#238] (#354)

- api to update name and email
- api to change password
- api to  set profile pic
- fixes update_attribute! deprecation warning
- introducing active storage
This commit is contained in:
Sojan Jose 2019-12-10 10:29:35 +05:30 committed by Pranav Raj S
parent 7f96c39b18
commit 1abaee04d8
15 changed files with 177 additions and 10 deletions

View file

@ -6,6 +6,8 @@ inherit_from: .rubocop_todo.yml
Metrics/LineLength:
Max: 150
RSpec/ExampleLength:
Max: 10
Documentation:
Enabled: false
Style/FrozenStringLiteralComment:

View file

@ -19,6 +19,11 @@ gem 'responders'
gem 'time_diff'
gem 'tzinfo-data'
gem 'valid_email2'
# compress javascript config.assets.js_compressor
gem 'uglifier'
##-- for active storage --##
gem 'mini_magick'
##-- gems for database --#
gem 'pg'
@ -40,7 +45,7 @@ gem 'jwt'
gem 'pundit'
##--- gems for pubsub service ---##
# TODO investigate and remove this gem
# https://karolgalanciak.com/blog/2019/11/30/from-activerecord-callbacks-to-publish-slash-subscribe-pattern-and-event-driven-design/
gem 'wisper', '2.0.0'
##--- gems for reporting ---##
@ -66,9 +71,7 @@ gem 'sentry-raven'
##-- TODO: move these gems to appropriate groups --##
# remove this gem in favor of active storage - github #158
gem 'carrierwave-aws'
gem 'mini_magick'
gem 'sidekiq'
gem 'uglifier'
group :development do
gem 'annotate'

View file

@ -13,7 +13,7 @@ class Api::V1::AgentsController < Api::BaseController
end
def update
@agent.update_attributes!(agent_params)
@agent.update!(agent_params)
render json: @agent
end

View file

@ -32,7 +32,7 @@ class Api::V1::CallbacksController < ApplicationController
fb_page = current_account.facebook_pages.find_by(page_id: fb_page_id)
if fb_page
fb_page.update_attributes!(
fb_page.update!(
user_access_token: @user_access_token,
page_access_token: page_detail['access_token']
)

View file

@ -12,7 +12,7 @@ class Api::V1::CannedResponsesController < Api::BaseController
end
def update
@canned_response.update_attributes!(canned_response_params)
@canned_response.update!(canned_response_params)
render json: @canned_response
end

View file

@ -22,7 +22,7 @@ class Api::V1::ContactsController < Api::BaseController
end
def update
@contact.update_attributes!(contact_params)
@contact.update!(contact_params)
end
private

View file

@ -0,0 +1,22 @@
class Api::V1::ProfilesController < Api::BaseController
before_action :fetch_user
def show
render json: @user
end
def update
@user.update!(profile_params)
render json: @user
end
private
def fetch_user
@user = current_user
end
def profile_params
params.require(:profile).permit(:email, :name, :password, :password_confirmation, :avatar)
end
end

View file

@ -10,7 +10,6 @@
# current_sign_in_ip :string
# email :string
# encrypted_password :string default(""), not null
# image :string
# last_sign_in_at :datetime
# last_sign_in_ip :string
# name :string not null
@ -60,6 +59,9 @@ class User < ApplicationRecord
# Used by the actionCable/PubSub Service we use for real time communications
has_secure_token :pubsub_token
# Uses active storage for the avatar
has_one_attached :avatar
# The validation below has been commented out as it does not
# work because :validatable in devise overrides this.
# validates_uniqueness_of :email, scope: :account_id

View file

@ -29,6 +29,7 @@ Rails.application.routes.draw do
resources :inboxes, only: [:create]
end
resource :profile, only: [:show, :update]
resources :accounts, only: [:create]
resources :inboxes, only: [:index, :destroy]
resources :agents, except: [:show, :edit, :new]

View file

@ -0,0 +1,27 @@
# This migration comes from active_storage (originally 20170806125915)
class CreateActiveStorageTables < ActiveRecord::Migration[5.2]
def change
create_table :active_storage_blobs do |t|
t.string :key, null: false
t.string :filename, null: false
t.string :content_type
t.text :metadata
t.bigint :byte_size, null: false
t.string :checksum, null: false
t.datetime :created_at, null: false
t.index [ :key ], unique: true
end
create_table :active_storage_attachments do |t|
t.string :name, null: false
t.references :record, null: false, polymorphic: true, index: false
t.references :blob, null: false
t.datetime :created_at, null: false
t.index [ :record_type, :record_id, :name, :blob_id ], name: "index_active_storage_attachments_uniqueness", unique: true
t.foreign_key :active_storage_blobs, column: :blob_id
end
end
end

View file

@ -0,0 +1,5 @@
class RemoveImageFromUser < ActiveRecord::Migration[6.0]
def change
remove_column :users, :image, :string
end
end

View file

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2019_12_04_192301) do
ActiveRecord::Schema.define(version: 2019_12_09_202758) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -21,6 +21,27 @@ ActiveRecord::Schema.define(version: 2019_12_04_192301) do
t.datetime "updated_at", null: false
end
create_table "active_storage_attachments", force: :cascade do |t|
t.string "name", null: false
t.string "record_type", null: false
t.bigint "record_id", null: false
t.bigint "blob_id", null: false
t.datetime "created_at", null: false
t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id"
t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true
end
create_table "active_storage_blobs", force: :cascade do |t|
t.string "key", null: false
t.string "filename", null: false
t.string "content_type"
t.text "metadata"
t.bigint "byte_size", null: false
t.string "checksum", null: false
t.datetime "created_at", null: false
t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true
end
create_table "attachments", id: :serial, force: :cascade do |t|
t.string "file"
t.integer "file_type", default: 0
@ -207,7 +228,6 @@ ActiveRecord::Schema.define(version: 2019_12_04_192301) do
t.string "unconfirmed_email"
t.string "name", null: false
t.string "nickname"
t.string "image"
t.string "email"
t.json "tokens"
t.integer "account_id", null: false
@ -223,6 +243,7 @@ ActiveRecord::Schema.define(version: 2019_12_04_192301) do
t.index ["uid", "provider"], name: "index_users_on_uid_and_provider", unique: true
end
add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id"
add_foreign_key "contact_inboxes", "contacts"
add_foreign_key "contact_inboxes", "inboxes"
add_foreign_key "users", "users", column: "inviter_id", on_delete: :nullify

BIN
spec/assets/avatar.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View file

@ -0,0 +1,80 @@
require 'rails_helper'
RSpec.describe 'Profile API', type: :request do
let(:account) { create(:account) }
describe 'GET /api/v1/profile' do
context 'when unauthenticated user' do
it 'returns unauthorized' do
get '/api/v1/profile'
expect(response).to have_http_status(:unauthorized)
end
end
context 'when it authenticated user' do
let(:agent) { create(:user, account: account, role: :agent) }
it 'returns current user information' do
get '/api/v1/profile',
headers: agent.create_new_auth_token,
as: :json
expect(response).to have_http_status(:success)
json_response = JSON.parse(response.body)
expect(json_response['id']).to eq(agent.id)
expect(json_response['email']).to eq(agent.email)
end
end
end
describe 'PUT /api/v1/profile' do
context 'when unauthenticated user' do
it 'returns unauthorized' do
put '/api/v1/profile'
expect(response).to have_http_status(:unauthorized)
end
end
context 'when it authenticated user' do
let(:agent) { create(:user, account: account, role: :agent) }
it 'updates the name & email' do
put '/api/v1/profile',
params: { profile: { name: 'test', 'email': 'test@test.com' } },
headers: agent.create_new_auth_token,
as: :json
expect(response).to have_http_status(:success)
json_response = JSON.parse(response.body)
agent.reload
expect(json_response['id']).to eq(agent.id)
expect(json_response['email']).to eq(agent.email)
expect(agent.email).to eq('test@test.com')
end
it 'updates the password' do
put '/api/v1/profile',
params: { profile: { password: 'test123', password_confirmation: 'test123' } },
headers: agent.create_new_auth_token,
as: :json
expect(response).to have_http_status(:success)
end
it 'updates avatar' do
# no avatar before upload
expect(agent.avatar.attached?).to eq(false)
file = fixture_file_upload(Rails.root.join('spec/assets/avatar.png'), 'image/png')
put '/api/v1/profile',
params: { profile: { name: 'test', 'email': 'test@test.com', avatar: file } },
headers: agent.create_new_auth_token
expect(response).to have_http_status(:success)
agent.reload
expect(agent.avatar.attached?).to eq(true)
end
end
end
end

View file

@ -18,5 +18,9 @@ FactoryBot.define do
after(:build) do |user, evaluator|
user.skip_confirmation! if evaluator.skip_confirmation
end
trait :with_avatar do
avatar { Rack::Test::UploadedFile.new('spec/assets/avatar.png', 'image/png') }
end
end
end