mirror of
https://github.com/zulip/zulip.git
synced 2025-11-14 19:06:09 +00:00
Compare commits
1 Commits
shared-0.0
...
6.0-rc1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ba3d004fd |
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"root": true,
|
||||
"env": {
|
||||
"es2020": true,
|
||||
"node": true
|
||||
@@ -51,7 +50,13 @@
|
||||
"import/newline-after-import": "error",
|
||||
"import/no-self-import": "error",
|
||||
"import/no-useless-path-segments": "error",
|
||||
"import/order": ["error", {"alphabetize": {"order": "asc"}, "newlines-between": "always"}],
|
||||
"import/order": [
|
||||
"error",
|
||||
{
|
||||
"alphabetize": {"order": "asc"},
|
||||
"newlines-between": "always"
|
||||
}
|
||||
],
|
||||
"import/unambiguous": "error",
|
||||
"lines-around-directive": "error",
|
||||
"new-cap": "error",
|
||||
@@ -96,10 +101,15 @@
|
||||
"no-useless-concat": "error",
|
||||
"no-useless-constructor": "error",
|
||||
"no-var": "error",
|
||||
"object-shorthand": ["error", "always", {"avoidExplicitReturnArrows": true}],
|
||||
"object-shorthand": "error",
|
||||
"one-var": ["error", "never"],
|
||||
"prefer-arrow-callback": "error",
|
||||
"prefer-const": ["error", {"ignoreReadBeforeAssign": true}],
|
||||
"prefer-const": [
|
||||
"error",
|
||||
{
|
||||
"ignoreReadBeforeAssign": true
|
||||
}
|
||||
],
|
||||
"radix": "error",
|
||||
"sort-imports": ["error", {"ignoreDeclarationSort": true}],
|
||||
"spaced-comment": ["error", "always", {"markers": ["/"]}],
|
||||
@@ -108,10 +118,11 @@
|
||||
"unicorn/explicit-length-check": "off",
|
||||
"unicorn/filename-case": "off",
|
||||
"unicorn/no-await-expression-member": "off",
|
||||
"unicorn/no-negated-condition": "off",
|
||||
"unicorn/no-nested-ternary": "off",
|
||||
"unicorn/no-null": "off",
|
||||
"unicorn/no-process-exit": "off",
|
||||
"unicorn/no-useless-undefined": "off",
|
||||
"unicorn/number-literal-case": "off",
|
||||
"unicorn/numeric-separators-style": "off",
|
||||
"unicorn/prefer-module": "off",
|
||||
"unicorn/prefer-node-protocol": "off",
|
||||
@@ -176,16 +187,18 @@
|
||||
{"allowExpressions": true}
|
||||
],
|
||||
"@typescript-eslint/member-ordering": "error",
|
||||
"@typescript-eslint/no-duplicate-imports": "error",
|
||||
"@typescript-eslint/no-duplicate-imports": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/no-extraneous-class": "error",
|
||||
"@typescript-eslint/no-non-null-assertion": "off",
|
||||
"@typescript-eslint/no-parameter-properties": "error",
|
||||
"@typescript-eslint/no-unnecessary-qualifier": "error",
|
||||
"@typescript-eslint/no-unused-vars": ["error", {"ignoreRestSiblings": true}],
|
||||
"@typescript-eslint/no-unsafe-argument": "off",
|
||||
"@typescript-eslint/no-unsafe-assignment": "off",
|
||||
"@typescript-eslint/no-unsafe-call": "off",
|
||||
"@typescript-eslint/no-unsafe-member-access": "off",
|
||||
"@typescript-eslint/no-unsafe-return": "off",
|
||||
"@typescript-eslint/no-unused-vars": ["error", {"ignoreRestSiblings": true}],
|
||||
"@typescript-eslint/no-use-before-define": "error",
|
||||
"@typescript-eslint/no-useless-constructor": "error",
|
||||
"@typescript-eslint/prefer-includes": "error",
|
||||
|
||||
6
.github/pull_request_template.md
vendored
6
.github/pull_request_template.md
vendored
@@ -9,8 +9,7 @@ Tooling tips: https://zulip.readthedocs.io/en/latest/tutorials/screenshot-and-gi
|
||||
|
||||
**Screenshots and screen captures:**
|
||||
|
||||
<details>
|
||||
<summary>Self-review checklist</summary>
|
||||
**Self-review checklist**
|
||||
|
||||
<!-- Prior to submitting a PR, follow our step-by-step guide to review your own code:
|
||||
https://zulip.readthedocs.io/en/latest/contributing/code-reviewing.html#how-to-review-code -->
|
||||
@@ -28,7 +27,7 @@ Communicate decisions, questions, and potential concerns.
|
||||
- [ ] Calls out remaining decisions and concerns.
|
||||
- [ ] Automated tests verify logic where appropriate.
|
||||
|
||||
Individual commits are ready for review (see [commit discipline](https://zulip.readthedocs.io/en/latest/contributing/commit-discipline.html)).
|
||||
Individual commits are ready for review (see [commit discipline](https://zulip.readthedocs.io/en/latest/contributing/version-control.html)).
|
||||
|
||||
- [ ] Each commit is a coherent idea.
|
||||
- [ ] Commit message(s) explain reasoning and motivation for changes.
|
||||
@@ -40,4 +39,3 @@ Completed manual review and testing of the following:
|
||||
- [ ] Strings and tooltips.
|
||||
- [ ] End-to-end functionality of buttons, interactions and flows.
|
||||
- [ ] Corner cases, error conditions, and easily imagined bugs.
|
||||
</details>
|
||||
|
||||
71
.github/workflows/production-suite.yml
vendored
71
.github/workflows/production-suite.yml
vendored
@@ -47,7 +47,6 @@ jobs:
|
||||
# the top explain how to build and upload these images.
|
||||
# Ubuntu 20.04 ships with Python 3.8.10.
|
||||
container: zulip/ci:focal
|
||||
|
||||
steps:
|
||||
- name: Add required permissions
|
||||
run: |
|
||||
@@ -104,22 +103,11 @@ jobs:
|
||||
path: /tmp/production-build
|
||||
retention-days: 14
|
||||
|
||||
- name: Generate failure report string
|
||||
id: failure_report_string
|
||||
if: ${{ failure() && github.repository == 'zulip/zulip' && github.event_name == 'push' }}
|
||||
run: tools/ci/generate-failure-message >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Report status to CZO
|
||||
if: ${{ failure() && github.repository == 'zulip/zulip' && github.event_name == 'push' }}
|
||||
uses: zulip/github-actions-zulip/send-message@v1
|
||||
with:
|
||||
api-key: ${{ secrets.ZULIP_BOT_KEY }}
|
||||
email: "github-actions-bot@chat.zulip.org"
|
||||
organization-url: "https://chat.zulip.org"
|
||||
to: "automated testing"
|
||||
topic: ${{ steps.failure_report_string.outputs.topic }}
|
||||
type: "stream"
|
||||
content: ${{ steps.failure_report_string.outputs.content }}
|
||||
- name: Report status
|
||||
if: failure()
|
||||
env:
|
||||
ZULIP_BOT_KEY: ${{ secrets.ZULIP_BOT_KEY }}
|
||||
run: tools/ci/send-failure-message
|
||||
|
||||
production_install:
|
||||
# This job installs the server release tarball built above on a
|
||||
@@ -172,7 +160,7 @@ jobs:
|
||||
chmod +x /tmp/production-pgroonga
|
||||
chmod +x /tmp/production-install
|
||||
chmod +x /tmp/production-verify
|
||||
chmod +x /tmp/generate-failure-message
|
||||
chmod +x /tmp/send-failure-message
|
||||
|
||||
- name: Create cache directories
|
||||
run: |
|
||||
@@ -209,22 +197,11 @@ jobs:
|
||||
if: ${{ matrix.os == 'focal' }}
|
||||
run: sudo /tmp/production-verify ${{ matrix.extra-args }}
|
||||
|
||||
- name: Generate failure report string
|
||||
id: failure_report_string
|
||||
if: ${{ failure() && github.repository == 'zulip/zulip' && github.event_name == 'push' }}
|
||||
run: tools/ci/generate-failure-message >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Report status to CZO
|
||||
if: ${{ failure() && github.repository == 'zulip/zulip' && github.event_name == 'push' }}
|
||||
uses: zulip/github-actions-zulip/send-message@v1
|
||||
with:
|
||||
api-key: ${{ secrets.ZULIP_BOT_KEY }}
|
||||
email: "github-actions-bot@chat.zulip.org"
|
||||
organization-url: "https://chat.zulip.org"
|
||||
to: "automated testing"
|
||||
topic: ${{ steps.failure_report_string.outputs.topic }}
|
||||
type: "stream"
|
||||
content: ${{ steps.failure_report_string.outputs.content }}
|
||||
- name: Report status
|
||||
if: failure()
|
||||
env:
|
||||
ZULIP_BOT_KEY: ${{ secrets.ZULIP_BOT_KEY }}
|
||||
run: /tmp/send-failure-message
|
||||
|
||||
production_upgrade:
|
||||
# The production upgrade job starts with a container with a
|
||||
@@ -248,9 +225,6 @@ jobs:
|
||||
- docker_image: zulip/ci:bullseye-5.0
|
||||
name: 5.0 Version Upgrade
|
||||
os: bullseye
|
||||
- docker_image: zulip/ci:bullseye-6.0
|
||||
name: 6.0 Version Upgrade
|
||||
os: bullseye
|
||||
|
||||
name: ${{ matrix.name }}
|
||||
container:
|
||||
@@ -277,7 +251,7 @@ jobs:
|
||||
# of the tarball uploaded by the upload artifact fix those.
|
||||
chmod +x /tmp/production-upgrade
|
||||
chmod +x /tmp/production-verify
|
||||
chmod +x /tmp/generate-failure-message
|
||||
chmod +x /tmp/send-failure-message
|
||||
|
||||
- name: Create cache directories
|
||||
run: |
|
||||
@@ -294,19 +268,8 @@ jobs:
|
||||
# - name: Verify install
|
||||
# run: sudo /tmp/production-verify
|
||||
|
||||
- name: Generate failure report string
|
||||
id: failure_report_string
|
||||
if: ${{ failure() && github.repository == 'zulip/zulip' && github.event_name == 'push' }}
|
||||
run: tools/ci/generate-failure-message >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Report status to CZO
|
||||
if: ${{ failure() && github.repository == 'zulip/zulip' && github.event_name == 'push' }}
|
||||
uses: zulip/github-actions-zulip/send-message@v1
|
||||
with:
|
||||
api-key: ${{ secrets.ZULIP_BOT_KEY }}
|
||||
email: "github-actions-bot@chat.zulip.org"
|
||||
organization-url: "https://chat.zulip.org"
|
||||
to: "automated testing"
|
||||
topic: ${{ steps.failure_report_string.outputs.topic }}
|
||||
type: "stream"
|
||||
content: ${{ steps.failure_report_string.outputs.content }}
|
||||
- name: Report status
|
||||
if: failure()
|
||||
env:
|
||||
ZULIP_BOT_KEY: ${{ secrets.ZULIP_BOT_KEY }}
|
||||
run: /tmp/send-failure-message
|
||||
|
||||
22
.github/workflows/zulip-ci.yml
vendored
22
.github/workflows/zulip-ci.yml
vendored
@@ -150,7 +150,6 @@ jobs:
|
||||
./tools/test-migrations
|
||||
./tools/setup/optimize-svg --check
|
||||
./tools/setup/generate_integration_bots_avatars.py --check-missing
|
||||
./tools/ci/check-executables
|
||||
|
||||
# Ban check-database-compatibility.py from transitively
|
||||
# relying on static/generated, because it might not be
|
||||
@@ -234,19 +233,8 @@ jobs:
|
||||
- name: Check development database build
|
||||
run: ./tools/ci/setup-backend
|
||||
|
||||
- name: Generate failure report string
|
||||
id: failure_report_string
|
||||
if: ${{ failure() && github.repository == 'zulip/zulip' && github.event_name == 'push' }}
|
||||
run: tools/ci/generate-failure-message >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Report status to CZO
|
||||
if: ${{ failure() && github.repository == 'zulip/zulip' && github.event_name == 'push' }}
|
||||
uses: zulip/github-actions-zulip/send-message@v1
|
||||
with:
|
||||
api-key: ${{ secrets.ZULIP_BOT_KEY }}
|
||||
email: "github-actions-bot@chat.zulip.org"
|
||||
organization-url: "https://chat.zulip.org"
|
||||
to: "automated testing"
|
||||
topic: ${{ steps.failure_report_string.outputs.topic }}
|
||||
type: "stream"
|
||||
content: ${{ steps.failure_report_string.outputs.content }}
|
||||
- name: Report status
|
||||
if: failure()
|
||||
env:
|
||||
ZULIP_BOT_KEY: ${{ secrets.ZULIP_BOT_KEY }}
|
||||
run: tools/ci/send-failure-message
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -33,7 +33,6 @@ package-lock.json
|
||||
!/var/puppeteer/test_credentials.d.ts
|
||||
|
||||
/.dmypy.json
|
||||
/.ruff_cache
|
||||
|
||||
# Generated i18n data
|
||||
/locale/en
|
||||
|
||||
19
.mailmap
19
.mailmap
@@ -24,7 +24,6 @@ Anders Kaseorg <anders@zulip.com> <anders@zulipchat.com>
|
||||
Anders Kaseorg <anders@zulip.com> <andersk@mit.edu>
|
||||
Aryan Shridhar <aryanshridhar7@gmail.com> <53977614+aryanshridhar@users.noreply.github.com>
|
||||
Aryan Shridhar <aryanshridhar7@gmail.com>
|
||||
aparna-bhatt <aparnabhatt2001@gmail.com> <86338542+aparna-bhatt@users.noreply.github.com>
|
||||
Ashwat Kumar Singh <ashwat.kumarsingh.met20@itbhu.ac.in>
|
||||
Austin Riba <austin@zulip.com> <austin@m51.io>
|
||||
BIKI DAS <bikid475@gmail.com>
|
||||
@@ -34,8 +33,6 @@ Brock Whittaker <brock@zulipchat.com> <brock@zulipchat.org>
|
||||
Chris Bobbe <cbobbe@zulip.com> <cbobbe@zulipchat.com>
|
||||
Chris Bobbe <cbobbe@zulip.com> <csbobbe@gmail.com>
|
||||
Eeshan Garg <eeshan@zulip.com> <jerryguitarist@gmail.com>
|
||||
Eric Smith <erwsmith@gmail.com> <99841919+erwsmith@users.noreply.github.com>
|
||||
Ganesh Pawar <pawarg256@gmail.com> <58626718+ganpa3@users.noreply.github.com>
|
||||
Greg Price <greg@zulip.com> <gnprice@gmail.com>
|
||||
Greg Price <greg@zulip.com> <greg@zulipchat.com>
|
||||
Greg Price <greg@zulip.com> <price@mit.edu>
|
||||
@@ -50,30 +47,21 @@ Kevin Mehall <km@kevinmehall.net> <kevin@humbughq.com>
|
||||
Kevin Mehall <km@kevinmehall.net> <kevin@zulip.com>
|
||||
Kevin Scott <kevin.scott.98@gmail.com>
|
||||
Lauryn Menard <lauryn@zulip.com> <lauryn.menard@gmail.com>
|
||||
Lauryn Menard <lauryn@zulip.com> <63245456+laurynmm@users.noreply.github.com>
|
||||
Mateusz Mandera <mateusz.mandera@zulip.com> <mateusz.mandera@protonmail.com>
|
||||
Matt Keller <matt@zulip.com>
|
||||
Matt Keller <matt@zulip.com> <m@cognusion.com>
|
||||
m-e-l-u-h-a-n <purushottam.tiwari.cd.cse19@itbhu.ac.in>
|
||||
Noble Mittal <noblemittal@outlook.com> <62551163+beingnoble03@users.noreply.github.com>
|
||||
Palash Raghuwanshi <singhpalash0@gmail.com>
|
||||
Parth <mittalparth22@gmail.com>
|
||||
Priyam Seth <sethpriyam1@gmail.com> <b19188@students.iitmandi.ac.in>
|
||||
Ray Kraesig <rkraesig@zulip.com> <rkraesig@zulipchat.com>
|
||||
Reid Barton <rwbarton@gmail.com> <rwbarton@humbughq.com>
|
||||
Rein Zustand (rht) <rhtbot@protonmail.com>
|
||||
Rishi Gupta <rishig@zulipchat.com> <rishig+git@mit.edu>
|
||||
Rishi Gupta <rishig@zulipchat.com> <rishig@kandralabs.com>
|
||||
Rishi Gupta <rishig@zulipchat.com> <rishig@users.noreply.github.com>
|
||||
Rishabh Maheshwari <b20063@students.iitmandi.ac.in>
|
||||
Rixant Rokaha <rixantrokaha@gmail.com>
|
||||
Rixant Rokaha <rixantrokaha@gmail.com> <rishantrokaha@gmail.com>
|
||||
Rixant Rokaha <rixantrokaha@gmail.com> <rrokaha@caldwell.edu>
|
||||
Sayam Samal <samal.sayam@gmail.com>
|
||||
Scott Feeney <scott@oceanbase.org> <scott@humbughq.com>
|
||||
Scott Feeney <scott@oceanbase.org> <scott@zulip.com>
|
||||
Shlok Patel <shlokcpatel2001@gmail.com>
|
||||
Somesh Ranjan <somesh.ranjan.met20@itbhu.ac.in> <77766761+somesh202@users.noreply.github.com>
|
||||
Steve Howell <showell@zulip.com> <showell30@yahoo.com>
|
||||
Steve Howell <showell@zulip.com> <showell@yahoo.com>
|
||||
Steve Howell <showell@zulip.com> <showell@zulipchat.com>
|
||||
@@ -91,12 +79,5 @@ Sahil Batra <sahil@zulip.com> <sahilbatra839@gmail.com>
|
||||
Yash RE <33805964+YashRE42@users.noreply.github.com> <YashRE42@github.com>
|
||||
Yash RE <33805964+YashRE42@users.noreply.github.com>
|
||||
Yogesh Sirsat <yogeshsirsat56@gmail.com>
|
||||
Yogesh Sirsat <yogeshsirsat56@gmail.com> <41695888+yogesh-sirsat@users.noreply.github.com>
|
||||
Zeeshan Equbal <equbalzeeshan@gmail.com> <54993043+zee-bit@users.noreply.github.com>
|
||||
Zeeshan Equbal <equbalzeeshan@gmail.com>
|
||||
Zev Benjamin <zev@zulip.com> <zev@dropbox.com>
|
||||
Zev Benjamin <zev@zulip.com> <zev@humbughq.com>
|
||||
Zev Benjamin <zev@zulip.com> <zev@mit.edu>
|
||||
Zixuan James Li <p359101898@gmail.com>
|
||||
Zixuan James Li <p359101898@gmail.com> <39874143+PIG208@users.noreply.github.com>
|
||||
Zixuan James Li <p359101898@gmail.com> <359101898@qq.com>
|
||||
|
||||
27
.tx/config
27
.tx/config
@@ -1,39 +1,32 @@
|
||||
# Migrated from transifex-client format with `tx migrate`
|
||||
#
|
||||
# See https://developers.transifex.com/docs/using-the-client which hints at
|
||||
# this format, but in general, the headings are in the format of:
|
||||
#
|
||||
# [o:<org>:p:<project>:r:<resource>]
|
||||
|
||||
[main]
|
||||
host = https://www.transifex.com
|
||||
lang_map = zh-Hans: zh_Hans, zh-Hant: zh_Hant
|
||||
|
||||
[o:zulip:p:zulip:r:djangopo]
|
||||
[zulip.djangopo]
|
||||
file_filter = locale/<lang>/LC_MESSAGES/django.po
|
||||
source_file = locale/en/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
type = PO
|
||||
|
||||
[o:zulip:p:zulip:r:mobile]
|
||||
[zulip.translationsjson]
|
||||
file_filter = locale/<lang>/translations.json
|
||||
source_file = locale/en/translations.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[zulip.mobile]
|
||||
file_filter = locale/<lang>/mobile.json
|
||||
source_file = locale/en/mobile.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[o:zulip:p:zulip:r:translationsjson]
|
||||
file_filter = locale/<lang>/translations.json
|
||||
source_file = locale/en/translations.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
[o:zulip:p:zulip-test:r:djangopo]
|
||||
[zulip-test.djangopo]
|
||||
file_filter = locale/<lang>/LC_MESSAGES/django.po
|
||||
source_file = locale/en/LC_MESSAGES/django.po
|
||||
source_lang = en
|
||||
type = PO
|
||||
|
||||
[o:zulip:p:zulip-test:r:translationsjson]
|
||||
[zulip-test.translationsjson]
|
||||
file_filter = locale/<lang>/translations.json
|
||||
source_file = locale/en/translations.json
|
||||
source_lang = en
|
||||
|
||||
@@ -102,71 +102,3 @@ This Code of Conduct is adapted from the
|
||||
under a
|
||||
[Creative Commons BY-SA](https://creativecommons.org/licenses/by-sa/4.0/)
|
||||
license.
|
||||
|
||||
## Moderating the Zulip community
|
||||
|
||||
Anyone can help moderate the Zulip community by helping make sure that folks are
|
||||
aware of the [community guidelines](https://zulip.com/development-community/)
|
||||
and this Code of Conduct, and that we maintain a positive and respectful
|
||||
atmosphere.
|
||||
|
||||
Here are some guidelines for you how can help:
|
||||
|
||||
- Be friendly! Welcoming folks, thanking them for their feedback, ideas and effort,
|
||||
and just trying to keep the atmosphere warm make the whole community function
|
||||
more smoothly. New participants who feel accepted, listened to and respected
|
||||
are likely to treat others the same way.
|
||||
|
||||
- Be familiar with the [community
|
||||
guidelines](https://zulip.com/development-community/), and cite them liberally
|
||||
when a user violates them. Be polite but firm. Some examples:
|
||||
|
||||
- @user please note that there is no need to @-mention @\_**Tim Abbott** when
|
||||
you ask a question. As noted in the [guidelines for this
|
||||
community](https://zulip.com/development-community/):
|
||||
|
||||
> Use @-mentions sparingly… there is generally no need to @-mention a
|
||||
> core contributor unless you need their timely attention.
|
||||
|
||||
- @user, please keep in mind the following [community
|
||||
guideline](https://zulip.com/development-community/):
|
||||
|
||||
> Don’t ask the same question in multiple places. Moderators read every
|
||||
> public stream, and make sure every question gets a reply.
|
||||
|
||||
I’ve gone ahead and moved the other copy of this message to this thread.
|
||||
|
||||
- If asked a question in a PM that is better discussed in a public stream:
|
||||
> Hi @user! Please start by reviewing
|
||||
> https://zulip.com/development-community/#community-norms to learn how to
|
||||
> get help in this community.
|
||||
|
||||
- Users sometimes think chat.zulip.org is a testing instance. When this happens,
|
||||
kindly direct them to use the **#test here** stream.
|
||||
|
||||
- If you see a message that’s posted in the wrong place, go ahead and move it if
|
||||
you have permissions to do so, even if you don’t plan to respond to it.
|
||||
Leaving the “Send automated notice to new topic” option enabled helps make it
|
||||
clear what happened to the person who sent the message.
|
||||
|
||||
If you are responding to a message that's been moved, mention the user in your
|
||||
reply, so that the mention serves as a notification of the new location for
|
||||
their conversation.
|
||||
|
||||
- If a user is posting spam, please report it to an administrator. They will:
|
||||
|
||||
- Change the user's name to `<name> (spammer)` and deactivate them.
|
||||
- Delete any spam messages they posted in public streams.
|
||||
|
||||
- We care very much about maintaining a respectful tone in our community. If you
|
||||
see someone being mean or rude, point out that their tone is inappropriate,
|
||||
and ask them to communicate their perspective in a respectful way in the
|
||||
future. If you don’t feel comfortable doing so yourself, feel free to ask a
|
||||
member of Zulip's core team to take care of the situation.
|
||||
|
||||
- Try to assume the best intentions from others (given the range of
|
||||
possibilities presented by their visible behavior), and stick with a friendly
|
||||
and positive tone even when someone‘s behavior is poor or disrespectful.
|
||||
Everyone has bad days and stressful situations that can result in them
|
||||
behaving not their best, and while we should be firm about our community
|
||||
rules, we should also enforce them with kindness.
|
||||
|
||||
@@ -76,13 +76,12 @@ to help.
|
||||
|
||||
- First, make an account on the
|
||||
[Zulip community server](https://zulip.com/development-community/),
|
||||
paying special attention to the
|
||||
[community norms](https://zulip.com/development-community/#community-norms).
|
||||
If you'd like, introduce yourself in
|
||||
paying special attention to the community norms. If you'd like, introduce
|
||||
yourself in
|
||||
[#new members](https://chat.zulip.org/#narrow/stream/95-new-members), using
|
||||
your name as the topic. Bonus: tell us about your first impressions of
|
||||
Zulip, and anything that felt confusing/broken or interesting/helpful as you
|
||||
started using the product.
|
||||
Zulip, and anything that felt confusing/broken as you started using the
|
||||
product.
|
||||
- Read [What makes a great Zulip contributor](#what-makes-a-great-zulip-contributor).
|
||||
- [Install the development environment](https://zulip.readthedocs.io/en/latest/development/overview.html),
|
||||
getting help in
|
||||
@@ -147,6 +146,14 @@ Note that you are _not_ claiming an issue while you are iterating through steps
|
||||
1-4. _Before you claim an issue_, you should be confident that you will be able to
|
||||
tackle it effectively.
|
||||
|
||||
If the lists of issues are overwhelming, you can post in
|
||||
[#new members](https://chat.zulip.org/#narrow/stream/95-new-members) with a
|
||||
bit about your background and interests, and we'll help you out. The most
|
||||
important thing to say is whether you're looking for a backend (Python),
|
||||
frontend (JavaScript and TypeScript), mobile (React Native), desktop (Electron),
|
||||
documentation (English) or visual design (JavaScript/TypeScript + CSS) issue, and a
|
||||
bit about your programming experience and available time.
|
||||
|
||||
Additional tips for the [main server and web app
|
||||
repository](https://github.com/zulip/zulip/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22):
|
||||
|
||||
@@ -333,21 +340,10 @@ labels.
|
||||
have a new feature you'd like to add, you can start a conversation [in our
|
||||
development community](https://zulip.com/development-community/#where-do-i-send-my-message)
|
||||
explaining the feature idea and the problem that you're hoping to solve.
|
||||
- **I'm waiting for the next round of review on my PR. Can I pick up
|
||||
another issue in the meantime?** Someone's first Zulip PR often
|
||||
requires quite a bit of iteration, so please [make sure your pull
|
||||
request is reviewable][reviewable-pull-requests] and go through at
|
||||
least one round of feedback from others before picking up a second
|
||||
issue. After that, sure! If
|
||||
[Zulipbot](https://github.com/zulip/zulipbot) does not allow you to
|
||||
claim an issue, you can post a comment describing the status of your
|
||||
other work on the issue you're interested in, and asking for the
|
||||
issue to be assigned to you. Note that addressing feedback on
|
||||
in-progress PRs should always take priority over starting a new PR.
|
||||
- **I think my PR is done, but it hasn't been merged yet. What's going on?**
|
||||
1. **Double-check that you have addressed all the feedback**, including any comments
|
||||
on [Git commit
|
||||
discipline](https://zulip.readthedocs.io/en/latest/contributing/commit-discipline.html).
|
||||
discipline](https://zulip.readthedocs.io/en/latest/contributing/version-control.html#commit-discipline).
|
||||
2. If all the feedback has been addressed, did you [leave a
|
||||
comment](#how-to-help-move-the-review-process-forward)
|
||||
explaining that you have done so and **requesting another review**? If not,
|
||||
@@ -365,8 +361,6 @@ labels.
|
||||
occasionally take a few weeks for a PR in the final stages of the review
|
||||
process to be merged.
|
||||
|
||||
[reviewable-pull-requests]: https://zulip.readthedocs.io/en/latest/contributing/reviewable-prs.html
|
||||
|
||||
## What makes a great Zulip contributor?
|
||||
|
||||
Zulip has a lot of experience working with new contributors. In our
|
||||
@@ -378,7 +372,7 @@ experience, these are the best predictors of success:
|
||||
you got stuck. Post tracebacks or other error messages if appropriate. For
|
||||
more advice, check out [our guide][great-questions]!
|
||||
- Learning and practicing
|
||||
[Git commit discipline](https://zulip.readthedocs.io/en/latest/contributing/commit-discipline.html).
|
||||
[Git commit discipline](https://zulip.readthedocs.io/en/latest/contributing/version-control.html#commit-discipline).
|
||||
- Submitting carefully tested code. See our [detailed guide on how to review
|
||||
code](https://zulip.readthedocs.io/en/latest/contributing/code-reviewing.html#how-to-review-code)
|
||||
(yours or someone else's).
|
||||
|
||||
@@ -17,7 +17,6 @@ Come find us on the [development community chat](https://zulip.com/development-c
|
||||
[](https://github.com/zulip/zulip/actions/workflows/zulip-ci.yml?query=branch%3Amain)
|
||||
[](https://codecov.io/gh/zulip/zulip)
|
||||
[][mypy-coverage]
|
||||
[](https://github.com/charliermarsh/ruff)
|
||||
[](https://github.com/psf/black)
|
||||
[](https://github.com/prettier/prettier)
|
||||
[](https://github.com/zulip/zulip/releases/latest)
|
||||
|
||||
@@ -8,7 +8,7 @@ from django.utils.timezone import now as timezone_now
|
||||
|
||||
from analytics.lib.counts import COUNT_STATS, CountStat
|
||||
from analytics.models import installation_epoch
|
||||
from zerver.lib.timestamp import TimeZoneNotUTCError, floor_to_day, floor_to_hour, verify_UTC
|
||||
from zerver.lib.timestamp import TimeZoneNotUTCException, floor_to_day, floor_to_hour, verify_UTC
|
||||
from zerver.models import Realm
|
||||
|
||||
states = {
|
||||
@@ -48,7 +48,7 @@ class Command(BaseCommand):
|
||||
last_fill = installation_epoch()
|
||||
try:
|
||||
verify_UTC(last_fill)
|
||||
except TimeZoneNotUTCError:
|
||||
except TimeZoneNotUTCException:
|
||||
return {"status": 2, "message": f"FillState not in UTC for {property}"}
|
||||
|
||||
if stat.frequency == CountStat.DAY:
|
||||
|
||||
@@ -32,7 +32,7 @@ class ActivityTest(ZulipTestCase):
|
||||
user_profile.save(update_fields=["is_staff"])
|
||||
|
||||
flush_per_request_caches()
|
||||
with self.assert_database_query_count(18):
|
||||
with self.assert_database_query_count(19):
|
||||
result = self.client_get("/activity")
|
||||
self.assertEqual(result.status_code, 200)
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ from zerver.actions.users import do_deactivate_user
|
||||
from zerver.lib.create_user import create_user
|
||||
from zerver.lib.exceptions import InvitationError
|
||||
from zerver.lib.test_classes import ZulipTestCase
|
||||
from zerver.lib.timestamp import TimeZoneNotUTCError, floor_to_day
|
||||
from zerver.lib.timestamp import TimeZoneNotUTCException, floor_to_day
|
||||
from zerver.lib.topic import DB_TOPIC_NAME
|
||||
from zerver.lib.utils import assert_is_not_none
|
||||
from zerver.models import (
|
||||
@@ -290,7 +290,7 @@ class TestProcessCountStat(AnalyticsTestCase):
|
||||
stat = self.make_dummy_count_stat("test stat")
|
||||
with self.assertRaises(ValueError):
|
||||
process_count_stat(stat, installation_epoch() + 65 * self.MINUTE)
|
||||
with self.assertRaises(TimeZoneNotUTCError):
|
||||
with self.assertRaises(TimeZoneNotUTCException):
|
||||
process_count_stat(stat, installation_epoch().replace(tzinfo=None))
|
||||
|
||||
# This tests the LoggingCountStat branch of the code in do_delete_counts_at_hour.
|
||||
|
||||
@@ -3,16 +3,14 @@ import sys
|
||||
from datetime import datetime
|
||||
from html import escape
|
||||
from typing import Any, Collection, Dict, List, Optional, Sequence
|
||||
from urllib.parse import urlencode
|
||||
|
||||
from django.conf import settings
|
||||
from django.db.backends.utils import CursorWrapper
|
||||
from django.template import loader
|
||||
from django.urls import reverse
|
||||
from markupsafe import Markup
|
||||
from markupsafe import Markup as mark_safe
|
||||
|
||||
from zerver.lib.url_encoding import append_url_query_string
|
||||
from zerver.models import UserActivity, get_realm
|
||||
from zerver.models import UserActivity
|
||||
|
||||
if sys.version_info < (3, 9): # nocoverage
|
||||
from backports import zoneinfo
|
||||
@@ -48,7 +46,7 @@ def make_table(
|
||||
|
||||
|
||||
def dictfetchall(cursor: CursorWrapper) -> List[Dict[str, Any]]:
|
||||
"""Returns all rows from a cursor as a dict"""
|
||||
"Returns all rows from a cursor as a dict"
|
||||
desc = cursor.description
|
||||
return [dict(zip((col[0] for col in desc), row)) for row in cursor.fetchall()]
|
||||
|
||||
@@ -60,50 +58,36 @@ def format_date_for_activity_reports(date: Optional[datetime]) -> str:
|
||||
return ""
|
||||
|
||||
|
||||
def user_activity_link(email: str, user_profile_id: int) -> Markup:
|
||||
def user_activity_link(email: str, user_profile_id: int) -> mark_safe:
|
||||
from analytics.views.user_activity import get_user_activity
|
||||
|
||||
url = reverse(get_user_activity, kwargs=dict(user_profile_id=user_profile_id))
|
||||
email_link = f'<a href="{escape(url)}">{escape(email)}</a>'
|
||||
return Markup(email_link)
|
||||
return mark_safe(email_link)
|
||||
|
||||
|
||||
def realm_activity_link(realm_str: str) -> Markup:
|
||||
def realm_activity_link(realm_str: str) -> mark_safe:
|
||||
from analytics.views.realm_activity import get_realm_activity
|
||||
|
||||
url = reverse(get_realm_activity, kwargs=dict(realm_str=realm_str))
|
||||
realm_link = f'<a href="{escape(url)}">{escape(realm_str)}</a>'
|
||||
return Markup(realm_link)
|
||||
return mark_safe(realm_link)
|
||||
|
||||
|
||||
def realm_stats_link(realm_str: str) -> Markup:
|
||||
def realm_stats_link(realm_str: str) -> mark_safe:
|
||||
from analytics.views.stats import stats_for_realm
|
||||
|
||||
url = reverse(stats_for_realm, kwargs=dict(realm_str=realm_str))
|
||||
stats_link = f'<a href="{escape(url)}"><i class="fa fa-pie-chart"></i></a>'
|
||||
return Markup(stats_link)
|
||||
stats_link = f'<a href="{escape(url)}"><i class="fa fa-pie-chart"></i>{escape(realm_str)}</a>'
|
||||
return mark_safe(stats_link)
|
||||
|
||||
|
||||
def realm_support_link(realm_str: str) -> Markup:
|
||||
support_url = reverse("support")
|
||||
query = urlencode({"q": realm_str})
|
||||
url = append_url_query_string(support_url, query)
|
||||
support_link = f'<a href="{escape(url)}">{escape(realm_str)}</a>'
|
||||
return Markup(support_link)
|
||||
|
||||
|
||||
def realm_url_link(realm_str: str) -> Markup:
|
||||
url = get_realm(realm_str).uri
|
||||
realm_link = f'<a href="{escape(url)}"><i class="fa fa-home"></i></a>'
|
||||
return Markup(realm_link)
|
||||
|
||||
|
||||
def remote_installation_stats_link(server_id: int, hostname: str) -> Markup:
|
||||
def remote_installation_stats_link(server_id: int, hostname: str) -> mark_safe:
|
||||
from analytics.views.stats import stats_for_remote_installation
|
||||
|
||||
url = reverse(stats_for_remote_installation, kwargs=dict(remote_server_id=server_id))
|
||||
stats_link = f'<a href="{escape(url)}"><i class="fa fa-pie-chart"></i>{escape(hostname)}</a>'
|
||||
return Markup(stats_link)
|
||||
return mark_safe(stats_link)
|
||||
|
||||
|
||||
def get_user_activity_summary(records: Collection[UserActivity]) -> Dict[str, Any]:
|
||||
|
||||
@@ -10,7 +10,7 @@ from django.http import HttpRequest, HttpResponse
|
||||
from django.shortcuts import render
|
||||
from django.template import loader
|
||||
from django.utils.timezone import now as timezone_now
|
||||
from markupsafe import Markup
|
||||
from markupsafe import Markup as mark_safe
|
||||
from psycopg2.sql import SQL, Composable, Literal
|
||||
|
||||
from analytics.lib.counts import COUNT_STATS
|
||||
@@ -20,15 +20,13 @@ from analytics.views.activity_common import (
|
||||
make_table,
|
||||
realm_activity_link,
|
||||
realm_stats_link,
|
||||
realm_support_link,
|
||||
realm_url_link,
|
||||
remote_installation_stats_link,
|
||||
)
|
||||
from analytics.views.support import get_plan_name
|
||||
from zerver.decorator import require_server_admin
|
||||
from zerver.lib.request import has_request_variables
|
||||
from zerver.lib.timestamp import timestamp_to_datetime
|
||||
from zerver.models import Realm, UserActivityInterval, get_org_type_display_name
|
||||
from zerver.models import Realm, UserActivityInterval, UserProfile, get_org_type_display_name
|
||||
|
||||
if settings.BILLING_ENABLED:
|
||||
from corporate.lib.stripe import (
|
||||
@@ -189,10 +187,19 @@ def realm_summary_table(realm_minutes: Dict[str, float]) -> str:
|
||||
rows = dictfetchall(cursor)
|
||||
cursor.close()
|
||||
|
||||
# Fetch all the realm administrator users
|
||||
realm_owners: Dict[str, List[str]] = defaultdict(list)
|
||||
for up in UserProfile.objects.select_related("realm").filter(
|
||||
role=UserProfile.ROLE_REALM_OWNER,
|
||||
is_active=True,
|
||||
):
|
||||
realm_owners[up.realm.string_id].append(up.delivery_email)
|
||||
|
||||
for row in rows:
|
||||
row["date_created_day"] = row["date_created"].strftime("%Y-%m-%d")
|
||||
row["age_days"] = int((now - row["date_created"]).total_seconds() / 86400)
|
||||
row["is_new"] = row["age_days"] < 12 * 7
|
||||
row["realm_owner_emails"] = ", ".join(realm_owners[row["string_id"]])
|
||||
|
||||
# get messages sent per day
|
||||
counts = get_realm_day_counts()
|
||||
@@ -248,9 +255,7 @@ def realm_summary_table(realm_minutes: Dict[str, float]) -> str:
|
||||
|
||||
# formatting
|
||||
for row in rows:
|
||||
row["realm_url"] = realm_url_link(row["string_id"])
|
||||
row["stats_link"] = realm_stats_link(row["string_id"])
|
||||
row["support_link"] = realm_support_link(row["string_id"])
|
||||
row["string_id"] = realm_activity_link(row["string_id"])
|
||||
|
||||
# Count active sites
|
||||
@@ -276,10 +281,9 @@ def realm_summary_table(realm_minutes: Dict[str, float]) -> str:
|
||||
org_type_string="",
|
||||
effective_rate="",
|
||||
arr=total_arr,
|
||||
realm_url="",
|
||||
stats_link="",
|
||||
support_link="",
|
||||
date_created_day="",
|
||||
realm_owner_emails="",
|
||||
dau_count=total_dau_count,
|
||||
user_profile_count=total_user_profile_count,
|
||||
bot_count=total_bot_count,
|
||||
@@ -294,14 +298,14 @@ def realm_summary_table(realm_minutes: Dict[str, float]) -> str:
|
||||
dict(
|
||||
rows=rows,
|
||||
num_active_sites=num_active_sites,
|
||||
utctime=now.strftime("%Y-%m-%d %H:%M %Z"),
|
||||
utctime=now.strftime("%Y-%m-%d %H:%MZ"),
|
||||
billing_enabled=settings.BILLING_ENABLED,
|
||||
),
|
||||
)
|
||||
return content
|
||||
|
||||
|
||||
def user_activity_intervals() -> Tuple[Markup, Dict[str, float]]:
|
||||
def user_activity_intervals() -> Tuple[mark_safe, Dict[str, float]]:
|
||||
day_end = timestamp_to_datetime(time.time())
|
||||
day_start = day_end - timedelta(hours=24)
|
||||
|
||||
@@ -353,7 +357,7 @@ def user_activity_intervals() -> Tuple[Markup, Dict[str, float]]:
|
||||
output += f"\nTotal duration: {total_duration}\n"
|
||||
output += f"\nTotal duration in minutes: {total_duration.total_seconds() / 60.}\n"
|
||||
output += f"Total duration amortized to a month: {total_duration.total_seconds() * 30. / 60.}"
|
||||
content = Markup("<pre>" + output + "</pre>")
|
||||
content = mark_safe("<pre>" + output + "</pre>")
|
||||
return content, realm_minutes
|
||||
|
||||
|
||||
@@ -368,7 +372,7 @@ def ad_hoc_queries() -> List[Dict[str, str]]:
|
||||
cursor.close()
|
||||
|
||||
def fix_rows(
|
||||
i: int, fixup_func: Union[Callable[[str], Markup], Callable[[datetime], str]]
|
||||
i: int, fixup_func: Union[Callable[[str], mark_safe], Callable[[datetime], str]]
|
||||
) -> None:
|
||||
for row in rows:
|
||||
row[i] = fixup_func(row[i])
|
||||
|
||||
@@ -13,7 +13,6 @@ from analytics.views.activity_common import (
|
||||
format_date_for_activity_reports,
|
||||
get_user_activity_summary,
|
||||
make_table,
|
||||
realm_stats_link,
|
||||
user_activity_link,
|
||||
)
|
||||
from zerver.decorator import require_server_admin
|
||||
@@ -253,10 +252,8 @@ def get_realm_activity(request: HttpRequest, realm_str: str) -> HttpResponse:
|
||||
data += [(page_title, content)]
|
||||
|
||||
title = realm_str
|
||||
realm_stats = realm_stats_link(realm_str)
|
||||
|
||||
return render(
|
||||
request,
|
||||
"analytics/activity.html",
|
||||
context=dict(data=data, realm_stats_link=realm_stats, title=title),
|
||||
context=dict(data=data, realm_link=None, title=title),
|
||||
)
|
||||
|
||||
@@ -49,35 +49,23 @@ def is_analytics_ready(realm: Realm) -> bool:
|
||||
def render_stats(
|
||||
request: HttpRequest,
|
||||
data_url_suffix: str,
|
||||
realm: Optional[Realm],
|
||||
*,
|
||||
title: Optional[str] = None,
|
||||
target_name: str,
|
||||
for_installation: bool = False,
|
||||
remote: bool = False,
|
||||
analytics_ready: bool = True,
|
||||
) -> HttpResponse:
|
||||
assert request.user.is_authenticated
|
||||
|
||||
if realm is not None:
|
||||
# Same query to get guest user count as in get_seat_count in corporate/lib/stripe.py.
|
||||
guest_users = UserProfile.objects.filter(
|
||||
realm=realm, is_active=True, is_bot=False, role=UserProfile.ROLE_GUEST
|
||||
realm=request.user.realm, is_active=True, is_bot=False, role=UserProfile.ROLE_GUEST
|
||||
).count()
|
||||
space_used = realm.currently_used_upload_space_bytes()
|
||||
if title:
|
||||
pass
|
||||
else:
|
||||
title = realm.name or realm.string_id
|
||||
else:
|
||||
assert title
|
||||
guest_users = None
|
||||
space_used = None
|
||||
|
||||
page_params = dict(
|
||||
data_url_suffix=data_url_suffix,
|
||||
for_installation=for_installation,
|
||||
remote=remote,
|
||||
upload_space_used=space_used,
|
||||
upload_space_used=request.user.realm.currently_used_upload_space_bytes(),
|
||||
guest_users=guest_users,
|
||||
)
|
||||
|
||||
@@ -93,9 +81,7 @@ def render_stats(
|
||||
request,
|
||||
"analytics/stats.html",
|
||||
context=dict(
|
||||
target_name=title,
|
||||
page_params=page_params,
|
||||
analytics_ready=analytics_ready,
|
||||
target_name=target_name, page_params=page_params, analytics_ready=analytics_ready
|
||||
),
|
||||
)
|
||||
|
||||
@@ -108,7 +94,9 @@ def stats(request: HttpRequest) -> HttpResponse:
|
||||
# TODO: Make @zulip_login_required pass the UserProfile so we
|
||||
# can use @require_member_or_admin
|
||||
raise JsonableError(_("Not allowed for guest users"))
|
||||
return render_stats(request, "", realm, analytics_ready=is_analytics_ready(realm))
|
||||
return render_stats(
|
||||
request, "", realm.name or realm.string_id, analytics_ready=is_analytics_ready(realm)
|
||||
)
|
||||
|
||||
|
||||
@require_server_admin
|
||||
@@ -122,7 +110,7 @@ def stats_for_realm(request: HttpRequest, realm_str: str) -> HttpResponse:
|
||||
return render_stats(
|
||||
request,
|
||||
f"/realm/{realm_str}",
|
||||
realm,
|
||||
realm.name or realm.string_id,
|
||||
analytics_ready=is_analytics_ready(realm),
|
||||
)
|
||||
|
||||
@@ -137,8 +125,7 @@ def stats_for_remote_realm(
|
||||
return render_stats(
|
||||
request,
|
||||
f"/remote/{server.id}/realm/{remote_realm_id}",
|
||||
None,
|
||||
title=f"Realm {remote_realm_id} on server {server.hostname}",
|
||||
f"Realm {remote_realm_id} on server {server.hostname}",
|
||||
)
|
||||
|
||||
|
||||
@@ -179,8 +166,7 @@ def get_chart_data_for_remote_realm(
|
||||
|
||||
@require_server_admin
|
||||
def stats_for_installation(request: HttpRequest) -> HttpResponse:
|
||||
assert request.user.is_authenticated
|
||||
return render_stats(request, "/installation", None, title="installation", for_installation=True)
|
||||
return render_stats(request, "/installation", "installation", True)
|
||||
|
||||
|
||||
@require_server_admin
|
||||
@@ -190,10 +176,9 @@ def stats_for_remote_installation(request: HttpRequest, remote_server_id: int) -
|
||||
return render_stats(
|
||||
request,
|
||||
f"/remote/{server.id}/installation",
|
||||
None,
|
||||
title=f"remote installation {server.hostname}",
|
||||
for_installation=True,
|
||||
remote=True,
|
||||
f"remote installation {server.hostname}",
|
||||
True,
|
||||
True,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ module.exports = {
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
corejs: "3.27",
|
||||
corejs: "3.25",
|
||||
shippedProposals: true,
|
||||
useBuiltIns: "usage",
|
||||
},
|
||||
|
||||
@@ -29,7 +29,7 @@ from zerver.models import (
|
||||
)
|
||||
|
||||
|
||||
class ConfirmationKeyError(Exception):
|
||||
class ConfirmationKeyException(Exception):
|
||||
WRONG_LENGTH = 1
|
||||
EXPIRED = 2
|
||||
DOES_NOT_EXIST = 3
|
||||
@@ -40,11 +40,11 @@ class ConfirmationKeyError(Exception):
|
||||
|
||||
|
||||
def render_confirmation_key_error(
|
||||
request: HttpRequest, exception: ConfirmationKeyError
|
||||
request: HttpRequest, exception: ConfirmationKeyException
|
||||
) -> HttpResponse:
|
||||
if exception.error_type == ConfirmationKeyError.WRONG_LENGTH:
|
||||
if exception.error_type == ConfirmationKeyException.WRONG_LENGTH:
|
||||
return render(request, "confirmation/link_malformed.html", status=404)
|
||||
if exception.error_type == ConfirmationKeyError.EXPIRED:
|
||||
if exception.error_type == ConfirmationKeyException.EXPIRED:
|
||||
return render(request, "confirmation/link_expired.html", status=404)
|
||||
return render(request, "confirmation/link_does_not_exist.html", status=404)
|
||||
|
||||
@@ -77,16 +77,16 @@ def get_object_from_key(
|
||||
|
||||
# Confirmation keys used to be 40 characters
|
||||
if len(confirmation_key) not in (24, 40):
|
||||
raise ConfirmationKeyError(ConfirmationKeyError.WRONG_LENGTH)
|
||||
raise ConfirmationKeyException(ConfirmationKeyException.WRONG_LENGTH)
|
||||
try:
|
||||
confirmation = Confirmation.objects.get(
|
||||
confirmation_key=confirmation_key, type__in=confirmation_types
|
||||
)
|
||||
except Confirmation.DoesNotExist:
|
||||
raise ConfirmationKeyError(ConfirmationKeyError.DOES_NOT_EXIST)
|
||||
raise ConfirmationKeyException(ConfirmationKeyException.DOES_NOT_EXIST)
|
||||
|
||||
if confirmation.expiry_date is not None and timezone_now() > confirmation.expiry_date:
|
||||
raise ConfirmationKeyError(ConfirmationKeyError.EXPIRED)
|
||||
raise ConfirmationKeyException(ConfirmationKeyException.EXPIRED)
|
||||
|
||||
obj = confirmation.content_object
|
||||
assert obj is not None
|
||||
@@ -96,10 +96,10 @@ def get_object_from_key(
|
||||
if hasattr(obj, "status") and obj.status in [used_value, revoked_value]:
|
||||
# Confirmations where the object has the status attribute are one-time use
|
||||
# and are marked after being used (or revoked).
|
||||
raise ConfirmationKeyError(ConfirmationKeyError.EXPIRED)
|
||||
raise ConfirmationKeyException(ConfirmationKeyException.EXPIRED)
|
||||
|
||||
if mark_object_used:
|
||||
# MultiuseInvite objects do not use the STATUS_USED status, since they are
|
||||
# MultiuseInvite objects have no status field, since they are
|
||||
# intended to be used more than once.
|
||||
assert confirmation.type != Confirmation.MULTIUSE_INVITE
|
||||
assert hasattr(obj, "status")
|
||||
@@ -240,10 +240,10 @@ def validate_key(creation_key: Optional[str]) -> Optional["RealmCreationKey"]:
|
||||
try:
|
||||
key_record = RealmCreationKey.objects.get(creation_key=creation_key)
|
||||
except RealmCreationKey.DoesNotExist:
|
||||
raise RealmCreationKey.InvalidError()
|
||||
raise RealmCreationKey.Invalid()
|
||||
time_elapsed = timezone_now() - key_record.date_created
|
||||
if time_elapsed.total_seconds() > settings.REALM_CREATION_LINK_VALIDITY_DAYS * 24 * 3600:
|
||||
raise RealmCreationKey.InvalidError()
|
||||
raise RealmCreationKey.Invalid()
|
||||
return key_record
|
||||
|
||||
|
||||
@@ -266,5 +266,5 @@ class RealmCreationKey(models.Model):
|
||||
# is theirs, and skip sending mail to it to confirm that.
|
||||
presume_email_valid = models.BooleanField(default=False)
|
||||
|
||||
class InvalidError(Exception):
|
||||
class Invalid(Exception):
|
||||
pass
|
||||
|
||||
@@ -248,13 +248,13 @@ class UpgradeWithExistingPlanError(BillingError):
|
||||
)
|
||||
|
||||
|
||||
class InvalidBillingScheduleError(Exception):
|
||||
class InvalidBillingSchedule(Exception):
|
||||
def __init__(self, billing_schedule: int) -> None:
|
||||
self.message = f"Unknown billing_schedule: {billing_schedule}"
|
||||
super().__init__(self.message)
|
||||
|
||||
|
||||
class InvalidTierError(Exception):
|
||||
class InvalidTier(Exception):
|
||||
def __init__(self, tier: int) -> None:
|
||||
self.message = f"Unknown tier: {tier}"
|
||||
super().__init__(self.message)
|
||||
@@ -570,16 +570,16 @@ def get_price_per_license(
|
||||
elif billing_schedule == CustomerPlan.MONTHLY:
|
||||
price_per_license = 800
|
||||
else: # nocoverage
|
||||
raise InvalidBillingScheduleError(billing_schedule)
|
||||
raise InvalidBillingSchedule(billing_schedule)
|
||||
elif tier == CustomerPlan.PLUS:
|
||||
if billing_schedule == CustomerPlan.ANNUAL:
|
||||
price_per_license = 16000
|
||||
elif billing_schedule == CustomerPlan.MONTHLY:
|
||||
price_per_license = 1600
|
||||
else: # nocoverage
|
||||
raise InvalidBillingScheduleError(billing_schedule)
|
||||
raise InvalidBillingSchedule(billing_schedule)
|
||||
else:
|
||||
raise InvalidTierError(tier)
|
||||
raise InvalidTier(tier)
|
||||
|
||||
if discount is not None:
|
||||
price_per_license = calculate_discounted_price_per_license(price_per_license, discount)
|
||||
@@ -602,7 +602,7 @@ def compute_plan_parameters(
|
||||
elif billing_schedule == CustomerPlan.MONTHLY:
|
||||
period_end = add_months(billing_cycle_anchor, 1)
|
||||
else: # nocoverage
|
||||
raise InvalidBillingScheduleError(billing_schedule)
|
||||
raise InvalidBillingSchedule(billing_schedule)
|
||||
|
||||
price_per_license = get_price_per_license(tier, billing_schedule, discount)
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user