Git Product home page Git Product logo

Comments (5)

dsaronin avatar dsaronin commented on August 25, 2024

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 again

As 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, :validatable

The 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.

jekuno avatar jekuno commented on August 25, 2024

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}

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.

dsaronin avatar dsaronin commented on August 25, 2024

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:

  1. review db/migrate migrations to see how the tables are being set up;
    check against the reference app (sample-milia-app).
  2. review the code in app/models/tenant.rb, user.rb; check against the
    reference app
  3. review the code in config/initializers/milia.rb; check against the
    reference app
  4. review app/controllers/application_controller.rb; make sure the correct
    position of:
    before_action :authenticate_tenant!
  5. 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 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}

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.

jekuno avatar jekuno commented on August 25, 2024

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.

jekuno avatar jekuno commented on August 25, 2024

Issue has been fixed (see documentation in https://github.com/jekuno/milia/blob/rails5-support/README.md)

from milia.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.