Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Include teams info in users API #3817

Merged
merged 2 commits into from
Feb 1, 2024
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Enable Grafana Alerting V2 feature flag by default
- Allow configuration of outgoing webhook timeout via `OUTGOING_WEBHOOK_TIMEOUT` environment variable @kevindw-fluxys ([#3801](https://github.com/grafana/oncall/pull/3801))
- Include teams info in users API ([#3817](https://github.com/grafana/oncall/pull/3817))

### Fixed

Expand Down
7 changes: 5 additions & 2 deletions docs/sources/oncall-api-reference/users.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ The above command returns JSON structured in the following way:
],
"username": "alex",
"role": "admin",
"timezone": "UTC"
"timezone": "UTC",
"teams": []
}
```

Expand All @@ -47,6 +48,7 @@ Use `{{API_URL}}/api/v1/users/current` to retrieve the current user.
| `username` | Yes/org | User username |
| `role` | No | One of: `user`, `observer`, `admin`. |
| `timezone` | No | timezone of the user one of [time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). |
| `teams` | No | List of team IDs the user belongs to |

# List Users

Expand Down Expand Up @@ -76,7 +78,8 @@ The above command returns JSON structured in the following way:
],
"username": "alex",
"role": "admin",
"timezone": "UTC"
"timezone": "UTC",
"teams": ["TAAM1K1NNEHAG"]
}
],
"current_page_number": 1,
Expand Down
34 changes: 18 additions & 16 deletions engine/apps/public_api/serializers/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@


class SlackUserIdentitySerializer(serializers.ModelSerializer):
user_id = serializers.CharField(source="slack_id")
team_id = serializers.CharField(source="slack_team_identity.slack_id")
user_id: str = serializers.CharField(source="slack_id")
team_id: str = serializers.CharField(source="slack_team_identity.slack_id")

class Meta:
model = SlackUserIdentity
Expand All @@ -19,49 +19,51 @@ class Meta:


class FastUserSerializer(serializers.ModelSerializer):
id = serializers.ReadOnlyField(read_only=True, source="public_primary_key")
email = serializers.EmailField(read_only=True)
role = serializers.SerializerMethodField() # LEGACY, should be removed eventually
is_phone_number_verified = serializers.SerializerMethodField()
id: str = serializers.ReadOnlyField(read_only=True, source="public_primary_key")
email: str = serializers.EmailField(read_only=True)
role: str = serializers.SerializerMethodField() # LEGACY, should be removed eventually
is_phone_number_verified: bool = serializers.SerializerMethodField()

class Meta:
model = User
fields = ["id", "email", "username", "role", "is_phone_number_verified"]

@staticmethod
def get_role(obj):
def get_role(obj: User) -> str:
"""
LEGACY, should be removed eventually
"""
return LegacyAccessControlRole(obj.role).name.lower()

def get_is_phone_number_verified(self, obj):
def get_is_phone_number_verified(self, obj: User) -> bool:
return obj.verified_phone_number is not None


class UserSerializer(serializers.ModelSerializer, EagerLoadingMixin):
id = serializers.ReadOnlyField(read_only=True, source="public_primary_key")
email = serializers.EmailField(read_only=True)
slack = SlackUserIdentitySerializer(read_only=True, source="slack_user_identity")
role = serializers.SerializerMethodField() # LEGACY, should be removed eventually
is_phone_number_verified = serializers.SerializerMethodField()
id: str = serializers.ReadOnlyField(read_only=True, source="public_primary_key")
email: str = serializers.EmailField(read_only=True)
slack: SlackUserIdentity = SlackUserIdentitySerializer(read_only=True, source="slack_user_identity")
role: str = serializers.SerializerMethodField() # LEGACY, should be removed eventually
is_phone_number_verified: bool = serializers.SerializerMethodField()
teams: list[str] = serializers.SlugRelatedField(read_only=True, many=True, slug_field="public_primary_key")

SELECT_RELATED = [
"slack_user_identity",
"slack_user_identity__slack_team_identity",
]
PREFETCH_RELATED = ["teams"]

class Meta:
model = User
fields = ["id", "email", "slack", "username", "role", "is_phone_number_verified", "timezone"]
fields = ["id", "email", "slack", "username", "role", "is_phone_number_verified", "timezone", "teams"]
read_only_fields = ["timezone"]

@staticmethod
def get_role(obj):
def get_role(obj: User) -> str:
"""
LEGACY, should be removed eventually
"""
return LegacyAccessControlRole(obj.role).name.lower()

def get_is_phone_number_verified(self, obj):
def get_is_phone_number_verified(self, obj: User) -> bool:
return obj.verified_phone_number is not None
6 changes: 6 additions & 0 deletions engine/apps/public_api/tests/test_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def test_get_user(
"role": "admin",
"is_phone_number_verified": False,
"timezone": user.timezone,
"teams": [],
}

assert response.status_code == status.HTTP_200_OK
Expand All @@ -51,10 +52,13 @@ def test_get_user(
@pytest.mark.django_db
def test_get_users_list(
user_public_api_setup,
make_team,
make_user_for_organization,
):
organization, user_1, token, slack_team_identity, slack_user_identity = user_public_api_setup
team = make_team(organization)
user_2 = make_user_for_organization(organization)
user_2.teams.add(team)

client = APIClient()

Expand All @@ -74,6 +78,7 @@ def test_get_users_list(
"role": "admin",
"is_phone_number_verified": False,
"timezone": user_1.timezone,
"teams": [],
},
{
"id": user_2.public_primary_key,
Expand All @@ -83,6 +88,7 @@ def test_get_users_list(
"role": "admin",
"is_phone_number_verified": False,
"timezone": user_2.timezone,
"teams": [team.public_primary_key],
},
],
"current_page_number": 1,
Expand Down
Loading