Commit Graph

41 Commits

Author SHA1 Message Date
Steve Howell c4d0e4c9f9 bot_data: Eliminate all uses of `bot.owner` (email).
We now use `bot.owner_id` for everything internally.
2020-05-11 16:16:58 -07:00
Steve Howell 5c16bb9c99 bot settings: Load bots independently.
We no longer use `/json/users` in the codepath
for bot settings (admin side).

We also specifically don't load human users when
we load bots, so you no longer have to pay for
the server round trip as a side effect of loading
bots.  Instead, there is a dedicated `set_up_bots`
entry point.

We also get the bot ids directly from `bot_data` now.

This commit, to some degree, builds on the prior commit
that had us hydrate data from `people.js` instead
of the payload from `/json/users`.
2020-05-11 16:16:58 -07:00
Steve Howell 155f6da8ba bots: Add owner_id to bot-related payloads.
For the below payloads we want `owner_id` instead
of `owner`, which we should deprecate.  (The
`owner` field is actually an email, which is
not a stable key.)

    page_params.realm_bots

    realm_bot/add

    realm_bot/update

IMPORTANT NOTE: Some of the data served in
these payloads is cached with the key
`bot_dicts_in_realm_cache_key`.

For page_params, we get the new field
via `get_owned_bot_dicts`.

For realm_bot/add, we modified
`created_bot_event`.

For realm_bot/update, we modified
`do_change_bot_owner`.

On the JS side, we no longer
look up the bot's owner directly in
`server_events_dispatch` when we get
a realm_bot/update event. Instead, we
delegate that job to `bot_data.js`.
I modified the tests accordingly.
2020-05-11 16:16:58 -07:00
Steve Howell 7c1f64d4e5 bot_data: Remove get_bot_owner_email. 2020-05-10 16:20:41 -04:00
Steve Howell 6d03b82dcb bot_data: Remove set_can_admin.
We stopped needing this with
0329b67048
(Dec 2016).

The function sets `bot.can_admin`,
which was only used in `bot_data.get_editable`.

We removed two tests (and then put back
some test setup that needed to leak down
to the last test).
2020-03-24 20:40:19 -07:00
Steve Howell d916cbbb70 cosmetic: Remove ugly bot_data__* names. 2020-03-24 20:40:19 -07:00
Steve Howell da79fd206a ui_init: Handle page_params more cleanly.
This cleans up the handoff of page_params
data between ui_init and modules that
take over ownership of page_params-derived
data.

Read the long comment in ui_init for a bit
more context.

Most of this diff is actually test cleanup.
And a lot of the diff to "real" code is
just glorified `s/page_params/params/`
in the `initialize` functions.

One little oddity is that we don't actually
surrender ownership of `page_params.user_id`
to `people.js`.  We could plausibly sweep
the rest of the codebase to just use
`people.my_user_id()` consistently, but it's
not a super high priority thing to fix,
since the value never changes.

The stream_data situation is a bit messy,
since we consume `page_params` data in the
initialize() function in addition to the
`params` data we "own".  I added a comment
there and intend to follow up.  I tried
to mostly avoid the "word soup" by extracting
three locals at the top.

Finally, I don't touch `alert_words` yet,
despite it also doing the delete-page-params-data
dance.  The problem is that `alert_words`
doesn't have a proper `initialize()`.  We
should clean that up and have it use a
`Map` internally, too.
2020-02-26 13:14:09 -08:00
Anders Kaseorg 5ba593f124 int_dict: Replace with Map.
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-25 15:37:37 -08:00
Anders Kaseorg 7cc16757aa int_dict: Remove filter_values method.
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-25 15:35:42 -08:00
Anders Kaseorg dbffb2a614 js: Convert _.extend to spread syntax or Object.assign.
This is not always a behavior-preserving translation: _.extend mutates
its first argument.  However, the code does not always appear to have
been written to expect that.

Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-25 14:09:39 -08:00
Anders Kaseorg ac7b09d57e js: Convert _.map(a, …) to a.map(…).
And convert the corresponding function expressions to arrow style
while we’re here.

import * as babelParser from "recast/parsers/babel";
import * as recast from "recast";
import * as tsParser from "recast/parsers/typescript";
import { builders as b, namedTypes as n } from "ast-types";
import K from "ast-types/gen/kinds";
import fs from "fs";
import path from "path";
import process from "process";

const checkExpression = (node: n.Node): node is K.ExpressionKind =>
  n.Expression.check(node);

for (const file of process.argv.slice(2)) {
  console.log("Parsing", file);
  const ast = recast.parse(fs.readFileSync(file, { encoding: "utf8" }), {
    parser: path.extname(file) === ".ts" ? tsParser : babelParser,
  });
  let changed = false;

  recast.visit(ast, {
    visitCallExpression(path) {
      const { callee, arguments: args } = path.node;
      if (
        n.MemberExpression.check(callee) &&
        !callee.computed &&
        n.Identifier.check(callee.object) &&
        callee.object.name === "_" &&
        n.Identifier.check(callee.property) &&
        callee.property.name === "map" &&
        args.length === 2 &&
        checkExpression(args[0]) &&
        checkExpression(args[1])
      ) {
        const [arr, fn] = args;
        path.replace(
          b.callExpression(b.memberExpression(arr, b.identifier("map")), [
            n.FunctionExpression.check(fn) ||
            n.ArrowFunctionExpression.check(fn)
              ? b.arrowFunctionExpression(
                  fn.params,
                  n.BlockStatement.check(fn.body) &&
                    fn.body.body.length === 1 &&
                    n.ReturnStatement.check(fn.body.body[0])
                    ? fn.body.body[0].argument || b.identifier("undefined")
                    : fn.body
                )
              : fn,
          ])
        );
        changed = true;
      }
      this.traverse(path);
    },
  });

  if (changed) {
    console.log("Writing", file);
    fs.writeFileSync(file, recast.print(ast).code, { encoding: "utf8" });
  }
}

Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 14:08:12 -08:00
Anders Kaseorg 02511bff1c js: Automatically convert _.each to for…of.
This commit was automatically generated by the following script,
followed by lint --fix and a few small manual lint-related cleanups.

import * as babelParser from "recast/parsers/babel";
import * as recast from "recast";
import * as tsParser from "recast/parsers/typescript";
import { builders as b, namedTypes as n } from "ast-types";
import { Context } from "ast-types/lib/path-visitor";
import K from "ast-types/gen/kinds";
import { NodePath } from "ast-types/lib/node-path";
import assert from "assert";
import fs from "fs";
import path from "path";
import process from "process";

const checkExpression = (node: n.Node): node is K.ExpressionKind =>
  n.Expression.check(node);
const checkStatement = (node: n.Node): node is K.StatementKind =>
  n.Statement.check(node);

for (const file of process.argv.slice(2)) {
  console.log("Parsing", file);
  const ast = recast.parse(fs.readFileSync(file, { encoding: "utf8" }), {
    parser: path.extname(file) === ".ts" ? tsParser : babelParser,
  });
  let changed = false;
  let inLoop = false;
  let replaceReturn = false;

  const visitLoop = (...args: string[]) =>
    function(this: Context, path: NodePath) {
      for (const arg of args) {
        this.visit(path.get(arg));
      }
      const old = { inLoop };
      inLoop = true;
      this.visit(path.get("body"));
      inLoop = old.inLoop;
      return false;
    };

  recast.visit(ast, {
    visitDoWhileStatement: visitLoop("test"),

    visitExpressionStatement(path) {
      const { expression, comments } = path.node;
      let valueOnly;
      if (
        n.CallExpression.check(expression) &&
        n.MemberExpression.check(expression.callee) &&
        !expression.callee.computed &&
        n.Identifier.check(expression.callee.object) &&
        expression.callee.object.name === "_" &&
        n.Identifier.check(expression.callee.property) &&
        ["each", "forEach"].includes(expression.callee.property.name) &&
        [2, 3].includes(expression.arguments.length) &&
        checkExpression(expression.arguments[0]) &&
        (n.FunctionExpression.check(expression.arguments[1]) ||
          n.ArrowFunctionExpression.check(expression.arguments[1])) &&
        [1, 2].includes(expression.arguments[1].params.length) &&
        n.Identifier.check(expression.arguments[1].params[0]) &&
        ((valueOnly = expression.arguments[1].params[1] === undefined) ||
          n.Identifier.check(expression.arguments[1].params[1])) &&
        (expression.arguments[2] === undefined ||
          n.ThisExpression.check(expression.arguments[2]))
      ) {
        const old = { inLoop, replaceReturn };
        inLoop = false;
        replaceReturn = true;
        this.visit(
          path
            .get("expression")
            .get("arguments")
            .get(1)
            .get("body")
        );
        inLoop = old.inLoop;
        replaceReturn = old.replaceReturn;

        const [right, { body, params }] = expression.arguments;
        const loop = b.forOfStatement(
          b.variableDeclaration("let", [
            b.variableDeclarator(
              valueOnly ? params[0] : b.arrayPattern([params[1], params[0]])
            ),
          ]),
          valueOnly
            ? right
            : b.callExpression(
                b.memberExpression(right, b.identifier("entries")),
                []
              ),
          checkStatement(body) ? body : b.expressionStatement(body)
        );
        loop.comments = comments;
        path.replace(loop);
        changed = true;
      }
      this.traverse(path);
    },

    visitForStatement: visitLoop("init", "test", "update"),

    visitForInStatement: visitLoop("left", "right"),

    visitForOfStatement: visitLoop("left", "right"),

    visitFunction(path) {
      this.visit(path.get("params"));
      const old = { replaceReturn };
      replaceReturn = false;
      this.visit(path.get("body"));
      replaceReturn = old.replaceReturn;
      return false;
    },

    visitReturnStatement(path) {
      if (replaceReturn) {
        assert(!inLoop); // could use labeled continue if this ever fires
        const { argument, comments } = path.node;
        if (argument === null) {
          const s = b.continueStatement();
          s.comments = comments;
          path.replace(s);
        } else {
          const s = b.expressionStatement(argument);
          s.comments = comments;
          path.replace(s, b.continueStatement());
        }
        return false;
      }
      this.traverse(path);
    },

    visitWhileStatement: visitLoop("test"),
  });

  if (changed) {
    console.log("Writing", file);
    fs.writeFileSync(file, recast.print(ast).code, { encoding: "utf8" });
  }
}

Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-07 14:09:47 -08:00
Anders Kaseorg fe54e73c77 dict, lazy_set: Rename del method to delete, for consistency with Map.
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-04 12:22:03 -08:00
Anders Kaseorg 031afa6014 bots: Convert services from object to IntDict.
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-01-16 13:23:47 -08:00
Anders Kaseorg bc626e2470 bots: Convert bots from object to IntDict.
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-01-16 13:23:47 -08:00
Anders Kaseorg 28f3dfa284 js: Automatically convert var to let and const in most files.
This commit was originally automatically generated using `tools/lint
--only=eslint --fix`.  It was then modified by tabbott to contain only
changes to a set of files that are unlikely to result in significant
merge conflicts with any open pull request, excluding about 20 files.
His plan is to merge the remaining changes with more precise care,
potentially involving merging parts of conflicting pull requests
before running the `eslint --fix` operation.

Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2019-11-03 12:42:39 -08:00
Anders Kaseorg d17b577d0c js: Purge useless IIFEs.
With webpack, variables declared in each file are already file-local
(Global variables need to be explicitly exported), so these IIFEs are
no longer needed.

Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2019-10-25 13:51:21 -07:00
Anders Kaseorg 5f590d3500 js: Remove /* eslint indent: "off" */ comments.
The time has come to dedent these files.

Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2019-10-25 13:21:43 -07:00
Anders Kaseorg bde31a54c7 bot_data: Rename delete to del.
`delete` is a reserved keyword that would interfere with the migration
to an ES6 module.

Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2019-07-04 16:48:33 -07:00
Yashashvi Dave 5759d5a762 statis/js/bot_data.js: Add `get_bot_owner_email` function. 2018-11-16 09:52:05 -08:00
Armaan Ahluwalia 6d255efe4c app: Prepare JS files for consumption by webpack.
This commit prepares the frontend code to be consumed by webpack.

It is a hack: In theory, modules should be declaring and importing the
modules they depend on and the globals they expose directly.

However, that requires significant per-module work, which we don't
really want to block moving our toolchain to webpack on.

So we expose the modules by setting window.varName = varName; as
needed in the js files.
2018-07-05 10:53:36 +02:00
Steve Howell 26b48b95dc refactor: Export settings_bots.render_bots().
We also now call this explicitly when we need to
re-render (instead of triggering a custom event).
2018-07-03 06:02:49 -07:00
Robert Hönig 647c63050f botserver: Add outgoing webhook tokens to botserverrc.
The tokens will be used to authorize the server when sending
messages to the Botserver.
2018-05-30 10:00:19 -04:00
Tim Abbott 7ab8a8e820 js: Fix a bunch of indentation issues found by eslint.
This is preparation for enabling an eslint indentation configuration.
90% of these changes are just fixes for indentation errors that have
snuck into the codebase over the years; the others are more
significant reformatting to make eslint happy (that are not otherwise
actually improvements).

The one area that we do not attempt to work on here is the
"switch/case" indentation.
2018-05-06 16:25:02 -07:00
Shubham Padia a78024f53d bots: Delete bot from bot_data set on realm_bot delete event.
Fixes #8577.
2018-03-08 07:54:19 -08:00
Robert Hönig 044b0beeab frontend: Store embedded bot data in bot_data.js.
In specific, this stores config_data and service_name
for embedded bots.
2018-03-01 08:25:43 -08:00
Robert Hönig 561e0ffe3b frontend: Delete page_params.realm_bots after first usage.
The data in page_params.realm_bots is parsed and captured
in bot_data. bot_data provides a safe system for accessing
this data.
2018-02-09 12:30:24 -08:00
Robert Hönig 4cc8c74aaa frontend: Internally refer to bots by ID.
This is done by using a bot's ID instead of email in
the handler methods for bot_data.bots and bot_data.services,
and updating all code paths involved.
2018-01-23 07:29:00 -05:00
Robert Hönig bd6fa385a5 frontend: Add outgoing webhook config entries to the "edit bot" menu.
This allows users to edit an outgoing webhook's endpoint URL
and interface type after it has been created.

Fixes #7411.
2018-01-23 07:29:00 -05:00
Abhijeet Kaur af7e08acb0 bots: Add UI to view bot types of existing bots in "Your bots".
Tweaked by tabbott for more standard internationalization.
2017-06-15 10:08:31 -07:00
Elliott Jin 573e06260a Don't initialize bot_data until after people.initialize()
bot_data initialization depends on the results of people.initialize(); for
example, to determine whether a bot is owned by the current user.
2017-05-24 17:58:57 -07:00
fionabunny 84c4d67916 home.py: move bot_list as realm_bots to register_ret.
Simplify the page_params generation logic #3853
2017-04-28 21:24:44 -07:00
Harshit Bansal a05795c85c bot_data.js: Add `get_all_bots_for_current_user()` function.
This function can be used to get all the bots whether active or
inactive that belong to current logged in user.
2017-02-28 16:15:10 -08:00
Harshit Bansal bbcd927375 bot_data.js: Replace `remove()` with `deactivate()`.
On receiving a `remove` event of type `realm_bot`, instead
of deleting the bot from `bots` dict, set it's `is_active`
flag to false.
2017-02-26 23:56:51 -08:00
Harshit Bansal a900a2076a bot_data.js: Add `is_active` field to `bot_dict`. 2017-02-26 23:56:51 -08:00
Steve Howell 73125e2718 refactor: Move is_current_user() to people.js.
We no longer have it in util.js, because we will
want to encapsulate this better for upcoming commits
related to email changes.
2017-01-21 21:45:12 -08:00
Tommy Ip 0329b67048 admin: Limit bots in settings page.
Updated `get_editable()` so that organization admins only see their
own bots in their personal settings page; this removes a lot of
unnecessary clutter.

Fixes #2657.
2016-12-14 19:29:02 -08:00
Tim Abbott b25562ca1d Add and use util.is_current_user helper function.
Previously, we were checking if a particular user was the current user
in dozens of places in the codebase, and correct case-insensitive
checks were not used consistently, leading to bugs like #502.
2016-06-07 21:58:44 -07:00
Steve Howell 0d0c427f2b Remove unused bot_data.get_all()
(imported from commit 70ec624667dacede72c00f1bb207d8d18dfdd4c1)
2014-03-14 20:48:45 -04:00
Jason Michalski fa37e91e5c Add admin status to bot_data
(imported from commit 47b84b3ef1e97e355dee84f0595e94a4612bf4df)
2014-03-05 14:16:20 -05:00
Jason Michalski 3f6e53db6e Add bot_data module that updated with events
(imported from commit b0bd714258132fc81db763d316a15f5a81b1f4ff)
2014-03-05 14:16:20 -05:00