Devise com multipapeis e modelos diferentes com um unico controller de autenticação.

199 views
Skip to first unread message

Luis Gustavo Verri Zacheu

unread,
Oct 5, 2017, 10:39:13 AM10/5/17
to rails-br
Galera seguinte, peguei um sistema legado para mexer onde tinha o seguinte cenário:
Modelos: User, Customer, Merchant cada modelo era um modelo do Devise. E existem outros modelos como SuperAdmin, Operator e etc que para esse modelos é criado um User, pois o modelo User é polimorfico, onde tenho dois attributos role_id e role_type, para definir se esse User é um SuperAdmin, Operator e etc.

Então fiz algumas alterações para as novas necessidades que seria 1 user poder ter multi roles, nesse caso não estou usando mais o role_id e role_type e criei uma tabela auxiliar para armazenar o id do user e suas roles. Até ai fez sentido. 

Porém o problema vem agora, a autenticacao dos apps mobile são feitas no controller do Customer, "ws/customers/" dado login e senha informados retorno o objeto customer, porém surgiu  a necessidade de 1 User ter um determinado papel que pode logar nos apps tb. Então como poderia usar um unico controller e logar tanto o Customer quando o User, já que ambos são modelos diferentes porem do Devise?


Obrigado, espero q alguém possa dar uma luz!

Jonathan Calixto

unread,
Oct 5, 2017, 1:35:42 PM10/5/17
to Grupos Rails BR
Luiz não tem como, se existe varios models com devise vai ser um controller para cada model. Se não for dar muito trabalho seria interessante colocar todos os models de login(devise) em um unico model e usar STi. é o que eu faço.


Atenciosamente,

Jonathan Celestino Calixto
Desenvolvedor Web Ruby on Rails
email:     jonathan...@gmail.com
msn:       jonathan...@gmail.com
github:    https://github.com/jonathanccalixto
skype:    jonathanccalixto
twitter:    jonathanccalixt

--
--
Você recebeu essa mensagem porquê está inscrito no Google
Groups "rails-br".
Para enviar uma mensagem para o grupo, mande um email para rail...@googlegroups.com
Para se descadastrar, mande um e-mail para
rails-br+unsubscribe@googlegroups.com
Visite o grupo em http://groups.google.com/group/rails-br?hl=pt-BR
Leia nossa política de uso: https://goo.gl/BHB0wS
---
Você recebeu essa mensagem porque está inscrito no grupo "rails-br" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para rails-br+unsubscribe@googlegroups.com.
Para mais opções, acesse https://groups.google.com/d/optout.

Luis Gustavo Verri Zacheu

unread,
Oct 5, 2017, 2:28:02 PM10/5/17
to rails-br
Hum, então Jonathan quer dizer que se eu pegar meu model Customer e remover todas as referencias do devise dele e deixar somente o que faz sentido para esse model e herdar de User, poderia manter as minhas regras nesse modelo e no final ele seria um user, correto? E ainda teria a regrado do user de multi papeis na qual eu controlo com uma tabela e não com o role_id e role_type?

Obrigado! 


Em quinta-feira, 5 de outubro de 2017 14:35:42 UTC-3, Jonathan C. Calixto escreveu:
Luiz não tem como, se existe varios models com devise vai ser um controller para cada model. Se não for dar muito trabalho seria interessante colocar todos os models de login(devise) em um unico model e usar STi. é o que eu faço.


Atenciosamente,

Jonathan Celestino Calixto
Desenvolvedor Web Ruby on Rails
email:     jonathan...@gmail.com
msn:       jonathan...@gmail.com
github:    https://github.com/jonathanccalixto
skype:    jonathanccalixto
twitter:    jonathanccalixt

Em 5 de outubro de 2017 11:39, Luis Gustavo Verri Zacheu <luisz...@gmail.com> escreveu:
Galera seguinte, peguei um sistema legado para mexer onde tinha o seguinte cenário:
Modelos: User, Customer, Merchant cada modelo era um modelo do Devise. E existem outros modelos como SuperAdmin, Operator e etc que para esse modelos é criado um User, pois o modelo User é polimorfico, onde tenho dois attributos role_id e role_type, para definir se esse User é um SuperAdmin, Operator e etc.

Então fiz algumas alterações para as novas necessidades que seria 1 user poder ter multi roles, nesse caso não estou usando mais o role_id e role_type e criei uma tabela auxiliar para armazenar o id do user e suas roles. Até ai fez sentido. 

Porém o problema vem agora, a autenticacao dos apps mobile são feitas no controller do Customer, "ws/customers/" dado login e senha informados retorno o objeto customer, porém surgiu  a necessidade de 1 User ter um determinado papel que pode logar nos apps tb. Então como poderia usar um unico controller e logar tanto o Customer quando o User, já que ambos são modelos diferentes porem do Devise?


Obrigado, espero q alguém possa dar uma luz!

--
--
Você recebeu essa mensagem porquê está inscrito no Google
Groups "rails-br".
Para enviar uma mensagem para o grupo, mande um email para rail...@googlegroups.com
Para se descadastrar, mande um e-mail para

Visite o grupo em http://groups.google.com/group/rails-br?hl=pt-BR
Leia nossa política de uso: https://goo.gl/BHB0wS
---
Você recebeu essa mensagem porque está inscrito no grupo "rails-br" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para rails-br+u...@googlegroups.com.

Luis Gustavo Verri Zacheu

unread,
Oct 5, 2017, 2:32:33 PM10/5/17
to rails-br
Outro ponto seria, eu precisaria definir dentro de Customer < User que ele belongs_to :user?

Jonathan Calixto

unread,
Oct 5, 2017, 3:09:52 PM10/5/17
to Grupos Rails BR
então, é parecido com isso.

No meu caso eu tenho uma tabela chamada users e tenho basicamente 6 models de usuarios que herdam de User.

# users table
users
  - name:string
  - type:string # sem este campo a magica não funciona para STI
  - demais campos do devise

aí eu tenho o model base que é o User onde eu coloco todas as regras de autenticação e todas as regras em comum entre os users

tenho um model chamado Admin, que não tem dada de especial, mas é usado nas permissões/perfis para diferenciar os acessos.

tenho um model chamado SponsorUser, que tem como referencia um has_one com o model Sponsor que é um usuario dos clientes (seria o seu customer)

tenho um usuario chamado EmployeerUser que tem referencia has_one com o model Employee que é um usuario para a equipe de suporte

tenho um usuario chamado SystemUser que não loga mas é usado para referenciar alterações do sistema

e tenho um usuario chamado Accountant que é usado para fiscais do governo para fiscalizar o sistema

desconsiderando os nome, destes 6 models, 5 são usuais no sistem Admin, SponsorUser, SystemUser, Accountant


e todos estão na tabelas users e como eu falei, eu mantive estrutura para facilitar na utulização do Pundit, pois eu recebeo o usuario e como é tudo do tipo User não preciso ficar alterando código e tenho "varios usuários diferentes" que me auxilia na autorização do sistema.






Atenciosamente,

Jonathan Celestino Calixto
Desenvolvedor Web Ruby on Rails
email:     jonathan...@gmail.com
msn:       jonathan...@gmail.com
github:    https://github.com/jonathanccalixto
skype:    jonathanccalixto
twitter:    jonathanccalixt


Visite o grupo em http://groups.google.com/group/rails-br?hl=pt-BR
Leia nossa política de uso: https://goo.gl/BHB0wS
---
Você recebeu essa mensagem porque está inscrito no grupo "rails-br" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para rails-br+unsubscribe@googlegroups.com.

Jonathan Calixto

unread,
Oct 5, 2017, 3:13:31 PM10/5/17
to Grupos Rails BR
se precisar de algum auxilio especifico estou a disposição.


Atenciosamente,

Jonathan Celestino Calixto
Desenvolvedor Web Ruby on Rails
email:     jonathan...@gmail.com
msn:       jonathan...@gmail.com
github:    https://github.com/jonathanccalixto
skype:    jonathanccalixto
twitter:    jonathanccalixt

Luis Gustavo Verri Zacheu

unread,
Oct 5, 2017, 3:42:04 PM10/5/17
to rails-br
Posso adicionar vc no meu skype?

Abs

Marcelo Junior

unread,
Oct 5, 2017, 4:53:47 PM10/5/17
to rail...@googlegroups.com
@Luis Gustavo 

O que tem de tão diferente nesses user para ter tantas modelos? User é p ter so campos referente a autenticação (email, password) e no maximo um campo role_id/type_id para ser usado na autorização. Se forem N roles/types vc deve usar has_many ou ENUM ou JSON.


Visite o grupo em http://groups.google.com/group/rails-br?hl=pt-BR
Leia nossa política de uso: https://goo.gl/BHB0wS
---
Você recebeu essa mensagem porque está inscrito no grupo "rails-br" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para rails-br+unsubscribe@googlegroups.com.

Jonathan Calixto

unread,
Oct 5, 2017, 11:07:52 PM10/5/17
to Grupos Rails BR
pode sim


Atenciosamente,

Jonathan Celestino Calixto
Desenvolvedor Web Ruby on Rails
email:     jonathan...@gmail.com
msn:       jonathan...@gmail.com
github:    https://github.com/jonathanccalixto
skype:    jonathanccalixto
twitter:    jonathanccalixt


Visite o grupo em http://groups.google.com/group/rails-br?hl=pt-BR
Leia nossa política de uso: https://goo.gl/BHB0wS
---
Você recebeu essa mensagem porque está inscrito no grupo "rails-br" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para rails-br+unsubscribe@googlegroups.com.

Luis Gustavo Verri Zacheu

unread,
Oct 6, 2017, 10:24:21 AM10/6/17
to rails-br
Então Marcelo, o User tem os campos referente a autenticação, porém haviam outros modelos de usuário no sistema que criavam um user ao invés de herdar dele, utilizando o os campos role_id e role_type, e o modelo Customer era um modelo do devise assim como User. Isso foi uma decisão de quem fez no inicio.
Porém agora o que eu fiz, foi Manter somente o User e usar uma has_many para uma tabela de roles, onde, 1 User pode ter mais de uma role. Isso para a parte de administração do sistema.
Porém agora para a parte do mobile, como o único modelo que era autenticado é o Customer não havia mexido nele. Mas agora existe a necessidade de Um Customer ou um User poder logar. E o customer possui vários campos q não são comuns para o user.

Eu cheguei a fazer um teste utilizando o conceito de STI porém quando vou persistir esta rando rollback. :(

Abs.

Marcelo Junior

unread,
Oct 6, 2017, 3:46:40 PM10/6/17
to rail...@googlegroups.com
Boa tarde.

Cara um problema por vez. Primeiro tem que resolver a autenticação. 

Os forms de login no mobile e no web tem so email e senha? A unica diferente é a rota? Se for isso, tem como fazer varias rotas bater no mesmo controller de autenticação. Assim vc resolve isso sem força a barra.

Campos adicionais? Vc pode tratar isso em outro controller. Vc poder colocar tudo em User e validar de acordo com o type_id. Ou levar esse adicionais para um model Perfil.





Visite o grupo em http://groups.google.com/group/rails-br?hl=pt-BR
Leia nossa política de uso: https://goo.gl/BHB0wS
---
Você recebeu essa mensagem porque está inscrito no grupo "rails-br" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para rails-br+unsubscribe@googlegroups.com.

Luis Gustavo Verri Zacheu

unread,
Oct 6, 2017, 4:22:45 PM10/6/17
to rails-br
Boa tarde!

Sim tanto na web quanto no mobile são email e senha. Se tivesse uma única rota, onde eu verificasse se é User ou Customer, já facilitaria muito. 
Então com relação a adicionar todos os campos em um unico modelo, pensei nisso, mas não sei se seria o ideal, O outro ponto que pensei, seria manter o model Customer, porém sem os atributos do devise, e para 1 Customer eu crio um user e nesse user eu adiciono um role_type do tipo Customer, talvez faria mais sentido. 

Luis Gustavo Verri Zacheu

unread,
Oct 6, 2017, 4:25:47 PM10/6/17
to rails-br
Outra coisa Marcelo,  hoje praticamente eu estou somente fornecendo APIs nesse projeto, pois ele tem uma interface usando ActiveAdmin mas resolvemos criar um outro projeto para lidar com o front-end.

Marcelo Junior

unread,
Oct 6, 2017, 4:35:35 PM10/6/17
to rail...@googlegroups.com
 Se tivesse uma única rota, onde eu verificasse se é User ou Customer, já facilitaria muito. 

Isso vc pode fazer logo. Ai ja resolve 1 ponto
Proximo é analisar se vai pesar tanto ter todos os campo em user ou em outro modelo. Porem o controller deve ser outro diferente do devise para vc desacoplar as coisas. 


Visite o grupo em http://groups.google.com/group/rails-br?hl=pt-BR
Leia nossa política de uso: https://goo.gl/BHB0wS
---
Você recebeu essa mensagem porque está inscrito no grupo "rails-br" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para rails-br+unsubscribe@googlegroups.com.

Luis Gustavo Verri Zacheu

unread,
Oct 6, 2017, 4:42:56 PM10/6/17
to rails-br
Certo, Obrigado Marcelo.

Thiago Miranda

unread,
Oct 6, 2017, 8:33:21 PM10/6/17
to rails-br
Cara,

STI resolve o problema no Devise.
Tenho vários projetos funcionando assim.

Qual o banco?

Se for postgres, o STI também resolve o problema.
Crie um field :profile, :details (ou o nome que desejar), com o tipo JSONB.

Exemplo:
class User < ApplicationRecord
# Toda a bagaça do Devise aqui...
end


Aí... Company tem CNPJ, Customer CPF, certo?
Então você separa a lógica em cada model de acordo com o tipo de usuário
class Company < User
  attr_accessor
:cnpj

 
def cnpj
    profile
['cnpj']
 
end

 
def cnpj=(c)
    profile
['cnpj'] = c
 
end

end


class Customer < User
  attr_accessor
:cpf

 
def cpf
    profile
['cpf']
 
end

 
def cnpj=(c)
    profile
['cpf'] = c
 
end

end


Também seria possível utilizar validações normalmente em :cnpj e :cpf.
Ao meu ver STI é muito mais claro, e quando você instanciar o objeto (Customer, Company), o rails automaticamente retornará o tipo correto.
Ou seja, se fizer um User.find(1) e User#1 for um Customer, o Objeto retornado será Customer e não User.
Acredito que isso economizaria muitos if role_type == 'blablabla'


Marcelo Junior

unread,
Oct 7, 2017, 3:42:12 PM10/7/17
to rail...@googlegroups.com
STI é muito massa tbm.

So que no teu caso, 1 usuario tem N roles/papeis. Com STI 1 cliente teria 1 login para cada role/papel. Ja vi soluções em que o cliente escolhe em qual role/papel ele quer logar. Poder gerar esforço adicional em vc manter 1 controller por role/papel. 
Porém se separar autenticação de autorização, pode trabalhar muito menos. Autenticação so precisa de email/password/app_id/secret_id. Já autorização so precisa de um role/papel, aqui pode usar JSONB, ENUM, BelongsTo, HasMany. Essa separação vai t ajudar mt na manutencação, se tiver problema na autenticação vai resolver sem sabe que existe autorização, e o contrário tbm.

Com todas essas dicas da glra. É melhor vc parar e analisar antes de codar. Assim vc soma as dicas e monta a sua solução. 
Boa sorte!

--
--
Você recebeu essa mensagem porquê está inscrito no Google
Groups "rails-br".
Para enviar uma mensagem para o grupo, mande um email para rail...@googlegroups.com
Para se descadastrar, mande um e-mail para

Visite o grupo em http://groups.google.com/group/rails-br?hl=pt-BR
Leia nossa política de uso: https://goo.gl/BHB0wS
---
Você recebeu essa mensagem porque está inscrito no grupo "rails-br" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para rails-br+unsubscribe@googlegroups.com.

Luis Gustavo Verri Zacheu

unread,
Oct 9, 2017, 9:02:41 AM10/9/17
to rails-br
Poxa galera muito obrigado pelas dias, com certeza Marcelo estou analisando qual é a melhor forma sim! Até mesmo como se trata de um sistema legado e ja tem dados populados na atual estrutura. 

Thiago é Postgres sim. 

Mais uma vez, obrigado pessoal.

Visite o grupo em http://groups.google.com/group/rails-br?hl=pt-BR
Leia nossa política de uso: https://goo.gl/BHB0wS
---
Você recebeu essa mensagem porque está inscrito no grupo "rails-br" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para rails-br+u...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages