Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
nomad-lab
nomad-FAIR
Commits
749d76f5
Commit
749d76f5
authored
Jan 29, 2019
by
Markus Scheidgen
Browse files
Switched to token based GUI authentification.
parent
3f475478
Changes
7
Hide whitespace changes
Inline
Side-by-side
gui/src/components/Development.js
View file @
749d76f5
...
...
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
import
{
withStyles
}
from
'
@material-ui/core/styles
'
import
Markdown
from
'
./Markdown
'
import
gitInfo
from
'
../gitinfo
'
import
{
kibanaBase
,
appBase
,
apiBase
}
from
'
../config
'
import
{
kibanaBase
,
apiBase
}
from
'
../config
'
class
Development
extends
React
.
Component
{
static
propTypes
=
{
...
...
gui/src/components/Navigation.js
View file @
749d76f5
...
...
@@ -60,7 +60,7 @@ class LoginLogoutComponent extends React.Component {
static
propTypes
=
{
classes
:
PropTypes
.
object
.
isRequired
,
api
:
PropTypes
.
object
.
isRequired
,
user
Name
:
PropTypes
.
string
,
user
:
PropTypes
.
object
,
login
:
PropTypes
.
func
.
isRequired
,
logout
:
PropTypes
.
func
.
isRequired
}
...
...
@@ -124,13 +124,13 @@ class LoginLogoutComponent extends React.Component {
}
render
()
{
const
{
classes
,
user
Name
}
=
this
.
props
const
{
classes
,
user
}
=
this
.
props
const
{
loggingIn
,
failure
}
=
this
.
state
if
(
user
Name
)
{
if
(
user
)
{
return
(
<
div
className
=
{
classes
.
root
}
>
<
Typography
color
=
"
inherit
"
variant
=
"
body1
"
>
Welcome
,
{
user
N
ame
}
Welcome
,
{
user
.
first_name
}
{
user
.
last_n
ame
}
<
/Typography
>
<
Button
color
=
"
inherit
"
variant
=
"
outlined
"
onClick
=
{
this
.
handleLogout
}
>
Logout
<
/Button
>
<
/div
>
...
...
gui/src/components/api.js
View file @
749d76f5
...
...
@@ -99,23 +99,30 @@ class Upload {
}
class
Api
{
constructor
(
userName
,
password
)
{
userName
=
userName
||
'
sheldon.cooper@nomad-fairdi.tests.de
'
password
=
password
||
'
password
'
this
.
swaggerPromise
=
Swagger
(
`
${
apiBase
}
/swagger.json`
,
{
authorizations
:
{
'
HTTP Basic
'
:
{
username
:
userName
,
password
:
password
static
async
createSwaggerClient
(
userNameToken
,
password
)
{
let
data
if
(
userNameToken
)
{
let
auth
=
{
'
X-Token
'
:
userNameToken
}
if
(
password
)
{
auth
=
{
'
HTTP Basic
'
:
{
username
:
userNameToken
,
password
:
password
}
}
}
})
this
.
auth_headers
=
{
Authorization
:
'
Basic
'
+
btoa
(
`
${
userName
}
:
${
password
}
`
)
data
=
{
authorizations
:
auth
}
}
return
Swagger
(
`
${
apiBase
}
/swagger.json`
,
data
)
}
constructor
(
user
)
{
user
=
user
||
{}
this
.
swaggerPromise
=
Api
.
createSwaggerClient
(
user
.
token
)
this
.
handleApiError
=
this
.
handleApiError
.
bind
(
this
)
}
...
...
@@ -214,7 +221,7 @@ class Api {
.
then
(
response
=>
response
.
body
)
}
async
authenticate
(
userName
,
password
)
{
static
async
authenticate
(
userName
,
password
)
{
const
client
=
await
this
.
swaggerPromise
return
client
.
apis
.
auth
.
get_token
()
.
catch
(
error
=>
{
...
...
@@ -280,21 +287,31 @@ export class ApiProvider extends React.Component {
}
state
=
{
errors
:
[],
api
:
new
Api
(),
token
:
null
,
userName
:
null
,
user
:
null
,
login
:
(
userName
,
password
,
callback
)
=>
{
const
api
=
new
Api
(
userName
,
password
)
api
.
authenticate
().
then
(
result
=>
{
if
(
result
)
{
this
.
setState
({
api
:
api
,
userName
:
userName
})
}
callback
(
result
)
})
Api
.
createSwaggerClient
(
userName
,
password
)
.
catch
(
this
.
state
.
api
.
handleApiError
)
.
then
(
client
=>
{
client
.
apis
.
auth
.
get_user
()
.
catch
(
error
=>
{
if
(
error
.
response
.
status
!==
401
)
{
this
.
handleApiError
(
error
)
}
})
.
then
(
response
=>
{
if
(
response
)
{
const
user
=
response
.
body
this
.
setState
({
api
:
new
Api
(
user
),
user
:
user
})
callback
(
true
)
}
else
{
callback
(
false
)
}
})
})
},
logout
:
()
=>
{
this
.
setState
({
api
:
new
Api
(),
user
Name
:
null
})
this
.
setState
({
api
:
new
Api
(),
user
:
null
})
}
}
...
...
@@ -314,9 +331,9 @@ export function withApi(loginRequired) {
return
(
<
ApiContext
.
Consumer
>
{
apiContext
=>
(
(
apiContext
.
user
Name
||
!
loginRequired
)
(
apiContext
.
user
||
!
loginRequired
)
?
<
Component
{...
props
}
api
=
{
apiContext
.
api
}
user
Name
=
{
apiContext
.
user
Name
}
{...
props
}
api
=
{
apiContext
.
api
}
user
=
{
apiContext
.
user
}
login
=
{
apiContext
.
login
}
logout
=
{
apiContext
.
logout
}
/
>
:
<
Typography
color
=
"
error
"
>
Please
login
to
use
this
functionality
<
/Typography
>
)}
...
...
nomad/api/auth.py
View file @
749d76f5
...
...
@@ -35,8 +35,8 @@ authenticated user information for authorization or otherwise.
.. autofunction:: login_really_required
"""
from
flask
import
g
,
request
,
make_response
from
flask_restplus
import
abort
,
Resource
from
flask
import
g
,
request
from
flask_restplus
import
abort
,
Resource
,
fields
from
flask_httpauth
import
HTTPBasicAuth
from
nomad
import
config
,
processing
,
files
,
utils
,
coe_repo
...
...
@@ -126,10 +126,21 @@ ns = api.namespace(
description
=
'Authentication related endpoints.'
)
@
ns
.
route
(
'/token'
)
user_model
=
api
.
model
(
'User'
,
{
'first_name'
:
fields
.
String
(
description
=
'The user
\'
s first name'
),
'last_name'
:
fields
.
String
(
description
=
'The user
\'
s last name'
),
'email'
:
fields
.
String
(
description
=
'Guess what, the user
\'
s email'
),
'affiliation'
:
fields
.
String
(
description
=
'The user
\'
s affiliation'
),
'token'
:
fields
.
String
(
description
=
'The access token that authenticates the user with the API. '
'User the HTTP header "X-Token" to provide it in API requests.'
)
})
@
ns
.
route
(
'/user'
)
class
TokenResource
(
Resource
):
@
api
.
doc
(
'get_
token
'
)
@
api
.
response
(
200
,
'Token send'
,
headers
=
{
'Content-Type'
:
'text/plain; charset=utf-8'
}
)
@
api
.
doc
(
'get_
user
'
)
@
api
.
marshal_with
(
user_model
,
skip_none
=
True
,
code
=
200
,
description
=
'User data send'
)
@
login_really_required
def
get
(
self
):
"""
...
...
@@ -140,14 +151,11 @@ class TokenResource(Resource):
a more secure method of authentication.
"""
try
:
response
=
make_response
(
g
.
user
.
get_auth_token
().
decode
(
'utf-8'
))
response
.
headers
[
'Content-Type'
]
=
'text/plain; charset=utf-8'
return
response
return
g
.
user
except
LoginException
:
abort
(
401
,
message
=
'You are not propertly logged in at the NOMAD coe repository, '
'there is no token for you.'
)
message
=
'User not logged in, provide credentials via Basic HTTP authentication.'
)
def
create_authorization_predicate
(
upload_id
,
calc_id
=
None
):
...
...
nomad/coe_repo/user.py
View file @
749d76f5
...
...
@@ -43,8 +43,9 @@ class User(Base): # type: ignore
user_id
=
Column
(
Integer
,
primary_key
=
True
)
email
=
Column
(
String
)
firstname
=
Column
(
String
)
lastname
=
Column
(
String
)
first_name
=
Column
(
String
,
name
=
'firstname'
)
last_name
=
Column
(
String
,
name
=
'lastname'
)
affiliation
=
Column
(
String
)
password
=
Column
(
String
)
def
__repr__
(
self
):
...
...
@@ -73,6 +74,10 @@ class User(Base): # type: ignore
return
session
.
token
.
encode
(
'utf-8'
)
@
property
def
token
(
self
):
return
self
.
get_auth_token
().
decode
(
'utf-8'
)
@
property
def
is_admin
(
self
)
->
bool
:
return
self
.
email
==
'admin'
...
...
nomad/migration.py
View file @
749d76f5
...
...
@@ -178,7 +178,7 @@ class NomadCOEMigration:
admin
=
target_db
.
query
(
User
).
filter_by
(
email
=
'admin'
).
first
()
if
admin
is
None
:
admin
=
User
(
user_id
=
0
,
email
=
'admin'
,
firstname
=
'admin'
,
lastname
=
'admin'
,
user_id
=
0
,
email
=
'admin'
,
first
_
name
=
'admin'
,
last
_
name
=
'admin'
,
password
=
bcrypt
.
encrypt
(
config
.
services
.
admin_password
,
ident
=
'2y'
))
target_db
.
add
(
admin
)
target_db
.
commit
()
...
...
tests/test_api.py
View file @
749d76f5
...
...
@@ -146,10 +146,18 @@ class TestAuth:
})
assert
rv
.
status_code
==
401
def
test_get_token
(
self
,
client
,
test_user_auth
,
test_user
:
User
,
no_warn
):
rv
=
client
.
get
(
'/auth/token'
,
headers
=
test_user_auth
)
def
test_get_user
(
self
,
client
,
test_user_auth
,
test_user
:
User
,
no_warn
):
rv
=
client
.
get
(
'/auth/user'
,
headers
=
test_user_auth
)
assert
rv
.
status_code
==
200
user
=
json
.
loads
(
rv
.
data
)
for
key
in
[
'first_name'
,
'last_name'
,
'email'
,
'token'
]:
assert
key
in
user
rv
=
client
.
get
(
'/uploads/'
,
headers
=
{
'X-Token'
:
user
[
'token'
]
})
assert
rv
.
status_code
==
200
assert
rv
.
data
.
decode
(
'utf-8'
)
==
test_user
.
get_auth_token
().
decode
(
'utf-8'
)
class
TestUploads
:
...
...
Write
Preview
Supports
Markdown
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