
Security News
The Hidden Blast Radius of the Axios Compromise
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.
API part of PopIt which lets you store details of people, organisations and positions
The API specific part of the PopIt project. Provides read and write access to the data and manages where it is stored. Will be Popolo compliant.
Can be used as a standalone server, or embedded in a Express backed website.
This is alpha code and subject to frequent and backwards incompatible change. Feel free to experiment but do not use in production until this message is removed.
The exact implementation of the Popolo standard used here may not be fully up to date, or may contain discrepancies to the official one. See the json files in the schemas directory for the current spec we're validating against.
We (mySociety) are using this project to help develop the standard in the light of requirements from our own projects. The eventual aim is to be Popolo compliant.
Install these dependencies using your package manager:
npm install popit-api
Example of how to create a simple API server.
mkdir popit-api-example && cd popit-api-example
npm install express popit-api
Put the following in a file called server.js:
var express = require('express'),
popitApi = require('popit-api');
var app = express();
// Configure the PopIt API app
var apiApp = popitApi({
databaseName: 'mp-contacts'
});
// Mount the PopIt API app at the appropriate path
app.use('/api', apiApp);
// Start to listen
app.listen(3000);
console.log("API Server listening at http://127.0.0.1:3000/api");
Then run it with node.
node server.js
You should then be able to go to http://127.0.0.1:3000/api/persons to list all people (which will not be any initially as the database is empty).
You can add a person to the database using curl.
curl \
-H 'Content-Type: application/json' \
-d '{"id": "uk.org.publicwhip/member/40665", "name": "David Cameron", "email": "camerond@example.com"}' \
http://127.0.0.1:3000/api/persons
Which should give the following response.
{
"result": {
"id": "uk.org.publicwhip/member/40665",
"name": "David Cameron",
"email": "camerond@example.com"
}
}
Now visiting http://127.0.0.1:3000/api/persons you will see the entry you just created.
This app provides a REST interface to an API that lets you store Popolo compliant data.
It does not provide any logging and only basic authentication. It is intended that you will do this in the app that you use this module in.
There is a test app included that you can use to experiment quickly. These commands will get you a dev environment set up:
git clone https://github.com/mysociety/popit-api.git
cd popit-api
npm install
npm test
node test-server.js
open http://127.0.0.1:3000/
When running the tests or the test-server a database called test-popit-api-db
is used.
All configuration is done by passing in the config to the app. Currently you need to either supply one of these two:
// Specify the database name directly
var apiApp = popitApi({
databaseName: 'name-of-mongodb-to-use'
});
// Derive the database name from the Host header
var apiApp = popitApi({
storageSelector: 'hostName'
});
If you want to include url properties in the API output then you'll need to configure the API with an apiBaseUrl to use.
var apiApp = popitApi({
databaseName: 'name-of-mongodb-to-use',
apiBaseUrl: 'http://example.org/api'
});
Expect the configuration to change significantly as we work out what we actually need.
All data written to the REST API is validated against the schemas stored in schemas/popolo. Local copies are used rather than fetching over http so that changes can be easily made and experimented with. Note that these schemas may be different to the current official ones until the standard is finalised.
Some applications may want to keep a subset of fields hidden from the public. For example, PopIt could be used to store contact details for writing to MPs, the MP has given the service their email to use but don't want it to be publicly available. The service can still store email addresses in PopIt, but they will only be returned when the correct API key is provided.
The simplest way to get started is to specify fields to be hidden
globally directly in the configuration when creating the api using the
fieldSpec option, along with an API key which will unlock all the fields.
// ...
// Configure the PopIt API app with hidden fields.
var apiApp = popitApi({
databaseName: 'mp-contacts',
apiKey: 'secret' // This could come from an environment variable or similar
fieldSpec: [
{
collectionName: 'persons',
fields: {
email: false
}
}
]
});
// ...
This example uses email: false in the fieldSpec option, which means
that the email field will not be included it the response. If you wanted
the output to only contain an email address then you'd set email: true which wouldn't render any fields except the email.
After restarting the app, public requests to http://127.0.0.1:3000/api/persons
won't include any email addresses unless you specify provide the correct apiKey
parameter, e.g. http://127.0.0.1:3000/api/persons?apiKey=secret.
Putting the hidden fields in the configuration is a convenient way to
hide fields across all instances, but sometimes you might want more
granular control over which documents are hidden in which database. To
do this you can add documents to a hidden collection in the database
you want to change, as shown below.
To hide all the email addresses for people in this instance, add a document to mongo from the command line:
mongo mp-contacts
> db.hidden.insert({collectionName: 'persons', fields: {email: false}})
Or to hide an individual document's fields
mongo mp-contacts
> db.hidden.insert({collectionName: 'persons', doc: 'uk.org.publicwhip/member/40665', fields: {email: false}})
The REST API is being kept as simple as possible. We'll be adding features as required.
Responses are always in JSON, or JSONP if a callback query is provided. HTTP
Status codes are used to describe the success or failure. If data is returned it
will be something like:
{ "result": { "id": "123", "name": "Joe Bloggs" } }
{ "result": [ { "id": "123", "name": "Joe Bloggs" }, ... ] }
If you don't want the result wrapper at the root of the returned JSON then set the include_root query parameter to false.
GET /api/persons/123?include_root=false
{ "id": "123", "name": "Joe Bloggs" }
Note this only works for responses that return a single records, so it won't work for /api/persons.
Errors will also return JSON:
{ "errors": [ "Error message - hopefully helpful...", ... ] }
Note that the structure of the errors response is not affected by the include_root parameter described above. To detect if an error has occurred check the status code of the response, if it's not 200 then check the body for an errors key.
/api/:collectionReturns an array of all the documents in that collection (currently there is no filtering or pagination).
/api/:collectionAdds the posted document to the collection, if it validates. Can either specify
an id or one will be created. Returns 200 with the document as the body
(with the id in it).
/api/:collectionNot implemented, will return 405. Replacing a whole collection is not
something we think that API users will want to do.
/api/:collectionNot implemented, will return 405. Deleting a whole collection is not
something we think that API users will want to do.
/api/:collection/:idReturns the document requested, or 404 if it does not exist.
/api/:collection/:idNot implemented, will return 405. As the documents can not be treated as
collections adding something to them with a POST does not apply.
/api/:collection/:idReplaces the current document with the one provided, if valid. Returns the document with status 200.
/api/:collection/:idDeletes the document. Returns 204 (even if the document did not exist).
/api/search/:collection?q=<search-query>Searches for a document in the named collection which matches the q parameter.
You'll probably want to mount this app in your own app. For an example see
server.js in the mysociety-deploy branch. This is how we deploy it.
FAQs
API part of PopIt which lets you store details of people, organisations and positions
The npm package popit-api receives a total of 8 weekly downloads. As such, popit-api popularity was classified as not popular.
We found that popit-api demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.

Research
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.

Research
Malicious versions of the Telnyx Python SDK on PyPI delivered credential-stealing malware via a multi-stage supply chain attack.