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.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +295 -0
- data/CHANGELOG.md +83 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/LICENSE.txt +21 -0
- data/README.md +340 -0
- data/Rakefile +12 -0
- data/docs/API_REFERENCE.md +512 -0
- data/docs/EXAMPLES.md +665 -0
- data/docs/GETTING_STARTED.md +340 -0
- data/lib/gophish/base.rb +206 -0
- data/lib/gophish/configuration.rb +5 -0
- data/lib/gophish/group.rb +72 -0
- data/lib/gophish/version.rb +5 -0
- data/lib/gophish-ruby.rb +18 -0
- data/sig/gophish/ruby.rbs +6 -0
- metadata +137 -0
@@ -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
|
+
```
|