Skip to content

Commit fd964c2

Browse files
committed
Adds flow, modernizes Auth component
1 parent 16ebf16 commit fd964c2

File tree

8 files changed

+122
-93
lines changed

8 files changed

+122
-93
lines changed

.babelrc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
{
2-
"presets": ["es2015"]
2+
"presets": ["es2015", "flow"],
3+
"plugins": [ "transform-object-rest-spread" ]
34
}

.eslintrc

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,6 @@
66
"mocha": true,
77
"node": true
88
},
9-
"ecmaFeatures": {
10-
"modules": true,
11-
"experimentalObjectRestSpread": true
12-
},
139
"rules": {
1410
"brace-style": [ 1, "1tbs" ],
1511
// REST API objects include underscores

.flowconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[ignore]
2+
3+
[include]
4+
src/
5+
6+
[libs]
7+
8+
[lints]
9+
10+
[options]
11+
12+
[strict]

package.json

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"url": "git://github.com/Simperium/node-simperium.git"
99
},
1010
"scripts": {
11+
"flow": "flow",
1112
"test": "mocha --compilers js:babel-core/register test/**",
1213
"prepublish": "babel -q -d lib/ src/"
1314
},
@@ -20,7 +21,13 @@
2021
"devDependencies": {
2122
"babel-cli": "^6.2.0",
2223
"babel-core": "^6.2.0",
23-
"babel-preset-es2015": "^6.2.0",
24-
"mocha": "^2.3.4"
24+
"babel-eslint": "^8.2.1",
25+
"babel-plugin-transform-object-rest-spread": "^6.26.0",
26+
"babel-preset-es2015": "^6.24.1",
27+
"babel-preset-flow": "^6.23.0",
28+
"eslint": "^4.17.0",
29+
"flow": "^0.2.3",
30+
"flow-bin": "^0.65.0",
31+
"mocha": "^2.5.3"
2532
}
2633
}

src/simperium/auth.js

Lines changed: 73 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,94 @@
1-
import { EventEmitter } from 'events'
2-
import User from './user'
3-
import { format, inherits } from 'util'
1+
// @flow
2+
import events from 'events'
43
import https from 'https'
54
import url from 'url'
65

6+
// @flow
7+
type User = {};
8+
9+
const fromJSON = ( json: string ) => {
10+
const data = JSON.parse( json );
11+
return {
12+
options: data,
13+
access_token: data.access_token
14+
};
15+
};
16+
17+
const { EventEmitter } = events;
18+
719
const URL = 'https://auth.simperium.com/1';
820

9-
export default function Auth( appId, appSecret ) {
10-
this.appId = appId;
11-
this.appSecret = appSecret;
21+
export class AuthError extends Error {
22+
underlyingError: Error
23+
24+
constructor( underlyingError: Error ) {
25+
super( 'Failed to authenticate user.' );
26+
this.underlyingError = underlyingError;
27+
}
1228
}
1329

14-
inherits( Auth, EventEmitter );
30+
export class Auth extends EventEmitter {
31+
appId: string
32+
appSecret: string
1533

16-
Auth.prototype.authorize = function( username, password ) {
17-
var body = JSON.stringify( { username: username, password: password } ),
18-
promise = this.request( 'authorize/', body );
34+
constructor( appId: string, appSecret: string ) {
35+
super();
36+
this.appId = appId;
37+
this.appSecret = appSecret;
38+
}
1939

20-
return promise;
21-
}
40+
authorize( username: string, password: string ) {
41+
const body = JSON.stringify( { username: username, password: password } );
42+
return this.request( 'authorize/', body );
43+
}
2244

23-
Auth.prototype.create = function( username, password, provider ) {
24-
var userData = { username, password };
25-
if ( provider ) {
26-
userData.provider = provider;
45+
create( username: String, password: String, provider: ?String ) {
46+
const userData: { username: String, password: String, provider?: String } = { username, password };
47+
if ( provider ) {
48+
userData.provider = provider;
49+
}
50+
const body = JSON.stringify( userData );
51+
return this.request( 'create/', body );
2752
}
28-
var body = JSON.stringify( userData ),
29-
promise = this.request( 'create/', body );
3053

31-
return promise;
32-
}
54+
getUrlOptions( path: string ) {
55+
const options = url.parse( `${URL}/${ this.appId }/${ path}` );
56+
return {
57+
... options,
58+
method: 'POST',
59+
headers: {'X-Simperium-API-Key': this.appSecret }
60+
};
61+
}
3362

34-
Auth.prototype.getUrlOptions = function( path ) {
35-
const options = url.parse( format( '%s/%s/%s', URL, this.appId, path ) );
36-
return Object.assign( options, { method: 'POST', headers: {'X-Simperium-API-Key': this.appSecret}} );
37-
}
63+
request( endpoint: string, body: string ): Promise<User> {
64+
return new Promise( ( resolve, reject ) => {
65+
const req = https.request( this.getUrlOptions( endpoint ), ( res ) => {
66+
let responseData = '';
3867

39-
Auth.prototype.request = function( endpoint, body ) {
40-
return new Promise( ( resolve, reject ) => {
41-
const req = https.request( this.getUrlOptions( endpoint ), ( res ) => {
42-
var responseData = '';
68+
res.on( 'data', ( data ) => {
69+
responseData += data.toString();
70+
} );
4371

44-
res.on( 'data', ( data ) => {
45-
responseData += data.toString();
72+
res.on( 'end', () => {
73+
try {
74+
const user = fromJSON( responseData );
75+
resolve( user );
76+
this.emit( 'authorize', user );
77+
} catch ( error ) {
78+
return reject( new AuthError( error ) );
79+
}
80+
} );
4681
} );
4782

48-
res.on( 'end', () => {
49-
var user;
50-
51-
try {
52-
user = User.fromJSON( responseData );
53-
} catch ( e ) {
54-
return reject( new Error( responseData ) );
55-
}
56-
this.emit( 'authorize', user );
57-
resolve( user );
83+
req.on( 'error', ( e ) => {
84+
reject( e );
5885
} );
59-
} );
6086

61-
req.on( 'error', ( e ) => {
62-
reject( e );
87+
req.end( body );
6388
} );
89+
}
90+
};
6491

65-
req.end( body );
66-
} );
67-
}
92+
export default ( appId: string, appSecret: string ) => {
93+
return new Auth( appId, appSecret );
94+
};

src/simperium/index.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import User from './user'
21
import Client from './client'
32
import Auth from './auth'
43
import * as util from './util'
@@ -7,4 +6,4 @@ export default function( appId, token, options ) {
76
return new Client( appId, token, options );
87
}
98

10-
export { Auth, User, Client, util }
9+
export { Auth, Client, util }

src/simperium/user.js

Lines changed: 0 additions & 9 deletions
This file was deleted.

test/simperium/auth_test.js

Lines changed: 25 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import Auth from '../../src/simperium/auth'
1+
import buildAuth from '../../src/simperium/auth'
22
import https from 'https'
33
import { equal, deepEqual } from 'assert'
44
import { EventEmitter } from 'events'
@@ -19,11 +19,11 @@ const stubResponse = ( data ) => stub( ( body, handler ) => {
1919
} )
2020

2121
describe( 'Auth', () => {
22-
var auth
22+
let auth;
2323

2424
beforeEach( () => {
25-
auth = new Auth( 'token', 'secret' );
26-
} )
25+
auth = buildAuth( 'token', 'secret' );
26+
} );
2727

2828
it( 'getUrlOptions', () => {
2929
const { hostname, headers, pathname, method } = auth.getUrlOptions( 'path' )
@@ -33,7 +33,7 @@ describe( 'Auth', () => {
3333
deepEqual( headers, { 'X-Simperium-API-Key': 'secret' } )
3434
} )
3535

36-
it( 'should request auth token', ( done ) => {
36+
it( 'should request auth token', () => {
3737
stub( ( data, handler ) => {
3838
const { username, password } = JSON.parse( data )
3939
const response = new EventEmitter()
@@ -45,24 +45,22 @@ describe( 'Auth', () => {
4545
response.emit( 'end' );
4646
} )
4747

48-
auth.authorize( 'username', 'password' )
49-
.then( ( user ) => {
50-
equal( user.access_token, 'secret-token' )
51-
done()
52-
} )
53-
} )
48+
return auth.authorize( 'username', 'password' )
49+
.then( ( user ) => {
50+
equal( user.access_token, 'secret-token' );
51+
} );
52+
} );
5453

55-
it( 'should fail to auth with invalid credentials', ( done ) => {
54+
it( 'should fail to auth with invalid credentials', () => {
5655
stubResponse( 'this is not json' )
5756

58-
auth.authorize( 'username', 'bad-password' )
59-
.catch( ( e ) => {
60-
equal( e.message, 'this is not json' )
61-
done()
62-
} )
57+
return auth.authorize( 'username', 'bad-password' )
58+
.catch( ( e ) => {
59+
equal( e.message, 'Failed to authenticate user.' );
60+
} );
6361
} )
6462

65-
it( 'should create an account with valid credentials', ( done ) => {
63+
it( 'should create an account with valid credentials', () => {
6664
stub( ( data, handler ) => {
6765
const { username, password } = JSON.parse( data )
6866
const response = new EventEmitter()
@@ -74,20 +72,18 @@ describe( 'Auth', () => {
7472
response.emit( 'end' );
7573
} )
7674

77-
auth.create( 'username', 'password' )
78-
.then( ( user ) => {
79-
equal( user.access_token, 'secret-token' )
80-
done()
81-
} )
75+
return auth.create( 'username', 'password' )
76+
.then( user => {
77+
equal( user.access_token, 'secret-token' )
78+
} );
8279
} )
8380

84-
it( 'should fail to create an account with invalid credentials', ( done ) => {
81+
it( 'should fail to create an account with invalid credentials', () => {
8582
stubResponse( 'this is not json' )
8683

87-
auth.create( 'username', 'bad-password' )
88-
.catch( ( e ) => {
89-
equal( e.message, 'this is not json' )
90-
done()
91-
} )
84+
return auth.create( 'username', 'bad-password' )
85+
.catch( ( e ) => {
86+
equal( e.message, 'Failed to authenticate user.' );
87+
} );
9288
} )
9389
} )

0 commit comments

Comments
 (0)