Skip to content
This repository has been archived by the owner on Jun 27, 2022. It is now read-only.

Commit

Permalink
Port of Cipher API breaking changes update (#17)
Browse files Browse the repository at this point in the history
* Port of Cipher API breaking changes update

port of jcs/rubywarden#32

* migration script

* Compatibility

* ucfirst all URIs

* Unnecessary imports

* eslint fixes

* Fix tests and allow null notes

* Fix migration script
  • Loading branch information
vvondra committed Mar 25, 2018
1 parent 474532c commit 222f152
Show file tree
Hide file tree
Showing 10 changed files with 153 additions and 40 deletions.
11 changes: 10 additions & 1 deletion README.md
Expand Up @@ -36,11 +36,20 @@ If you have AWS credentials set up, this should get you a running instance of th
npm install -g serverless
npm install
# Feel free to deploy to an AWS region closer to your typical location
serverless deploy --region us-east-1
serverless deploy --region us-east-1 --stage prod
```

The deploy command will return a service URL (e.g. `https://abcd01234.execute-api.us-east-1.amazonaws.com/prod`), which you can set up in Bitwarden as your own self-hosted endpoint.

## Upgrade

Simply re-deploy with `serverless deploy` from the latest checkout.

Some releases need a a database migration. A special function is deployed for this purpose, invoke with:
```bash
serverless invoke -f migrate [--stage] [--region]
```

## Enable 2FA

Run `./two_factor.sh`, the script will ask you for the e-mail you want to set up two factor authentication form. Then copy the data URL with the QR code into your web browser and scan it with your authenticator app of choice. Provide one valid token to confirm the setup.
Expand Down
47 changes: 26 additions & 21 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -17,7 +17,6 @@
"eslint-config-airbnb-base": "^12.1.0",
"eslint-plugin-import": "^2.8.0",
"get-stdin": "^5.0.1",
"lodash": "^4.17.4",
"mocha": "^4.0.1",
"mocha-steps": "^1.1.0",
"serverless-webpack": "^3.1.1",
Expand All @@ -33,6 +32,7 @@
"fast-csv": "^2.4.1",
"joi": "^13.0.2",
"jsonwebtoken": "^8.1.0",
"lodash": "^4.17.5",
"object.entries": "^1.0.4",
"qrcode": "^1.2.0",
"speakeasy": "^2.0.0"
Expand Down
4 changes: 4 additions & 0 deletions serverless.yml
Expand Up @@ -101,6 +101,10 @@ functions:
method: delete
cors: true
path: api/folders/{uuid}
migrate:
handler: src/migrate.migrateHandler
timeout: 300
memorySize: 1024
two_factor_setup:
handler: src/two_factor.setupHandler
two_factor_complete:
Expand Down
29 changes: 18 additions & 11 deletions src/lib/bitwarden.js
Expand Up @@ -2,13 +2,15 @@ import jwt from 'jsonwebtoken';
import crypto from 'crypto';
import bufferEq from 'buffer-equal-constant-time';
import entries from 'object.entries';
import mapKeys from 'lodash/mapKeys';
import { User, Device } from './models';

const JWT_DEFAULT_ALGORITHM = 'HS256';

export const TYPE_LOGIN = 1;
export const TYPE_NOTE = 2;
export const TYPE_CARD = 3;
export const TYPE_IDENTITY = 4;

export const DEFAULT_VALIDITY = 60 * 60;

Expand Down Expand Up @@ -85,40 +87,45 @@ export function buildCipherDocument(body, user) {
folderUuid: body.folderid,
favorite: !!body.favorite,
type: parseInt(body.type, 10),
};

const data = {
Name: body.name,
Notes: body.notes,
name: body.name,
notes: body.notes,
fields: [],
};

let additionalParams = null;
if (params.type === TYPE_LOGIN) {
additionalParams = 'login';
} else if (params.type === TYPE_CARD) {
additionalParams = 'card';
} else if (params.type === TYPE_IDENTITY) {
additionalParams = 'identity';
} else if (params.type === TYPE_NOTE) {
additionalParams = 'securenote';
}

if (additionalParams && body[additionalParams]) {
params[additionalParams] = {};
entries(body[additionalParams]).forEach(([key, value]) => {
data[ucfirst(key)] = value;
let paramValue = value;
if (ucfirst(key) === 'Uris') {
paramValue = value.map(val => mapKeys(val, (uriValue, uriKey) => ucfirst(uriKey)));
}

params[additionalParams][ucfirst(key)] = paramValue;
});
}

if (body.fields && Array.isArray(body.fields)) {
data.Fields = body.fields.map((field) => {
params.fields = body.fields.map((field) => {
const vals = {};
entries(field).forEach(([key, value]) => {
vals[ucfirst(key)] = value;
});

return vals;
});
} else {
data.Fields = null;
}

params.data = data;

return params;
}

Expand Down
9 changes: 8 additions & 1 deletion src/lib/mappers.js
Expand Up @@ -8,7 +8,14 @@ export function mapCipher(cipher) {
OrganizationId: cipher.get('organizationUuid'),
Attachments: cipher.get('attachments'),
OrganizationUseTotp: false,
Data: cipher.get('data'),
CollectionIds: [],
Name: cipher.get('name'),
Notes: cipher.get('notes'),
Fields: cipher.get('fields'),
Login: cipher.get('login'),
Card: cipher.get('card'),
Identity: cipher.get('identity'),
SecureNote: cipher.get('securenote'),
Object: 'cipher',
};
}
Expand Down
10 changes: 9 additions & 1 deletion src/lib/models.js
Expand Up @@ -61,9 +61,17 @@ export const Cipher = dynogels.define('Cipher', {
folderUuid: Joi.string().allow(null),
organizationUuid: Joi.string().allow(null),
type: Joi.number(),
data: Joi.object(),
version: Joi.number().allow(null),
data: Joi.object().allow(null),
favorite: Joi.boolean(),
attachments: Joi.binary(),
name: Joi.string().allow(null),
notes: Joi.string().allow(null),
fields: Joi.any().allow(null),
login: Joi.object().allow(null),
securenote: Joi.object().allow(null),
identity: Joi.object().allow(null),
card: Joi.object().allow(null),
},
});

Expand Down

0 comments on commit 222f152

Please sign in to comment.