Skip to content

Commit 7920f39

Browse files
committed
Update the Django example for token rotation
1 parent cf322cf commit 7920f39

File tree

6 files changed

+102
-13
lines changed

6 files changed

+102
-13
lines changed

examples/django/myslackapp/urls.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from django.contrib import admin
1717
from django.urls import path
1818

19+
# Set this flag to False if you want to enable oauth_app instead
1920
is_simple_app = True
2021

2122
if is_simple_app:
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Generated by Django 3.2.3 on 2021-07-15 23:44
2+
3+
from django.db import migrations
4+
from django.db import models
5+
6+
7+
class Migration(migrations.Migration):
8+
9+
dependencies = [
10+
("oauth_app", "0001_initial"),
11+
]
12+
13+
operations = [
14+
migrations.AddField(
15+
"SlackBot", "bot_refresh_token", models.TextField(null=True)
16+
),
17+
migrations.AddField(
18+
"SlackBot", "bot_token_expires_at", models.DateTimeField(null=True)
19+
),
20+
migrations.AddField(
21+
"SlackInstallation", "bot_refresh_token", models.TextField(null=True)
22+
),
23+
migrations.AddField(
24+
"SlackInstallation", "bot_token_expires_at", models.DateTimeField(null=True)
25+
),
26+
migrations.AddField(
27+
"SlackInstallation", "user_refresh_token", models.TextField(null=True)
28+
),
29+
migrations.AddField(
30+
"SlackInstallation",
31+
"user_token_expires_at",
32+
models.DateTimeField(null=True),
33+
),
34+
]

examples/django/oauth_app/models.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ class SlackBot(models.Model):
1313
team_id = models.CharField(null=True, max_length=32)
1414
team_name = models.TextField(null=True)
1515
bot_token = models.TextField(null=True)
16+
bot_refresh_token = models.TextField(null=True)
17+
bot_token_expires_at = models.DateTimeField(null=True)
1618
bot_id = models.CharField(null=True, max_length=32)
1719
bot_user_id = models.CharField(null=True, max_length=32)
1820
bot_scopes = models.TextField(null=True)
@@ -36,11 +38,15 @@ class SlackInstallation(models.Model):
3638
team_id = models.CharField(null=True, max_length=32)
3739
team_name = models.TextField(null=True)
3840
bot_token = models.TextField(null=True)
41+
bot_refresh_token = models.TextField(null=True)
42+
bot_token_expires_at = models.DateTimeField(null=True)
3943
bot_id = models.CharField(null=True, max_length=32)
4044
bot_user_id = models.TextField(null=True)
4145
bot_scopes = models.TextField(null=True)
4246
user_id = models.CharField(null=False, max_length=32)
4347
user_token = models.TextField(null=True)
48+
user_refresh_token = models.TextField(null=True)
49+
user_token_expires_at = models.DateTimeField(null=True)
4450
user_scopes = models.TextField(null=True)
4551
incoming_webhook_url = models.TextField(null=True)
4652
incoming_webhook_channel = models.TextField(null=True)

examples/django/oauth_app/slack_datastores.py

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,50 @@ def save(self, installation: Installation):
3333
i = installation.to_dict()
3434
if is_naive(i["installed_at"]):
3535
i["installed_at"] = make_aware(i["installed_at"])
36+
if "bot_token_expires_at" in i and is_naive(i["bot_token_expires_at"]):
37+
i["bot_token_expires_at"] = make_aware(i["bot_token_expires_at"])
38+
if "user_token_expires_at" in i and is_naive(i["user_token_expires_at"]):
39+
i["user_token_expires_at"] = make_aware(i["user_token_expires_at"])
3640
i["client_id"] = self.client_id
37-
SlackInstallation(**i).save()
38-
b = installation.to_bot().to_dict()
41+
row_to_update = (
42+
SlackInstallation.objects.filter(client_id=self.client_id)
43+
.filter(enterprise_id=installation.enterprise_id)
44+
.filter(team_id=installation.team_id)
45+
.filter(installed_at=i["installed_at"])
46+
.first()
47+
)
48+
if row_to_update is not None:
49+
for key, value in i.items():
50+
setattr(row_to_update, key, value)
51+
row_to_update.save()
52+
else:
53+
SlackInstallation(**i).save()
54+
55+
self.save_bot(installation.to_bot())
56+
57+
def save_bot(self, bot: Bot):
58+
b = bot.to_dict()
3959
if is_naive(b["installed_at"]):
4060
b["installed_at"] = make_aware(b["installed_at"])
61+
if "bot_token_expires_at" in b is not None and is_naive(
62+
b["bot_token_expires_at"]
63+
):
64+
b["bot_token_expires_at"] = make_aware(b["bot_token_expires_at"])
4165
b["client_id"] = self.client_id
42-
SlackBot(**b).save()
66+
67+
row_to_update = (
68+
SlackBot.objects.filter(client_id=self.client_id)
69+
.filter(enterprise_id=bot.enterprise_id)
70+
.filter(team_id=bot.team_id)
71+
.filter(installed_at=b["installed_at"])
72+
.first()
73+
)
74+
if row_to_update is not None:
75+
for key, value in b.items():
76+
setattr(row_to_update, key, value)
77+
row_to_update.save()
78+
else:
79+
SlackBot(**b).save()
4380

4481
def find_bot(
4582
self,
@@ -53,7 +90,8 @@ def find_bot(
5390
if is_enterprise_install:
5491
t_id = None
5592
rows = (
56-
SlackBot.objects.filter(enterprise_id=e_id)
93+
SlackBot.objects.filter(client_id=self.client_id)
94+
.filter(enterprise_id=e_id)
5795
.filter(team_id=t_id)
5896
.order_by(F("installed_at").desc())[:1]
5997
)
@@ -64,10 +102,12 @@ def find_bot(
64102
enterprise_id=b.enterprise_id,
65103
team_id=b.team_id,
66104
bot_token=b.bot_token,
105+
bot_refresh_token=b.bot_refresh_token,
106+
bot_token_expires_at=b.bot_token_expires_at,
67107
bot_id=b.bot_id,
68108
bot_user_id=b.bot_user_id,
69109
bot_scopes=b.bot_scopes,
70-
installed_at=b.installed_at.timestamp(),
110+
installed_at=b.installed_at,
71111
)
72112
return None
73113

@@ -85,13 +125,15 @@ def find_installation(
85125
t_id = None
86126
if user_id is None:
87127
rows = (
88-
SlackInstallation.objects.filter(enterprise_id=e_id)
128+
SlackInstallation.objects.filter(client_id=self.client_id)
129+
.filter(enterprise_id=e_id)
89130
.filter(team_id=t_id)
90131
.order_by(F("installed_at").desc())[:1]
91132
)
92133
else:
93134
rows = (
94-
SlackInstallation.objects.filter(enterprise_id=e_id)
135+
SlackInstallation.objects.filter(client_id=self.client_id)
136+
.filter(enterprise_id=e_id)
95137
.filter(team_id=t_id)
96138
.filter(user_id=user_id)
97139
.order_by(F("installed_at").desc())[:1]
@@ -104,16 +146,20 @@ def find_installation(
104146
enterprise_id=i.enterprise_id,
105147
team_id=i.team_id,
106148
bot_token=i.bot_token,
149+
bot_refresh_token=i.bot_refresh_token,
150+
bot_token_expires_at=i.bot_token_expires_at,
107151
bot_id=i.bot_id,
108152
bot_user_id=i.bot_user_id,
109153
bot_scopes=i.bot_scopes,
110154
user_id=i.user_id,
111155
user_token=i.user_token,
156+
user_refresh_token=i.user_refresh_token,
157+
user_token_expires_at=i.user_token_expires_at,
112158
user_scopes=i.user_scopes,
113159
incoming_webhook_url=i.incoming_webhook_url,
114160
incoming_webhook_channel_id=i.incoming_webhook_channel_id,
115161
incoming_webhook_configuration_url=i.incoming_webhook_configuration_url,
116-
installed_at=i.installed_at.timestamp(),
162+
installed_at=i.installed_at,
117163
)
118164
return None
119165

examples/django/oauth_app/slack_listeners.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,16 @@
2222

2323
app = App(
2424
signing_secret=signing_secret,
25-
installation_store=DjangoInstallationStore(
26-
client_id=client_id,
27-
logger=logger,
28-
),
2925
oauth_settings=OAuthSettings(
3026
client_id=client_id,
3127
client_secret=client_secret,
3228
scopes=scopes,
29+
# If you want to test token rotation, enabling the following line will make it easy
30+
# token_rotation_expiration_minutes=1000000,
31+
installation_store=DjangoInstallationStore(
32+
client_id=client_id,
33+
logger=logger,
34+
),
3335
state_store=DjangoOAuthStateStore(
3436
expiration_seconds=120,
3537
logger=logger,

examples/django/requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
Django>=3.2,<4
2-
slack-bolt>=1.6,<2
2+
slack-bolt>=1.7,<2

0 commit comments

Comments
 (0)