Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Base API - settings, basic auth, and experimental endpoints #35

Merged
merged 3 commits into from
Jul 29, 2014

Conversation

jasoncalabrese
Copy link
Member

No description provided.

@jasoncalabrese
Copy link
Member Author

Work in progress, any help or feedback would be great. I'm planning to store the settings in mongo, and support any json values sent by the client.

@brianhanifin
Copy link
Contributor

Slick work Jason, I like it!

Should we add an advanced setting to enable Websockets over xhr-polling, when you know you can support it? "websockets": true?

Are there any other settings we should add? 24 hour clock option?

@jasoncalabrese
Copy link
Member Author

I'm planning to make the settings API very dumb, have it store/retrieve anything we throw at it, then when ever we need an option we can just use it with a default and let users override it.

Trying to decide if we should let it handle nested json values and/or arrays. We could model that as a single settings doc in a settings collection, or more of a key/value model.

GET /api/v1/settings:

{
  'key1': true,
  'key2': 'value of something',
  'key3': {'sub1': true, 'sub2': 'blue'},
  ...
}

PUT /api/v1/settings: (each key/value would be treated as an upsert)

{
  'key1': true,
  'key2': 'value of something',
  'key3': {'sub1': true, 'sub2': 'blue'},
  ...
}

@brianhanifin
Copy link
Contributor

What do you think about my stab at extending your starting point?
https://github.com/brianhanifin/cgm-remote-monitor/tree/feature/api-experiments

I have sample responses from:
http://localhost:1337/api/v1/entries/10
http://localhost:1337/api/v1/phone
http://localhost:1337/api/v1/settings

I have some validation happening on a parameter:
http://localhost:1337/api/v1/entries/0
http://localhost:1337/api/v1/entries/a

Finally, I setup a PUT request test, which echos the JSON sent to the console. Use this CURL to test.
curl -H 'Content-Type: application/json' -H 'Accept: application/json' -X PUT -d '{"battery":"73%", "data":true,"wifi":false}' http://localhost:1337/api/v1/phone

@jasoncalabrese
Copy link
Member Author

I'll take a look it more in the morning, I'm thinking for this first PR we should do the bare minimum to get settings and maybe post/get entries in place.

Probably some very basic auth too. Then as we need more settings, new data to post, etc it will be easy to extend.

Also wondering if the phone post should be a post to entries with type = phone.

@brianhanifin
Copy link
Contributor

I agree. I wasn't planning on trying to do everything at once. It is more of an experiment for my education. I just renamed my branch to api-experiments.

https://github.com/brianhanifin/cgm-remote-monitor/tree/feature/api-experiments

@brianhanifin
Copy link
Contributor

What were you thinking for authorization, OAuth2, HTTP Basic Authentication?

Here is the opinion from the article Best Practices for Designing a Pragmatic RESTful API

"However, this token-over-basic-auth method of authentication is only acceptable in cases where it's practical to have the user copy a token from an administration interface to the API consumer environment. In cases where this isn't possible, OAuth 2 should be used to provide secure token transfer to a third party. OAuth 2 uses Bearer tokens & also depends on SSL for its underlying transport encryption."

Here are a couple of examples of OAuth2 implimentations:
http://aleksandrov.ws/2013/09/12/restful-api-with-nodejs-plus-mongodb/
https://www.npmjs.org/package/node-oauth2-server

@jasoncalabrese
Copy link
Member Author

I was thinking of something much simpler than OAuth2. For OAuth2 you really should be exchange the authorization token for an access token server to server, if you do that client side your secret key is exposed. So you just did a bunch of work and really aren't any better off.

For starters what if we just set a secret using an ENV VAR and then pass it to the api, if we're going to be using SSL that should be ok, any way better than doing nothing. Later we can add a admin section where we can create tokens, users, etc.

Using HTTP Basic Auth as described in the link above seems good to me, it would still be hard to explore the api using a browser since we'll be using more than GET's.

@brianhanifin
Copy link
Contributor

Setting an ENV VAR sounds OK, and easy enough to set on Azure or Heroku. The concern with passing the value in the get request is it could get stored in the server's log file.

I have found a nice OS X GUI to use instead of constantly Googling Curl parameters. There is a tab to set Basic HTTP Auth.
http://mmattozzi.github.io/cocoa-rest-client/

I also discovered a website to verify my responses are valid JSON.
http://jsonlint.com/

In my experimental branch I am currently experimenting with best practices for returning a validation error.

Request zero entries

GET http://localhost:1337/api/v1/entries/0
HTTP 422 Client Error

Connection: keep-alive
Etag: W/"66-2649162529"
Content-Type: application/json; charset=utf-8
X-Powered-By: Express
Content-Length: 102
Date: Fri, 04 Jul 2014 19:28:57 GMT

{
    "code": 422,
    "message": "Validation Error",
    "description": "Parameter must be an integer greater than 0."
}

Request "ten" entries

GET http://localhost:1337/api/v1/entries/ten
HTTP 422 Client Error

Connection: keep-alive
Etag: W/"57-3996339694"
Content-Type: application/json; charset=utf-8
X-Powered-By: Express
Content-Length: 87
Date: Fri, 04 Jul 2014 19:32:27 GMT

{
  "code" : 422,
  "message" : "Validation Error",
  "description" : "Parameter must be an integer."
}

@bewest
Copy link
Member

bewest commented Jul 4, 2014

I was also thinking of something a bit simpler, to build on what Jason
proposes:

  • read env variable UPLOAD_SECRET, if empty refuse to run
  • store "secret" as output of sha1sum of UPLOAD_SECRET
  • endpoint /api/$secret/... is valid endpoint for upload

On the android side, you'd put the same secret phrase, and the code would
follow the same procedure. None of the code actually depends on the pass
phrase, except to generate the magic hash used to verify everything.
There would have to be a good failure mode, so that if the secret is empty,
fall back to mongo, and if there is no mongo, shut down.

This would provide a way to at least introduce the API and allow for some
way to eventually introduce stronger protections.
Right now, there is a certain simplicity in allowing open reads: it allows
us to monitor operations (think about the aggregator) as well make it easy
for the school nurse to check in without a lot of work.

When we introduce better authorization and access controls, there are a lot
of use cases like these that will need extra effort to get right. Right
now the goal is just introducing some endpoint which doesn't require
transmitting db credentials in the clear. The environment variable
approach Jason suggests seems reasonable.

-bewest

@brianhanifin
Copy link
Contributor

So in Ben's scenerio, the request with a key of abcdefg woud look like this?

GET http://localhost:1337/api/v1/abcdefg/phone

@bewest
Copy link
Member

bewest commented Jul 4, 2014

Something like that, if it's in the URL/query string it's easier to test,
but also easier to sniff.
It could go in a header instead, I suppose.

To be more clear, if the UPLOAD_SECRET=myupl0adsecret

echo myupl0adsecret | sha1sum
c6eddc48a5cc43dbe45a1473925ea9aa79497b6c

So the request would look something like this:

GET http://localhost/api/.../c6eddc48a5cc43dbe45a1473925ea9aa79497b6c/...

Changing the secrets across android phone and the web monitor is relatively
simple this way.
Certainly easier than the mongo details, and just slightly more secure.

The other places are the query string or the headers. The header is best
practice but requires an extra flag using curl from the command line. Not
a big deal.

With this approach the user would put the api base, and the secret phrase
"myupl0adsecret" in the android phone. On the azure site, they would have
the mongo, mongo_collection, and upload_secret environment variables
defined.

If upload_secret is defined, the sha1sum is used to expose an API.
This eliminates needing the mongo cred in multiple places, which is the
main thing we are after.
(Although there are a number of other benefits from having a basic API as
well. One we should think about sooner is adding some kind of version/git
hash in the UI/api somewhere.

-bewest

On Fri, Jul 4, 2014 at 1:20 PM, Brian Hanifin [email protected]
wrote:

So in Ben's scenerio, the request with a key of abcdefg woud look like
this?

GET http://localhost:1337/api/v1/abcdefg/phone


Reply to this email directly or view it on GitHub
#35 (comment)
.

@jasoncalabrese
Copy link
Member Author

Instead of UPLOAD_SECRET I think it should be a general API_SECRET that can
be used for everything. Posting entries, settings, query, etc
On Jul 4, 2014 1:42 PM, "Ben West" [email protected] wrote:

Something like that, if it's in the URL/query string it's easier to test,
but also easier to sniff.
It could go in a header instead, I suppose.

To be more clear, if the UPLOAD_SECRET=myupl0adsecret

echo myupl0adsecret | sha1sum
c6eddc48a5cc43dbe45a1473925ea9aa79497b6c

So the request would look something like this:

GET http://localhost/api/.../c6eddc48a5cc43dbe45a1473925ea9aa79497b6c/...

Changing the secrets across android phone and the web monitor is
relatively
simple this way.
Certainly easier than the mongo details, and just slightly more secure.

The other places are the query string or the headers. The header is best
practice but requires an extra flag using curl from the command line. Not
a big deal.

With this approach the user would put the api base, and the secret phrase
"myupl0adsecret" in the android phone. On the azure site, they would have
the mongo, mongo_collection, and upload_secret environment variables
defined.

If upload_secret is defined, the sha1sum is used to expose an API.
This eliminates needing the mongo cred in multiple places, which is the
main thing we are after.
(Although there are a number of other benefits from having a basic API as
well. One we should think about sooner is adding some kind of version/git
hash in the UI/api somewhere.

-bewest

On Fri, Jul 4, 2014 at 1:20 PM, Brian Hanifin [email protected]
wrote:

So in Ben's scenerio, the request with a key of abcdefg woud look like
this?

GET http://localhost:1337/api/v1/abcdefg/phone


Reply to this email directly or view it on GitHub
<
https://github.com/nightscout/cgm-remote-monitor/pull/35#issuecomment-48068588>

.


Reply to this email directly or view it on GitHub
#35 (comment)
.

@brianhanifin
Copy link
Contributor

Good name choice Jason. API_SECRET

After some reading, it sounds like it is OK to send a 301 Permanent Redirect for API requests. Obviously, after the /api/v1/pebble endpoint is returning proper data we will need someone with a Pebble Watch to test it. If the redirect doesn't break the Pebble app, then we could lose the old pebble.js code without having to worry about breaking any Pebble apps that aren't using the new API.

app.use("/pebble", function(req, res) {
    res.redirect(301, 'http://' + req.headers.host + '/api/v1/pebble');
});

This is fun, I'm really enjoying this collaboration. :)

@jasoncalabrese
Copy link
Member Author

Why change the pebble endpoint now?
On Jul 4, 2014 2:04 PM, "Brian Hanifin" [email protected] wrote:

Good name choice Jason. API_SECRET

After some reading, it sounds like it is OK to send a 301 Permanent
Redirect for API requests. Obviously, after the /api/v1/pebble endpoint is
returning proper data we will need someone with a Pebble Watch to test it.
If the redirect doesn't break the Pebble app, then we could lose the old
pebble.js code without having to worry about breaking any Pebble apps that
aren't using the new API.

app.use("/pebble", function(req, res) {
res.redirect(301, 'http://' + req.headers.host + '/api/v1/pebble');
});

This is fun, I'm really enjoying this collaboration. :)


Reply to this email directly or view it on GitHub
#35 (comment)
.

@bewest
Copy link
Member

bewest commented Jul 4, 2014

Agreed, no need to change /pebble.

Lets add an /api/ similar to what people have been proposing.
with basic CRUD, optimizing for postings from the android app.
I would also like an easy way to upload insulin/carb records.
The treatment data needs to look like this:
[
{ insulin: 1.5,
CR: 12,
carbs: 18
},
...
]

This is a simple addition of a feature, shouldn't really impact anything
else.
FWIW, Ross and I have been working on an MQTT implementation, we will use a
similar convention for authorizing updates from MQTT.
We expect the MQTT implementation to be cheaper for people using cell plans.
(Also, my MNVO plans at $0.70/MB requre less than 25MB usage in order to
compete with other plans ;-)).

-bewest

On Fri, Jul 4, 2014 at 2:15 PM, Jason Calabrese [email protected]
wrote:

Why change the pebble endpoint now?
On Jul 4, 2014 2:04 PM, "Brian Hanifin" [email protected] wrote:

Good name choice Jason. API_SECRET

After some reading, it sounds like it is OK to send a 301 Permanent
Redirect for API requests. Obviously, after the /api/v1/pebble endpoint
is
returning proper data we will need someone with a Pebble Watch to test
it.
If the redirect doesn't break the Pebble app, then we could lose the old
pebble.js code without having to worry about breaking any Pebble apps
that
aren't using the new API.

app.use("/pebble", function(req, res) {
res.redirect(301, 'http://' + req.headers.host + '/api/v1/pebble');
});

This is fun, I'm really enjoying this collaboration. :)


Reply to this email directly or view it on GitHub
<
https://github.com/nightscout/cgm-remote-monitor/pull/35#issuecomment-48070004>

.


Reply to this email directly or view it on GitHub
#35 (comment)
.

@brianhanifin
Copy link
Contributor

Because maintaining two copies of nearly identical code can cause problems in the long run. If my assumption is right, the /pebble and /entries return JSON is going to be identical (or nearly identical), then it would be easier to maintain one codebase instead of two.

@jasoncalabrese
Copy link
Member Author

I don't think /entries will be identical, to /pebble, /entries will just
echo what's in mongo /pebble will do some extra work to make thing things
easy/compatible with the pebble app
On Jul 4, 2014 2:29 PM, "Brian Hanifin" [email protected] wrote:

Because maintaining two copies of nearly identical code can cause problems
in the long run. If my assumption is right, the /pebble and /entries return
JSON is going to be identical (or nearly identical), then it would be
easier to maintain.


Reply to this email directly or view it on GitHub
#35 (comment)
.

@bewest
Copy link
Member

bewest commented Jul 4, 2014

Yeah, I think of pebble as it's own app, not part of the api.

In the future, after the api is in place, we can re-write the pebble
endpoint to consume the api, or to re-use bits of the api code we've
developed in order to simplify/improve pebble. But it's essentially it's
own app.

-bewest

On Fri, Jul 4, 2014 at 2:32 PM, Jason Calabrese [email protected]
wrote:

I don't think /entries will be identical, to /pebble, /entries will just
echo what's in mongo /pebble will do some extra work to make thing things
easy/compatible with the pebble app
On Jul 4, 2014 2:29 PM, "Brian Hanifin" [email protected] wrote:

Because maintaining two copies of nearly identical code can cause
problems
in the long run. If my assumption is right, the /pebble and /entries
return
JSON is going to be identical (or nearly identical), then it would be
easier to maintain.


Reply to this email directly or view it on GitHub
<
https://github.com/nightscout/cgm-remote-monitor/pull/35#issuecomment-48070752>

.


Reply to this email directly or view it on GitHub
#35 (comment)
.

@brianhanifin
Copy link
Contributor

I was operating under the assumption that /entries would return the records array, and /pebble would return the records array, wrapped in more information. See this Gist:
https://gist.github.com/brianhanifin/1847c945dd3bab05bf6b

@bewest
Copy link
Member

bewest commented Jul 4, 2014

But if we change the pebble app's behavior radically we don't want to
change the api, just the pebble endpoint.

Eg, if the pebble endpoint is not the same as the api, then we can add
descriptions of alarms and other features to the pebble behavior without
modifying the entire API.

-bewest

On Fri, Jul 4, 2014 at 2:37 PM, Brian Hanifin [email protected]
wrote:

I was operating under the assumption that /entries would return the
records array, and /pebble would return the records array, wrapped in more
information. See this Gist:
https://gist.github.com/brianhanifin/1847c945dd3bab05bf6b


Reply to this email directly or view it on GitHub
#35 (comment)
.

@brianhanifin
Copy link
Contributor

OK. I honestly thought the /pebble endpoint is already an API that simply returns JSON. I thought it was a natural addition to the API. I will leave /pebble alone unless otherwise directed. :)

@brianhanifin
Copy link
Contributor

Ben, to clarify you are recommending an /api/v1/treatment endpoint?

@jasoncalabrese
Copy link
Member Author

I think entries should be generic, and have a type. Then the collection is
just an event stream.
On Jul 4, 2014 3:05 PM, "Brian Hanifin" [email protected] wrote:

Ben, to clarify you are recommending an /api/v1/treatment endpoint?


Reply to this email directly or view it on GitHub
#35 (comment)
.

@brianhanifin
Copy link
Contributor

Excuse me. I'm coming from a SQL database background so I'm new to loosey goosey databases. :) Where would this "event stream" be stored? In the primary collection?

@jasoncalabrese
Copy link
Member Author

Yeah just throw it all in there and index the type and timestamp fields
On Jul 4, 2014 3:22 PM, "Brian Hanifin" [email protected] wrote:

Excuse me. I'm coming from a SQL database background so I'm new to loosey
goosey databases. :) Where would this "event stream" be stored? In the
primary collection?


Reply to this email directly or view it on GitHub
#35 (comment)
.

@brianhanifin
Copy link
Contributor

Will all of the new data (e.g. settings) be stored in the same collection?
I look forward to learning how that is accomplished.
On Jul 4, 2014 3:25 PM, "Jason Calabrese" [email protected] wrote:

Yeah just throw it all in there and index the type and timestamp fields
On Jul 4, 2014 3:22 PM, "Brian Hanifin" [email protected] wrote:

Excuse me. I'm coming from a SQL database background so I'm new to
loosey
goosey databases. :) Where would this "event stream" be stored? In the
primary collection?


Reply to this email directly or view it on GitHub
<
https://github.com/nightscout/cgm-remote-monitor/pull/35#issuecomment-48072035>

.


Reply to this email directly or view it on GitHub
#35 (comment)
.

@jasoncalabrese
Copy link
Member Author

Settings are something else, so a different collection.

Same for users or any other admin like things.

I think all the data points that we want to show on the timeline should be
an entry in the event stream collection. Entries would be rendered based
on their type.
On Jul 4, 2014 3:49 PM, "Brian Hanifin" [email protected] wrote:

Will all of the new data (e.g. settings) be stored in the same collection?
I look forward to learning how that is accomplished.
On Jul 4, 2014 3:25 PM, "Jason Calabrese" [email protected]
wrote:

Yeah just throw it all in there and index the type and timestamp fields
On Jul 4, 2014 3:22 PM, "Brian Hanifin" [email protected]
wrote:

Excuse me. I'm coming from a SQL database background so I'm new to
loosey
goosey databases. :) Where would this "event stream" be stored? In the
primary collection?


Reply to this email directly or view it on GitHub
<

https://github.com/nightscout/cgm-remote-monitor/pull/35#issuecomment-48072035>

.


Reply to this email directly or view it on GitHub
<
https://github.com/nightscout/cgm-remote-monitor/pull/35#issuecomment-48072117>

.


Reply to this email directly or view it on GitHub
#35 (comment)
.

@jasoncalabrese
Copy link
Member Author

If we can populate the treaments with the data expected on the client it should just work

@bewest
Copy link
Member

bewest commented Jul 5, 2014

Howdy

On Fri, Jul 4, 2014 at 4:29 PM, Jason Calabrese [email protected]
wrote:

If we can populate the treaments
https://github.com/nightscout/cgm-remote-monitor/blob/master/server.js#L253
with the data expected
https://github.com/nightscout/cgm-remote-monitor/blob/master/static/js/client.js#L778
on the client it should just work

This might be a little tricky.
Data from pumps comes back like this (fairly consistently across vendors):

  • smbg @ datetime
  • ...
  • BWZ @ datetime (recommended food, correction, total, carbs, bg, ratio)
  • ...
  • Bolus @ datetime (programmed, delivered)

The visualization expects treatment elements to have the delivered from the
bolus, plus the food, and ratio from the BWZ record. These records can be
separated in time and sparsely interwoven with other records (like
LowReservoir) which makes coalescing them into a single record a little
tricky, but not insurmountable.

Very open to ideas here. I worked out most of the obvious remaining bugs
today on fetching this data. I've just got chrome configured to give me a
transport to usb/serial to the stick, and also confirmed how to get
browserify to package npm packages for chrome. Getting very very close.

-bewest


Reply to this email directly or view it on GitHub
#35 (comment)
.

@brianhanifin
Copy link
Contributor

I am trying to wrap my head around the recommended Git branching model. I think I have a decent understanding of it, but I don't see a "develop" branch.

I am thinking about splitting the "feature/base-api" branch off into "feature/settings-ui", so I can start experimenting with a settings interface. If I do that should feature/base-api be merged into a "develop" branch.

@bewest
Copy link
Member

bewest commented Jul 17, 2014

The actual name of the branch doesn't matter so much. Everyone seems pleased with feature/$myslug instead of develop, I think that's fine.

If I were you I'd do this:

git checkout feature/base-api
git pull 
git checkout -b feature/settings-ui

The really special things to keep in mind is that touching master branch causes things to happen, so all work happens on other branches. The naming conventions, like agreeing on a certain prefix are to help constrain chaos a bit. "Good naming" guides suggest using author date and creation are good, which is why I often use $user/$myslug, but for now I plan on following the feature/$foo pattern. I've seen some people use wip/$myslug which is nice and short.

@bewest
Copy link
Member

bewest commented Jul 17, 2014

If we get more than 6 or 7 pull requests consistently at the same time from inside the repo, I'll ask people to host their branches on their own forks and pull into a more central develop style branch. For now we're doing a good job keeping each other updated on ongoing work. Once what we're doing becomes unworkable, we should start on new features from inside our forks and only use branches on this repo for shared maintenance and upcoming releases.

@brianhanifin
Copy link
Contributor

Did someone start using a module "type-is"? I am getting an error this morning which was resolved by installing it. Did I do something wrong?

Error: Cannot find module 'type-is'

@bewest
Copy link
Member

bewest commented Jul 18, 2014

Strange, no stack trace? Did you try just npm install?

@brianhanifin
Copy link
Contributor

Error: Cannot find module 'type-is'
    at Function.Module._resolveFilename (module.js:338:15)
    at Function.Module._load (module.js:280:25)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)
    at Object.<anonymous> (/Volumes/HDD/Projects/nightscout-cgm-remote-monitor/node_modules/body-parser/lib/types/raw.js:12:14)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.require (module.js:364:17)

@brianhanifin
Copy link
Contributor

Ah-ha! Depenencies of body-parser includes "type-is".

So, does sudo npm update not install a package's dependancies?

@bewest
Copy link
Member

bewest commented Jul 18, 2014

When you run npm sans sudo it only works eg on ./node_modules/ which is per project.
Running sudo npm ... touches analog of /usr/local/sys/node/.... aka the system packages, it won't touch your project modules at all.

Right thing to do after pulling merges is generally just npm install (without sudo). Body parser, being included, should pull it's dependencies into ./node_modules/body-parser/node_modules/... automatically.

@brianhanifin
Copy link
Contributor

See I tried doing npm install but I have been getting errors, which went away when I added sudo.

"npm install" output

> [email protected] postinstall /Volumes/HDD/Projects/nightscout-cgm-remote-monitor
> node node_modules/bower/bin/bower install

\
module.js:340
    throw err;
          ^
Error: Cannot find module 'chalk'
    at Function.Module._resolveFilename (module.js:338:15)
    at Function.Module._load (module.js:280:25)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)
    at Object.<anonymous> (/Volumes/HDD/Projects/nightscout-cgm-remote-monitor/node_modules/bower/lib/renderers/JsonRenderer.js:1:75)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.require (module.js:364:17)

npm ERR! [email protected] postinstall: `node node_modules/bower/bin/bower install`
npm ERR! Exit status 8
npm ERR!
npm ERR! Failed at the [email protected] postinstall script.
npm ERR! This is most likely a problem with the Nightscout package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     node node_modules/bower/bin/bower install
npm ERR! You can get their info via:
npm ERR!     npm owner ls Nightscout
npm ERR! There is likely additional logging output above.
npm ERR! System Darwin 13.3.0
npm ERR! command "node" "/usr/local/bin/npm" "install"
npm ERR! cwd /Volumes/HDD/Projects/nightscout-cgm-remote-monitor
npm ERR! node -v v0.10.29
npm ERR! npm -v 1.4.14
npm ERR! code ELIFECYCLE
npm ERR!
npm ERR! Additional logging details can be found in:
npm ERR!     /Volumes/HDD/Projects/nightscout-cgm-remote-monitor/npm-debug.log
npm ERR! not ok code 0

@bewest
Copy link
Member

bewest commented Jul 18, 2014

Ah, ok, quick fix:

$ sudo rm -rf node_modules
$ npm install

Here's what happens:
When you run npm install the first time, it creates eg:

./node_modules/
  foo/...
  bar/
    node_module/...
      cccc

All of these files are owned by you.

Then, the first time you use sudo something like this happens:

./node_modules/
  foo/... (owned by you)
  bar/  (owned by root)
    node_module/
      aaaa

Watch what happens when a merge update expects npm install as you to update something in ./node_modules/bar/node_module/ from aaaa to bbbb (maybe dependencies changed after pull).

./node_modules/
  foo/... (owned by you)
  bar/  (owned by root)
    node_module/... (owned by root, bbbb not created)
      aaaa  (owned by root) - not modified

So if you completely remove your node modules and just do npm install it will take awhile but should work with clean and consistent permissions.

@brianhanifin
Copy link
Contributor

Sorry to be a pain, but I deleted my node_modules folder and now running *npm install gives me this, which includes the recommendation "npm ERR! Please try running this command again as root/Administrator."

acbookpro:nightscout-cgm-remote-monitor dev$ npm install
npm ERR! Error: EACCES, open '/Users/dev/.npm/errorhandler/1.1.1/package/package.json'
npm ERR!  { [Error: EACCES, open '/Users/dev/.npm/errorhandler/1.1.1/package/package.json']
npm ERR!   errno: 3,
npm ERR!   code: 'EACCES',
npm ERR!   path: '/Users/dev/.npm/errorhandler/1.1.1/package/package.json',
npm ERR!   parent: 'Nightscout' }
npm ERR!
npm ERR! Please try running this command again as root/Administrator.

npm ERR! System Darwin 13.3.0
npm ERR! command "node" "/usr/local/bin/npm" "install"
npm ERR! cwd /Volumes/HDD/Projects/nightscout-cgm-remote-monitor
npm ERR! node -v v0.10.29
npm ERR! npm -v 1.4.14
npm ERR! path /Users/dev/.npm/errorhandler/1.1.1/package/package.json
npm ERR! code EACCES
npm ERR! errno 3
npm ERR! stack Error: EACCES, open '/Users/dev/.npm/errorhandler/1.1.1/package/package.json'
npm ERR!
npm ERR! Additional logging details can be found in:
npm ERR!     /Volumes/HDD/Projects/nightscout-cgm-remote-monitor/npm-debug.log
npm ERR! not ok code 0

@brianhanifin
Copy link
Contributor

OK, I have an idea. I am trying to add my dev user to the "Sharing and Permissions" list for that folder on OS X.

@bewest
Copy link
Member

bewest commented Jul 18, 2014

npm switches modes when it detects itself running as root. This modal behavior is confusing and harmful. Specifically, running sudo npm install, packages in ./node_modules and other places are affected, leading to incompatible behavior when some packages with global flags are installed in a user's package location instead as a result of this behavior (-g adds another mode which installs in system location instead). In some scenarios this leads to user files being recorded as root-only permissions, with EACCES as a result. This essentially corrupts those files because the user expects to be able to modify them and cannot without root access.

Best solution is to delete the files in user owned directories that are created by npm but owned by root, and installing again without sudo.

In your scenario, you can follow up with:

sudo rm -rf /Users/dev/.npm/

And probably try again with success.

@bewest
Copy link
Member

bewest commented Jul 18, 2014

Setting up sharing might work but defeats the point of having the permissions... the insane modal interface corrupted your permissions, once fixed it should work again.

@bewest
Copy link
Member

bewest commented Jul 18, 2014

If you are using a separate dev account, I recommend creating a group and adding you and your dev account to the same group, then your group will have shared read/write and things will also work well.

@brianhanifin
Copy link
Contributor

Thank you! That last command did the trick! I have a Macbook Pro with the OS and apps on an SSD and everything else on a larger hard disk. I certainly didn't mean to do get things all screwed up. I am so used to running Unix commands using sudo I must have done it out of habit.

@bewest
Copy link
Member

bewest commented Jul 18, 2014

I've done the Exact. Same. Thing. Repeatedly.

Modal interfaces considered harmful.

I now avoid using sudo and -g altogether, and explicitly list all my dependencies in package.json. I don't trust the system or the "shared" packages at all because the interface is unpredictable/confusing/modal.

@bewest
Copy link
Member

bewest commented Jul 18, 2014

Want to add tests to this, should be ready for testing, will hopefully get a chance to get Brandon's rig using this soon.

@brianhanifin
Copy link
Contributor

Battery level? Interesting. I could play with adding a battery glyph.

bewest and others added 3 commits July 28, 2014 22:46
@jasoncalabrese pointed out that some agents do odd things with
underscores and that using a hyphen is more common.
This also adds tests to ensure that the API_SECRET handling works as
expected.
Cherry-picked in the wrong order

This reverts commit 8e56ef1.
brianhanifin added a commit that referenced this pull request Jul 29, 2014
Base API - settings, basic auth, and experimental endpoints
@brianhanifin brianhanifin merged commit 3187646 into master Jul 29, 2014
@brianhanifin brianhanifin deleted the feature/base-api branch July 29, 2014 09:25
sulkaharo pushed a commit that referenced this pull request Aug 28, 2019
freddyyi pushed a commit to freddyyi/cgm-remote-monitor that referenced this pull request Apr 22, 2022
tzachi-dar referenced this pull request in tzachi-dar/nightscout-vps Nov 17, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants