I have devise_invitable installed on my rails application. Creating a new invitation works properly.
I built a view to manage the list of invitations, and created a form button to allow the admin to delete outstanding invitations. Here is the code:
<%= link_to "Cancel Invitation", remove_user_invitation_path(invitation_token: invited.invitation_token), confirm: "Are you sure?", class: 'btn btn-mini btn-danger' %>
The result is always an error "The invitation token provided is not valid!"
Looking at the server logs, I see something like this:
Started GET "/invitation/remove?invitation_token=f4e26062f27c7cc32a60e2024b9dba2b1350abba" for 127.0.0.1 at 2013-10-28 15:07:44 -0700
Processing by Devise::InvitationsController#destroy as HTML
Parameters: {"invitation_token"=>"f4e26062f27c7cc32a60e2024b9dba2b1350abba"}
User Load (2.9ms) SELECT "users".* FROM "users" WHERE "users"."invitation_token" = '46488d68fb36387ec639d5d6b9749273b56561a944f76eeefb2f5294ea5225e6' LIMIT 1
This suggests that the delete method is not expecting the raw invite token. (I can understand this from a security stand point.)
What value should I be passing to remove_user_invitation_path?
I'm building the exact same thing at the moment, and ran into the same issue.
What I found is that when Devise-Invitable accept link tokens are actually are an encrypted version of the 'raw' token. The raw token is not persisted - its an instance variable on the (invited) user object. (see generate_invitation_token() in lib/devise_invitable/model.rb )
Since you're already on the listing page, that original user object is long gone, and all you have left is what was persisted.
I see a few ways around this - either persist the raw_invitation_token when the user is invited. (You might do this by adding another column to your user, and overriding the relevant invite() method. This gets nasty quickly with multiple saves or a tempting monkey patch.)
I started down route and got about 90% of the way there before I realized that even if you get this to work, the standard remove endpoint actually expects a user to not be logged in, which forced me to rethink why I need to reuse that route anyway?
So my current solution involves a new endpoint, which 1) uses a different finder method besides User.find_by_invitation_token() (it decrypts the token), and doesnt check that you're logged out :-)
eg.
class InvitationsController < ApplicationController
...
before_filter :user_from_invitation_token
def remove
User.destroy(@user.id)
flash[:notice] = 'Invitation removed'
redirect_to company_users_path
end
private
def user_from_invitation_token
unless params[:invitation_token] && @user = @company.invited_users.where(invitation_token: params[:invitation_token]).first
flash[:error] = 'Invitation not found'
redirect_to company_users_path
end
end
...
This is a WIP and I'm not 100% satisfied with the solution - however it makes sense that if you are building a UI for managing invitations, then you're stepping beyond what Devise-invitable provides out of the box.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With