Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
66 changes: 60 additions & 6 deletions .github/hooks/pre-commit.bash
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@

[ -n "$CI" ] && exit 0

green='\033[0;32m'
no_color='\033[0m'
grey='\033[0;90m'
red='\033[0;31m'

pnpm lint-staged --relative
lintStatus=$?

Expand All @@ -11,13 +16,62 @@ if [ $lintStatus -ne 0 ]; then
exit 1
fi

green='\033[0;32m'
no_color='\033[0m'
grey='\033[0;90m'
red='\033[0;31m'
##
## 1) Scan staged text files for secrets
##

scan_staged_secrets() {
local file
local files_scanned=0
local scan_status=0
local tmpfile

if ! pnpm exec secretlint --version >/dev/null 2>&1; then
echo -e "${red}secretlint is not available. Run pnpm install from the repository root.${no_color}"
return 1
fi

if ! tmpfile=$(mktemp); then
echo -e "${red}Could not create temp file for secret scanning${no_color}"
return 1
fi

echo -e "Scanning staged files for secrets ${grey}(pre-commit hook)${no_color} "

while IFS= read -r -d '' file; do
if ! git show ":$file" > "$tmpfile"; then
scan_status=1
continue
fi

if LC_ALL=C grep -Iq . "$tmpfile"; then
files_scanned=$((files_scanned + 1))

if ! pnpm exec secretlint --format=compact --stdinFileName="$file" < "$tmpfile"; then
scan_status=1
fi
fi
done < <(git diff --cached --name-only --diff-filter=ACMR -z)

if [ $files_scanned -eq 0 ]; then
echo "No staged text files to scan, continuing..."
fi

rm -f "$tmpfile"

return $scan_status
}

scan_staged_secrets
secretScanStatus=$?

if [ $secretScanStatus -ne 0 ]; then
echo -e "${red}❌ Secret scanning failed${no_color}"
exit 1
fi

##
## 1) Check and remove submodules before committing
## 2) Check and remove submodules before committing
##

ROOT_DIR=$(git rev-parse --show-cdup)
Expand Down Expand Up @@ -47,7 +101,7 @@ else
fi

##
## 2) Suggest shipping a new version of @tryghost/activitypub when changes are detected
## 3) Suggest shipping a new version of @tryghost/activitypub when changes are detected
## The intent is to ship smaller changes more frequently to production
##

Expand Down
38 changes: 38 additions & 0 deletions .secretlintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"rules": [
{
"id": "@secretlint/secretlint-rule-preset-recommend"
},
{
"id": "@secretlint/secretlint-rule-pattern",
"options": {
"patterns": [
{
"name": "Tinybird token",
"patterns": [
"/\\b(?<CREDENTIAL>p\\.eyJ[A-Za-z0-9_-]{15,}\\.[A-Za-z0-9_-]{20,})\\b/"
]
},
{
"name": "credential in URL query string",
"patterns": [
"/[?&](?:token|api[_-]?key|access[_-]?token|auth[_-]?token|client[_-]?secret|secret|password)=(?<CREDENTIAL>(?!p\\.)[^&\\s\"'<>]{16,})/i"
]
},
{
"name": "credential assignment",
"patterns": [
"/(?:^|[\\s{\"',])\\b(?:api[_-]?key|access[_-]?token|auth[_-]?token|client[_-]?secret|secret[_-]?key|private[_-]?key|password)\\b\\s*[:=]\\s*[\"']?(?<CREDENTIAL>[A-Za-z0-9_./+=:-]{20,})[\"']?/i"
]
},
{
"name": "authorization header",
"patterns": [
"/\\bAuthorization\\s*:\\s*(?:Bearer|Basic)\\s+(?<CREDENTIAL>[A-Za-z0-9_./+=:-]{20,})/i"
]
}
]
}
}
]
}
4 changes: 2 additions & 2 deletions ghost/core/core/server/data/tinybird/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ Core member accounts.
- `id` (string, 24 chars) - Primary key
- `uuid` (string, 36 chars) - UUID for Tinybird correlation
- `email` - Member email address
- `status` - 'free', 'paid', 'comped'
- `status` - 'free', 'paid', 'comped', 'gift'
- `created_at` - Signup timestamp

#### `newsletters`
Expand Down Expand Up @@ -214,7 +214,7 @@ Fields with specific data in the schema:
{
"site_uuid": "string",
"member_uuid": "string|undefined", // member.uuid in MySQL
"member_status": "free|paid|comped|undefined", // member.status in MySQL
"member_status": "free|paid|comped|gift|undefined", // member.status in MySQL. Note: when filtering Tinybird endpoints by `paid`, `comped` and `gift` are bucketed in alongside `paid`.
"post_uuid": "string|undefined", // post.uuid in MySQL
"post_type": "post|page|empty", //post.type in MySQL
"user-agent": "string",
Expand Down
9 changes: 8 additions & 1 deletion ghost/core/core/server/data/tinybird/endpoints/api_kpis.pipe
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,14 @@ SQL >
on fs.session_id = h.session_id
where
site_uuid = {{ String(site_uuid, 'mock_site_uuid', description="Tenant ID", required=True) }}
{% if defined(member_status) %} and member_status IN {{ Array(member_status, "'undefined', 'free', 'paid'", description="Member status to filter on", required=False) }} {% end %}
{% if defined(member_status) %}
and member_status IN (
select arrayJoin(
{{ Array(member_status, "'undefined', 'free', 'paid'", description="Member status to filter on", required=False) }}
|| if('paid' IN {{ Array(member_status) }}, ['comped', 'gift'], [])
)
)
{% end %}
{% if defined(location) %} and location = {{ String(location, description="Location to filter on", required=False) }} {% end %}
{% if defined(pathname) %} and pathname = {{ String(pathname, description="Pathname to filter on", required=False) }} {% end %}
{% if defined(post_uuid) %} and post_uuid = {{String(post_uuid, description="Post UUID to filter on", required=False) }} {% end %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,14 @@ SQL >
on fs.session_id = h.session_id
where
site_uuid = {{ String(site_uuid, 'mock_site_uuid', description="Tenant ID", required=True) }}
{% if defined(member_status) %} and member_status IN {{ Array(member_status, "'undefined', 'free', 'paid'", description="Member status to filter on", required=False) }} {% end %}
{% if defined(member_status) %}
and member_status IN (
select arrayJoin(
{{ Array(member_status, "'undefined', 'free', 'paid'", description="Member status to filter on", required=False) }}
|| if('paid' IN {{ Array(member_status) }}, ['comped', 'gift'], [])
)
)
{% end %}
{% if defined(location) %} and location = {{ String(location, description="Location to filter on", required=False) }} {% end %}
{% if defined(pathname) %} and pathname = {{ String(pathname, description="Pathname to filter on", required=False) }} {% end %}
{% if defined(post_uuid) %} and post_uuid = {{String(post_uuid, description="Post UUID to filter on", required=False) }} {% end %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ SQL >
and member_status IN (
select arrayJoin(
{{ Array(member_status, "'undefined', 'free', 'paid'", description="Member status to filter on", required=False) }}
|| if('paid' IN {{ Array(member_status) }}, ['comped'], [])
|| if('paid' IN {{ Array(member_status) }}, ['comped', 'gift'], [])
)
)
{% end %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ SQL >
and member_status IN (
select arrayJoin(
{{ Array(member_status, "'undefined', 'free', 'paid'", description="Member status to filter on", required=False) }}
|| if('paid' IN {{ Array(member_status) }}, ['comped'], [])
|| if('paid' IN {{ Array(member_status) }}, ['comped', 'gift'], [])
)
)
{% end %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ SQL >
and member_status IN (
select arrayJoin(
{{ Array(member_status, "'undefined', 'free', 'paid'", description="Member status to filter on", required=False) }}
|| if('paid' IN {{ Array(member_status) }}, ['comped'], [])
|| if('paid' IN {{ Array(member_status) }}, ['comped', 'gift'], [])
)
)
{% end %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ SQL >
and member_status IN (
select arrayJoin(
{{ Array(member_status, "'undefined', 'free', 'paid'", description="Member status to filter on", required=False) }}
|| if('paid' IN {{ Array(member_status) }}, ['comped'], [])
|| if('paid' IN {{ Array(member_status) }}, ['comped', 'gift'], [])
)
)
{% end %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ SQL >
AND member_status IN (
SELECT arrayJoin(
{{ Array(member_status, "'undefined', 'free', 'paid'", description="Member status to filter on", required=False) }}
|| if('paid' IN {{ Array(member_status) }}, ['comped'], [])
|| if('paid' IN {{ Array(member_status) }}, ['comped', 'gift'], [])
)
)
{% end %}
Expand Down Expand Up @@ -80,7 +80,7 @@ SQL >
AND member_status IN (
SELECT arrayJoin(
{{ Array(member_status, "'undefined', 'free', 'paid'", description="Member status to filter on", required=False) }}
|| if('paid' IN {{ Array(member_status) }}, ['comped'], [])
|| if('paid' IN {{ Array(member_status) }}, ['comped', 'gift'], [])
)
)
{% end %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@
{"timestamp":"2100-01-06 01:28:38","session_id":"61a2896b-7cf8-4853-86a6-a0e4f87c1e21","action":"page_hit","version":"1","payload":{"site_uuid":"mock_site_uuid","member_uuid":"undefined","member_status":"undefined","post_uuid":"6b8635fb-292f-4422-9fe4-d76cfab2ba31","post_type":"post","user-agent":"Mozilla/5.0 (Windows; U; Windows NT 5.1) AppleWebKit/533.1.0 (KHTML, like Gecko) Chrome/18.0.852.0 Safari/533.1.0","device":"desktop","locale":"en-GB","location":"GB","referrer":"https://search.yahoo.com/","pathname":"/blog/hello-world/","href":"https://my-ghost-site.com/blog/hello-world/","meta":{"referrerSource":"https://search.yahoo.com/"}}}
{"timestamp":"2100-01-07 01:44:10","session_id":"7f1e88e1-da8e-46df-bc69-d04fb29d603d","action":"page_hit","version":"1","payload":{"site_uuid":"mock_site_uuid","member_uuid":"undefined","member_status":"undefined","post_uuid":"06b1b0c9-fb53-4a15-a060-3db3fde7b1fc","post_type":"page","user-agent":"Mozilla/5.0 (Windows NT 5.0; WOW64; rv:13.9) Gecko/20100101 Firefox/13.9.7","device":"desktop","locale":"en-US","location":"US","referrer":"http://wilted-tick.com","pathname":"/about/","href":"https://my-ghost-site.com/about/?utm_source=reddit&utm_medium=social&utm_campaign=product_launch&utm_term=announcement","utm_source":"reddit","utm_medium":"social","utm_campaign":"product_launch","utm_term":"announcement","utm_content":null,"meta":{"referrerSource":"http://wilted-tick.com","received_timestamp":"2100-01-07 01:44:10.000Z"}},"inserted_at":"2100-01-07 01:44:10.250"}
{"timestamp":"2100-01-07 02:23:19","session_id":"98159299-8111-4dc8-9156-bb339fe9508c","action":"page_hit","version":"1","payload":{"site_uuid":"mock_site_uuid","member_uuid":"undefined","member_status":"undefined","post_uuid":"06b1b0c9-fb53-4a15-a060-3db3fde7b1dd","post_type":"post","user-agent":"Mozilla/5.0 (Windows NT 5.0; WOW64; rv:13.9) Gecko/20100101 Firefox/13.9.7","device":"desktop","locale":"en-US","location":"US","referrer":"https://my-ghost-site.com","pathname":"/blog/hello-world/","href":"https://my-ghost-site.com/blog/hello-world/?utm_source=google&utm_medium=cpc&utm_campaign=holiday_promo&utm_term=black_friday&utm_content=search_ad","utm_source":"google","utm_medium":"cpc","utm_campaign":"holiday_promo","utm_term":"black_friday","utm_content":"search_ad","meta":{"referrerSource":"https://my-ghost-site.com"}}}
{"timestamp":"2100-01-07 03:15:00","session_id":"9f2c7d18-1e73-4a55-bf91-ea63dc12bb7a","action":"page_hit","version":"1","payload":{"site_uuid":"mock_site_uuid","member_uuid":"b5df84a2-1e35-4f88-9c0e-2dca7351a4e9","member_status":"gift","post_uuid":"6b8635fb-292f-4422-9fe4-d76cfab2ba31","post_type":"post","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15","device":"desktop","locale":"it-IT","location":"IT","referrer":"","pathname":"/blog/hello-world/","href":"https://my-ghost-site.com/blog/hello-world/","meta":{"referrerSource":""}}}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ SQL >
and member_status IN (
select arrayJoin(
{{ Array(member_status, "'undefined', 'free', 'paid'", description="Member status to filter on", required=False) }}
|| if('paid' IN {{ Array(member_status) }}, ['comped'], [])
|| if('paid' IN {{ Array(member_status) }}, ['comped', 'gift'], [])
)
)
{% end %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ SQL >
and member_status IN (
select arrayJoin(
{{ Array(member_status, "'undefined', 'free', 'paid'", description="Member status to filter on", required=False) }}
|| if('paid' IN {{ Array(member_status) }}, ['comped'], [])
|| if('paid' IN {{ Array(member_status) }}, ['comped', 'gift'], [])
)
)
{% end %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,11 @@ class DockerAnalyticsManager {
this.locales = ['en-US', 'en-GB', 'es-ES', 'fr-FR', 'de-DE', 'it-IT', 'pt-BR', 'ja-JP'];

this.memberStatusWeights = [
{value: 'undefined', weight: 83},
{value: 'paid', weight: 9},
{value: 'free', weight: 8}
{value: 'undefined', weight: 82},
{value: 'paid', weight: 8},
{value: 'free', weight: 8},
{value: 'comped', weight: 1},
{value: 'gift', weight: 1}
];

this.locationWeights = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@
description: Test active visitors with default site UUID
parameters: site_uuid=mock_site_uuid
expected_result: |
{"active_visitors":16}
{"active_visitors":17}

- name: active_visitors_default
description: Test active visitors with only required site_uuid parameter
parameters: site_uuid=mock_site_uuid
expected_result: |
{"active_visitors":16}
{"active_visitors":17}

- name: active_visitors_with_post
description: Test active visitors filtered by specific post
parameters: site_uuid=mock_site_uuid&post_uuid=6b8635fb-292f-4422-9fe4-d76cfab2ba31
expected_result: |
{"active_visitors":9}
{"active_visitors":10}

- name: active_visitors_custom_site
description: Test active visitors with custom site UUID
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@
description: Test active visitors with default site UUID
parameters: site_uuid=mock_site_uuid
expected_result: |
{"active_visitors":16}
{"active_visitors":17}

- name: active_visitors_default
description: Test active visitors with only required site_uuid parameter
parameters: site_uuid=mock_site_uuid
expected_result: |
{"active_visitors":16}
{"active_visitors":17}

- name: active_visitors_with_post
description: Test active visitors filtered by specific post
parameters: site_uuid=mock_site_uuid&post_uuid=6b8635fb-292f-4422-9fe4-d76cfab2ba31
expected_result: |
{"active_visitors":9}
{"active_visitors":10}

- name: active_visitors_custom_site
description: Test active visitors with custom site UUID
Expand Down
10 changes: 5 additions & 5 deletions ghost/core/core/server/data/tinybird/tests/api_kpis.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
{"date":"2100-01-04","visits":3,"pageviews":7,"bounce_rate":0.33,"avg_session_sec":572}
{"date":"2100-01-05","visits":2,"pageviews":5,"bounce_rate":0,"avg_session_sec":308}
{"date":"2100-01-06","visits":2,"pageviews":2,"bounce_rate":1,"avg_session_sec":0}
{"date":"2100-01-07","visits":2,"pageviews":2,"bounce_rate":1,"avg_session_sec":0}
{"date":"2100-01-07","visits":3,"pageviews":3,"bounce_rate":1,"avg_session_sec":0}

- name: Filtered by location - UK
description: Filtered by location - UK
Expand Down Expand Up @@ -60,7 +60,7 @@
{"date":"2100-01-07","visits":0,"pageviews":0,"bounce_rate":0,"avg_session_sec":0}

- name: Filtered by member status - paid
description: Filtered by member status - paid
description: Filtered by member status - paid (includes comped and gift)
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&member_status=paid
expected_result: |
{"date":"2100-01-01","visits":0,"pageviews":0,"bounce_rate":0,"avg_session_sec":0}
Expand All @@ -69,7 +69,7 @@
{"date":"2100-01-04","visits":1,"pageviews":1,"bounce_rate":1,"avg_session_sec":0}
{"date":"2100-01-05","visits":1,"pageviews":2,"bounce_rate":0,"avg_session_sec":123}
{"date":"2100-01-06","visits":0,"pageviews":0,"bounce_rate":0,"avg_session_sec":0}
{"date":"2100-01-07","visits":0,"pageviews":0,"bounce_rate":0,"avg_session_sec":0}
{"date":"2100-01-07","visits":1,"pageviews":1,"bounce_rate":1,"avg_session_sec":0}

- name: Filtered by member status - undefined
description: Filtered by member status - undefined
Expand All @@ -92,7 +92,7 @@
{"date":"2100-01-03","visits":3,"pageviews":7,"bounce_rate":0.33,"avg_session_sec":572}
{"date":"2100-01-04","visits":2,"pageviews":5,"bounce_rate":0,"avg_session_sec":308}
{"date":"2100-01-05","visits":2,"pageviews":2,"bounce_rate":1,"avg_session_sec":0}
{"date":"2100-01-06","visits":2,"pageviews":2,"bounce_rate":1,"avg_session_sec":0}
{"date":"2100-01-06","visits":3,"pageviews":3,"bounce_rate":1,"avg_session_sec":0}
{"date":"2100-01-07","visits":0,"pageviews":0,"bounce_rate":0,"avg_session_sec":0}

- name: Single day - Date range
Expand Down Expand Up @@ -264,4 +264,4 @@
{"date":"2100-01-04","visits":3,"pageviews":7,"bounce_rate":0.33,"avg_session_sec":572}
{"date":"2100-01-05","visits":2,"pageviews":5,"bounce_rate":0,"avg_session_sec":308}
{"date":"2100-01-06","visits":2,"pageviews":2,"bounce_rate":1,"avg_session_sec":0}
{"date":"2100-01-07","visits":2,"pageviews":2,"bounce_rate":1,"avg_session_sec":0}
{"date":"2100-01-07","visits":3,"pageviews":3,"bounce_rate":1,"avg_session_sec":0}
Loading
Loading