mavo icon indicating copy to clipboard operation
mavo copied to clipboard

New special properties for currently logged in user

Open LeaVerou opened this issue 6 years ago • 15 comments

Potential names: $username, $name, $avatar, and $user for any misc backend-specific info.

Will update on login/logout.

For multiple reasons:

  • Default property values that depend on current user
  • UI conditionals
  • Storing object creator
  • Reduce custom code for Mavo toolbar
  • Possibly might help with granular permissions #318

LeaVerou avatar Jun 17 '18 21:06 LeaVerou

Another option could be an object or functional syntax: $user.username or userinfo('username') to avoid polluting the global expression space with too many special variables.

LeaVerou avatar Jan 15 '21 11:01 LeaVerou

As we know, backends that support authentication provide the user object to Mavo, and Mavo uses it to add some info about a logged-in user to the Mavo bar.

We also know that this object can have not only expected properties like username, name, avatar (even though there is no guarantee), but also some extra properties that are provided either via the info property or some other way.

For me, as an author, it is rather easy to find out what properties the $user special property has via, e.g., log($user) and then get any of them either via $user.propertyName or get($user, propertyName). For example, I can even do this: get(get($user, info), uid).

It seems to me that with functional syntax, there will not be an easy way to know what info provides a backend about a logged-in user. However, I must say that it's rather straightforward to get the same data as above using the functional syntax: get(userinfo('info'), uid).

That's why I personally am for an object syntax, i.e., for $user.username. ☺️

DmitrySharabin avatar Jan 15 '21 13:01 DmitrySharabin

We already have a working prototype of the $user special property, which @karger and I heavily use in conjunction with the Firebase plugin in our apps. For now, we have to add it via custom JS like so:

(async function () {
	await Mavo.ready;
	
	Mavo.DOMExpression.special.event("$user", {
		type: "mv-login mv-logout",
		update: (evt) => evt.backend.user
	});
})();

You can see it in action in this demo app.

DmitrySharabin avatar Nov 21 '23 22:11 DmitrySharabin

LGTM, what's the downside? Why can't we just add this to core?

LeaVerou avatar Nov 22 '23 08:11 LeaVerou

LGTM, what's the downside? Why can't we just add this to core?

We can. Just needed to resolve it first. ☺️ I’ll send a PR soon.

DmitrySharabin avatar Nov 22 '23 08:11 DmitrySharabin

Actually, the downside of this approach is that the $user special property is updated on the mv-login and mv-logout events firing on any Mavo app on the page so that it returns the user of the backend fired the corresponding event last.

However, we expect it to return every app's (primary backend) user separately.

Another issue is whether an app works with two backends requiring authentication. For example, the author uses GitHub's private repo as the source and a Google spreadsheet as the storage. AFAIC, in that case, the Google Sheets will be the primary backend (the default login button will log the user in with their Google account), and $user will return info from the user's Google account. Will the app user be able to log in to their GitHub account? It seems to me that without custom JS, no.

DmitrySharabin avatar Nov 22 '23 17:11 DmitrySharabin

Hmm, these are pretty signifiant. We do have special variables scoped to nodes, maybe we can scope them to the root node?

LeaVerou avatar Nov 23 '23 03:11 LeaVerou

I think @DmitrySharabin urfaced a situation that is independent of the special $user variable. how does a user log in if mv-source and mv-storage have different back-ends? Then there's the separate question of what we should do with $user in that case, since there may be two different sets of user info....

karger avatar Nov 23 '23 04:11 karger

We do have special variables scoped to nodes, maybe we can scope them to the root node?

If you mean $item, $all, and other buddies, yes, I’m trying to find a way to make $user work similarly. Now I know I’m searching in the right direction. ☺️

Then there's the separate question of what we should do with $user in that case, since there may be two different sets of user info.

Exactly. That was the reason why I pointed out (but not fully expressed in words) the second issue.

Maybe someday we need to expose $source and $storage special properties so that authors can get not only the info about the logged-in user but also, e.g., the permissions the backends have. And the problem with different sets of user info will be solved automatically. In that case, we’d get something like $storage.user and $storage.permissions. Or maybe we’ll come up with the idea that it would be nice for the author to have access to the underlying backends’ methods (actions) like $storage.save(), $source.load(), $source.logout(), etc. 🤔

DmitrySharabin avatar Nov 23 '23 08:11 DmitrySharabin

I think @DmitrySharabin urfaced a situation that is independent of the special $user variable. how does a user log in if mv-source and mv-storage have different back-ends? Then there's the separate question of what we should do with $user in that case, since there may be two different sets of user info....

That's separate and much easier to deal with. E.g. $user can be defined as user of the primary backend and we could have $storage_user, $source_user, $init_user for more granularity.

LeaVerou avatar Nov 23 '23 17:11 LeaVerou

I'm not sure "primary back end" is a tractable concept. If the author is creating an app that actually requires the user to have two different logins, it's very unlikely that we can figure out which back-end is primary. Maybe we should just accept that $user will come from the first mavo on the page?

karger avatar Nov 23 '23 19:11 karger

"Primary backend" is an established concept already. Roughly, storage || source || init. It's scoped to a specific Mavo, hence the more pressing problem of scoping.

LeaVerou avatar Nov 23 '23 20:11 LeaVerou

oh, i thought you were talking about which backend is primary among multiple mavo apps on the same page (which is the problem I was referring to).

karger avatar Nov 23 '23 20:11 karger

I built a prototype of the $user special property, which is context-aware.

Here is all the code that needs to be added to our code base (from my perspective):

Mavo.DOMExpression.special.event("$user", {
	type: "mv-login mv-logout",
	target: document
});

Mavo.Data.special["$user"] = function (obj) {
	return obj[Mavo.mavo]?.primaryBackend?.user;
};

@LeaVerou Is this legal at all? 😅

DmitrySharabin avatar Dec 28 '23 17:12 DmitrySharabin

I was also examining the option to put $user into Mavo.Functions. Unfortunately, I don't know how to make it a context-aware getter. I know how to do the context-aware $user function:

Mavo.Functions["$user"] = $.extend(function () {
	return this[Mavo.mavo]?.primaryBackend?.user;
}, {needsContext: true})

But it doesn't play well with other special properties since they are getters.

DmitrySharabin avatar Dec 28 '23 17:12 DmitrySharabin