Commit Graph

34587 Commits

Author SHA1 Message Date
Greg Price e3d843baf9 push-to-pull-request: Give a more detailed error on URL parse failure.
This simplifies debugging when this error fires, e.g. for finding
an issue like the one we just used `git remote get-url` to fix.
2020-02-11 14:45:17 -08:00
Greg Price e7a82e732e push-to-pull-request: Use `git remote get-url`.
This gives us the right behavior when using the `url.*.insteadOf`
mechanism for aliases in Git remote URLs.  For example, if
one's ~/.gitconfig has:

  [url "git@github.com:"]
      insteadOf = gh:

then `git remote add upstream gh:zulip/zulip` will work great, as
the nice, short, mnemonic `gh:` prefix gets expanded to the more
finicky `git@github.com:`.  I use just such a prefix routinely.

But the feature does require that scripts go through the right
abstractions.  In particular `git remote get-url`, since Git 2.7
(from 2016), exists for exactly this reason.  A plain `git config`
command bypasses the expansion, getting the verbatim `gh:...`
version, which doesn't work.

So, switch to that.

As a bonus, we get to behave correctly if for some reason the user
has configured a push URL distinct from the fetch URL for this
remote, just by adding `--push`.  With `git config`, we'd have had
to manually implement the fallback from `remote.upstream.pushUrl` to
`remote.upstream.url` in order to properly handle that case.
2020-02-11 14:45:17 -08:00
Hashir Sarwar 6e14c39468 top_left_corner: Don't export `should_expand_pm_list()`.
We don't need to export `should_expand_pm_list` function
since we are not using it anywhere else.
2020-02-11 14:14:59 -08:00
Tim Abbott 4a36ed6cb2 docs: Advertise support for GitLab authentication. 2020-02-11 14:13:39 -08:00
Dinesh 4304d5f8db auth: Add support for GitLab authentication.
With some tweaks by tabbott to the documentation and comments.

Fixes #13694.
2020-02-11 13:54:17 -08:00
Dinesh 4cb94bf483 auth: Update authentication setup links for github and google config error.
The URL used earlier no longer consists of authentication guide for
github and google. So, two different permalinks to google and github
in authentication.html are added to config_error.html to direct the
user to proper authentication setup guide.
2020-02-11 13:16:49 -08:00
Steve Howell 900f98c0c5 presence: Use realm_id for UserPresence queries.
We now use realm_id for querying UserPresence
instead of building a big WHERE clause from the
list of user_ids.

This commit may be a bit hard to measure, since
we still get the list of user_ids for the PushToken
query in the same method.
2020-02-11 13:11:58 -08:00
Steve Howell d68052b68d presence: Add realm/timestamp index to UserPresence.
It adds this index:

    "zerver_userpresence_realm_id_timestamp_25f410da_idx" btree (realm_id, "timestamp")

We expect this index to provide a major performance improvement when
fetching presence data for the whole realm from the database on
servers like zulipchat.com hosting several realms.
2020-02-11 13:11:28 -08:00
Tim Abbott fcac3a4342 recipients: Rename extract_recipients to extract_private_recipients.
Recent changes mean this function is now only used for private
messages.
2020-02-11 12:28:14 -08:00
Steve Howell 1b6578cafd messages: Fix bug with commas in stream names.
We now validate streams with a separate
function from PM recipients.

It's confusing enough all the ways you can
encode a stream or encode the PM recipients,
but trying to do it all in one function was
hard to reason about and led to at least one
bug.

In particular, there was a bug where streams
with commas in them would get split.  Now
we just don't ever split on commas inside
of `extract_stream_indicator`.

Fixes #13836
2020-02-11 12:20:54 -08:00
Steve Howell 96132fe0e9 extract_recipients: Enforce str as incoming type.
After removing internal_send_message() in a recent
commit, we now have only two callers for
extract_recipients, and they are both related
to our REQ mechanism that always passes strings
to converters.  (If there are default values,
REQ does not call the converters.)

We therefore make two changes:

    - use the more strict annotation of "str"
      for the `s` parameter

    - don't bother with the isinstance check
2020-02-11 12:20:54 -08:00
Steve Howell 8c3eaeb872 Remove obsolete internal_send_messages().
We have been phasing this out for a couple years,
and I fixed the last stragglers over the last
couple days.
2020-02-11 12:20:54 -08:00
Steve Howell 2e8dec233e slow queries: Use internal_send_stream_message().
Note that while the test mocks the actual message
send, we now have a `get_stream` call in the queue
worker, so we have to set up a real stream for
testing (or we could have mocked that as well, but
it didn't seem necessary).  The setup queries add
to the amount of queries reported by the test,
plus the `get_stream` call.  I just made the
query count a digits regex, which is a little bit
lame, but I don't think it's worth risking test
flakes for this.
2020-02-11 12:20:54 -08:00
Steve Howell e37d660d19 error_notify: Use internal_send_stream_message(). 2020-02-11 12:20:53 -08:00
Steve Howell 795c3ad8a5 zjquery: Remove closest() implementation.
This effectively reverts the following
commit from May 2019:

be527905ca

The implementation of closest() was a bit
buggy and complex.  It's easy enough
to just stub the method yourself.  We may
want to eventually re-implement it, but we
should follow the template of parent/set_parent.

If you fail to stub `closest` zjquery gives
a fairly helpful error message:

Error: You must create a stub for $("link-stub").closest
2020-02-11 14:19:03 -05:00
Steve Howell 8f0018ee7c node tests: Use stubs in lightbox tests.
We stub out jquery elements rather than giving
the illusion of having real DOM.

Also, we make it so that the message_store
interaction has an assertion attached to it.
2020-02-11 14:19:03 -05:00
Steve Howell c4e3cfebb0 presence: Add realm_id to UserPresence.
This index is intended to optimize the performance of the very
frequently run query of "what is the presence status of all users in a
realm?".

Main changes:
    - add realm_id to UserPresence
    - add index for realm_id
    - backfill realm_id for old rows
    - change all writes to UserPresence to include
      realm_id

The index is of this form:

    "zerver_userpresence_realm_id_5c4ef5a9" btree (realm_id)

We will create an index on (realm_id, timestamp) in a
future commit, but I think it's a bit faster if you do
the backfill before the index.

There's also a minor tweak to the populate_db script.
2020-02-10 17:21:45 -08:00
Steve Howell 1f62b5e671 populate_db: Remove create_user_presenses() helper.
The last caller to this function was removed in
64230b3bd5

So it's been dead code for a while.
2020-02-10 17:20:44 -08:00
Anders Kaseorg e66c4ea474 settings_invites: Convert invited_as_values from object to Map.
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 15:57:20 -08:00
Anders Kaseorg ed032817c7 hotspots: Convert HOTSPOT_LOCATIONS from object to Map.
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 15:57:20 -08:00
Anders Kaseorg ee68ef516d js: Convert _.isString to typeof.
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 15:57:20 -08:00
Anders Kaseorg a3e5fef663 js: Convert _.isObject to typeof.
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 15:57:20 -08:00
Anders Kaseorg 9f07cf6b0e js: Convert _.values to Object.values.
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 15:57:20 -08:00
Anders Kaseorg 7ca52f1e80 js: Convert _.keys to Object.keys.
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 15:57:20 -08:00
Anders Kaseorg 76e6ffe3c3 tests: Convert all_pills from object to Map.
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 15:57:20 -08:00
Steve Howell 28a8ffbc4c email_mirror: Use internal_send_stream_message().
This is just a refactoring to the more modern API
for sending internal messages.

To make this work we now plumb the email_gateway
flag through `internal_send_stream_message` instead
of `internal_send_message`.

We also change `send_zulip` to have its callers
pass in a full UserProfile object (which one of
them already had).
2020-02-10 15:45:13 -08:00
Steve Howell 6922eef380 signups: Use internal_send_stream_message().
We prefer this to internal_send_message().

We are trying to deprecate `internal_send_message`,
which has extra moving parts related to
`extract_recipients` and `Addressee.legacy_build`.

There are two chunks of code that I touch here
that look pretty similar, but I'm not quite
sure they're worth de-duplicating, since they
use different topics and different message
content.
2020-02-10 15:45:13 -08:00
Steve Howell f1ac16973c tests: Create signups stream in RealmCreationTests. 2020-02-10 15:45:13 -08:00
Steve Howell b33552997e cross realm bots: Simplify notify_new_user.
Instead of having `notify_new_user` delegate
all the heavy lifting to `send_signup_message`,
we just rename `send_signup_message` to be
`notify_new_user` and remove the one-line
wrapper.

We remove a lot of obsolete complexity:

    - `internal` was no longer ever set to True
      by real code, so we kill it off as well
      as well as killing off the internal_blurb code
      and the now-obsolete test

    - the `sender` parameter was actually an
      email, not a UserProfile, but I think
      that got past mypy due to the caller
      passing in something from settings.py

    - we were only passing in NOTIFICATION_BOT
      for the sender, so we just hard code
      that now

    - we eliminate the verbose
      `admin_realm_signup_notifications_stream`
      parameter and just hard code it to
      "signups"

    - we weren't using the optional realm
      parameter

There's also a long ugly comment in
`get_recipient_info` related to this code
that I amended for now.
We should try to take action in a subsequent
commit.
2020-02-10 15:45:13 -08:00
Steve Howell 6e40db4b1f minor: Fix misleading comments.
These comments were naming the wrong function.
2020-02-10 15:45:13 -08:00
Steve Howell 14396c3e32 presence: Prep for upcoming changes to server data.
In the next commit we're going to change what the
server sends for the following:

    - page_params
    - server responses to /json/users/me/presence

We will **not** yet be changing the format of the data
that we get in events when users update their presence.

It's also just a bit in flux what our final formats
will be for various presence payloads, and different
optimizations may lead us to use different data
structures in different payloads.

So for now we decouple these two things:

    raw_info: this is intended to represent a
        snapshot of the latest data from the
        server, including some data like
        timestamps that are only used
        in downstream calculations and not
        user-facing

    exports.presence_info: this is calculated
        info for modules like buddy_data that
        just need to know active vs. idle and
        last_active_date

Another change that happens here is we rename
set_info_for_user to update_info_for_event,
which just makes it clear that the function
expects data in the "event" format (as opposed
to the format for page_params or server
responses).

As of now keeping the intermediate raw_info data
around feels slightly awkward, because we just
immediately calculate presence_info for any kind
of update.  This may be sorta surprising if you
just skim the code and see the various timeout
constants.  You would think we might be automatically
expiring "active" statuses in the client due to
the simple passage of time, but in fact the precise
places we do this are all triggered by new data
from the server and we re-calculate statuses
immediately.

(There are indirect ways that clients
have timing logic, since they ask the
server for new data at various intervals, but a
smarter client could simply expire users on its
own, or at least with a more efficient transfer
of info between it and the server. One of
the thing that complicates client-side logic
is that server and client clocks may be out
of sync.  Also, it's not inherently super expensive
to get updates from the server.)
2020-02-10 14:37:44 -08:00
Steve Howell 75dbc4a2b1 presence: Extract presence.initialize(). 2020-02-10 14:37:44 -08:00
Steve Howell b63909ad41 node tests: Simplify activate_people().
The important details for the test setup here
are just the number of users who are active.
We don't need to simulate the currently awkward
way of populating this data.
2020-02-10 14:37:44 -08:00
Anders Kaseorg 4c1453df68 code-style: Modernize some ancient JavaScript advice.
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 14:08:12 -08:00
Anders Kaseorg bafdf5229a js: Convert _.flatten(a, true) to [].concat(...a).
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 14:08:12 -08:00
Anders Kaseorg 62ad436c64 js: Convert _.compact(a) to a.filter(Boolean).
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 14:08:12 -08:00
Anders Kaseorg d0b0a64af3 js: Convert _.isEmpty(a) to a.length !== 0.
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 14:08:12 -08:00
Anders Kaseorg 8abf5da717 js: Convert _.isArray to Array.isArray.
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 14:08:12 -08:00
Anders Kaseorg e1cf5e4630 js: Convert _.reduce to less convoluted code.
reduce is almost never a better solution than the alternatives.  Avoid
it.

Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 14:08:12 -08:00
Anders Kaseorg 050915c46c js: Convert _.size(a) to a.length.
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 14:08:12 -08:00
Anders Kaseorg 612b237cec js: Convert remaining _.each(a, …) to a.forEach(…).
The _.each calls with an inline function expression have already been
converted to for…of loops.  We could do that here, but using .forEach
when we’re just reusing an existing function seems like a good
guideline.

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

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

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

Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 14:08:12 -08:00
Anders Kaseorg 70ff164f89 js: Convert _.any(a, …), _.some(a, …) to a.some(…).
And convert the corresponding function expressions to arrow style
while we’re here.

Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 14:08:12 -08:00
Anders Kaseorg 2285ee922e js: Convert _.contains(a, …) to a.includes(…).
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 14:08:12 -08:00
Anders Kaseorg ef50346a29 js: Convert _.reject(a, … => …) to a.filter(… => !…).
And convert the corresponding function expressions to arrow style
while we’re here.

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

Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-02-10 14:08:12 -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 719546641f js: Convert a.indexOf(…) !== -1 to a.includes(…).
Babel polyfills this for us for Internet Explorer.

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, {
    visitBinaryExpression(path) {
      const { operator, left, right } = path.node;
      if (
        n.CallExpression.check(left) &&
        n.MemberExpression.check(left.callee) &&
        !left.callee.computed &&
        n.Identifier.check(left.callee.property) &&
        left.callee.property.name === "indexOf" &&
        left.arguments.length === 1 &&
        checkExpression(left.arguments[0]) &&
        ((["===", "!==", "==", "!=", ">", "<="].includes(operator) &&
          n.UnaryExpression.check(right) &&
          right.operator == "-" &&
          n.Literal.check(right.argument) &&
          right.argument.value === 1) ||
          ([">=", "<"].includes(operator) &&
            n.Literal.check(right) &&
            right.value === 0))
      ) {
        const test = b.callExpression(
          b.memberExpression(left.callee.object, b.identifier("includes")),
          [left.arguments[0]]
        );
        path.replace(
          ["!==", "!=", ">", ">="].includes(operator)
            ? test
            : b.unaryExpression("!", test)
        );
        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