> For the complete documentation index, see [llms.txt](https://goldenore.gitbook.io/goldenore-cdc/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://goldenore.gitbook.io/goldenore-cdc/moduly-goldenore-cdc/transforms-smt.md).

# TRANSFORMS (SMT)

<figure><img src="/files/hbBezLjRo6VIK9hv6pNc" alt=""><figcaption></figcaption></figure>

## 1. GDPR&#x20;

<table data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td></td><td>GdprEmail</td><td></td><td><a href="/pages/wcxs9OkCg7LZyE7FlAKj#5.-gdpr-email">/pages/wcxs9OkCg7LZyE7FlAKj#5.-gdpr-email</a></td></tr><tr><td></td><td>GdprPesel</td><td></td><td><a href="/pages/wcxs9OkCg7LZyE7FlAKj#6.-gdpr-pesel">/pages/wcxs9OkCg7LZyE7FlAKj#6.-gdpr-pesel</a></td></tr><tr><td></td><td>GdprPhone</td><td></td><td><a href="/pages/wcxs9OkCg7LZyE7FlAKj#7.-gdpr-phone">/pages/wcxs9OkCg7LZyE7FlAKj#7.-gdpr-phone</a></td></tr><tr><td></td><td>GdprPassportId</td><td></td><td><a href="/pages/wcxs9OkCg7LZyE7FlAKj#8.-gdpr-gdprpassportid">/pages/wcxs9OkCg7LZyE7FlAKj#8.-gdpr-gdprpassportid</a></td></tr><tr><td></td><td>GdprCreditCard</td><td></td><td><a href="/pages/wcxs9OkCg7LZyE7FlAKj#9.-gdpr-creditcard">/pages/wcxs9OkCg7LZyE7FlAKj#9.-gdpr-creditcard</a></td></tr></tbody></table>

## 2. FPE&#x20;

**Example:**&#x20;

{% hint style="info" %}

```json
{
"transforms":"fpe",
"transforms.fpe.type":"FpeField$Value",
"transforms.fpe.key":"3677397A24432646294A404D63516654",
"transforms.fpe.fields":"SENDER"
}
```

{% endhint %}

## 3. INSERT FIELD&#x20;

**Example:**

{% hint style="info" %}

```json
{"transforms": "InsertField",
"transforms.InsertField.type": "org.apache.kafka.connect.transforms.InsertField$Value",
"transforms.InsertField.static.field": "TARGET_SYSTEM",
"transforms.InsertField.static.value": "GOLDENORE CDC"}
```

{% endhint %}

## 4. MASK FIELD

**Example:**

```json
{"transforms": "Name",
"transforms.Name.type": "org.apache.kafka.connect.transforms.MaskField$Value",
"transforms.Name.fields": "SENDER_NAME",
"transforms.Name.replacement": "MASK SENDER NAME"}

```

## 5. TimestampConverter

Dostepne typy danych :

string, unix, Date, Time, or Timestamp.

**Example:**

```json
{
  "transforms": "StringToNumber,TimestampConverter",
  
  "transforms.StringToNumber.type": "org.apache.kafka.connect.transforms.Cast$Value",
  "transforms.StringToNumber.spec": "epoch:int64",
  
  "transforms.TimestampConverter.type": "org.apache.kafka.connect.transforms.TimestampConverter$Value",
  "transforms.TimestampConverter.field": "epoch",
  "transforms.TimestampConverter.target.type": "string",
  "transforms.TimestampConverter.format": "yyyy-MM-dd HH:mm:ss.SSS"
}

```

Rename Field&#x20;

```json
{"transforms": "RenameField",
"transforms.RenameField.type": "org.apache.kafka.connect.transforms.ReplaceField$Value",
"transforms.RenameField.renames": "epoch:time"}
```

{% hint style="info" %}

```json
{"transforms": "TimestampConverter",
"transforms.TimestampConverter.type": "org.apache.kafka.connect.transforms.TimestampConverter$Value",
"transforms.TimestampConverter.format": "yyyy-MM-dd HH:mm:ss",
"transforms.TimestampConverter.field": "epoch",
"transforms.TimestampConverter.target.type": "string"}
```

{% endhint %}

## 6. GDPR Email

### Tabela z dostępnymi ustawieniami

<table><thead><tr><th width="249.33333333333331">Opis</th><th>Wzór</th><th>Wartość domyślna</th></tr></thead><tbody><tr><td>Nazwa pola</td><td>"transforms.&#x3C;nazwa transformaty>.fields": "&#x3C;nazwa kolumny w której znajduje się mail>"</td><td>BRAK</td></tr><tr><td>Pole określające czy chcemy aby dane generowane przez system były zbliżone do ciągu wejściowego ( email format ) </td><td>"transforms.&#x3C;nazwa transformaty>.email.format": &#x3C;true lub false></td><td>true</td></tr><tr><td>Pole określające czy w przypadku nieprawidłowego formatu email ma być wstawiany placeholder</td><td>transforms.&#x3C;nazwa transformaty>.want.placeholder": &#x3C;true lub false></td><td>true</td></tr><tr><td>Pole określające klucz dla szyfrowania AES</td><td>"transforms.&#x3C;nazwa transformaty>.key": "&#x3C;klucz AES>"</td><td>"770A8B65BB156D24DE2A093277530142"</td></tr><tr><td>Pole określające czy nie zważając na format danych chcemy zaszyfrować dane algorytmem AES</td><td>"transforms.&#x3C;nazwa transformaty>.encryption": &#x3C;true lub false></td><td>false</td></tr><tr><td>Pole określające czy nie zważając na format danych chcemy deszyfrować dane algorytmem AES</td><td>"transforms.&#x3C;nazwa transformaty>.decryption": &#x3C;true lub false></td><td>false</td></tr></tbody></table>

#### Uwagi dodatkowe

* Pól które posiadają wartości domyślne nie musimy zawierać w definicji transformaty.
* W przypadku braku chęci wstawiania placeholdera dane szyfrowane są za pomocą algorytmu MD5
* W przypadku niemożliwości deszyfrowania (ze względu na niedozwolone znaki w kolumnie typu kropki) wykonywane jest domyślna operacja dla całej transformaty a więc szyfrowanie słownikowe

#### Przykładowe transformaty

<details>

<summary>Transformata z formatem mail(szyfrowanie słownikowe)</summary>

```json
{ 
  "transforms": "FieldMailReal",
  "transforms.FieldMailReal.type": "GdprEmail$Value",
  "transforms.FieldMailReal.fields": "email_adress",
  "transforms.FieldMailReal.email.format": true
}

lub

{
  "transforms": "FieldMail",
  "transforms.FieldMail.type": "GdprEmail$Value",
  "transforms.FieldMail.fields": "email_adress"
}
```

</details>

<details>

<summary>Transformata bez formatu mail(szyfrowanie SHA256) z placeholderem w przypadku, gdy dana w tabeli nie jest mailem</summary>

```json
{
  "transforms": "FieldMailNotReal",
  "transforms.FieldMailNotReal.type": "GdprEmail$Value",
  "transforms.FieldMailNotReal.fields": "email_adress",
  "transforms.FieldMailNotReal.email.format": false,
  "transforms.FieldMailNotReal.want.placeholder": true 
}

lub

{
  "transforms": "FieldMailNotReal",
  "transforms.FieldMailNotReal.type": "GdprEmail$Value",
  "transforms.FieldMailNotReal.fields": "email_adress",
  "transforms.FieldMailNotReal.email.format": false 
}
```

</details>

<details>

<summary>Transformata bez formatu mail(szyfrowanie SHA256) z szyfrowaniem MD5 w przypadku, gdy dana w tabeli nie jest mailem</summary>

```json
{
  "transforms": "FieldMailNotReal",
  "transforms.FieldMailNotReal.type": "GdprEmail$Value",
  "transforms.FieldMailNotReal.fields": "email_adress",
  "transforms.FieldMailNotReal.email.format": false,
  "transforms.FieldMailNotReal.want.placeholder": false 
}
```

</details>

<details>

<summary>Transformata szyfrująca AES</summary>

```json
{
  "transforms": "FieldEncryption",
  "transforms.FieldEncryption.type": "GdprEmail$Value",
  "transforms.FieldEncryption.fields": "email_adress",
  "transforms.FieldEncryption.encryption": true 
}

lub

{
  "transforms": "FieldEncryption",
  "transforms.FieldEncryption.type": "GdprEmail$Value",
  "transforms.FieldEncryption.fields": "email_adress",
  "transforms.FieldEncryption.key": "770A8B65DB156D24ED2C093277530142",
  "transforms.FieldEncryption.encryption": true 
}
```

</details>

<details>

<summary>Transformata deszyfrująca AES</summary>

```json
{
  "transforms": "FieldDecryption",
  "transforms.FieldDecryption.type": "GdprEmail$Value",
  "transforms.FieldDecryption.fields": "email",
  "transforms.FieldDecryption.decryption": true 
}

lub

{
  "transforms": "FieldDecryption",
  "transforms.FieldDecryption.type": "GdprEmail$Value",
  "transforms.FieldDecryption.fields": "email",
  "transforms.FieldDecryption.key": "770A8B65DB156D24ED2C093277530142",
  "transforms.FieldDecryption.decryption": true 
}
```

</details>

## 7. GDPR Pesel

### Tabela z dostępnymi ustawieniami

<table><thead><tr><th width="249.33333333333331">Opis</th><th>Wzór</th><th>Wartość domyślna</th></tr></thead><tbody><tr><td>Nazwa pola</td><td>"transforms.&#x3C;nazwa transformaty>.fields": "&#x3C;nazwa kolumny w której znajduje się pesel>"</td><td>BRAK</td></tr></tbody></table>

#### Uwagi dodatkowe

* W przypadku, gdy w podanym polu wartość nie jest numerem pesel wstawiana zostaje wartość 0.

#### Przykładowa transformata

```json
{
  "transforms": "FieldPesel", 
  "transforms.FieldPesel.type": "GdprPesel$Value", 
  "transforms.FieldPesel.fields": "pesel" 
}
```

## 8. GDPR Phone

### Tabela z dostępnymi ustawieniami

<table><thead><tr><th width="249.33333333333331">Opis</th><th>Wzór</th><th>Wartość domyślna</th></tr></thead><tbody><tr><td>Nazwa pola</td><td>"transforms.&#x3C;nazwa transformaty>.fields": "&#x3C;nazwa kolumny w której znajduje się numer telefonu>"</td><td>BRAK</td></tr></tbody></table>

#### Uwagi dodatkowe

* W przypadku, gdy w podanym polu wartość nie jest numerem telefonu wstawiana zostaje wartość 48 z następstwem zer w zależności od długości ciągu wejściowego. W przypadku podania wartości krótszej niż 3 cyfry wstawiana jest wartość 0.
* Obsługiwane są numery międzynarodowe.
* Nie obsługiwane są numery wewnętrzne, alarmowe oraz operatora.
* Numery telefonów mogą posiadać spację między cyframi oraz numer kierunkowy kraju poprzedzony +

#### Przykładowa transformata

```json
{
  "transforms": "FieldPhoneNumber",
  "transforms.FieldPhoneNumber.type": "GdprPhoneNumber$Value",
  "transforms.FieldPhoneNumber.fields": "phone_number"
}
```

## 9. GDPR GdprPassportId

### Tabela z dostępnymi ustawieniami

<table><thead><tr><th width="249.33333333333331">Opis</th><th>Wzór</th><th>Wartość domyślna</th></tr></thead><tbody><tr><td>Nazwa pola</td><td>"transforms.&#x3C;nazwa transformaty>.fields": "&#x3C;nazwa kolumny w której znajduje się numer paszportu lub dowodu osobistego>"</td><td>BRAK</td></tr><tr><td>Pole określające czy w przypadku nieprawidłowego formatu paszportu lub dowodu osobistego ma być wstawiany placeholder</td><td>"transforms.&#x3C;nazwa transformaty>.want.placeholder": &#x3C;true lub false>"</td><td>true</td></tr><tr><td>Pole określające czy chcemy anonimizować numer paszportu czy dowodu osobistego</td><td>"transforms.&#x3C;nazwa transformaty>.type.settings": &#x3C;"passport" lub "id">"</td><td>null</td></tr></tbody></table>

#### Uwagi dodatkowe

* Pól które posiadają wartości domyślne nie musimy zawierać w definicji transformaty.
* W przypadku braku chęci wstawiania placeholdera dane szyfrowane są za pomocą algorytmu FPE za pomocą cyfr i wielkich liter.

#### Przykładowe transformaty

<details>

<summary>Transformata anonimizacji numeru paszportu z placeholderem w przypadku, gdy dana w tabeli nie jest numerem paszportu</summary>

```json
{
  "transforms": "FieldPassport",
  "transforms.FieldPassport.type": "GdprPassportId$Value",
  "transforms.FieldPassport.fields": "passport_number",
  "transforms.FieldPassport.want.placeholder": true,
  "transforms.FieldPassport.type.settings": "passport"
}

lub 

{
  "transforms": "FieldPassport",
  "transforms.FieldPassport.type": "GdprPassportId$Value",
  "transforms.FieldPassport.fields": "passport_number",
  "transforms.FieldPassport.type.settings": "passport"
}
```

</details>

<details>

<summary>Transformata anonimizacji numeru paszportu z szyfrowaniem FPE za pomocą cyfr i wielkich liter w przypadku, gdy dana w tabeli nie jest numerem paszportu</summary>

```json
{
  "transforms": "FieldPassport",
  "transforms.FieldPassport.type": "GdprPassportId$Value",
  "transforms.FieldPassport.fields": "passport_number",
  "transforms.FieldPassport.want.placeholder": false,
  "transforms.FieldPassport.type.settings": "passport"
}
```

</details>

<details>

<summary>Transformata anonimizacji numeru dowodu osobistego z placeholderem w przypadku, gdy dana w tabeli nie jest numerem dowodu osobistego</summary>

```json
{
  "transforms": "FieldIdNumber",
  "transforms.FieldIdNumber.type": "GdprPassportId$Value",
  "transforms.FieldIdNumber.fields": "id_number",
  "transforms.FieldIdNumber.want.placeholder": true,
  "transforms.FieldIdNumber.type.settings": "id"
}

lub

{
  "transforms": "FieldIdNumber",
  "transforms.FieldIdNumber.type": "GdprPassportId$Value",
  "transforms.FieldIdNumber.fields": "id_number",
  "transforms.FieldIdNumber.type.settings": "id"
}
```

</details>

<details>

<summary>Transformata anonimizacji numeru dowodu osobistego z szyfrowaniem FPE za pomocą cyfr i wielkich liter w przypadku, gdy dana w tabeli nie jest numerem dowodu osobistego</summary>

```json
{
  "transforms": "FieldIdNumber",
  "transforms.FieldIdNumber.type": "GdprPassportId$Value",
  "transforms.FieldIdNumber.fields": "id_number",
  "transforms.FieldIdNumber.want.placeholder": false,
  "transforms.FieldIdNumber.type.settings": "id"
}
```

</details>

## 10. GDPR CreditCard

### Tabela z dostępnymi ustawieniami

<table><thead><tr><th width="249.33333333333331">Opis</th><th>Wzór</th><th>Wartość domyślna</th></tr></thead><tbody><tr><td>Nazwa pola</td><td>"transforms.&#x3C;nazwa transformaty>.fields": "&#x3C;nazwa kolumny w której znajduje się numer karty bankowej>"</td><td>BRAK</td></tr></tbody></table>

#### Uwagi dodatkowe

* W przypadku, gdy w podanym polu wartość nie jest numerem pesel wstawiane zostaje 16 zer (w przypadku przechowywania wartości w zmiennej np. bigint wstawiana jest wartość 0).

#### Przykładowa transformata

```json
{
  "transforms": "FieldCard",
  "transforms.FieldCard.type": "GdprCardNumber$Value",
  "transforms.FieldCard.fields": "credit_card"
}
```

## 11. Filter (Confluent)

### Tabela z dostępnymi ustawieniami

<table><thead><tr><th width="249.33333333333331">Opis</th><th>Wzór</th><th>Wartość domyślna</th></tr></thead><tbody><tr><td>Określa kryteria używane do filtrowania rekordów, które mają zostać uwzględnione lub wykluczone przez tę transformatę. Notacja używana do zapisu warunku filtrowania to predykat JSON Path, którego opis znajduje się w linku: https://github.com/json-path/JsonPath.</td><td>"transforms.&#x3C;nazwa transformaty>.filter.condition": "&#x3C;warunek filtrowania>"</td><td>BRAK</td></tr><tr><td>Określa akcję wykonywaną na rekordach pasujących do predykatu filter.condition. Dopuszczalne wartości to: [include, exclude]. Wartość "include", zostawia rekordy pasujące do predykatu i usuwa wszystkie rekordy, które nie spełniają predykatu. Wartość "exclude" usuwa wszystkie rekordy pasujące do predykatu.</td><td>"transforms.&#x3C;nazwa transformaty>.filter.type": "&#x3C;"include" lub "exclude">"</td><td>BRAK</td></tr><tr><td>Określa zachowanie, gdy rekord nie ma pola (pól) użytych w filter.condition. Użyj "fail", aby rzucić wyjątek i nie wykonać zadania konektora, "include", aby przepuścić rekord, lub "exclude", aby go odrzucić.</td><td>"transforms.&#x3C;nazwa transformaty>.missing.or.null.behavior": "&#x3C;"fail", "include" lub "exclude">"</td><td>fail</td></tr></tbody></table>

#### Przykładowa transformata

```json
{
  "transforms": "filterPoland",
  "transforms.filterPoland.type": "io.confluent.connect.transforms.Filter$Value",
  "transforms.filterPoland.filter.condition": "$[?(@.nation== 'Poland')]",
  "transforms.filterPoland.filter.type": "include", 
  "transforms.filterPoland.missing.or.null.behavior": "fail"
}
```

### Transformata z predykatem

```json
{
  "transforms": "filterPoland",
  "transforms.filterPoland.predicate": "IsPredicate2",
  "transforms.filterPoland.type": "io.confluent.connect.transforms.Filter$Value",
  "transforms.filterPoland.filter.condition": "$[?(@.nation== 'Poland')]",
  "transforms.filterPoland.filter.type": "include", 
  "transforms.filterPoland.missing.or.null.behavior": "fail",
  "predicates": "IsPredicate2",
  "predicates.IsPredicate2.type": "org.apache.kafka.connect.transforms.predicates.TopicNameMatches",
  "predicates.IsPredicate2.pattern": ".*client"
}
```

Powyższa transformata przedstawia użycie predykatu, który pozwala nam na filtrowanie konkretnej tabeli lub tabel. Gdy replikujemy cały schemat lub wiele tabel, które mają kolumny o takiej samej nazwie filtr zadziałałby na wszystkie tabele. Użycie predykatu typu TopicNameMatches pozwala na wskazanie jednego lub wielu topicków za pomocą regex i rozwiązuje problem filtrowania wszystkich tabel znajdujących się w naszym connectorze.

## 12.  Przykład użycia wielu transformat

<pre class="language-json"><code class="lang-json">{
  "transforms": ["FirstNameField", "LastNameField", "CompanyField",  "PhoneNumberField", "NationField", "CreditCardField", "PeselField", "EmailField", "PassportField", "PolishIdField"],

 
<strong>  "transforms.FirstNameField.type": "org.apache.kafka.connect.transforms.MaskField$Value",
</strong><strong>  "transforms.FirstNameField.fields": "first_name",
</strong>  "transforms.FirstNameField.replacement": "First Name",

  "transforms.LastNameField.type": "org.apache.kafka.connect.transforms.MaskField$Value",
  "transforms.LastNameField.fields": "last_name",
  "transforms.LastNameField.replacement": "Last Name",

  "transforms.CompanyField.type":"FpeField$Value",
  "transforms.CompanyField.key":"3677397A24432646294A404D63516654",
<strong>  "transforms.CompanyField.fields":"company",
</strong>
  "transforms.PhoneNumberField.type": "GdprPhoneNumber$Value",
  "transforms.PhoneNumberField.fields": "phone_number",

  "transforms.NationField.type":"FpeField$Value",
  "transforms.NationField.key":"3677397A24432646294A404D63516654",
  "transforms.NationField.fields":"nation",

  "transforms.CreditCardField.type": "GdprCardNumber$Value",
  "transforms.CreditCardField.fields": "credit_card",

  "transforms.PeselField.type": "GdprPesel$Value", 
  "transforms.PeselField.fields": "pesel",

  "transforms.EmailField.type": "GdprEmail$Value",
  "transforms.EmailField.fields": "adress_email",

  "transforms.PassportField.type": "GdprPassportId$Value",
  "transforms.PassportField.fields": "passport_number",
  "transforms.PassportField.type.settings": "passport",

  "transforms.PolishIdField.type": "GdprPassportId$Value",
  "transforms.PolishIdField.fields": "polish_id_number",
  "transforms.PolishIdField.type.settings": "id"
}
</code></pre>
