Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fides ints 62 greenhouse harvestapi access erasure #4945

Merged
merged 30 commits into from
Jun 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
f23229b
Init commit
MarcGEthyca May 31, 2024
d0c9d72
Update 1 to the dataset
MarcGEthyca May 31, 2024
2a5d838
icon
MarcGEthyca May 31, 2024
fdb1621
Simplified Version
MarcGEthyca Jun 3, 2024
16ad9bf
access passing (erasure passing too but cheating)
MarcGEthyca Jun 3, 2024
32c26b8
All tests passing ... still cheating with one value
MarcGEthyca Jun 3, 2024
39f8b5d
more cleanup
MarcGEthyca Jun 3, 2024
f1ee0b7
Merge branch 'main' into fides_ints_62_greenhouse_harvestapi_access_e…
MarcGEthyca Jun 3, 2024
842bb41
All passing now
MarcGEthyca Jun 3, 2024
a30d583
Cleaning a comment
MarcGEthyca Jun 3, 2024
9b0de7f
removed comment
MarcGEthyca Jun 3, 2024
edf8a44
Merge branch 'main' into fides_ints_62_greenhouse_harvestapi_access_e…
MarcGEthyca Jun 4, 2024
4868950
Expanding details required to provide requested values
MarcGEthyca Jun 4, 2024
163fa3c
swapped text to indicate navigation
MarcGEthyca Jun 4, 2024
715edcf
Changelog
MarcGEthyca Jun 4, 2024
9125330
fixed name of param
MarcGEthyca Jun 4, 2024
2ba019d
Fixes to labels and descriptions
MarcGEthyca Jun 4, 2024
d28770a
Removed extraneous lines
MarcGEthyca Jun 4, 2024
5fba5a9
fixes to icon, general cleanup
MarcGEthyca Jun 4, 2024
62699a8
Cleanup
MarcGEthyca Jun 4, 2024
87b9095
Cleaned up description
MarcGEthyca Jun 4, 2024
847fc2f
Renaming
MarcGEthyca Jun 5, 2024
edef1a7
Changed naming to be more user friendly
MarcGEthyca Jun 5, 2024
63a2a51
Merge branch 'main' into fides_ints_62_greenhouse_harvestapi_access_e…
MarcGEthyca Jun 6, 2024
667e8a9
Merge branch 'main' into fides_ints_62_greenhouse_harvestapi_access_e…
MarcGEthyca Jun 10, 2024
12fff6f
Merge branch 'main' into fides_ints_62_greenhouse_harvestapi_access_e…
MarcGEthyca Jun 11, 2024
266fc95
Merge branch 'main' into fides_ints_62_greenhouse_harvestapi_access_e…
MarcGEthyca Jun 11, 2024
6d6dfe7
Updating the basic auth strategy to support empty passwords
galvana Jun 11, 2024
4a6d3b7
Merge branch 'main' into fides_ints_62_greenhouse_harvestapi_access_e…
galvana Jun 11, 2024
43bef14
Mypy fix
galvana Jun 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ The types of changes are:
- Added model and data migrations and CRUD-layer operations for property-specific messaging [#4901](https://github.com/ethyca/fides/pull/4901)
- Added option in FidesJS SDK to only disable notice-served API [#4965](https://github.com/ethyca/fides/pull/4965)
- External ID support for consent management [#4927](https://github.com/ethyca/fides/pull/4927)
- Added access and erasure support for the Greenhouse Harvest integration [#4945](https://github.com/ethyca/fides/pull/4945)

### Changed
- Move new data map reporting table out of beta and remove old table from Data Lineage map. [#4963](https://github.com/ethyca/fides/pull/4963)
Expand Down
65 changes: 65 additions & 0 deletions data/saas/config/greenhouse_config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
saas_config:
fides_key: <instance_fides_key>
name: Greenhouse
type: greenhouse
description: A sample schema representing the Greenhouse integration for Fides
user_guide: https://docs.ethyca.com/user-guides/integrations/saas-integrations/greenhouse
version: 0.1.0

connector_params:
- name: domain
label: Domain
description: The Harvest domain. Default harvest.greenhouse.io
default_value: harvest.greenhouse.io
- name: api_key
label: API key
description: The Harvest API key. This can be generated by navigating from the Greenhouse main page to Configure then Dev Center then API Credential Management and taking note of the Harvest API key value.
sensitive: True
- name: greenhouse_user_id
label: Greenhouse user ID
description: Your Greenhouse user id. This value can be seen by any Greenhouse user from the main page by examining the URL when viewing this user. From the Greenhouse main page, navigate to Configure select Users then Select the desired user. The URL when viewing the account will look like this https://app8.greenhouse.io/account/users/4054555008/edit where the numeric value is the Greenhouse user ID.

client_config:
protocol: https
host: <domain>
authentication:
strategy: basic
configuration:
username: <api_key>

test_request:
method: GET
path: /v1/candidates
query_params:
- name: per_page
value: 1

endpoints:
- name: user
requests:
read:
method: GET
path: /v1/candidates
query_params:
- name: email
value: <email>
param_values:
- name: email
identity: email
update:
method: PUT
path: /v1/candidates/<user_id>/anonymize
headers:
- name: On-Behalf-Of
value: <greenhouse_user_id>
param_values:
- name: greenhouse_user_id
connector_param: greenhouse_user_id
- name: user_id
references:
- dataset: <instance_fides_key>
field: user.id
direction: from
query_params:
- name: fields
value: "full_name,current_company,current_title,tags,phone_numbers,emails,social_media_links,websites,addresses,location,custom_candidate_fields,source,recruiter,coordinator,attachments,application_questions,referral_questions,notes,rejection_notes,email_addresses,activity_items,innotes,inmails,rejection_reason,scorecards_and_interviews,offers,credited_to,headline,all_offer_versions,follow_up_reminders,custom_application_fields,education,employment,candidate_stage_data,prospect_owner,custom_rejection_question_fields,touchpoints,prospect_pool_and_stage,prospect_jobs,prospect_offices,prospect_offices_and_departments,third_party_integrations"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the future, we could make this more dynamic by using the keys of the masked_object_fields map as the query params

172 changes: 172 additions & 0 deletions data/saas/dataset/greenhouse_dataset.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
dataset:
- fides_key: <instance_fides_key>
name: Greenhouse Dataset
description: A sample dataset representing the Greenhouse integration for Fides
collections:
- name: user
fields:
- name: id
data_categories: [user.unique_id]
fidesops_meta:
primary_key: True
data_type: integer
- name: first_name
data_categories: [user.name.first]
fidesops_meta:
data_type: string
- name: last_name
data_categories: [user.name.last]
fidesops_meta:
data_type: string
- name: company
- name: title
- name: created_at
data_categories: [system.operations]
fidesops_meta:
data_type: string
- name: updated_at
data_categories: [system.operations]
fidesops_meta:
data_type: string
- name: last_activity
data_categories: [system.operations]
fidesops_meta:
data_type: string
- name: is_private
data_categories: [system.operations]
fidesops_meta:
data_type: boolean
- name: photo_url
- name: attachments
- name: application_ids
data_categories: [system.operations]
fidesops_meta:
data_type: "integer[]"
- name: phone_numbers
fidesops_meta:
data_type: "object[]"
fields:
- name: value
data_categories: [user.contact.phone_number]
fidesops_meta:
data_type: string
- name: type
data_categories: [system.operations]
fidesops_meta:
data_type: string
- name: addresses
- name: email_addresses
fidesops_meta:
data_type: "object[]"
fields:
- name: value
data_categories: [user.contact.email]
fidesops_meta:
data_type: string
- name: type
data_categories: [system.operations]
fidesops_meta:
data_type: string
- name: website_addresses
- name: social_media_addresses
- name: recruiter
- name: coordinator
- name: can_email
data_categories: [system.operations]
fidesops_meta:
data_type: boolean
- name: tags
- name: applications
fidesops_meta:
data_type: "object[]"
fields:
- name: id
data_categories: [system.operations]
fidesops_meta:
data_type: integer
- name: candidate_id
data_categories: [system.operations]
fidesops_meta:
data_type: integer
- name: prospect
data_categories: [system.operations]
fidesops_meta:
data_type: boolean
- name: applied_at
data_categories: [system.operations]
fidesops_meta:
data_type: string
- name: rejected_at
- name: last_activity_at
data_categories: [system.operations]
fidesops_meta:
data_type: string
- name: location
- name: attachments
- name: source
fidesops_meta:
data_type: object
fields:
- name: id
data_categories: [system.operations]
fidesops_meta:
data_type: integer
- name: public_name
data_categories: [system.operations]
fidesops_meta:
data_type: string
- name: credited_to
- name: rejection_reason
- name: rejection_details
- name: jobs
fidesops_meta:
data_type: "object[]"
fields:
- name: id
data_categories: [system.operations]
fidesops_meta:
data_type: integer
- name: name
data_categories: [system.operations]
fidesops_meta:
data_type: string
- name: job_post_id
- name: status
data_categories: [system.operations]
fidesops_meta:
data_type: string
- name: current_stage
fidesops_meta:
data_type: object
fields:
- name: id
data_categories: [system.operations]
fidesops_meta:
data_type: integer
- name: name
data_categories: [system.operations]
fidesops_meta:
data_type: string
- name: answers
- name: prospective_department
- name: prospective_office
- name: prospect_detail
fidesops_meta:
data_type: object
fields:
- name: prospect_pool
- name: prospect_stage
- name: prospect_owner
- name: educations
- name: employments
- name: linked_user_ids
- name: custom_fields
fidesops_meta:
data_type: object
fields:
- name: work_authorization
- name: keyed_custom_fields
fidesops_meta:
data_type: object
fields:
- name: work_authorization
3 changes: 3 additions & 0 deletions data/saas/icon/greenhouse.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from base64 import b64encode

from requests import PreparedRequest

from fides.api.models.connectionconfig import ConnectionConfig
Expand Down Expand Up @@ -28,11 +30,15 @@ def add_authentication(
) -> PreparedRequest:
"""Add basic authentication to the request"""
secrets = connection_config.secrets
username = assign_placeholders(self.username, secrets) # type: ignore
password = assign_placeholders(self.password, secrets) # type: ignore

# the requests library treats a None password as a "None" literal string
# so we need to override this behavior
if password is None:
password = ""

request.prepare_auth(
auth=(
assign_placeholders(self.username, secrets), # type: ignore
assign_placeholders(self.password, secrets), # type: ignore
)
request.headers["Authorization"] = (
"Basic " + b64encode(f"{username}:{password}".encode()).decode()
)
return request
105 changes: 105 additions & 0 deletions tests/fixtures/saas/greenhouse_fixtures.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
from base64 import b64encode
from typing import Any, Dict, Generator

import pydash
import pytest
import requests

from tests.ops.integration_tests.saas.connector_runner import (
ConnectorRunner,
generate_random_email,
)
from tests.ops.test_helpers.vault_client import get_secrets

secrets = get_secrets("greenhouse")


@pytest.fixture(scope="session")
def greenhouse_secrets(saas_config) -> Dict[str, Any]:
return {
"domain": pydash.get(saas_config, "greenhouse.domain") or secrets["domain"],
"api_key": pydash.get(saas_config, "greenhouse.api_key") or secrets["api_key"],
"greenhouse_user_id": pydash.get(saas_config, "greenhouse.greenhouse_user_id")
or secrets["greenhouse_user_id"],
}


@pytest.fixture(scope="session")
def greenhouse_identity_email(saas_config) -> str:
return (
pydash.get(saas_config, "greenhouse.identity_email")
or secrets["identity_email"]
)


@pytest.fixture
def greenhouse_erasure_identity_email() -> str:
return generate_random_email()


@pytest.fixture
def greenhouse_erasure_data(
greenhouse_secrets,
greenhouse_erasure_identity_email: str,
) -> Generator:
base_url = f"https://{greenhouse_secrets['domain']}/v1/candidates"
headers = {
"On-Behalf-Of": f"{greenhouse_secrets['greenhouse_user_id']}",
}
# details of the test user - note that the job_id value below is from our instance and the sample job. This id is required for this call to work.
body = {
"first_name": "Test",
"last_name": "Ethyca",
"company": "Ethyca",
"title": "Customer Success Representative",
"is_private": "false",
"phone_numbers": [{"value": "555-1212", "type": "mobile"}],
"addresses": [{"value": "123 Fake St.", "type": "home"}],
"email_addresses": [
{"value": greenhouse_erasure_identity_email, "type": "work"},
{"value": "testpersonal@example.com", "type": "personal"},
],
"website_addresses": [{"value": "ethyca.example.com", "type": "personal"}],
"social_media_addresses": [
{"value": "linkedin.example.com/ethyca"},
{"value": "@ethyca"},
],
"educations": [
{
"start_date": "2001-09-15T00:00:00.000Z",
"end_date": "2004-05-15T00:00:00.000Z",
}
],
"employments": [
{
"company_name": "Greenhouse",
"title": "Engineer",
"start_date": "2017-08-15T00:00:00.000Z",
"end_date": "2018-05-15T00:00:00.000Z",
}
],
"tags": ["Walkabout", "Orientation"],
"applications": [{"job_id": 4020768008}],
}
response = requests.post(
base_url, auth=(greenhouse_secrets["api_key"], ""), headers=headers, json=body
)
assert response.ok
json_response = response.json()
user_id = json_response["id"]
assert json_response["id"] > 1
yield {user_id}


@pytest.fixture
def greenhouse_runner(
db,
cache,
greenhouse_secrets,
) -> ConnectorRunner:
return ConnectorRunner(
db,
cache,
"greenhouse",
greenhouse_secrets,
)
Loading
Loading