Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 41 additions & 1 deletion docs/source/Resources/Run/Run_Types.rst
Original file line number Diff line number Diff line change
Expand Up @@ -261,13 +261,52 @@ UserCreateInfo

| **name**: str
| **email**: str
| **password****: str
| **password**: NotRequired[str]
| Omit when ``generate_password`` is True.
| **timezone**: str
| **company**: Optional[str]
| **phone**: Optional[str]
| **language**: Optional[str]
| **tags**: Optional[list[:ref:`TagsObj`]]
| **active**: Optional[bool]
| **generate_password**: NotRequired[bool]
| Server generates the password and turns on ``force_password_change``. Rejected if ``password`` is also sent.
| **send_email**: NotRequired[Union[bool, str]]
| True sends the ``welcome`` email; a string picks an ``email_templates`` key. Unknown keys fall back to ``welcome``, then to a built-in default.

.. _UserEditInfo:

UserEditInfo
------------

All attributes are optional.

**Attributes:**

| **name**: str
| **password**: str
| **timezone**: str
| **company**: Optional[str]
| **phone**: Optional[str]
| **language**: str
| **newsletter**: Optional[bool]
| **active**: bool
| **options**: Optional[dict]
| **tags**: list[:ref:`TagsObj`]
| **custom_preferences**: Optional[dict]
| **force_password_change**: bool
| **logout_sessions**: bool
| Deletes the user's active sessions.

.. _UserInviteInfo:

UserInviteInfo
--------------

**Attributes:**

| **invite_template**: NotRequired[str]
| An ``email_templates`` key to send instead of ``welcome``.

.. _UserInfo:

Expand All @@ -293,6 +332,7 @@ UserInfo
| **updated_at**: datetime
| **options**: object
| **tags**: list[:ref:`TagsObj`]
| **force_password_change**: bool

.. _LoginResponseRunUser:

Expand Down
54 changes: 53 additions & 1 deletion docs/source/Resources/Run/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ userCreate

Creates a new user in the Run environment.

Set ``generate_password`` to True to let the server generate the password (omit ``password``) and require a new one at first sign-in.
Set ``send_email`` to True to send the Run's ``welcome`` email, or to an ``email_templates`` key to pick another template.
With ``generate_password`` or ``send_email`` and no ``active``, the user is created active; ``active: False`` together with ``send_email`` is rejected.

See: `TagoRun <https://help.tago.io/portal/en/kb/articles/191-tagorun>`_

**Parameters:**
Expand All @@ -152,21 +156,32 @@ See: `TagoRun <https://help.tago.io/portal/en/kb/articles/191-tagorun>`_
})
print(result) # {'user': 'user-id-123'}

# Let the server generate the password and email a set-password link
result = resources.run.userCreate({
"name": "John Doe",
"email": "john@example.com",
"timezone": "America/New_York",
"generate_password": True,
"send_email": True
})


========
userEdit
========

Updates information for an existing Run user.

Set ``force_password_change`` to True to require a new password at the next sign-in, and ``logout_sessions`` to True to end the user's active sessions.

See: `TagoRun <https://help.tago.io/portal/en/kb/articles/191-tagorun>`_

**Parameters:**

| **userID**: :ref:`GenericID`
| User identification

| **data**: dict
| **data**: :ref:`UserEditInfo`
| User data to update

**Returns:**
Expand All @@ -182,6 +197,43 @@ See: `TagoRun <https://help.tago.io/portal/en/kb/articles/191-tagorun>`_
result = resources.run.userEdit("user-id-123", {"name": "Updated Name"})
print(result) # TagoIO Run User Successfully Updated

# Require a new password on next sign-in and end the user's current sessions
result = resources.run.userEdit("user-id-123", {"force_password_change": True, "logout_sessions": True})


================
userResendInvite
================

Resends the set-password link to a Run user whose invite is still pending.
The invite is pending while the user has never signed in and ``force_password_change`` is True.
Can be sent at most once per hour per user. Rejected for an inactive user.

See: `TagoRun <https://help.tago.io/portal/en/kb/articles/191-tagorun>`_

**Parameters:**

| **userID**: :ref:`GenericID`
| User identification

| *Optional* **data**: :ref:`UserInviteInfo`
| Invite options (e.g., invite_template)

**Returns:**

| str

.. code-block:: python

# If receive an error "Authorization Denied", check policy **Run User** / **Edit** in Access Management.
from tagoio_sdk import Resources

resources = Resources()
result = resources.run.userResendInvite("user-id-123")
print(result) # Invite sent

result = resources.run.userResendInvite("user-id-123", {"invite_template": "custom_invite"})


==========
userDelete
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "hatchling.build"

[project]
name = "tagoio-sdk"
version = "5.1.6"
version = "5.1.7"
description = "Official Python SDK for TagoIO"
authors = [{name = "TagoIO Inc.", email = "contact@tago.io"}]
license = {text = "Apache-2.0"}
Expand Down
52 changes: 51 additions & 1 deletion src/tagoio_sdk/modules/Resources/Run.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from typing import Dict
from typing import Optional
from typing import Union

from tagoio_sdk.common.Common_Type import GenericID
from tagoio_sdk.common.Common_Type import Query
Expand All @@ -16,7 +17,9 @@
from tagoio_sdk.modules.Resources.Run_Type import RunSAMLEditInfo
from tagoio_sdk.modules.Resources.Run_Type import RunSAMLInfo
from tagoio_sdk.modules.Resources.Run_Type import UserCreateInfo
from tagoio_sdk.modules.Resources.Run_Type import UserEditInfo
from tagoio_sdk.modules.Resources.Run_Type import UserInfo
from tagoio_sdk.modules.Resources.Run_Type import UserInviteInfo
from tagoio_sdk.modules.Utils.dateParser import dateParser
from tagoio_sdk.modules.Utils.dateParser import dateParserList

Expand Down Expand Up @@ -152,6 +155,8 @@ def userCreate(self, data: UserCreateInfo) -> Dict[str, str]:
"""
@description:
Creates a new user in the Run environment.
With `generate_password` or `send_email` and no `active`, the user is created active;
`active: False` together with `send_email` is rejected.

@see:
https://help.tago.io/portal/en/kb/articles/191-tagorun TagoRun
Expand All @@ -167,6 +172,15 @@ def userCreate(self, data: UserCreateInfo) -> Dict[str, str]:
"timezone": "America/New_York"
})
print(result) # {'user': 'user-id-123'}

# Let the server generate the password (omit "password") and email a set-password link
result = resources.run.userCreate({
"name": "John Doe",
"email": "john@example.com",
"timezone": "America/New_York",
"generate_password": True,
"send_email": True
})
```
"""
result = self.doRequest(
Expand All @@ -179,7 +193,7 @@ def userCreate(self, data: UserCreateInfo) -> Dict[str, str]:

return result

def userEdit(self, userID: GenericID, data: Dict) -> str:
def userEdit(self, userID: GenericID, data: Union[UserEditInfo, Dict]) -> str:
"""
@description:
Updates information for an existing Run user.
Expand All @@ -193,6 +207,9 @@ def userEdit(self, userID: GenericID, data: Dict) -> str:
resources = Resources()
result = resources.run.userEdit("user-id-123", {"name": "Updated Name"})
print(result) # TagoIO Run User Successfully Updated

# Require a new password on next sign-in and end the user's current sessions
result = resources.run.userEdit("user-id-123", {"force_password_change": True, "logout_sessions": True})
```
"""
result = self.doRequest(
Expand All @@ -205,6 +222,39 @@ def userEdit(self, userID: GenericID, data: Dict) -> str:

return result

def userResendInvite(
self, userID: GenericID, data: Optional[UserInviteInfo] = None
) -> str:
"""
@description:
Resends the set-password link to a Run user whose invite is still pending.
The invite is pending while the user has never signed in and `force_password_change` is True.
Can be sent at most once per hour per user. Rejected for an inactive user.
Pass `{"invite_template": "template-key"}` to pick an `email_templates` key instead of `welcome`.

@see:
https://help.tago.io/portal/en/kb/articles/191-tagorun TagoRun

@example:
If receive an error "Authorization Denied", check policy **Run User** / **Edit** in Access Management.
```python
resources = Resources()
result = resources.run.userResendInvite("user-id-123")
print(result) # Invite sent

result = resources.run.userResendInvite("user-id-123", {"invite_template": "custom_invite"})
```
"""
result = self.doRequest(
{
"path": f"/run/users/{userID}/invite",
"method": "POST",
"body": data or {},
}
)

return result

def userDelete(self, userID: GenericID) -> str:
"""
@description:
Expand Down
44 changes: 43 additions & 1 deletion src/tagoio_sdk/modules/Resources/Run_Type.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from datetime import datetime
from typing import Dict
from typing import Literal
from typing import NotRequired
from typing import Optional
from typing import TypedDict
from typing import Union
Expand Down Expand Up @@ -209,13 +210,46 @@ class RunInfo(TypedDict):
class UserCreateInfo(TypedDict):
name: str
email: str
password: str
password: NotRequired[str]
"""
Omit when `generate_password` is True.
"""
timezone: str
company: Optional[str]
phone: Optional[str]
language: Optional[str]
tags: Optional[list[TagsObj]]
active: Optional[bool]
generate_password: NotRequired[bool]
"""
Server generates the password and turns on `force_password_change`. Rejected if `password` is also sent.
"""
send_email: NotRequired[Union[bool, str]]
"""
True sends the welcome email using the Run's `welcome` template.
A string picks an `email_templates` key; unknown keys fall back to `welcome`, then to a built-in default.
With `generate_password` or `send_email` and no `active`, the user is created active.
`active: False` together with `send_email` is rejected.
"""


class UserEditInfo(TypedDict, total=False):
name: str
password: str
timezone: str
company: Optional[str]
phone: Optional[str]
language: str
newsletter: Optional[bool]
active: bool
options: Optional[Dict]
tags: list[TagsObj]
custom_preferences: Optional[Dict]
force_password_change: bool
logout_sessions: bool
"""
Deletes the user's active sessions.
"""


class UserInfo(TypedDict):
Expand All @@ -236,6 +270,14 @@ class UserInfo(TypedDict):
updated_at: datetime
options: object
tags: list[TagsObj]
force_password_change: bool


class UserInviteInfo(TypedDict):
invite_template: NotRequired[str]
"""
An `email_templates` key to send instead of `welcome`.
"""


class LoginResponse(TypedDict):
Expand Down
Loading
Loading