Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
coopwire-hypothesis
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
孙灵跃 Leon Sun
coopwire-hypothesis
Commits
f4e9e5de
Commit
f4e9e5de
authored
Jul 27, 2015
by
Randall Leeds
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2403 from hypothesis/simpler-session-service
Simpler session service
parents
b29c9bac
3ed424cb
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
238 additions
and
210 deletions
+238
-210
app.coffee
h/static/scripts/app.coffee
+1
-1
accounts.js
h/static/scripts/config/accounts.js
+3
-35
session.coffee
h/static/scripts/session.coffee
+0
-81
session.js
h/static/scripts/session.js
+114
-0
session-test.coffee
h/static/scripts/test/session-test.coffee
+0
-93
session-test.js
h/static/scripts/test/session-test.js
+120
-0
No files found.
h/static/scripts/app.coffee
View file @
f4e9e5de
...
...
@@ -121,7 +121,6 @@ module.exports = angular.module('h', [
.
filter
(
'urlencode'
,
require
(
'./filter/urlencode'
))
.
provider
(
'identity'
,
require
(
'./identity'
))
.
provider
(
'session'
,
require
(
'./session'
))
.
service
(
'annotator'
,
->
new
Annotator
(
angular
.
element
(
'<div>'
)))
.
service
(
'annotationMapper'
,
require
(
'./annotation-mapper'
))
...
...
@@ -140,6 +139,7 @@ module.exports = angular.module('h', [
.
service
(
'queryParser'
,
require
(
'./query-parser'
))
.
service
(
'render'
,
require
(
'./render'
))
.
service
(
'searchFilter'
,
require
(
'./search-filter'
))
.
service
(
'session'
,
require
(
'./session'
))
.
service
(
'store'
,
require
(
'./store'
))
.
service
(
'streamFilter'
,
require
(
'./stream-filter'
))
.
service
(
'streamer'
,
require
(
'./streamer'
))
...
...
h/static/scripts/config/accounts.js
View file @
f4e9e5de
var
angular
=
require
(
'angular'
);
var
SESSION_ACTIONS
=
[
'login'
,
'logout'
,
'register'
,
'forgot_password'
,
'reset_password'
,
'edit_profile'
,
'disable_user'
];
configure
.
$inject
=
[
'$httpProvider'
,
'identityProvider'
,
'sessionProvider'
];
function
configure
(
$httpProvider
,
identityProvider
,
sessionProvider
)
{
configure
.
$inject
=
[
'$httpProvider'
,
'identityProvider'
];
function
configure
(
$httpProvider
,
identityProvider
)
{
// Pending authentication check
var
authCheck
=
null
;
...
...
@@ -66,32 +60,6 @@ function configure( $httpProvider, identityProvider, sessionProvider) {
});
}
];
sessionProvider
.
actions
.
load
=
{
method
:
'GET'
,
withCredentials
:
true
};
sessionProvider
.
actions
.
profile
=
{
method
:
'GET'
,
params
:
{
__formid__
:
'profile'
},
withCredentials
:
true
};
for
(
var
i
=
0
;
i
<
SESSION_ACTIONS
.
length
;
i
++
)
{
var
action
=
SESSION_ACTIONS
[
i
];
sessionProvider
.
actions
[
action
]
=
{
method
:
'POST'
,
params
:
{
__formid__
:
action
},
withCredentials
:
true
};
}
}
angular
.
module
(
'h'
)
.
value
(
'xsrf'
,
{
token
:
null
})
.
config
(
configure
);
angular
.
module
(
'h'
).
config
(
configure
);
h/static/scripts/session.coffee
deleted
100644 → 0
View file @
b29c9bac
angular
=
require
(
'angular'
)
###*
# @ngdoc provider
# @name sessionProvider
# @property {Object} actions additional actions to mix into the resource.
# @property {Object} options additional options mix into resource actions.
# @description
# This class provides an angular $resource factory as an angular service
# for manipulating server-side sessions. It defines the REST-ish actions
# that return the state of the users session after modifying it through
# registration, authentication, or account management.
###
module.exports = class SessionProvider
actions: null
options: null
constructor: ->
@actions = {}
@options = {}
###
*
# @ngdoc service
# @name session
# @description
# An angular resource factory for sessions. See the documentation for
# {@link sessionProvider sessionProvider} for ways to configure the
# resource.
#
# @example
# Using the session with BrowserID.
#
# navigator.id.beginAuthentication(function (email) {
# session.load(function (data) {
# var user = data.user;
# if(user && user.email == email) {
# navigator.id.completeAuthentication();
# } else {
# displayLoginForm();
# }
# });
# });
###
$get
:
[
'$document'
,
'$http'
,
'$q'
,
'$resource'
,
'flash'
,
'xsrf'
,
(
$document
,
$http
,
$q
,
$resource
,
flash
,
xsrf
)
->
actions
=
{}
provider
=
this
prepare
=
(
data
,
headersGetter
)
->
headersGetter
()[
$http
.
defaults
.
xsrfHeaderName
]
=
xsrf
.
token
return
angular
.
toJson
data
process
=
(
data
,
headersGetter
)
->
# Parse as json
data
=
angular
.
fromJson
data
# Lift response data
model
=
data
.
model
or
{}
model
.
errors
=
data
.
errors
model
.
reason
=
data
.
reason
# Fire flash messages.
for
q
,
msgs
of
data
.
flash
for
m
in
msgs
flash
[
q
](
m
)
xsrf
.
token
=
model
.
csrf
# Return the model
model
for
name
,
options
of
provider
.
actions
actions
[
name
]
=
angular
.
extend
{},
options
,
@
options
actions
[
name
].
transformRequest
=
prepare
actions
[
name
].
transformResponse
=
process
base
=
$document
.
prop
(
'baseURI'
)
endpoint
=
new
URL
(
'/app'
,
base
).
href
$resource
(
endpoint
,
{},
actions
)
]
h/static/scripts/session.js
0 → 100644
View file @
f4e9e5de
'use strict'
;
var
angular
=
require
(
'angular'
);
var
ACCOUNT_ACTIONS
=
[
[
'login'
,
'POST'
],
[
'logout'
,
'POST'
],
[
'register'
,
'POST'
],
[
'forgot_password'
,
'POST'
],
[
'reset_password'
,
'POST'
],
[
'profile'
,
'GET'
],
[
'edit_profile'
,
'POST'
],
[
'disable_user'
,
'POST'
]
];
function
sessionActions
(
options
)
{
var
actions
=
{};
// These map directly to views in `h.accounts`, and all have a similar form:
for
(
var
i
=
0
,
len
=
ACCOUNT_ACTIONS
.
length
;
i
<
len
;
i
++
)
{
var
name
=
ACCOUNT_ACTIONS
[
i
][
0
];
var
method
=
ACCOUNT_ACTIONS
[
i
][
1
];
actions
[
name
]
=
{
method
:
method
,
params
:
{
__formid__
:
name
}
};
}
// Finally, add a simple method for getting the current session state
actions
.
load
=
{
method
:
'GET'
};
if
(
typeof
options
!==
'undefined'
)
{
for
(
var
act
in
actions
)
{
for
(
var
opt
in
options
)
{
actions
[
act
][
opt
]
=
options
[
opt
];
}
}
}
return
actions
;
}
/**
* @ngdoc service
* @name session
* @description
* Access to the application session and account actions. This service gives
* other parts of the application access to parts of the server-side session
* state (such as current authenticated userid, CSRF token, etc.).
*
* In addition, this service also provides helper methods for mutating the
* session state, by, e.g. logging in, logging out, etc.
*/
// TODO: Move accounts data management (e.g. profile, edit_profile,
// disable_user, etc) into another module with another route.
session
.
$inject
=
[
'$document'
,
'$http'
,
'$resource'
,
'flash'
];
function
session
(
$document
,
$http
,
$resource
,
flash
)
{
var
actions
=
sessionActions
({
transformRequest
:
prepare
,
transformResponse
:
process
,
withCredentials
:
true
});
var
base
=
$document
.
prop
(
'baseURI'
);
var
endpoint
=
new
URL
(
'/app'
,
base
).
href
;
var
resource
=
$resource
(
endpoint
,
{},
actions
);
// Blank inital model state
resource
.
state
=
{};
function
prepare
(
data
,
headersGetter
)
{
var
csrfTok
=
resource
.
state
.
csrf
;
if
(
typeof
csrfTok
!==
'undefined'
)
{
headersGetter
()[
$http
.
defaults
.
xsrfHeaderName
]
=
csrfTok
;
}
return
angular
.
toJson
(
data
);
}
function
process
(
data
,
headersGetter
)
{
// Parse as json
data
=
angular
.
fromJson
(
data
);
// Lift response data
var
model
=
data
.
model
||
{};
if
(
typeof
data
.
errors
!==
'undefined'
)
{
model
.
errors
=
data
.
errors
;
}
if
(
typeof
data
.
reason
!==
'undefined'
)
{
model
.
reason
=
data
.
reason
;
}
// Fire flash messages.
for
(
var
type
in
data
.
flash
)
{
if
(
data
.
flash
.
hasOwnProperty
(
type
))
{
var
msgs
=
data
.
flash
[
type
];
for
(
var
i
=
0
,
len
=
msgs
.
length
;
i
<
len
;
i
++
)
{
flash
[
type
](
msgs
[
i
]);
}
}
}
// Copy the model data (including the CSRF token) into `resource.state`.
angular
.
copy
(
model
,
resource
.
state
);
// Return the model
return
model
;
}
return
resource
;
}
module
.
exports
=
session
;
h/static/scripts/test/session-test.coffee
deleted
100644 → 0
View file @
b29c9bac
{
module
,
inject
}
=
require
(
'angular-mock'
)
assert
=
chai
.
assert
sinon
.
assert
.
expose
assert
,
prefix
:
null
describe
'session'
,
->
fakeFlash
=
null
fakeDocument
=
null
fakeXsrf
=
null
sandbox
=
null
before
->
angular
.
module
(
'h'
,
[
'ngResource'
])
.
provider
(
'session'
,
require
(
'../session'
))
beforeEach
module
(
'h'
)
beforeEach
module
(
$provide
,
sessionProvider
)
->
sandbox
=
sinon
.
sandbox
.
create
()
fakeDocument
=
{
prop
:
->
'/session'
}
fakeFlash
=
error
:
sandbox
.
spy
()
fakeXsrf
=
{
token
:
'faketoken'
}
$provide
.
value
'$document'
,
fakeDocument
$provide
.
value
'flash'
,
fakeFlash
$provide
.
value
'xsrf'
,
fakeXsrf
sessionProvider
.
actions
=
login
:
url
:
'/login'
method
:
'POST'
return
afterEach
->
sandbox
.
restore
()
describe
'sessionService'
,
->
$httpBackend
=
null
session
=
null
beforeEach
inject
(
_$httpBackend_
,
_session_
)
->
$httpBackend
=
_$httpBackend_
session
=
_session_
describe
'#<action>()'
,
->
url
=
'/login'
it
'should send an HTTP POST to the action'
,
->
$httpBackend
.
expectPOST
(
url
,
code
:
123
).
respond
({})
result
=
session
.
login
(
code
:
123
)
$httpBackend
.
flush
()
it
'should invoke the flash service with any flash messages'
,
->
response
=
flash
:
error
:
[
'fail'
]
$httpBackend
.
expectPOST
(
url
).
respond
(
response
)
result
=
session
.
login
({})
$httpBackend
.
flush
()
assert
.
calledWith
fakeFlash
.
error
,
'fail'
it
'should assign errors and status reasons to the model'
,
->
response
=
model
:
userid
:
'alice'
errors
:
password
:
'missing'
reason
:
'bad credentials'
$httpBackend
.
expectPOST
(
url
).
respond
(
response
)
result
=
session
.
login
({})
$httpBackend
.
flush
()
assert
.
match
result
,
response
.
model
,
'the model is present'
assert
.
match
result
.
errors
,
response
.
errors
,
'the errors are present'
assert
.
match
result
.
reason
,
response
.
reason
,
'the reason is present'
it
'should capture and send the xsrf token'
,
->
token
=
'deadbeef'
headers
=
'Accept'
:
'application/json, text/plain, */*'
'Content-Type'
:
'application/json;charset=utf-8'
'X-XSRF-TOKEN'
:
token
model
=
{
csrf
:
token
}
request
=
$httpBackend
.
expectPOST
(
url
).
respond
({
model
})
result
=
session
.
login
({})
$httpBackend
.
flush
()
assert
.
equal
fakeXsrf
.
token
,
token
$httpBackend
.
expectPOST
(
url
,
{},
headers
).
respond
({})
session
.
login
({})
$httpBackend
.
flush
()
h/static/scripts/test/session-test.js
0 → 100644
View file @
f4e9e5de
"use strict"
;
var
mock
=
require
(
'angular-mock'
);
var
assert
=
chai
.
assert
;
sinon
.
assert
.
expose
(
assert
,
{
prefix
:
null
});
describe
(
'h:session'
,
function
()
{
var
$httpBackend
;
var
fakeFlash
;
var
fakeXsrf
;
var
sandbox
;
var
session
;
before
(
function
()
{
angular
.
module
(
'h'
,
[
'ngResource'
])
.
service
(
'session'
,
require
(
'../session'
));
});
beforeEach
(
mock
.
module
(
'h'
));
beforeEach
(
mock
.
module
(
function
(
$provide
)
{
sandbox
=
sinon
.
sandbox
.
create
();
var
fakeDocument
=
{
prop
:
sandbox
.
stub
()
};
fakeDocument
.
prop
.
withArgs
(
'baseURI'
).
returns
(
'http://foo.com/'
);
fakeFlash
=
{
error
:
sandbox
.
spy
()};
$provide
.
value
(
'$document'
,
fakeDocument
);
$provide
.
value
(
'flash'
,
fakeFlash
);
}));
beforeEach
(
mock
.
inject
(
function
(
_$httpBackend_
,
_session_
)
{
$httpBackend
=
_$httpBackend_
;
session
=
_session_
;
}));
afterEach
(
function
()
{
$httpBackend
.
verifyNoOutstandingExpectation
();
$httpBackend
.
verifyNoOutstandingRequest
();
sandbox
.
restore
();
});
// There's little point testing every single route here, as they're
// declarative and ultimately we'd be testing ngResource.
describe
(
'#login()'
,
function
()
{
var
url
=
'http://foo.com/app?__formid__=login'
;
it
(
'should send an HTTP POST to the action'
,
function
()
{
$httpBackend
.
expectPOST
(
url
,
{
code
:
123
}).
respond
({});
session
.
login
({
code
:
123
});
$httpBackend
.
flush
();
});
it
(
'should invoke the flash service with any flash messages'
,
function
()
{
var
response
=
{
flash
:
{
error
:
[
'fail'
]
}
};
$httpBackend
.
expectPOST
(
url
).
respond
(
response
);
session
.
login
({});
$httpBackend
.
flush
();
assert
.
calledWith
(
fakeFlash
.
error
,
'fail'
);
});
it
(
'should assign errors and status reasons to the model'
,
function
()
{
var
response
=
{
model
:
{
userid
:
'alice'
},
errors
:
{
password
:
'missing'
},
reason
:
'bad credentials'
};
$httpBackend
.
expectPOST
(
url
).
respond
(
response
);
var
result
=
session
.
login
({});
$httpBackend
.
flush
();
assert
.
match
(
result
,
response
.
model
,
'the model is present'
);
assert
.
match
(
result
.
errors
,
response
.
errors
,
'the errors are present'
);
assert
.
match
(
result
.
reason
,
response
.
reason
,
'the reason is present'
);
});
it
(
'should capture and send the xsrf token'
,
function
()
{
var
token
=
'deadbeef'
;
var
headers
=
{
'Accept'
:
'application/json, text/plain, */*'
,
'Content-Type'
:
'application/json;charset=utf-8'
,
'X-XSRF-TOKEN'
:
token
};
var
model
=
{
csrf
:
token
};
$httpBackend
.
expectPOST
(
url
).
respond
({
model
:
model
});
session
.
login
({});
$httpBackend
.
flush
();
assert
.
equal
(
session
.
state
.
csrf
,
token
);
$httpBackend
.
expectPOST
(
url
,
{},
headers
).
respond
({});
session
.
login
({});
$httpBackend
.
flush
();
});
it
(
'should expose the model as session.state'
,
function
()
{
var
response
=
{
model
:
{
userid
:
'alice'
}
};
assert
.
deepEqual
(
session
.
state
,
{});
$httpBackend
.
expectPOST
(
url
).
respond
(
response
);
session
.
login
({});
$httpBackend
.
flush
();
assert
.
deepEqual
(
session
.
state
,
response
.
model
);
});
});
});
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment