Comments (5)
yes, all universal tables (ie, non-tenanted tables), including users, and
tenants, MUST have a tenant_id field and that field value MUST always be
NULL. if you are grafting this onto an existing database, you will need to
ensure that there is a migration that has done that and the default value
for the new field is NULL.
On Fri, Mar 13, 2015 at 8:36 AM jekuno [email protected] wrote:
I encountered a problem adding milia-1.2.0 to my rails-4.2.0 application
(I unfortunately couldn't graft my app onto the sample-milia-app because
the existing application is too evolved).I setup everything as described in your documentation. When calling
http://localhost:3000/users/sign_up the form for signing up a new tenant
shows up as expected. However after submitting the form an error flash
message wrong tenant access; sign out & try again appears.I debugged the problem and found out the following:
The data get processed by Milia::RegistrationsController as expected. The
controller
- creates the tenant correctly, then
- enters devise_create( user_params ) in line 36, then
- tries to save the devise user with resource.save in line 122, then
- raises exception in milia/base.rb, line 62: raise
::Milia::Control::InvalidTenantAccess unless obj.tenant_id.nil?- gets caught by application_controller writing the flash error wrong
tenant access; sign out & try againAs far as I understand the problem is that the user object in the callback
in base.rb has a tenant_id even though it is an universal object. I
didn't find out how to solve this problem. Any help would be greatly
appreciated! :)Some information which might help to narrow down the problem:
- I work on a brand new database.
- I use Postgres, milia-1.2.0, devise-3.4.1 and rails-4.2.0
- My user model contains the line
acts_as_universal_and_determines_account.- I use the following devise modules: :invitable,
:database_authenticatable, :registerable, :confirmable, :recoverable,
:rememberable, :trackable, :validatableThe log looks as follows:
Started POST "/users" for ::1 at 2015-03-13 15:32:44 +0100
Processing by Milia::RegistrationsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"xxxxx", "user"=>{"name"=>"Admin TestCompany", "email"=>"[email protected]", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "tenant"=>{"name"=>"TestCompany"}, "commit"=>"Register"}
(0.2ms) BEGIN
SQL (1.1ms) INSERT INTO "tenants" ("name", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id" [["name", "TestCompany"], ["created_at", "2015-03-13 14:32:45.045574"], ["updated_at", "2015-03-13 14:32:45.045574"]]
MILIA >>>>> [change tenant] new: 1 old: %
User Exists (1.6ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = '[email protected]' LIMIT 1
User Load (0.5ms) SELECT "users".* FROM "users" WHERE (users.tenant_id IS NULL) AND "users"."confirmation_token" = $1 ORDER BY "users"."id" ASC LIMIT 1 [["confirmation_token", "72a251b1aa2a2ac60e4f7025370d259e75338aab60540e41dfca6420769ffe46"]]
SQL (0.9ms) INSERT INTO "users" ("email", "encrypted_password", "name", "role", "skip_confirm_change_password", "created_at", "updated_at", "confirmation_token", "confirmation_sent_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING "id" [["email", "[email protected]"], ["encrypted_password", "$2a$10$aPLmuYCDLh23Z74jErof8OEvbw7BnEJXa0tOgjUkyStx9ECxuJH0q"], ["name", "Admin TestCompany"], ["role", 0], ["skip_confirm_change_password", "t"], ["created_at", "2015-03-13 14:32:45.135246"], ["updated_at", "2015-03-13 14:32:45.135246"], ["confirmation_token", "72a251b1aa2a2ac60e4f7025370d259e75338aab60540e41dfca6420769ffe46"], ["confirmation_sent_at", "2015-03-13 14:32:45.360023"]]
Tenant Load (0.4ms) SELECT "tenants".* FROM "tenants" WHERE (tenants.tenant_id IS NULL) AND "tenants"."id" = $1 LIMIT 1 [["id", 1]]
User Exists (0.4ms) SELECT "users".* FROM "users" WHERE (users.tenant_id IS NULL) AND "users"."tenant_id" = $1 AND "users"."id" = $2 [["tenant_id", 1], ["id", 1]]
User Exists (0.5ms) SELECT 1 AS one FROM "users" WHERE ("users"."email" = '[email protected]' AND "users"."id" != 1) LIMIT 1
(0.2ms) ROLLBACK
Redirected to http://localhost:3000/users/sign_up
- The newly created tenant gets set in the session.
- The attributes of the user resource (which cannot be saved) don't
contain a tenant_id before calling resource.save:"{"id"=>nil, "email"=>"[email protected]", "encrypted_password"=>"$2a$10$aPLmuYCDLh23Z74jErof8OEvbw7BnEJXa0tOgjUkyStx9ECxuJH0q", "reset_password_token"=>nil, "reset_password_sent_at"=>nil, "remember_created_at"=>nil, "sign_in_count"=>0, "current_sign_in_at"=>nil, "last_sign_in_at"=>nil, "current_sign_in_ip"=>nil, "last_sign_in_ip"=>nil, "created_at"=>nil, "updated_at"=>nil, "name"=>"firmenadmin", "confirmation_token"=>nil, "confirmed_at"=>nil, "confirmation_sent_at"=>nil, "unconfirmed_email"=>nil, "role"=>0, "invitation_token"=>nil, "invitation_created_at"=>nil, "invitation_sent_at"=>nil, "invitation_accepted_at"=>nil, "invitation_limit"=>nil, "invited_by_id"=>nil, "invited_by_type"=>nil, "invitations_count"=>0, "skip_confirm_change_password"=>true, "tenant_id"=>nil}"
—
Reply to this email directly or view it on GitHub
#52.
from milia.
I work on an empty database i.e. there are no "old" user records. The problem described occurs when I try to add a NEW tenant using the users/sign_up
form.
What I would expect:
- a new tenant record gets created for the organization
- this will then be the first and only tenant record in the DB
- a new user record gets created for the "organizer" with tenant_id=nil
- this will then be the first and only user record in the DB
- an entry in the tenants_users table gets created which joins the two records
To limit it further down: I didn't create a member model yet (I only user a user model for now) and my method Tenant.tenant_signup
is empty. I set up the tenant_id of the users table according to https://github.com/dsaronin/sample-milia-app/blob/master/db/schema.rb as t.integer "tenant_id"
(no default value).
While debugging I saw:
- The following line (before_save callback in
milia/base.rb, line 62
) is passed three times:
raise ::Milia::Control::InvalidTenantAccess unless obj.tenant_id.nil?
- First time: The tenant gets created with the following attrs (obj.tenant_id is nil):
{"id"=>nil, "tenant_id"=>nil, "name"=>"TestCompany", "created_at"=>nil, "updated_at"=>nil}
- Second time:
resource.save (line 122, registrations_controller)
is called which ends up in the before_save callback with the following attrs:
{"id"=>nil, "email"=>"[email protected]", "encrypted_password"=>"$2a$10$mMknzwDEDNlt/ujDI6OmZ.HjgqFD4FI.8L6yFaG9PuItYum20J.3a", "reset_password_token"=>nil, "reset_password_sent_at"=>nil, "remember_created_at"=>nil, "sign_in_count"=>0, "current_sign_in_at"=>nil, "last_sign_in_at"=>nil, "current_sign_in_ip"=>nil, "last_sign_in_ip"=>nil, "created_at"=>nil, "updated_at"=>nil, "name"=>"Admin TestCompany", "confirmation_token"=>nil, "confirmed_at"=>nil, "confirmation_sent_at"=>nil, "unconfirmed_email"=>nil, "role"=>0, "invitation_token"=>nil, "invitation_created_at"=>nil, "invitation_sent_at"=>nil, "invitation_accepted_at"=>nil, "invitation_limit"=>nil, "invited_by_id"=>nil, "invited_by_type"=>nil, "invitations_count"=>0, "skip_confirm_change_password"=>true, "tenant_id"=>nil}
- Info:
Thread.current[:tenant_id] == 1
- Third time (without another call of
resource.save (line 122, registrations_controller)
in between): The before_save callback is called with a tenant_id set to 1:
{"id"=>1, "email"=>"[email protected]", "encrypted_password"=>"$2a$10$mMknzwDEDNlt/ujDI6OmZ.HjgqFD4FI.8L6yFaG9PuItYum20J.3a", "reset_password_token"=>nil, "reset_password_sent_at"=>nil, "remember_created_at"=>nil, "sign_in_count"=>0, "current_sign_in_at"=>nil, "last_sign_in_at"=>nil, "current_sign_in_ip"=>nil, "last_sign_in_ip"=>nil, "created_at"=>Sat, 14 Mar 2015 13:02:17 CET +01:00, "updated_at"=>Sat, 14 Mar 2015 13:02:17 CET +01:00, "name"=>"Admin TestCompany", "confirmation_token"=>"bdcf598f8e019027424268eb7315f48c06afcd49ed8635076cc985636bd191ad", "confirmed_at"=>nil, "confirmation_sent_at"=>Sat, 14 Mar 2015 13:02:17 CET +01:00, "unconfirmed_email"=>nil, "role"=>0, "invitation_token"=>nil, "invitation_created_at"=>nil, "invitation_sent_at"=>nil, "invitation_accepted_at"=>nil, "invitation_limit"=>nil, "invited_by_id"=>nil, "invited_by_type"=>nil, "invitations_count"=>0, "skip_confirm_change_password"=>true, "tenant_id"=>1}
- First time: The tenant gets created with the following attrs (obj.tenant_id is nil):
The last attr hash contains a tenant_id which is obviously wrong and triggers the DB transaction rollback. However I didn't set this tenant_id attribute. I suppose this attr has been set by milia?! Do you have any suggestion where it comes from?
from milia.
You are correct that the attempt to write to users table with tenant_id: 1
is incorrect. I doubt that milia is doing this, as there are no places
there where user records are being created.
Some suggestions:
- review db/migrate migrations to see how the tables are being set up;
check against the reference app (sample-milia-app). - review the code in app/models/tenant.rb, user.rb; check against the
reference app - review the code in config/initializers/milia.rb; check against the
reference app - review app/controllers/application_controller.rb; make sure the correct
position of:
before_action :authenticate_tenant! - make sure that your code does not have any "default_scope" defined
anywhere
If you haven't caught the error in the above 5 steps then,
start with a simpler skeleton of code, such as sample-milia-app. make sure
that is working correctly first. then alter and gradually add your code
into it, until you encounter a change which produces the error.
On Sat, Mar 14, 2015 at 5:31 AM jekuno [email protected] wrote:
I work on an empty database i.e. there are no "old" user records. The
problem described occurs when I try to add a NEW tenant using the
users/sign_up form.What I would expect:
- a new tenant record gets created for the organization
- this will then be the first and only tenant record in the DB
- a new user record gets created for the "organizer" with
tenant_id=nil- this will then be the first and only user record in the DB
- an entry in the tenants_users table gets created which joins the
two recordsTo limit it further down: I didn't create a member model yet (I only user
a user model for now) and my method Tenant.tenant_signup is empty. I set
up the tenant_id of the users table according to
https://github.com/dsaronin/sample-milia-app/blob/master/db/schema.rb as t.integer
"tenant_id" (no default value).While debugging I saw:
- The following line (before_save callback in milia/base.rb, line 62)
is passed three times: raise ::Milia::Control::InvalidTenantAccess
unless obj.tenant_id.nil?
- First time: The tenant gets created with the following attrs
(obj.tenant_id is nil): {"id"=>nil, "tenant_id"=>nil,
"name"=>"TestCompany", "created_at"=>nil, "updated_at"=>nil}- Second time: resource.save (line 122, registrations_controller)
is called which ends up in the before_save callback with the following
attrs: {"id"=>nil, "email"=>"[email protected]",
"encrypted_password"=>"$2a$10$mMknzwDEDNlt/ujDI6OmZ.HjgqFD4FI.8L6yFaG9PuItYum20J.3a",
"reset_password_token"=>nil, "reset_password_sent_at"=>nil,
"remember_created_at"=>nil, "sign_in_count"=>0, "current_sign_in_at"=>nil,
"last_sign_in_at"=>nil, "current_sign_in_ip"=>nil, "last_sign_in_ip"=>nil,
"created_at"=>nil, "updated_at"=>nil, "name"=>"Admin TestCompany",
"confirmation_token"=>nil, "confirmed_at"=>nil,
"confirmation_sent_at"=>nil, "unconfirmed_email"=>nil, "role"=>0,
"invitation_token"=>nil, "invitation_created_at"=>nil,
"invitation_sent_at"=>nil, "invitation_accepted_at"=>nil,
"invitation_limit"=>nil, "invited_by_id"=>nil, "invited_by_type"=>nil,
"invitations_count"=>0, "skip_confirm_change_password"=>true,
"tenant_id"=>nil}- Info: Thread.current[:tenant_id] == 1
- Third time (without another call of resource.save (line 122,
registrations_controller) in between): The before_save callback is
called with a tenant_id set to 1: {"id"=>1, "email"=>"
[email protected]",
"encrypted_password"=>"$2a$10$mMknzwDEDNlt/ujDI6OmZ.HjgqFD4FI.8L6yFaG9PuItYum20J.3a",
"reset_password_token"=>nil, "reset_password_sent_at"=>nil,
"remember_created_at"=>nil, "sign_in_count"=>0, "current_sign_in_at"=>nil,
"last_sign_in_at"=>nil, "current_sign_in_ip"=>nil, "last_sign_in_ip"=>nil,
"created_at"=>Sat, 14 Mar 2015 13:02:17 CET +01:00, "updated_at"=>Sat, 14
Mar 2015 13:02:17 CET +01:00, "name"=>"Admin TestCompany",
"confirmation_token"=>"bdcf598f8e019027424268eb7315f48c06afcd49ed8635076cc985636bd191ad",
"confirmed_at"=>nil, "confirmation_sent_at"=>Sat, 14 Mar 2015 13:02:17 CET
+01:00, "unconfirmed_email"=>nil, "role"=>0, "invitation_token"=>nil,
"invitation_created_at"=>nil, "invitation_sent_at"=>nil,
"invitation_accepted_at"=>nil, "invitation_limit"=>nil,
"invited_by_id"=>nil, "invited_by_type"=>nil, "invitations_count"=>0,
"skip_confirm_change _password"=>true, "tenant_id"=>1}The last attr hash contains a tenant_id which is obviously wrong and
triggers the DB transaction rollback. However I didn't set this tenant_id
attribute. I suppose this attr has been set by milia?! Do you have any
suggestion where it comes from?—
Reply to this email directly or view it on GitHub
#52 (comment).
from milia.
Thanks a lot for your answers. I once more worked through the setup and diffs and finally found the solution:
In your example app at https://github.com/dsaronin/sample-milia-app/blob/master/app/models/tenant.rb
there is the following line: has_many :members, dependent: :destroy
As I wrote before I don't have a members table yet (but only a users table). Accordingly my tenant.rb
model had the following line: has_many :users, dependent: :destroy
This line led to the described behaviour - for whatever reason! I removed it and everything is fine!
Thanks again for your rapid response - maybe you can add a hint to the docs that a has_many :users
relation (both with and without dependent: destroy
) breaks the app.
One additional note:
In https://github.com/dsaronin/sample-milia-app/blob/master/app/models/user.rb the line acts_as_universal_and_determines_account
comes after the devise modules. If there isn't any important reason for this order I would suggest swapping these lines:
That way an InvalidTenantAccess exception (as I had) will be thrown before triggering devise callbacks so tht e.g. no invitation mails will be sent out by devise. (Otherwise devise sends a 'broken' inviation mail for confirming the user account which then doesn't get created due to the exception and transaction rollback)
from milia.
Issue has been fixed (see documentation in https://github.com/jekuno/milia/blob/rails5-support/README.md)
from milia.
Related Issues (20)
- Email address gets lost while inviting a new user HOT 1
- Upgrade path from 1.2.x to 1.3.x HOT 2
- Complare to ErwinM/acts_as_tenant HOT 1
- Setting tenant with JWT. Works with Thread.current_tenant? HOT 2
- Milia::Control::InvalidTenantAccess in MembersController#create no existing valid current tenant HOT 2
- can't install on rails 5.1 HOT 17
- rails 5 sign up raise error "Tenant must exists" HOT 1
- Milia gem installation problem HOT 33
- Can't install milia. plz help. HOT 3
- Can't create table using command rake db:migrate
- Can't install on Rails 5.1.3 HOT 2
- Tenant models with String primary key(ID) instead Integer(ID) - Not working HOT 3
- Error installing milia "Could not find generator 'milia:install'. Maybe you meant 'devise:install', 'migration' or 'mailer'" HOT 3
- Cannot install properly on Rails 5.2.1, uses depreciated "before_filter" HOT 3
- NoMethodError in Milia::RegistrationsController#create HOT 3
- Generator creating references which should be deleted? HOT 1
- [register user/org] tenant create failed - Tenant must exist HOT 3
- Rails 6.0.1 undefined method `skip_before_filter' for Milia::RegistrationsController:Class HOT 8
- Milia gem doesn't uploaded HOT 2
- Future of milia HOT 12
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from milia.