Skip to content

add cv cron command #246

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
michaelmcandrew opened this issue Apr 9, 2025 · 7 comments
Open

add cv cron command #246

michaelmcandrew opened this issue Apr 9, 2025 · 7 comments

Comments

@michaelmcandrew
Copy link
Contributor

Following discussion here: civicrm/civicrm-docker#28 (comment)

What do you think about adding a cv cron command that is a wrapper around cv api3 Job.execute and also picks up a new setting in CiviCRM called CRON_USER which is the user that is used to execute the command.

This would simplify sysadmin because we would be able to call cron for sites without knowing anything about the users installed on those sites. We currently need to maintain a mapping of sites and their cron users outside of CiviCRM in order to trigger cron.

Aside: should we really need to pass a cms user to execute a cron job in 2025?

@michaelmcandrew
Copy link
Contributor Author

@mlutfy - any thoughts on this given your experience with Spark?

@mlutfy
Copy link
Member

mlutfy commented Apr 9, 2025

@michaelmcandrew Any simplification is welcome, for sure.

It would be great to have the equivalent of a fake user for cron, which cannot be used for logins, and has full permissions. And where Scheduled Reminders or other scheduled job activities are not all "Admin, Admin".

Spark uses Aegir, and we have a lot of monitoring around cron, because admins change the username, delete the account, etc. (Spark locks the superadmin account down, but my other verticals do not)

Aegir stores the cron username in the site settings, part of the Ansible inventory. Ansible is then used to generate systemd timers/service units.

@totten
Copy link
Member

totten commented Apr 9, 2025

should we really need to pass a cms user to execute a cron job in 2025?

Yeah, I also feel like it's poor-UX/AX for crons to require a user. I'm not really clear on how much trouble there would be to omit them.

FWIW, if it's just a matter of ensuring that CRM_Core_Permission::check('foo') will pass... then we could try something like this before calling Job.execute:

    \CRM_Core_Config::singleton()->userPermissionTemp = new \CRM_Core_Permission_Temp();
    \CRM_Core_Config::singleton()->userPermissionTemp->grant('administer CiviCRM');

Other theories (speculative) for how user might be important to cronjobs:

  • Logs: If a new record is created/modified by a cron, how is it attributed in the logs?
    • We could protentially autocreate a Contact for this purpose and set the corresponding userId in session.
    • Autocreating a Contact is a lot easier than doing it for a User (because that's UF dependent).
    • Probably want some way to mark the contact as special... (Non-deletable? Different icon?) But that's not hard-blocker.
  • Multisite: Do jobs vary by domain? Using different principals per domain? (@seamuslee001 might have insight.)
  • ACLs: Do we need some jobs to have access to different ACLs?
    • For example, I could imagine wanting to send different email reports (mail_report) to different users. But if you were doing that, it would seem to be a very specialized setup. We don't need cv cron to handle that...

@mlutfy
Copy link
Member

mlutfy commented Apr 9, 2025

We could protentially autocreate a Contact for this purpose and set the corresponding userId in session.

How about using the default org domain contact? (it would make more sense in the logs?)

@seamuslee001
Copy link
Contributor

Sometimes in a multi domain environment it would be possible for the jobs to vary e.g. on one domain you might have iATS and on another they are using stripe as the payment processor and they need different jobs right? There would be some jobs that would be consistent some might vary

In regards to ACLs possibly that might be important but that would be in a limited number of e.g. CiviMail, CiviReport Search Kit ones. The more pressing thing would be is managing the coarse grained permissions . e.g. having Access CiviContribute etc if your doing payment processing jobs. At the moment there is no sense of what those sorts of permissions are for the different jobs e.g. what does the ProcessPaymentWebhooks require from a permissions sense. At the moment in most sites we have just granted the cron user administrator level roles and permissions and so the ACLs effectively have been ignored.

@totten
Copy link
Member

totten commented Apr 10, 2025

(mlutfy) How about using the default org domain contact?

That sounds pretty elegant...

(seamuslee) In regards to ACLs possibly that might be important but that would be in a limited number... At the moment in most sites we have just granted the cron user administrator level roles and permissions and so the ACLs effectively have been ignored.

OK, sounds like a new cv cron entry-point could initially aim for that common case. (Just run one cron as superuser.) And after that's implemented/working/merged, we could have another issue to figure out extra options (--domain=N, --domain=*, etc) for the other cases.


This is sounding something like....

if (empty($input->getOption('user))) {
  \CRM_Core_Config::singleton()->userPermissionTemp = new \CRM_Core_Permission_Temp();
  \CRM_Core_Config::singleton()->userPermissionTemp->grant('all CiviCRM permissions and ACLs');

  $cid = CRM_Core_DAO::singleValueQuery('SELECT contact_id FROM civicrm_domain ORDER BY id LIMIT 1');
  CRM_Core_Session::singleton()->set('userId', $cid);
  // Or maybe:
  // authx_login(['principal' => ['contactId' => $cid]]);
}

civicrm_api3('Job', 'execute', []);

@michaelmcandrew
Copy link
Contributor Author

OK, sounds like a new cv cron entry-point could initially aim for that common case. (Just run one cron as superuser.) And after that's implemented/working/merged, we could have another issue to figure out extra options (--domain=N, --domain=*, etc) for the other cases.

This sounds good

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants