Skip to content
This repository has been archived by the owner on Dec 3, 2019. It is now read-only.

add new routes for frontend authentication and user flow #473

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
223 changes: 201 additions & 22 deletions apiary.apib
Original file line number Diff line number Diff line change
@@ -1713,16 +1713,39 @@ API endpoints that Operation Code's Rails backend makes available to its React f
{
errors: "Some error message"
}
## User | Create [/api/v1/users{?first_name,last_name,email,zip,password,mentor}]
## User | Create [/api/v1/users{?first_name,last_name,email,zip,password,bio,verified,state,address1,address2,city,username,volunteer,branch_of_service,years_of_service,pay_grade,military_occupational_speciality,github,twitter,linked_in,mentor,employment_status,education,military_status,company_role,company_name,education_level,scholarship_info,interests}]

+ Parameters

+ first_name (string, required) - First Name of the user in the form of an string
+ last_name (string, required) - Last Name of the user in the form of an string
+ email (string, required) - Email of the User in the form of a string
+ zip (string, required) - Zipcode of the User in the form of a string
+ first_name (string, required) - First Name of the user in the form of an string
+ last_name (string, required) - Last Name of the user in the form of an string
+ mentor (string, optional) - in the form of a string
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be a boolean

+ password (string, required) - Password of the User in the form on a string
+ mentor (boolean, optional) - Is User requesting mentor in the form of a boolean
+ bio (string, optional) - in the form of a string
+ verified (string, optional) - in the form of a string
+ state (string, optional) - in the form of a string
+ address1 (string, optional) - in the form of a string
+ address2 (string, optional) - in the form of a string
+ city (string, optional) - in the form of a string
+ username (string, optional) - in the form of a string
+ volunteer (string, optional) - in the form of a string
+ branch_of_service (string, optional) - in the form of a string
+ years_of_service (string, optional) - in the form of a string
+ pay_grade (string, optional) - in the form of a string
+ military_occupational_speciality (string, optional) - in the form of a string
+ github (string, optional) - in the form of a string
+ twitter (string, optional) - in the form of a string
+ linked_in (string, optional) - in the form of a string
+ employment_status (string, optional) - in the form of a string
+ education (string, optional) - in the form of a string
+ military_status (string, optional) - in the form of a string
+ company_role (string, optional) - in the form of a string
+ company_name (string, optional) - in the form of a string
+ education_level (string, optional) - in the form of a string
+ scholarship_info (boolean, optional) - in the form of a string
+ interests (string, optional) - in the form of a string

### Create new user record [POST]

@@ -1731,11 +1754,37 @@ API endpoints that Operation Code's Rails backend makes available to its React f
+ Body

{
first_name: "Mike",
last_name: "Johnson",
email: "dreams@operationcode.org",
password: "hunter2",
zip: "80020",
mentor: "true"
first_name: "Mike",
last_name: "Johnson",
bio: "Information",
verified: false,
state: "NC",
address1: "My address",
address2: "PO BOX",
city: "My city",
username: "mike house"
volunteer: "false",
branch_of_service: "Air Force",
years_of_service: "100",
pay_grade: "0",
military_occupational_speciality: "3N",
github: "user_name",
twitter: "user_name",
linked_in: "user_name",
mentor: "true",
education_level: "College Graduate",
scholarship_info: "true",
employment_status: "Employed",
education: "BS",
military_status: "spouse",
company_role: "Developer",
company_name: "Comcast",
education_level: "BS",
scholarship_info: "True",
interests: "Python, Python, Python, Python"
}


@@ -1751,6 +1800,96 @@ API endpoints that Operation Code's Rails backend makes available to its React f
errors: "Some error message"
}

## User | Exists [/api/v1/users/email/{email}]

+ Parameters

+ email (string, required) - User email in form of a string

### Checks if a user currently exists [GET]

+ Request (application/json)

+ Response 200 (application/json)
+ Body

{
status: "ok"
}

+ Response 422 (application/json)
+ Body

{
status: "Unprocessable Entity"
}

## User | Me [/api/v1/users{?email}]

+ Parameters

+ email (string, required) - Email of the User in the form of a string

### Get full details for a specific user [GET]

+ Request (application/json)

+ Headers

Authorization: Bearer Access-Token

+ Response 200 (application/json)

+ Body

{
email: "dreams@operationcode.org",
zip: "80020",
first_name: "Mike",
last_name: "Johnson",
bio: "Information",
verified: false,
state: "NC",
address1: "My address",
address2: "PO BOX",
city: "My city",
username: "mike house"
volunteer: "false",
branch_of_service: "Air Force",
years_of_service: "100",
pay_grade: "0",
military_occupational_speciality: "3N",
github: "user_name",
twitter: "user_name",
linked_in: "user_name",
mentor: "true",
education_level: "College Graduate",
scholarship_info: "true",
employment_status: "Employed",
education: "BS",
military_status: "spouse",
company_role: "Developer",
company_name: "Comcast",
education_level: "BS",
scholarship_info: "True",
interests: "Python, Python, Python, Python"
}

+ Response 422 (application/json)

+ Body

{
status: "Unprocessable Entity"
}

+ Response 404 (application/json)

{
error: 'No such record'
}


## User | Reset Password [/api/v1/users/passwords/reset{?email}]

+ Parameters
@@ -1798,20 +1937,39 @@ API endpoints that Operation Code's Rails backend makes available to its React f
{
errors: "Some error message"
}
## User | Update [/api/v1/users{?education_level,mentor,scholarship_info,employment_status,company_name,company_role,volunteer,military_status,branch_of_service,interests}]
## User | Update [/api/v1/users{?first_name,last_name,email,zip,password,mentor,bio,verified,state,address1,address2,city,username,volunteer,branch_of_service,years_of_service,pay_grade,military_occupational_speciality,github,twitter,linked_in,employment_status,education,military_status,company_role,company_name,education_level,scholarship_info,interests}]

+ Parameters

+ education_level (string, optional) - Users highest level of education in the form of a string
+ first_name (string, required) - First Name of the user in the form of an string
+ last_name (string, required) - Last Name of the user in the form of an string
+ email (string, required) - Email of the User in the form of a string
+ zip (string, required) - Zipcode of the User in the form of a string
+ password (string, required) - Password of the User in the form on a string
+ mentor (boolean, optional) - Is User requesting mentor in the form of a boolean
+ scholarship_info (boolean, optional) - Is User interested in scholarship info in the form of a boolean
+ employment_status (string, optional) - Users employment status in the form of a string
+ company_name (string, optional) - Users name of employer in the form on a string
+ company_role (string, optional) - Users role at company in the form of a string
+ volunteer (boolean, optional) - Is User wanting to volunteer in the form of a boolean
+ military_status (string, optional) - Users military status, either current, veteran, spouse, or blank
+ branch_of_service (string, optional) - Users branch of service in the form of a string
+ interests (string, optional) - User interests in the form of a string.
+ bio (string, optional) - in the form of a string
+ verified (string, optional) - in the form of a string
+ state (string, optional) - in the form of a string
+ address1 (string, optional) - in the form of a string
+ address2 (string, optional) - in the form of a string
+ city (string, optional) - in the form of a string
+ username (string, optional) - in the form of a string
+ volunteer (string, optional) - in the form of a string
+ branch_of_service (string, optional) - in the form of a string
+ years_of_service (string, optional) - in the form of a string
+ pay_grade (string, optional) - in the form of a string
+ military_occupational_speciality (string, optional) - in the form of a string
+ github (string, optional) - in the form of a string
+ twitter (string, optional) - in the form of a string
+ linked_in (string, optional) - in the form of a string
+ employment_status (string, optional) - in the form of a string
+ education (string, optional) - in the form of a string
+ military_status (string, optional) - in the form of a string
+ company_role (string, optional) - in the form of a string
+ company_name (string, optional) - in the form of a string
+ education_level (string, optional) - in the form of a string
+ scholarship_info (boolean, optional) - in the form of a string
+ interests (string, optional) - in the form of a string

### Update user record [PATCH]

@@ -1824,15 +1982,36 @@ API endpoints that Operation Code's Rails backend makes available to its React f
+ Body

{
education_level: "College Graduate" ,
email: "dreams@operationcode.org",
password: "hunter2",
zip: "80020",
first_name: "Mike",
last_name: "Johnson",
bio: "Information",
verified: false,
state: "NC",
address1: "My address",
address2: "PO BOX",
city: "My city",
username: "mike house"
volunteer: "false",
branch_of_service: "Air Force",
years_of_service: "100",
pay_grade: "0",
military_occupational_speciality: "3N",
github: "user_name",
twitter: "user_name",
linked_in: "user_name",
mentor: "true",
education_level: "College Graduate",
scholarship_info: "true",
employment_status: "Employed",
company_name: "Comcast",
company_role: "Developer",
education: "BS",
military_status: "spouse",
volunteer: "false",
branch_of_service: "Air Force",
company_role: "Developer",
company_name: "Comcast",
education_level: "BS",
scholarship_info: "True",
interests: "Python, Python, Python, Python"
}

26 changes: 23 additions & 3 deletions app/controllers/api/v1/users_controller.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module Api
module V1
class UsersController < ApiController
before_action :authenticate_user!, only: %i[update]
before_action :authenticate_user!, only: %i[update me]

def index
render json: { user_count: User.count }, status: :ok
@@ -13,7 +13,8 @@ def create
user = User.new(user_params)

if user.save
user.welcome_user
user.invite_to_slack
user.add_to_send_grid
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these should probably occur after sign_in right? Unsure why user.welcome_user was listed before UserMailer.welcome(user).deliver unless user.invalid?

UserMailer.welcome(user).deliver unless user.invalid?
sign_in(user)
render json: { token: user.token }
@@ -53,6 +54,25 @@ def by_location
render json: { errors: e.message }, status: :unprocessable_entity
end

def by_email
user = User.find_by(email: params[:email])
if user
Rails.logger.debug "search by email successful #{request.env}"
render json: { status: :ok }, status: :ok
else
Rails.logger.debug "search by email not found from request: #{request.env}"
render json: { status: :not_found }, status: :not_found
end
end

def me
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's happening in this method?

# Rails.logger.debug "search by email for authed user email: #{current_user}"
render json: ComplexUserSerializer.new(current_user), status: :ok
rescue StandardError => e
Rails.logger.debug "search by email errored: #{current_user} error: #{e}"
render json: { status: :unprocessable_entity }, status: :unprocessable_entity
end

private

def user_params
@@ -68,6 +88,7 @@ def user_params
:state,
:address1,
:address2,
:city,
:username,
:volunteer,
:branch_of_service,
@@ -84,7 +105,6 @@ def user_params
:company_name,
:education_level,
:scholarship_info,
:role_id,
interests: []
)
end
1 change: 1 addition & 0 deletions app/jobs/add_user_to_send_grid_job.rb
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@ class AddUserToSendGridJob < ApplicationJob

def perform(user_id)
user = User.find(user_id)

SendGridClient.new.add_user(user)
end
end
8 changes: 7 additions & 1 deletion app/lib/slack/client.rb
Original file line number Diff line number Diff line change
@@ -23,7 +23,9 @@ def initialize(subdomain:, token:)
end

def invite(extra_message:, email:, channels: [])
Rails.logger.info "Inviting user with email '#{email}'"
# unsure if some string expansion is causing an error here
Rails.logger.info 'Inviting slack user user'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can prolly delete this line and comment above

Rails.logger.info "Inviting slack user user with email #{email}"
body = send_api_request(
to: INVITE_PATH,
payload: {
@@ -40,6 +42,10 @@ def invite(extra_message:, email:, channels: [])
end

true
rescue StandardError => e
Rails.logger.warn "Some Exception occured while inviting slack user #{e}"
# want to reraise the exception so the job retries
raise
end

def post_message_to(channel:, with_text:)
9 changes: 4 additions & 5 deletions app/models/user.rb
Original file line number Diff line number Diff line change
@@ -151,17 +151,16 @@ def name
"#{first_name} #{last_name}"
end

def welcome_user
add_to_send_grid
invite_to_slack
end

def invite_to_slack
SlackJobs::InviterJob.perform_async(self.email)
rescue StandardError => e
Rails.logger.warn "Error occured when trying to add to job queue for slack invite #{e}"
end

def add_to_send_grid
AddUserToSendGridJob.perform_async(self.id)
rescue StandardError => e
Rails.logger.warn "Error occured when trying to add to job queue for sendgrid #{e}"
end

def token
30 changes: 30 additions & 0 deletions app/serializers/complex_user_serializer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
class ComplexUserSerializer < ActiveModel::Serializer
attributes :email,
:zip,
:mentor,
:first_name,
:last_name,
:bio,
:verified,
:state,
:address1,
:address2,
:city,
:username,
:volunteer,
:branch_of_service,
:years_of_service,
:pay_grade,
:military_occupational_specialty,
:github,
:twitter,
:linked_in,
:employment_status,
:education,
:military_status,
:company_role,
:company_name,
:education_level,
:scholarship_info,
interests: []
end
3 changes: 2 additions & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
@@ -24,6 +24,7 @@
get '/status/protected', to: 'status#protected'

get '/users/by_location', to: 'users#by_location'
get '/users/by_email', to: 'users#by_email'
post '/users/profile/verify', to: 'users#verify'

resources :code_schools do
@@ -49,7 +50,7 @@
resources :team_members, only: [:index, :create, :update, :destroy]
resources :users, only: [:index, :create]
patch '/users', to: 'users#update'

get '/users/me', to: 'users#me'
devise_scope :user do
post '/sessions', to: 'sessions#create'
get '/sessions/sso', to: 'sessions#sso'
44 changes: 42 additions & 2 deletions test/controllers/api/v1/users_controller_test.rb
Original file line number Diff line number Diff line change
@@ -54,13 +54,53 @@ def valid_user_params
assert valid_user_params[:zip], user.zip
end

test '#create welcomes a new user' do
User.any_instance.expects(:welcome_user)
test '#create calls add_to_send_grid job queue addition' do
User.any_instance.expects(:add_to_send_grid)
post api_v1_users_url,
params: { user: valid_user_params },
as: :json
end

test '#create calls invite_to_slack job queue addition' do
User.any_instance.expects(:invite_to_slack)
post api_v1_users_url,
params: { user: valid_user_params },
as: :json
end

test '#by_email returns success when user exists' do
tom = create(:user)
params = { email: tom.email }
get api_v1_users_by_email_path(params), as: :json
assert_equal({ 'status' => 'ok' }, response.parsed_body)
assert_equal 200, response.status
end

test '#by_email returns failure user when doesn\'t exist' do
params = { email: 'fake_email@gmail.com' }
get api_v1_users_by_email_url(params), as: :json
assert_equal({ 'status' => 'not_found'}, response.parsed_body)
assert_equal 404, response.status
end

# test '#me requires auth token to get valid response' do
# user_good = create(:user)
# user_bad = create(:user)
# headers_good = authorization_headers(user_good)
# headers_bad = authorization_headers(user_bad)
# user_good.valid?
# debugger user_good.errors.messages
# get api_v1_users_me_url, params: { email: user_bad.email }, headers: headers_good , as: :json
# assert_equal 422, response.status
# end

# test '#me with valid auth token returns success' do
# user = create(:user)
# headers = authorization_headers(user)
# post api_v1_users_me_url, params: { email: user.email }, headers: headers, as: :json
# assert_equal 200, response.status
# end

test ':by_location returns User.count of users located in the passed in location' do
tom = create :user
sam = create :user
4 changes: 2 additions & 2 deletions test/models/user_test.rb
Original file line number Diff line number Diff line change
@@ -11,14 +11,14 @@ def teardown

test 'welcoming a user adds them to SendGrid' do
user = create(:user, user_opts)
user.welcome_user
user.add_to_send_grid
assert_equal 1, AddUserToSendGridJob.jobs.length
assert_equal [user.id], AddUserToSendGridJob.jobs.first['args']
end

test 'welcoming a user adds them to SlackInvite' do
user = create(:user, user_opts)
user.welcome_user
user.invite_to_slack
assert_equal 1, SlackJobs::InviterJob.jobs.length
assert_equal [user.email], SlackJobs::InviterJob.jobs.first['args']
end