or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

drf-integration.mdindex.mdmanagement-commands.mdmanagement-views.mdmodels.mdoauth2-endpoints.mdoidc.mdsettings.mdview-protection.md

management-views.mddocs/

0

# Management Views

1

2

Django OAuth Toolkit provides comprehensive web interface views for managing OAuth2 applications and user-authorized tokens. These class-based views integrate with Django's admin system and provide complete CRUD operations.

3

4

## Capabilities

5

6

### Application Management Views

7

8

Web interface for OAuth2 client application management with full CRUD operations.

9

10

```python { .api }

11

class ApplicationList(ListView):

12

"""

13

List view for OAuth2 applications.

14

URL: /o/applications/

15

16

Shows paginated list of applications owned by the current user.

17

Requires user authentication.

18

19

Template: oauth2_provider/application_list.html

20

Context: applications (queryset of Application objects)

21

"""

22

23

model = Application

24

template_name = "oauth2_provider/application_list.html"

25

context_object_name = "applications"

26

27

class ApplicationDetail(DetailView):

28

"""

29

Detail view for OAuth2 application.

30

URL: /o/applications/{pk}/

31

32

Shows detailed information about a specific application.

33

Only accessible to application owner.

34

35

Template: oauth2_provider/application_detail.html

36

Context: application (Application object)

37

"""

38

39

model = Application

40

template_name = "oauth2_provider/application_detail.html"

41

context_object_name = "application"

42

43

class ApplicationRegistration(CreateView):

44

"""

45

Create view for registering new OAuth2 applications.

46

URL: /o/applications/register/

47

48

Form for creating new OAuth2 client applications.

49

Automatically assigns current user as application owner.

50

51

Template: oauth2_provider/application_registration_form.html

52

Form: ApplicationForm

53

"""

54

55

model = Application

56

template_name = "oauth2_provider/application_registration_form.html"

57

form_class = ApplicationForm

58

59

class ApplicationUpdate(UpdateView):

60

"""

61

Update view for OAuth2 applications.

62

URL: /o/applications/{pk}/update/

63

64

Form for updating existing OAuth2 applications.

65

Only accessible to application owner.

66

67

Template: oauth2_provider/application_form.html

68

Form: ApplicationForm

69

"""

70

71

model = Application

72

template_name = "oauth2_provider/application_form.html"

73

form_class = ApplicationForm

74

75

class ApplicationDelete(DeleteView):

76

"""

77

Delete view for OAuth2 applications.

78

URL: /o/applications/{pk}/delete/

79

80

Confirmation form for deleting OAuth2 applications.

81

Only accessible to application owner.

82

83

Template: oauth2_provider/application_confirm_delete.html

84

Context: application (Application object)

85

"""

86

87

model = Application

88

template_name = "oauth2_provider/application_confirm_delete.html"

89

success_url = reverse_lazy("oauth2_provider:list")

90

```

91

92

### Token Management Views

93

94

Web interface for users to manage their authorized OAuth2 tokens.

95

96

```python { .api }

97

class AuthorizedTokensListView(ListView):

98

"""

99

List view for user's authorized OAuth2 tokens.

100

URL: /o/authorized_tokens/

101

102

Shows paginated list of access tokens authorized by current user.

103

Groups tokens by application and shows token details.

104

105

Template: oauth2_provider/authorized-tokens.html

106

Context: authorized_tokens (queryset of AccessToken objects)

107

"""

108

109

template_name = "oauth2_provider/authorized-tokens.html"

110

context_object_name = "authorized_tokens"

111

112

def get_queryset(self):

113

"""Get access tokens for current user"""

114

115

class AuthorizedTokenDeleteView(DeleteView):

116

"""

117

Delete view for revoking authorized tokens.

118

URL: /o/authorized_tokens/{pk}/delete/

119

120

Allows users to revoke their authorized tokens.

121

Revokes both access and refresh tokens.

122

123

Template: oauth2_provider/authorized-token-delete.html

124

Context: authorized_token (AccessToken object)

125

"""

126

127

template_name = "oauth2_provider/authorized-token-delete.html"

128

context_object_name = "authorized_token"

129

success_url = reverse_lazy("oauth2_provider:authorized-token-list")

130

```

131

132

### Management URL Patterns

133

134

URL patterns for application and token management views.

135

136

```python { .api }

137

management_urlpatterns = [

138

# Application management views

139

path("applications/", views.ApplicationList.as_view(), name="list"),

140

path("applications/register/", views.ApplicationRegistration.as_view(), name="register"),

141

path("applications/<slug:pk>/", views.ApplicationDetail.as_view(), name="detail"),

142

path("applications/<slug:pk>/delete/", views.ApplicationDelete.as_view(), name="delete"),

143

path("applications/<slug:pk>/update/", views.ApplicationUpdate.as_view(), name="update"),

144

# Token management views

145

path("authorized_tokens/", views.AuthorizedTokensListView.as_view(), name="authorized-token-list"),

146

path(

147

"authorized_tokens/<slug:pk>/delete/",

148

views.AuthorizedTokenDeleteView.as_view(),

149

name="authorized-token-delete",

150

),

151

]

152

```

153

154

## Usage Examples

155

156

### URL Configuration

157

158

```python

159

# urls.py

160

from django.urls import path, include

161

162

urlpatterns = [

163

# Include OAuth2 management URLs

164

path('o/', include('oauth2_provider.urls', namespace='oauth2_provider')),

165

]

166

167

# This provides these management URLs:

168

# /o/applications/ - List applications

169

# /o/applications/register/ - Register new application

170

# /o/applications/{id}/ - View application details

171

# /o/applications/{id}/update/ - Update application

172

# /o/applications/{id}/delete/ - Delete application

173

# /o/authorized_tokens/ - List authorized tokens

174

# /o/authorized_tokens/{id}/delete/ - Revoke token

175

```

176

177

### Custom Application Management

178

179

```python

180

from oauth2_provider.views.application import ApplicationRegistration

181

from oauth2_provider.forms import ApplicationForm

182

from django import forms

183

184

class CustomApplicationForm(ApplicationForm):

185

"""Custom form with additional fields"""

186

187

description = forms.CharField(

188

max_length=500,

189

required=False,

190

widget=forms.Textarea,

191

help_text="Describe your application"

192

)

193

194

class Meta(ApplicationForm.Meta):

195

fields = ApplicationForm.Meta.fields + ['description']

196

197

class CustomApplicationRegistration(ApplicationRegistration):

198

"""Custom registration view with additional fields"""

199

200

form_class = CustomApplicationForm

201

template_name = "myapp/custom_application_form.html"

202

203

def form_valid(self, form):

204

"""Add custom processing before saving"""

205

# Custom logic here

206

return super().form_valid(form)

207

208

# URL configuration

209

# path('custom/register/', CustomApplicationRegistration.as_view(), name='custom_register')

210

```

211

212

### Template Customization

213

214

```html

215

<!-- templates/oauth2_provider/application_list.html -->

216

{% extends "base.html" %}

217

218

{% block content %}

219

<h1>My OAuth2 Applications</h1>

220

221

<a href="{% url 'oauth2_provider:register' %}" class="btn btn-primary">

222

Register New Application

223

</a>

224

225

<div class="applications">

226

{% for application in applications %}

227

<div class="application-card">

228

<h3>{{ application.name }}</h3>

229

<p><strong>Client ID:</strong> {{ application.client_id }}</p>

230

<p><strong>Type:</strong> {{ application.get_client_type_display }}</p>

231

<p><strong>Grant Type:</strong> {{ application.get_authorization_grant_type_display }}</p>

232

233

<div class="actions">

234

<a href="{% url 'oauth2_provider:detail' application.pk %}">View</a>

235

<a href="{% url 'oauth2_provider:update' application.pk %}">Edit</a>

236

<a href="{% url 'oauth2_provider:delete' application.pk %}">Delete</a>

237

</div>

238

</div>

239

{% empty %}

240

<p>No applications registered yet.</p>

241

{% endfor %}

242

</div>

243

{% endblock %}

244

```

245

246

### Access Control

247

248

```python

249

from oauth2_provider.views.application import ApplicationDetail

250

from django.contrib.auth.mixins import LoginRequiredMixin

251

from django.core.exceptions import PermissionDenied

252

253

class SecureApplicationDetail(LoginRequiredMixin, ApplicationDetail):

254

"""Application detail view with enhanced security"""

255

256

def get_object(self, queryset=None):

257

"""Ensure user can only access their own applications"""

258

obj = super().get_object(queryset)

259

if obj.user != self.request.user:

260

raise PermissionDenied("You can only view your own applications")

261

return obj

262

263

class AdminApplicationList(ApplicationList):

264

"""Admin view to see all applications (requires staff permission)"""

265

266

def get_queryset(self):

267

"""Show all applications for staff users"""

268

if not self.request.user.is_staff:

269

raise PermissionDenied("Staff access required")

270

return Application.objects.all()

271

```

272

273

### Token Management Integration

274

275

```python

276

from oauth2_provider.views.token import AuthorizedTokensListView

277

from django.db.models import Q

278

279

class EnhancedTokenListView(AuthorizedTokensListView):

280

"""Enhanced token list with filtering and search"""

281

282

def get_queryset(self):

283

"""Add filtering and search capabilities"""

284

queryset = super().get_queryset()

285

286

# Filter by application

287

app_filter = self.request.GET.get('application')

288

if app_filter:

289

queryset = queryset.filter(application__name__icontains=app_filter)

290

291

# Filter by scope

292

scope_filter = self.request.GET.get('scope')

293

if scope_filter:

294

queryset = queryset.filter(scope__icontains=scope_filter)

295

296

# Filter active tokens only

297

if self.request.GET.get('active_only'):

298

from django.utils import timezone

299

queryset = queryset.filter(expires__gt=timezone.now())

300

301

return queryset.order_by('-created')

302

303

def get_context_data(self, **kwargs):

304

"""Add filter context"""

305

context = super().get_context_data(**kwargs)

306

context['applications'] = Application.objects.filter(

307

accesstoken__user=self.request.user

308

).distinct()

309

return context

310

```

311

312

### API Integration

313

314

```python

315

from oauth2_provider.views.application import ApplicationList

316

from django.http import JsonResponse

317

from django.views.generic import View

318

319

class ApplicationAPIView(View):

320

"""API endpoint for application management"""

321

322

def get(self, request):

323

"""Return applications as JSON"""

324

if not request.user.is_authenticated:

325

return JsonResponse({'error': 'Authentication required'}, status=401)

326

327

applications = Application.objects.filter(user=request.user)

328

data = []

329

330

for app in applications:

331

data.append({

332

'id': app.pk,

333

'name': app.name,

334

'client_id': app.client_id,

335

'client_type': app.client_type,

336

'authorization_grant_type': app.authorization_grant_type,

337

'created': app.created.isoformat(),

338

})

339

340

return JsonResponse({'applications': data})

341

342

class TokenAPIView(View):

343

"""API endpoint for token management"""

344

345

def get(self, request):

346

"""Return user's tokens as JSON"""

347

if not request.user.is_authenticated:

348

return JsonResponse({'error': 'Authentication required'}, status=401)

349

350

tokens = AccessToken.objects.filter(user=request.user)

351

data = []

352

353

for token in tokens:

354

data.append({

355

'id': token.pk,

356

'application': token.application.name,

357

'scope': token.scope,

358

'expires': token.expires.isoformat(),

359

'is_expired': token.is_expired(),

360

})

361

362

return JsonResponse({'tokens': data})

363

364

def delete(self, request, token_id):

365

"""Revoke specific token"""

366

if not request.user.is_authenticated:

367

return JsonResponse({'error': 'Authentication required'}, status=401)

368

369

try:

370

token = AccessToken.objects.get(pk=token_id, user=request.user)

371

token.revoke()

372

return JsonResponse({'message': 'Token revoked successfully'})

373

except AccessToken.DoesNotExist:

374

return JsonResponse({'error': 'Token not found'}, status=404)

375

```

376

377

### Bulk Operations

378

379

```python

380

from oauth2_provider.views.token import AuthorizedTokensListView

381

from django.shortcuts import redirect

382

from django.contrib import messages

383

384

class BulkTokenManagementView(AuthorizedTokensListView):

385

"""Token list view with bulk operations"""

386

387

def post(self, request, *args, **kwargs):

388

"""Handle bulk operations"""

389

action = request.POST.get('action')

390

token_ids = request.POST.getlist('selected_tokens')

391

392

if not token_ids:

393

messages.error(request, 'No tokens selected')

394

return redirect('oauth2_provider:authorized-token-list')

395

396

tokens = AccessToken.objects.filter(

397

pk__in=token_ids,

398

user=request.user

399

)

400

401

if action == 'revoke_selected':

402

count = 0

403

for token in tokens:

404

token.revoke()

405

count += 1

406

messages.success(request, f'{count} tokens revoked successfully')

407

408

elif action == 'revoke_expired':

409

expired_tokens = tokens.filter(expires__lt=timezone.now())

410

count = expired_tokens.count()

411

for token in expired_tokens:

412

token.revoke()

413

messages.success(request, f'{count} expired tokens revoked')

414

415

return redirect('oauth2_provider:authorized-token-list')

416

```