@spaship/api
Advanced tools
Comparing version 0.5.0 to 0.6.0
@@ -6,2 +6,16 @@ # Change Log | ||
# [0.6.0](https://github.com/spaship/spaship/compare/v0.5.0...v0.6.0) (2020-03-26) | ||
### Bug Fixes | ||
- **api:** dont cache invalid response from autosync ([#243](https://github.com/spaship/spaship/issues/243)) ([af57dc0](https://github.com/spaship/spaship/commit/af57dc0349477838b61d5fe9377fa4fd0524c2a7)) | ||
- **api:** exclude invalid spa paths ([#241](https://github.com/spaship/spaship/issues/241)) ([444db20](https://github.com/spaship/spaship/commit/444db202fb1a7a838ad39c8d87be9dba25888b68)) | ||
- **api:** fix connection to mongodb ([#216](https://github.com/spaship/spaship/issues/216)) ([2342c66](https://github.com/spaship/spaship/commit/2342c66ce414603d40ba5dafb96f8aaee72e9d31)) | ||
### Features | ||
- **api:** add jwt and api key validation to the api ([#218](https://github.com/spaship/spaship/issues/218)) ([0d5437f](https://github.com/spaship/spaship/commit/0d5437ff1677d658c6d42f7d06b7d822bd8b7e8d)) | ||
- **api:** use UUID v4 format for API keys ([#223](https://github.com/spaship/spaship/issues/223)) ([3eff190](https://github.com/spaship/spaship/commit/3eff190271bbc215bcf3bd4c611fc4928c6157a6)) | ||
- **apiKeys:** add REST endpoints for managing API keys. ([#204](https://github.com/spaship/spaship/issues/204)) ([618f8b1](https://github.com/spaship/spaship/commit/618f8b1bc94793da660699f90de4482540d59ee3)) | ||
# [0.5.0](https://github.com/spaship/spaship/compare/v0.4.0...v0.5.0) (2020-03-09) | ||
@@ -8,0 +22,0 @@ |
const path = require("path"); | ||
const nconf = require("nconf"); | ||
const { uniq } = require("lodash"); | ||
const { mapValues, flow, keyBy, identity } = require("lodash/fp"); | ||
@@ -10,16 +11,36 @@ | ||
const validOptions = [ | ||
let validOptions = [ | ||
// filesystem related | ||
"config_file", | ||
"upload_dir", | ||
"webroot", | ||
// network service options | ||
"host", | ||
"port", | ||
// autosync stands alone | ||
"autosync", | ||
"mongo_user", | ||
"mongo_password", | ||
"mongo_url", | ||
"mock_db" | ||
// database | ||
"db:mongo:user", | ||
"db:mongo:password", | ||
"db:mongo:url", | ||
"db:mongo:db_name", | ||
"db:mongo:mock", | ||
// authentication | ||
"auth:keycloak:url", | ||
"auth:keycloak:realm", | ||
"auth:keycloak:pubkey", | ||
"auth:keycloak:pubkey_file", | ||
"auth:keycloak:clientid", | ||
"auth:keycloak:id_prop" | ||
]; | ||
const filepathOptions = ["config_file", "upload_dir", "webroot"]; // config options that represent filepaths | ||
// expand validOptions to include the nesting separator for environment variables (they use __ instead of :, since : is | ||
// an invalid character in env var names). | ||
validOptions = uniq(validOptions.concat(validOptions.map(p => p.replace(/:/g, "__")))); | ||
// Read CLI flags first, then environment variables (argv). | ||
@@ -43,2 +64,3 @@ nconf | ||
.env({ | ||
separator: "__", | ||
whitelist: validOptions, | ||
@@ -60,8 +82,3 @@ lowerCase: true, | ||
nconf.file({ | ||
file: configFile, | ||
transform: obj => { | ||
// use underscore as delimeter | ||
obj.key = obj.key.replace(/-/g, "_"); | ||
return obj; | ||
} | ||
file: configFile | ||
}); | ||
@@ -75,7 +92,14 @@ } | ||
upload_dir: "/tmp/spaship_uploads", | ||
mongo_user: null, | ||
mongo_password: null, | ||
mongo_url: "localhost:27017", | ||
mongo_db: "spaship", | ||
mock_db: process.env.NODE_ENV !== "production" // use a mock database by default in dev environments | ||
db: { | ||
mongo: { | ||
url: "localhost:27017", | ||
db_name: "spaship", | ||
mock: process.env.NODE_ENV !== "production" // use a mock database by default in dev environments | ||
} | ||
}, | ||
auth: { | ||
keycloak: { | ||
jwt_uuid_prop: "sub" | ||
} | ||
} | ||
}); | ||
@@ -82,0 +106,0 @@ |
#!/usr/bin/env node | ||
const express = require("express"); | ||
const bodyParser = require("body-parser"); | ||
@@ -16,2 +17,6 @@ const { log, pinoExpress } = require("@spaship/common/lib/logging/pino"); | ||
// BodyParser for parsing application/json and for parsing application/x-www-form-urlencoded | ||
app.use(bodyParser.json()); | ||
app.use(bodyParser.urlencoded({ extended: true })); | ||
routes.register(app); | ||
@@ -18,0 +23,0 @@ |
@@ -116,3 +116,3 @@ const ms = require("ms"); | ||
try { | ||
if (response) { | ||
if (response && response.status === 200) { | ||
// Make sure dest path exists | ||
@@ -130,2 +130,4 @@ let exists = await this.isDirectory(path); | ||
return true; | ||
} else { | ||
log.error("[Autosync] Invalid response while trying to get url:", url, response.status); | ||
} | ||
@@ -132,0 +134,0 @@ } catch (error) { |
const db = require("./db"); | ||
const shortid = require("shortid"); | ||
const uuidv4 = require("uuid").v4; | ||
const shajs = require("sha.js"); | ||
@@ -9,9 +9,7 @@ | ||
function hash(apikey) { | ||
return shajs("sha256") | ||
.update(apikey) | ||
.digest("hex"); | ||
return shajs("sha256").update(apikey).digest("hex"); | ||
} | ||
async function createKey(userid = null) { | ||
const apikey = shortid.generate(); | ||
const apikey = uuidv4(); | ||
const doc = { userid, apikey }; | ||
@@ -29,3 +27,3 @@ await storeKey(doc); | ||
userid: doc.userid, | ||
apikey: hash(doc.apikey) | ||
apikey: hash(doc.apikey), | ||
}); | ||
@@ -35,10 +33,9 @@ } | ||
async function deleteKey(apikey) { | ||
await apikeys.deleteMany({ apikey }); | ||
const keys = await apikeys.find({ apikey }).toArray(); | ||
const result = keys.length ? await apikeys.deleteMany({ apikey }) : { error: "Hashed key not found" }; | ||
return result; | ||
} | ||
async function getKeysByUser(userid, limit = 100) { | ||
return await apikeys | ||
.find({ userid }) | ||
.limit(limit) | ||
.toArray(); | ||
return await apikeys.find({ userid }).limit(limit).toArray(); | ||
} | ||
@@ -53,5 +50,15 @@ | ||
return { getKeysByUser, getUserByKey, createKey, deleteKey }; | ||
async function getUserByHashedKey(apikey, limit = 100) { | ||
return await apikeys.find({ apikey }).limit(limit).toArray(); | ||
} | ||
async function deleteKeysByUser(userid) { | ||
const users = await apikeys.find({ userid }).toArray(); | ||
const result = users.length ? await apikeys.deleteMany({ userid }) : { error: "User not found" }; | ||
return result; | ||
} | ||
return { getKeysByUser, getUserByKey, getUserByHashedKey, deleteKeysByUser, createKey, deleteKey }; | ||
} | ||
module.exports = { attach }; |
@@ -1,2 +0,2 @@ | ||
const shortid = require("shortid"); | ||
const uuid = require("uuid"); | ||
const mockfs = require("mock-fs"); | ||
@@ -6,10 +6,10 @@ const db_apikey = require("./db.apikey"); | ||
// make shortid non-random while testing | ||
jest.mock("shortid"); | ||
shortid.generate.mockResolvedValue("MOCK_KEY"); | ||
// make uuid non-random while testing | ||
jest.mock("uuid"); | ||
uuid.v4.mockResolvedValue("MOCK_KEY"); | ||
// override some configuration values | ||
config.get = jest.fn(opt => { | ||
config.get = jest.fn((opt) => { | ||
const fakeConfig = { | ||
webroot: "/fake/webroot" | ||
webroot: "/fake/webroot", | ||
}; | ||
@@ -41,3 +41,3 @@ return fakeConfig[opt]; | ||
// special mock key for this test | ||
shortid.generate.mockReturnValueOnce("fake.key"); | ||
uuid.v4.mockReturnValueOnce("fake.key"); | ||
@@ -56,3 +56,3 @@ const doc = await apikeys.createKey("fake.name"); | ||
// special mock key for this test | ||
shortid.generate.mockReturnValueOnce(apikey); | ||
uuid.v4.mockReturnValueOnce(apikey); | ||
@@ -72,3 +72,3 @@ await apikeys.createKey(userid); | ||
// special mock key for this test | ||
shortid.generate.mockReturnValueOnce(apikey); | ||
uuid.v4.mockReturnValueOnce(apikey); | ||
@@ -81,2 +81,18 @@ await apikeys.createKey(userid); | ||
test("should be able to get userid by hashedapikey", async () => { | ||
const apikeys = await db_apikey.attach(); | ||
const userid = "babyyoda"; | ||
const apikey = "018265271839"; | ||
const apikeyhash = "fdf1fcb03dab8d28a97d2ab228225a196b9d99f0b3e1a2c1f6a05165ccb1d255"; | ||
// special mock key for this test | ||
uuid.v4.mockReturnValueOnce(apikeyhash); | ||
await apikeys.createKey(userid); | ||
const doc = await apikeys.getUserByHashedKey(apikeyhash); | ||
console.log(doc); | ||
expect(doc).toMatchObject([{ userid, apikey: apikeyhash }]); | ||
}); | ||
test("should be able to delete a key", async () => { | ||
@@ -88,3 +104,3 @@ const apikeys = await db_apikey.attach(); | ||
// special mock key for this test | ||
shortid.generate.mockReturnValueOnce(apikey); | ||
uuid.v4.mockReturnValueOnce(apikey); | ||
@@ -91,0 +107,0 @@ // create key, delete it, then check for its existance |
@@ -7,34 +7,6 @@ /** | ||
const mongoPkg = config.get("mock_db") ? "mongo-mock" : "mongodb"; | ||
const mongodb = require(mongoPkg); | ||
mongodb.max_delay = 0; //you can choose to NOT pretend to be async (default is 400ms) | ||
const MongoClient = mongodb.MongoClient; | ||
MongoClient.persist = "mock-db.js"; //persist the data to disk | ||
// Connection URL | ||
const connectUrls = ["mongodb://"]; | ||
if (config.get("mongo_user") && config.get("mongo_password")) { | ||
connectUrls.push(`${config.get("mongo_user")}:${config.get("mongo_password")}@`); | ||
if (config.get("db:mongo:mock")) { | ||
module.exports = require("./db.mongo-mock.js"); | ||
} else { | ||
module.exports = require("./db.mongo.js"); | ||
} | ||
connectUrls.push(config.get("mongo_url")); | ||
connectUrls.push(`/${config.get("mongo_db")}`); | ||
const url = connectUrls.join(""); | ||
let reusableClient; | ||
async function connect(collectionName) { | ||
if (!collectionName) { | ||
throw new Error("db.connect must be given a collection name"); | ||
} | ||
// if a connection is already open, use it | ||
if (reusableClient) { | ||
return reusableClient.collection(collectionName); | ||
} | ||
// otherwise, connect | ||
reusableClient = await MongoClient.connect(url, {}); | ||
return reusableClient.collection(collectionName); | ||
} | ||
module.exports = { connect }; |
@@ -16,3 +16,4 @@ const path = require("path"); | ||
const webrootFiles = await fsp.readdir(config.get("webroot")); | ||
const spaDirs = flow(map(get))(webrootFiles); | ||
const validFiles = webrootFiles.filter(fileName => /^(?![_\.])[a-zA-Z0-9\_\-]*$/.test(fileName)); | ||
const spaDirs = flow(map(get))(validFiles); | ||
return await Promise.all(spaDirs); | ||
@@ -19,0 +20,0 @@ } catch (e) { |
@@ -36,3 +36,4 @@ const metadata = require("./metadata"); | ||
// some non-SPAs in the webroot | ||
chrome: {}, | ||
_include: {}, | ||
_test1: {}, | ||
".htaccess": "# global htaccess file" | ||
@@ -78,9 +79,2 @@ } | ||
deploykey: "arfgrn" | ||
}, | ||
// some non-SPAs in the webroot | ||
{ | ||
path: "/.htaccess" | ||
}, | ||
{ | ||
path: "/chrome" | ||
} | ||
@@ -87,0 +81,0 @@ ]; |
{ | ||
"name": "@spaship/api", | ||
"version": "0.5.0", | ||
"version": "0.6.0", | ||
"description": "The file synchronization service for the SPAship platform.", | ||
@@ -22,3 +22,4 @@ "homepage": "https://github.com/spaship/spaship/tree/master/packages/api#readme", | ||
"dev": "nodemon index.js", | ||
"test": "../../node_modules/.bin/jest --restoreMocks" | ||
"test": "../../node_modules/.bin/jest --restoreMocks", | ||
"get-pubkey": "node scripts/fetchpk.js" | ||
}, | ||
@@ -29,4 +30,5 @@ "keywords": [], | ||
"dependencies": { | ||
"@spaship/common": "^0.5.0", | ||
"@spaship/common": "^0.6.0", | ||
"axios": "^0.19.0", | ||
"body-parser": "^1.19.0", | ||
"cors": "^2.8.5", | ||
@@ -38,2 +40,3 @@ "decompress": "^4.2.0", | ||
"express": "^4.17.1", | ||
"express-jwt": "^5.3.1", | ||
"express-pino-logger": "^4.0.0", | ||
@@ -50,6 +53,9 @@ "lodash": "^4.17.15", | ||
"tmp-promise": "^2.0.2", | ||
"url-join": "^4.0.1" | ||
"url-join": "^4.0.1", | ||
"uuid": "^7.0.2", | ||
"uuid-validate": "0.0.3", | ||
"validator": "^12.2.0" | ||
}, | ||
"devDependencies": { | ||
"mongo-mock": "3.9.0" | ||
"mongo-mock": "4.0.0" | ||
}, | ||
@@ -59,3 +65,3 @@ "publishConfig": { | ||
}, | ||
"gitHead": "e964423b0c185b35d1adeee1465ca55ce1df0d45" | ||
"gitHead": "a82a07fa6f0f337b753593a03a9dd046bb0e00d1" | ||
} |
@@ -7,3 +7,3 @@ # SPAship API | ||
``` | ||
```bash | ||
npm install -g @spaship/api | ||
@@ -15,3 +15,3 @@ spaship-api | ||
``` | ||
```bash | ||
git@github.com:spaship/api.git | ||
@@ -44,18 +44,24 @@ npm install | ||
| Option | Description | CLI | Env | config.json | Default | | ||
| ------------------ | ------------------------------------------------------------------------------------------ | ------------------ | ------------------------ | ------------------ | ---------------------------------------------- | | ||
| **config file** | Where to find the config file. | `--config-file` | `SPASHIP_API_CONFIG_FILE`| N/A | none | | ||
| **upload dir** | Directory to upload SPA archives. | `--upload-dir` | `SPASHIP_UPLOAD_DIR` | `"upload_dir"` | `/tmp/spaship_uploads` | | ||
| **webroot** | Directory to extract/deploy SPAs. | `--webroot` | `SPASHIP_WEBROOT` | `"webroot"` | `/var/www` | | ||
| **host** | Hostname to run on. | `--host` | `SPASHIP_HOST` | `"host"` | `localhost` | | ||
| **port** | Port to run on. | `--port` | `SPASHIP_API_PORT` | `"port"` | `8008` | | ||
| **log-level** | Granularity of log messages to print. | `--log-level` | `SPASHIP_LOG_LEVEL` | `"log_level"` | `info` | | ||
| **log-format** | `pretty` for human-friendly logs, `json` for machine-friendly logs. | `--log-format` | `SPASHIP_LOG_FORMAT` | `"log_format"` | `pretty` | | ||
| **mongo_url** | The hosts of your mongodb instance. | `--mongo-url` | `SPASHIP_MONGO_URL` | `"mongo_url"` | `"localhost:27017"` | | ||
| **mongo_user** | (Optional) The username of your mongodb instance. | `--mongo-user` | `SPASHIP_MONGO_USER` | `"mongo_user"` | `null` | | ||
| **mongo_password** | (Optional) The password of your mongodb instance. | `--mongo-password` | `SPASHIP_MONGO_PASSWORD` | `"mongo_password"` | `null` | | ||
| **mongo_db** | The mongodb database name. | `--mongo-db` | `SPASHIP_MONGO_DB` | `"mongo_db"` | `"spaship"` | | ||
| **mock_db** | Whether to use a mock database ([mongo-mock](https://github.com/williamkapke/mongo-mock)). | `--mock-db` | `SPASHIP_MOCK_DB` | `"mock_db"` | `true`, except when `NODE_ENV == "production"` | | ||
| Option | Description | CLI | Env | config.json | Default | | ||
| ---------------------------- | ------------------------------------------------------------------------------ | ----------------------------- | ------------------------------------- | --------------------------- | ------------------------------------------------------- | | ||
| **config file** | Where to find the config file. | `--config-file` | `SPASHIP_API_CONFIG_FILE` | N/A | none | | ||
| **upload dir** | Directory to upload SPA archives. | `--upload-dir` | `SPASHIP_UPLOAD_DIR` | `"upload_dir"` | `/tmp/spaship_uploads` | | ||
| **webroot** | Directory to extract/deploy SPAs. | `--webroot` | `SPASHIP_WEBROOT` | `"webroot"` | `/var/www` | | ||
| **host** | Hostname to run on. | `--host` | `SPASHIP_HOST` | `"host"` | `localhost` | | ||
| **port** | Port to run on. | `--port` | `SPASHIP_API_PORT` | `"port"` | `8008` | | ||
| **log-level** | Granularity of log messages to print. | `--log-level` | `SPASHIP_LOG_LEVEL` | `"log_level"` | `info` | | ||
| **log-format** | `pretty` for human-friendly logs, `json` for machine-friendly logs. | `--log-format` | `SPASHIP_LOG_FORMAT` | `"log_format"` | `pretty` | | ||
| **mongo_url** | The hosts of your mongodb instance. | `--db:mongo:url` | `SPASHIP_DB__MONGO__URL` | `"db.mongo.url"` | `"localhost:27017"` | | ||
| **mongo_user** | (Optional) The username of your mongodb instance. | `--db:mongo:user` | `SPASHIP_DB__MONGO__USER` | `"db.mongo.user"` | `null` | | ||
| **mongo_password** | (Optional) The password of your mongodb instance. | `--db:mongo:password` | `SPASHIP_DB__MONGO__PASSWORD` | `"db.mongo.password"` | `null` | | ||
| **mongo_db** | The mongodb database name. | `--db:mongo:db_name` | `SPASHIP_DB__MONGO__DB_NAME` | `"db.mongo.db_name"` | `"spaship"` | | ||
| **mock_db** | Whether to use a mock database ([mongo-mock][mongo-mock]). | `--db:mongo:mock` | `SPASHIP_DB__MONGO__MOCK` | `"db.mongo.mock"` | `true` for dev, `false` when `NODE_ENV == "production"` | | ||
| **Keycloak URL** | The URL to a Keycloak instance you wish to use for authentication.<sup>2</sup> | `--auth:keycloak:url` | `SPASHIP_AUTH__KEYCLOAK__URL` | `auth.keycloak.url` | none | | ||
| **Keycloak REALM** | The Keycloak Realm under which your SPAship Manager client is registered. | `--auth:keycloak:realm` | `SPASHIP_AUTH__KEYCLOAK__REALM` | `auth.keycloak.realm` | none | | ||
| **Keycloak client id** | The Keycloak client id for your SPAship Manager instance. | `--auth:keycloak:client-id` | `SPASHIP_AUTH__KEYCLOAK__CLIENTID` | `auth.keycloak.clientid` | none | | ||
| **JWT user UUID prop** | The JWT property to treat as a UUID.<sup>3</sup> | `--auth:keycloak:id_prop` | `SPASHIP_AUTH__KEYCLOAK__ID_PROP` | `auth.keycloak.id_prop` | `"sub"` <sup>4</sup> | | ||
| **Keycloak public key** | Your Keycloak realm's public key. | `--auth:keycloak:pubkey` | `SPASHIP_AUTH__KEYCLOAK__PUBKEY` | `auth.keycloak.pubkey` | none | | ||
| **Keycloak public key file** | A file path to your Keycloak realm's public key. | `--auth:keycloak:pubkey_file` | `SPASHIP_AUTH__KEYCLOAK__PUBKEY_FILE` | `auth.keycloak.pubkey_file` | none | | ||
**Note** about the filepath configurations, `config file`, `upload dir`, and `webroot`: they must be absolute paths when defined in an environment variable or config file. When defined in CLI options like, they can be written relative to CWD. Example: `--config-file=./config.json` | ||
**Note:** the filepath configurations (`config file`, `upload dir`, and `webroot`) must be absolute paths when defined in an environment variable or config file. When defined in CLI options like, they can be written relative to CWD. Example: `--config-file=../config.json`. | ||
@@ -70,3 +76,3 @@ **Note:** When `mock_db` is on, the mocked database will be persisted as a flat file named `mock-db.js` right here in the same directory as this README. | ||
``` | ||
```bash | ||
www | ||
@@ -88,3 +94,3 @@ ├── .my-app | ||
``` | ||
```bash | ||
NAME="My Awesome Application" | ||
@@ -131,1 +137,25 @@ SPA_PATH="/my-app" | ||
- The "SPAnonymous" app has `null` values for name and ref because it was not deployed with `/deploy`, but it's included so that `/list` provides a complete report of what paths are being made available. | ||
## Scripts | ||
During development, this repo includes a handy script (`npm run get-pubkey`) for downloading your Keycloak server's public key. It accepts the same `auth:keycloak:url` and `auth:keycloak:realm` options as the API itself. You can run it as follows: | ||
``` | ||
npm run get-pubkey -- --auth:keycloak:url https://auth.spaship.io --auth:keycloak:realm SPAshipUsers | ||
``` | ||
_(Just like the API, it also accepts environment variables or a config file instead of CLI options.)_ | ||
After running the script, a `.key` file will be saved in your current directory. You can reference that file in the `auth:keycloak:pubkey_file` configuration option. | ||
[mongo-mock]: https://github.com/williamkapke/mongo-mock | ||
### /apikeys | ||
| HTTP Method | Endpoint | Description | | ||
| ----------- | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| `POST` | `/apikey` | Creates and returns an API key object such as `{ key: "ABCD" }`. It expects the body of the request body to contain an user id as `{ user: "babyyoda" }` | | ||
| `DELETE` | `/apikey?hashedKey=e12e115a` | Deletes key ABCD (hashed to "e12e115a") | | ||
| `GET` | `/apikey?user=babyyoda` | Returns an API key object such as `{ user: "babyyoda", key: "ABCD" }` | | ||
| `GET` | `/user?hashedKey=e12e115a` | Returns an API key object such as `{ user: "babyyoda" }` | | ||
| `DELETE` | `/user?user=babyyoda` | Deletes all API keys for user `babyyoda` | |
const Autosync = require("../../lib/background/autosync"); | ||
// Return a function for getting list of deployed spas and info about them | ||
module.exports = function createAutosyncMiddleware() { | ||
@@ -5,0 +4,0 @@ const autosync = new Autosync(); |
@@ -5,3 +5,3 @@ const fs = require("fs"); | ||
// include our middlewares | ||
// include our endpoint middlewares | ||
const forceSyncAll = require("./forceSyncAll/forceSyncAllMiddleware"); | ||
@@ -11,5 +11,17 @@ const deploy = require("./deploy/deployMiddleware"); | ||
const getAPIKeysByUser = require("./apikeys/key/getKeysByUserMiddleware"); | ||
const deleteAPIKeysByUser = require("./apikeys/user/deleteKeysByUserMiddleware"); | ||
const getUserByAPIKey = require("./apikeys/user/getUserByKeyMiddleware"); | ||
const createAPIKey = require("./apikeys/key/createKeyMiddleware"); | ||
const deleteAPIKey = require("./apikeys/key/deleteKeyMiddleware"); | ||
// include our auth middlewares | ||
const auth = require("./authMiddleware"); | ||
const jwt = require("./jwtMiddleware"); | ||
const apiKey = require("./apiKeyMiddleware"); | ||
const cors = corsMiddleware({ | ||
origin: true, | ||
credentials: true | ||
credentials: true, | ||
}); | ||
@@ -25,3 +37,3 @@ | ||
.route("/deploy") | ||
.post(cors, ...deploy()) | ||
.post(cors, auth(jwt(), apiKey()), ...deploy()) | ||
.get((req, res) => { | ||
@@ -33,7 +45,18 @@ fs.readFile(path.resolve(__dirname, "..", "index.html"), (err, data) => { | ||
app.route("/list").get(cors, list()); | ||
app.route("/list").get(cors, auth(apiKey(), jwt()), list()).options(cors); // for CORS preflight | ||
app.post("/autosync/forceSyncAll", cors, forceSyncAll()); | ||
app.post("/autosync/forceSyncAll", cors, auth(apiKey(), jwt()), forceSyncAll()); | ||
// API Keys | ||
app | ||
.route("/apikey") | ||
.get(cors, auth(jwt(), apiKey()), getAPIKeysByUser()) | ||
.post(cors, auth(jwt()), createAPIKey()) | ||
.delete(cors, auth(jwt(), apiKey()), deleteAPIKey()); | ||
app | ||
.route("/user") | ||
.get(cors, auth(jwt(), apiKey()), getUserByAPIKey()) | ||
.delete(cors, auth(jwt(), apiKey()), deleteAPIKeysByUser()); | ||
} | ||
module.exports = { register }; |
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
75433
34
1149
156
25
12
1
+ Addedbody-parser@^1.19.0
+ Addedexpress-jwt@^5.3.1
+ Addeduuid@^7.0.2
+ Addeduuid-validate@0.0.3
+ Addedvalidator@^12.2.0
+ Added@spaship/common@0.6.0(transitive)
+ Addedbuffer-equal-constant-time@1.0.1(transitive)
+ Addedecdsa-sig-formatter@1.0.11(transitive)
+ Addedexpress-jwt@5.3.3(transitive)
+ Addedexpress-unless@0.3.1(transitive)
+ Addedjsonwebtoken@8.5.1(transitive)
+ Addedjwa@1.4.1(transitive)
+ Addedjws@3.2.2(transitive)
+ Addedlodash.includes@4.3.0(transitive)
+ Addedlodash.isboolean@3.0.3(transitive)
+ Addedlodash.isinteger@4.0.4(transitive)
+ Addedlodash.isnumber@3.0.3(transitive)
+ Addedlodash.isplainobject@4.0.6(transitive)
+ Addedlodash.isstring@4.0.1(transitive)
+ Addedlodash.once@4.1.1(transitive)
+ Addedlodash.set@4.3.2(transitive)
+ Addeduuid@7.0.3(transitive)
+ Addeduuid-validate@0.0.3(transitive)
+ Addedvalidator@12.2.0(transitive)
- Removed@spaship/common@0.5.0(transitive)
- Removedhandlebars@4.7.8(transitive)
- Removedneo-async@2.6.2(transitive)
- Removedsource-map@0.6.1(transitive)
- Removeduglify-js@3.19.3(transitive)
- Removedwordwrap@1.0.0(transitive)
Updated@spaship/common@^0.6.0