ronin-db-activerecord 0.1.6 → 0.2.0.rc1
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 +4 -4
- data/ChangeLog.md +91 -0
- data/README.md +49 -1
- data/db/migrate/0037_add_created_at_column_to_ronin_ports_table.rb +40 -0
- data/db/migrate/0038_add_created_at_column_to_ronin_services_table.rb +40 -0
- data/db/migrate/0039_create_ronin_cert_names_table.rb +37 -0
- data/db/migrate/0040_create_ronin_cert_issuers_table.rb +52 -0
- data/db/migrate/0041_create_ronin_cert_subjects_table.rb +54 -0
- data/db/migrate/0042_create_ronin_cert_subject_alt_names_table.rb +42 -0
- data/db/migrate/0043_create_ronin_certs_table.rb +61 -0
- data/db/migrate/0044_add_cert_id_column_to_ronin_open_ports_table.rb +35 -0
- data/db/migrate/0045_create_ronin_notes_table.rb +120 -0
- data/db/migrate/0046_create_ronin_web_vulns_table.rb +61 -0
- data/db/migrate/0047_create_ronin_phone_numbers_table.rb +47 -0
- data/db/migrate/0048_create_ronin_street_addresses_table.rb +46 -0
- data/db/migrate/0049_create_ronin_people_table.rb +48 -0
- data/db/migrate/0050_create_ronin_personal_connections_table.rb +48 -0
- data/db/migrate/0051_create_ronin_personal_phone_numbers_table.rb +48 -0
- data/db/migrate/0052_create_ronin_personal_email_addresses_table.rb +45 -0
- data/db/migrate/0053_create_ronin_personal_street_addresses_table.rb +47 -0
- data/db/migrate/0054_add_type_column_to_ronin_organizations_table.rb +33 -0
- data/db/migrate/0055_add_parent_id_column_to_ronin_organizations_table.rb +43 -0
- data/db/migrate/0056_create_ronin_organization_departments_table.rb +59 -0
- data/db/migrate/0057_create_ronin_organization_members_table.rb +62 -0
- data/db/migrate/0058_create_ronin_organization_customers_table.rb +52 -0
- data/db/migrate/0059_create_ronin_organization_phone_numbers_table.rb +47 -0
- data/db/migrate/0060_create_ronin_organization_email_addresses_table.rb +45 -0
- data/db/migrate/0061_create_ronin_organization_street_addresses_table.rb +47 -0
- data/db/migrate/0062_add_source_ip_column_to_http_requests_table.rb +30 -0
- data/db/migrate/0063_create_ronin_dns_queries_table.rb +41 -0
- data/db/migrate/0064_create_ronin_dns_records_table.rb +42 -0
- data/db/migrate/0065_create_ronin_organization_host_names_table.rb +43 -0
- data/db/migrate/0066_create_ronin_organization_ip_addresses_table.rb +43 -0
- data/gemspec.yml +1 -1
- data/lib/ronin/db/address.rb +1 -1
- data/lib/ronin/db/advisory.rb +66 -1
- data/lib/ronin/db/arch.rb +1 -1
- data/lib/ronin/db/asn.rb +15 -1
- data/lib/ronin/db/cert.rb +501 -0
- data/lib/ronin/db/cert_issuer.rb +78 -0
- data/lib/ronin/db/cert_name.rb +107 -0
- data/lib/ronin/db/cert_organization.rb +127 -0
- data/lib/ronin/db/cert_subject.rb +81 -0
- data/lib/ronin/db/cert_subject_alt_name.rb +88 -0
- data/lib/ronin/db/credential.rb +10 -1
- data/lib/ronin/db/dns_query.rb +98 -0
- data/lib/ronin/db/dns_record.rb +76 -0
- data/lib/ronin/db/email_address.rb +139 -1
- data/lib/ronin/db/host_name.rb +45 -1
- data/lib/ronin/db/host_name_ip_address.rb +1 -1
- data/lib/ronin/db/http_header_name.rb +1 -1
- data/lib/ronin/db/http_query_param.rb +1 -1
- data/lib/ronin/db/http_query_param_name.rb +1 -1
- data/lib/ronin/db/http_request.rb +13 -1
- data/lib/ronin/db/http_request_header.rb +1 -1
- data/lib/ronin/db/http_response.rb +1 -1
- data/lib/ronin/db/http_response_header.rb +1 -1
- data/lib/ronin/db/ip_address.rb +46 -1
- data/lib/ronin/db/ip_address_mac_address.rb +1 -1
- data/lib/ronin/db/mac_address.rb +28 -1
- data/lib/ronin/db/migrations.rb +1 -1
- data/lib/ronin/db/model/has_name.rb +18 -1
- data/lib/ronin/db/model/has_unique_name.rb +1 -1
- data/lib/ronin/db/model/importable.rb +1 -1
- data/lib/ronin/db/model/last_scanned_at.rb +1 -1
- data/lib/ronin/db/model.rb +1 -1
- data/lib/ronin/db/models.rb +44 -2
- data/lib/ronin/db/note.rb +199 -0
- data/lib/ronin/db/open_port.rb +104 -3
- data/lib/ronin/db/organization.rb +237 -3
- data/lib/ronin/db/organization_customer.rb +73 -0
- data/lib/ronin/db/organization_department.rb +97 -0
- data/lib/ronin/db/organization_email_address.rb +66 -0
- data/lib/ronin/db/organization_host_name.rb +65 -0
- data/lib/ronin/db/organization_ip_address.rb +65 -0
- data/lib/ronin/db/organization_member.rb +158 -0
- data/lib/ronin/db/organization_phone_number.rb +66 -0
- data/lib/ronin/db/organization_street_address.rb +66 -0
- data/lib/ronin/db/os.rb +35 -1
- data/lib/ronin/db/os_guess.rb +1 -1
- data/lib/ronin/db/password.rb +84 -1
- data/lib/ronin/db/person.rb +455 -0
- data/lib/ronin/db/personal_connection.rb +110 -0
- data/lib/ronin/db/personal_email_address.rb +66 -0
- data/lib/ronin/db/personal_phone_number.rb +76 -0
- data/lib/ronin/db/personal_street_address.rb +66 -0
- data/lib/ronin/db/phone_number.rb +330 -0
- data/lib/ronin/db/port.rb +110 -1
- data/lib/ronin/db/service.rb +130 -1
- data/lib/ronin/db/service_credential.rb +1 -1
- data/lib/ronin/db/software.rb +37 -1
- data/lib/ronin/db/software_vendor.rb +1 -1
- data/lib/ronin/db/street_address.rb +340 -0
- data/lib/ronin/db/url.rb +37 -1
- data/lib/ronin/db/url_query_param.rb +1 -1
- data/lib/ronin/db/url_query_param_name.rb +9 -1
- data/lib/ronin/db/url_scheme.rb +1 -1
- data/lib/ronin/db/user_name.rb +58 -1
- data/lib/ronin/db/vulnerability.rb +1 -1
- data/lib/ronin/db/web_credential.rb +1 -1
- data/lib/ronin/db/web_vuln.rb +348 -0
- metadata +57 -2
@@ -0,0 +1,455 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-db-activerecord - ActiveRecord backend for the Ronin Database.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2022-2024 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-db-activerecord is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-db-activerecord is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with ronin-db-activerecord. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/db/model'
|
22
|
+
require 'ronin/db/model/importable'
|
23
|
+
|
24
|
+
require 'active_record'
|
25
|
+
|
26
|
+
module Ronin
|
27
|
+
module DB
|
28
|
+
#
|
29
|
+
# Represents a person.
|
30
|
+
#
|
31
|
+
# @since 0.2.0
|
32
|
+
#
|
33
|
+
class Person < ActiveRecord::Base
|
34
|
+
|
35
|
+
include Model
|
36
|
+
include Model::Importable
|
37
|
+
|
38
|
+
# @!attribute [rw] id
|
39
|
+
# The primary key of the person.
|
40
|
+
#
|
41
|
+
# @return [Integer]
|
42
|
+
attribute :id, :integer
|
43
|
+
|
44
|
+
# @!attribute [rw] full_name
|
45
|
+
# The person's full name.
|
46
|
+
#
|
47
|
+
# @return [String]
|
48
|
+
attribute :full_name, :string
|
49
|
+
validates :full_name, presence: true,
|
50
|
+
uniqueness: true,
|
51
|
+
format: {
|
52
|
+
with: /\A(?:(?:Mr|Mrs|Ms|Miss|Dr|Sir|Madam|Master|Fr|Rev|Atty)\.?\s)?(?:\p{L}+(['-]\p{L}+)?)(?:(?:\s(?:(?:(?:\p{Lu})\.?)|(?:\p{Lu}\p{L}+(?:['-]\p{L}+)?)))?\s(?:\p{L}+(?:['-]\p{L}+)?)(?:,?\s(?:Jr|Sr|II|III|IV|V|Esq|CPA|Dc|Dds|Vm|Jd|Md|Phd)\.?)?)?\z/,
|
53
|
+
message: 'must be a valid personal name'
|
54
|
+
}
|
55
|
+
|
56
|
+
# @!attribute [rw] prefix
|
57
|
+
# The person's prefix.
|
58
|
+
#
|
59
|
+
# @return [String, nil]
|
60
|
+
attribute :prefix, :string
|
61
|
+
validates :prefix, inclusion: %w[
|
62
|
+
Mr Mrs Ms Miss Dr Sir Madam Master Fr Rev Atty
|
63
|
+
],
|
64
|
+
allow_nil: true
|
65
|
+
|
66
|
+
# @!attribute [rw] first_name
|
67
|
+
# The person's first name.
|
68
|
+
#
|
69
|
+
# @return [String]
|
70
|
+
attribute :first_name, :string
|
71
|
+
validates :first_name, presence: true,
|
72
|
+
format: {
|
73
|
+
with: /\A\p{L}+(?:['-]\p{L}+)?\z/,
|
74
|
+
message: 'must be a valid first name'
|
75
|
+
}
|
76
|
+
|
77
|
+
# @!attribute [rw] middle_name
|
78
|
+
# The person's middle name.
|
79
|
+
#
|
80
|
+
# @return [String, nil]
|
81
|
+
attribute :middle_name, :string
|
82
|
+
validates :middle_name, format: {
|
83
|
+
with: /\A\p{L}+(?:['-]\p{L}+)?\z/,
|
84
|
+
message: 'must be a valid middle name'
|
85
|
+
},
|
86
|
+
allow_nil: true
|
87
|
+
|
88
|
+
# @!attribute [rw] middle_initial
|
89
|
+
# The person's middle initial.
|
90
|
+
#
|
91
|
+
# @return [String, nil]
|
92
|
+
attribute :middle_initial, :string
|
93
|
+
validates :middle_initial, presence: true,
|
94
|
+
format: {
|
95
|
+
with: /\A\p{Lu}\z/,
|
96
|
+
message: 'must be a valid middle initial'
|
97
|
+
},
|
98
|
+
allow_nil: true
|
99
|
+
|
100
|
+
# @!attribute [rw] last_name
|
101
|
+
# The person's last name.
|
102
|
+
#
|
103
|
+
# @return [String, nil]
|
104
|
+
attribute :last_name, :string
|
105
|
+
validates :last_name, format: {
|
106
|
+
with: /\A\p{L}+(?:['-]\p{L}+)?\z/,
|
107
|
+
message: 'must be a valid last name'
|
108
|
+
},
|
109
|
+
allow_nil: true
|
110
|
+
|
111
|
+
# @!attribute [rw] suffix
|
112
|
+
# The person's suffix.
|
113
|
+
#
|
114
|
+
# @return [String, nil]
|
115
|
+
attribute :suffix, :string
|
116
|
+
validates :suffix, inclusion: %w[
|
117
|
+
Jr Sr II III IV V Esq CPA Dc Dds Vm Jd Md Phd
|
118
|
+
],
|
119
|
+
allow_nil: true
|
120
|
+
|
121
|
+
# @!attribute [rw] created_at
|
122
|
+
# Tracks when the person was first created.
|
123
|
+
#
|
124
|
+
# @return [Time]
|
125
|
+
attribute :created_at, :datetime
|
126
|
+
|
127
|
+
# @!attribute [rw] personal_street_addresses
|
128
|
+
# The association of street addresses associated with the person.
|
129
|
+
#
|
130
|
+
# @return [Array<PersonalStreetAddress>]
|
131
|
+
has_many :personal_street_addresses, dependent: :destroy
|
132
|
+
|
133
|
+
# @!attribute [rw] street_addresses
|
134
|
+
# The street addresses associated with the person.
|
135
|
+
#
|
136
|
+
# @return [Array<StreetAddress>]
|
137
|
+
has_many :street_addresses, through: :personal_street_addresses
|
138
|
+
|
139
|
+
# @!attribute [rw] personal_phone_numbers
|
140
|
+
# The perons's phone numbers.
|
141
|
+
#
|
142
|
+
# @return [Array<PersonalPhoneNumber>]
|
143
|
+
has_many :personal_phone_numbers, dependent: :destroy
|
144
|
+
|
145
|
+
# @!attribute [rw] phone_numbers
|
146
|
+
# The phone numbers associated with the person.
|
147
|
+
#
|
148
|
+
# @return [Array<PhoneNumber>]
|
149
|
+
has_many :phone_numbers, through: :personal_phone_numbers
|
150
|
+
|
151
|
+
# @!attribute [rw] personal_email_addresss
|
152
|
+
# The perons's email addresses.
|
153
|
+
#
|
154
|
+
# @return [Array<PersonalEmailAddress>]
|
155
|
+
has_many :personal_email_addresses, dependent: :destroy
|
156
|
+
|
157
|
+
# @!attribute [rw] email_addresses
|
158
|
+
# The email addresses associated with the person.
|
159
|
+
#
|
160
|
+
# @return [Array<EmailAddress>]
|
161
|
+
has_many :email_addresses, through: :personal_email_addresses
|
162
|
+
|
163
|
+
# @!attribute [rw] personal_connections
|
164
|
+
# The perons's connections with other people.
|
165
|
+
#
|
166
|
+
# @return [Array<PersonalConnection>]
|
167
|
+
has_many :personal_connections, dependent: :destroy
|
168
|
+
|
169
|
+
# @!attribute [rw] connected_people
|
170
|
+
# The other people connected to the person.
|
171
|
+
#
|
172
|
+
# @return [Array<Person>]
|
173
|
+
has_many :connected_people, through: :personal_connections,
|
174
|
+
source: :other_person
|
175
|
+
|
176
|
+
# @!attribute [rw] organization_customers
|
177
|
+
# The perons's customer relationships with other organizations.
|
178
|
+
#
|
179
|
+
# @return [Array<OrganizationCustomer>]
|
180
|
+
has_many :organization_customers, class_name: 'OrganizationCustomer',
|
181
|
+
foreign_key: :customer_id,
|
182
|
+
dependent: :destroy
|
183
|
+
|
184
|
+
# @!attribute [rw] vendors
|
185
|
+
# The vendor organizations of the person.
|
186
|
+
#
|
187
|
+
# @return [Array<Organization>]
|
188
|
+
has_many :vendors, through: :organization_customers
|
189
|
+
|
190
|
+
# @!attribute [rw] notes
|
191
|
+
# The associated notes.
|
192
|
+
#
|
193
|
+
# @return [Array<Note>]
|
194
|
+
has_many :notes, dependent: :destroy
|
195
|
+
|
196
|
+
#
|
197
|
+
# Queries all people associated with the street address.
|
198
|
+
#
|
199
|
+
# @param [String] address
|
200
|
+
# The street address to search for.
|
201
|
+
#
|
202
|
+
# @return [Array<Person>]
|
203
|
+
# The people associated with the street address.
|
204
|
+
#
|
205
|
+
# @api public
|
206
|
+
#
|
207
|
+
def self.for_address(address)
|
208
|
+
joins(:street_addresses).where(street_addresses: {address: address})
|
209
|
+
end
|
210
|
+
|
211
|
+
#
|
212
|
+
# Queries all people associated with the city.
|
213
|
+
#
|
214
|
+
# @param [String] city
|
215
|
+
# The city to search for.
|
216
|
+
#
|
217
|
+
# @return [Array<Person>]
|
218
|
+
# The people associated with the city.
|
219
|
+
#
|
220
|
+
# @api public
|
221
|
+
#
|
222
|
+
def self.for_city(city)
|
223
|
+
joins(:street_addresses).where(street_addresses: {city: city})
|
224
|
+
end
|
225
|
+
|
226
|
+
#
|
227
|
+
# Queries all people associated with the state.
|
228
|
+
#
|
229
|
+
# @param [String] state
|
230
|
+
# The state to search for.
|
231
|
+
#
|
232
|
+
# @return [Array<Person>]
|
233
|
+
# The people associated with the state.
|
234
|
+
#
|
235
|
+
# @api public
|
236
|
+
#
|
237
|
+
def self.for_state(state)
|
238
|
+
joins(:street_addresses).where(street_addresses: {state: state})
|
239
|
+
end
|
240
|
+
|
241
|
+
#
|
242
|
+
# Queries all people associated with the province.
|
243
|
+
#
|
244
|
+
# @param [String] province
|
245
|
+
# The province to search for.
|
246
|
+
#
|
247
|
+
# @return [Array<Person>]
|
248
|
+
# The people associated with the province.
|
249
|
+
#
|
250
|
+
# @see for_state
|
251
|
+
#
|
252
|
+
# @api public
|
253
|
+
#
|
254
|
+
def self.for_province(province)
|
255
|
+
for_state(province)
|
256
|
+
end
|
257
|
+
|
258
|
+
#
|
259
|
+
# Queries all people associated with the zipcode.
|
260
|
+
#
|
261
|
+
# @param [String] zipcode
|
262
|
+
# The zipcode to search for.
|
263
|
+
#
|
264
|
+
# @return [Array<Person>]
|
265
|
+
# The people associated with the zipcode.
|
266
|
+
#
|
267
|
+
# @api public
|
268
|
+
#
|
269
|
+
def self.for_zipcode(zipcode)
|
270
|
+
joins(:street_addresses).where(street_addresses: {zipcode: zipcode})
|
271
|
+
end
|
272
|
+
|
273
|
+
#
|
274
|
+
# Queries all people associated with the country.
|
275
|
+
#
|
276
|
+
# @param [String] country
|
277
|
+
# The country to search for.
|
278
|
+
#
|
279
|
+
# @return [Array<Person>]
|
280
|
+
# The people associated with the country.
|
281
|
+
#
|
282
|
+
# @api public
|
283
|
+
#
|
284
|
+
def self.for_country(country)
|
285
|
+
joins(:street_addresses).where(street_addresses: {country: country})
|
286
|
+
end
|
287
|
+
|
288
|
+
#
|
289
|
+
# Queries all people with the given prefix.
|
290
|
+
#
|
291
|
+
# @param [String] prefix
|
292
|
+
# The name prefix to search for.
|
293
|
+
#
|
294
|
+
# @return [Array<Person>]
|
295
|
+
# The people with the matching {#prefix}.
|
296
|
+
#
|
297
|
+
# @api public
|
298
|
+
#
|
299
|
+
def self.with_prefix(prefix)
|
300
|
+
where(prefix: prefix)
|
301
|
+
end
|
302
|
+
|
303
|
+
#
|
304
|
+
# Queries all people with the matching first name.
|
305
|
+
#
|
306
|
+
# @param [String] first_name
|
307
|
+
# The first name to search for.
|
308
|
+
#
|
309
|
+
# @return [Array<Person>]
|
310
|
+
# The people with the matching {#first_name}.
|
311
|
+
#
|
312
|
+
# @api public
|
313
|
+
#
|
314
|
+
def self.with_first_name(first_name)
|
315
|
+
where(first_name: first_name)
|
316
|
+
end
|
317
|
+
|
318
|
+
#
|
319
|
+
# Queries all people with the matching middle name.
|
320
|
+
#
|
321
|
+
# @param [String] middle_name
|
322
|
+
# The middle name to search for.
|
323
|
+
#
|
324
|
+
# @return [Array<Person>]
|
325
|
+
# The people with the matching {#middle_name}.
|
326
|
+
#
|
327
|
+
# @api public
|
328
|
+
#
|
329
|
+
def self.with_middle_name(middle_name)
|
330
|
+
where(middle_name: middle_name)
|
331
|
+
end
|
332
|
+
|
333
|
+
#
|
334
|
+
# Queries all people with the matching middle initial.
|
335
|
+
#
|
336
|
+
# @param [String] initial
|
337
|
+
# The middle initial to search for.
|
338
|
+
#
|
339
|
+
# @return [Array<Person>]
|
340
|
+
# The people with the matching {#middle_initial}.
|
341
|
+
#
|
342
|
+
# @api public
|
343
|
+
#
|
344
|
+
def self.with_middle_initial(initial)
|
345
|
+
where(middle_initial: initial)
|
346
|
+
end
|
347
|
+
|
348
|
+
#
|
349
|
+
# Queries all people with the matching last name.
|
350
|
+
#
|
351
|
+
# @param [String] last_name
|
352
|
+
# The last name to search for.
|
353
|
+
#
|
354
|
+
# @return [Array<Person>]
|
355
|
+
# The people with the matching {#last_name}.
|
356
|
+
#
|
357
|
+
# @api public
|
358
|
+
#
|
359
|
+
def self.with_last_name(last_name)
|
360
|
+
where(last_name: last_name)
|
361
|
+
end
|
362
|
+
|
363
|
+
#
|
364
|
+
# Queries all people with the given suffix.
|
365
|
+
#
|
366
|
+
# @param [String] suffix
|
367
|
+
# The name suffix to search for.
|
368
|
+
#
|
369
|
+
# @return [Array<Person>]
|
370
|
+
# The people with the matching {#suffix}.
|
371
|
+
#
|
372
|
+
# @api public
|
373
|
+
#
|
374
|
+
def self.with_suffix(suffix)
|
375
|
+
where(suffix: suffix)
|
376
|
+
end
|
377
|
+
|
378
|
+
#
|
379
|
+
# Looks up a person by name.
|
380
|
+
#
|
381
|
+
# @param [String] name
|
382
|
+
# The person's full name to query.
|
383
|
+
#
|
384
|
+
# @return [Person, nil]
|
385
|
+
# The found person.
|
386
|
+
#
|
387
|
+
# @api public
|
388
|
+
#
|
389
|
+
def self.lookup(name)
|
390
|
+
find_by(full_name: name)
|
391
|
+
end
|
392
|
+
|
393
|
+
#
|
394
|
+
# Parses a person's full name into attributes.
|
395
|
+
#
|
396
|
+
# @param [String] name
|
397
|
+
# The person's full name to parse.
|
398
|
+
#
|
399
|
+
# @return [Hash{Symbol => String}]
|
400
|
+
# The parsed attributes.
|
401
|
+
#
|
402
|
+
# @api private
|
403
|
+
#
|
404
|
+
def self.parse(name)
|
405
|
+
if (match = name.match(/\A(?:(?<prefix>Mr|Mrs|Ms|Miss|Dr|Sir|Madam|Master|Fr|Rev|Atty)\.?\s)?(?<first_name>\p{L}+(?:['-]\p{L}+)?)(?:(?:\s(?:(?:(?<middle_initial>\p{Lu})\.?)|(?<middle_name>(?<middle_initial>\p{Lu})\p{L}+(?:['-]\p{L}+)?)))?\s(?!Jr|Sr|II|III|IV|V|Esq|CPA|Dc|Dds|Vm|Jd|Md|Phd)(?<last_name>\p{L}+(?:['-]\p{L}+)?)(?:,?\s(?<suffix>Jr|Sr|II|III|IV|V|Esq|CPA|Dc|Dds|Vm|Jd|Md|Phd)\.?)?)?\z/))
|
406
|
+
{
|
407
|
+
full_name: name,
|
408
|
+
|
409
|
+
prefix: match[:prefix],
|
410
|
+
first_name: match[:first_name],
|
411
|
+
middle_name: match[:middle_name],
|
412
|
+
middle_initial: match[:middle_initial],
|
413
|
+
last_name: match[:last_name],
|
414
|
+
suffix: match[:suffix]
|
415
|
+
}
|
416
|
+
else
|
417
|
+
raise(ArgumentError,"invalid personal name: #{name.inspect}")
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
#
|
422
|
+
# Imports a person by name.
|
423
|
+
#
|
424
|
+
# @param [String] name
|
425
|
+
# The person's full name.
|
426
|
+
#
|
427
|
+
# @return [Person]
|
428
|
+
# The imported person.
|
429
|
+
#
|
430
|
+
# @api public
|
431
|
+
#
|
432
|
+
def self.import(name)
|
433
|
+
create(parse(name))
|
434
|
+
end
|
435
|
+
|
436
|
+
#
|
437
|
+
# Converts the person into a String.
|
438
|
+
#
|
439
|
+
# @return [String]
|
440
|
+
# The person's full name.
|
441
|
+
#
|
442
|
+
def to_s
|
443
|
+
full_name
|
444
|
+
end
|
445
|
+
|
446
|
+
end
|
447
|
+
end
|
448
|
+
end
|
449
|
+
|
450
|
+
require 'ronin/db/personal_street_address'
|
451
|
+
require 'ronin/db/personal_phone_number'
|
452
|
+
require 'ronin/db/personal_connection'
|
453
|
+
require 'ronin/db/organization_customer'
|
454
|
+
require 'ronin/db/organization'
|
455
|
+
require 'ronin/db/note'
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-db-activerecord - ActiveRecord backend for the Ronin Database.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2022-2024 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-db-activerecord is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-db-activerecord is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with ronin-db-activerecord. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/db/model'
|
22
|
+
require 'ronin/db/model/importable'
|
23
|
+
|
24
|
+
require 'active_record'
|
25
|
+
|
26
|
+
module Ronin
|
27
|
+
module DB
|
28
|
+
#
|
29
|
+
# Represents a connection between two {Person}s.
|
30
|
+
#
|
31
|
+
# @since 0.2.0
|
32
|
+
#
|
33
|
+
class PersonalConnection < ActiveRecord::Base
|
34
|
+
|
35
|
+
include Model
|
36
|
+
|
37
|
+
# NOTE: disable STI so we can use the type column as an enum.
|
38
|
+
self.inheritance_column = nil
|
39
|
+
|
40
|
+
# @!attribute [rw] id
|
41
|
+
# The primary key of the friendship.
|
42
|
+
#
|
43
|
+
# @return [Integer]
|
44
|
+
attribute :id, :integer
|
45
|
+
|
46
|
+
# @!attribute [rw] type
|
47
|
+
# The type of the connection.
|
48
|
+
#
|
49
|
+
# @return [String, nil]
|
50
|
+
enum :type, {
|
51
|
+
friend: 'friend',
|
52
|
+
collegue: 'collegue',
|
53
|
+
coworker: 'coworker',
|
54
|
+
|
55
|
+
parent: 'parent',
|
56
|
+
mother: 'mother',
|
57
|
+
father: 'father',
|
58
|
+
aunt: 'aunt',
|
59
|
+
uncle: 'uncle',
|
60
|
+
brother: 'brother',
|
61
|
+
sister: 'sister',
|
62
|
+
cousin: 'cousin',
|
63
|
+
nephew: 'nephew',
|
64
|
+
niece: 'niece',
|
65
|
+
|
66
|
+
stepmother: 'stepmother',
|
67
|
+
stepfather: 'stepfather',
|
68
|
+
stepchild: 'stepchild',
|
69
|
+
stepbrother: 'stepbrother',
|
70
|
+
stepsister: 'stepsister',
|
71
|
+
|
72
|
+
in_law: 'in-law',
|
73
|
+
father_in_law: 'father-in-law',
|
74
|
+
mother_in_law: 'mother-in-law',
|
75
|
+
|
76
|
+
partner: 'partner',
|
77
|
+
boyfriend: 'boyfriend',
|
78
|
+
girlfriend: 'girlfriend',
|
79
|
+
hushband: 'husband',
|
80
|
+
wife: 'wife',
|
81
|
+
|
82
|
+
ex: 'ex',
|
83
|
+
ex_husband: 'ex-husband',
|
84
|
+
ex_wife: 'ex-wife'
|
85
|
+
}, prefix: 'is_'
|
86
|
+
|
87
|
+
# @!attribute [rw] person
|
88
|
+
# The person who is befriending the other person.
|
89
|
+
#
|
90
|
+
# @return [Person]
|
91
|
+
belongs_to :person
|
92
|
+
|
93
|
+
# @!attribute [rw] friend
|
94
|
+
# The friend of the {#person}.
|
95
|
+
#
|
96
|
+
# @return [Person]
|
97
|
+
belongs_to :other_person, class_name: 'Person'
|
98
|
+
validates :other_person, uniqueness: {scope: [:person, :type]}
|
99
|
+
|
100
|
+
# @!attribute [rw] created_at
|
101
|
+
# Tracks when the friendship was created.
|
102
|
+
#
|
103
|
+
# @return [Time]
|
104
|
+
attribute :created_at, :datetime
|
105
|
+
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
require 'ronin/db/person'
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-db-activerecord - ActiveRecord backend for the Ronin Database.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2022-2024 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-db-activerecord is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-db-activerecord is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with ronin-db-activerecord. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/db/model'
|
22
|
+
|
23
|
+
require 'active_record'
|
24
|
+
|
25
|
+
module Ronin
|
26
|
+
module DB
|
27
|
+
#
|
28
|
+
# Represents an email address associated with a {Person}.
|
29
|
+
#
|
30
|
+
# @since 0.2.0
|
31
|
+
#
|
32
|
+
class PersonalEmailAddress < ActiveRecord::Base
|
33
|
+
|
34
|
+
include Model
|
35
|
+
|
36
|
+
# @!attribute [rw] id
|
37
|
+
# Primary key of the personal email address.
|
38
|
+
#
|
39
|
+
# @return [Integer]
|
40
|
+
attribute :id, :integer
|
41
|
+
|
42
|
+
# @!attribute [rw] person
|
43
|
+
# The perons.
|
44
|
+
#
|
45
|
+
# @return [Person]
|
46
|
+
belongs_to :person
|
47
|
+
|
48
|
+
# @!attribute [rw] email_address
|
49
|
+
# The email address associated with the person.
|
50
|
+
#
|
51
|
+
# @return [EmailAddress]
|
52
|
+
belongs_to :email_address
|
53
|
+
validates :email_address, uniqueness: {scope: :person_id}
|
54
|
+
|
55
|
+
# @!attribute [r] created_at
|
56
|
+
# Tracks when the personal email address was first created.
|
57
|
+
#
|
58
|
+
# @return [Time]
|
59
|
+
attribute :created_at, :datetime
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
require 'ronin/db/person'
|
66
|
+
require 'ronin/db/email_address'
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-db-activerecord - ActiveRecord backend for the Ronin Database.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2022-2024 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-db-activerecord is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-db-activerecord is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with ronin-db-activerecord. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/db/model'
|
22
|
+
require 'ronin/db/model/importable'
|
23
|
+
|
24
|
+
require 'active_record'
|
25
|
+
|
26
|
+
module Ronin
|
27
|
+
module DB
|
28
|
+
#
|
29
|
+
# Represents a {PhoneNumber} that belongs to a {Person}.
|
30
|
+
#
|
31
|
+
# @since 0.2.0
|
32
|
+
#
|
33
|
+
class PersonalPhoneNumber < ActiveRecord::Base
|
34
|
+
|
35
|
+
include Model
|
36
|
+
|
37
|
+
# NOTE: disable STI so we can use the type column as an enum.
|
38
|
+
self.inheritance_column = nil
|
39
|
+
|
40
|
+
# @!attribute [rw] id
|
41
|
+
# The primary key of the personal phone number.
|
42
|
+
#
|
43
|
+
# @return [Integer]
|
44
|
+
attribute :id, :integer
|
45
|
+
|
46
|
+
# @!attribute [rw] type
|
47
|
+
# The type of the phone number.
|
48
|
+
#
|
49
|
+
# @return ["home", "cell", "fax", "voip", nil]
|
50
|
+
enum :type, {home: 'home', cell: 'cell', fax: 'fax', voip: 'voip'}
|
51
|
+
|
52
|
+
# @!attribute [rw] person
|
53
|
+
# The person who owns the phone number.
|
54
|
+
#
|
55
|
+
# @return [Person]
|
56
|
+
belongs_to :person
|
57
|
+
|
58
|
+
# @!attribute [rw] phone_number
|
59
|
+
# The phone number.
|
60
|
+
#
|
61
|
+
# @return [PhoneNumber]
|
62
|
+
belongs_to :phone_number
|
63
|
+
validates :phone_number, uniqueness: {scope: [:type, :person_id]}
|
64
|
+
|
65
|
+
# @!attribute [rw] created_at
|
66
|
+
# Tracks when the personal phone number was created.
|
67
|
+
#
|
68
|
+
# @return [Time]
|
69
|
+
attribute :created_at, :datetime
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
require 'ronin/db/person'
|
76
|
+
require 'ronin/db/phone_number'
|