diff --git a/api_docs/changelog.md b/api_docs/changelog.md index 5885c24161..35135474df 100644 --- a/api_docs/changelog.md +++ b/api_docs/changelog.md @@ -386,9 +386,9 @@ No changes; feature level used for Zulip 8.0 release. to an organization. Previously, only admin users could create these links. -* `POST /invites/multiuse`: Non-admin users can now use this endpoint - to create reusable invitation links. Previously, this endpoint was - restricted to admin users only. +* [`POST /invites/multiuse`](/api/create-invite-link): Non-admin users can + now use this endpoint to create reusable invitation links. Previously, + this endpoint was restricted to admin users only. * [`GET /invites`](/api/get-invites): Endpoint response for non-admin users now includes both email invitations and reusable invitation links that they have @@ -1120,7 +1120,8 @@ user's profile. **Feature level 126** -* [`POST /invites`](/api/send-invites), `POST /invites/multiuse`: Replaced +* [`POST /invites`](/api/send-invites), + [`POST /invites/multiuse`](/api/create-invite-link): Replaced `invite_expires_in_days` parameter with `invite_expires_in_minutes`. **Feature level 125** @@ -1180,9 +1181,10 @@ No changes; feature level used for Zulip 5.0 release. **Feature level 117** -* [`POST /invites`](/api/send-invites), `POST /invites/multiuse`: Added - support for passing `null` as the `invite_expires_in_days` parameter - to request an invitation that never expires. +* [`POST /invites`](/api/send-invites), + [`POST /invites/multiuse`](/api/create-invite-link): Added support + for passing `null` as the `invite_expires_in_days` parameter to + request an invitation that never expires. **Feature level 116** @@ -1340,7 +1342,8 @@ No changes; feature level used for Zulip 5.0 release. * [`PATCH /realm/user_settings_defaults`](/api/update-realm-user-settings-defaults): Added new endpoint to update default values of user settings in a realm. -* [`POST /invites`](/api/send-invites), `POST /invites/multiuse`: Added +* [`POST /invites`](/api/send-invites), + [`POST /invites/multiuse`](/api/create-invite-link): Added `invite_expires_in_days` parameter encoding the number days before the invitation should expire. @@ -1601,8 +1604,9 @@ No changes; feature level used for Zulip 4.0 release. **Feature level 61** -* [`POST /invites`](/api/send-invites), `POST /invites/multiuse`: Added - support for inviting users as moderators. +* [`POST /invites`](/api/send-invites), + [`POST /invites/multiuse`](/api/create-invite-link): Added support + for inviting users as moderators. **Feature level 60** diff --git a/api_docs/include/rest-endpoints.md b/api_docs/include/rest-endpoints.md index 5d1b3a0ce1..6dfd3bd2f4 100644 --- a/api_docs/include/rest-endpoints.md +++ b/api_docs/include/rest-endpoints.md @@ -92,6 +92,7 @@ * [Get all invitations](/api/get-invites) * [Send invitations](/api/send-invites) +* [Create reusable invitation link](/api/create-invite-link) #### Server & organizations diff --git a/zerver/openapi/python_examples.py b/zerver/openapi/python_examples.py index 1ca2093367..29d6b721bc 100644 --- a/zerver/openapi/python_examples.py +++ b/zerver/openapi/python_examples.py @@ -329,6 +329,21 @@ def send_invitations(client: Client) -> None: validate_against_openapi_schema(result, "/invites", "post", "200") +@openapi_test_function("/invites/multiuse:post") +def create_reusable_invitation_link(client: Client) -> None: + # {code_example|start} + # Create reusable invitation link + request = { + "invite_expires_in_minutes": 60 * 24 * 10, # 10 days + "invite_as": 400, + "stream_ids": [1, 8, 9], + } + result = client.call_endpoint(url="/invites/multiuse", method="POST", request=request) + # {code_example|end} + + validate_against_openapi_schema(result, "/invites/multiuse", "post", "200") + + @openapi_test_function("/users/{user_id}:get") def get_single_user(client: Client) -> None: ensure_users([8], ["cordelia"]) @@ -1686,6 +1701,7 @@ def test_errors(client: Client) -> None: def test_invitations(client: Client) -> None: send_invitations(client) + create_reusable_invitation_link(client) get_invitations(client) diff --git a/zerver/openapi/zulip.yaml b/zerver/openapi/zulip.yaml index a221afe11e..abe256194d 100644 --- a/zerver/openapi/zulip.yaml +++ b/zerver/openapi/zulip.yaml @@ -11857,7 +11857,7 @@ paths: invited_as: 400, invited_by_user_id: 9, is_multiuse: true, - link_url: "http://localhost:9991/join/6i4324pzbtyvmwv5nwyghoof/", + link_url: "https://example.zulipchat.com/join/yddhtzk4jgl7rsmazc5fyyyy/", }, ], } @@ -11891,46 +11891,9 @@ paths: type: string example: example@zulip.com, logan@zulip.com invite_expires_in_minutes: - description: | - The number of minutes before the invitation will expire. If `null`, the - invitation will never expire. If unspecified, the server will use a default - value (based on the `INVITATION_LINK_VALIDITY_MINUTES` server setting, which - defaults to 10) for when the invitation will expire. - - **Changes**: New in Zulip 6.0 (feature level 126). Previously, there was an - `invite_expires_in_days` parameter, which specified the duration in days instead - of minutes. - type: integer - nullable: true - example: 14400 + $ref: "#/components/schemas/InviteExpirationParameter" invite_as: - description: | - The [organization-level role](/api/roles-and-permissions) of the user that is - created when the invitation is accepted. - Possible values are: - - - 100 = Organization owner - - 200 = Organization administrator - - 300 = Organization moderator - - 400 = Member - - 600 = Guest - - Users can only send invitations for - [roles with equal or stricter restrictions](/api/roles-and-permissions#permission-levels) - as their own. For example, a moderator cannot invite someone to be an owner - or administrator, but they can invite them to be a moderator or member. - - **Changes**: In Zulip 4.0 (feature level 61), added support for inviting - users as moderators. - type: integer - enum: - - 100 - - 200 - - 300 - - 400 - - 600 - default: 400 - example: 600 + $ref: "#/components/schemas/InviteRoleParameter" stream_ids: description: | A list containing the [IDs of the streams](/api/get-stream-id) that the @@ -12038,6 +12001,119 @@ paths: description: | An example JSON error response for when the user doesn't have permission to subscribe other users to streams and `stream_ids` is not empty. + /invites/multiuse: + post: + operationId: create-invite-link + summary: Create reusable invitation link + tags: ["invites"] + description: | + Create a [reusable invitation link](/help/invite-new-users#create-a-reusable-invitation-link) + which can be used to invite new users to the organization. + + **Changes**: In Zulip 8.0 (feature level 209), added support for non-admin + users [with permission](/help/restrict-account-creation#change-who-can-send-invitations) + to use this endpoint. Previously, it was restricted to administrators only. + + In Zulip 6.0 (feature level 126), the `invite_expires_in_days` + parameter was removed and replaced by `invite_expires_in_minutes`. + + In Zulip 5.0 (feature level 117), added support for passing `null` as + the `invite_expires_in_days` parameter to request an invitation that never + expires. + + In Zulip 5.0 (feature level 96), the `invite_expires_in_days` parameter was + added which specified the number of days before the invitation would expire. + requestBody: + required: false + content: + application/x-www-form-urlencoded: + schema: + type: object + properties: + invite_expires_in_minutes: + $ref: "#/components/schemas/InviteExpirationParameter" + invite_as: + $ref: "#/components/schemas/InviteRoleParameter" + stream_ids: + description: | + A list containing the [IDs of the streams](/api/get-stream-id) that the + newly created user will be automatically subscribed to if the invitation + is accepted. If unspecified, it will be set to empty list. If the list is + empty, then the new user will not be subscribed to any streams. + type: array + items: + type: integer + default: [] + example: [1, 2] + encoding: + invite_expires_in_minutes: + contentType: application/json + stream_ids: + contentType: application/json + responses: + "200": + description: Success. + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/JsonSuccessBase" + - additionalProperties: false + properties: + result: {} + msg: {} + ignored_parameters_unsupported: {} + invite_link: + type: string + description: | + The URL of the [reusable invitation link](/help/invite-new-users#create-a-reusable-invitation-link) + that was created by this request. + example: + { + "result": "success", + "msg": "", + "invite_link": "https://example.zulipchat.com/join/yddhtzk4jgl7rsmazc5fyyyy/", + } + "400": + description: Bad request. + content: + application/json: + schema: + oneOf: + - allOf: + - $ref: "#/components/schemas/CodedError" + - example: + { + "code": "BAD_REQUEST", + "msg": "Insufficient permission", + "result": "error", + } + description: | + An example JSON error response for when the user doesn't have permission + to send invitations. + - allOf: + - $ref: "#/components/schemas/CodedError" + - example: + { + "code": "BAD_REQUEST", + "msg": "Invalid stream ID 11. No invites were sent.", + "result": "error", + } + description: | + An example JSON error response for when any of the specified streams + does not exist or the user does not have permission to access one of + the targeted streams. + - allOf: + - $ref: "#/components/schemas/CodedError" + - example: + { + "code": "BAD_REQUEST", + "msg": "You do not have permission to subscribe other users to streams.", + "result": "error", + } + description: | + An example JSON error response for when the user doesn't have permission + to subscribe other users to streams and `stream_ids` is not empty. /register: post: operationId: register-queue @@ -19618,6 +19694,13 @@ components: description: | The [organization-level role](/api/roles-and-permissions) of the user that is created when the invitation is accepted. + Possible values are: + + - 100 = Organization owner + - 200 = Organization administrator + - 300 = Organization moderator + - 400 = Member + - 600 = Guest email: type: string description: | @@ -19633,6 +19716,47 @@ components: description: | A boolean specifying whether the [invitation](/help/invite-new-users) is a reusable invitation link or an email invitation. + InviteExpirationParameter: + description: | + The number of minutes before the invitation will expire. If `null`, the + invitation will never expire. If unspecified, the server will use a default + value (based on the `INVITATION_LINK_VALIDITY_MINUTES` server setting, which + defaults to 14400, i.e. 10 days) for when the invitation will expire. + + **Changes**: New in Zulip 6.0 (feature level 126). Previously, there was an + `invite_expires_in_days` parameter, which specified the duration in days instead + of minutes. + type: integer + nullable: true + example: 14400 + InviteRoleParameter: + description: | + The [organization-level role](/api/roles-and-permissions) of the user that is + created when the invitation is accepted. + Possible values are: + + - 100 = Organization owner + - 200 = Organization administrator + - 300 = Organization moderator + - 400 = Member + - 600 = Guest + + Users can only create invitation links for + [roles with equal or stricter restrictions](/api/roles-and-permissions#permission-levels) + as their own. For example, a moderator cannot invite someone to be an owner + or administrator, but they can invite them to be a moderator or member. + + **Changes**: In Zulip 4.0 (feature level 61), added support for inviting + users as moderators. + type: integer + enum: + - 100 + - 200 + - 300 + - 400 + - 600 + default: 400 + example: 600 Subscriptions: type: object additionalProperties: false diff --git a/zerver/tests/test_openapi.py b/zerver/tests/test_openapi.py index 233b2f84df..b0e72d547a 100644 --- a/zerver/tests/test_openapi.py +++ b/zerver/tests/test_openapi.py @@ -239,7 +239,6 @@ class OpenAPIArgumentsTest(ZulipTestCase): "/default_stream_groups/{group_id}", "/default_stream_groups/{group_id}/streams", # Administer invitations - "/invites/multiuse", "/invites/{prereg_id}", "/invites/{prereg_id}/resend", "/invites/multiuse/{invite_id}",