or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cicd.mdclient-auth.mdgraphql.mdindex.mdissues-mrs.mdprojects.mdrepository.mdusers-groups.md

users-groups.mddocs/

0

# Users and Groups

1

2

User account management, group administration, membership control, and access level configuration. Covers user profiles, authentication keys, group hierarchies, and membership management across the GitLab instance.

3

4

## Capabilities

5

6

### User Management

7

8

Comprehensive user account management including creation, profile updates, authentication methods, and account status control.

9

10

```python { .api }

11

class User(SaveMixin, ObjectDeleteMixin, RESTObject):

12

"""

13

GitLab user object with profile and access management.

14

15

Key Attributes:

16

- id: User ID

17

- username: User login name

18

- name: Full display name

19

- email: Primary email address

20

- state: Account state ("active", "blocked", "deactivated")

21

- avatar_url: Profile picture URL

22

- web_url: User profile URL

23

- created_at: Account creation timestamp

24

- last_sign_in_at: Last login timestamp

25

- current_sign_in_at: Current session start

26

- is_admin: Administrator status

27

- can_create_group: Can create groups

28

- can_create_project: Can create projects

29

- projects_limit: Maximum number of projects

30

- external: External user status

31

- private_profile: Profile visibility setting

32

- location: User location

33

- skype: Skype username

34

- linkedin: LinkedIn profile

35

- twitter: Twitter handle

36

- website_url: Personal website

37

- organization: Organization name

38

- job_title: Job title

39

- bio: User biography

40

"""

41

42

def save(self) -> None:

43

"""

44

Save user profile changes.

45

46

Raises:

47

GitlabUpdateError: If update fails

48

"""

49

50

def delete(self) -> None:

51

"""

52

Delete user account permanently.

53

54

Raises:

55

GitlabDeleteError: If deletion fails

56

"""

57

58

def block(self) -> dict:

59

"""

60

Block the user account.

61

62

Returns:

63

Dictionary with operation result

64

65

Raises:

66

GitlabBlockError: If blocking fails

67

"""

68

69

def unblock(self) -> dict:

70

"""

71

Unblock the user account.

72

73

Returns:

74

Dictionary with operation result

75

76

Raises:

77

GitlabUnblockError: If unblocking fails

78

"""

79

80

def deactivate(self) -> dict:

81

"""

82

Deactivate the user account.

83

84

Returns:

85

Dictionary with operation result

86

87

Raises:

88

GitlabDeactivateError: If deactivation fails

89

"""

90

91

def activate(self) -> dict:

92

"""

93

Activate the user account.

94

95

Returns:

96

Dictionary with operation result

97

98

Raises:

99

GitlabActivateError: If activation fails

100

"""

101

```

102

103

### User Manager

104

105

```python { .api }

106

class UserManager(CRUDMixin[User]):

107

"""Manager for GitLab users with comprehensive filtering and administration."""

108

109

def list(

110

self,

111

active: bool | None = None,

112

blocked: bool | None = None,

113

external: bool | None = None,

114

exclude_external: bool | None = None,

115

without_projects: bool | None = None,

116

admins: bool | None = None,

117

order_by: str | None = None,

118

sort: str | None = None,

119

search: str | None = None,

120

username: str | None = None,

121

extern_uid: str | None = None,

122

provider: str | None = None,

123

created_before: str | None = None,

124

created_after: str | None = None,

125

with_custom_attributes: bool | None = None,

126

two_factor: str | None = None,

127

without_project_bots: bool | None = None,

128

**kwargs

129

) -> list[User]:

130

"""

131

List users with extensive filtering options.

132

133

Parameters:

134

- active: Filter by active status

135

- blocked: Filter by blocked status

136

- external: Filter by external user status

137

- exclude_external: Exclude external users

138

- without_projects: Users without projects

139

- admins: Filter by admin status

140

- order_by: Order by field ("id", "name", "username", "created_at", "updated_at")

141

- sort: Sort direction ("asc", "desc")

142

- search: Search in name, username, and email

143

- username: Filter by specific username

144

- extern_uid: Filter by external UID

145

- provider: Filter by authentication provider

146

- created_before: Filter by creation date (ISO format)

147

- created_after: Filter by creation date (ISO format)

148

- with_custom_attributes: Include custom attributes

149

- two_factor: Filter by 2FA status ("enabled", "disabled")

150

- without_project_bots: Exclude project bot users

151

152

Returns:

153

List of User objects

154

"""

155

156

def get(self, id: int | str, lazy: bool = False, **kwargs) -> User:

157

"""

158

Get a specific user.

159

160

Parameters:

161

- id: User ID or username

162

- lazy: Return object without making API call

163

- with_custom_attributes: Include custom attributes

164

165

Returns:

166

User object

167

168

Raises:

169

GitlabGetError: If user not found

170

"""

171

172

def create(self, data: dict, **kwargs) -> User:

173

"""

174

Create a new user account.

175

176

Parameters:

177

- data: User creation parameters

178

179

Required fields in data:

180

- email: User email address

181

- password: User password

182

- username: User login name

183

- name: Full display name

184

185

Optional fields in data:

186

- skype: Skype username

187

- linkedin: LinkedIn profile

188

- twitter: Twitter handle

189

- website_url: Personal website

190

- organization: Organization name

191

- projects_limit: Maximum projects (default: global limit)

192

- extern_uid: External authentication UID

193

- provider: Authentication provider

194

- bio: User biography

195

- location: User location

196

- admin: Admin privileges (default: False)

197

- can_create_group: Can create groups (default: True)

198

- skip_confirmation: Skip email confirmation

199

- external: External user status (default: False)

200

- avatar: Avatar image file

201

- private_profile: Make profile private (default: False)

202

- color_scheme_id: Color scheme ID

203

- theme_id: Theme ID

204

- force_random_password: Generate random password

205

- reset_password: Send password reset email

206

207

Returns:

208

New User object

209

210

Raises:

211

GitlabCreateError: If user creation fails

212

"""

213

```

214

215

### Current User Management

216

217

```python { .api }

218

class CurrentUser(SaveMixin, RESTObject):

219

"""

220

Represents the currently authenticated user with enhanced profile management.

221

222

Provides access to current user's resources and settings.

223

"""

224

225

def save(self) -> None:

226

"""Save current user profile changes."""

227

228

class CurrentUserManager(GetWithoutIdMixin[CurrentUser], UpdateMixin[CurrentUser]):

229

"""Manager for current user operations."""

230

231

def get(self, **kwargs) -> CurrentUser:

232

"""

233

Get current user information.

234

235

Returns:

236

CurrentUser object

237

"""

238

239

def update(self, data: dict, **kwargs) -> CurrentUser:

240

"""

241

Update current user profile.

242

243

Parameters:

244

- data: Profile update data

245

246

Returns:

247

Updated CurrentUser object

248

"""

249

```

250

251

### User SSH Keys

252

253

```python { .api }

254

class UserKey(ObjectDeleteMixin, RESTObject):

255

"""

256

User SSH key object.

257

258

Attributes:

259

- id: Key ID

260

- title: Key title/name

261

- key: SSH public key content

262

- created_at: Creation timestamp

263

- expires_at: Expiration timestamp (optional)

264

- usage_type: Key usage type

265

"""

266

267

def delete(self) -> None:

268

"""Delete SSH key."""

269

270

class UserKeyManager(ListMixin[UserKey], CreateMixin[UserKey], DeleteMixin[UserKey]):

271

"""Manager for user SSH keys."""

272

273

def list(self, **kwargs) -> list[UserKey]:

274

"""List user's SSH keys."""

275

276

def create(self, data: dict, **kwargs) -> UserKey:

277

"""

278

Create new SSH key for user.

279

280

Parameters:

281

- data: Key creation data

282

283

Required fields:

284

- title: Key title

285

- key: SSH public key content

286

287

Optional fields:

288

- expires_at: Expiration date (ISO format)

289

- usage_type: Key usage type

290

"""

291

292

class CurrentUserKey(ObjectDeleteMixin, RESTObject):

293

"""Current user's SSH key object."""

294

295

class CurrentUserKeyManager(CRUDMixin[CurrentUserKey]):

296

"""Manager for current user's SSH keys."""

297

```

298

299

### User GPG Keys

300

301

```python { .api }

302

class UserGPGKey(ObjectDeleteMixin, RESTObject):

303

"""

304

User GPG key object.

305

306

Attributes:

307

- id: Key ID

308

- key: GPG public key content

309

- created_at: Creation timestamp

310

- emails: Associated email addresses

311

- subkeys: GPG subkeys

312

"""

313

314

class UserGPGKeyManager(ListMixin[UserGPGKey], CreateMixin[UserGPGKey], DeleteMixin[UserGPGKey]):

315

"""Manager for user GPG keys."""

316

317

def create(self, data: dict, **kwargs) -> UserGPGKey:

318

"""

319

Add GPG key to user.

320

321

Parameters:

322

- data: Key data with 'key' field containing GPG public key

323

"""

324

325

class CurrentUserGPGKey(ObjectDeleteMixin, RESTObject):

326

"""Current user's GPG key object."""

327

328

class CurrentUserGPGKeyManager(CRUDMixin[CurrentUserGPGKey]):

329

"""Manager for current user's GPG keys."""

330

```

331

332

### User Email Management

333

334

```python { .api }

335

class UserEmail(ObjectDeleteMixin, RESTObject):

336

"""

337

User email address object.

338

339

Attributes:

340

- id: Email ID

341

- email: Email address

342

- confirmed_at: Confirmation timestamp

343

"""

344

345

class UserEmailManager(ListMixin[UserEmail], CreateMixin[UserEmail], DeleteMixin[UserEmail]):

346

"""Manager for user email addresses."""

347

348

def create(self, data: dict, **kwargs) -> UserEmail:

349

"""

350

Add email address to user.

351

352

Parameters:

353

- data: Email data with 'email' field

354

"""

355

356

class CurrentUserEmail(ObjectDeleteMixin, RESTObject):

357

"""Current user's email address object."""

358

359

class CurrentUserEmailManager(ListMixin[CurrentUserEmail], CreateMixin[CurrentUserEmail]):

360

"""Manager for current user's email addresses."""

361

```

362

363

### Group Management

364

365

```python { .api }

366

class Group(SaveMixin, ObjectDeleteMixin, RESTObject):

367

"""

368

GitLab group object with comprehensive resource management.

369

370

Key Attributes:

371

- id: Group ID

372

- name: Group name

373

- path: Group path (URL slug)

374

- full_name: Full group name with parent hierarchy

375

- full_path: Full group path with parent hierarchy

376

- description: Group description

377

- visibility: Group visibility ("private", "internal", "public")

378

- lfs_enabled: Git LFS enabled status

379

- avatar_url: Group avatar URL

380

- web_url: Group web URL

381

- request_access_enabled: Allow access requests

382

- parent_id: Parent group ID (for subgroups)

383

- created_at: Creation timestamp

384

- statistics: Group statistics (if included)

385

"""

386

387

def save(self) -> None:

388

"""

389

Save group changes.

390

391

Raises:

392

GitlabUpdateError: If update fails

393

"""

394

395

def delete(self) -> None:

396

"""

397

Delete group permanently.

398

399

Raises:

400

GitlabDeleteError: If deletion fails

401

"""

402

403

def transfer(self, to_parent_id: int | None) -> dict:

404

"""

405

Transfer group to different parent.

406

407

Parameters:

408

- to_parent_id: Target parent group ID (None for root level)

409

410

Returns:

411

Dictionary with transfer result

412

413

Raises:

414

GitlabGroupTransferError: If transfer fails

415

"""

416

```

417

418

### Group Manager

419

420

```python { .api }

421

class GroupManager(CRUDMixin[Group]):

422

"""Manager for GitLab groups with comprehensive filtering."""

423

424

def list(

425

self,

426

skip_groups: list[int] | None = None,

427

all_available: bool | None = None,

428

search: str | None = None,

429

order_by: str | None = None,

430

sort: str | None = None,

431

statistics: bool | None = None,

432

with_custom_attributes: bool | None = None,

433

owned: bool | None = None,

434

min_access_level: int | None = None,

435

top_level_only: bool | None = None,

436

**kwargs

437

) -> list[Group]:

438

"""

439

List groups with filtering options.

440

441

Parameters:

442

- skip_groups: Group IDs to skip

443

- all_available: Include all available groups

444

- search: Search in group name and path

445

- order_by: Order by field ("name", "path", "id", "similarity")

446

- sort: Sort direction ("asc", "desc")

447

- statistics: Include group statistics

448

- with_custom_attributes: Include custom attributes

449

- owned: Show only owned groups

450

- min_access_level: Minimum access level

451

- top_level_only: Show only top-level groups

452

453

Returns:

454

List of Group objects

455

"""

456

457

def create(self, data: dict, **kwargs) -> Group:

458

"""

459

Create a new group.

460

461

Parameters:

462

- data: Group creation parameters

463

464

Required fields:

465

- name: Group name

466

- path: Group path

467

468

Optional fields:

469

- description: Group description

470

- visibility: Group visibility ("private", "internal", "public")

471

- lfs_enabled: Enable Git LFS (default: True)

472

- request_access_enabled: Allow access requests (default: False)

473

- parent_id: Parent group ID (for subgroups)

474

- auto_devops_enabled: Enable Auto DevOps

475

- emails_disabled: Disable group emails

476

- mentions_disabled: Disable group mentions

477

- subgroup_creation_level: Subgroup creation level

478

- project_creation_level: Project creation level

479

- share_with_group_lock: Prevent sharing with other groups

480

- require_two_factor_authentication: Require 2FA for members

481

- two_factor_grace_period: 2FA grace period in hours

482

- default_branch_protection: Default branch protection level

483

484

Returns:

485

New Group object

486

487

Raises:

488

GitlabCreateError: If group creation fails

489

"""

490

```

491

492

### Group Members and Access Control

493

494

```python { .api }

495

class GroupMember(SaveMixin, ObjectDeleteMixin, RESTObject):

496

"""

497

Group member object with access level management.

498

499

Attributes:

500

- id: User ID

501

- username: Username

502

- name: Full name

503

- access_level: Access level (10=Guest, 20=Reporter, 30=Developer, 40=Maintainer, 50=Owner)

504

- expires_at: Membership expiration date

505

"""

506

507

def save(self) -> None:

508

"""Save member access level changes."""

509

510

def delete(self) -> None:

511

"""Remove member from group."""

512

513

class GroupMemberManager(CRUDMixin[GroupMember]):

514

"""Manager for group members."""

515

516

def list(

517

self,

518

query: str | None = None,

519

user_ids: list[int] | None = None,

520

**kwargs

521

) -> list[GroupMember]:

522

"""

523

List group members.

524

525

Parameters:

526

- query: Search query for member names

527

- user_ids: Filter by specific user IDs

528

529

Returns:

530

List of GroupMember objects

531

"""

532

533

def create(self, data: dict, **kwargs) -> GroupMember:

534

"""

535

Add member to group.

536

537

Parameters:

538

- data: Member data

539

540

Required fields:

541

- user_id: User ID to add

542

- access_level: Access level (10-50)

543

544

Optional fields:

545

- expires_at: Membership expiration date (ISO format)

546

547

Returns:

548

New GroupMember object

549

"""

550

551

# Similar classes for all group members (including inherited)

552

class GroupMemberAll(RESTObject):

553

"""Group member including inherited members."""

554

555

class GroupMemberAllManager(ListMixin[GroupMemberAll]):

556

"""Manager for all group members including inherited."""

557

```

558

559

### Access Request Management

560

561

```python { .api }

562

class GroupAccessRequest(ObjectDeleteMixin, RESTObject):

563

"""

564

Group access request object.

565

566

Attributes:

567

- id: Request ID

568

- username: Requesting username

569

- name: Full name

570

- requested_at: Request timestamp

571

"""

572

573

def approve(self, access_level: int = 30) -> dict:

574

"""

575

Approve access request.

576

577

Parameters:

578

- access_level: Access level to grant (default: 30=Developer)

579

580

Returns:

581

Dictionary with approval result

582

"""

583

584

class GroupAccessRequestManager(ListMixin[GroupAccessRequest], CreateMixin[GroupAccessRequest], DeleteMixin[GroupAccessRequest]):

585

"""Manager for group access requests."""

586

```

587

588

### Usage Examples

589

590

```python

591

import gitlab

592

from gitlab import DEVELOPER_ACCESS, MAINTAINER_ACCESS

593

594

# Initialize client

595

gl = gitlab.Gitlab("https://gitlab.example.com", private_token="your-token")

596

597

# User management

598

users = gl.users.list(active=True, search="john")

599

user = gl.users.get(123)

600

601

# Update user profile

602

user.bio = "Updated biography"

603

user.location = "New York"

604

user.save()

605

606

# Block/unblock user

607

user.block()

608

user.unblock()

609

610

# Create new user

611

user_data = {

612

"email": "newuser@example.com",

613

"password": "secure_password",

614

"username": "newuser",

615

"name": "New User",

616

"projects_limit": 10,

617

"can_create_group": True

618

}

619

new_user = gl.users.create(user_data)

620

621

# Current user operations

622

current_user = gl.user

623

print(f"Logged in as: {current_user.name}")

624

625

# Manage SSH keys

626

keys = current_user.keys.list()

627

key_data = {

628

"title": "My Laptop Key",

629

"key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQ..."

630

}

631

new_key = current_user.keys.create(key_data)

632

633

# Group management

634

groups = gl.groups.list(owned=True, order_by="name")

635

group = gl.groups.get(456)

636

637

# Create subgroup

638

subgroup_data = {

639

"name": "Development Team",

640

"path": "dev-team",

641

"parent_id": group.id,

642

"visibility": "private"

643

}

644

subgroup = gl.groups.create(subgroup_data)

645

646

# Group member management

647

members = group.members.list()

648

649

# Add member to group

650

member_data = {

651

"user_id": 123,

652

"access_level": DEVELOPER_ACCESS,

653

"expires_at": "2024-12-31"

654

}

655

new_member = group.members.create(member_data)

656

657

# Update member access level

658

member = group.members.get(123)

659

member.access_level = MAINTAINER_ACCESS

660

member.save()

661

662

# Remove member

663

member.delete()

664

665

# Handle access requests

666

access_requests = group.accessrequests.list()

667

for request in access_requests:

668

request.approve(access_level=DEVELOPER_ACCESS)

669

670

# Transfer group

671

group.transfer(to_parent_id=None) # Move to root level

672

673

# Delete user (admin only)

674

# user.delete()

675

```

676

677

### Error Handling

678

679

```python { .api }

680

class GitlabBlockError(GitlabOperationError):

681

"""Raised when user blocking fails."""

682

pass

683

684

class GitlabUnblockError(GitlabOperationError):

685

"""Raised when user unblocking fails."""

686

pass

687

688

class GitlabActivateError(GitlabOperationError):

689

"""Raised when user activation fails."""

690

pass

691

692

class GitlabDeactivateError(GitlabOperationError):

693

"""Raised when user deactivation fails."""

694

pass

695

696

class GitlabGroupTransferError(GitlabOperationError):

697

"""Raised when group transfer fails."""

698

pass

699

```

700

701

Example error handling:

702

```python

703

try:

704

user = gl.users.create(invalid_user_data)

705

except gitlab.GitlabCreateError as e:

706

print(f"User creation failed: {e}")

707

708

try:

709

user.block()

710

except gitlab.GitlabBlockError as e:

711

print(f"Cannot block user: {e}")

712

713

try:

714

group.transfer(invalid_parent_id)

715

except gitlab.GitlabGroupTransferError as e:

716

print(f"Group transfer failed: {e}")

717

```