Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
C
core
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to JiHu GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Chenhao Ma
core
Commits
c518a637
Commit
c518a637
authored
11 years ago
by
Kevin S. Hahn
Browse files
Options
Downloads
Patches
Plain Diff
revisions to nimsapi URL routes
parent
c31d68f0
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
epochs.py
+13
-13
13 additions, 13 deletions
epochs.py
experiments.py
+10
-10
10 additions, 10 deletions
experiments.py
nimsapi.py
+94
-70
94 additions, 70 deletions
nimsapi.py
nimsapiutil.py
+91
-0
91 additions, 0 deletions
nimsapiutil.py
sessions.py
+14
-14
14 additions, 14 deletions
sessions.py
with
222 additions
and
107 deletions
epochs.py
+
13
−
13
View file @
c518a637
...
...
@@ -9,17 +9,17 @@ import nimsapiutil
class
Epochs
(
nimsapiutil
.
NIMSRequestHandler
):
def
count
(
self
):
def
count
(
self
,
iid
):
"""
Return the number of Epochs.
"""
self
.
response
.
write
(
'
epochs count
\n
'
)
def
post
(
self
):
"""
Create a new Epoch
"""
def
post
(
self
,
iid
):
"""
Create a new Epoch
.
"""
self
.
response
.
write
(
'
epochs post
\n
'
)
def
get
(
self
,
sess_
id
):
def
get
(
self
,
iid
,
s
id
):
"""
Return the list of Session Epochs.
"""
session
=
self
.
app
.
db
.
sessions
.
find_one
({
'
_id
'
:
bson
.
objectid
.
ObjectId
(
s
ess_
id
)})
session
=
self
.
app
.
db
.
sessions
.
find_one
({
'
_id
'
:
bson
.
objectid
.
ObjectId
(
sid
)})
if
not
session
:
self
.
abort
(
404
)
experiment
=
self
.
app
.
db
.
experiments
.
find_one
({
'
_id
'
:
bson
.
objectid
.
ObjectId
(
session
[
'
experiment
'
])})
...
...
@@ -27,21 +27,21 @@ class Epochs(nimsapiutil.NIMSRequestHandler):
self
.
abort
(
500
)
if
not
self
.
user_is_superuser
and
self
.
userid
not
in
experiment
[
'
permissions
'
]:
self
.
abort
(
403
)
query
=
{
'
session
'
:
bson
.
objectid
.
ObjectId
(
s
ess_
id
)}
query
=
{
'
session
'
:
bson
.
objectid
.
ObjectId
(
sid
)}
projection
=
[
'
timestamp
'
,
'
series
'
,
'
acquisition
'
,
'
description
'
,
'
datatype
'
]
epochs
=
list
(
self
.
app
.
db
.
epochs
.
find
(
query
,
projection
))
self
.
response
.
write
(
json
.
dumps
(
epochs
,
default
=
bson
.
json_util
.
default
))
def
put
(
self
):
def
put
(
self
,
iid
):
"""
Update many Epochs.
"""
self
.
response
.
write
(
'
epochs put
\n
'
)
class
Epoch
(
nimsapiutil
.
NIMSRequestHandler
):
def
get
(
self
,
epoch_
id
):
def
get
(
self
,
iid
,
e
id
):
"""
Return one Epoch, conditionally with details.
"""
epoch
=
self
.
app
.
db
.
epochs
.
find_one
({
'
_id
'
:
bson
.
objectid
.
ObjectId
(
e
poch_
id
)})
epoch
=
self
.
app
.
db
.
epochs
.
find_one
({
'
_id
'
:
bson
.
objectid
.
ObjectId
(
eid
)})
if
not
epoch
:
self
.
abort
(
404
)
session
=
self
.
app
.
db
.
sessions
.
find_one
({
'
_id
'
:
epoch
[
'
session
'
]})
...
...
@@ -54,10 +54,10 @@ class Epoch(nimsapiutil.NIMSRequestHandler):
self
.
abort
(
403
)
self
.
response
.
write
(
json
.
dumps
(
epoch
,
default
=
bson
.
json_util
.
default
))
def
put
(
self
,
_
id
):
def
put
(
self
,
iid
,
e
id
):
"""
Update an existing Epoch.
"""
self
.
response
.
write
(
'
epoch %s put, %s
\n
'
%
(
_id
,
self
.
request
.
params
))
self
.
response
.
write
(
'
epoch %s put, %s
\n
'
%
(
epoch
_id
,
self
.
request
.
params
))
def
delete
(
self
,
_
id
):
def
delete
(
self
,
iid
,
e
id
):
"""
Delete an Epoch.
"""
self
.
response
.
write
(
'
epoch %s delete, %s
\n
'
%
(
_id
,
self
.
request
.
params
))
self
.
response
.
write
(
'
epoch %s delete, %s
\n
'
%
(
epoch
_id
,
self
.
request
.
params
))
This diff is collapsed.
Click to expand it.
experiments.py
+
10
−
10
View file @
c518a637
...
...
@@ -9,15 +9,15 @@ import nimsapiutil
class
Experiments
(
nimsapiutil
.
NIMSRequestHandler
):
def
count
(
self
):
def
count
(
self
,
iid
):
"""
Return the number of Experiments.
"""
self
.
response
.
write
(
'
%d experiments
\n
'
%
self
.
app
.
db
.
experiments
.
count
())
def
post
(
self
):
"""
Create a new Experiment
"""
def
post
(
self
,
iid
):
"""
Create a new Experiment
.
"""
self
.
response
.
write
(
'
experiments post
\n
'
)
def
get
(
self
):
def
get
(
self
,
iid
):
"""
Return the list of Experiments.
"""
query
=
{
'
permissions.
'
+
self
.
userid
:
{
'
$exists
'
:
'
true
'
}}
if
not
self
.
user_is_superuser
else
None
projection
=
[
'
group
'
,
'
name
'
,
'
permissions.
'
+
self
.
userid
]
...
...
@@ -31,20 +31,20 @@ class Experiments(nimsapiutil.NIMSRequestHandler):
exp
[
'
timestamp
'
]
=
timestamps
[
exp
[
'
_id
'
]]
self
.
response
.
write
(
json
.
dumps
(
experiments
,
default
=
bson
.
json_util
.
default
))
def
put
(
self
):
def
put
(
self
,
iid
):
"""
Update many Experiments.
"""
self
.
response
.
write
(
'
experiments put
\n
'
)
class
Experiment
(
nimsapiutil
.
NIMSRequestHandler
):
def
get
(
self
,
exp_
id
):
def
get
(
self
,
iid
,
x
id
):
"""
Return one Experiment, conditionally with details.
"""
experiment
=
self
.
app
.
db
.
experiments
.
find_one
({
'
_id
'
:
bson
.
objectid
.
ObjectId
(
exp_
id
)})
experiment
=
self
.
app
.
db
.
experiments
.
find_one
({
'
_id
'
:
bson
.
objectid
.
ObjectId
(
x
id
)})
if
not
experiment
:
self
.
abort
(
404
)
experiment
[
'
timestamp
'
]
=
self
.
app
.
db
.
sessions
.
aggregate
([
{
'
$match
'
:
{
'
experiment
'
:
bson
.
objectid
.
ObjectId
(
exp_
id
)}},
{
'
$match
'
:
{
'
experiment
'
:
bson
.
objectid
.
ObjectId
(
x
id
)}},
{
'
$group
'
:
{
'
_id
'
:
'
$experiment
'
,
'
timestamp
'
:
{
'
$max
'
:
'
$timestamp
'
}}},
])[
'
result
'
][
0
][
'
timestamp
'
]
if
not
self
.
user_is_superuser
:
...
...
@@ -54,10 +54,10 @@ class Experiment(nimsapiutil.NIMSRequestHandler):
experiment
[
'
permissions
'
]
=
{
self
.
userid
:
experiment
[
'
permissions
'
][
self
.
userid
]}
self
.
response
.
write
(
json
.
dumps
(
experiment
,
default
=
bson
.
json_util
.
default
))
def
put
(
self
,
exp_
id
):
def
put
(
self
,
iid
,
x
id
):
"""
Update an existing Experiment.
"""
self
.
response
.
write
(
'
experiment %s put, %s
\n
'
%
(
exp_id
,
self
.
request
.
params
))
def
delete
(
self
,
exp_
id
):
def
delete
(
self
,
iid
,
x
id
):
"""
Delete an Experiment.
"""
self
.
response
.
write
(
'
experiment %s delete, %s
\n
'
%
(
exp_id
,
self
.
request
.
params
))
This diff is collapsed.
Click to expand it.
nimsapi.py
+
94
−
70
View file @
c518a637
...
...
@@ -10,9 +10,11 @@ import logging
import
pymongo
import
tarfile
import
webapp2
import
requests
import
zipfile
import
argparse
import
bson.json_util
import
webapp2_extras.routes
import
nimsutil
...
...
@@ -26,8 +28,14 @@ log = logging.getLogger('nimsapi')
class
NIMSAPI
(
nimsapiutil
.
NIMSRequestHandler
):
def
head
(
self
):
"""
Return 200 OK.
"""
self
.
response
.
set_status
(
200
)
def
get
(
self
):
self
.
response
.
write
(
'
nimsapi
\n
'
)
"""
Return API documentation
"""
self
.
response
.
headers
[
'
Content-Type
'
]
=
'
text/html; charset=utf-8
'
self
.
response
.
write
(
'
nimsapi - {0}
\n
'
.
format
(
self
.
app
.
config
[
'
site_id
'
]))
def
upload
(
self
):
# TODO add security: either authenticated user or machine-to-machine CRAM
...
...
@@ -47,7 +55,7 @@ class NIMSAPI(nimsapiutil.NIMSRequestHandler):
self
.
abort
(
400
,
'
Content-MD5 mismatch.
'
)
if
not
tarfile
.
is_tarfile
(
upload_filepath
)
and
not
zipfile
.
is_zipfile
(
upload_filepath
):
self
.
abort
(
415
)
os
.
rename
(
upload_filepath
,
os
.
path
.
join
(
stage_path
,
str
(
uuid
.
uuid1
())
+
'
_
'
+
fi
lename
))
# add UUID to prevent clobbering files
os
.
rename
(
upload_filepath
,
os
.
path
.
join
(
stage_path
,
str
(
uuid
.
uuid1
())
+
'
_
'
+
fi
d
))
# add UUID to prevent clobbering files
def
download
(
self
):
paths
=
[]
...
...
@@ -64,33 +72,33 @@ class NIMSAPI(nimsapiutil.NIMSRequestHandler):
class
Users
(
nimsapiutil
.
NIMSRequestHandler
):
def
count
(
self
):
def
count
(
self
,
iid
):
"""
Return the number of Users.
"""
self
.
response
.
write
(
'
%d users
\n
'
%
self
.
app
.
db
.
users
.
count
())
def
post
(
self
):
def
post
(
self
,
iid
):
"""
Create a new User
"""
self
.
response
.
write
(
'
users post
\n
'
)
def
get
(
self
):
def
get
(
self
,
iid
):
"""
Return the list of Users.
"""
projection
=
[
'
firstname
'
,
'
lastname
'
,
'
email_hash
'
]
users
=
list
(
self
.
app
.
db
.
users
.
find
({},
projection
))
self
.
response
.
write
(
json
.
dumps
(
users
,
default
=
bson
.
json_util
.
default
))
def
put
(
self
):
def
put
(
self
,
iid
):
"""
Update many Users.
"""
self
.
response
.
write
(
'
users put
\n
'
)
class
User
(
nimsapiutil
.
NIMSRequestHandler
):
def
get
(
self
,
uid
):
def
get
(
self
,
iid
,
uid
):
"""
Return User details.
"""
user
=
self
.
app
.
db
.
users
.
find_one
({
'
_id
'
:
uid
})
self
.
response
.
write
(
json
.
dumps
(
user
,
default
=
bson
.
json_util
.
default
))
def
put
(
self
,
uid
):
def
put
(
self
,
iid
,
uid
):
"""
Update an existing User.
"""
user
=
self
.
app
.
db
.
users
.
find_one
({
'
_id
'
:
uid
})
if
not
user
:
...
...
@@ -112,80 +120,127 @@ class User(nimsapiutil.NIMSRequestHandler):
self
.
abort
(
403
)
self
.
response
.
write
(
json
.
dumps
(
user
,
default
=
bson
.
json_util
.
default
)
+
'
\n
'
)
def
delete
(
self
,
uid
):
def
delete
(
self
,
iid
,
uid
):
"""
Delete an User.
"""
self
.
response
.
write
(
'
user %s delete, %s
\n
'
%
(
uid
,
self
.
request
.
params
))
class
Groups
(
nimsapiutil
.
NIMSRequestHandler
):
def
count
(
self
):
def
count
(
self
,
iid
):
"""
Return the number of Groups.
"""
self
.
response
.
write
(
'
%d groups
\n
'
%
self
.
app
.
db
.
groups
.
count
())
def
post
(
self
):
def
post
(
self
,
iid
):
"""
Create a new Group
"""
self
.
response
.
write
(
'
groups post
\n
'
)
def
get
(
self
):
def
get
(
self
,
iid
):
"""
Return the list of Groups.
"""
projection
=
[
'
_id
'
]
groups
=
list
(
self
.
app
.
db
.
groups
.
find
({},
projection
))
self
.
response
.
write
(
json
.
dumps
(
groups
,
default
=
bson
.
json_util
.
default
))
def
put
(
self
):
def
put
(
self
,
iid
):
"""
Update many Groups.
"""
self
.
response
.
write
(
'
groups put
\n
'
)
class
Group
(
nimsapiutil
.
NIMSRequestHandler
):
def
get
(
self
,
gid
):
def
get
(
self
,
iid
,
gid
):
"""
Return Group details.
"""
group
=
self
.
app
.
db
.
groups
.
find_one
({
'
_id
'
:
gid
})
self
.
response
.
write
(
json
.
dumps
(
group
,
default
=
bson
.
json_util
.
default
))
def
put
(
self
,
gid
):
def
put
(
self
,
iid
,
gid
):
"""
Update an existing Group.
"""
self
.
response
.
write
(
'
group %s put, %s
\n
'
%
(
gid
,
self
.
request
.
params
))
def
delete
(
self
,
gid
):
def
delete
(
self
,
iid
,
gid
):
"""
Delete an Group.
"""
class
Remotes
(
nimsapiutil
.
NIMSRequestHandler
):
def
get
(
self
):
"""
Return Remote NIMS sites
"""
logging
.
info
(
self
.
user
)
# TODO: remotes by default will show all registered remote site
if
self
.
request
.
get
(
'
all
'
):
projection
=
[
'
_id
'
,
'
hostname
'
,
'
ip4
'
]
sites
=
list
(
self
.
app
.
db
.
remotes
.
find
({},
projection
))
self
.
response
.
write
(
json
.
dumps
(
sites
,
default
=
bson
.
json_util
.
default
))
# if 'all' not specificed, then user MUST be speficied
else
:
"""
Return the list of remotes where user has membership
"""
logging
.
info
(
self
.
user
[
'
_id
'
])
# projection = ['_id', 'hostname', 'ip4']
projection
=
[
'
_id
'
,
'
hostname
'
,
'
ip4
'
,
'
users
'
]
remotes
=
list
(
self
.
app
.
db
.
remotes
.
find
({
'
users
'
:
{
'
$in
'
:
[
self
.
user
[
'
_id
'
]]}},
projection
))
self
.
response
.
write
(
json
.
dumps
(
remotes
,
default
=
bson
.
json_util
.
default
))
# TODO: IMPORTANT; refine how remotes are returned from pymongo queries
# in the list of remotes; in which sites, are there experiments, which the person has access to?
# return ONLY remote site names.
# if not superuser, does person have permissions to what is being queried
# query = {'permissions.' + self.userid: {'$in': 'true'}} if not self.user_is_superuser else None
# projection = ['_id', 'users', 'hostname', 'ip4']
# remotes = list(self.app.db.remotes.find(query, projection))
# session_aggregates = self.app.db.sessions.aggregate([
# # {'$match': {'experiment': {'$in': [exp['_id'] for exp in experiments]}}},
# {'$group': {'_id': '$experiment', 'timestamp': {'$max': '$timestamp'}}},
# ])['result']
# timestamps = {sa['_id']: sa['timestamp'] for sa in session_aggregates}
# for exp in experiments:
# exp['timestamp'] = timestamps[exp['_id']]
# self.response.write(json.dumps(experiments, default=bson.json_util.default))
class
ArgumentParser
(
argparse
.
ArgumentParser
):
def
__init__
(
self
):
super
(
ArgumentParser
,
self
).
__init__
()
self
.
add_argument
(
'
uri
'
,
help
=
'
NIMS DB URI
'
)
self
.
add_argument
(
'
stage_path
'
,
help
=
'
path to staging area
'
)
self
.
add_argument
(
'
--pubkey
'
,
default
=
'
internims/NIMSpubkey.pub
'
,
help
=
'
path to ssl pubkey
'
)
self
.
add_argument
(
'
-u
'
,
'
--uid
'
,
default
=
'
local
'
,
help
=
'
site uid
'
)
self
.
add_argument
(
'
-f
'
,
'
--logfile
'
,
help
=
'
path to log file
'
)
self
.
add_argument
(
'
-l
'
,
'
--loglevel
'
,
default
=
'
info
'
,
help
=
'
path to log file
'
)
self
.
add_argument
(
'
-q
'
,
'
--quiet
'
,
action
=
'
store_true
'
,
default
=
False
,
help
=
'
disable console logging
'
)
routes
=
[
webapp2
.
Route
(
r
'
/nimsapi
'
,
NIMSAPI
),
webapp2
.
Route
(
r
'
/nimsapi/upload
'
,
NIMSAPI
,
handler_method
=
'
upload
'
,
methods
=
[
'
PUT
'
]),
webapp2
.
Route
(
r
'
/nimsapi/download
'
,
NIMSAPI
,
handler_method
=
'
download
'
,
methods
=
[
'
GET
'
]),
webapp2
.
Route
(
r
'
/nimsapi/dump
'
,
NIMSAPI
,
handler_method
=
'
dump
'
,
methods
=
[
'
GET
'
]),
webapp2
.
Route
(
r
'
/nimsapi/users
'
,
Users
),
webapp2
.
Route
(
r
'
/nimsapi/users/count
'
,
Users
,
handler_method
=
'
count
'
,
methods
=
[
'
GET
'
]),
webapp2
.
Route
(
r
'
/nimsapi/users/<:.+>
'
,
User
),
webapp2
.
Route
(
r
'
/nimsapi/groups
'
,
Groups
),
webapp2
.
Route
(
r
'
/nimsapi/groups/count
'
,
Groups
,
handler_method
=
'
count
'
,
methods
=
[
'
GET
'
]),
webapp2
.
Route
(
r
'
/nimsapi/groups/<:.+>
'
,
Group
),
webapp2
.
Route
(
r
'
/nimsapi/experiments
'
,
experiments
.
Experiments
),
webapp2
.
Route
(
r
'
/nimsapi/experiments/count
'
,
experiments
.
Experiments
,
handler_method
=
'
count
'
,
methods
=
[
'
GET
'
]),
webapp2
.
Route
(
r
'
/nimsapi/experiments/<:[0-9a-f]+>
'
,
experiments
.
Experiment
),
webapp2
.
Route
(
r
'
/nimsapi/experiments/<:[0-9a-f]+>/sessions
'
,
sessions
.
Sessions
),
webapp2
.
Route
(
r
'
/nimsapi/sessions/count
'
,
sessions
.
Sessions
,
handler_method
=
'
count
'
,
methods
=
[
'
GET
'
]),
webapp2
.
Route
(
r
'
/nimsapi/sessions/<:[0-9a-f]+>
'
,
sessions
.
Session
),
webapp2
.
Route
(
r
'
/nimsapi/sessions/<:[0-9a-f]+>/move
'
,
sessions
.
Session
,
handler_method
=
'
move
'
),
webapp2
.
Route
(
r
'
/nimsapi/sessions/<:[0-9a-f]+>/epochs
'
,
epochs
.
Epochs
),
webapp2
.
Route
(
r
'
/nimsapi/epochs/count
'
,
epochs
.
Epochs
,
handler_method
=
'
count
'
,
methods
=
[
'
GET
'
]),
webapp2
.
Route
(
r
'
/nimsapi/epochs/<:[0-9a-f]+>
'
,
epochs
.
Epoch
),
]
webapp2
.
Route
(
r
'
/nimsapi
'
,
NIMSAPI
),
webapp2_extras
.
routes
.
PathPrefixRoute
(
r
'
/nimsapi
'
,
[
webapp2
.
Route
(
r
'
/download
'
,
NIMSAPI
,
handler_method
=
'
download
'
,
methods
=
[
'
GET
'
]),
webapp2
.
Route
(
r
'
/dump
'
,
NIMSAPI
,
handler_method
=
'
dump
'
,
methods
=
[
'
GET
'
]),
webapp2
.
Route
(
r
'
/upload/<fid>
'
,
NIMSAPI
,
handler_method
=
'
upload
'
,
methods
=
[
'
PUT
'
]),
webapp2
.
Route
(
r
'
/remotes
'
,
Remotes
),
]),
# webapp2_extras.routes.PathPrefixRoute has bug, variable MUST have regex
webapp2_extras
.
routes
.
PathPrefixRoute
(
r
'
/nimsapi/<iid:[^/]+>
'
,
[
webapp2
.
Route
(
r
'
/users
'
,
Users
),
webapp2
.
Route
(
r
'
/users/count
'
,
Users
,
handler_method
=
'
count
'
,
methods
=
[
'
GET
'
]),
webapp2
.
Route
(
r
'
/users/<uid>
'
,
User
),
webapp2
.
Route
(
r
'
/groups
'
,
Groups
),
webapp2
.
Route
(
r
'
/groups/count
'
,
Groups
,
handler_method
=
'
count
'
,
methods
=
[
'
GET
'
]),
webapp2
.
Route
(
r
'
/groups/<gid>
'
,
Group
),
webapp2
.
Route
(
r
'
/experiments
'
,
experiments
.
Experiments
),
webapp2
.
Route
(
r
'
/experiments/count
'
,
experiments
.
Experiments
,
handler_method
=
'
count
'
,
methods
=
[
'
GET
'
]),
webapp2
.
Route
(
r
'
/experiments/<xid:[0-9a-f]{24}>
'
,
experiments
.
Experiment
),
webapp2
.
Route
(
r
'
/experiments/<xid:[0-9a-f]{24}>/sessions
'
,
sessions
.
Sessions
),
webapp2
.
Route
(
r
'
/sessions/count
'
,
sessions
.
Sessions
,
handler_method
=
'
count
'
,
methods
=
[
'
GET
'
]),
webapp2
.
Route
(
r
'
/sessions/<sid:[0-9a-f]{24}>
'
,
sessions
.
Session
),
webapp2
.
Route
(
r
'
/sessions/<sid:[0-9a-f]{24}>/move
'
,
sessions
.
Session
,
handler_method
=
'
move
'
),
webapp2
.
Route
(
r
'
/sessions/<sid:[0-9a-f]{24}>/epochs
'
,
epochs
.
Epochs
),
webapp2
.
Route
(
r
'
/epochs/count
'
,
epochs
.
Epochs
,
handler_method
=
'
count
'
,
methods
=
[
'
GET
'
]),
webapp2
.
Route
(
r
'
/epochs/<eid:[0-9a-f]{24}>
'
,
epochs
.
Epoch
),
]),
]
if
__name__
==
'
__main__
'
:
...
...
@@ -193,37 +248,6 @@ if __name__ == '__main__':
nimsutil
.
configure_log
(
args
.
logfile
,
not
args
.
quiet
,
args
.
loglevel
)
from
paste
import
httpserver
app
=
webapp2
.
WSGIApplication
(
routes
,
debug
=
True
,
config
=
dict
(
stage_path
=
args
.
stage_path
))
app
=
webapp2
.
WSGIApplication
(
routes
,
debug
=
True
,
config
=
dict
(
stage_path
=
args
.
stage_path
,
site_id
=
args
.
uid
,
pubkey
=
args
.
pubkey
))
app
.
db
=
(
pymongo
.
MongoReplicaSetClient
(
args
.
uri
)
if
'
replicaSet
'
in
args
.
uri
else
pymongo
.
MongoClient
(
args
.
uri
)).
get_default_database
()
httpserver
.
serve
(
app
,
host
=
httpserver
.
socket
.
gethostname
(),
port
=
'
8080
'
)
#API = NIMSAPI
#APIResource = experiments.Experiments
#routes = [
# webapp2.Route(r'/', API),
# webapp2.Route(r'/resource', APIResource),
# ]
#
#from webapp2_extras.routes import PathPrefixRoute
#
#if __name__ == '__main__':
# from paste import httpserver
# nimsapi = webapp2.WSGIApplication([PathPrefixRoute('/', routes)], debug=True)
# httpserver.serve(nimsapi, host='127.0.0.1', port='8080')
#else:
# from webapp2_extras.routes import PathPrefixRoute
# nimsapi = webapp2.WSGIApplication([PathPrefixRoute('/nimsapi', routes)], debug=True)
# /experiments experiment info for all experiments
# /experiments/ID/sessions experiment info with embedded sessions for one experiment
# /experiments/ID/epochs experiment info with embedded sessions and embedded epochs for one experiment
# /sessions/ID/epochs experiment info with embedded sessions and embedded epochs for one session
# /sessions experiment info with embedded sessions for all experiments
# /epochs experiment info with embedded sessions and embedded epochs for all sessions
# /experiments/ID experiment details for one experiment
# /sessions/ID sessions details for one session
# /epochs/ID epoch details for one epoch
This diff is collapsed.
Click to expand it.
nimsapiutil.py
+
91
−
0
View file @
c518a637
# @author: Gunnar Schaefer
# @author: Kevin S. Hahn
import
base64
import
datetime
import
json
import
logging
import
requests
import
webapp2
import
socket
# socket.gethostname()
from
Crypto.Hash
import
HMAC
from
Crypto.Random
import
random
logging
.
basicConfig
(
level
=
logging
.
INFO
)
class
NIMSRequestHandler
(
webapp2
.
RequestHandler
):
"""
fetches pubkey from own self.db.remotes. needs to be aware of OWN site uid
"""
def
__init__
(
self
,
request
=
None
,
response
=
None
):
webapp2
.
RequestHandler
.
__init__
(
self
,
request
,
response
)
# call initialize, isntead of __init__
self
.
request
.
remote_user
=
self
.
request
.
get
(
'
user
'
,
None
)
# FIXME: auth system should set REMOTE_USER
self
.
userid
=
self
.
request
.
remote_user
or
'
@public
'
self
.
user
=
self
.
app
.
db
.
users
.
find_one
({
'
_id
'
:
self
.
userid
})
self
.
user_is_superuser
=
self
.
user
.
get
(
'
superuser
'
)
self
.
response
.
headers
[
'
Content-Type
'
]
=
'
application/json
'
try
:
self
.
target_id
=
request
.
route_kwargs
[
'
iid
'
]
# for what site is the request meant
except
KeyError
:
self
.
target_id
=
'
local
'
# change to site_id?
self
.
useragent
=
self
.
request
.
headers
[
'
user-agent
'
]
# browser or internimsP2P request
self
.
site_id
=
self
.
app
.
config
[
'
site_id
'
]
# what is THIS site
self
.
pubkey
=
open
(
self
.
app
.
config
[
'
pubkey
'
]).
read
()
# requests coming from another NIMS instance are dealt with differently
if
self
.
useragent
.
startswith
(
'
NIMS Instance
'
):
logging
.
info
(
"
request from
'
{0}
'
, interNIMS p2p initiated
"
.
format
(
self
.
useragent
))
try
:
authinfo
=
self
.
request
.
headers
[
'
authorization
'
]
challenge_id
,
digest
=
base64
.
b64decode
(
authinfo
).
split
()
user
,
remote_site
=
challenge_id
.
split
(
'
:
'
)
# logging.info('{0} {1} {2}'.format(user, remote_site, digest))
projection
=
{
'
_id
'
:
False
,
'
pubkey
'
:
True
}
remote_pubkey
=
self
.
app
.
db
.
remotes
.
find_one
({
'
_id
'
:
remote_site
},
projection
)[
'
pubkey
'
]
# get the challenge from db.challenges
projection
=
{
'
_id
'
:
False
,
'
challenge
'
:
True
}
challenge
=
self
.
app
.
db
.
challenges
.
find_one
({
'
_id
'
:
challenge_id
},
projection
)[
'
challenge
'
]
# purge challenge (challenges are single use)
self
.
app
.
db
.
challenges
.
remove
({
'
_id
'
:
challenge_id
})
# verify
h
=
HMAC
.
new
(
remote_pubkey
,
challenge
)
self
.
expected
=
base64
.
b64encode
(
'
%s %s
'
%
(
challenge_id
,
h
.
hexdigest
()))
if
self
.
expected
==
authinfo
:
logging
.
info
(
'
CRAM successful
'
)
else
:
self
.
abort
(
403
,
'
Not Authorized: cram failed
'
)
except
KeyError
,
e
:
# send a 401 with a fresh challenge
cid
=
self
.
request
.
get
(
'
cid
'
)
if
not
cid
:
self
.
abort
(
403
,
'
challenge_id not in payload
'
)
challenge
=
{
'
_id
'
:
cid
,
'
challenge
'
:
str
(
random
.
getrandbits
(
128
)),
'
timestamp
'
:
datetime
.
datetime
.
now
()}
# upsert challenge with time of creation
spam
=
self
.
app
.
db
.
challenges
.
find_and_modify
(
query
=
{
'
_id
'
:
cid
},
update
=
challenge
,
upsert
=
True
,
new
=
True
)
# send 401 + challenge in 'www-authenticate' header
self
.
response
.
headers
[
'
www-authenticate
'
]
=
base64
.
b64encode
(
challenge
[
'
challenge
'
])
self
.
response
.
set_status
(
401
)
def
dispatch
(
self
):
"""
dispatching and request forwarding
"""
if
self
.
target_id
in
[
'
local
'
,
self
.
site_id
]:
logging
.
info
(
'
{0} delegating to local {1}
'
.
format
(
socket
.
gethostname
(),
self
.
request
.
url
))
super
(
NIMSRequestHandler
,
self
).
dispatch
()
else
:
logging
.
info
(
'
{0} delegating to remote {1}
'
.
format
(
socket
.
gethostname
(),
self
.
target_id
))
# is target registered?
target
=
self
.
app
.
db
.
remotes
.
find_one
({
'
_id
'
:
self
.
target_id
},
{
'
_id
'
:
False
,
'
hostname
'
:
True
})
if
not
target
:
logging
.
info
(
'
remote host {0} not in auth list. DENIED
'
.
format
(
self
.
target_id
))
self
.
abort
(
403
,
'
forbidden: site is not registered with interNIMS
'
)
self
.
cid
=
self
.
userid
+
'
:
'
+
self
.
site_id
reqheaders
=
dict
(
self
.
request
.
headers
)
# adjust the request, pass as much of orig request as possible
reqheaders
[
'
User-Agent
'
]
=
'
NIMS Instance {0}
'
.
format
(
self
.
site_id
)
del
reqheaders
[
'
Host
'
]
target_api
=
'
http://{0}{1}?{2}
'
.
format
(
target
[
'
hostname
'
],
self
.
request
.
path
,
self
.
request
.
query_string
)
reqparams
=
{
'
cid
'
:
self
.
cid
}
# first attempt, expect 401, send as little as possible...
r
=
requests
.
request
(
method
=
self
.
request
.
method
,
url
=
target_api
,
params
=
reqparams
,
headers
=
reqheaders
,
cookies
=
self
.
request
.
cookies
)
if
r
.
status_code
==
401
:
challenge
=
base64
.
b64decode
(
r
.
headers
[
'
www-authenticate
'
])
# logging.info('challenge {0} recieved'.format(challenge))
h
=
HMAC
.
new
(
self
.
pubkey
,
challenge
)
response
=
base64
.
b64encode
(
'
%s %s
'
%
(
self
.
cid
,
h
.
hexdigest
()))
# logging.info('sending: {0} {1}'.format(self.cid, h.hexdigest()))
#adjust the request and try again
reqheaders
[
'
authorization
'
]
=
response
r
=
requests
.
request
(
method
=
self
.
request
.
method
,
url
=
target_api
,
params
=
reqparams
,
data
=
self
.
request
.
body
,
headers
=
reqheaders
,
cookies
=
self
.
request
.
cookies
)
self
.
response
.
write
(
r
.
content
)
This diff is collapsed.
Click to expand it.
sessions.py
+
14
−
14
View file @
c518a637
...
...
@@ -9,36 +9,36 @@ import nimsapiutil
class
Sessions
(
nimsapiutil
.
NIMSRequestHandler
):
def
count
(
self
):
def
count
(
self
,
iid
):
"""
Return the number of Sessions.
"""
self
.
response
.
write
(
'
sessions count
\n
'
)
def
post
(
self
):
def
post
(
self
,
iid
):
"""
Create a new Session
"""
self
.
response
.
write
(
'
sessions post
\n
'
)
def
get
(
self
,
exp_
id
):
def
get
(
self
,
iid
,
x
id
):
"""
Return the list of Experiment Sessions.
"""
experiment
=
self
.
app
.
db
.
experiments
.
find_one
({
'
_id
'
:
bson
.
objectid
.
ObjectId
(
exp_
id
)})
experiment
=
self
.
app
.
db
.
experiments
.
find_one
({
'
_id
'
:
bson
.
objectid
.
ObjectId
(
x
id
)})
if
not
experiment
:
self
.
abort
(
404
)
if
not
self
.
user_is_superuser
and
self
.
userid
not
in
experiment
[
'
permissions
'
]:
self
.
abort
(
403
)
query
=
{
'
experiment
'
:
bson
.
objectid
.
ObjectId
(
exp_
id
)}
query
=
{
'
experiment
'
:
bson
.
objectid
.
ObjectId
(
x
id
)}
projection
=
[
'
timestamp
'
,
'
subject
'
]
sessions
=
list
(
self
.
app
.
db
.
sessions
.
find
(
query
,
projection
))
self
.
response
.
write
(
json
.
dumps
(
sessions
,
default
=
bson
.
json_util
.
default
))
def
put
(
self
):
def
put
(
self
,
iid
):
"""
Update many Sessions.
"""
self
.
response
.
write
(
'
sessions put
\n
'
)
class
Session
(
nimsapiutil
.
NIMSRequestHandler
):
def
get
(
self
,
sess_
id
):
def
get
(
self
,
iid
,
s
id
):
"""
Return one Session, conditionally with details.
"""
session
=
self
.
app
.
db
.
sessions
.
find_one
({
'
_id
'
:
bson
.
objectid
.
ObjectId
(
s
ess_
id
)})
session
=
self
.
app
.
db
.
sessions
.
find_one
({
'
_id
'
:
bson
.
objectid
.
ObjectId
(
sid
)})
if
not
session
:
self
.
abort
(
404
)
experiment
=
self
.
app
.
db
.
experiments
.
find_one
({
'
_id
'
:
bson
.
objectid
.
ObjectId
(
session
[
'
experiment
'
])})
...
...
@@ -48,19 +48,19 @@ class Session(nimsapiutil.NIMSRequestHandler):
self
.
abort
(
403
)
self
.
response
.
write
(
json
.
dumps
(
session
,
default
=
bson
.
json_util
.
default
))
def
put
(
self
,
_
id
):
def
put
(
self
,
iid
,
s
id
):
"""
Update an existing Session.
"""
self
.
response
.
write
(
'
session %s put, %s
\n
'
%
(
_
id
,
self
.
request
.
params
))
self
.
response
.
write
(
'
session %s put, %s
\n
'
%
(
s
id
,
self
.
request
.
params
))
def
delete
(
self
,
_
id
):
def
delete
(
self
,
iid
,
s
id
):
"""
Delete an Session.
"""
self
.
response
.
write
(
'
session %s delete, %s
\n
'
%
(
_
id
,
self
.
request
.
params
))
self
.
response
.
write
(
'
session %s delete, %s
\n
'
%
(
s
id
,
self
.
request
.
params
))
def
move
(
self
,
_
id
):
def
move
(
self
,
iid
,
s
id
):
"""
Move a Session to another Experiment.
Usage:
/nimsapi/sessions/123/move?dest=456
"""
self
.
response
.
write
(
'
session %s move, %s
\n
'
%
(
_
id
,
self
.
request
.
params
))
self
.
response
.
write
(
'
session %s move, %s
\n
'
%
(
s
id
,
self
.
request
.
params
))
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment