labclient 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ab2d7a4a0dcf9e876c42f3d92537ad03f6cc9d00391bf574188de36fa5dde3a6
4
- data.tar.gz: 9bba10386c15059b97c79a0e6f0ed322af7614736b78e55fd968f362e767dd8e
3
+ metadata.gz: '09bb30f5014cb0b4a37d7f4aa421549337b6177bf132580974cf1a35199c6242'
4
+ data.tar.gz: cc354dc398276bba64db00bc9adafd23e9c341eba16c4c2dd315788f3ab72fb1
5
5
  SHA512:
6
- metadata.gz: 8998430e5b8d07584da6fe906d465238fd7725fa0773b9bb11a7b47dc755ce5fcb80d0cbb22055b16327665d70cbd034a24a63d310fabd11bd560c0ebd994f95
7
- data.tar.gz: 3e61e5c568a93cfad5955198f6524349a89a06d729ead2d8f98c1d05c78e885edfb9fbb069fee2226731b26a1ab8c0404b857883f745d99c7564280e8f855b4d
6
+ metadata.gz: f492cb23a182293f165733d7d54830a2a34b9666c487cf63b5bd2dded2dbd58a7713f513eeba0813e382f1efe0d2c50cb8204f485678448b76f109bf289b8887
7
+ data.tar.gz: 0d558d85cea6f58bddf600dd36962b9a3fe1bc0c91e9b398ff6d2c35103fd61d88e4b6d47d24aa06bff15a5c2c195561847f495400ddef1eabaf78cfd7c65498
@@ -36,7 +36,6 @@ require 'labclient/users/current'
36
36
  require 'labclient/users/status'
37
37
  require 'labclient/users/counts'
38
38
  require 'labclient/users/activity'
39
- require 'labclient/users/memberships'
40
39
  require 'labclient/users/search'
41
40
  require 'labclient/users/create'
42
41
  require 'labclient/users/update'
@@ -47,6 +46,8 @@ require 'labclient/users/activate'
47
46
  require 'labclient/users/deactivate'
48
47
  require 'labclient/users/delete'
49
48
  require 'labclient/users/delete_identity'
49
+ require 'labclient/users/memberships'
50
+ require 'labclient/users/membership'
50
51
  require 'labclient/users/user'
51
52
 
52
53
  # ===============================================
@@ -149,6 +150,13 @@ require 'labclient/projects/environments/delete'
149
150
  require 'labclient/projects/environments/stop'
150
151
  require 'labclient/projects/environments/project_environment'
151
152
 
153
+ # Protected Environments
154
+ require 'labclient/protected_environments/list'
155
+ require 'labclient/protected_environments/show'
156
+ require 'labclient/protected_environments/protect'
157
+ require 'labclient/protected_environments/unprotect'
158
+ require 'labclient/protected_environments/protected_environment'
159
+
152
160
  # Project Deployments
153
161
  require 'labclient/projects/deployments/client'
154
162
  require 'labclient/projects/deployments/list'
@@ -1,6 +1,7 @@
1
1
  # Top Namespace
2
2
  module LabClient
3
3
  # API Specifics
4
+ # rubocop:disable Metrics/ClassLength
4
5
  class Client
5
6
  # include HTTParty
6
7
  attr_accessor :settings, :resp, :klass, :link, :http
@@ -55,6 +56,7 @@ module LabClient
55
56
  project_runners: ProjectRunners,
56
57
  projects: Projects,
57
58
  protected_branches: ProtectedBranches,
59
+ protected_environments: ProtectedEnvironments,
58
60
  protected_tags: ProtectedTags,
59
61
  registry: Registry,
60
62
  repo: Repositories,
@@ -91,18 +93,33 @@ module LabClient
91
93
  end
92
94
 
93
95
  # Default setup, pull in settings
94
- def initialize(settings = nil)
95
- @settings = settings
96
+ def initialize(user_settings = nil)
97
+ @settings = user_settings
98
+ setup_profile if user_settings&.key?(:profile) || ENV['LABCLIENT_PROFILE']
96
99
  @settings ||= fill_configuration
97
100
 
98
101
  # Set Unspecified Defaults
99
102
  unspecified_defaults
100
103
 
101
- raise 'LabClient Error - Missing URL!' if @settings[:url].nil?
104
+ prompt_for_url if @settings[:url].blank?
105
+
106
+ # Only prompt if explicitly set to nil
107
+ prompt_for_token if @settings[:token].nil?
102
108
 
103
109
  self.http = HTTP.new(@settings)
104
110
  end
105
111
 
112
+ def prompt_for_url
113
+ print 'Enter GitLab URL (e.g. https://gitlab.com): '
114
+ @settings[:url] = STDIN.gets.chomp
115
+ raise 'LabClient Error - Missing URL!' if @settings[:url].blank?
116
+ end
117
+
118
+ def prompt_for_token
119
+ print 'Enter Personal Access Token: '
120
+ @settings[:token] = STDIN.gets.chomp
121
+ end
122
+
106
123
  def unspecified_defaults
107
124
  @settings[:paginate] = true if @settings[:paginate].nil?
108
125
  @settings[:ssl_verify] = true if @settings[:ssl_verify].nil?
@@ -112,6 +129,27 @@ module LabClient
112
129
  ENV['HOME'] + '/.gitlab-labclient'
113
130
  end
114
131
 
132
+ # Easier Profile Name Access
133
+ def profile
134
+ if settings&.key? :profile
135
+ settings[:profile].to_sym
136
+ else
137
+ ENV['LABCLIENT_PROFILE'].to_sym
138
+ end
139
+ end
140
+
141
+ # Support for Named Profiles
142
+ def setup_profile
143
+ return false unless File.exist? home_file
144
+
145
+ config = Oj.load_file(home_file, { symbol_keys: true })
146
+ return false unless config.key? profile
147
+
148
+ self.settings ||= {}
149
+ settings.merge! config[profile]
150
+ end
151
+
152
+ # Load default profile
115
153
  def fill_configuration
116
154
  if File.exist? home_file
117
155
  Oj.load_file(home_file, { symbol_keys: true })
@@ -155,4 +193,5 @@ module LabClient
155
193
  end
156
194
  end
157
195
  end
196
+ # rubocop:enable Metrics/ClassLength
158
197
  end
@@ -43,13 +43,13 @@ module LabClient
43
43
 
44
44
  doc 'Wizard' do
45
45
  markdown <<~DOC
46
- | Setting | Type | Description |
47
- | -------- | ------- | ------------------------------------------------------ |
48
- | random | Boolean | Run Populate. Setup random Users, Projects, and Groups |
49
- | count | Hash | Settings for random. User, Project, Group count |
50
- | password | String | Default password for generated Users |
51
- | domain | String | Defaults to client url. Default email domain for users |
52
-
46
+ | Setting | Type | Description |
47
+ | ----------------- | ------- | ------------------------------------------------------ |
48
+ | random | Boolean | Run Populate. Setup random Users, Projects, and Groups |
49
+ | count | Hash | Settings for random. User, Project, Group count |
50
+ | password | String | Default password for generated Users |
51
+ | domain | String | Defaults to client url. Default email domain for users |
52
+ | skip_confirmation | Boolean | Enable/Disable skip_confirmation on new users |
53
53
  DOC
54
54
  end
55
55
 
@@ -5,7 +5,7 @@ module LabClient
5
5
  class Wizard
6
6
  include Generator::Names # Name Generator
7
7
  attr_reader :client
8
- attr_accessor :count, :random, :password, :templates, :domain
8
+ attr_accessor :count, :random, :password, :templates, :domain, :skip_confirmation
9
9
 
10
10
  def inspect
11
11
  "#<Wizard count=#{count}, random=#{random}, domain=#{domain}> templates=#{templates}"
@@ -26,6 +26,9 @@ module LabClient
26
26
  self.random = true # Populate Random or use only Templates
27
27
  self.count = default_count
28
28
  self.password = SecureRandom.uuid
29
+ puts "Default Password: #{password}"
30
+
31
+ self.skip_confirmation = true
29
32
  self.domain = URI.parse(client.settings[:url]).hostname
30
33
 
31
34
  # Default Templates
@@ -61,7 +64,8 @@ module LabClient
61
64
  name: name,
62
65
  email: email,
63
66
  password: password,
64
- username: username
67
+ username: username,
68
+ skip_confirmation: skip_confirmation
65
69
  )
66
70
  end
67
71
  end
@@ -51,6 +51,7 @@ module LabClient
51
51
  option 'level', 'Humanized symbol of access level. e.g. :developer'
52
52
  option 'user', 'Collect user object.'
53
53
  option '<permission>?', 'True/False evaluation each guest?, developer? etc'
54
+ option 'greater_than', 'True/False if user has greater than [Permission Name]'
54
55
  end
55
56
  end
56
57
  end
@@ -44,6 +44,41 @@ module LabClient
44
44
  DOC
45
45
  end
46
46
 
47
+ doc 'Authentication' do
48
+ title 'Named Profiles'
49
+ markdown 'Within the `~/.gitlab-labclient` you can also specify profile names'
50
+ example <<~DOC
51
+ {
52
+ "prod": {
53
+ "url": "https://labclient-prod",
54
+ "token": "super_secure",
55
+ "paginate": false
56
+ },
57
+ "dev": {
58
+ "url": "https://labclient-dev",
59
+ "token": "super_secure",
60
+ "ssl_verify": false,
61
+ "paginate": true
62
+ }
63
+ }
64
+ DOC
65
+ end
66
+
67
+ doc 'Authentication' do
68
+ desc 'Manually select a named profile'
69
+ example <<~DOC
70
+ client = LabClient::Client.new(profile: 'prod')
71
+ DOC
72
+ end
73
+
74
+ doc 'Authentication' do
75
+ desc 'Automatically select via ENV Variables'
76
+ example <<~DOC
77
+ ENV['LABCLIENT_PROFILE'] = 'dev'
78
+ client = LabClient::Client.new
79
+ DOC
80
+ end
81
+
47
82
  doc 'Authentication' do
48
83
  title 'Environment Variables'
49
84
  desc 'If not provided, and credentials file does not exist will attempt to use ENV variables'
@@ -252,21 +287,6 @@ module LabClient
252
287
  DOC
253
288
  end
254
289
 
255
- doc 'Other' do
256
- title 'Docker'
257
- desc 'A docker image is created from master and can be used to execute snippets or load a quick pry session'
258
-
259
- example 'docker run -it registry.gitlab.com/labclient/labclient'
260
-
261
- result <<~DOC
262
- # Run Container
263
- docker run -it -e LABCLIENT_URL="https://labclient" -e LABCLIENT_TOKEN="token" registry.gitlab.com/labclient/labclient
264
-
265
- client = LabClient::Client.new
266
- client.users.list
267
- DOC
268
- end
269
-
270
290
  doc 'Other' do
271
291
  title 'Curl'
272
292
  desc 'Sometimes you just wana have a curl example to test or send someone'
@@ -291,6 +311,30 @@ module LabClient
291
311
  - [API Authentication](https://docs.gitlab.com/ee/api/README.html#authentication)
292
312
  DOC
293
313
  end
314
+
315
+ doc 'Docker' do
316
+ desc 'A docker image is created from master and can be used to execute snippets or load a quick pry session'
317
+
318
+ example 'docker run -it registry.gitlab.com/labclient/labclient'
319
+
320
+ result <<~DOC
321
+ # Run Container
322
+ docker run -it registry.gitlab.com/labclient/labclient
323
+ # Without settings configured, initial will prompt for credentials
324
+
325
+ client.users.list
326
+ DOC
327
+ end
328
+
329
+ doc 'Docker' do
330
+ desc 'The docker container configured and execute code snippets'
331
+
332
+ example 'docker run -it registry.gitlab.com/labclient/labclient'
333
+
334
+ result <<~DOC
335
+ docker run -it -e LABCLIENT_URL="https://labclient" -e LABCLIENT_TOKEN="secure_token" labclient 'puts client.users.list.count'
336
+ DOC
337
+ end
294
338
  end
295
339
  end
296
340
  # rubocop:enable Metrics/ClassLength
@@ -492,6 +492,23 @@ module LabClient
492
492
  client.projects.environments.stop(id, environment_id)
493
493
  end
494
494
 
495
+ # Protected Environments
496
+ def protected_environments
497
+ client.protected_environments.list(id)
498
+ end
499
+
500
+ def protected_environment(environment_id)
501
+ client.protected_environments.show(id, environment_id)
502
+ end
503
+
504
+ def protect_environment(query)
505
+ client.protected_environments.protect(id, query)
506
+ end
507
+
508
+ def unprotect_environment(environment_id)
509
+ client.protected_environments.unprotect(id, environment_id)
510
+ end
511
+
495
512
  # Project Triggers
496
513
  def triggers
497
514
  client.projects.triggers.list(id)
@@ -71,6 +71,12 @@ module LabClient
71
71
  option 'environment_update', 'Update project environment [Environment ID, Hash]'
72
72
  option 'environment_stop', 'Stop project environment [Environment ID]'
73
73
 
74
+ # Protected Environments
75
+ option 'protected_environments', 'List protected environments [String]'
76
+ option 'protected_environment', 'Show single protected environment [String]'
77
+ option 'protect_environment', 'Protect a single environment [Hash]'
78
+ option 'unprotect_environment', 'Unprotect environment [Environment]'
79
+
74
80
  # Deployments
75
81
  option 'deployments', "List this project's deployments"
76
82
  option 'deployment_create', 'Create project deployment [Hash]'
@@ -19,11 +19,12 @@ module LabClient
19
19
  | allowed_to_unprotect | array | no | **(STARTER)** Array of access levels allowed to unprotect, with each described by a hash |
20
20
  | code_owner_approval_required | boolean | no | **(PREMIUM)** Prevent pushes to this branch if it matches an item in the CODEOWNERS file (defaults: false) |
21
21
 
22
- *Valid access levels*
23
- 0 => No access, :none
24
- 30 => Developer access, :developer
25
- 40 => Maintainer access, :maintainer
26
- 60 => Admin access, :admin
22
+ **Valid access levels**
23
+
24
+ - 0, :none => No access
25
+ - 30, :developer => Developer access
26
+ - 40, :maintainer => Maintainer access
27
+ - 60, :admin => Admin access
27
28
 
28
29
  DOC
29
30
  end
@@ -0,0 +1,29 @@
1
+ # Top namespace
2
+ module LabClient
3
+ # Specifics
4
+ class ProtectedEnvironments < Common
5
+ doc 'List' do
6
+ desc 'Gets a list of protected environmentes from a project. [Project ID, String]'
7
+ example 'client.protected_environments.list(36)'
8
+ result '[#<ProtectedEnvironment name: prod>]'
9
+
10
+ markdown <<~DOC
11
+ Search: You can use ^term and term$ to find environmentes that begin and end with term respectively.
12
+ DOC
13
+ end
14
+
15
+ doc 'List' do
16
+ desc 'via Project'
17
+ example <<~DOC
18
+ project = client.projects.show(264)
19
+ project.protected_environments
20
+ DOC
21
+ end
22
+
23
+ def list(project_id)
24
+ project_id = format_id(project_id)
25
+
26
+ client.request(:get, "projects/#{project_id}/protected_environments", ProtectedEnvironment)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,53 @@
1
+ # Top namespace
2
+ module LabClient
3
+ # Specifics
4
+ class ProtectedEnvironments < Common
5
+ doc 'Protect' do
6
+ desc 'Protects a single environment [Project ID, Hash]'
7
+ example <<~DOC
8
+ client.protected_environments.protect(36,
9
+ name: :prod,
10
+ deploy_access_levels: [
11
+ { access_level: :developer }
12
+ ]
13
+ )
14
+ DOC
15
+ result '#<ProtectedEnvironment name: prod>'
16
+
17
+ markdown <<~DOC
18
+ | Attribute | Type | Required | Description |
19
+ | -------------------- | -------------- | -------- | ---------------------------------------------------------------------------------------------------------------- |
20
+ | name | string | yes | The name of the environment. |
21
+ | deploy_access_levels | array | yes | Array of access levels allowed to deploy, with each described by a hash. |
22
+
23
+ Elements in the deploy_access_levels array should take the form {user_id: integer}, {group_id: integer} or {access_level: integer}. Each user must have access to the project and each group must have this project shared.
24
+
25
+ **Valid access levels**
26
+
27
+ | Access Level | Values |
28
+ | ------------ | --------------- |
29
+ | Developer | 30, :developer |
30
+ | Maintainer | 40, :maintainer |
31
+ | Admin | 60, :admin |
32
+
33
+ DOC
34
+ end
35
+
36
+ doc 'Protect' do
37
+ desc 'via Project'
38
+ example <<~DOC
39
+ project = client.projects.show(264)
40
+ project.protect_environment(name: :other, push_access_level: :admin)
41
+ DOC
42
+ end
43
+
44
+ def protect(project_id, query)
45
+ query[:deploy_access_levels].each do |access_level|
46
+ protected_query_access_level(access_level, :access_level)
47
+ end
48
+
49
+ project_id = format_id(project_id)
50
+ client.request(:post, "projects/#{project_id}/protected_environments", ProtectedEnvironment, query)
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,22 @@
1
+ # Top namespace
2
+ module LabClient
3
+ # Inspect Helper
4
+ class ProtectedEnvironment < Klass
5
+ include ClassHelpers
6
+ def inspect
7
+ "#<ProtectedEnvironment name: #{name}>"
8
+ end
9
+
10
+ def unprotect
11
+ project_id = collect_project_id
12
+
13
+ client.protected_environments.unprotect(project_id, name)
14
+ end
15
+
16
+ help do
17
+ subtitle 'ProjectEnvironment'
18
+ option 'project', 'Show Project'
19
+ option 'unprotect', 'Remove protected environment'
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,24 @@
1
+ # Top namespace
2
+ module LabClient
3
+ # Specifics
4
+ class ProtectedEnvironments < Common
5
+ doc 'Show' do
6
+ desc 'Gets a single protected environment [Project ID, ProtectedEnvironment]'
7
+ example 'client.protected_environments.show(36, :prod)'
8
+ result '#<ProtectedEnvironment name: prod>'
9
+ end
10
+
11
+ doc 'Show' do
12
+ desc 'via Project'
13
+ example <<~DOC
14
+ project = client.projects.show(264)
15
+ project.protected_environment(:master)
16
+ DOC
17
+ end
18
+
19
+ def show(project_id, environment_id)
20
+ project_id = format_id(project_id)
21
+ client.request(:get, "projects/#{project_id}/protected_environments/#{environment_id}", ProtectedEnvironment)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,31 @@
1
+ # Top namespace
2
+ module LabClient
3
+ # Specifics
4
+ class ProtectedEnvironments < Common
5
+ doc 'Unprotect' do
6
+ desc 'Unprotects the given protected environment [Project ID, ProtectedEnvironment]'
7
+ example 'client.protected_environments.unprotect(264, :prod)'
8
+ end
9
+
10
+ doc 'Unprotect' do
11
+ desc 'via Project'
12
+ example <<~DOC
13
+ project = client.projects.show(264)
14
+ project.unprotect_environment(:other)
15
+ DOC
16
+ end
17
+
18
+ doc 'Unprotect' do
19
+ desc 'via ProtectedEnvironment'
20
+ example <<~DOC
21
+ protected_env = client.protected_environments.show(36, :prod)
22
+ protected_env.unprotect
23
+ DOC
24
+ end
25
+
26
+ def unprotect(project_id, environment_id)
27
+ project_id = format_id(project_id)
28
+ client.request(:delete, "projects/#{project_id}/protected_environments/#{environment_id}")
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,62 @@
1
+ # Top namespace
2
+ module LabClient
3
+ # Inspect Helper
4
+ class Membership < Klass
5
+ include ClassHelpers
6
+ include AccessLevel
7
+
8
+ def inspect
9
+ "#<Membership name: #{source_name}, access: #{level}>"
10
+ end
11
+
12
+ def parent
13
+ case source_type
14
+ when 'Project'
15
+ client.projects.show(source_id)
16
+ when 'Namespace'
17
+ client.groups.show(source_id)
18
+ end
19
+ end
20
+
21
+ def level
22
+ human_access_level(access_level)
23
+ end
24
+
25
+ def guest?
26
+ level == :guest
27
+ end
28
+
29
+ def reporter?
30
+ level == :reporter
31
+ end
32
+
33
+ def developer?
34
+ level == :developer
35
+ end
36
+
37
+ def maintainer?
38
+ level == :maintainer
39
+ end
40
+
41
+ def owner?
42
+ level == :owner
43
+ end
44
+
45
+ def greater_than(leveler)
46
+ case leveler
47
+ when Symbol
48
+ access_level > machine_access_level(leveler)
49
+ when Integer
50
+ access_level > leveler
51
+ end
52
+ end
53
+
54
+ help do
55
+ subtitle 'Membership'
56
+ option 'level', 'Humanized symbol of access level. e.g. :developer'
57
+ option 'parent', 'Collect project/namespace for this membership'
58
+ option '<permission>?', 'True/False evaluation each guest?, developer? etc'
59
+ option 'greater_than', 'True/False if user has greater than [Permission Name]'
60
+ end
61
+ end
62
+ end
@@ -7,7 +7,9 @@ module LabClient
7
7
  desc 'Lists all projects and groups a user is a member of. [User ID, Type]'
8
8
 
9
9
  markdown <<~DOC
10
- Filter memberships by type. Can be either Project or Namespace
10
+ | Attribute | Type | Required | Description |
11
+ | --------- | ------ | -------- | -------------------------------------------------------------- |
12
+ | type | string | no | Filter memberships by type. Can be either Project or Namespace |
11
13
  DOC
12
14
 
13
15
  example 'client.users.memberships(1)'
@@ -26,9 +28,12 @@ module LabClient
26
28
  DOC
27
29
  end
28
30
 
29
- def memberships(user_id, type = 'Project')
31
+ def memberships(user_id, type = nil)
30
32
  user_id = format_id(user_id)
31
- client.request(:get, "users/#{user_id}/memberships", nil, { from: type })
33
+
34
+ query = nil
35
+ query = { type: type } if type
36
+ client.request(:get, "users/#{user_id}/memberships", Membership, query)
32
37
  end
33
38
  end
34
39
  end
@@ -101,7 +101,7 @@ module LabClient
101
101
  client.impersonation_tokens.show(id, token_id)
102
102
  end
103
103
 
104
- def memberships(type = 'Project')
104
+ def memberships(type = nil)
105
105
  client.users.memberships(id, type)
106
106
  end
107
107
 
@@ -1,3 +1,3 @@
1
1
  module LabClient
2
- VERSION = '0.1.3'.freeze
2
+ VERSION = '0.1.4'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: labclient
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Davin Walker
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-15 00:00:00.000000000 Z
11
+ date: 2020-07-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -766,6 +766,11 @@ files:
766
766
  - lib/labclient/protected_branches/protect.rb
767
767
  - lib/labclient/protected_branches/show.rb
768
768
  - lib/labclient/protected_branches/unprotect.rb
769
+ - lib/labclient/protected_environments/list.rb
770
+ - lib/labclient/protected_environments/protect.rb
771
+ - lib/labclient/protected_environments/protected_environment.rb
772
+ - lib/labclient/protected_environments/show.rb
773
+ - lib/labclient/protected_environments/unprotect.rb
769
774
  - lib/labclient/protected_tags/list.rb
770
775
  - lib/labclient/protected_tags/protect.rb
771
776
  - lib/labclient/protected_tags/show.rb
@@ -860,6 +865,7 @@ files:
860
865
  - lib/labclient/users/keys/list.rb
861
866
  - lib/labclient/users/keys/show.rb
862
867
  - lib/labclient/users/list.rb
868
+ - lib/labclient/users/membership.rb
863
869
  - lib/labclient/users/memberships.rb
864
870
  - lib/labclient/users/search.rb
865
871
  - lib/labclient/users/show.rb