static async updateCron (req, res) {
    const key = req.params.key;
    if (key === 'primary-viewer') {
      return res.serverError(403, 'Bad query key');
    }
    if (!ArkimeUtil.isString(key)) {
      return res.serverError(403, 'Missing query key');
    }
    if (!ArkimeUtil.isString(req.body.name)) {
      return res.serverError(403, 'Missing query name');
    }
    if (!ArkimeUtil.isString(req.body.query)) {
      return res.serverError(403, 'Missing query expression');
    }
    if (!ArkimeUtil.isString(req.body.action)) {
      return res.serverError(403, 'Missing query action');
    }
    if (!ArkimeUtil.isString(req.body.tags)) {
      return res.serverError(403, 'Missing query tag(s)');
    }

    if (req.body.roles !== undefined && !ArkimeUtil.isStringArray(req.body.roles)) {
      return res.serverError(403, 'Roles field must be an array of strings');
    }

    if (req.body.editRoles !== undefined && !ArkimeUtil.isStringArray(req.body.editRoles)) {
      return res.serverError(403, 'Edit roles field must be an array of strings');
    }

    if (req.body.users !== undefined && !ArkimeUtil.isString(req.body.users, 0)) {
      return res.serverError(403, 'Users field must be a string');
    }

    // comma/newline separated value -> array of values
    let users = ArkimeUtil.commaOrNewlineStringToArray(req.body.users || '');
    users = await User.validateUserIds(users);
    req.body.users = users.validUsers;

    const doc = {
      doc: {
        description: '',
        notifier: undefined,
        name: req.body.name,
        tags: req.body.tags,
        users: req.body.users,
        roles: req.body.roles,
        query: req.body.query,
        action: req.body.action,
        enabled: req.body.enabled,
        editRoles: req.body.editRoles
      }
    };

    if (ArkimeUtil.isString(req.body.notifier)) {
      doc.doc.notifier = req.body.notifier;
    }

    if (ArkimeUtil.isString(req.body.description)) {
      doc.doc.description = req.body.description;
    }

    try {
      const { body: { _source: cron } } = await Db.getQuery(key);

      // sets the owner if it has changed
      doc.doc.creator ??= req.body.creator;
      if (!await User.setOwner(req, res, doc.doc, cron, 'creator')) {
        return;
      }

      if (doc.doc.enabled !== cron.enabled) { // the query was enabled or disabled
        doc.doc.lastToggledBy = req.settingUser.userId;
        doc.doc.lastToggled = Math.floor(Date.now() / 1000);
      }

      const query = { // last object property overwrites the previous one
        ...cron,
        ...doc.doc
      };

      try {
        await Db.update('queries', 'query', key, doc, { refresh: true });
      } catch (err) {
        console.log(`ERROR - ${req.method} /api/cron/%s`, ArkimeUtil.sanitizeStr(key), util.inspect(err, false, 50));
      }

      if (CronAPIs.#primaryViewer) { CronAPIs.processCronQueries(); }

      query.key = key;
      if (query.users) {
        query.users = query.users.join(',');
      }

      return res.send(JSON.stringify({
        query,
        success: true,
        text: 'Updated periodic query!',
        invalidUsers: users.invalidUsers
      }));
    } catch (err) {
      console.log(`ERROR - ${req.method} /api/cron/%s`, ArkimeUtil.sanitizeStr(key), util.inspect(err, false, 50));
      return res.serverError(403, 'Periodic query update failed');
    }
  }
POST - /api/cron/:key

Update a periodic query.
@name /user/:key
@returns {boolean} success - Whether the update operation was successful.
@returns {string} text - The success/error message to (optionally) display to the user.
@returns {ArkimeQuery} query - The updated query object