gophish-ruby 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,512 @@
1
+ # API Reference
2
+
3
+ This document provides detailed API reference for the Gophish Ruby SDK.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Configuration](#configuration)
8
+ - [Base Class](#base-class)
9
+ - [Group Class](#group-class)
10
+ - [Error Handling](#error-handling)
11
+ - [Examples](#examples)
12
+
13
+ ## Configuration
14
+
15
+ The `Gophish::Configuration` class manages all SDK configuration settings.
16
+
17
+ ### Class: `Gophish::Configuration`
18
+
19
+ #### Attributes
20
+
21
+ | Attribute | Type | Description | Default |
22
+ |-----------|------|-------------|---------|
23
+ | `url` | String | Base URL of the Gophish server | `nil` |
24
+ | `api_key` | String | API authentication key | `nil` |
25
+ | `verify_ssl` | Boolean | Enable SSL certificate verification | `true` |
26
+ | `debug_output` | Boolean | Enable HTTP debug output | `false` |
27
+
28
+ #### Usage
29
+
30
+ ```ruby
31
+ # Block configuration (recommended)
32
+ Gophish.configure do |config|
33
+ config.url = "https://gophish.example.com"
34
+ config.api_key = "your-api-key"
35
+ config.verify_ssl = true
36
+ config.debug_output = false
37
+ end
38
+
39
+ # Direct configuration
40
+ Gophish.configuration.url = "https://gophish.example.com"
41
+ Gophish.configuration.api_key = "your-api-key"
42
+
43
+ # Access configuration
44
+ puts Gophish.configuration.url
45
+ ```
46
+
47
+ ## Base Class
48
+
49
+ The `Gophish::Base` class provides common functionality for all API resources.
50
+
51
+ ### Class: `Gophish::Base`
52
+
53
+ #### Class Methods
54
+
55
+ ##### `.all`
56
+
57
+ Retrieve all resources of this type.
58
+
59
+ **Returns:** Array of resource instances
60
+
61
+ **Raises:**
62
+
63
+ - `StandardError` if API request fails
64
+
65
+ **Example:**
66
+
67
+ ```ruby
68
+ groups = Gophish::Group.all
69
+ puts "Found #{groups.length} groups"
70
+ ```
71
+
72
+ ##### `.find(id)`
73
+
74
+ Find a specific resource by ID.
75
+
76
+ **Parameters:**
77
+
78
+ - `id` (Integer) - The resource ID
79
+
80
+ **Returns:** Resource instance
81
+
82
+ **Raises:**
83
+
84
+ - `StandardError` if resource not found or API request fails
85
+
86
+ **Example:**
87
+
88
+ ```ruby
89
+ group = Gophish::Group.find(1)
90
+ puts group.name
91
+ ```
92
+
93
+ ##### `.resource_name`
94
+
95
+ Get the resource name used for API endpoints.
96
+
97
+ **Returns:** String (snake_case, dasherized)
98
+
99
+ **Example:**
100
+
101
+ ```ruby
102
+ Gophish::Group.resource_name # => "group"
103
+ ```
104
+
105
+ ##### `.resource_path`
106
+
107
+ Get the API path for this resource.
108
+
109
+ **Returns:** String (pluralized resource path)
110
+
111
+ **Example:**
112
+
113
+ ```ruby
114
+ Gophish::Group.resource_path # => "/groups"
115
+ ```
116
+
117
+ #### Instance Methods
118
+
119
+ ##### `#save`
120
+
121
+ Create or update the resource on the server.
122
+
123
+ **Returns:** Boolean (true if successful, false otherwise)
124
+
125
+ **Side Effects:**
126
+
127
+ - Sets `@persisted` to true on success
128
+ - Clears `@changed_attributes` on success
129
+ - Adds errors to `#errors` on failure
130
+
131
+ **Example:**
132
+
133
+ ```ruby
134
+ group = Gophish::Group.new(name: "Test", targets: [...])
135
+ if group.save
136
+ puts "Saved with ID: #{group.id}"
137
+ else
138
+ puts "Errors: #{group.errors.full_messages}"
139
+ end
140
+ ```
141
+
142
+ ##### `#destroy`
143
+
144
+ Delete the resource from the server.
145
+
146
+ **Returns:** Boolean (true if successful, false otherwise)
147
+
148
+ **Side Effects:**
149
+
150
+ - Sets `@persisted` to false on success
151
+ - Freezes the object on success
152
+
153
+ **Example:**
154
+
155
+ ```ruby
156
+ group = Gophish::Group.find(1)
157
+ if group.destroy
158
+ puts "Group deleted"
159
+ end
160
+ ```
161
+
162
+ ##### `#valid?`
163
+
164
+ Check if the resource passes all validations.
165
+
166
+ **Returns:** Boolean
167
+
168
+ **Side Effects:**
169
+
170
+ - Populates `#errors` with validation messages
171
+
172
+ **Example:**
173
+
174
+ ```ruby
175
+ group = Gophish::Group.new
176
+ unless group.valid?
177
+ puts group.errors.full_messages
178
+ end
179
+ ```
180
+
181
+ ##### `#persisted?`
182
+
183
+ Check if the resource is saved to the server.
184
+
185
+ **Returns:** Boolean (true if saved and has an ID)
186
+
187
+ **Example:**
188
+
189
+ ```ruby
190
+ group = Gophish::Group.new
191
+ puts group.persisted? # => false
192
+
193
+ group.save
194
+ puts group.persisted? # => true (if save successful)
195
+ ```
196
+
197
+ ##### `#new_record?`
198
+
199
+ Check if the resource is new (not yet saved).
200
+
201
+ **Returns:** Boolean (opposite of `#persisted?`)
202
+
203
+ **Example:**
204
+
205
+ ```ruby
206
+ group = Gophish::Group.new
207
+ puts group.new_record? # => true
208
+ ```
209
+
210
+ ##### `#changed_attributes`
211
+
212
+ Get array of attribute names that have changed.
213
+
214
+ **Returns:** Array of Strings
215
+
216
+ **Example:**
217
+
218
+ ```ruby
219
+ group = Gophish::Group.find(1)
220
+ group.name = "New Name"
221
+ puts group.changed_attributes # => ["name"]
222
+ ```
223
+
224
+ ##### `#attribute_changed?(attr)`
225
+
226
+ Check if a specific attribute has changed.
227
+
228
+ **Parameters:**
229
+
230
+ - `attr` (String|Symbol) - Attribute name
231
+
232
+ **Returns:** Boolean
233
+
234
+ **Example:**
235
+
236
+ ```ruby
237
+ group = Gophish::Group.find(1)
238
+ group.name = "New Name"
239
+ puts group.attribute_changed?(:name) # => true
240
+ puts group.attribute_changed?("targets") # => false
241
+ ```
242
+
243
+ ##### `#attribute_was(attr)`
244
+
245
+ Get the previous value of a changed attribute.
246
+
247
+ **Parameters:**
248
+
249
+ - `attr` (String|Symbol) - Attribute name
250
+
251
+ **Returns:** Previous value or nil
252
+
253
+ **Example:**
254
+
255
+ ```ruby
256
+ group = Gophish::Group.find(1)
257
+ original_name = group.name
258
+ group.name = "New Name"
259
+ puts group.attribute_was(:name) # => original_name
260
+ ```
261
+
262
+ ## Group Class
263
+
264
+ The `Gophish::Group` class represents a target group in Gophish.
265
+
266
+ ### Class: `Gophish::Group < Gophish::Base`
267
+
268
+ #### Attributes
269
+
270
+ | Attribute | Type | Required | Description |
271
+ |-----------|------|----------|-------------|
272
+ | `id` | Integer | No | Unique group identifier (set by server) |
273
+ | `name` | String | Yes | Group name |
274
+ | `modified_date` | String | No | Last modification timestamp (set by server) |
275
+ | `targets` | Array | Yes | Array of target hashes |
276
+
277
+ #### Target Structure
278
+
279
+ Each target in the `targets` array must have:
280
+
281
+ | Field | Type | Required | Description |
282
+ |-------|------|----------|-------------|
283
+ | `first_name` | String | Yes | Target's first name |
284
+ | `last_name` | String | Yes | Target's last name |
285
+ | `email` | String | Yes | Valid email address |
286
+ | `position` | String | Yes | Job position/title |
287
+
288
+ #### Validations
289
+
290
+ - `name` must be present
291
+ - `targets` must be present and be an Array
292
+ - Each target must be a Hash with required fields
293
+ - Each target's email must have valid format
294
+
295
+ #### Instance Methods
296
+
297
+ ##### `#import_csv(csv_data)`
298
+
299
+ Import targets from CSV data.
300
+
301
+ **Parameters:**
302
+
303
+ - `csv_data` (String) - CSV data with headers: "First Name", "Last Name", "Email", "Position"
304
+
305
+ **Returns:** Void
306
+
307
+ **Side Effects:**
308
+
309
+ - Replaces current `targets` array with imported data
310
+
311
+ **Example:**
312
+
313
+ ```ruby
314
+ csv_data = <<~CSV
315
+ First Name,Last Name,Email,Position
316
+ John,Doe,john@example.com,Manager
317
+ Jane,Smith,jane@example.com,Developer
318
+ CSV
319
+
320
+ group = Gophish::Group.new(name: "Team")
321
+ group.import_csv(csv_data)
322
+ puts group.targets.length # => 2
323
+ ```
324
+
325
+ #### Usage Examples
326
+
327
+ ##### Create a Group
328
+
329
+ ```ruby
330
+ group = Gophish::Group.new(
331
+ name: "Marketing Team",
332
+ targets: [
333
+ {
334
+ first_name: "Alice",
335
+ last_name: "Johnson",
336
+ email: "alice@company.com",
337
+ position: "Marketing Manager"
338
+ },
339
+ {
340
+ first_name: "Bob",
341
+ last_name: "Wilson",
342
+ email: "bob@company.com",
343
+ position: "Marketing Coordinator"
344
+ }
345
+ ]
346
+ )
347
+
348
+ if group.save
349
+ puts "Group created with ID: #{group.id}"
350
+ end
351
+ ```
352
+
353
+ ##### Update a Group
354
+
355
+ ```ruby
356
+ group = Gophish::Group.find(1)
357
+ group.name = "Updated Marketing Team"
358
+
359
+ # Add new target
360
+ group.targets << {
361
+ first_name: "Carol",
362
+ last_name: "Brown",
363
+ email: "carol@company.com",
364
+ position: "Marketing Intern"
365
+ }
366
+
367
+ group.save
368
+ ```
369
+
370
+ ##### Import from CSV
371
+
372
+ ```ruby
373
+ csv_content = File.read("targets.csv")
374
+ group = Gophish::Group.new(name: "Imported Group")
375
+ group.import_csv(csv_content)
376
+ group.save
377
+ ```
378
+
379
+ ## Error Handling
380
+
381
+ ### Validation Errors
382
+
383
+ Validation errors are stored in the `errors` object (ActiveModel::Errors):
384
+
385
+ ```ruby
386
+ group = Gophish::Group.new(name: "", targets: [])
387
+
388
+ unless group.valid?
389
+ puts "Validation failed:"
390
+ group.errors.full_messages.each { |msg| puts " - #{msg}" }
391
+
392
+ # Check specific field errors
393
+ if group.errors[:name].any?
394
+ puts "Name errors: #{group.errors[:name]}"
395
+ end
396
+ end
397
+ ```
398
+
399
+ ### API Errors
400
+
401
+ API errors are handled and added to the errors collection:
402
+
403
+ ```ruby
404
+ group = Gophish::Group.new(name: "Test", targets: [...])
405
+
406
+ unless group.save
407
+ puts "Save failed:"
408
+ group.errors.full_messages.each { |msg| puts " - #{msg}" }
409
+ end
410
+ ```
411
+
412
+ ### Network Errors
413
+
414
+ Network-level errors raise exceptions:
415
+
416
+ ```ruby
417
+ begin
418
+ group = Gophish::Group.find(999) # Non-existent ID
419
+ rescue StandardError => e
420
+ puts "API Error: #{e.message}"
421
+ end
422
+ ```
423
+
424
+ ## Examples
425
+
426
+ ### Complete Workflow Example
427
+
428
+ ```ruby
429
+ require 'gophish-ruby'
430
+
431
+ # Configure the SDK
432
+ Gophish.configure do |config|
433
+ config.url = "https://localhost:3333"
434
+ config.api_key = "your-api-key"
435
+ config.verify_ssl = false
436
+ config.debug_output = true
437
+ end
438
+
439
+ # Create a new group
440
+ group = Gophish::Group.new(
441
+ name: "Security Training Group",
442
+ targets: []
443
+ )
444
+
445
+ # Import targets from CSV
446
+ csv_data = <<~CSV
447
+ First Name,Last Name,Email,Position
448
+ John,Doe,john@example.com,Manager
449
+ Jane,Smith,jane@example.com,Developer
450
+ Bob,Johnson,bob@example.com,Analyst
451
+ CSV
452
+
453
+ group.import_csv(csv_data)
454
+
455
+ # Validate before saving
456
+ if group.valid?
457
+ if group.save
458
+ puts "✓ Group created successfully!"
459
+ puts " ID: #{group.id}"
460
+ puts " Name: #{group.name}"
461
+ puts " Targets: #{group.targets.length}"
462
+ else
463
+ puts "✗ Failed to save group:"
464
+ group.errors.full_messages.each { |msg| puts " - #{msg}" }
465
+ end
466
+ else
467
+ puts "✗ Group validation failed:"
468
+ group.errors.full_messages.each { |msg| puts " - #{msg}" }
469
+ end
470
+
471
+ # List all groups
472
+ puts "\nAll groups:"
473
+ Gophish::Group.all.each do |g|
474
+ puts " #{g.id}: #{g.name} (#{g.targets.length} targets)"
475
+ end
476
+ ```
477
+
478
+ ### Error Recovery Example
479
+
480
+ ```ruby
481
+ # Robust error handling
482
+ def create_group_safely(name, csv_data)
483
+ group = Gophish::Group.new(name: name)
484
+
485
+ begin
486
+ group.import_csv(csv_data)
487
+ rescue CSV::MalformedCSVError => e
488
+ puts "CSV parsing failed: #{e.message}"
489
+ return false
490
+ end
491
+
492
+ unless group.valid?
493
+ puts "Validation failed: #{group.errors.full_messages.join(', ')}"
494
+ return false
495
+ end
496
+
497
+ unless group.save
498
+ puts "Save failed: #{group.errors.full_messages.join(', ')}"
499
+ return false
500
+ end
501
+
502
+ puts "Group '#{name}' created successfully with ID #{group.id}"
503
+ true
504
+ rescue StandardError => e
505
+ puts "Unexpected error: #{e.message}"
506
+ false
507
+ end
508
+
509
+ # Usage
510
+ csv_data = File.read("team.csv")
511
+ create_group_safely("Development Team", csv_data)
512
+ ```