Skip to content

Commit

Permalink
Merge branch 'release/3.0.3'
Browse files Browse the repository at this point in the history
  • Loading branch information
electerious committed Jan 24, 2021
2 parents ec97b7f + 0fd3811 commit f03ffc8
Show file tree
Hide file tree
Showing 22 changed files with 258 additions and 211 deletions.
22 changes: 21 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [3.0.3] - 2021-01-24

### Added

- Missing breaking change notice in the changelog of version 3.0.0 for those using a wildcard `Access-Control-Allow-Origin` header

### Fixed

- Unknown sizes id when a size is zero (#217)
- Prevent unknown id errors like in #217 for other record properties
- Updated ackee-tracker which re-added `ignoreOwnVisits` for those using a wildcard `Access-Control-Allow-Origin` header

## [3.0.2] - 2021-01-21

### Fixed
Expand Down Expand Up @@ -43,6 +55,14 @@ Oh, and we also reduced the JS file size of the UI by ~60%.

### Breaking changes

#### `Access-Control-Allow-Origin: "*"` not recommended

> This change is relevant for you when using a wildcard as the Access-Control-Allow-Origin.
Using a wildcard (`*`) for the `Access-Control-Allow-Origin` header was never recommended as it's neither a secure solution nor does it allow Ackee to ignore your own visits. Please disable the `ignoreOwnVisits` option in ackee-tracker if you're currently using a wildcard. The [SSL and HTTPS](docs/SSL%20and%20HTTPS.md) guide contains better alternatives.

`ignoreOwnVisits` is now enabled by default and won't work when using a wildcard.

#### New `Access-Control-Allow-Credentials` header

> This change is relevant for everyone.
Expand Down Expand Up @@ -273,7 +293,7 @@ The first major back-end and front-end rewrite of Ackee with new API, dashboard,
### Added

- Simply [deploy to Heroku](docs/Get%20started.md#with-heroku) by clicking one button (#72, thanks @aleccool213)
- `ACKEE_ALLOW_ORIGIN` option for [Heroku or other Platforms-As-A-Service](docs/CORS%20headers.md) (#73, thanks @aleccool213)
- `ACKEE_ALLOW_ORIGIN` option for [Platforms-As-A-Service](docs/CORS%20headers.md) (#73, thanks @aleccool213)

## [1.4.2] - 2019-12-19

Expand Down
2 changes: 1 addition & 1 deletion dist/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/tracker.js

Large diffs are not rendered by default.

22 changes: 8 additions & 14 deletions docs/CORS headers.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Ackee requires correct [CORS headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS). [ackee-tracker](https://github.com/electerious/ackee-tracker) (the script that sends data from your sites to Ackee) won't be able to contact your server when the CORS headers aren't available or when they are configured incorrectly.

- [Reverse proxy configuration](#reverse-proxy-configuration)
- [Heroku or Platforms-As-A-Service configuration](#heroku-or-platforms-as-a-service-configuration)
- [Platforms-As-A-Service configuration](#platforms-as-a-service-configuration)

## Why?

Expand All @@ -20,18 +20,12 @@ Access-Control-Allow-Credentials: true

### Origin

Your server needs to allow requests from your sites (recommended) or from all sites (easier to implement, but insecure).
The `Access-Control-Allow-Origin` header only allows one domain. A wildcard (`*`) isn't recommended as it's neither a secure solution nor does it allow Ackee to ignore your own visits. Take a look at our [recommended configuration](SSL%20and%20HTTPS.md#recommended-configuration) if you want to allow requests from multiple domains or disable the `ignoreOwnVisits` option in ackee-tracker if using a wildcard is the only option for you.

```
Access-Control-Allow-Origin: https://example.com
```

```
Access-Control-Allow-Origin: *
```

The `Access-Control-Allow-Origin` header only allows one domain or a wildcard (`*`). Take a look at our [advanced configuration](SSL%20and%20HTTPS.md#advanced-configuration) if you want to allow requests from multiple domains without using the insecure wildcard.

### Methods

[ackee-tracker](https://github.com/electerious/ackee-tracker) needs the permission to send GET, POST, PATCH and OPTIONS requests to the server.
Expand All @@ -58,7 +52,7 @@ The `Access-Control-Allow-Credentials` header tells the browser to include the `
Access-Control-Allow-Credentials: true
```

## Heroku or Platforms-As-A-Service configuration
## Platforms-As-A-Service configuration

If you are running Ackee on a platform which handles SSL for you, you may want a quick solution for setting CORS headers instead of using a [reverse proxy](SSL%20and%20HTTPS.md).

Expand All @@ -68,14 +62,14 @@ As an environment variable, you will need to set:
ACKEE_ALLOW_ORIGIN="https://example.com"
```

The proper header value for `Access-Control-Allow-Origin` will be set with the other headers being the recommended values.

It's also possible to allow requests from all domains (not recommended) or from multiple domains:
*or*

```
ACKEE_ALLOW_ORIGIN="*"
ACKEE_ALLOW_ORIGIN="https://example.com,https://one.example.com,https://two.example.com"
```

Setting a wildcard (`*`) is also supported, but not recommended. It's neither a secure solution nor does it allow Ackee to ignore your own visits. Please disable the `ignoreOwnVisits` option in ackee-tracker if using a wildcard is the only option for you.

```
ACKEE_ALLOW_ORIGIN="https://example.com,https://example2.com"
ACKEE_ALLOW_ORIGIN="*"
```
4 changes: 2 additions & 2 deletions docs/Get started.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ Ackee now runs on port `3000` and is only accessible from you local network. It'

- You need to have a MongoDB instance running (e.g. [MongoDB Atlas](https://www.mongodb.com/cloud/atlas))
- Set a username and password to protect your interface
- Ensure that you're using the correct CORS headers by setting [`ACKEE_ALLOW_ORIGIN`](CORS%20headers.md#heroku-or-platforms-as-a-service-configuration).
- Ensure that you're using the correct CORS headers by setting [`ACKEE_ALLOW_ORIGIN`](CORS%20headers.md#platforms-as-a-service-configuration).

### 3. Updating Ackee

Expand Down Expand Up @@ -214,7 +214,7 @@ Deploy to Heroku by clicking this button:
### 2. Configure Ackee

- You need to have a MongoDB instance running, either hosting it yourself, using [MongoDB Atlas](https://www.mongodb.com/cloud/atlas) or by using a (paid) add-on like [ObjectRocket MongoDB](https://elements.heroku.com/addons/ormongo). This is as simple as typing `heroku addons:create ormongo:2-wt --app <YOUR_APP_NAME>` using the CLI, or using the web dashboard; more details at the [official documentation](https://devcenter.heroku.com/articles/managing-add-ons). You'll need to provide connection details to Ackee dyno, either from the web dashboard or via command line, e.g. `heroku config:add "ACKEE_MONGODB=mongodb://<host>:<port>/<db>"`
- Ensure that you're using the correct CORS headers by setting [`ACKEE_ALLOW_ORIGIN`](CORS%20headers.md#heroku-or-platforms-as-a-service-configuration).
- Ensure that you're using the correct CORS headers by setting [`ACKEE_ALLOW_ORIGIN`](CORS%20headers.md#platforms-as-a-service-configuration).

### 3. Updating Ackee

Expand Down
10 changes: 5 additions & 5 deletions docs/Options.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,20 +74,20 @@ NODE_ENV=development

## CORS headers

Quick solution for setting [CORS headers](CORS%20headers.md) instead of using a [reverse proxy](SSL%20and%20HTTPS.md). This is helpful if you are running Ackee on a platform which handles SSL for you.
Quick solution for setting [CORS headers](CORS%20headers.md) instead of using a [reverse proxy](SSL%20and%20HTTPS.md). This is helpful if you are running Ackee on a platform that handles SSL for you.

```
ACKEE_ALLOW_ORIGIN="*"
ACKEE_ALLOW_ORIGIN="https://example.com"
```

*or*

```
ACKEE_ALLOW_ORIGIN="https://example.com"
ACKEE_ALLOW_ORIGIN="https://example.com,https://one.example.com,https://two.example.com"
```

*or*
Setting a wildcard (`*`) is also supported, but not recommended. It's neither a secure solution nor does it allow Ackee to ignore your own visits. Please disable the `ignoreOwnVisits` option in ackee-tracker if using a wildcard is the only option for you.

```
ACKEE_ALLOW_ORIGIN="https://example.com,https://example2.com"
ACKEE_ALLOW_ORIGIN="*"
```
111 changes: 75 additions & 36 deletions docs/SSL and HTTPS.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,45 +14,15 @@ I highly recommend [this article](https://medium.com/intrinsic/why-should-i-use-

### nginx

#### Basic configuration
- [Recommended configuration](#recommended-configuration)
- [Single domain configuration](#single-domain-configuration)
- [Insecure wildcard configuration](#insecure-wildcard-configuration)

This configuration secures all connections using TSL/SSL and gives any domain permission to access Ackee.
#### Recommended configuration

> 👉 The CORS headers are required so all your sites can send data to Ackee, even when their domain is different to the one Ackee uses. Take a look at the next example to tighten the CORS headers.
This configuration redirects all requests to the non-www domain `example.com`, secures connections using TSL/SSL and allows CORS requests from a list of known domains.

```conf
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
access_log /var/log/nginx/log/example.com.access.log main;
error_log /var/log/nginx/log/example.com.error.log;
location / {
add_header Access-Control-Allow-Origin "*" always;
add_header Access-Control-Allow-Methods "GET, POST, PATCH, OPTIONS" always;
add_header Access-Control-Allow-Headers "Content-Type, Authorization, Time-Zone" always;
add_header Access-Control-Allow-Credentials "true" always;
add_header Strict-Transport-Security "max-age=31536000" always;
add_header X-Frame-Options deny;
proxy_pass http://localhost:3000;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_redirect off;
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
```

#### Advanced configuration

This configuration redirects all requests to the non-www domain `example.com` and adds the CORS headers only for known domains. It also secures connections using TSL/SSL.
> 👉 The CORS headers are required so your sites can send data to Ackee, even when their domain is different to the one Ackee uses.
```conf
#
Expand Down Expand Up @@ -122,3 +92,72 @@ server {
}
}
```

#### Single domain configuration

This configuration secures all connections using TSL/SSL and allows `https://example.com` to send data to `https://ackee.example.com`.

> ℹ️ This configuration only allows requests from a single domain. Take a look at our [recommended configuration](#recommended-configuration) if you want to allow requests from multiple domains or use the [insecure wildcard configuration](#insecure-wildcard-configuration).
```conf
server {
listen 443 ssl http2;
server_name ackee.example.com;
ssl_certificate /etc/letsencrypt/live/ackee.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/ackee.example.com/privkey.pem;
access_log /var/log/nginx/log/ackee.example.com.access.log main;
error_log /var/log/nginx/log/ackee.example.com.error.log;
location / {
add_header Access-Control-Allow-Origin "https://example.com" always;
add_header Access-Control-Allow-Methods "GET, POST, PATCH, OPTIONS" always;
add_header Access-Control-Allow-Headers "Content-Type, Authorization, Time-Zone" always;
add_header Access-Control-Allow-Credentials "true" always;
add_header Strict-Transport-Security "max-age=31536000" always;
add_header X-Frame-Options deny;
proxy_pass http://localhost:3000;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_redirect off;
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
```

#### Insecure wildcard configuration

A wildcard (`*`) isn't recommended as it's neither a secure solution nor does it allow Ackee to ignore your own visits. Please disable the `ignoreOwnVisits` option in ackee-tracker if using a wildcard is the only option for you.

```conf
server {
listen 443 ssl http2;
server_name ackee.example.com;
ssl_certificate /etc/letsencrypt/live/ackee.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/ackee.example.com/privkey.pem;
access_log /var/log/nginx/log/ackee.example.com.access.log main;
error_log /var/log/nginx/log/ackee.example.com.error.log;
location / {
add_header Access-Control-Allow-Origin "*" always;
add_header Access-Control-Allow-Methods "GET, POST, PATCH, OPTIONS" always;
add_header Access-Control-Allow-Headers "Content-Type, Authorization, Time-Zone" always;
add_header Strict-Transport-Security "max-age=31536000" always;
add_header X-Frame-Options deny;
proxy_pass http://localhost:3000;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_redirect off;
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
```
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "ackee",
"private": true,
"version": "3.0.2",
"version": "3.0.3",
"authors": [
"Tobias Reich <tobias@electerious.com>"
],
Expand Down Expand Up @@ -33,7 +33,7 @@
"lint": "eslint '{functions,src,test}/**/*.js'"
},
"dependencies": {
"ackee-tracker": "^5.0.0",
"ackee-tracker": "^5.0.1",
"apollo-server-lambda": "^2.19.2",
"apollo-server-micro": "^2.19.2",
"apollo-server-plugin-http-headers": "^0.1.4",
Expand All @@ -47,7 +47,7 @@
"is-url": "^1.2.4",
"micro": "^9.3.4",
"microrouter": "^3.1.3",
"mongoose": "^5.11.12",
"mongoose": "^5.11.13",
"node-fetch": "^2.6.1",
"node-schedule": "^1.3.2",
"normalize-url": "^5.0.0",
Expand Down
14 changes: 7 additions & 7 deletions src/database/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ const update = async (id, data) => {

const getChart = async (ids, type, interval, limit, dateDetails) => {

const aggregation = (() => {

if (type === 'TOTAL') return aggregateActions(ids, false, interval, limit, dateDetails)
if (type === 'AVERAGE') return aggregateActions(ids, true, interval, limit, dateDetails)

})()

const enhance = (entries) => {

const matchDay = [ intervals.INTERVALS_DAILY ].includes(interval)
Expand Down Expand Up @@ -92,13 +99,6 @@ const getChart = async (ids, type, interval, limit, dateDetails) => {

}

const aggregation = (() => {

if (type === 'TOTAL') return aggregateActions(ids, false, interval, limit, dateDetails)
if (type === 'AVERAGE') return aggregateActions(ids, true, interval, limit, dateDetails)

})()

return enhance(
await Action.aggregate(aggregation)
)
Expand Down
31 changes: 17 additions & 14 deletions src/database/browsers.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,9 @@ const aggregateNewRecords = require('../aggregations/aggregateNewRecords')
const aggregateRecentRecords = require('../aggregations/aggregateRecentRecords')
const sortings = require('../constants/sortings')
const constants = require('../constants/browsers')
const bestMatch = require('../utils/bestMatch')

const get = async (ids, sorting, type, range, limit, dateDetails) => {

const enhance = (entries) => {

return entries.map((entry) => ({
id: bestMatch([
[ `${ entry._id.browserName } ${ entry._id.browserVersion }`, [ entry._id.browserName, entry._id.browserVersion ]],
[ `${ entry._id.browserName }`, [ entry._id.browserName ]]
]),
count: entry.count,
created: entry.created
}))

}

const aggregation = (() => {

if (type === constants.BROWSERS_TYPE_NO_VERSION) {
Expand All @@ -38,6 +24,23 @@ const get = async (ids, sorting, type, range, limit, dateDetails) => {

})()

const enhanceId = (id) => {

if (type === constants.BROWSERS_TYPE_NO_VERSION) return `${ id.browserName }`
if (type === constants.BROWSERS_TYPE_WITH_VERSION) return `${ id.browserName } ${ id.browserVersion }`

}

const enhance = (entries) => {

return entries.map((entry) => ({
id: enhanceId(entry._id),
count: entry.count,
created: entry.created
}))

}

return enhance(
await Record.aggregate(aggregation)
)
Expand Down
Loading

1 comment on commit f03ffc8

@vercel
Copy link

@vercel vercel bot commented on f03ffc8 Jan 24, 2021

Choose a reason for hiding this comment

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

Please sign in to comment.