Review and improve login process
A basic login works now, but it probably isn't fully correct.
The following things are outstanding (there will be more, but these are on my mind)
- When someone "logs in" through a browser in a normal way we're generally talking about a logged-in session. This means we have a session cookie that enables us to remember stuff to do with a user between calls. It seems that the primary things here are:
userId
(which refers to a contact ID of the logged in user) andufId
which refers to the User (api4 entity, defined in this extension) ID. - The login is mostly done through the standalone authx class. I think this is a bit lacking at present as it possibly doesn't reset the session?
- There is no way to logout yet - This is very easy to implement if someone wants a quick win :-)
- I've tried to make the auto-login on enabling the extension (see upgrader class) emit a status message with the user and password but this doesn't show up.
- User creation, including generating crypto-secure salt and hash is handled by CRM_Core_BAO_CMSUser::create - that links to one of the phpunit tests that does this, as an example. We will need an Api4 action for this, either by augmenting User.create or making a new dedicated action.
- The permissions granted to the admin user are wrong. I just assigned all the core permissions, but this is a subset and is almost definitely the wrong way to do it! There probably just needs to be one or two superuser style permissions - someone could figure that out and make that change.
- UF Match - this is a table that's supposed to link Contacts to CMS Users. We have some redundancy here. Our User entity has a contact_id field, however we also need the UF Match row as well as various parts of Civi look there for it. I think there needs to be a PR that removes our contact_id field and makes everything rely on the UF Match row. A UF Match row is created by CRM_Core_BAO_CMSUser::create, but there is no Api4 for UFmatch. It's a bit messy.
- I'm proposing that we disallow the concept of someone being logged in as a user but not a contact. i.e. I want it so that it's impossible to be a user without a contact. I think this makes things stronger in a standalone context. Please raise this as a separate issue if you think it needs discussion.
- There's the concept of stateless logins - i.e. those without a session, as might be used server-to-server, or client to server using one of the authx "flows" other than "login". I'm not sure these are implemented correctly because I'm unclear what we do about the session since that's where Civi looks to determine who is logged in. I think the answer might come in the form of a fake session (which is really just a global array) - but this needs investigation and implementation.
- There are some tests. If you're new to tests: you need the buildkit environment to run them (Fun fact: if you run them on a normal site they may destroy a lot of your data. Not that I'd ever make that mistake. Honest.)
- Also, on a painful experience note: Remember that if you are working in a BK instance, then destroying that instance will lose any work you haven't committed-and-pushed to any of the repos involved. Also, watch carefully if you end up with several instances/copies - I've lost work by deleting the wrong one, and lost time by trying to fix a problem in one code file while looking for the fix in a browser accessing the other instance! Yes, I know you're not as stupid as me, but thought I'd share :-)