diff --git a/docs/built_in_transformers/standard_transformers/index.md b/docs/built_in_transformers/standard_transformers/index.md index ccd1ce68..29882003 100644 --- a/docs/built_in_transformers/standard_transformers/index.md +++ b/docs/built_in_transformers/standard_transformers/index.md @@ -40,13 +40,7 @@ Standard transformers are ready-to-use methods that require no customization and 1. [RandomCCNumber](random_cc_number.md) — generates a random credit card number. 1. [RandomCurrency](random_currency.md) — generates a random currency code. 1. [RandomAmountWithCurrency](random_amount_with_currency.md) — generates a random monetary amount with currency. -1. [RandomName](random_name.md) — generates a full random name. -1. [RandomLastName](random_last_name.md) — generates a random last name. -1. [RandomFirstName](random_first_name.md) — generates a random first name. -1. [RandomFirstNameMale](random_first_name_male.md) — generates a random male first name. -1. [RandomFirstNameFemale](random_first_name_female.md) — generates a random female first name. -1. [RandomTitleMale](random_title_male.md) — generates a random male title. -1. [RandomTitleFemale](random_title_female.md) — generates a random female title. +1. [RandomPerson](random_person.md) — generates a random person data (first name, last name, etc.) 1. [RandomPhoneNumber](random_phone_number.md) — generates a random phone number. 1. [RandomTollFreePhoneNumber](random_toll_free_phone_number.md) — generates a random toll-free phone number. 1. [RandomE164PhoneNumber](random_e164_phone_number.md) — generates a random phone number in E.164 format. diff --git a/docs/built_in_transformers/standard_transformers/random_first_name.md b/docs/built_in_transformers/standard_transformers/random_first_name.md deleted file mode 100644 index f184e7f7..00000000 --- a/docs/built_in_transformers/standard_transformers/random_first_name.md +++ /dev/null @@ -1,28 +0,0 @@ -The `RandomFirstName` transformer is designed to populate specified database columns with random first names. This tool is indispensable for applications requiring the simulation of user profiles, testing user registration systems, or anonymizing user data in datasets. - -## Parameters - -| Name | Description | Default | Required | Supported DB types | -|------------|------------------------------------------------------|---------|----------|--------------------| -| column | The name of the column to be affected | | Yes | text, varchar | -| keep_null | Indicates whether NULL values should be preserved | `false` | No | - | - -## Description - -The `RandomFirstName` transformer utilizes a comprehensive list of first names to inject random first names into the designated database column. This feature allows for the creation of diverse and realistic user profiles by simulating a variety of first names without using real user data. - -## Example: Populate random first names for the `user_profiles` table - -This example demonstrates configuring the `RandomFirstName` transformer to populate the `first_name` column in the `user_profiles` table with random first names. It is an effective method for simulating a variety of user profiles with diverse first names. - -```yaml title="RandomFirstName transformer example" -- schema: "public" - name: "user_profiles" - transformers: - - name: "RandomFirstName" - params: - column: "first_name" - keep_null: false -``` - -In this configuration, the `first_name` column will be updated with random first names for each user profile entry, replacing any existing non-NULL values. If the `keep_null` parameter is set to `true`, existing NULL values in the column will be preserved, ensuring the integrity of records where first name information is not applicable or provided. diff --git a/docs/built_in_transformers/standard_transformers/random_first_name_female.md b/docs/built_in_transformers/standard_transformers/random_first_name_female.md deleted file mode 100644 index 0921a2e6..00000000 --- a/docs/built_in_transformers/standard_transformers/random_first_name_female.md +++ /dev/null @@ -1,28 +0,0 @@ -The `RandomFirstNameFemale` transformer is designed to populate specified database columns with random female first names. This tool is crucial for applications requiring the simulation of user profiles, testing gender-specific features, or anonymizing user data in datasets while focusing on female names. - -## Parameters - -| Name | Description | Default | Required | Supported DB types | -|------------|------------------------------------------------------|---------|----------|--------------------| -| column | The name of the column to be affected | | Yes | text, varchar | -| keep_null | Indicates whether NULL values should be preserved | `false` | No | - | - -## Description - -The `RandomFirstNameFemale` transformer utilizes a comprehensive list of female first names to inject random female first names into the designated database column. This feature allows for the creation of diverse and realistic user profiles with a focus on female names without using real user data. - -## Example: Populate random female first names for the `user_profiles` table - -This example demonstrates configuring the `RandomFirstNameFemale` transformer to populate the `first_name` column in the `user_profiles` table with random female first names. It is an effective method for simulating a variety of user profiles with diverse female first names. - -```yaml title="RandomFirstNameFemale transformer example" -- schema: "public" - name: "user_profiles" - transformers: - - name: "RandomFirstNameFemale" - params: - column: "first_name" - keep_null: false -``` - -In this configuration, the `first_name` column will be updated with random female first names for each user profile entry, replacing any existing non-NULL values. If the `keep_null` parameter is set to `true`, existing NULL values in the column will be preserved, ensuring the integrity of records where female first name information is not applicable or provided. diff --git a/docs/built_in_transformers/standard_transformers/random_first_name_male.md b/docs/built_in_transformers/standard_transformers/random_first_name_male.md deleted file mode 100644 index fc25b1fc..00000000 --- a/docs/built_in_transformers/standard_transformers/random_first_name_male.md +++ /dev/null @@ -1,28 +0,0 @@ -The `RandomFirstNameMale` transformer is developed to populate specified database columns with random male first names. This tool is essential for applications requiring the simulation of user profiles, testing gender-specific features, or anonymizing user data in datasets while focusing on male names. - -## Parameters - -| Name | Description | Default | Required | Supported DB types | -|------------|------------------------------------------------------|---------|----------|---------------------| -| column | The name of the column to be affected | | Yes | text, varchar | -| keep_null | Indicates whether NULL values should be preserved | `false` | No | - | - -## Description - -The `RandomFirstNameMale` transformer utilizes a comprehensive list of male first names to inject random male first names into the designated database column. This feature allows for the creation of diverse and realistic user profiles with a focus on male names without using real user data. - -## Example: Populate random male first names for the `user_profiles` table - -This example demonstrates configuring the `RandomFirstNameMale` transformer to populate the `first_name` column in the `user_profiles` table with random male first names. It is an effective method for simulating a variety of user profiles with diverse male first names. - -```yaml title="RandomFirstNameMale transformer example" -- schema: "public" - name: "user_profiles" - transformers: - - name: "RandomFirstNameMale" - params: - column: "first_name" - keep_null: false -``` - -In this configuration, the `first_name` column will be updated with random male first names for each user profile entry, replacing any existing non-NULL values. If the `keep_null` parameter is set to `true`, existing NULL values in the column will be preserved, ensuring the integrity of records where male first name information is not applicable or provided. diff --git a/docs/built_in_transformers/standard_transformers/random_last_name.md b/docs/built_in_transformers/standard_transformers/random_last_name.md deleted file mode 100644 index 8fd8aba9..00000000 --- a/docs/built_in_transformers/standard_transformers/random_last_name.md +++ /dev/null @@ -1,28 +0,0 @@ -The `RandomLastName` transformer is developed to populate specified database columns with random last names. This tool is essential for applications requiring the simulation of user profiles, testing user registration systems, or anonymizing user data in datasets. - -## Parameters - -| Name | Description | Default | Required | Supported DB types | -|------------|------------------------------------------------------|---------|----------|--------------------| -| column | The name of the column to be affected | | Yes | text, varchar | -| keep_null | Indicates whether NULL values should be preserved | `false` | No | - | - -## Description - -The `RandomLastName` transformer utilizes a comprehensive list of last names to inject random last names into the designated database column. This feature allows for the creation of diverse and realistic user profiles by simulating a variety of last names without using real user data. - -## Example: Populate random last names for the `user_profiles` table - -This example demonstrates configuring the `RandomLastName` transformer to populate the `last_name` column in the `user_profiles` table with random last names. It is an effective method for simulating a variety of user profiles with diverse last names. - -```yaml title="RandomLastName transformer example" -- schema: "public" - name: "user_profiles" - transformers: - - name: "RandomLastName" - params: - column: "last_name" - keep_null: false -``` - -In this configuration, the `last_name` column will be updated with random last names for each user profile entry, replacing any existing non-NULL values. If the `keep_null` parameter is set to `true`, existing NULL values in the column will be preserved, ensuring the integrity of records where last name information is not applicable or provided. diff --git a/docs/built_in_transformers/standard_transformers/random_name.md b/docs/built_in_transformers/standard_transformers/random_name.md deleted file mode 100644 index e2e86fbd..00000000 --- a/docs/built_in_transformers/standard_transformers/random_name.md +++ /dev/null @@ -1,28 +0,0 @@ -The `RandomName` transformer is designed to populate specified database columns with random full names, including both first names and last names. This tool is indispensable for applications requiring the simulation of user profiles, testing user registration systems, or anonymizing user data in datasets. - -## Parameters - -| Name | Description | Default | Required | Supported DB types | -|------------|------------------------------------------------------|---------|----------|--------------------| -| column | The name of the column to be affected | | Yes | text, varchar | -| keep_null | Indicates whether NULL values should be preserved | `false` | No | - | - -## Description - -The `RandomName` transformer utilizes a comprehensive list of first names and last names to inject random full names into the designated database column. This feature allows for the creation of diverse and realistic user profiles by simulating a variety of full names without using real user data. - -## Example: Populate random full names for the `user_profiles` table - -This example demonstrates configuring the `RandomName` transformer to populate the name column in the `user_profiles` table with random full names. It is an effective method for simulating a variety of user profiles with diverse full names. - -```yaml title="RandomName transformer example" -- schema: "public" - name: "user_profiles" - transformers: - - name: "RandomName" - params: - column: "name" - keep_null: false -``` - -In this configuration, the `name` column will be updated with random full names for each user profile entry, replacing any existing non-NULL values. If the `keep_null` parameter is set to `true`, existing NULL values in the column will be preserved, ensuring the integrity of records where full name information is not applicable or provided. diff --git a/docs/built_in_transformers/standard_transformers/random_person.md b/docs/built_in_transformers/standard_transformers/random_person.md new file mode 100644 index 00000000..69099326 --- /dev/null +++ b/docs/built_in_transformers/standard_transformers/random_person.md @@ -0,0 +1,121 @@ +The `RandomPerson` transformer is designed to populate specified database columns with personal attributes such as +first name, last name, title and gender. + +## Parameters + +| Name | Description | Default | Required | Supported DB types | +|------------|------------------------------------------------------|---------|----------|--------------------| +| columns | The name of the column to be affected | | Yes | text, varchar | +| gender | set specific gender (possible values: Male, Female, Any) | `Any` | No | - | +| gender_mapping | Specify gender name to possible values when using dynamic mode in "gender" parameter | `Any` |No |- | +| fallback_gender | Specify fallback gender if not mapped when using dynamic mode in "gender" parameter | `Any` |No |- | +| engine | The engine used for generating the values [random, hash]. Use hash for deterministic generation | `random` |No |- | + + +## Description + +The `RandomPerson` transformer utilizes a comprehensive list of first names to inject random first names into the +designated database column. This feature allows for the creation of diverse and realistic user profiles by +simulating a variety of first names without using real user data. + + +### *column* object attributes + +* `name` — the name of the column where the personal attributes will be stored. This value is required. +* `template` - the template for the column value. +You can use the next attributes: `.FirstName`, `.LastName` or `.Title`. For example, if you want to generate a full name, you can use the next template: + `"{{ .FirstName }} {{ .LastName }}"` + +* `hashing` - the bool value. Indicates whether the column value must be passed through the hashing function. +The default value is `false`. If all column has `hashing` set to `false` (by default), then all columns will be hashed. + + +### *gender_mapping* object attributes + +`gender_mapping` - a dictionary that maps the gender value when `gender` parameters works in dynamic mode. +The default value is: + +```json +{ + "Male": [ + "male", + "M", + "m", + "man", + "Man" + ], + "Female": [ + "female", + "F", + "f", + "w", + "woman", + "Woman" + ] +} +``` + +### *fallback_gender* + +Gender that will be used if `gender_mapping` was not found. This parameter is optional +and required only for `gender` parameter in dynamic mode. The default value is `Any`. + +## Example: Populate random first name and last name for table user_profiles in static mode + +This example demonstrates how to use the `RandomPerson` transformer to populate the `name` and `surname` columns in +the `user_profiles` table with random first names, last name, respectively. + +```sql title="Create table user_profiles and insert data" + +CREATE TABLE personal_data ( + id SERIAL PRIMARY KEY, + name VARCHAR(100), + surname VARCHAR(100), + sex CHAR(1) CHECK (sex IN ('M', 'F')) +); + +-- Insert sample data into the table +INSERT INTO personal_data (name, surname, sex) VALUES + ('John', 'Doe', 'M'), + ('Jane', 'Smith', 'F'), + ('Alice', 'Johnson', 'F'), + ('Bob', 'Lee', 'M'); +``` + +```yaml title="RandomPerson transformer example" +- schema: public + name: personal_data + transformers: + - name: "RandomPerson" + params: + gender: "Any" + columns: + - name: "name" + template: "{{ .FirstName }}" + - name: "surname" + template: "{{ .LastName }}" + engine: "hash" +``` + +## Example: Populate random first name and last name for table user_profiles in dynamic mode + +This example demonstrates how to use the `RandomPerson` transformer to populate the `name`, `surname` using dynamic +gender + + +```yaml title="RandomPerson transformer example with dynamic mode" +- schema: public + name: personal_data + transformers: + - name: "RandomPerson" + params: + columns: + - name: "name" + template: "{{ .FirstName }}" + - name: "surname" + template: "{{ .LastName }}" + engine: "random" + dynamic_params: + gender: + column: sex +``` diff --git a/docs/built_in_transformers/standard_transformers/random_title_female.md b/docs/built_in_transformers/standard_transformers/random_title_female.md deleted file mode 100644 index cea669c7..00000000 --- a/docs/built_in_transformers/standard_transformers/random_title_female.md +++ /dev/null @@ -1,28 +0,0 @@ -The `RandomTitleFemale` transformer is designed to populate specified database columns with random female titles. This tool is crucial for applications that require the simulation of user profiles, testing gender-specific features, or anonymizing user data in datasets. - -## Parameters - -| Name | Description | Default | Required | Supported DB types | -|------------|-------------------------------------------------------|---------|----------|--------------------| -| column | The name of the column to be affected | | Yes | text, varchar | -| keep_null | Indicates whether NULL values should be preserved | `false` | No | - | - -## Description - -The `RandomTitleFemale` transformer utilizes a predefined list of female titles (e. g., Mrs., Dr., Prof.) to inject random female titles into the designated database column. This feature allows for the creation of diverse and realistic user profiles by simulating a variety of female titles without using real user data. - -## Example: Populate random female titles for the `user_profiles` table - -This example demonstrates configuring the `RandomTitleFemale` transformer to populate the `title` column in the `user_profiles` table with random female titles. It is an effective method for simulating a variety of user profiles with female titles. - -```yaml title="RandomTitleFemale transformer example" -- schema: "public" - name: "user_profiles" - transformers: - - name: "RandomTitleFemale" - params: - column: "title" - keep_null: false -``` - -In this configuration, the `title` column will be updated with random female titles for each user profile entry, replacing any existing non-NULL values. If the `keep_null` parameter is set to `true`, existing NULL values in the column will be preserved, ensuring the integrity of records where title information is not applicable or provided. diff --git a/docs/built_in_transformers/standard_transformers/random_title_male.md b/docs/built_in_transformers/standard_transformers/random_title_male.md deleted file mode 100644 index 59e668b3..00000000 --- a/docs/built_in_transformers/standard_transformers/random_title_male.md +++ /dev/null @@ -1,28 +0,0 @@ -The `RandomTitleMale` transformer is developed to populate specified database columns with random male titles. This tool is essential for applications that require the simulation of user profiles, testing gender-specific features, or anonymizing user data in datasets. - -## Parameters - -| Name | Description | Default | Required | Supported DB types | -|------------|-------------------------------------------------------|---------|----------|--------------------| -| column | The name of the column to be affected | | Yes | text, varchar | -| keep_null | Indicates whether NULL values should be preserved | `false` | No | - | - -## Description - -The `RandomTitleMale` transformer utilizes a predefined list of male titles (e. g., Mr., Dr., Prof.) to inject random male titles into the designated database column. This feature allows for the creation of diverse and realistic user profiles by simulating a variety of male titles without using real user data. - -## Example: Populate random male titles for the `user_profile` table - -This example outlines configuring the `RandomTitleMale` transformer to populate the `title` column in a `user_profiles` table with random male titles. It is a straightforward method for simulating a variety of user profiles with male titles. - -```yaml title="RandomTitleMale transformer example" -- schema: "public" - name: "user_profiles" - transformers: - - name: "RandomTitleMale" - params: - column: "title" - keep_null: false -``` - -In this configuration, the `title` column will be updated with random male titles for each user profile entry, replacing any existing non-NULL values. If the `keep_null` parameter is set to `true`, existing NULL values in the column will be preserved, ensuring the integrity of records where title information is not applicable or provided. diff --git a/docs/release_notes/greenmask_0_1_1.md b/docs/release_notes/greenmask_0_1_1.md index 93e0a592..71437007 100644 --- a/docs/release_notes/greenmask_0_1_1.md +++ b/docs/release_notes/greenmask_0_1_1.md @@ -8,41 +8,41 @@ Added the following new transformers: | Transformer | Description | |----------------------------------------------------------------------------------------|--------------------------------------------------| -| [RandomLatitude](../built_in_transformers/standard_transformers/random_latitude.md) | Generates a random latitude value | -| [RandomLongitude](../built_in_transformers/standard_transformers/random_longitude.md) | Generates a random longitude value | -| [RandomUnixTime](../built_in_transformers/standard_transformers/random_unix_time.md) | Generates a random Unix timestamp | -| [RandomMonthName](../built_in_transformers/standard_transformers/random_month_name.md) | Generates the name of a random month | -| [RandomYearString](../built_in_transformers/standard_transformers/random_year_string.md) | Generates a random year as a string | -| [RandomDayOfWeek](../built_in_transformers/standard_transformers/random_day_of_week.md) | Generates a random day of the week | -| [RandomDayOfMonth](../built_in_transformers/standard_transformers/random_day_of_month.md) | Generates a random day of the month | -| [RandomCentury](../built_in_transformers/standard_transformers/random_century.md) | Generates a random century | -| [RandomTimezone](../built_in_transformers/standard_transformers/random_timezone.md) | Generates a random timezone | -| [RandomEmail](../built_in_transformers/standard_transformers/random_email.md) | Generates a random email address | -| [RandomMacAddress](../built_in_transformers/standard_transformers/random_mac_address.md) | Generates a random MAC address | -| [RandomDomainName](../built_in_transformers/standard_transformers/random_domain_name.md) | Generates a random domain name | -| [RandomURL](../built_in_transformers/standard_transformers/random_url.md) | Generates a random URL | -| [RandomUsername](../built_in_transformers/standard_transformers/random_username.md) | Generates a random username | -| [RandomIPv4](../built_in_transformers/standard_transformers/random_ipv4.md) | Generates a random IPv4 address | -| [RandomIPv6](../built_in_transformers/standard_transformers/random_ipv6.md) | Generates a random IPv6 address | -| [RandomPassword](../built_in_transformers/standard_transformers/random_password.md) | Generates a random password | -| [RandomWord](../built_in_transformers/standard_transformers/random_word.md) | Generates a random word | -| [RandomSentence](../built_in_transformers/standard_transformers/random_sentence.md) | Generates a random sentence | -| [RandomParagraph](../built_in_transformers/standard_transformers/random_paragraph.md) | Generates a random paragraph | -| [RandomCCType](../built_in_transformers/standard_transformers/random_cc_type.md) | Generates a random credit card type | -| [RandomCCNumber](../built_in_transformers/standard_transformers/random_cc_number.md) | Generates a random credit card number | -| [RandomCurrency](../built_in_transformers/standard_transformers/random_currency.md) | Generates a random currency code | -| [RandomAmountWithCurrency](../built_in_transformers/standard_transformers/random_amount_with_currency.md) | Generates a random monetary amount with currency | -| [RandomTitleMale](../built_in_transformers/standard_transformers/random_title_male.md) | Generates a random title for males | -| [RandomTitleFemale](../built_in_transformers/standard_transformers/random_title_female.md) | Generates a random title for females | -| [RandomFirstName](../built_in_transformers/standard_transformers/random_first_name.md) | Generates a random first name | -| [RandomFirstNameMale](../built_in_transformers/standard_transformers/random_first_name_male.md) | Generates a random male first name | -| [RandomFirstNameFemale](../built_in_transformers/standard_transformers/random_first_name_female.md) | Generates a random female first name | -| [RandomLastName](../built_in_transformers/standard_transformers/random_last_name.md) | Generates a random last name | -| [RandomName](../built_in_transformers/standard_transformers/random_name.md) | Generates a full random name | -| [RandomPhoneNumber](../built_in_transformers/standard_transformers/random_phone_number.md) | Generates a random phone number | -| [RandomTollFreePhoneNumber](../built_in_transformers/standard_transformers/random_toll_free_phone_number.md) | Generates a random toll-free phone number | -| [RandomE164PhoneNumber](../built_in_transformers/standard_transformers/random_e164_phone_number.md) | Generates a random phone number in E.164 format | -| [RealAddress](../built_in_transformers/standard_transformers/real_address.md) | Generates a real address | +| RandomLatitude | Generates a random latitude value | +| RandomLongitude | Generates a random longitude value | +| RandomUnixTime | Generates a random Unix timestamp | +| RandomMonthName | Generates the name of a random month | +| RandomYearString | Generates a random year as a string | +| RandomDayOfWeek | Generates a random day of the week | +| RandomDayOfMonth | Generates a random day of the month | +| RandomCentury | Generates a random century | +| RandomTimezone | Generates a random timezone | +| RandomEmail | Generates a random email address | +| RandomMacAddress | Generates a random MAC address | +| RandomDomainName | Generates a random domain name | +| RandomURL | Generates a random URL | +| RandomUsername | Generates a random username | +| RandomIPv4 | Generates a random IPv4 address | +| RandomIPv6 | Generates a random IPv6 address | +| RandomPassword | Generates a random password | +| RandomWord | Generates a random word | +| RandomSentence | Generates a random sentence | +| RandomParagraph | Generates a random paragraph | +| RandomCCType | Generates a random credit card type | +| RandomCCNumber | Generates a random credit card number | +| RandomCurrency | Generates a random currency code | +| RandomAmountWithCurrency | Generates a random monetary amount with currency | +| RandomTitleMale | Generates a random title for males | +| RandomTitleFemale | Generates a random title for females | +| RandomFirstName | Generates a random first name | +| RandomFirstNameMale | Generates a random male first name | +| RandomFirstNameFemale | Generates a random female first name | +| RandomLastName | Generates a random last name | +| RandomName | Generates a full random name | +| RandomPhoneNumber | Generates a random phone number | +| RandomTollFreePhoneNumber | Generates a random toll-free phone number | +| RandomE164PhoneNumber | Generates a random phone number in E.164 format | +| RealAddress | Generates a real address | ## Assets diff --git a/internal/db/postgres/transformers/data.go b/internal/db/postgres/transformers/data.go index 9faabd0e..38a67610 100644 --- a/internal/db/postgres/transformers/data.go +++ b/internal/db/postgres/transformers/data.go @@ -1,75 +1,5 @@ package transformers -// ccTlds - countries domains -var ccTlds = []string{ - "us", // United States - "uk", // United Kingdom (commonly .uk but officially .gb is reserved) - "de", // Germany - "ca", // Canada - "fr", // France - "au", // Australia - "jp", // Japan - "cn", // China - "in", // India - "br", // Brazil - "ru", // Russia - "za", // South Africa - "nl", // Netherlands - "mx", // Mexico - "it", // Italy - "es", // Spain - "se", // Sweden - "no", // Norway - "fi", // Finland - "dk", // Denmark - "pl", // Poland - "be", // Belgium - "ch", // Switzerland - "kr", // South Korea - "sg", // Singapore - "nz", // New Zealand - "il", // Israel - "ie", // Ireland - "at", // Austria - "pt", // Portugal - "my", // Malaysia - "th", // Thailand - "ph", // Philippines - "tr", // Turkey - "id", // Indonesia - "hk", // Hong Kong - "ar", // Argentina - "cl", // Chile - "co", // Colombia - "gr", // Greece - "sa", // Saudi Arabia - "ae", // United Arab Emirates - "cy", // Cyprus -} - -var gTlds = []string{ - "com", - "org", - "net", - "int", - "edu", - "gov", - "mil", - "co", - "tv", - "xyz", - "top", - "club", - "online", - "site", - "vip", - "web", - "info", - "biz", - "cc", - "io", -} - // Predefined global variable containing a list of top email providers as a slice of strings var defaultEmailProviders = []string{ "gmail.com", // Google Gmail diff --git a/internal/db/postgres/transformers/random_faker.go b/internal/db/postgres/transformers/random_faker.go index f05bcc41..dfeba428 100644 --- a/internal/db/postgres/transformers/random_faker.go +++ b/internal/db/postgres/transformers/random_faker.go @@ -170,43 +170,6 @@ var FakerTransformersDes = map[string]*FakerTransformerDef{ Description: "Generates a random monetary amount with currency.", }, - // Faker Person - "RandomTitleMale": { - Generator: faker.TitleMale, - SupportedTypes: []string{"text", "varchar"}, - Description: "Generates a random title for males.", - }, - "RandomTitleFemale": { - Generator: faker.TitleFemale, - SupportedTypes: []string{"text", "varchar"}, - Description: "Generates a random title for females.", - }, - "RandomFirstName": { - Generator: faker.FirstName, - SupportedTypes: []string{"text", "varchar"}, - Description: "Generates a random first name.", - }, - "RandomFirstNameMale": { - Generator: faker.FirstNameMale, - SupportedTypes: []string{"text", "varchar"}, - Description: "Generates a random male first name.", - }, - "RandomFirstNameFemale": { - Generator: faker.FirstNameFemale, - SupportedTypes: []string{"text", "varchar"}, - Description: "Generates a random female first name.", - }, - "RandomLastName": { - Generator: faker.LastName, - SupportedTypes: []string{"text", "varchar"}, - Description: "Generates a random last name.", - }, - "RandomName": { - Generator: faker.Name, - SupportedTypes: []string{"text", "varchar"}, - Description: "Generates a full random name.", - }, - // Faker Phone "RandomPhoneNumber": { Generator: faker.Phonenumber, diff --git a/internal/db/postgres/transformers/random_person.go b/internal/db/postgres/transformers/random_person.go new file mode 100644 index 00000000..f3d9ef1b --- /dev/null +++ b/internal/db/postgres/transformers/random_person.go @@ -0,0 +1,334 @@ +package transformers + +import ( + "bytes" + "context" + "fmt" + "slices" + "text/template" + + "github.com/greenmaskio/greenmask/internal/db/postgres/transformers/utils" + "github.com/greenmaskio/greenmask/internal/generators/transformers" + "github.com/greenmaskio/greenmask/pkg/toolkit" +) + +const ( + randomEngineMode = iota + hashEngineMode +) + +const randomPersonAnyGender = "Any" + +var randomPersonTransformerDefinition = utils.NewTransformerDefinition( + utils.NewTransformerProperties( + "RandomPerson", + "Generate random person data (Title, FirstName, LastName, Gender)", + ), + + NewRandomNameTransformer, + + toolkit.MustNewParameterDefinition( + "columns", + "columns name", + ).SetRequired(true), + + toolkit.MustNewParameterDefinition( + "gender", + "set specific gender (possible values: Male, Female, Any)", + ).SetDynamicMode( + toolkit.NewDynamicModeProperties(). + SetCompatibleTypes("text", "varchar", "char", "bpchar"), + ).SetDefaultValue(toolkit.ParamsValue("Any")), + + toolkit.MustNewParameterDefinition( + "gender_mapping", + "Specify gender name to possible values when using dynamic mode in \"gender\" parameter", + ).SetDefaultValue(toolkit.ParamsValue(`{"Male": ["male", "M", "m", "man", "Man"], "Female": ["female", "F", "f", "w", "woman", "Woman"]}`)), + + toolkit.MustNewParameterDefinition( + "fallback_gender", + "Specify fallback gender if not mapped when using dynamic mode in \"gender\" parameter", + ).SetDefaultValue(toolkit.ParamsValue("Any")), + + // TODO: Allow user to override the default names, surnames and genders with kind of dictionary + + engineParameterDefinition, +) + +const randomPersonTransformerAllAttributes = "All" + +type randomNameColumns struct { + Name string `json:"name"` + Template string `json:"template"` + Hashing bool `json:"hashing"` + tmpl *template.Template + columnIdx int +} + +type RandomNameTransformer struct { + t *transformers.RandomPersonTransformer + columns []*randomNameColumns + gender string + fallbackGender string + affectedColumns map[int]string + dynamicMode bool + genderMapping map[string]string + genderParam toolkit.Parameterizer + // originalData is used to store original data for hash engine for further hashing + originalData []byte + engine int + buf *bytes.Buffer +} + +func NewRandomNameTransformer(ctx context.Context, driver *toolkit.Driver, parameters map[string]toolkit.Parameterizer) (utils.Transformer, toolkit.ValidationWarnings, error) { + var engine, fallbackGender string + var dynamicMode bool + var columns []*randomNameColumns + var warns toolkit.ValidationWarnings + genderMapping := make(map[string][]string) + reverseGenderMapping := make(map[string]string) + + gender := transformers.AnyGenderName + + columnsParam := parameters["columns"] + genderParam := parameters["gender"] + genderMappingParam := parameters["gender_mapping"] + engineParam := parameters["engine"] + fallbackGenderParam := parameters["fallback_gender"] + + if err := engineParam.Scan(&engine); err != nil { + return nil, nil, fmt.Errorf(`unable to scan "engine" param: %w`, err) + } + + var engineMode int + switch engine { + case randomEngineName: + engineMode = randomEngineMode + case hashEngineName: + engineMode = hashEngineMode + } + + t := transformers.NewRandomPersonTransformer(gender, nil) + + g, err := getGenerateEngine(ctx, engine, t.GetRequiredGeneratorByteLength()) + if err != nil { + return nil, nil, fmt.Errorf("unable to get generator: %w", err) + } + + if err = t.SetGenerator(g); err != nil { + return nil, nil, fmt.Errorf("unable to set generator: %w", err) + } + + attributes := t.GetDb().Attributes + + if err := columnsParam.Scan(&columns); err != nil { + return nil, nil, fmt.Errorf(`unable to scan "columns" param: %w`, err) + } + + affectedColumns, warns := validateColumnsAndSetDefault(driver, columns, engineMode, attributes) + if warns.IsFatal() { + return nil, warns, nil + } + + if genderParam.IsDynamic() { + // if we are in dynamic mode, we will get this value from the record + dynamicMode = true + } else { + if err := genderParam.Scan(&gender); err != nil { + return nil, nil, fmt.Errorf("unable to scan \"gender\" parameter: %w", err) + } + } + + if gender != "" { + warns = append(warns, randomNameTransformerValidateGender(gender, t.GetDb().Genders)...) + } + if warns.IsFatal() { + return nil, warns, nil + } + + if err := genderMappingParam.Scan(&genderMapping); err != nil { + return nil, nil, fmt.Errorf(`unable to scan "gender_mapping" param: %w`, err) + } + // generate reverse mapping for faster access + for k, v := range genderMapping { + warns = append(warns, randomNameTransformerValidateGender(k, t.GetDb().Genders)...) + for _, val := range v { + reverseGenderMapping[val] = k + } + } + if warns.IsFatal() { + return nil, warns, nil + } + + if err := fallbackGenderParam.Scan(&fallbackGender); err != nil { + return nil, nil, fmt.Errorf(`unable to scan "fallback_gender" param: %w`, err) + } + warns = append(warns, randomNameTransformerValidateGender(fallbackGender, t.GetDb().Genders)...) + + return &RandomNameTransformer{ + t: t, + gender: gender, + fallbackGender: fallbackGender, + genderMapping: reverseGenderMapping, + columns: columns, + genderParam: genderParam, + affectedColumns: affectedColumns, + dynamicMode: dynamicMode, + originalData: make([]byte, 256), + engine: engineMode, + buf: bytes.NewBuffer(nil), + }, nil, nil +} + +func (nft *RandomNameTransformer) GetAffectedColumns() map[int]string { + return nft.affectedColumns +} + +func (nft *RandomNameTransformer) Init(ctx context.Context) error { + return nil +} + +func (nft *RandomNameTransformer) Done(ctx context.Context) error { + return nil +} + +func (nft *RandomNameTransformer) Transform(ctx context.Context, r *toolkit.Record) (*toolkit.Record, error) { + gender := nft.gender + if nft.dynamicMode { + if err := nft.genderParam.Scan(&gender); err != nil { + return nil, fmt.Errorf("unable to scan \"gender\" parameter dynamically: %w", err) + } + var ok bool + gender, ok = nft.genderMapping[gender] + if !ok { + gender = nft.fallbackGender + } + } + + // if we are in hash engine mode, we need to clear buffer before filling it with new data + if nft.engine == hashEngineMode { + clear(nft.originalData) + for _, c := range nft.columns { + // we need to hash only columns that are marked for hashing + if !c.Hashing { + continue + } + rawVal, err := r.GetRawColumnValueByIdx(c.columnIdx) + if err != nil { + return nil, fmt.Errorf("unable to get raw value by idx %d: %w", c.columnIdx, err) + } + if !rawVal.IsNull { + nft.originalData = append(nft.originalData, rawVal.Data...) + } + } + } + + nameAttrs, err := nft.t.GetFullName(gender, nft.originalData) + if err != nil { + return nil, fmt.Errorf("error generating name: %w", err) + } + + for _, c := range nft.columns { + newRawVal := toolkit.NewRawValue(nil, false) + nft.buf.Reset() + err = c.tmpl.Execute(nft.buf, nameAttrs) + if err != nil { + return nil, fmt.Errorf("error executing template for column %s: %w", c.Name, err) + } + newRawVal.Data = slices.Clone(nft.buf.Bytes()) + if err = r.SetRawColumnValueByIdx(c.columnIdx, newRawVal); err != nil { + return nil, fmt.Errorf("unable to set new value for column \"%s\": %w", c.Name, err) + } + } + return r, nil +} + +func randomNameTransformerValidateGender(gender string, genders []string) toolkit.ValidationWarnings { + if !slices.Contains(genders, gender) && gender != randomPersonAnyGender { + return []*toolkit.ValidationWarning{ + toolkit.NewValidationWarning(). + SetSeverity(toolkit.ErrorValidationSeverity). + AddMeta("ParameterValue", gender). + AddMeta("AllowedValues", append(append([]string{}, genders...), randomPersonAnyGender)). + SetMsg("wrong gender name"), + } + } + return nil +} + +func validateColumnsAndSetDefault(driver *toolkit.Driver, columns []*randomNameColumns, engineMode int, attributes []string) (map[int]string, toolkit.ValidationWarnings) { + affectedColumns := make(map[int]string) + var warns toolkit.ValidationWarnings + + var hasHashingColumns bool + + for idx, c := range columns { + if c.Name == "" { + warns = append(warns, + toolkit.NewValidationWarning(). + SetSeverity(toolkit.ErrorValidationSeverity). + AddMeta("ParameterName", "columns"). + AddMeta("ListIdx", idx). + SetMsg("name is required"), + ) + continue + } + + columnIdx, _, ok := driver.GetColumnByName(c.Name) + if !ok { + warns = append(warns, toolkit.NewValidationWarning(). + SetSeverity(toolkit.ErrorValidationSeverity). + AddMeta("ParameterName", "columns"). + AddMeta("ParameterValue", c.Name). + AddMeta("ListIdx", idx). + SetMsg("column is not found")) + continue + } + affectedColumns[idx] = c.Name + c.columnIdx = columnIdx + + if c.Template == "" { + warns = append(warns, + toolkit.NewValidationWarning(). + SetSeverity(toolkit.ErrorValidationSeverity). + AddMeta("ParameterName", "columns"). + AddMeta("ListIdx", idx). + SetMsg("\"template\" parameters is required: received empty"), + ) + } + + if c.Template != "" { + tmpl, err := template.New(c.Name). + Funcs(toolkit.FuncMap()). + Parse(c.Template) + if err != nil { + warns = append(warns, toolkit.NewValidationWarning(). + SetSeverity(toolkit.ErrorValidationSeverity). + AddMeta("Error", err.Error()). + AddMeta("ParameterName", "columns"). + AddMeta("ListIdx", idx). + SetMsg("error parsing template"), + ) + continue + } + c.tmpl = tmpl + } + + // Do we need to calculate hash for this column? + if c.Hashing { + hasHashingColumns = true + } + } + + if !hasHashingColumns && engineMode != hashEngineMode { + for _, c := range columns { + c.Hashing = true + } + } + + return affectedColumns, warns +} + +func init() { + utils.DefaultTransformerRegistry.MustRegister(randomPersonTransformerDefinition) +} diff --git a/internal/db/postgres/transformers/random_person_test.go b/internal/db/postgres/transformers/random_person_test.go new file mode 100644 index 00000000..286d7cd4 --- /dev/null +++ b/internal/db/postgres/transformers/random_person_test.go @@ -0,0 +1,133 @@ +package transformers + +import ( + "context" + "slices" + "strings" + "testing" + + "github.com/greenmaskio/greenmask/internal/db/postgres/transformers/utils" + "github.com/greenmaskio/greenmask/internal/generators/transformers" + "github.com/greenmaskio/greenmask/pkg/toolkit" + "github.com/rs/zerolog/log" + "github.com/stretchr/testify/require" +) + +func TestRandomPersonTransformer_Transform_static_fullname(t *testing.T) { + + columnName := "data" + originalValue := "John Dust123" + params := map[string]toolkit.ParamsValue{ + "columns": toolkit.ParamsValue(`[{"name": "data", "template": "{{ .Title }} {{ .FirstName }} {{ .LastName }}"}]`), + "engine": toolkit.ParamsValue("random"), + "gender": toolkit.ParamsValue("Any"), + } + + driver, record := getDriverAndRecord(columnName, originalValue) + def, ok := utils.DefaultTransformerRegistry.Get("RandomPerson") + require.True(t, ok) + + transformer, warnings, err := def.Instance( + context.Background(), + driver, + params, + nil, + ) + require.NoError(t, err) + require.Empty(t, warnings) + + r, err := transformer.Transformer.Transform( + context.Background(), + record, + ) + require.NoError(t, err) + + rawVal, err := r.GetRawColumnValueByName(columnName) + require.NoError(t, err) + require.False(t, rawVal.IsNull) + log.Debug().Str("Result", string(rawVal.Data)).Msg("Generated data") + require.True(t, testStringContainsOneOfItemFromList(string(rawVal.Data), transformers.DefaultFirstNamesFemale) || testStringContainsOneOfItemFromList(string(rawVal.Data), transformers.DefaultFirstNamesMale)) + require.True(t, testStringContainsOneOfItemFromList(string(rawVal.Data), transformers.DefaultLastNames)) +} + +func TestRandomPersonTransformer_Transform_static_firstname(t *testing.T) { + + columnName := "data" + originalValue := "John Dust123" + params := map[string]toolkit.ParamsValue{ + "columns": toolkit.ParamsValue(`[{"name": "data", "template": "{{ .FirstName }}"}]`), + "engine": toolkit.ParamsValue("random"), + "gender": toolkit.ParamsValue("Any"), + } + + driver, record := getDriverAndRecord(columnName, originalValue) + def, ok := utils.DefaultTransformerRegistry.Get("RandomPerson") + require.True(t, ok) + + transformer, warnings, err := def.Instance( + context.Background(), + driver, + params, + nil, + ) + require.NoError(t, err) + require.Empty(t, warnings) + + r, err := transformer.Transformer.Transform( + context.Background(), + record, + ) + require.NoError(t, err) + + rawVal, err := r.GetRawColumnValueByName(columnName) + require.NoError(t, err) + require.False(t, rawVal.IsNull) + log.Debug().Str("Result", string(rawVal.Data)).Msg("Generated data") + totalNames := append(transformers.DefaultFirstNamesFemale, transformers.DefaultFirstNamesMale...) + require.True(t, slices.Contains(totalNames, string(rawVal.Data))) +} + +func TestRandomPersonTransformer_Transform_static_lastname(t *testing.T) { + + columnName := "data" + originalValue := "John Dust123" + params := map[string]toolkit.ParamsValue{ + "columns": toolkit.ParamsValue(`[{"name": "data", "template": "{{ .LastName }}"}]`), + "engine": toolkit.ParamsValue("random"), + "gender": toolkit.ParamsValue("Any"), + } + + driver, record := getDriverAndRecord(columnName, originalValue) + def, ok := utils.DefaultTransformerRegistry.Get("RandomPerson") + require.True(t, ok) + + transformer, warnings, err := def.Instance( + context.Background(), + driver, + params, + nil, + ) + require.NoError(t, err) + require.Empty(t, warnings) + + r, err := transformer.Transformer.Transform( + context.Background(), + record, + ) + require.NoError(t, err) + + rawVal, err := r.GetRawColumnValueByName(columnName) + require.NoError(t, err) + require.False(t, rawVal.IsNull) + log.Debug().Str("Result", string(rawVal.Data)).Msg("Generated data") + require.True(t, slices.Contains(transformers.DefaultLastNames, string(rawVal.Data))) +} + +func testStringContainsOneOfItemFromList(val string, values []string) bool { + for _, item := range values { + if strings.Contains(val, item) { + return true + } + } + return false +} diff --git a/internal/generators/transformers/random_person.go b/internal/generators/transformers/random_person.go new file mode 100644 index 00000000..ffa1fd18 --- /dev/null +++ b/internal/generators/transformers/random_person.go @@ -0,0 +1,263 @@ +package transformers + +import ( + "encoding/binary" + "fmt" + "slices" + + "github.com/greenmaskio/greenmask/internal/generators" +) + +const ( + MaleGenderName = "Male" + FemaleGenderName = "Female" + AnyGenderName = "Any" +) + +const ( + RandomFullNameTransformerFullNameMode = iota + RandomFullNameTransformerFirstNameMode + RandomFullNameTransformerSurnameMode +) + +var DefaultFirstNamesMale = []string{ + "Aaron", "Abdiel", "Abdul", "Abdullah", "Abe", "Abel", "Abelardo", "Abner", "Abraham", "Adalberto", "Adam", "Adan", "Adelbert", "Adolfo", "Adolph", "Adolphus", "Adonis", "Adrain", "Adrian", "Adriel", "Adrien", "Afton", "Agustin", "Ahmad", "Ahmed", "Aidan", "Aiden", "Akeem", "Al", "Alan", "Albert", "Alberto", "Albin", "Alden", "Alec", "Alejandrin", "Alek", "Alessandro", "Alex", "Alexander", "Alexandre", "Alexandro", "Alexie", "Alexis", "Alexys", "Alexzander", "Alf", "Alfonso", "Alfonzo", "Alford", "Alfred", "Alfredo", "Ali", "Allan", "Allen", "Alphonso", "Alvah", "Alvis", "Amani", "Amari", "Ambrose", "Americo", "Amir", "Amos", "Amparo", "Anastacio", "Anderson", "Andre", "Andres", "Andrew", "Andy", "Angel", "Angelo", "Angus", "Anibal", "Ansel", "Ansley", "Anthony", "Antone", "Antonio", "Antwan", "Antwon", "Arch", "Archibald", "Arden", "Arely", "Ari", "Aric", "Ariel", "Arjun", "Arlo", "Armand", "Armando", "Armani", "Arnaldo", "Arne", "Arno", "Arnold", "Arnoldo", "Arnulfo", "Aron", "Art", "Arthur", "Arturo", "Arvel", "Arvid", "Ashton", "August", "Augustus", "Aurelio", "Austen", "Austin", "Austyn", "Avery", "Axel", "Ayden", + "Bailey", "Barney", "Baron", "Barrett", "Barry", "Bart", "Bartholome", "Barton", "Baylee", "Beau", "Bell", "Ben", "Benedict", "Benjamin", "Bennett", "Bennie", "Benny", "Benton", "Bernard", "Bernardo", "Bernhard", "Bernie", "Berry", "Berta", "Bertha", "Bertram", "Bertrand", "Bill", "Billy", "Blair", "Blaise", "Blake", "Blaze", "Bo", "Bobbie", "Bobby", "Boris", "Boyd", "Brad", "Braden", "Bradford", "Bradley", "Bradly", "Brady", "Braeden", "Brain", "Brando", "Brandon", "Brandt", "Brannon", "Branson", "Brant", "Braulio", "Braxton", "Brayan", "Brendan", "Brenden", "Brendon", "Brennan", "Brennon", "Brent", "Bret", "Brett", "Brian", "Brice", "Brock", "Broderick", "Brody", "Brook", "Brooks", "Brown", "Bruce", "Bryce", "Brycen", "Bryon", "Buck", "Bud", "Buddy", "Buford", "Burley", "Buster", + "Cade", "Caden", "Caesar", "Cale", "Caleb", "Camden", "Cameron", "Camren", "Camron", "Camryn", "Candelario", "Candido", "Carey", "Carleton", "Carlo", "Carlos", "Carmel", "Carmelo", "Carmine", "Carol", "Carroll", "Carson", "Carter", "Cary", "Casey", "Casimer", "Casimir", "Casper", "Ceasar", "Cecil", "Cedrick", "Celestino", "Cesar", "Chad", "Chadd", "Chadrick", "Chaim", "Chance", "Chandler", "Charles", "Charley", "Charlie", "Chase", "Chauncey", "Chaz", "Chelsey", "Chesley", "Chester", "Chet", "Chris", "Christ", "Christian", "Christop", "Christophe", "Christopher", "Cicero", "Cielo", "Clair", "Clark", "Claud", "Claude", "Clay", "Clemens", "Clement", "Cleo", "Cletus", "Cleve", "Cleveland", "Clifford", "Clifton", "Clint", "Clinton", "Clovis", "Cloyd", "Clyde", "Coby", "Cody", "Colby", "Cole", "Coleman", "Colin", "Collin", "Colt", "Colten", "Colton", "Columbus", "Conner", "Connor", "Conor", "Conrad", "Constantin", "Consuelo", "Cooper", "Corbin", "Cordelia", "Cordell", "Cornelius", "Cornell", "Cortez", "Cory", "Coty", "Coy", "Craig", "Crawford", "Cristian", "Cristina", "Cristobal", "Cristopher", "Cruz", "Cullen", "Curt", "Curtis", "Cyril", "Cyrus", + "Dagmar", "Dale", "Dallas", "Dallin", "Dalton", "Dameon", "Damian", "Damien", "Damion", "Damon", "Dan", "Dane", "D'angelo", "Dangelo", "Danial", "Danny", "Dante", "Daren", "Darian", "Darien", "Dario", "Darion", "Darius", "Daron", "Darrel", "Darrell", "Darren", "Darrick", "Darrin", "Darrion", "Darron", "Darryl", "Darwin", "Daryl", "Dashawn", "Dave", "David", "Davin", "Davion", "Davon", "Davonte", "Dawson", "Dax", "Dayne", "Dayton", "Dean", "Deangelo", "Declan", "Dedric", "Dedrick", "Dee", "Deion", "Dejon", "Dejuan", "Delaney", "Delbert", "Dell", "Delmer", "Demarco", "Demarcus", "Demario", "Demetrius", "Demond", "Denis", "Dennis", "Deon", "Deondre", "Deontae", "Deonte", "Dereck", "Derek", "Derick", "Deron", "Derrick", "Deshaun", "Deshawn", "Desmond", "Destin", "Devan", "Devante", "Deven", "Devin", "Devon", "Devonte", "Devyn", "Dewayne", "Dewitt", "Dexter", "Diamond", "Diego", "Dillan", "Dillon", "Dimitri", "Dino", "Dion", "Dock", "Domenic", "Domenick", "Domenico", "Domingo", "Dominic", "Don", "Donald", "Donato", "Donavon", "Donnell", "Donnie", "Donny", "Dorcas", "Dorian", "Doris", "Dorthy", "Doug", "Douglas", "Doyle", "Drake", "Dudley", "Duncan", "Durward", "Dustin", "Dusty", "Dwight", "Dylan", + "Earl", "Earnest", "Easter", "Easton", "Ed", "Edd", "Eddie", "Edgar", "Edgardo", "Edison", "Edmond", "Edmund", "Eduardo", "Edward", "Edwardo", "Edwin", "Efrain", "Efren", "Einar", "Eino", "Eladio", "Elbert", "Eldon", "Eldred", "Eleazar", "Eli", "Elian", "Elias", "Eliezer", "Elijah", "Eliseo", "Elliot", "Elliott", "Ellis", "Ellsworth", "Elmer", "Elmo", "Elmore", "Eloy", "Elroy", "Elton", "Elvis", "Elwin", "Elwyn", "Emanuel", "Emerald", "Emerson", "Emery", "Emil", "Emile", "Emiliano", "Emilio", "Emmanuel", "Emmet", "Emmett", "Emmitt", "Emory", "Enid", "Enoch", "Enos", "Enrico", "Enrique", "Ephraim", "Eriberto", "Eric", "Erich", "Erick", "Erik", "Erin", "Erling", "Ernest", "Ernesto", "Ernie", "Ervin", "Erwin", "Esteban", "Estevan", "Ethan", "Ethel", "Eugene", "Eusebio", "Evan", "Evans", "Everardo", "Everett", "Evert", "Ewald", "Ewell", "Ezekiel", "Ezequiel", "Ezra", + "Fabian", "Faustino", "Fausto", "Favian", "Federico", "Felipe", "Felix", "Felton", "Fermin", "Fern", "Fernando", "Ferne", "Fidel", "Filiberto", "Finn", "Flavio", "Fletcher", "Florencio", "Florian", "Floy", "Floyd", "Ford", "Forest", "Forrest", "Foster", "Francesco", "Francis", "Francisco", "Franco", "Frank", "Frankie", "Franz", "Fred", "Freddie", "Freddy", "Frederic", "Frederick", "Frederik", "Fredrick", "Fredy", "Freeman", "Friedrich", "Fritz", "Furman", + "Gabe", "Gabriel", "Gaetano", "Gage", "Gardner", "Garett", "Garfield", "Garland", "Garnet", "Garnett", "Garret", "Garrett", "Garrick", "Garrison", "Garry", "Garth", "Gaston", "Gavin", "Gay", "Gayle", "Gaylord", "Gene", "General", "Gennaro", "Geo", "Geoffrey", "George", "Geovanni", "Geovanny", "Geovany", "Gerald", "Gerard", "Gerardo", "Gerhard", "German", "Gerson", "Gianni", "Gideon", "Gilbert", "Gilberto", "Giles", "Gillian", "Gino", "Giovani", "Giovanni", "Giovanny", "Giuseppe", "Glen", "Glennie", "Godfrey", "Golden", "Gonzalo", "Gordon", "Grady", "Graham", "Grant", "Granville", "Grayce", "Grayson", "Green", "Greg", "Gregg", "Gregorio", "Gregory", "Greyson", "Griffin", "Grover", "Guido", "Guillermo", "Guiseppe", "Gunnar", "Gunner", "Gus", "Gussie", "Gust", "Gustave", "Guy", + "Hadley", "Hailey", "Hal", "Haleigh", "Haley", "Halle", "Hank", "Hans", "Hardy", "Harley", "Harmon", "Harold", "Harrison", "Harry", "Harvey", "Haskell", "Hassan", "Hayden", "Hayley", "Hazel", "Hazle", "Heber", "Hector", "Helmer", "Henderson", "Henri", "Henry", "Herbert", "Herman", "Hermann", "Herminio", "Hershel", "Hester", "Hilario", "Hilbert", "Hillard", "Hilton", "Hipolito", "Hiram", "Hobart", "Holden", "Hollis", "Horace", "Horacio", "Houston", "Howard", "Howell", "Hoyt", "Hubert", "Hudson", "Hugh", "Humberto", "Hunter", "Hyman", + "Ian", "Ibrahim", "Ignacio", "Ignatius", "Ike", "Imani", "Immanuel", "Irving", "Irwin", "Isaac", "Isac", "Isadore", "Isai", "Isaiah", "Isaias", "Isidro", "Ismael", "Isom", "Israel", "Issac", "Izaiah", + "Jabari", "Jace", "Jacey", "Jacinto", "Jack", "Jackson", "Jacques", "Jaden", "Jadon", "Jaeden", "Jaiden", "Jaime", "Jairo", "Jake", "Jakob", "Jaleel", "Jalen", "Jalon", "Jamaal", "Jamal", "Jamar", "Jamarcus", "Jamel", "Jameson", "Jamey", "Jamie", "Jamil", "Jamir", "Jamison", "Jan", "Janick", "Jaquan", "Jared", "Jaren", "Jarod", "Jaron", "Jarred", "Jarrell", "Jarret", "Jarrett", "Jarrod", "Jarvis", "Jasen", "Jasmin", "Jason", "Jasper", "Javier", "Javon", "Javonte", "Jay", "Jayce", "Jaycee", "Jayde", "Jayden", "Jaydon", "Jaylan", "Jaylen", "Jaylin", "Jaylon", "Jayme", "Jayson", "Jean", "Jed", "Jedediah", "Jedidiah", "Jeff", "Jefferey", "Jeffery", "Jeffrey", "Jeffry", "Jennings", "Jensen", "Jerad", "Jerald", "Jeramie", "Jeramy", "Jerel", "Jeremie", "Jeremy", "Jermain", "Jermey", "Jerod", "Jerome", "Jeromy", "Jerrell", "Jerrod", "Jerrold", "Jerry", "Jess", "Jesse", "Jessie", "Jessy", "Jesus", "Jett", "Jettie", "Jevon", "Jillian", "Jimmie", "Jimmy", "Jo", "Joan", "Joany", "Joaquin", "Jocelyn", "Joe", "Joel", "Joesph", "Joey", "Johan", "Johann", "Johathan", "John", "Johnathan", "Johnathon", "Johnnie", "Johnny", "Johnpaul", "Johnson", "Jon", "Jonas", "Jonatan", "Jonathan", "Jonathon", "Jordan", "Jordi", "Jordon", "Jordy", "Jordyn", "Jorge", "Jose", "Joseph", "Josh", "Joshua", "Joshuah", "Josiah", "Josue", "Jovan", "Jovani", "Jovanny", "Jovany", "Judah", "Judd", "Judge", "Judson", "Jules", "Julian", "Julien", "Julio", "Julius", "Junior", "Junius", "Justen", "Justice", "Juston", "Justus", "Justyn", "Juvenal", "Juwan", + "Kacey", "Kade", "Kaden", "Kadin", "Kale", "Kaleb", "Kaleigh", "Kaley", "Kameron", "Kamren", "Kamron", "Kamryn", "Kane", "Kareem", "Karl", "Karley", "Karson", "Kay", "Kayden", "Kayleigh", "Kayley", "Keagan", "Keanu", "Keaton", "Keegan", "Keeley", "Keenan", "Keith", "Kellen", "Kelley", "Kelton", "Kelvin", "Ken", "Kendall", "Kendrick", "Kennedi", "Kennedy", "Kenneth", "Kennith", "Kenny", "Kenton", "Kenyon", "Keon", "Keshaun", "Keshawn", "Keven", "Kevin", "Kevon", "Keyon", "Keyshawn", "Khalid", "Khalil", "Kian", "Kiel", "Kieran", "Kiley", "Kim", "King", "Kip", "Kirk", "Kobe", "Koby", "Kody", "Kolby", "Kole", "Korbin", "Korey", "Kory", "Kraig", "Kris", "Kristian", "Kristofer", "Kristoffer", "Kristopher", "Kurt", "Kurtis", "Kyle", "Kyleigh", "Kyler", + "Ladarius", "Lafayette", "Lamar", "Lambert", "Lamont", "Lance", "Landen", "Lane", "Laron", "Larry", "Larue", "Laurel", "Lavern", "Laverna", "Laverne", "Lavon", "Lawrence", "Lawson", "Layne", "Lazaro", "Lee", "Leif", "Leland", "Lemuel", "Lennie", "Lenny", "Leo", "Leon", "Leonard", "Leonardo", "Leone", "Leonel", "Leopold", "Leopoldo", "Lesley", "Lester", "Levi", "Lew", "Lewis", "Lexus", "Liam", "Lincoln", "Lindsey", "Linwood", "Lionel", "Lisandro", "Llewellyn", "Lloyd", "Logan", "Lon", "London", "Lonnie", "Lonny", "Lonzo", "Lorenz", "Lorenza", "Lorenzo", "Louie", "Louisa", "Lourdes", "Louvenia", "Lowell", "Loy", "Loyal", "Lucas", "Luciano", "Lucio", "Lucious", "Lucius", "Ludwig", "Luigi", "Luis", "Lukas", "Lula", "Luther", "Lyric", + "Mac", "Macey", "Mack", "Mackenzie", "Madisen", "Madison", "Madyson", "Magnus", "Major", "Makenna", "Malachi", "Malcolm", "Mallory", "Manley", "Manuel", "Manuela", "Marc", "Marcel", "Marcelino", "Marcellus", "Marcelo", "Marco", "Marcos", "Marcus", "Mariano", "Mario", "Mark", "Markus", "Marley", "Marlin", "Marlon", "Marques", "Marquis", "Marshall", "Martin", "Marty", "Marvin", "Mason", "Mateo", "Mathew", "Mathias", "Matt", "Matteo", "Maurice", "Mauricio", "Maverick", "Mavis", "Max", "Maxime", "Maximilian", "Maximillian", "Maximo", "Maximus", "Maxine", "Maxwell", "Maynard", "Mckenna", "Mckenzie", "Mekhi", "Melany", "Melvin", "Melvina", "Merl", "Merle", "Merlin", "Merritt", "Mervin", "Micah", "Michael", "Michale", "Micheal", "Michel", "Miguel", "Mike", "Mikel", "Milan", "Miles", "Milford", "Miller", "Milo", "Milton", "Misael", "Mitchel", "Mitchell", "Modesto", "Mohamed", "Mohammad", "Mohammed", "Moises", "Monroe", "Monserrat", "Monserrate", "Montana", "Monte", "Monty", "Morgan", "Moriah", "Morris", "Mortimer", "Morton", "Mose", "Moses", "Moshe", "Muhammad", "Murl", "Murphy", "Murray", "Mustafa", "Myles", "Myrl", "Myron", + "Napoleon", "Narciso", "Nash", "Nasir", "Nat", "Nathan", "Nathanael", "Nathanial", "Nathaniel", "Nathen", "Neal", "Ned", "Neil", "Nels", "Nelson", "Nestor", "Newell", "Newton", "Nicholas", "Nicholaus", "Nick", "Nicklaus", "Nickolas", "Nico", "Nicola", "Nicolas", "Nigel", "Nikko", "Niko", "Nikolas", "Nils", "Noah", "Noble", "Noe", "Noel", "Nolan", "Norbert", "Norberto", "Norris", "Norval", "Norwood", + "Obie", "Oda", "Odell", "Okey", "Ola", "Olaf", "Ole", "Olen", "Olin", "Oliver", "Omari", "Omer", "Oral", "Oran", "Oren", "Orin", "Orion", "Orland", "Orlando", "Orlo", "Orrin", "Orval", "Orville", "Osbaldo", "Osborne", "Oscar", "Osvaldo", "Oswald", "Oswaldo", "Otho", "Otis", "Ottis", "Otto", "Owen", + "Pablo", "Paolo", "Paris", "Parker", "Patrick", "Paul", "Paxton", "Payton", "Pedro", "Percival", "Percy", "Perry", "Pete", "Peter", "Peyton", "Philip", "Pierce", "Pierre", "Pietro", "Porter", "Presley", "Preston", "Price", "Prince", + "Quentin", "Quincy", "Quinn", "Quinten", "Quinton", + "Rafael", "Raheem", "Rahul", "Raleigh", "Ralph", "Ramiro", "Ramon", "Randal", "Randall", "Randi", "Randy", "Ransom", "Raoul", "Raphael", "Rashad", "Rashawn", "Rasheed", "Raul", "Raven", "Ray", "Raymond", "Raymundo", "Reagan", "Reece", "Reed", "Reese", "Regan", "Reggie", "Reginald", "Reid", "Reilly", "Reinhold", "Remington", "Rene", "Reuben", "Rex", "Rey", "Reyes", "Reymundo", "Reynold", "Rhett", "Rhiannon", "Ricardo", "Richard", "Richie", "Richmond", "Rick", "Rickey", "Rickie", "Ricky", "Rico", "Rigoberto", "Riley", "Robb", "Robbie", "Robert", "Roberto", "Robin", "Rocio", "Rocky", "Rod", "Roderick", "Rodger", "Rodolfo", "Rodrick", "Rodrigo", "Roel", "Rogelio", "Roger", "Rogers", "Rolando", "Rollin", "Roman", "Ron", "Ronaldo", "Ronny", "Roosevelt", "Rory", "Rosario", "Roscoe", "Rosendo", "Ross", "Rowan", "Rowland", "Roy", "Royal", "Royce", "Ruben", "Rudolph", "Rudy", "Rupert", "Russ", "Russel", "Russell", "Rusty", "Ryan", "Ryann", "Ryder", "Rylan", "Ryleigh", "Ryley", + "Sage", "Saige", "Salvador", "Salvatore", "Sam", "Samir", "Sammie", "Sammy", "Samson", "Sanford", "Santa", "Santiago", "Santino", "Santos", "Saul", "Savion", "Schuyler", "Scot", "Scottie", "Scotty", "Seamus", "Sean", "Sebastian", "Sedrick", "Selmer", "Seth", "Shad", "Shane", "Shaun", "Shawn", "Shayne", "Sheldon", "Sheridan", "Sherman", "Sherwood", "Sid", "Sidney", "Sigmund", "Sigrid", "Sigurd", "Silas", "Sim", "Simeon", "Skye", "Skylar", "Sofia", "Soledad", "Solon", "Sonny", "Spencer", "Stan", "Stanford", "Stanley", "Stanton", "Stefan", "Stephan", "Stephen", "Stephon", "Sterling", "Steve", "Stevie", "Stewart", "Stone", "Stuart", "Sven", "Sydney", "Sylvan", "Sylvester", + "Tad", "Talon", "Tanner", "Tate", "Tatum", "Taurean", "Tavares", "Taylor", "Ted", "Terence", "Terrance", "Terrell", "Terrence", "Terrill", "Terry", "Tevin", "Thad", "Thaddeus", "Theo", "Theodore", "Theron", "Thomas", "Thurman", "Tillman", "Timmothy", "Timmy", "Timothy", "Tito", "Titus", "Tobin", "Toby", "Tod", "Tom", "Tomas", "Tommie", "Toney", "Toni", "Tony", "Torey", "Torrance", "Torrey", "Toy", "Trace", "Tracey", "Travis", "Travon", "Tre", "Tremaine", "Tremayne", "Trent", "Trenton", "Trever", "Trevion", "Trevor", "Trey", "Tristian", "Tristin", "Triston", "Troy", "Trystan", "Turner", "Tyler", "Tyree", "Tyreek", "Tyrel", "Tyrell", "Tyrese", "Tyrique", "Tyshawn", "Tyson", + "Ubaldo", "Ulices", "Ulises", "Unique", "Urban", "Uriah", "Uriel", + "Valentin", "Van", "Vance", "Vaughn", "Vern", "Verner", "Vernon", "Vicente", "Victor", "Vidal", "Vince", "Vincent", "Vincenzo", "Vinnie", "Virgil", "Vito", "Vladimir", + "Wade", "Waino", "Waldo", "Walker", "Wallace", "Walter", "Walton", "Ward", "Warren", "Watson", "Waylon", "Wayne", "Webster", "Weldon", "Wellington", "Wendell", "Werner", "Westley", "Weston", "Wilber", "Wilbert", "Wilburn", "Wiley", "Wilford", "Wilfred", "Wilfredo", "Wilfrid", "Wilhelm", "Will", "Willard", "William", "Willis", "Willy", "Wilmer", "Wilson", "Wilton", "Winfield", "Winston", "Woodrow", "Wyatt", "Wyman", + "Xavier", "Xzavier", "Xander", + "Yadav", "Yogesh", "Yaatiesh", "Yaamir", + "Zachariah", "Zachary", "Zachery", "Zack", "Zackary", "Zackery", "Zakary", "Zander", "Zane", "Zechariah", "Zion", +} + +var DefaultFirstNamesFemale = []string{ + "Aaliyah", "Abagail", "Abbey", "Abbie", "Abbigail", "Abby", "Abigail", "Abigale", "Abigayle", "Ada", "Adah", "Adaline", "Addie", "Addison", "Adela", "Adele", "Adelia", "Adeline", "Adell", "Adella", "Adelle", "Aditya", "Adriana", "Adrianna", "Adrienne", "Aglae", "Agnes", "Agustina", "Aida", "Aileen", "Aimee", "Aisha", "Aiyana", "Alaina", "Alana", "Alanis", "Alanna", "Alayna", "Alba", "Alberta", "Albertha", "Albina", "Alda", "Aleen", "Alejandra", "Alena", "Alene", "Alessandra", "Alessia", "Aletha", "Alexa", "Alexandra", "Alexandrea", "Alexandria", "Alexandrine", "Alexane", "Alexanne", "Alfreda", "Alia", "Alice", "Alicia", "Alisa", "Alisha", "Alison", "Alivia", "Aliya", "Aliyah", "Aliza", "Alize", "Allene", "Allie", "Allison", "Ally", "Alta", "Althea", "Alva", "Alvena", "Alvera", "Alverta", "Alvina", "Alyce", "Alycia", "Alysa", "Alysha", "Alyson", "Alysson", "Amalia", "Amanda", "Amara", "Amaya", "Amber", "Amelia", "Amelie", "Amely", "America", "Amie", "Amina", "Amira", "Amiya", "Amy", "Amya", "Ana", "Anabel", "Anabelle", "Anahi", "Anais", "Anastasia", "Andreane", "Andreanne", "Angela", "Angelica", "Angelina", "Angeline", "Angelita", "Angie", "Anika", "Anissa", "Anita", "Aniya", "Aniyah", "Anjali", "Anna", "Annabel", "Annabell", "Annabelle", "Annalise", "Annamae", "Annamarie", "Anne", "Annetta", "Annette", "Annie", "Antoinette", "Antonetta", "Antonette", "Antonia", "Antonietta", "Antonina", "Anya", "April", "Ara", "Araceli", "Aracely", "Ardella", "Ardith", "Ariane", "Arianna", "Arielle", "Arlene", "Arlie", "Arvilla", "Aryanna", "Asa", "Asha", "Ashlee", "Ashleigh", "Ashley", "Ashly", "Ashlynn", "Ashtyn", "Asia", "Assunta", "Astrid", "Athena", "Aubree", "Aubrey", "Audie", "Audra", "Audreanne", "Audrey", "Augusta", "Augustine", "Aurelia", "Aurelie", "Aurore", "Autumn", "Ava", "Avis", "Ayana", "Ayla", "Aylin", + "Baby", "Bailee", "Barbara", "Beatrice", "Beaulah", "Bella", "Belle", "Berenice", "Bernadette", "Bernadine", "Berneice", "Bernice", "Berniece", "Bernita", "Bert", "Beryl", "Bessie", "Beth", "Bethany", "Bethel", "Betsy", "Bette", "Bettie", "Betty", "Bettye", "Beulah", "Beverly", "Bianka", "Billie", "Birdie", "Blanca", "Blanche", "Bonita", "Bonnie", "Brandi", "Brandy", "Brandyn", "Breana", "Breanna", "Breanne", "Brenda", "Brenna", "Bria", "Briana", "Brianne", "Bridget", "Bridgette", "Bridie", "Brielle", "Brigitte", "Brionna", "Brisa", "Britney", "Brittany", "Brooke", "Brooklyn", "Bryana", "Bulah", "Burdette", "Burnice", + "Caitlyn", "Caleigh", "Cali", "Calista", "Callie", "Camila", "Camilla", "Camille", "Camylle", "Candace", "Candice", "Candida", "Cara", "Carissa", "Carlee", "Carley", "Carli", "Carlie", "Carlotta", "Carmela", "Carmella", "Carmen", "Carolanne", "Carole", "Carolina", "Caroline", "Carolyn", "Carolyne", "Carrie", "Casandra", "Cassandra", "Cassandre", "Cassidy", "Cassie", "Catalina", "Caterina", "Catharine", "Catherine", "Cathrine", "Cathryn", "Cathy", "Cayla", "Cecelia", "Cecile", "Cecilia", "Celestine", "Celia", "Celine", "Chanel", "Chanelle", "Charity", "Charlene", "Charlotte", "Chasity", "Chaya", "Chelsea", "Chelsie", "Cheyanne", "Cheyenne", "Chloe", "Christa", "Christelle", "Christiana", "Christina", "Christine", "Christy", "Chyna", "Ciara", "Cierra", "Cindy", "Citlalli", "Claire", "Clara", "Clarabelle", "Clare", "Clarissa", "Claudia", "Claudie", "Claudine", "Clementina", "Clementine", "Clemmie", "Cleora", "Cleta", "Clotilde", "Colleen", "Concepcion", "Connie", "Constance", "Cora", "Coralie", "Cordia", "Cordie", "Corene", "Corine", "Corrine", "Cortney", "Courtney", "Creola", "Cristal", "Crystal", "Crystel", "Cydney", "Cynthia", + "Dahlia", "Daija", "Daisha", "Daisy", "Dakota", "Damaris", "Dana", "Dandre", "Daniela", "Daniella", "Danielle", "Danika", "Dannie", "Danyka", "Daphne", "Daphnee", "Daphney", "Darby", "Dariana", "Darlene", "Dasia", "Dawn", "Dayana", "Dayna", "Deanna", "Deborah", "Deja", "Dejah", "Delfina", "Delia", "Delilah", "Della", "Delores", "Delpha", "Delphia", "Delphine", "Delta", "Demetris", "Dena", "Desiree", "Dessie", "Destany", "Destinee", "Destiney", "Destini", "Destiny", "Diana", "Dianna", "Dina", "Dixie", "Dolly", "Dolores", "Domenica", "Dominique", "Donna", "Dora", "Dorothea", "Dorothy", "Dorris", "Dortha", "Dovie", "Drew", "Duane", "Dulce", + "Earlene", "Earline", "Earnestine", "Ebba", "Ebony", "Eda", "Eden", "Edna", "Edwina", "Edyth", "Edythe", "Effie", "Eileen", "Elaina", "Elda", "Eldora", "Eldridge", "Eleanora", "Eleanore", "Electa", "Elena", "Elenor", "Elenora", "Eleonore", "Elfrieda", "Eliane", "Elinor", "Elinore", "Elisa", "Elisabeth", "Elise", "Elisha", "Elissa", "Eliza", "Elizabeth", "Ella", "Ellen", "Ellie", "Elmira", "Elna", "Elnora", "Elody", "Eloisa", "Eloise", "Elouise", "Elsa", "Else", "Elsie", "Elta", "Elva", "Elvera", "Elvie", "Elyse", "Elyssa", "Elza", "Emelia", "Emelie", "Emely", "Emie", "Emilia", "Emilie", "Emily", "Emma", "Emmalee", "Emmanuelle", "Emmie", "Emmy", "Ena", "Enola", "Era", "Erica", "Ericka", "Erika", "Erna", "Ernestina", "Ernestine", "Eryn", "Esmeralda", "Esperanza", "Esta", "Estefania", "Estel", "Estell", "Estella", "Estelle", "Esther", "Estrella", "Etha", "Ethelyn", "Ethyl", "Ettie", "Eudora", "Eugenia", "Eula", "Eulah", "Eulalia", "Euna", "Eunice", "Eva", "Evalyn", "Evangeline", "Eve", "Eveline", "Evelyn", "Everette", "Evie", + "Fabiola", "Fae", "Fannie", "Fanny", "Fatima", "Fay", "Faye", "Felicia", "Felicita", "Felicity", "Felipa", "Filomena", "Fiona", "Flavie", "Fleta", "Flo", "Florence", "Florida", "Florine", "Flossie", "Frances", "Francesca", "Francisca", "Freda", "Frederique", "Freeda", "Freida", "Frida", "Frieda", + "Gabriella", "Gabrielle", "Gail", "Genesis", "Genevieve", "Genoveva", "Georgette", "Georgiana", "Georgianna", "Geraldine", "Gerda", "Germaine", "Gerry", "Gertrude", "Gia", "Gilda", "Gina", "Giovanna", "Gisselle", "Gladyce", "Gladys", "Glenda", "Glenna", "Gloria", "Golda", "Grace", "Gracie", "Graciela", "Gregoria", "Greta", "Gretchen", "Guadalupe", "Gudrun", "Gwen", "Gwendolyn", + "Hailee", "Hailie", "Halie", "Hallie", "Hanna", "Hannah", "Harmony", "Hassie", "Hattie", "Haven", "Haylee", "Haylie", "Heath", "Heather", "Heaven", "Heidi", "Helen", "Helena", "Helene", "Helga", "Hellen", "Heloise", "Henriette", "Hermina", "Herminia", "Herta", "Hertha", "Hettie", "Hilda", "Hildegard", "Hillary", "Hilma", "Hollie", "Holly", "Hope", "Hortense", "Hosea", "Hulda", + "Icie", "Ida", "Idell", "Idella", "Ila", "Ilene", "Iliana", "Ima", "Imelda", "Imogene", "Ines", "Irma", "Isabel", "Isabell", "Isabella", "Isabelle", "Isobel", "Itzel", "Iva", "Ivah", "Ivory", "Ivy", "Izabella", + "Jacinthe", "Jackeline", "Jackie", "Jacklyn", "Jacky", "Jaclyn", "Jacquelyn", "Jacynthe", "Jada", "Jade", "Jadyn", "Jaida", "Jailyn", "Jakayla", "Jalyn", "Jammie", "Jana", "Janae", "Jane", "Janelle", "Janessa", "Janet", "Janice", "Janie", "Janis", "Janiya", "Jannie", "Jany", "Jaquelin", "Jaqueline", "Jaunita", "Jayda", "Jayne", "Jazlyn", "Jazmin", "Jazmyn", "Jazmyne", "Jeanette", "Jeanie", "Jeanne", "Jena", "Jenifer", "Jennie", "Jennifer", "Jennyfer", "Jermaine", "Jessica", "Jessika", "Jessyca", "Jewel", "Jewell", "Joana", "Joanie", "Joanne", "Joannie", "Joanny", "Jodie", "Jody", "Joelle", "Johanna", "Jolie", "Jordane", "Josefa", "Josefina", "Josephine", "Josiane", "Josianne", "Josie", "Joy", "Joyce", "Juana", "Juanita", "Jude", "Judy", "Julia", "Juliana", "Julianne", "Julie", "Juliet", "June", "Justina", "Justine", + "Kaci", "Kacie", "Kaela", "Kaelyn", "Kaia", "Kailee", "Kailey", "Kailyn", "Kaitlin", "Kaitlyn", "Kali", "Kallie", "Kamille", "Kara", "Karelle", "Karen", "Kari", "Kariane", "Karianne", "Karina", "Karine", "Karlee", "Karli", "Karlie", "Karolann", "Kasandra", "Kasey", "Kassandra", "Katarina", "Katelin", "Katelyn", "Katelynn", "Katharina", "Katherine", "Katheryn", "Kathleen", "Kathlyn", "Kathryn", "Kathryne", "Katlyn", "Katlynn", "Katrina", "Katrine", "Kattie", "Kavon", "Kaya", "Kaycee", "Kayla", "Kaylah", "Kaylee", "Kayli", "Kaylie", "Kaylin", "Keara", "Keely", "Keira", "Kelli", "Kellie", "Kelly", "Kelsi", "Kelsie", "Kendra", "Kenna", "Kenya", "Kenyatta", "Kiana", "Kianna", "Kiara", "Kiarra", "Kiera", "Kimberly", "Kira", "Kirsten", "Kirstin", "Kitty", "Krista", "Kristin", "Kristina", "Kristy", "Krystal", "Krystel", "Krystina", "Kyla", "Kylee", "Kylie", "Kyra", + "Lacey", "Lacy", "Laila", "Laisha", "Laney", "Larissa", "Laura", "Lauren", "Laurence", "Lauretta", "Lauriane", "Laurianne", "Laurie", "Laurine", "Laury", "Lauryn", "Lavada", "Lavina", "Lavinia", "Lavonne", "Layla", "Lea", "Leann", "Leanna", "Leanne", "Leatha", "Leda", "Leila", "Leilani", "Lela", "Lelah", "Lelia", "Lempi", "Lenna", "Lenora", "Lenore", "Leola", "Leonie", "Leonor", "Leonora", "Leora", "Lera", "Leslie", "Lesly", "Lessie", "Leta", "Letha", "Letitia", "Lexi", "Lexie", "Lia", "Liana", "Libbie", "Libby", "Lila", "Lilian", "Liliana", "Liliane", "Lilla", "Lillian", "Lilliana", "Lillie", "Lilly", "Lily", "Lilyan", "Lina", "Linda", "Lindsay", "Linnea", "Linnie", "Lisa", "Lisette", "Litzy", "Liza", "Lizeth", "Lizzie", "Lois", "Lola", "Lolita", "Loma", "Lonie", "Lora", "Loraine", "Loren", "Lorena", "Lori", "Lorine", "Lorna", "Lottie", "Lou", "Loyce", "Lucie", "Lucienne", "Lucile", "Lucinda", "Lucy", "Ludie", "Lue", "Luella", "Luisa", "Lulu", "Luna", "Lupe", "Lura", "Lurline", "Luz", "Lyda", "Lydia", "Lyla", "Lynn", "Lysanne", + "Mabel", "Mabelle", "Mable", "Maci", "Macie", "Macy", "Madaline", "Madalyn", "Maddison", "Madeline", "Madelyn", "Madelynn", "Madge", "Madie", "Madilyn", "Madisyn", "Madonna", "Mae", "Maegan", "Maeve", "Mafalda", "Magali", "Magdalen", "Magdalena", "Maggie", "Magnolia", "Maia", "Maida", "Maiya", "Makayla", "Makenzie", "Malika", "Malinda", "Mallie", "Malvina", "Mandy", "Mara", "Marcelina", "Marcella", "Marcelle", "Marcia", "Margaret", "Margarete", "Margarett", "Margaretta", "Margarette", "Margarita", "Marge", "Margie", "Margot", "Margret", "Marguerite", "Maria", "Mariah", "Mariam", "Marian", "Mariana", "Mariane", "Marianna", "Marianne", "Maribel", "Marie", "Mariela", "Marielle", "Marietta", "Marilie", "Marilou", "Marilyne", "Marina", "Marion", "Marisa", "Marisol", "Maritza", "Marjolaine", "Marjorie", "Marjory", "Marlee", "Marlen", "Marlene", "Marquise", "Marta", "Martina", "Martine", "Mary", "Maryam", "Maryjane", "Maryse", "Mathilde", "Matilda", "Matilde", "Mattie", "Maud", "Maude", "Maudie", "Maureen", "Maurine", "Maxie", "Maximillia", "May", "Maya", "Maybell", "Maybelle", "Maye", "Maymie", "Mayra", "Mazie", "Mckayla", "Meagan", "Meaghan", "Meda", "Megane", "Meggie", "Meghan", "Melba", "Melisa", "Melissa", "Mellie", "Melody", "Melyna", "Melyssa", "Mercedes", "Meredith", "Mertie", "Meta", "Mia", "Micaela", "Michaela", "Michele", "Michelle", "Mikayla", "Millie", "Mina", "Minerva", "Minnie", "Miracle", "Mireille", "Mireya", "Missouri", "Misty", "Mittie", "Modesta", "Mollie", "Molly", "Mona", "Monica", "Monique", "Mossie", "Mozell", "Mozelle", "Muriel", "Mya", "Myah", "Mylene", "Myra", "Myriam", "Myrna", "Myrtice", "Myrtie", "Myrtis", "Myrtle", + "Nadia", "Nakia", "FirstName", "Nannie", "Naomi", "Naomie", "Natalia", "Natalie", "Natasha", "Nayeli", "Nedra", "Neha", "Nelda", "Nella", "Nelle", "Nellie", "Neoma", "Nettie", "Neva", "Nia", "Nichole", "Nicole", "Nicolette", "Nikita", "Nikki", "Nina", "Noelia", "Noemi", "Noemie", "Noemy", "Nola", "Nona", "Nora", "Norene", "Norma", "Nova", "Novella", "Nya", "Nyah", "Nyasia", + "Oceane", "Ocie", "Octavia", "Odessa", "Odie", "Ofelia", "Oleta", "Olga", "Ollie", "Oma", "Ona", "Onie", "Opal", "Ophelia", "Ora", "Orie", "Orpha", "Otha", "Otilia", "Ottilie", "Ova", "Ozella", + "Paige", "Palma", "Pamela", "Pansy", "Pascale", "Pasquale", "Pat", "Patience", "Patricia", "Patsy", "Pattie", "Paula", "Pauline", "Pearl", "Pearlie", "Pearline", "Peggie", "Penelope", "Petra", "Phoebe", "Phyllis", "Pink", "Pinkie", "Piper", "Polly", "Precious", "Princess", "Priscilla", "Providenci", "Prudence", + "Queen", "Queenie", + "Rachael", "Rachel", "Rachelle", "Rae", "Raegan", "Rafaela", "Rahsaan", "Raina", "Ramona", "Raphaelle", "Raquel", "Reanna", "Reba", "Rebeca", "Rebecca", "Rebeka", "Rebekah", "Reina", "Renee", "Ressie", "Reta", "Retha", "Retta", "Reva", "Reyna", "Rhea", "Rhianna", "Rhoda", "Rita", "River", "Roberta", "Robyn", "Roma", "Romaine", "Rosa", "Rosalee", "Rosalia", "Rosalind", "Rosalinda", "Rosalyn", "Rosamond", "Rosanna", "Rose", "Rosella", "Roselyn", "Rosemarie", "Rosemary", "Rosetta", "Rosie", "Rosina", "Roslyn", "Rossie", "Rowena", "Roxane", "Roxanne", "Rozella", "Rubie", "Ruby", "Rubye", "Ruth", "Ruthe", "Ruthie", "Rylee", + "Sabina", "Sabrina", "Sabryna", "Sadie", "Sadye", "Sallie", "Sally", "Salma", "Samanta", "Samantha", "Samara", "Sandra", "Sandrine", "Sandy", "Santina", "Sarah", "Sarai", "Sarina", "Sasha", "Savanah", "Savanna", "Savannah", "Scarlett", "Selena", "Selina", "Serena", "Serenity", "Shaina", "Shakira", "Shana", "Shanel", "Shanelle", "Shania", "Shanie", "Shaniya", "Shanna", "Shannon", "Shanny", "Shanon", "Shany", "Sharon", "Shawna", "Shaylee", "Shayna", "Shea", "Sheila", "Shemar", "Shirley", "Shyann", "Shyanne", "Sibyl", "Sienna", "Sierra", "Simone", "Sincere", "Sister", "Skyla", "Sonia", "Sonya", "Sophia", "Sophie", "Stacey", "Stacy", "Stefanie", "Stella", "Stephania", "Stephanie", "Stephany", "Summer", "Sunny", "Susan", "Susana", "Susanna", "Susie", "Suzanne", "Syble", "Sydnee", "Sydni", "Sydnie", "Sylvia", + "Tabitha", "Talia", "Tamara", "Tamia", "Tania", "Tanya", "Tara", "Taryn", "Tatyana", "Taya", "Teagan", "Telly", "Teresa", "Tess", "Tessie", "Thalia", "Thea", "Thelma", "Theodora", "Theresa", "Therese", "Theresia", "Thora", "Tia", "Tiana", "Tianna", "Tiara", "Tierra", "Tiffany", "Tina", "Tomasa", "Tracy", "Tressa", "Tressie", "Treva", "Trinity", "Trisha", "Trudie", "Trycia", "Twila", "Tyra", + "Una", "Ursula", + "Vada", "Valentina", "Valentine", "Valerie", "Vallie", "Vanessa", "Veda", "Velda", "Vella", "Velma", "Velva", "Vena", "Verda", "Verdie", "Vergie", "Verla", "Verlie", "Verna", "Vernice", "Vernie", "Verona", "Veronica", "Vesta", "Vicenta", "Vickie", "Vicky", "Victoria", "Vida", "Vilma", "Vincenza", "Viola", "Violet", "Violette", "Virgie", "Virginia", "Virginie", "Vita", "Viva", "Vivian", "Viviane", "Vivianne", "Vivien", "Vivienne", + "Wanda", "Wava", "Wendy", "Whitney", "Wilhelmine", "Willa", "Willie", "Willow", "Wilma", "Winifred", "Winnifred", "Winona", + "Xiu-Mei", "Xio", + "Yadira", "Yasmeen", "Yasmin", "Yasmine", "Yazmin", "Yesenia", "Yessenia", "Yolanda", "Yoshiko", "Yvette", "Yvonne", + "Zaria", "Zelda", "Zella", "Zelma", "Zena", "Zetta", "Zita", "Zoe", "Zoey", "Zoie", "Zoila", "Zola", "Zora", "Zula", +} + +var DefaultLastNames = []string{ + "Abbott", "Abernathy", "Abshire", "Adams", "Altenwerth", "Anderson", "Ankunding", "Armstrong", "Auer", "Aufderhar", + "Bahringer", "Bailey", "Balistreri", "Barrows", "Bartell", "Bartoletti", "Barton", "Bashirian", "Batz", "Bauch", "Baumbach", "Bayer", "Beahan", "Beatty", "Bechtelar", "Becker", "Bednar", "Beer", "Beier", "Berge", "Bergnaum", "Bergstrom", "Bernhard", "Bernier", "Bins", "Blanda", "Blick", "Block", "Bode", "Boehm", "Bogan", "Bogisich", "Borer", "Bosco", "Botsford", "Boyer", "Boyle", "Bradtke", "Brakus", "Braun", "Breitenberg", "Brekke", "Brown", "Bruen", "Buckridge", + "Carroll", "Carter", "Cartwright", "Casper", "Cassin", "Champlin", "Christiansen", "Cole", "Collier", "Collins", "Conn", "Connelly", "Conroy", "Considine", "Corkery", "Cormier", "Corwin", "Cremin", "Crist", "Crona", "Cronin", "Crooks", "Cruickshank", "Cummerata", "Cummings", + "Dach", "D'Amore", "Daniel", "Dare", "Daugherty", "Davis", "Deckow", "Denesik", "Dibbert", "Dickens", "Dicki", "Dickinson", "Dietrich", "Donnelly", "Dooley", "Douglas", "Doyle", "DuBuque", "Durgan", + "Ebert", "Effertz", "Eichmann", "Emard", "Emmerich", "Erdman", "Ernser", "Fadel", + "Fahey", "Farrell", "Fay", "Feeney", "Feest", "Feil", "Ferry", "Fisher", "Flatley", "Frami", "Franecki", "Friesen", "Fritsch", "Funk", + "Gaylord", "Gerhold", "Gerlach", "Gibson", "Gislason", "Gleason", "Gleichner", "Glover", "Goldner", "Goodwin", "Gorczany", "Gottlieb", "Goyette", "Grady", "Graham", "Grant", "Green", "Greenfelder", "Greenholt", "Grimes", "Gulgowski", "Gusikowski", "Gutkowski", "Gutmann", + "Haag", "Hackett", "Hagenes", "Hahn", "Haley", "Halvorson", "Hamill", "Hammes", "Hand", "Hane", "Hansen", "Harber", "Harris", "Hartmann", "Harvey", "Hauck", "Hayes", "Heaney", "Heathcote", "Hegmann", "Heidenreich", "Heller", "Herman", "Hermann", "Hermiston", "Herzog", "Hessel", "Hettinger", "Hickle", "Hilll", "Hills", "Hilpert", "Hintz", "Hirthe", "Hodkiewicz", "Hoeger", "Homenick", "Hoppe", "Howe", "Howell", "Hudson", "Huel", "Huels", "Hyatt", + "Jacobi", "Jacobs", "Jacobson", "Jakubowski", "Jaskolski", "Jast", "Jenkins", "Jerde", "Johns", "Johnson", "Johnston", "Jones", + "Kassulke", "Kautzer", "Keebler", "Keeling", "Kemmer", "Kerluke", "Kertzmann", "Kessler", "Kiehn", "Kihn", "Kilback", "King", "Kirlin", "Klein", "Kling", "Klocko", "Koch", "Koelpin", "Koepp", "Kohler", "Konopelski", "Koss", "Kovacek", "Kozey", "Krajcik", "Kreiger", "Kris", "Kshlerin", "Kub", "Kuhic", "Kuhlman", "Kuhn", "Kulas", "Kunde", "Kunze", "Kuphal", "Kutch", "Kuvalis", + "Labadie", "Lakin", "Lang", "Langosh", "Langworth", "Larkin", "Larson", "Leannon", "Lebsack", "Ledner", "Leffler", "Legros", "Lehner", "Lemke", "Lesch", "Leuschke", "Lind", "Lindgren", "Littel", "Little", "Lockman", "Lowe", "Lubowitz", "Lueilwitz", "Luettgen", "Lynch", + "Macejkovic", "Maggio", "Mann", "Mante", "Marks", "Marquardt", "Marvin", "Mayer", "Mayert", "McClure", "McCullough", "McDermott", "McGlynn", "McKenzie", "McLaughlin", "Medhurst", "Mertz", "Metz", "Miller", "Mills", "Mitchell", "Moen", "Mohr", "Monahan", "Moore", "Morar", "Morissette", "Mosciski", "Mraz", "Mueller", "Muller", "Murazik", "Murphy", "Murray", + "Nader", "Nicolas", "Nienow", "Nikolaus", "Nitzsche", "Nolan", + "Oberbrunner", "O'Connell", "O'Conner", "O'Hara", "O'Keefe", "O'Kon", "Okuneva", "Olson", "Ondricka", "O'Reilly", "Orn", "Ortiz", "Osinski", + "Pacocha", "Padberg", "Pagac", "Parisian", "Parker", "Paucek", "Pfannerstill", "Pfeffer", "Pollich", "Pouros", "Powlowski", "Predovic", "Price", "Prohaska", "Prosacco", "Purdy", + "Quigley", "Quitzon", + "Rath", "Ratke", "Rau", "Raynor", "Reichel", "Reichert", "Reilly", "Reinger", "Rempel", "Renner", "Reynolds", "Rice", "Rippin", "Ritchie", "Robel", "Roberts", "Rodriguez", "Rogahn", "Rohan", "Rolfson", "Romaguera", "Roob", "Rosenbaum", "Rowe", "Ruecker", "Runolfsdottir", "Runolfsson", "Runte", "Russel", "Rutherford", "Ryan", "Sanford", "Satterfield", "Sauer", "Sawayn", + "Schaden", "Schaefer", "Schamberger", "Schiller", "Schimmel", "Schinner", "Schmeler", "Schmidt", "Schmitt", "Schneider", "Schoen", "Schowalter", "Schroeder", "Schulist", "Schultz", "Schumm", "Schuppe", "Schuster", "Senger", "Shanahan", "Shields", "Simonis", "Sipes", "Skiles", "Smith", "Smitham", "Spencer", "Spinka", "Sporer", "Stamm", "Stanton", "Stark", "Stehr", "Steuber", "Stiedemann", "Stokes", "Stoltenberg", "Stracke", "Streich", "Stroman", "Strosin", "Swaniawski", "Swift", + "Terry", "Thiel", "Thompson", "Tillman", "Torp", "Torphy", "Towne", "Toy", "Trantow", "Tremblay", "Treutel", "Tromp", "Turcotte", "Turner", + "Ullrich", "Upton", "Vandervort", "Veum", "Volkman", "Von", "VonRueden", "Waelchi", "Walker", "Walsh", "Walter", "Ward", "Waters", "Watsica", "Weber", "Wehner", "Weimann", "Weissnat", "Welch", "West", "White", "Wiegand", "Wilderman", "Wilkinson", "Will", "Williamson", "Willms", "Windler", "Wintheiser", "Wisoky", "Wisozk", "Witting", "Wiza", "Wolf", "Wolff", "Wuckert", "Wunsch", "Wyman", + "Yost", "Yundt", "Zboncak", "Zemlak", "Ziemann", "Zieme", "Zulauf", +} + +var DefaultTitlesMale = []string{ + "Mr.", "Dr.", "Prof.", "Lord", "King", "Prince", +} +var DefaultTitlesFemale = []string{ + "Mrs.", "Ms.", "Miss", "Dr.", "Prof.", "Lady", "Queen", "Princess", +} + +type Database map[string]map[string][]string + +type PersonDatabase struct { + Db Database + Genders []string + Attributes []string + AttributesCount int +} + +func (pd *PersonDatabase) GetRandomAttribute(gender, attr string, randomIdx uint32) string { + attrs := pd.Db[gender][attr] + return attrs[randomIdx%uint32(len(attrs))] +} + +func (pd *PersonDatabase) GetRandomGender(randomIdx uint32) string { + return pd.Genders[randomIdx%uint32(len(pd.Genders))] +} + +func NewPersonalDatabase(data Database) *PersonDatabase { + uniqueAttributes := make(map[string]struct{}) + genders := make([]string, 0, len(data)) + + if data == nil { + panic("data is nil") + } + attrsCount := 0 + for gender, attributes := range data { + genders = append(genders, gender) + attrsCount = max(len(attributes), attrsCount) + for attrName := range attributes { + uniqueAttributes[attrName] = struct{}{} + } + } + + attributes := make([]string, 0, len(uniqueAttributes)) + for attrName := range uniqueAttributes { + attributes = append(attributes, attrName) + } + + slices.Sort(attributes) + + return &PersonDatabase{ + Db: data, + Attributes: attributes, + Genders: genders, + AttributesCount: attrsCount, + } +} + +var DefaultPersonMap = map[string]map[string][]string{ + MaleGenderName: { + "Title": DefaultTitlesMale, + "LastName": DefaultLastNames, + "FirstName": DefaultFirstNamesMale, + }, + FemaleGenderName: { + "Title": DefaultTitlesFemale, + "LastName": DefaultLastNames, + "FirstName": DefaultFirstNamesFemale, + }, +} + +var DefaultDb = NewPersonalDatabase(DefaultPersonMap) + +type NameAttrs struct { + FirstName string + LastName string + Gender string + Title string +} + +type RandomPersonTransformer struct { + gender string + byteLength int + generator generators.Generator + // db - mapping gender to other personal attribute + // common structure + // gender -> person_attribute -> []possible values + db *PersonDatabase + result map[string]string +} + +func NewRandomPersonTransformer(gender string, personDb Database) *RandomPersonTransformer { + + if personDb == nil { + personDb = DefaultPersonMap + } + + db := NewPersonalDatabase(personDb) + + return &RandomPersonTransformer{ + gender: gender, + // we assume 4 bytes peer attribute + 1 byte for gender + db: db, + result: make(map[string]string, db.AttributesCount), + byteLength: db.AttributesCount * 4, + } +} + +func (rpt *RandomPersonTransformer) GetDb() *PersonDatabase { + return rpt.db +} + +func (rpt *RandomPersonTransformer) GetFullName(gender string, original []byte) (map[string]string, error) { + + resBytes, err := rpt.generator.Generate(original) + if err != nil { + return nil, err + } + + genderRandIdx := resBytes[0] + gender, err = rpt.getGender(gender, genderRandIdx) + if err != nil { + return nil, err + } + + startIdx := 1 + for _, attr := range rpt.db.Attributes { + attrIdx := binary.LittleEndian.Uint32(resBytes[startIdx : startIdx+4]) + rpt.result[attr] = rpt.db.GetRandomAttribute(gender, attr, attrIdx) + startIdx += 4 + } + + return rpt.result, nil +} + +func (rpt *RandomPersonTransformer) getGender(gender string, randomGenderIdx byte) (string, error) { + if gender == "" { + gender = rpt.gender + } + + switch gender { + case MaleGenderName, FemaleGenderName: + case AnyGenderName: + gender = rpt.db.GetRandomGender(uint32(randomGenderIdx)) + default: + return "", fmt.Errorf("unable to match gender \"%s\"", gender) + } + return gender, nil +} + +func (rpt *RandomPersonTransformer) GetRequiredGeneratorByteLength() int { + return rpt.byteLength +} + +func (rpt *RandomPersonTransformer) SetGenerator(g generators.Generator) error { + if g.Size() < rpt.byteLength { + return fmt.Errorf("requested byte length (%d) higher than generator can produce (%d)", rpt.byteLength, g.Size()) + } + rpt.generator = g + return nil +} diff --git a/internal/generators/transformers/random_person_test.go b/internal/generators/transformers/random_person_test.go new file mode 100644 index 00000000..cd20180a --- /dev/null +++ b/internal/generators/transformers/random_person_test.go @@ -0,0 +1,22 @@ +package transformers + +import ( + "slices" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/greenmaskio/greenmask/internal/generators" +) + +func TestRandomNameTransformer_GetFullName(t *testing.T) { + rnt := NewRandomPersonTransformer(AnyGenderName, nil) + g := generators.NewRandomBytes(time.Now().UnixNano(), rnt.GetRequiredGeneratorByteLength()) + err := rnt.SetGenerator(g) + require.NoError(t, err) + res, err := rnt.GetFullName("", []byte{}) + require.NoError(t, err) + require.True(t, slices.Contains(DefaultFirstNamesMale, res["FirstName"]) || slices.Contains(DefaultFirstNamesFemale, res["FirstName"])) + require.True(t, slices.Contains(DefaultLastNames, res["LastName"])) +} diff --git a/mkdocs.yml b/mkdocs.yml index 336a2d99..0b5cdbe8 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -83,6 +83,7 @@ nav: - RandomPassword: built_in_transformers/standard_transformers/random_password.md - RandomMacAddress: built_in_transformers/standard_transformers/random_mac_address.md - RandomDomainName: built_in_transformers/standard_transformers/random_domain_name.md + - RandomPerson: built_in_transformers/standard_transformers/random_person.md - RandomURL: built_in_transformers/standard_transformers/random_url.md - RandomIPv4: built_in_transformers/standard_transformers/random_ipv4.md - RandomIPv6: built_in_transformers/standard_transformers/random_ipv6.md @@ -93,13 +94,6 @@ nav: - RandomCCNumber: built_in_transformers/standard_transformers/random_cc_number.md - RandomCurrency: built_in_transformers/standard_transformers/random_currency.md - RandomAmountWithCurrency: built_in_transformers/standard_transformers/random_amount_with_currency.md - - RandomName: built_in_transformers/standard_transformers/random_name.md - - RandomLastName: built_in_transformers/standard_transformers/random_last_name.md - - RandomFirstName: built_in_transformers/standard_transformers/random_first_name.md - - RandomFirstNameMale: built_in_transformers/standard_transformers/random_first_name_male.md - - RandomFirstNameFemale: built_in_transformers/standard_transformers/random_first_name_female.md - - RandomTitleMale: built_in_transformers/standard_transformers/random_title_male.md - - RandomTitleFemale: built_in_transformers/standard_transformers/random_title_female.md - RandomPhoneNumber: built_in_transformers/standard_transformers/random_phone_number.md - RandomTollFreePhoneNumber: built_in_transformers/standard_transformers/random_toll_free_phone_number.md - RandomE164PhoneNumber: built_in_transformers/standard_transformers/random_e164_phone_number.md @@ -113,9 +107,9 @@ nav: - Template: built_in_transformers/advanced_transformers/template.md - TemplateRecord: built_in_transformers/advanced_transformers/template_record.md - Custom functions: - - built_in_transformers/advanced_transformers/custom_functions/index.md - - Core custom functions: built_in_transformers/advanced_transformers/custom_functions/core_functions.md - - Faker function: built_in_transformers/advanced_transformers/custom_functions/faker_function.md + - built_in_transformers/advanced_transformers/custom_functions/index.md + - Core custom functions: built_in_transformers/advanced_transformers/custom_functions/core_functions.md + - Faker function: built_in_transformers/advanced_transformers/custom_functions/faker_function.md - Release notes: - Greenmask 0.1.13: release_notes/greenmask_0_1_13.md - Greenmask 0.1.12: release_notes/greenmask_0_1_12.md