[Lift] ProtoUser for Record?

203 views
Skip to first unread message

Nolan Darilek

unread,
May 6, 2010, 6:35:58 PM5/6/10
to liftweb
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Since lots of the more exciting (to me, anyway) new persistence options
are Record-based, I was wondering if anyone had done a port of
ProtoUser? If so, I'm wondering if it might be something to contribute
back to Lift, especially before 2.0?

If not, then I may take a crack at it, if only to publish something in
Gist form. Is there anything missing from Record in general, or
lift-mongodb-record in particular (since that's where my interests lie)
that would block such a port? Is it just a matter of porting the Mapper
idioms to Record ones, or is there more to it?

Thanks.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkvjRE4ACgkQIaMjFWMehWIsYACfQd+e/iccu8YhFjc9JAmIQe1f
GucAnRl89G9pdUhfpFDx7e9N5p2Bmv7u
=aVYN
-----END PGP SIGNATURE-----

--
You received this message because you are subscribed to the Google Groups "Lift" group.
To post to this group, send email to lif...@googlegroups.com.
To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.

Peter Robinett

unread,
May 6, 2010, 6:44:04 PM5/6/10
to Lift
I think it should be pretty straight-forward to port over. It's been
discussed on the mailing list before, just no one has done it. That
being said, ProtoUser seems to have some issues and to not be popular
with many committers (and thus is kind of orphaned). I've actually
been thinking about whipping up a quick persistance-agnostic User
trait and see whether it would have legs.

Peter

On May 7, 12:35 am, Nolan Darilek <no...@thewordnerd.info> wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Since lots of the more exciting (to me, anyway) new persistence options
> are Record-based, I was wondering if anyone had done a port of
> ProtoUser? If so, I'm wondering if it might be something to contribute
> back to Lift, especially before 2.0?
>
> If not, then I may take a crack at it, if only to publish something in
> Gist form. Is there anything missing from Record in general, or
> lift-mongodb-record in particular (since that's where my interests lie)
> that would block such a port? Is it just a matter of porting the Mapper
> idioms to Record ones, or is there more to it?
>
> Thanks.
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.10 (GNU/Linux)
> Comment: Using GnuPG with Mozilla -http://enigmail.mozdev.org/

Naftoli Gugenheim

unread,
May 6, 2010, 6:50:25 PM5/6/10
to liftweb
If there would be a trait all the persistence-based Users could conform to as well as most custom User classes, it would be great to have in Lift. If it could be abstracted properly there could be more rich and generally useful user-based functionality in webkit probably.

I think that someone was planning to refactor Mapper's ProtoUser to make it more extensible.

Timothy Perrett

unread,
May 6, 2010, 7:22:56 PM5/6/10
to lif...@googlegroups.com
Ross, is already covering this in his re-vamp of record... his input here is critical as last time him and I spoke about this his ideas / concepts were in line with the overall vision for record.

Cheers, Tim

Nolan Darilek

unread,
May 6, 2010, 7:38:39 PM5/6/10
to lif...@googlegroups.com
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 05/06/2010 06:22 PM, Timothy Perrett wrote:
> Ross, is already covering this in his re-vamp of record... his input here is critical as last time him and I spoke about this his ideas / concepts were in line with the overall vision for record.
>

Cool, is there a ticket tracking this anywhere? It isn't something I
need immediately, but is something I'd like to watch for the medium term.

Glad someone else is working on this. While I could certainly
cut-n-paste Mapper code and change idioms, I don't think I'm smart
enough to do it justice. :)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkvjUv8ACgkQIaMjFWMehWIz/gCdFua8o9IkGn4gDrPC/nOqTgcA
thwAnjJST83rZiPZ882mmEmzio46+TmC
=ZgEA

Timothy Perrett

unread,
May 6, 2010, 7:57:47 PM5/6/10
to lif...@googlegroups.com
This is the whole point, its not just cut and paste. There are some seriously sub-optiomal things in proto user and a heavy refactoring while we have the chance is important. I would object to cut and paste of mapper proto user; that is not what we need IMO.

There is no ticket (yet) - its all in with the record re-factor that has been off-line so far.

Cheers, Tim

Ross Mellgren

unread,
May 7, 2010, 1:42:00 AM5/7/10
to lif...@googlegroups.com
My plan was to implement trait(s) that represent a "storable" record that supports some basic idioms like insertion, fetching all, fetching by ID or something like that and then building CRUDify on top of those, and then do something similar for ProtoUser, e.g. some traits that represent a minimal user record and user record storage, then build the UI on top of the traits. Then mix together the user traits into a basic user model, to make it easy to start off.

My current task is to bring the Squeryl Record integration up to par so that there is a reasonable RDBMS backend for record, then work on that stuff.

There's no ticket for the future stuff yet.

-Ross

Timothy Perrett

unread,
May 7, 2010, 5:23:29 AM5/7/10
to lif...@googlegroups.com
Go Ross!

Like the sound of it :-)

Cheers, Tim

Peter Robinett

unread,
May 7, 2010, 11:49:03 AM5/7/10
to Lift
Here's my stab at it: http://gist.github.com/393607

SimpleUser and MetaSimpleUser are basic traits in
net.liftweb.persistentce that define what a user is and some actions
that can be preformed relevant to users. SimpleUser has firstName,
lastName, email, password, and passwordSalt methods, implementations
of which must return Strings. MetaSimpleUser has various methods to
log a user in and out of the running app.

MapperUser and MetaMapperUser are examples of how a Mapper model can
be built on top of SimpleUser and MetaSimpleUser. It's not complete
but works - uncomment ExampleUser and MetaExampleUser for proof.

So, I feel like I'm on the right track. What do you think? Comments
and code forks welcome.

Peter
> >>> Comment: Using GnuPG with Mozilla -http://enigmail.mozdev.org/
>
> >>> iEYEARECAAYFAkvjUv8ACgkQIaMjFWMehWIz/gCdFua8o9IkGn4gDrPC/nOqTgcA
> >>> thwAnjJST83rZiPZ882mmEmzio46+TmC
> >>> =ZgEA
> >>> -----END PGP SIGNATURE-----
>
> >>> --
> >>> You received this message because you are subscribed to the Google Groups "Lift" group.
> >>> To post to this group, send email to lif...@googlegroups.com.
> >>> To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
> >>> For more options, visit this group athttp://groups.google.com/group/liftweb?hl=en.
>
> >> --
> >> You received this message because you are subscribed to the Google Groups "Lift" group.
> >> To post to this group, send email to lif...@googlegroups.com.
> >> To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
> >> For more options, visit this group athttp://groups.google.com/group/liftweb?hl=en.
>
> > --
> > You received this message because you are subscribed to the Google Groups "Lift" group.
> > To post to this group, send email to lif...@googlegroups.com.
> > To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
> > For more options, visit this group athttp://groups.google.com/group/liftweb?hl=en.
>
> --
> You received this message because you are subscribed to the Google Groups "Lift" group.
> To post to this group, send email to lif...@googlegroups.com.
> To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
> For more options, visit this group athttp://groups.google.com/group/liftweb?hl=en.

Jeppe Nejsum Madsen

unread,
May 7, 2010, 12:05:54 PM5/7/10
to lif...@googlegroups.com
Peter Robinett <pe...@bubblefoundry.com> writes:

> Here's my stab at it: http://gist.github.com/393607

Cool!

> SimpleUser and MetaSimpleUser are basic traits in
> net.liftweb.persistentce that define what a user is and some actions
> that can be preformed relevant to users. SimpleUser has firstName,
> lastName, email, password, and passwordSalt methods, implementations
> of which must return Strings. MetaSimpleUser has various methods to
> log a user in and out of the running app.

What is the main purpose? To have some ProtoUser stuff that is usable
with different persistence backends or more a general interface (in
webkit) to some abstract authorization/authentication mechanism?

While I can see value in both, I think it could be nice with the
latter. This would allow lots of useful functionality (ie widgets,
sitemap, snippets etc) to be written against this interface and not care
about the impl afterwards.

You would need the definition of a SimpleUser (ie id, firstname,
lastname, email etc. but probably not password, this is backend
specific) and "Meta" functionality of loggedIn_?, currentUser, role, logout
etc. but probably not login (since it may be an openid, ldap or Megatron
backend that all require different impls)

Thoughts?

/Jeppe

Timothy Perrett

unread,
May 7, 2010, 12:13:03 PM5/7/10
to lif...@googlegroups.com
Sorry, can I just say how much i love that everyone has adopted megatron as being a well defined term in the Lift community... most amusing!

On 7 May 2010, at 17:05, Jeppe Nejsum Madsen wrote:

> or Megatron
> backend that all require different impls)

Peter Robinett

unread,
May 7, 2010, 12:31:48 PM5/7/10
to Lift
Thanks, Jeppe.

My purpose today was simply to have some ProtoUser stuff that is
usable with different persistent backends but think it would be really
cool if it was as general as possible. I definitely agree that things
should be written against the SimpleUser interface and not care about
the implementation used: that's one reason why I use Strings most
places (I tried to do some fancy type things but it became more
trouble than it was worth).

That being said, since definitions can be overridden is it such a bad
thing that MetaSimpleUser has a login def? If you want to avoid
overriding defs in traits and classes based upon SimpleUser maybe it
should be broken down into traits like:
SimpleUser
SimpleUserName
SimpleUserEmail
SimpleUserPassword
MapperUser extends SimpleUser with SimpleUserName with
SimpleUserPassword ...

This would mean that SimpleUser is REALLY simple, to the point of
being practically (actually?) empty.

I note that you mentioned roles. I deliberately didn't include
anything like ProtoUser's superUser field, as roles can be anything
from super simple (see superUser) to quite complex (see NSIT RBAC
systems) and aren't even always needed.

Peter

PS I seemed to have missed Tim's Megatron meme but I'm all for
Transformers shout-outs. ;-)

Timothy Perrett

unread,
May 7, 2010, 12:44:24 PM5/7/10
to lif...@googlegroups.com
Peter,

Whilst I applaud this effort, there is something about it that feels, well, out of sync with what we are trying to do going forward.

Maybe i'm just freaking for no reason, but it just feels a little wrong. Perhaps you should describe your use case again -- as Jeppe said, i see the two places this kind of thing is applicable, rather, it just feels at odds with where record is going?

Perhaps i'm missing something - if you could help me understand how you are going to hook up with the existing and future record infrastructure that might help me understand the value this might be adding; its a little invisible for right now.

Cheers, Tim

Ross Mellgren

unread,
May 7, 2010, 2:16:44 PM5/7/10
to lif...@googlegroups.com
I'm not giving this a full treatment as I'm at work right now and can't look in detail.

My plan was to create a proto user general trait that is specific to record, but not to any particular type of record. That is, it defines which fields have to be there for the Metatron UI to be implementable, something more like

trait BaseUserRecord {
// absolute minimum a user needs
def username: StringField[_]
def password: PasswordField[_]
}

trait EmailUsername {
self: BaseUserRecord =>
def email: StringField[_]
def username = email
}

abstract class UserRecord[MyType <: UserRecord[MyType]] with BaseUserRecord {
val username = new StringField(this, 100)
val firstName = new StringField(this, 100)
}

I don't like with your code that you have to name your fields something obscure (fn, ln) so that you can save the proper names (firstName, lastName) for the fields themselves.

The other thing I'm trying to avoid in general is mixing things into the MetaRecord. The reason is multiple backends. Consider if you had users that could be stored in either Mongo or SQL (say you're migrating from one to the other or something) There might be separate MetaRecords, and it seems like you'd have duplication if you made it so you had to mix into the MetaRecord. To this end, I was thinking the user management would be a completely separate object, rather than mixing into the hierarchy. This would have to tie into some more general idea of storable records as I mentioned though.

-Ross

Timothy Perrett

unread,
May 7, 2010, 2:46:24 PM5/7/10
to lif...@googlegroups.com
Ross, this is much more like what I had in mind. Kudos.

This relies on the revisions to record right?


Sent from my iPhone

Ross Mellgren

unread,
May 7, 2010, 2:56:19 PM5/7/10
to lif...@googlegroups.com
Well other than this completely glosses over how to get users from the backing store or persist changed ones back to the backing store, no it doesn't depend on any new stuff.

The general concept of a backing store agnostic storable record I've thought about and sketched a few things, but I haven't spent a ton of time on it. I'd really like to, but I want to get the squeryl integration done so that people have more than just document-oriented stores that come "in the box" (Mongo and Couch)

I don't think offhand the storable record will require alterations to the currently existing record stuff, it would be more of a design pattern + additional traits thing, but since I haven't implemented it fully I don't know if there are sticking points that require more underlying adjustments.

-Ross

Timothy Perrett

unread,
May 7, 2010, 3:06:23 PM5/7/10
to lif...@googlegroups.com
Right, the Squeryl integration is more important for the moment; lets get that squared away.

Peter, are you comfortable attempting to work on a design similar to what Ross outlined? I think his proposal his much more robust than what has already been discussed in this thread.

Cheers, Tim

Peter Robinett

unread,
May 7, 2010, 8:07:59 PM5/7/10
to Lift
Guys, I like your suggestions and accept them. What Ross outlined is
quite similar to my last point. I agree that the obscure field names
are undesirable, it was just what I managed to come up with over the
course of an hour's work this afternoon. Like I said, this was just a
first stab since code speaks louder than words, if you will, and I
felt that improving ProtoUser/bringing it to Record has been debated
enough that it was time for some actual code.

First, let me just say that I have never used Record. It sounds great
but I'm using SQL databases for my projects. Given this, take what you
will from my comments.

I would like something that is truly persistence-agnostic to the point
where the developer can use an SQL database. This is especially useful
for people coming to Lift from other frameworks where using an SQL
database and the framework's user implementation is standard. We don't
HAVE to please them, of course, but I think we all agree that there's
real value in having both good SQL support and user modeling.
Supporting SQL databases today means Mapper. If the Squerly
integration does happen soon (and I understand it's your, Tim's and
Ross', priority – great!), then are we the Lift community going to
completely depreciate Mapper ASAP? If so, then my desire to also
support Mapper is moot. If not, then I maintain that Mapper support is
reasonable. This requires something more general than even plain
Record and has the added benefit of allowing additional persistence
frameworks, such as JPA.

Ross, if I understand correctly you want to avoid mixing into
MetaRecord because some User entries may live, say, on an SQL database
and others on a Mongo datastore. It's an interesting use case but
seems like it has the potential to get quite tricky. Is there anything
in Record that already does this? How would you suggest handling these
different MetaRecords? Pass some MetaRecord object when creating a
User instance with the opportunity to use the app's default MetaRecord
object? And what about querying for a User? First try one MetaRecord
source and then another?

Just to wrap up, I'm willing to work on a design along whatever lines
we all decide is best but I would like to get my questions answered
first.

Thanks,
Peter
> >> For more options, visit this group athttp://groups.google.com/group/liftweb?hl=en.
>
> > --
> > You received this message because you are subscribed to the Google Groups "Lift" group.
> > To post to this group, send email to lif...@googlegroups.com.
> > To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
> > For more options, visit this group athttp://groups.google.com/group/liftweb?hl=en.
>
> --
> You received this message because you are subscribed to the Google Groups "Lift" group.
> To post to this group, send email to lif...@googlegroups.com.
> To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
> For more options, visit this group athttp://groups.google.com/group/liftweb?hl=en.

Ross Mellgren

unread,
May 7, 2010, 10:22:24 PM5/7/10
to lif...@googlegroups.com, Lift
Responses inline.

On May 7, 2010, at 8:07 PM, Peter Robinett <pe...@bubblefoundry.com> wrote:

> Guys, I like your suggestions and accept them. What Ross outlined is
> quite similar to my last point. I agree that the obscure field names
> are undesirable, it was just what I managed to come up with over the
> course of an hour's work this afternoon. Like I said, this was just a
> first stab since code speaks louder than words, if you will, and I
> felt that improving ProtoUser/bringing it to Record has been debated
> enough that it was time for some actual code.

Always admirable. In case you think otherwise I'm just trying to provide some constructive commentary while reconciling the ideas I had in mind with the code that you've written.

>
> First, let me just say that I have never used Record. It sounds great
> but I'm using SQL databases for my projects. Given this, take what you
> will from my comments.
>
> I would like something that is truly persistence-agnostic to the point
> where the developer can use an SQL database. This is especially useful

Record is intended to be that persistence-agnostic abstraction. You can have a SQL backend, a document store backend (e.g. Couch), LDAP, etc.

So, my plan was to target record and then leverage the abstractions already there to gain the persistence agnostic-ness there. I think basing User traits on record might make them considerably simpler.

Of course, there will be duplication with mapper there, but I think it's worth it to not have to abstract around it.

> for people coming to Lift from other frameworks where using an SQL
> database and the framework's user implementation is standard. We don't
> HAVE to please them, of course, but I think we all agree that there's
> real value in having both good SQL support and user modeling.

I think SQL is great for many applications, especially with the advent in the recent years of very good SQL integrations like squeryl, SQLAlchemy and so on.

> Supporting SQL databases today means Mapper. If the Squerly
> integration does happen soon (and I understand it's your, Tim's and
> Ross', priority – great!), then are we the Lift community going to
> completely depreciate Mapper ASAP? If so, then my desire to also

I have no idea :-)

I think it's up to the community.

> support Mapper is moot. If not, then I maintain that Mapper support is
> reasonable. This requires something more general than even plain
> Record and has the added benefit of allowing additional persistence
> frameworks, such as JPA.
>
> Ross, if I understand correctly you want to avoid mixing into
> MetaRecord because some User entries may live, say, on an SQL database
> and others on a Mongo datastore. It's an interesting use case but
> seems like it has the potential to get quite tricky. Is there anything
> in Record that already does this? How would you suggest handling these
> different MetaRecords? Pass some MetaRecord object when creating a
> User instance with the opportunity to use the app's default MetaRecord
> object? And what about querying for a User? First try one MetaRecord
> source and then another?

It sure can get quite tricky... I've gone through a couple iterations and still haven't hit on something that feels right all around. I've considered some models where the store is separate object from the MetaRecord and it seemed a little cleaner so that's where my comment came from. That said, as I said I haven't really converged on a design I would propose, so I can't answer those questions.

-Ross

Jeppe Nejsum Madsen

unread,
May 8, 2010, 4:30:29 AM5/8/10
to lif...@googlegroups.com
Ross Mellgren <dri...@gmail.com> writes:

> Responses inline.
>
> On May 7, 2010, at 8:07 PM, Peter Robinett <pe...@bubblefoundry.com> wrote:
>
>> Guys, I like your suggestions and accept them. What Ross outlined is
>> quite similar to my last point. I agree that the obscure field names
>> are undesirable, it was just what I managed to come up with over the
>> course of an hour's work this afternoon. Like I said, this was just a
>> first stab since code speaks louder than words, if you will, and I
>> felt that improving ProtoUser/bringing it to Record has been debated
>> enough that it was time for some actual code.
>
> Always admirable. In case you think otherwise I'm just trying to provide some constructive commentary while reconciling the ideas I had in mind with the code that you've written.
>
>>
>> First, let me just say that I have never used Record. It sounds great
>> but I'm using SQL databases for my projects. Given this, take what you
>> will from my comments.
>>
>> I would like something that is truly persistence-agnostic to the point
>> where the developer can use an SQL database. This is especially useful
>
> Record is intended to be that persistence-agnostic abstraction. You can have a SQL backend, a document store backend (e.g. Couch), LDAP, etc.
>
> So, my plan was to target record and then leverage the abstractions already there to gain the persistence agnostic-ness there. I think basing User traits on record might make them considerably simpler.

But I think the User/ProtUser concept has more uses than just
Record-based persistence backends (ie JPA). It would be nice to be able
to support this as well. I'm not sure what we loose if don't target
Record directly?

/Jeppe

[...]

Timothy Perrett

unread,
May 8, 2010, 6:39:34 AM5/8/10
to lif...@googlegroups.com
Jeppe,

Hear what your saying, but dont we want Record to be the unified persistence tier in Lift? One could make a Record+JPA implementation...

Cheers, Tim

Timothy Perrett

unread,
May 8, 2010, 6:48:05 AM5/8/10
to lif...@googlegroups.com
Peter,

Many moons ago before you joined the Lift community we made the choice that Record was going to be the main persistence mechanism in Lift going forward. So, it took us a lot longer than anyone could have anticipated to get this far, and thus mapper too evolved in parallel.

Mapper in its current form will continue to be supported for at least 3 years from any official move to Record... it would be a nightmare for users otherwise. The original plan was that the mapper internals would be migrated to Record so you would have a MapperRecord etc; so in some senses, mapper will still be around even after the current modules deprecation.

Personally though, as soon as the Squeryl stuff becomes available, I personally wont be using mapper as Squeryl is so much nice syntactically speaking. The bottom line is that Record will soon be supporting RDBMS... that was always the intention. What i'm really driving at is I would rather see resource spent on realising this long term goal, rather than fork some other system for Proto-style traits that will end up not fitting with the project strategy going forward. Record FTW.

Cheers, Tim

Ross Mellgren

unread,
May 8, 2010, 11:53:58 AM5/8/10
to lif...@googlegroups.com
On May 8, 2010, at 4:30 AM, Jeppe Nejsum Madsen wrote:
> Ross Mellgren <dri...@gmail.com> writes:
>> Responses inline.
>>
>> On May 7, 2010, at 8:07 PM, Peter Robinett <pe...@bubblefoundry.com> wrote:
>>
>>> Guys, I like your suggestions and accept them. What Ross outlined is
>>> quite similar to my last point. I agree that the obscure field names
>>> are undesirable, it was just what I managed to come up with over the
>>> course of an hour's work this afternoon. Like I said, this was just a
>>> first stab since code speaks louder than words, if you will, and I
>>> felt that improving ProtoUser/bringing it to Record has been debated
>>> enough that it was time for some actual code.
>>
>> Always admirable. In case you think otherwise I'm just trying to provide some constructive commentary while reconciling the ideas I had in mind with the code that you've written.
>>
>>>
>>> First, let me just say that I have never used Record. It sounds great
>>> but I'm using SQL databases for my projects. Given this, take what you
>>> will from my comments.
>>>
>>> I would like something that is truly persistence-agnostic to the point
>>> where the developer can use an SQL database. This is especially useful
>>
>> Record is intended to be that persistence-agnostic abstraction. You can have a SQL backend, a document store backend (e.g. Couch), LDAP, etc.
>>
>> So, my plan was to target record and then leverage the abstractions already there to gain the persistence agnostic-ness there. I think basing User traits on record might make them considerably simpler.
>
> But I think the User/ProtUser concept has more uses than just
> Record-based persistence backends (ie JPA). It would be nice to be able
> to support this as well. I'm not sure what we loose if don't target
> Record directly?

I think there's more than just "give me the email", "give me the first name" as Peter sketched out, and this additional support is nontrivial and will essentially drive an intermediate persistence-agnostic-agnostic layer in between the user UI and the persistence mechanism.

Consider things like "render me a form for this user" or "set the password", or "fetch me all users, sorted by this". The surface area of the previous simple SimpleUser seems to get more complicated. Conversely, Mapper and Record have these notions baked into them, so I think we could simplify by just targetting one.

However, I'm also of the mind that we can implement persistence backends with Record such as JPA, and I have no investment in JPA or Mapper so I'm biased towards Record.

-Ross

Timothy Perrett

unread,
May 8, 2010, 2:36:25 PM5/8/10
to lif...@googlegroups.com
Personal preferences aside, Record *will* be what we drive forward with strategically, so it makes sense to invest resource there. Ultimately, we are only talking about a short period of time before Record should become more valuable to people using SQL backends... thus, I don't see benefit in designing new stuff for mapper or JPA at this junction.

Peter, where are you at with your thinking now? Have we persuaded you?

Cheers, Tim

On 8 May 2010, at 16:53, Ross Mellgren wrote:

> I think there's more than just "give me the email", "give me the first name" as Peter sketched out, and this additional support is nontrivial and will essentially drive an intermediate persistence-agnostic-agnostic layer in between the user UI and the persistence mechanism.
>
> Consider things like "render me a form for this user" or "set the password", or "fetch me all users, sorted by this". The surface area of the previous simple SimpleUser seems to get more complicated. Conversely, Mapper and Record have these notions baked into them, so I think we could simplify by just targetting one.
>
> However, I'm also of the mind that we can implement persistence backends with Record such as JPA, and I have no investment in JPA or Mapper so I'm biased towards Record.

Jeppe Nejsum Madsen

unread,
May 9, 2010, 5:19:05 AM5/9/10
to lif...@googlegroups.com
On Sat, May 8, 2010 at 12:39 PM, Timothy Perrett
<tim...@getintheloop.eu> wrote:
> Jeppe,
>
> Hear what your saying, but dont we want Record to be the unified persistence tier in Lift? One could make a Record+JPA implementation...

I think you're correct that Record should be the unified persistence
tier in Lift if you have a "clean" Lift app. I haven't looked closely
at Record yet, but somehow I don't see how it makes sense to make a
JPA+Record backend? Could you elaborate how that would look like?

Just to clarify my statements here: I totally agree that we should
have a User mechanism based on Record that can be used with various
persistence mechanisms. This could be used to generate forms for a
user, allow users to change password, list users etc.

But at the same time I think there's a thinner abstraction, with a
broader set of use cases, that could make sense. Something I think of
as the "runtime" view of a User: Is there a user loggedin? Is it the
superuser? What's the name? The email? The id? The roles (this may be
too complex to tackle at first)

This would be used e.g in snippets (you used yourself in the auction
case. Is there a logged in user?). But many authentication backends
don't allow you to change the password, user name etc (e.g openId,
LDAP) and you may not be able to generate lists of users and so on.

Code wise, something like this. This is close to what Ross showed, but
I just don't think members in the base trait should be Record based:

trait User {
type Role

def hasRole(roles: Role*): Boolean
def emai: Box[String]
def id: String
def firstName: Box[String]
etc
}

trait MetaUser {
def loggedIn_?: Boolean
def logout: Unit
def currentUser: Box[User]
}

And the record impl:

abstract class RecordUser[MyType <: RecordUser[MyType]] with User {
}

User code an then rely on having an object of type MetaUser available
and use this in snippets etc without worrying about if it's mapper,
record, openid etc

WDYT?

/Jeppe

Peter Robinett

unread,
May 9, 2010, 3:59:35 PM5/9/10
to Lift
Hi all,

I like all the ideas we're discussing. Jeppe, what you posted is very
similar what I made and I like the idea of a 'thin' User that can be
the basis upon which more complex user traits are built. I think the
thin User should only have some basic attributes and the meta trait
should have log-in and -out methods and store the session's currently
logged in user. This is what I've done in my code. On the other hand,
a 'fat' User is essential for every-day user accounts. From Ross' and
Tim's posts I think it's clear that Record should be the target and
that Mapper can be safely ignored completely. Fat User traits should
have things such as Locs, access control, and so on. I would recommend
having a base Record User that simply is the thin User stored via a
Record backend and then a more complex Record user that has all the
(simple to ProtoUser versus MegaProtoUser in Mapper today).

Is this a useful compromise? The only real disadvantage I can think of
is that the basic attributes can only have basic types. Of course,
when using fat Users there's no reason you can't directly access the
Record fields and you can give them better names than I did in my
mapper example.

Peter

On May 9, 11:19 am, Jeppe Nejsum Madsen <je...@ingolfs.dk> wrote:
> On Sat, May 8, 2010 at 12:39 PM, Timothy Perrett
>

Ross Mellgren

unread,
May 11, 2010, 1:14:01 PM5/11/10
to lif...@googlegroups.com
Sorry I haven't contributed to this conversation recently, I've been ill.

I think the idea of a "thin" user trait is great if you guys think there are use cases (I personally don't have any offhand). My only contribution to that is that if we can make this trait not use simple names like "def email" or whatever, so that the persistence can take those names for the raw fields, that would be my preference.

That is, instead of

trait User {
def email: String
def username: String
}

use something like (suffix not important)

trait User {
def emailValue: String
def usernameValue: String
}

I just think it would be a shame for the generic code using the User trait to be "first class" and then the actual users as stored be "second class" leading to workarounds like this:

class MyUser extends ... {
object emailField extends StringField(...)
def email = emailField.value
object usernameField extends StringField(...)
def username = usernameField.value
}

I still think that the major Metatron user components (sign up, sign in, log out, forgot password) should probably be Record-specific to avoid overbuilding abstractions in between the UI and the persistence.

That said, code on and prosper!

-Ross

David Pollak

unread,
May 11, 2010, 1:32:37 PM5/11/10
to lif...@googlegroups.com
Guys,

We're getting a new committer who is decomposing ProtoUser, etc.  More on that later today, tomorrow.

Thanks,

David
--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Surf the harmonics

Ross Mellgren

unread,
May 11, 2010, 4:35:22 PM5/11/10
to lif...@googlegroups.com
Okay... is that committer already on the list? Perhaps they can write up a bit on what they're planning to do?

-Ross

Peter Robinett

unread,
May 12, 2010, 8:49:49 AM5/12/10
to Lift
Same here! :-(

I totally agree, Ross. Of course, I look forward to hearing what
Alexander has planned.

Peter

nau

unread,
Jun 15, 2010, 8:35:30 AM6/15/10
to Lift
Hello guys,

I'd like to implement complete, reusable and persistence-agnostic user
management solution for lift.
I've pushed some code in http://github.com/dpp/liftweb/branches/proto-user-decouple
That's just a starting point and everything could be changed in any
way we consider the best in further discussion. Current code is
backward compatible and all tests passed. But at least it allows a
developer to create JPA/Hibernate/whatever specific implementation by
implementing UserService/UserFinders/UserDetails traits leaving login/
signup/edit/changePassword etc functionality to lift.

I'm thinking about creating something similar to LiftRules object
holding user management preferences. Let's call it LiftUserRules. It
could hold such rules like: skipEmailValidation, from/cc/bcc emails
etc. This, however, will break backward compatibility.

Ideally, I'd like to allow a developer to:

1. Start quickly.
Developer uses ProtuUser, RecordProtoUser, JPAProtoUser traits to
start quickly (those need to be provided). All xhtml for login/signup
etc are predefined in CommonUserSnippet trait.

2. Customize.
Developer uses LiftUser built-in snippet (LiftUser) or overrides xhtml-
returning functions to customize templates. Developer can implement
UserSnippet/CommonUserSnippet traits to do whatever he wants.
Everything should be easily changeable by implementing/overriding
trait methods and configuring with LiftUserRules.

3. Use existing components.
We need to provide for a developer as much standard solutions as
possible. I'd like if a developer could add captcha signup validation
as easy as "MapperUserService with CaptchaSignupValidation" or have
different authentication sources (ldap, cas) just by configuring them
in LiftUserRules.

4. Have detailed, example-based documentation.
Good wiki page with examples similar to what we have.

Further, it'd be great to have complete role based ACL implemented and
authentication mechanism decoupled. If that's what you think of too,
let's discuss it :)

Please, criticize. Any suggestions, proposition and ideas are very
welcome. Please note, I'm pretty much new to lift and scala so I may
not know some techniques, "right ways to do" etc.

Thanks,
Alex

Malcolm

unread,
Jul 7, 2010, 5:22:13 PM7/7/10
to Lift
I've been creating a datamodel with Record objects against MongoDb
which is working great. I've been putting off any tasks related to
User , login etc hoping there could be some checked in code to use
from this thread.

how is it going? I would be happy to use and test functionality if
there was something to use. I'm on the Lift 2.0 aginast Scala
2.8.0.RC6 with a local build of liftweb.

Thanks in advance,

Malcolm

Timothy Perrett

unread,
Jul 7, 2010, 5:47:24 PM7/7/10
to lif...@googlegroups.com
Have you looked at the branch i posted?

Reply all
Reply to author
Forward
0 new messages