-
Notifications
You must be signed in to change notification settings - Fork 298
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Mattermost install flow remove utils Fix jwt error Add install flow details Fix formatting Fix auth token
- Loading branch information
1 parent
d8e1a1d
commit d58d17d
Showing
13 changed files
with
211 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
from typing import Tuple | ||
|
||
from rest_framework import exceptions | ||
from rest_framework.authentication import BaseAuthentication | ||
|
||
from apps.auth_token.exceptions import InvalidToken | ||
from apps.user_management.models import Organization | ||
|
||
from .models import MattermostAuthToken | ||
|
||
|
||
class MattermostAuthTokenAuthentication(BaseAuthentication): | ||
model = MattermostAuthToken | ||
|
||
def extract_auth_token(self, request) -> str: | ||
return request.query_params.get("auth_token") | ||
|
||
def authenticate(self, request) -> Tuple[Organization, MattermostAuthToken]: | ||
auth = self.extract_auth_token(request=request) | ||
organization, auth_token = self.authenticate_credentials(auth) | ||
return organization, auth_token | ||
|
||
def authenticate_credentials(self, token_string: str) -> Tuple[Organization, MattermostAuthToken]: | ||
try: | ||
auth_token = self.model.validate_token_string(token_string) | ||
except InvalidToken: | ||
raise exceptions.AuthenticationFailed("Invalid auth token") | ||
|
||
return auth_token.organization, auth_token | ||
|
||
|
||
class MattermostWebhookAuthTokenAuthentication(MattermostAuthTokenAuthentication): | ||
def extract_auth_token(self, request) -> str: | ||
return request.data.get("state", {}).get("auth_token", "") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# Generated by Django 4.2.11 on 2024-06-13 04:24 | ||
|
||
from django.db import migrations, models | ||
import django.db.models.deletion | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
initial = True | ||
|
||
dependencies = [ | ||
('user_management', '0022_alter_team_unique_together'), | ||
] | ||
|
||
operations = [ | ||
migrations.CreateModel( | ||
name='MattermostAuthToken', | ||
fields=[ | ||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||
('token_key', models.CharField(db_index=True, max_length=8)), | ||
('digest', models.CharField(max_length=128)), | ||
('created_at', models.DateTimeField(auto_now_add=True)), | ||
('revoked_at', models.DateTimeField(null=True)), | ||
('organization', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='mattermost_auth_token', to='user_management.organization')), | ||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='mattermost_auth_token_set', to='user_management.user')), | ||
], | ||
options={ | ||
'abstract': False, | ||
}, | ||
), | ||
] |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from .mattermost_auth_token import MattermostAuthToken # noqa: F401 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
from typing import Tuple | ||
|
||
from django.db import models | ||
|
||
from apps.auth_token import constants, crypto | ||
from apps.auth_token.models import BaseAuthToken | ||
from apps.user_management.models import Organization, User | ||
|
||
|
||
class MattermostAuthToken(BaseAuthToken): | ||
objects: models.Manager["MattermostAuthToken"] | ||
|
||
user = models.ForeignKey( | ||
"user_management.User", | ||
related_name="mattermost_auth_token_set", | ||
on_delete=models.CASCADE, | ||
) | ||
|
||
organization = models.OneToOneField( | ||
"user_management.Organization", on_delete=models.CASCADE, related_name="mattermost_auth_token" | ||
) | ||
|
||
@classmethod | ||
def create_auth_token(cls, user: User, organization: Organization) -> Tuple["MattermostAuthToken", str]: | ||
token_string = crypto.generate_token_string() | ||
digest = crypto.hash_token_string(token_string) | ||
|
||
instance = cls.objects.create( | ||
token_key=token_string[: constants.TOKEN_KEY_LENGTH], | ||
digest=digest, | ||
user=user, | ||
organization=organization, | ||
) | ||
return instance, token_string |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
from django.urls import path | ||
|
||
from .views import GetMattermostManifest, MattermostBindings, MattermostInstall | ||
|
||
urlpatterns = [ | ||
path("manifest", GetMattermostManifest.as_view()), | ||
path("install", MattermostInstall.as_view()), | ||
path("bindings", MattermostBindings.as_view()), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
from rest_framework import status | ||
from rest_framework.response import Response | ||
from rest_framework.views import APIView | ||
|
||
from apps.mattermost.auth import MattermostAuthTokenAuthentication, MattermostWebhookAuthTokenAuthentication | ||
|
||
MATTERMOST_CONNECTED_TEXT = ( | ||
"Done! <b>{app_id}</b> Successfully Installed and Linked with organization <b>{organization_title} 🎉</b>" | ||
) | ||
|
||
|
||
class GetMattermostManifest(APIView): | ||
authentication_classes = (MattermostAuthTokenAuthentication,) | ||
|
||
def get(self, request): | ||
auth_token = request.query_params.get("auth_token") | ||
manifest = self._build_manifest(auth_token) | ||
return Response(manifest, status=status.HTTP_200_OK) | ||
|
||
def _build_on_install_callback(self, auth_token: str) -> dict: | ||
return { | ||
"path": "/mattermost/install", | ||
"expand": {"app": "summary", "acting_user": "summary"}, | ||
"state": {"auth_token": auth_token}, | ||
} | ||
|
||
def _build_bindings_callback(self, auth_token: str) -> dict: | ||
return {"path": "/mattermost/bindings", "state": {"auth_token": auth_token}} | ||
|
||
def _build_manifest(self, auth_token: str) -> dict: | ||
return { | ||
"app_id": "Grafana-Oncall", | ||
"version": "1.0.0", | ||
"display_name": "Grafana Oncall", | ||
"description": "Grafana Oncall app for sending and receiving events from mattermost", | ||
"homepage_url": "https://grafana.com/docs/oncall/latest/", | ||
"requested_permissions": ["act_as_bot"], | ||
"requested_locations": ["/in_post", "/post_menu", "/command"], | ||
"on_install": self._build_on_install_callback(auth_token=auth_token), | ||
"bindings": self._build_bindings_callback(auth_token=auth_token), | ||
"http": {"root_url": "http://host.docker.internal:8080"}, | ||
} | ||
|
||
|
||
class MattermostInstall(APIView): | ||
authentication_classes = (MattermostWebhookAuthTokenAuthentication,) | ||
|
||
def post(self, request): | ||
app_id = request.data.get("context").get("app").get("app_id") | ||
view_text = MATTERMOST_CONNECTED_TEXT.format( | ||
app_id=app_id, organization_title=request.auth.organization.org_title | ||
) | ||
# TODO: Create and save bot user and access token and also link org and user with mattermost | ||
response = {"type": "ok", "text": view_text} | ||
return Response(response, status=status.HTTP_200_OK) | ||
|
||
|
||
class MattermostBindings(APIView): | ||
authentication_classes = (MattermostWebhookAuthTokenAuthentication,) | ||
|
||
def post(self, request): | ||
# TODO: Implement bindings or slash commands | ||
response = {"type": "ok"} | ||
return Response(response, status=status.HTTP_200_OK) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters