Skip to content

Commit

Permalink
Merge branch 'release/3.4.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
electerious committed May 15, 2022
2 parents c4f5ece + 7a1e893 commit ba976a8
Show file tree
Hide file tree
Showing 26 changed files with 2,224 additions and 2,795 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:

strategy:
matrix:
node-version: [14.x, 16.x]
node-version: [14.x, 16.x, 17.x]
os: [ubuntu-latest, windows-latest, macOS-latest]

steps:
Expand Down
12 changes: 12 additions & 0 deletions 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.4.0] - 2022-05-15

### Added

- Support for Node.js 17 (#302)
- Cache preflight requests (via `Access-Control-Max-Age`) (#261)
- Automatically add CORS headers for domains that have fully qualified domain names as titles ([`ACKEE_AUTO_ORIGIN`](docs/Options.md)) (#271)

### Changed

- MongoDB 4.4 or newer is now required, but older versions still may work

## [3.3.1] - 2022-01-16

You will see a lower unique visitor count after updating. This release contains a fix for the unique visitor count and anonymisation that was broken since 3.2.0. The recorded visits were still anonymous, but Ackee tracked the visit path of each visitor. Data that Ackee normally removes. Data tracked since 3.2.0 are all counted as unique, even if they were not.
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright (c) 2021 Tobias Reich
Copyright (c) Tobias Reich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
6 changes: 5 additions & 1 deletion app.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
"description": "Tracked domains which will be used on Ackee (CORS headers)",
"required": true
},
"ACKEE_AUTO_ORIGIN": {
"description": "Automatically add CORS headers for domains with fully qualified domain names as titles",
"required": false
},
"ACKEE_TTL": {
"description": "Specifies how long an Ackee TTL token is valid (Default: 3600000)",
"required": false
Expand All @@ -34,4 +38,4 @@
"required": false
}
}
}
}
246 changes: 129 additions & 117 deletions dist/index.js

Large diffs are not rendered by default.

15 changes: 12 additions & 3 deletions docs/CORS headers.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, POST, PATCH, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization, Time-Zone
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 3600
```

### Origin
Expand Down Expand Up @@ -52,24 +53,32 @@ The `Access-Control-Allow-Credentials` header tells the browser to include the `
Access-Control-Allow-Credentials: true
```

### Max-Age

The `Access-Control-Max-Age` header tells the browser that all `Access-Control-Allow-*` headers can be cached for one hour. This minimizes the amount of preflight requests.

```
Access-Control-Max-Age: 3600
```

## 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).

As an environment variable, you will need to set:

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

*or*

```
ACKEE_ALLOW_ORIGIN="https://example.com,https://one.example.com,https://two.example.com"
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="*"
ACKEE_ALLOW_ORIGIN=*
```
2 changes: 1 addition & 1 deletion docs/Get started.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ Ackee dependents on …

- [Node.js](https://nodejs.org/en/) (v14 or newer)
- [yarn](https://yarnpkg.com/en/)
- [MongoDB](https://www.mongodb.com) (v4.0.6 or newer)
- [MongoDB](https://www.mongodb.com) (v4.4 or newer)

Make sure to install and update all dependencies before you continue. The installation instructions for the individual dependencies can be found on the linked websites.

Expand Down
12 changes: 9 additions & 3 deletions docs/Options.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,17 +77,23 @@ NODE_ENV=development
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="https://example.com"
ACKEE_ALLOW_ORIGIN=https://example.com
```

*or*

```
ACKEE_ALLOW_ORIGIN="https://example.com,https://one.example.com,https://two.example.com"
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="*"
ACKEE_ALLOW_ORIGIN=*
```

As opposed to manually configuring CORS domains, you can also automatically add CORS Headers for domains in the domain list that have [fully qualified domain names](https://en.wikipedia.org/wiki/Fully_qualified_domain_name) as titles. To achieve this, set:

```
ACKEE_AUTO_ORIGIN=true
```
3 changes: 3 additions & 0 deletions docs/SSL and HTTPS.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ server {
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 Access-Control-Max-Age "3600" always;
add_header Strict-Transport-Security "max-age=31536000" always;
add_header X-Frame-Options deny;
proxy_pass http://localhost:3000;
Expand Down Expand Up @@ -116,6 +117,7 @@ server {
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 Access-Control-Max-Age "3600" always;
add_header Strict-Transport-Security "max-age=31536000" always;
add_header X-Frame-Options deny;
proxy_pass http://localhost:3000;
Expand Down Expand Up @@ -149,6 +151,7 @@ server {
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-Max-Age "3600" always;
add_header Strict-Transport-Security "max-age=31536000" always;
add_header X-Frame-Options deny;
proxy_pass http://localhost:3000;
Expand Down
3 changes: 2 additions & 1 deletion netlify.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@
ACKEE_MONGODB = "ACKEE_MONGODB"
ACKEE_USERNAME = "ACKEE_USERNAME"
ACKEE_PASSWORD = "ACKEE_PASSWORD"
ACKEE_ALLOW_ORIGIN = "ACKEE_ALLOW_ORIGIN"
ACKEE_ALLOW_ORIGIN = "ACKEE_ALLOW_ORIGIN"
ACKEE_AUTO_ORIGIN = "ACKEE_AUTO_ORIGIN"
44 changes: 23 additions & 21 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "ackee",
"private": true,
"version": "3.3.1",
"version": "3.4.0",
"authors": [
"Tobias Reich <[email protected]>"
],
Expand Down Expand Up @@ -33,21 +33,23 @@
"lint": "eslint \"{functions,src,test}/**/*.js\""
},
"dependencies": {
"@graphql-tools/merge": "^8.2.10",
"ackee-tracker": "^5.1.0",
"apollo-server-lambda": "^2.25.1",
"apollo-server-micro": "^2.25.1",
"apollo-server-core": "^3.6.7",
"apollo-server-lambda": "^3.6.7",
"apollo-server-micro": "^3.6.7",
"apollo-server-plugin-http-headers": "^0.1.4",
"date-fns": "^2.24.0",
"date-fns-tz": "^1.1.6",
"date-fns": "^2.28.0",
"date-fns-tz": "^1.3.4",
"debounce-promise": "^3.1.2",
"dotenv": "^10.0.0",
"graphql": "^15.5.3",
"graphql-scalars": "^1.10.1",
"graphql-tools": "^7.0.5",
"dotenv": "^16.0.0",
"graphql": "^16.4.0",
"graphql-scalars": "^1.17.0",
"is-url": "^1.2.4",
"is-valid-domain": "^0.1.6",
"micro": "^9.3.4",
"microrouter": "^3.1.3",
"mongoose": "^6.0.6",
"mongoose": "^6.3.1",
"node-fetch": "^2.6.1",
"node-schedule": "^2.0.0",
"normalize-url": "^6.0.1",
Expand All @@ -57,26 +59,26 @@
"uuid": "^8.3.2"
},
"devDependencies": {
"@apollo/client": "^3.4.12",
"@electerious/eslint-config": "^3.0.0",
"ava": "3.15.0",
"@apollo/client": "^3.6.1",
"@electerious/eslint-config": "^3.1.0",
"ava": "4.2.0",
"classnames": "^2.3.1",
"coveralls": "^3.1.1",
"formbase": "^12.0.2",
"history": "^5.1.0",
"human-number": "^1.0.6",
"history": "^5.3.0",
"human-number": "^1.0.10",
"mocked-env": "^1.3.5",
"mongodb-memory-server": "^8.0.4",
"nodemon": "^2.0.15",
"mongodb-memory-server": "^8.5.2",
"nodemon": "^2.0.16",
"normalize.css": "^8.0.1",
"nyc": "^15.1.0",
"prop-types": "^15.7.2",
"react": "^17.0.2",
"prop-types": "^15.8.1",
"react": "^18.1.0",
"react-apollo-network-status": "^5.0.1",
"react-dom": "^17.0.2",
"react-dom": "^18.1.0",
"react-fast-compare": "^3.2.0",
"react-hotkeys-hook": "^3.4.4",
"react-use": "^17.3.1",
"react-use": "^17.3.2",
"rosid-handler-js-next": "^1.0.1",
"rosid-handler-sass": "^8.0.0",
"s-ago": "^2.2.0",
Expand Down
2 changes: 1 addition & 1 deletion src/resolvers/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict'

const { mergeResolvers } = require('graphql-tools')
const { mergeResolvers } = require('@graphql-tools/merge')

module.exports = mergeResolvers([
require('./tokens'),
Expand Down
19 changes: 13 additions & 6 deletions src/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,19 +69,24 @@ const catchError = (fn) => async (req, res) => {
}
}

const attachCorsHeaders = (fn) => (req, res) => {
const matchingOrigin = findMatchingOrigin(req, config.allowOrigin)
const attachCorsHeaders = (fn) => async (req, res) => {
const matchingOrigin = await findMatchingOrigin(req, config.allowOrigin, config.autoOrigin)

if (matchingOrigin != null) {
res.setHeader('Access-Control-Allow-Origin', matchingOrigin)
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PATCH, OPTIONS')
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, Time-Zone')
res.setHeader('Access-Control-Allow-Credentials', 'true')
res.setHeader('Access-Control-Max-Age', '3600')
}

return fn(req, res)
}

const awaitedHandler = (fn) => async (req, res) => {
return (await fn)(req, res)
}

const notFound = (req) => {
const error = new Error(`\`${ req.url }\` not found`)

Expand All @@ -94,7 +99,9 @@ const apolloServer = createApolloServer(ApolloServer, {
})

const graphqlPath = '/api'
const graphqlHandler = apolloServer.createHandler({ path: graphqlPath })
const apolloHandler = apolloServer
.start()
.then(() => apolloServer.createHandler({ path: graphqlPath }))

const routes = [

Expand Down Expand Up @@ -127,9 +134,9 @@ const routes = [
res.end(await tracker)
}) : undefined,

post(graphqlPath, graphqlHandler),
get(graphqlPath, graphqlHandler),
get('/.well-known/apollo/server-health', graphqlHandler),
post(graphqlPath, awaitedHandler(apolloHandler)),
get(graphqlPath, awaitedHandler(apolloHandler)),
get('/.well-known/apollo/server-health', awaitedHandler(apolloHandler)),

get('/*', notFound),
post('/*', notFound),
Expand Down
49 changes: 36 additions & 13 deletions src/serverless.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const { ApolloServer } = require('apollo-server-lambda')

const config = require('./utils/config')
const connect = require('./utils/connect')
const fullyQualifiedDomainNames = require('./utils/fullyQualifiedDomainNames')
const createApolloServer = require('./utils/createApolloServer')
const { createServerlessContext } = require('./utils/createContext')

Expand All @@ -17,21 +18,43 @@ const apolloServer = createApolloServer(ApolloServer, {
context: createServerlessContext,
})

const origin = (() => {
const origin = (origin, callback) => {
if (config.autoOrigin === true) {
fullyQualifiedDomainNames()
.then((names) => callback(null, names))
.catch((error) => callback(error, false))
return
}

if (config.allowOrigin === '*') {
return true
callback(null, true)
return
}

if (config.allowOrigin != null) {
return config.allowOrigin.split(',')
callback(null, config.allowOrigin.split(','))
return
}
})()

exports.handler = apolloServer.createHandler({
cors: {
origin,
credentials: true,
methods: 'GET,POST,PATCH,OPTIONS',
allowedHeaders: 'Content-Type, Authorization, Time-Zone',
},
})

callback(null, false)
return
}

exports.handler = (event, context) => {
// Set request context which is missing on Vercel
// https://stackoverflow.com/questions/71360059/apollo-server-lambda-unable-to-determine-event-source-based-on-event
if (event.requestContext == null) event.requestContext = context

const handler = apolloServer.createHandler({
expressGetMiddlewareOptions: {
cors: {
origin,
credentials: true,
methods: 'GET,POST,PATCH,OPTIONS',
allowedHeaders: 'Content-Type, Authorization, Time-Zone',
},
},
})

return handler(event, context)
}
2 changes: 1 addition & 1 deletion src/types/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict'

const { mergeTypeDefs } = require('graphql-tools')
const { mergeTypeDefs } = require('@graphql-tools/merge')

module.exports = mergeTypeDefs([
require('./tokens'),
Expand Down
3 changes: 2 additions & 1 deletion src/utils/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const { day } = require('./times')

// Must be a function or object that load and returns the env variables at runtime.
// Must be a function or object that loads and returns the env variables at runtime.
// Otherwise it wouldn't be possible to mock the env variables with mockedEnv.
module.exports = new Proxy({}, {
get: function(target, prop) {
Expand All @@ -11,6 +11,7 @@ module.exports = new Proxy({}, {
port: process.env.ACKEE_PORT || process.env.PORT || 3000,
dbUrl: process.env.ACKEE_MONGODB || process.env.MONGODB_URI,
allowOrigin: process.env.ACKEE_ALLOW_ORIGIN,
autoOrigin: process.env.ACKEE_AUTO_ORIGIN === 'true',
username: process.env.ACKEE_USERNAME,
password: process.env.ACKEE_PASSWORD,
isDemoMode: process.env.ACKEE_DEMO === 'true',
Expand Down
Loading

1 comment on commit ba976a8

@vercel
Copy link

@vercel vercel bot commented on ba976a8 May 15, 2022

Choose a reason for hiding this comment

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

Successfully deployed to the following URLs:

ackee – ./

ackee-electerious.vercel.app
ackee-mocha.vercel.app
ackee-git-master-electerious.vercel.app

Please sign in to comment.