or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

authentication.mdconfiguration-utilities.mdcore-application.mddatabase-models.mdindex.mdmonitoring-metrics.mdrbac-permissions.mdrest-api.mdservices-oauth.mdsingleuser-integration.mdspawners.md

database-models.mddocs/

0

# Database Models and ORM

1

2

JupyterHub uses SQLAlchemy ORM for database operations, providing persistent storage for users, servers, groups, roles, services, and authentication state. The database models support the full JupyterHub feature set including role-based access control, server sharing, and OAuth integration.

3

4

## Capabilities

5

6

### Core User Management Models

7

8

Database models for managing users and their associated data.

9

10

```python { .api }

11

class User(Base):

12

"""

13

Database model for JupyterHub users.

14

15

Represents a user account with servers, groups, roles, and tokens.

16

"""

17

18

# Primary attributes

19

id: int # Primary key

20

name: str # Username (unique)

21

admin: bool # Whether user is an admin

22

created: datetime # When user was created

23

last_activity: datetime # Last recorded activity

24

25

# Authentication state

26

cookie_id: str # Cookie identifier

27

state: Dict[str, Any] # Arbitrary state dictionary

28

encrypted_auth_state: bytes # Encrypted authentication state

29

30

# Relationships

31

servers: List[Server] # User's servers

32

api_tokens: List[APIToken] # User's API tokens

33

oauth_tokens: List[APIToken] # OAuth tokens

34

groups: List[Group] # Groups user belongs to

35

roles: List[Role] # Roles assigned to user

36

37

def new_api_token(self, token=None, roles=None, scopes=None, note=None, expires_in=None):

38

"""

39

Create a new API token for this user.

40

41

Args:

42

token: Token string (generated if None)

43

roles: List of role names

44

scopes: List of scopes

45

note: Description of token

46

expires_in: Expiration time in seconds

47

48

Returns:

49

APIToken object

50

"""

51

52

def get_server(self, name=''):

53

"""

54

Get a named server for this user.

55

56

Args:

57

name: Server name (empty string for default server)

58

59

Returns:

60

Server object or None

61

"""

62

63

@property

64

def escaped_name(self) -> str:

65

"""URL-escaped username for safe use in URLs"""

66

67

@property

68

def auth_state(self) -> Dict[str, Any]:

69

"""Decrypted authentication state"""

70

71

class Server(Base):

72

"""

73

Database model for user notebook servers.

74

75

Represents a single-user notebook server instance.

76

"""

77

78

# Primary attributes

79

id: int # Primary key

80

name: str # Server name (empty for default)

81

url: str # Server URL

82

bind_url: str # Internal bind URL

83

last_activity: datetime # Last recorded activity

84

started: datetime # When server was started

85

base_url: str # Base URL prefix

86

87

# State and configuration

88

state: Dict[str, Any] # Spawner state

89

90

# Relationships

91

user_id: int # Foreign key to User

92

user: User # User who owns this server

93

oauth_tokens: List[APIToken] # OAuth tokens for this server

94

95

@property

96

def ready(self) -> bool:

97

"""Whether server is ready to accept connections"""

98

99

@property

100

def pending(self) -> bool:

101

"""Whether server is starting up"""

102

103

def stop(self):

104

"""Mark server as stopped"""

105

```

106

107

### Group and Role Models

108

109

Models for organizing users and managing permissions.

110

111

```python { .api }

112

class Group(Base):

113

"""

114

Database model for user groups.

115

116

Groups provide a way to organize users and assign permissions.

117

"""

118

119

# Primary attributes

120

id: int # Primary key

121

name: str # Group name (unique)

122

description: str # Group description

123

124

# Relationships

125

users: List[User] # Users in this group

126

roles: List[Role] # Roles assigned to this group

127

128

@property

129

def member_names(self) -> List[str]:

130

"""List of usernames in this group"""

131

132

class Role(Base):

133

"""

134

Database model for roles in the RBAC system.

135

136

Roles define collections of scopes that can be assigned to users,

137

groups, services, and tokens.

138

"""

139

140

# Primary attributes

141

id: int # Primary key

142

name: str # Role name (unique)

143

description: str # Role description

144

145

# Permissions

146

scopes: List[str] # List of scope strings

147

148

# Relationships

149

users: List[User] # Users with this role

150

groups: List[Group] # Groups with this role

151

services: List[Service] # Services with this role

152

tokens: List[APIToken] # Tokens with this role

153

154

@classmethod

155

def find(cls, db, name):

156

"""

157

Find role by name.

158

159

Args:

160

db: Database session

161

name: Role name

162

163

Returns:

164

Role object or None

165

"""

166

```

167

168

### Service and Authentication Models

169

170

Models for external services and authentication tokens.

171

172

```python { .api }

173

class Service(Base):

174

"""

175

Database model for JupyterHub services.

176

177

Services are external applications that integrate with JupyterHub.

178

"""

179

180

# Primary attributes

181

id: int # Primary key

182

name: str # Service name (unique)

183

admin: bool # Whether service has admin privileges

184

url: str # Service URL

185

prefix: str # URL prefix for routing

186

pid: int # Process ID (for managed services)

187

188

# Relationships

189

api_tokens: List[APIToken] # Service API tokens

190

oauth_tokens: List[APIToken] # OAuth tokens

191

roles: List[Role] # Roles assigned to service

192

oauth_client: OAuthClient # OAuth client info

193

194

class APIToken(Base):

195

"""

196

Database model for API authentication tokens.

197

198

Tokens provide API access for users, services, and OAuth clients.

199

"""

200

201

# Primary attributes

202

id: int # Primary key

203

hashed: str # Hashed token value

204

prefix: str # Token prefix (for identification)

205

created: datetime # When token was created

206

last_activity: datetime # Last token usage

207

expires_at: datetime # Token expiration (optional)

208

note: str # Description/note about token

209

210

# Relationships

211

user_id: int # Owner user (optional)

212

user: User # User who owns token

213

service_id: int # Owner service (optional)

214

service: Service # Service that owns token

215

oauth_client_id: str # OAuth client (optional)

216

oauth_client: OAuthClient # OAuth client

217

roles: List[Role] # Roles assigned to token

218

219

@property

220

def scopes(self) -> List[str]:

221

"""All scopes granted to this token"""

222

223

def match(self, token):

224

"""

225

Check if provided token matches this record.

226

227

Args:

228

token: Token string to check

229

230

Returns:

231

True if token matches

232

"""

233

```

234

235

### OAuth Integration Models

236

237

Models supporting OAuth 2.0 integration for external applications.

238

239

```python { .api }

240

class OAuthClient(Base):

241

"""

242

Database model for OAuth client applications.

243

244

OAuth clients can obtain tokens to access JupyterHub APIs.

245

"""

246

247

# Primary attributes

248

id: str # Client ID (primary key)

249

identifier: str # Client identifier

250

secret: str # Client secret (hashed)

251

description: str # Client description

252

redirect_uri: str # OAuth redirect URI

253

allowed_scopes: List[str] # Scopes client can request

254

255

# Relationships

256

tokens: List[APIToken] # Tokens issued to this client

257

codes: List[OAuthCode] # Authorization codes

258

259

def check_secret(self, secret):

260

"""

261

Verify client secret.

262

263

Args:

264

secret: Secret to verify

265

266

Returns:

267

True if secret matches

268

"""

269

270

class OAuthCode(Base):

271

"""

272

Database model for OAuth authorization codes.

273

274

Temporary codes used in OAuth authorization flow.

275

"""

276

277

# Primary attributes

278

id: int # Primary key

279

client_id: str # OAuth client ID

280

code: str # Authorization code

281

expires_at: datetime # Code expiration

282

redirect_uri: str # Redirect URI

283

session_id: str # Session identifier

284

285

# Relationships

286

client: OAuthClient # OAuth client

287

user_id: int # User who authorized

288

user: User # Authorizing user

289

```

290

291

### Server Sharing Models

292

293

Models supporting the server sharing feature.

294

295

```python { .api }

296

class Share(Base):

297

"""

298

Database model for server shares.

299

300

Represents a shared server that can be accessed by multiple users.

301

"""

302

303

# Primary attributes

304

id: int # Primary key

305

user_id: int # Owner user ID

306

server_name: str # Shared server name

307

308

# Relationships

309

user: User # User who owns the shared server

310

codes: List[ShareCode] # Access codes for this share

311

312

@property

313

def server(self) -> Server:

314

"""The shared server object"""

315

316

class ShareCode(Base):

317

"""

318

Database model for server share access codes.

319

320

Codes that allow access to shared servers.

321

"""

322

323

# Primary attributes

324

id: int # Primary key

325

code: str # Access code

326

created: datetime # When code was created

327

last_used: datetime # Last time code was used

328

accept_count: int # Number of times code was used

329

expires_at: datetime # Code expiration (optional)

330

331

# Relationships

332

share_id: int # Foreign key to Share

333

share: Share # The share this code belongs to

334

```

335

336

## Usage Examples

337

338

### Database Operations

339

340

```python

341

from jupyterhub.orm import User, Server, Group, Role

342

from sqlalchemy.orm import sessionmaker

343

344

# Database session example

345

Session = sessionmaker()

346

db = Session()

347

348

# Create a new user

349

user = User(name='alice', admin=False)

350

db.add(user)

351

db.commit()

352

353

# Find user by name

354

user = db.query(User).filter(User.name == 'alice').first()

355

356

# Create API token for user

357

token = user.new_api_token(

358

note='API access token',

359

scopes=['read:users', 'servers']

360

)

361

db.commit()

362

363

# Query user's servers

364

servers = db.query(Server).filter(Server.user == user).all()

365

```

366

367

### Group Management

368

369

```python

370

# Create group

371

group = Group(name='students', description='Student users')

372

db.add(group)

373

374

# Add users to group

375

alice = db.query(User).filter(User.name == 'alice').first()

376

bob = db.query(User).filter(User.name == 'bob').first()

377

group.users.extend([alice, bob])

378

379

# Create role and assign to group

380

role = Role(

381

name='student-role',

382

description='Basic student permissions',

383

scopes=['self', 'servers']

384

)

385

group.roles.append(role)

386

db.commit()

387

```

388

389

### Service Registration

390

391

```python

392

# Register external service

393

service = Service(

394

name='announcement-service',

395

admin=False,

396

url='http://localhost:8001',

397

prefix='/announcements'

398

)

399

db.add(service)

400

401

# Create API token for service

402

token = service.new_api_token(

403

scopes=['read:users', 'read:servers'],

404

note='Service API access'

405

)

406

db.commit()

407

```

408

409

### OAuth Client Setup

410

411

```python

412

# Register OAuth client

413

client = OAuthClient(

414

id='my-app',

415

identifier='my-app-client',

416

description='My Application',

417

redirect_uri='http://localhost:3000/callback',

418

allowed_scopes=['read:users', 'read:servers']

419

)

420

client.secret = 'hashed-secret-value'

421

db.add(client)

422

db.commit()

423

```

424

425

## Database Configuration

426

427

### Connection Setup

428

429

```python

430

# jupyterhub_config.py

431

432

# SQLite (default)

433

c.JupyterHub.db_url = 'sqlite:///jupyterhub.sqlite'

434

435

# PostgreSQL

436

c.JupyterHub.db_url = 'postgresql://user:password@localhost/jupyterhub'

437

438

# MySQL

439

c.JupyterHub.db_url = 'mysql+pymysql://user:password@localhost/jupyterhub'

440

```

441

442

### Migration and Upgrades

443

444

```python

445

# Database upgrade command

446

# jupyterhub upgrade-db

447

448

# Programmatic upgrade

449

from jupyterhub.dbutil import upgrade_if_needed

450

upgrade_if_needed(db_url, log=app.log)

451

```

452

453

### Query Patterns

454

455

```python

456

# Common query patterns

457

from jupyterhub.orm import User, Server, Group

458

459

# Active users with servers

460

active_users = db.query(User).join(Server).filter(

461

Server.last_activity > cutoff_date

462

).all()

463

464

# Admin users

465

admins = db.query(User).filter(User.admin == True).all()

466

467

# Users in specific group

468

group_users = db.query(User).join(User.groups).filter(

469

Group.name == 'students'

470

).all()

471

472

# Expired tokens

473

expired = db.query(APIToken).filter(

474

APIToken.expires_at < datetime.utcnow()

475

).all()

476

```