Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Simone Rossi
main
Commits
8be21d18
Commit
8be21d18
authored
Feb 23, 2018
by
Daniele Venzano
Browse files
Start implementing user commands
parent
aaaca527
Changes
11
Hide whitespace changes
Inline
Side-by-side
zoe_api/api_endpoint.py
View file @
8be21d18
...
...
@@ -226,7 +226,7 @@ class APIEndpoint:
users
=
self
.
sql
.
user
.
select
(
**
filters
)
return
users
def
user_new
(
self
,
user
:
zoe_lib
.
state
.
User
,
username
:
str
,
fs_uid
:
int
,
role_id
:
int
,
quota_id
:
int
,
auth_source
:
str
)
->
int
:
def
user_new
(
self
,
user
:
zoe_lib
.
state
.
User
,
username
:
str
,
email
:
str
,
role_id
:
int
,
quota_id
:
int
,
auth_source
:
str
)
->
int
:
"""Creates a new user."""
if
not
user
.
role
.
can_change_config
:
raise
zoe_api
.
exceptions
.
ZoeAuthException
()
...
...
@@ -236,7 +236,7 @@ class APIEndpoint:
if
self
.
quota_by_id
(
quota_id
)
is
None
:
raise
zoe_api
.
exceptions
.
ZoeNotFoundException
(
"Quota {} does not exist"
.
format
(
quota_id
))
return
self
.
sql
.
user
.
insert
(
username
,
fs_uid
,
role_id
,
quota_id
,
auth_source
)
return
self
.
sql
.
user
.
insert
(
username
,
email
,
auth_source
,
role_id
,
quota_id
)
def
user_update
(
self
,
user
:
zoe_lib
.
state
.
User
,
user_id
,
user_data
):
"""Update a user."""
...
...
@@ -257,16 +257,21 @@ class APIEndpoint:
update_fields
[
'enabled'
]
=
user_data
[
'enabled'
]
if
'auth_source'
in
user_data
:
update_fields
[
'auth_source'
]
=
user_data
[
'auth_source'
]
if
'quota'
in
user_data
:
quota
=
self
.
quota_by_name
(
user_data
[
'quota'
])
if
user_data
[
'auth_source'
]
!=
'internal'
:
user_data
[
'password'
]
=
None
if
'quota_id'
in
user_data
:
quota
=
self
.
quota_by_id
(
user_data
[
'quota_id'
])
if
quota
is
None
:
raise
zoe_api
.
exceptions
.
ZoeRestAPIException
(
'No quota
called
{}'
.
format
(
user_data
[
'quota'
]))
raise
zoe_api
.
exceptions
.
ZoeRestAPIException
(
'No quota
with ID
{}'
.
format
(
user_data
[
'quota
_id
'
]))
update_fields
[
'quota_id'
]
=
quota
.
id
if
'role'
in
user_data
:
role
=
self
.
role_by_
name
(
user_data
[
'role'
])
role
=
self
.
role_by_
id
(
user_data
[
'role
_id
'
])
if
role
is
None
:
raise
zoe_api
.
exceptions
.
ZoeRestAPIException
(
'No role
called
{}'
.
format
(
user_data
[
'role'
]))
raise
zoe_api
.
exceptions
.
ZoeRestAPIException
(
'No role
with ID
{}'
.
format
(
user_data
[
'role
_id
'
]))
update_fields
[
'role_id'
]
=
role
.
id
if
'password'
in
user_data
:
update_fields
[
'password'
]
=
user_data
[
'password'
]
update_fields
[
'auth_source'
]
=
'internal'
self
.
sql
.
user
.
update
(
user_id
,
**
update_fields
)
...
...
zoe_api/entrypoint.py
View file @
8be21d18
...
...
@@ -53,10 +53,6 @@ def zoe_web_main(test_conf=None) -> int:
logging
.
getLogger
(
"MARKDOWN"
).
setLevel
(
logging
.
WARNING
)
logging
.
getLogger
(
"tornado"
).
setLevel
(
logging
.
WARNING
)
if
config
.
get_conf
().
auth_type
==
'ldap'
and
not
zoe_api
.
auth
.
ldap
.
LDAP_AVAILABLE
:
log
.
error
(
"LDAP authentication requested, but 'pyldap' module not installed."
)
return
1
sql_manager
=
zoe_lib
.
state
.
SQLManager
(
config
.
get_conf
())
sql_manager
.
init_db
()
...
...
zoe_api/rest_api/user.py
View file @
8be21d18
...
...
@@ -102,6 +102,12 @@ class UserCollectionAPI(ZoeAPIRequestHandler):
if
filt
[
0
]
in
self
.
request
.
arguments
:
if
filt
[
1
]
==
str
:
filter_dict
[
filt
[
0
]]
=
self
.
request
.
arguments
[
filt
[
0
]][
0
].
decode
(
'utf-8'
)
if
filt
[
1
]
==
bool
:
text_val
=
self
.
request
.
arguments
[
filt
[
0
]][
0
].
decode
(
'utf-8'
)
if
text_val
==
'False'
:
filter_dict
[
filt
[
0
]]
=
False
elif
text_val
==
'True'
:
filter_dict
[
filt
[
0
]]
=
True
else
:
filter_dict
[
filt
[
0
]]
=
filt
[
1
](
self
.
request
.
arguments
[
filt
[
0
]][
0
])
...
...
@@ -125,7 +131,7 @@ class UserCollectionAPI(ZoeAPIRequestHandler):
return
try
:
new_id
=
self
.
api_endpoint
.
user_new
(
self
.
current_user
,
data
[
'username'
],
data
[
'
fs_uid
'
],
data
[
'role_id'
],
data
[
'quota_id'
],
data
[
'auth_source'
])
new_id
=
self
.
api_endpoint
.
user_new
(
self
.
current_user
,
data
[
'username'
],
data
[
'
email
'
],
data
[
'role_id'
],
data
[
'quota_id'
],
data
[
'auth_source'
])
except
KeyError
:
self
.
set_status
(
400
,
'Error decoding JSON data'
)
return
...
...
zoe_cmd/api_lib/executions.py
View file @
8be21d18
...
...
@@ -82,7 +82,7 @@ class ZoeExecutionsAPI(ZoeAPIBase):
"""
data
,
status_code
=
self
.
_rest_get
(
'/execution'
,
kwargs
)
if
status_code
==
200
:
return
data
return
list
(
data
.
values
())
else
:
raise
ZoeAPIException
(
data
)
...
...
zoe_cmd/api_lib/quota.py
View file @
8be21d18
...
...
@@ -82,7 +82,7 @@ class ZoeQuotaAPI(ZoeAPIBase):
data
,
status_code
=
self
.
_rest_get
(
'/quota'
,
filters
)
if
status_code
!=
200
:
raise
ZoeAPIException
(
data
)
return
data
return
list
(
data
.
values
())
def
update
(
self
,
quota_id
:
int
,
entries
:
dict
)
->
None
:
"""
...
...
zoe_cmd/api_lib/role.py
View file @
8be21d18
...
...
@@ -82,7 +82,7 @@ class ZoeRoleAPI(ZoeAPIBase):
data
,
status_code
=
self
.
_rest_get
(
'/role'
,
filters
)
if
status_code
!=
200
:
raise
ZoeAPIException
(
data
)
return
data
return
list
(
data
.
values
())
def
update
(
self
,
role_id
:
int
,
entries
:
dict
)
->
None
:
"""
...
...
zoe_cmd/api_lib/user.py
View file @
8be21d18
...
...
@@ -82,7 +82,7 @@ class ZoeUserAPI(ZoeAPIBase):
data
,
status_code
=
self
.
_rest_get
(
'/user'
,
filters
)
if
status_code
!=
200
:
raise
ZoeAPIException
(
data
)
return
data
return
list
(
data
.
values
())
def
update
(
self
,
user_id
:
int
,
entries
)
->
None
:
"""
...
...
zoe_cmd/entrypoint.py
View file @
8be21d18
...
...
@@ -87,7 +87,7 @@ def exec_list_cmd(api: ZoeAPI, args):
data
=
api
.
executions
.
list
(
**
filters
)
if
len
(
data
)
==
0
:
return
tabular_data
=
[[
e
[
'id'
],
e
[
'name'
],
e
[
'user_id'
],
e
[
'status'
]]
for
e
in
sorted
(
data
.
values
()
,
key
=
lambda
x
:
x
[
'id'
])]
tabular_data
=
[[
e
[
'id'
],
e
[
'name'
],
e
[
'user_id'
],
e
[
'status'
]]
for
e
in
sorted
(
data
,
key
=
lambda
x
:
x
[
'id'
])]
headers
=
[
'ID'
,
'Name'
,
'User ID'
,
'Status'
]
print
(
tabulate
(
tabular_data
,
headers
))
...
...
zoe_cmd/entrypoint_admin.py
View file @
8be21d18
...
...
@@ -75,7 +75,7 @@ def exec_list_cmd(api: ZoeAPI, args):
data
=
api
.
executions
.
list
(
**
filters
)
if
len
(
data
)
==
0
:
return
tabular_data
=
[[
e
[
'id'
],
e
[
'name'
],
e
[
'user_id'
],
e
[
'status'
]]
for
e
in
sorted
(
data
.
values
()
,
key
=
lambda
x
:
x
[
'id'
])]
tabular_data
=
[[
e
[
'id'
],
e
[
'name'
],
e
[
'user_id'
],
e
[
'status'
]]
for
e
in
sorted
(
data
,
key
=
lambda
x
:
x
[
'id'
])]
headers
=
[
'ID'
,
'Name'
,
'User ID'
,
'Status'
]
print
(
tabulate
(
tabular_data
,
headers
))
...
...
@@ -147,7 +147,7 @@ def quota_ls_cmd(api: ZoeAPI, args):
if
'name'
in
args
:
filters
[
'name'
]
=
args
.
name
quotas
=
api
.
quota
.
list
(
filters
)
tabular_data
=
[[
q
[
'id'
],
q
[
'name'
],
q
[
'concurrent_executions'
],
q
[
'memory'
],
q
[
'cores'
]]
for
q_id
,
q
in
sorted
(
quotas
.
items
()
)]
tabular_data
=
[[
q
[
'id'
],
q
[
'name'
],
q
[
'concurrent_executions'
],
q
[
'memory'
],
q
[
'cores'
]]
for
q
in
sorted
(
quotas
)]
headers
=
[
'ID'
,
'Name'
,
'Conc. Executions'
,
'Memory'
,
'Cores'
]
print
(
tabulate
(
tabular_data
,
headers
))
...
...
@@ -201,10 +201,10 @@ def role_ls_cmd(api: ZoeAPI, args):
return
"No"
filters
=
{}
if
'
name
'
i
n
args
:
if
args
.
name
i
s
not
None
:
filters
[
'name'
]
=
args
.
name
roles
=
api
.
role
.
list
(
filters
)
tabular_data
=
[[
r
[
'id'
],
r
[
'name'
],
b2t
(
r
[
'can_see_status'
]),
b2t
(
r
[
'can_change_config'
]),
b2t
(
r
[
'can_operate_others'
]),
b2t
(
r
[
'can_delete_executions'
]),
b2t
(
r
[
'can_access_api'
]),
b2t
(
r
[
'can_customize_resources'
])]
for
r_id
,
r
in
sorted
(
roles
.
items
()
)]
tabular_data
=
[[
r
[
'id'
],
r
[
'name'
],
b2t
(
r
[
'can_see_status'
]),
b2t
(
r
[
'can_change_config'
]),
b2t
(
r
[
'can_operate_others'
]),
b2t
(
r
[
'can_delete_executions'
]),
b2t
(
r
[
'can_access_api'
]),
b2t
(
r
[
'can_customize_resources'
])]
for
r
in
sorted
(
roles
)]
headers
=
[
'ID'
,
'Name'
,
'See status'
,
'Change config'
,
'Operate others'
,
'Delete execs'
,
'API access'
,
'Customize resources'
]
print
(
tabulate
(
tabular_data
,
headers
))
...
...
@@ -265,6 +265,92 @@ def role_update_cmd(api: ZoeAPI, args):
api
.
role
.
update
(
args
.
id
,
role_update
)
def
user_ls_cmd
(
api
:
ZoeAPI
,
args
):
"""List defined users."""
filters
=
{}
if
args
.
username
is
not
None
:
filters
[
'username'
]
=
args
.
username
if
args
.
enabled
is
not
None
:
filters
[
'enabled'
]
=
True
if
args
.
enabled
==
1
else
False
if
args
.
auth_source
is
not
None
:
filters
[
'auth_source'
]
=
args
.
auth_source
if
args
.
role
is
not
None
:
role
=
api
.
role
.
list
({
'name'
:
args
.
role
})[
0
]
if
role
is
None
:
print
(
'Unknown role specified'
)
return
filters
[
'role_id'
]
=
role
[
'id'
]
if
args
.
quota
is
not
None
:
quota
=
api
.
quota
.
list
({
'name'
:
args
.
quota
})[
0
]
if
quota
is
None
:
print
(
'Unknown quota specified'
)
return
filters
[
'quota_id'
]
=
quota
[
'id'
]
users
=
api
.
user
.
list
(
filters
)
tabular_data
=
[]
role_cache
=
{}
quota_cache
=
{}
for
user
in
sorted
(
users
,
key
=
lambda
u
:
u
[
'id'
]):
if
user
[
'role_id'
]
in
role_cache
:
role
=
role_cache
[
user
[
'role_id'
]]
else
:
role
=
api
.
role
.
get
(
user
[
'role_id'
])
role_cache
[
user
[
'role_id'
]]
=
role
if
user
[
'quota_id'
]
in
quota_cache
:
quota
=
quota_cache
[
user
[
'quota_id'
]]
else
:
quota
=
api
.
quota
.
get
(
user
[
'quota_id'
])
quota_cache
[
user
[
'quota_id'
]]
=
quota
tabular_data
.
append
([
user
[
'id'
],
user
[
'username'
],
user
[
'email'
],
user
[
'fs_uid'
],
user
[
'priority'
],
user
[
'enabled'
],
user
[
'auth_source'
],
role
[
'name'
],
quota
[
'name'
]])
headers
=
[
'ID'
,
'Username'
,
'Email'
,
'FS UID'
,
'Priority'
,
'Enabled'
,
'Auth source'
,
'Role'
,
'Quota'
]
print
(
tabulate
(
tabular_data
,
headers
))
def
user_get_cmd
(
api
:
ZoeAPI
,
args
):
"""Get a user by its ID."""
user
=
api
.
user
.
get
(
args
.
id
)
role
=
api
.
role
.
get
(
user
[
'role_id'
])
quota
=
api
.
quota
.
get
(
role
[
'quota_id'
])
tabular_data
=
[[
user
[
'id'
],
user
[
'username'
],
user
[
'email'
],
user
[
'fs_uid'
],
user
[
'priority'
],
user
[
'enabled'
],
user
[
'auth_source'
],
role
[
'name'
],
quota
[
'name'
]]]
headers
=
[
'ID'
,
'Username'
,
'Email'
,
'FS UID'
,
'Priority'
,
'Enabled'
,
'Auth source'
,
'Role'
,
'Quota'
]
print
(
tabulate
(
tabular_data
,
headers
))
def
user_create_cmd
(
api
:
ZoeAPI
,
args
):
"""Creates a user."""
user
=
{
'username'
:
args
.
username
,
'email'
:
args
.
email
,
'auth_source'
:
args
.
auth_source
,
}
quota
=
api
.
quota
.
list
({
'name'
:
args
.
quota
})[
0
]
if
quota
is
None
:
print
(
'Unknown quota'
)
return
user
[
'quota_id'
]
=
quota
[
'id'
]
role
=
api
.
role
.
list
({
'name'
:
args
.
role
})[
0
]
if
role
is
None
:
print
(
'Unknown role'
)
return
user
[
'role_id'
]
=
role
[
'id'
]
new_id
=
api
.
user
.
create
(
user
)
print
(
'New user created with ID: {}'
.
format
(
new_id
))
def
user_delete_cmd
(
api
:
ZoeAPI
,
args
):
"""Delete a user."""
api
.
user
.
delete
(
args
.
id
)
def
user_update_cmd
(
api
:
ZoeAPI
,
args
):
"""Updates a user."""
pass
ENV_HELP_TEXT
=
'''To authenticate with Zoe you need to define three environment variables:
ZOE_URL: point to the URL of the Zoe Scheduler (ex.: http://localhost:5000/
ZOE_USER: the username used for authentication
...
...
@@ -380,6 +466,43 @@ def process_arguments() -> Tuple[ArgumentParser, Namespace]:
sub_parser
.
add_argument
(
'--can_customize_resources'
,
choices
=
[
0
,
1
],
type
=
int
,
help
=
"Can customize resource reservations before starting executions"
)
sub_parser
.
set_defaults
(
func
=
role_update_cmd
)
# Users
sub_parser
=
subparser
.
add_parser
(
'user-ls'
,
help
=
"List existing users"
)
sub_parser
.
add_argument
(
'--username'
,
help
=
"Filter by user name"
)
sub_parser
.
add_argument
(
'--enabled'
,
type
=
int
,
choices
=
[
0
,
1
],
help
=
"Filter by enabled status"
)
sub_parser
.
add_argument
(
'--auth_source'
,
choices
=
[
'internal'
,
'ldap'
,
'ldap+ssl'
,
'textfile'
],
help
=
"Filter by auth source"
)
sub_parser
.
add_argument
(
'--role'
,
help
=
"Filter by role name"
)
sub_parser
.
add_argument
(
'--quota'
,
help
=
"Filter by quota name"
)
sub_parser
.
set_defaults
(
func
=
user_ls_cmd
)
sub_parser
=
subparser
.
add_parser
(
'user-get'
,
help
=
"Get a user by its ID"
)
sub_parser
.
add_argument
(
'id'
,
type
=
int
,
help
=
"User ID"
)
sub_parser
.
set_defaults
(
func
=
user_get_cmd
)
sub_parser
=
subparser
.
add_parser
(
'user-create'
,
help
=
"Create a new user"
)
sub_parser
.
add_argument
(
'username'
,
help
=
"Username"
)
sub_parser
.
add_argument
(
'email'
,
help
=
"Email"
)
sub_parser
.
add_argument
(
'auth_source'
,
choices
=
[
'internal'
,
'ldap'
,
'ldap+ssl'
,
'textfile'
],
help
=
"Authentication method"
)
sub_parser
.
add_argument
(
'role'
,
help
=
"Role name"
)
sub_parser
.
add_argument
(
'quota'
,
help
=
"Quota name"
)
sub_parser
.
set_defaults
(
func
=
user_create_cmd
)
sub_parser
=
subparser
.
add_parser
(
'user-delete'
,
help
=
"Delete a user"
)
sub_parser
.
add_argument
(
'id'
,
type
=
int
,
help
=
"User ID"
)
sub_parser
.
set_defaults
(
func
=
user_delete_cmd
)
sub_parser
=
subparser
.
add_parser
(
'user-update'
,
help
=
"Update an existing role"
)
sub_parser
.
add_argument
(
'id'
,
type
=
int
,
help
=
"ID of the user to update"
)
sub_parser
.
add_argument
(
'--email'
,
help
=
"Change the email"
)
sub_parser
.
add_argument
(
'--fs_uid'
,
type
=
int
,
help
=
"Filesystem UID"
)
sub_parser
.
add_argument
(
'--password'
,
help
=
"Change or set the password for internal authentication"
)
sub_parser
.
add_argument
(
'--enabled'
,
type
=
int
,
choices
=
[
0
,
1
],
help
=
"Enable or disable the user"
)
sub_parser
.
add_argument
(
'--auth_source'
,
choices
=
[
'internal'
,
'ldap'
,
'ldap+ssl'
,
'textfile'
],
help
=
"Change the authentication source"
)
sub_parser
.
add_argument
(
'--priority'
,
type
=
int
,
help
=
"Change priority"
)
sub_parser
.
add_argument
(
'--role_id'
,
help
=
"Change role"
)
sub_parser
.
add_argument
(
'--quota_id'
,
help
=
"Change quota"
)
sub_parser
.
set_defaults
(
func
=
user_update_cmd
)
return
parser
,
parser
.
parse_args
()
...
...
zoe_lib/config.py
View file @
8be21d18
...
...
@@ -79,9 +79,6 @@ def load_configuration(test_conf=None):
argparser
.
add_argument
(
'--master-url'
,
help
=
'URL of the Zoe master process'
,
default
=
'tcp://127.0.0.1:4850'
)
argparser
.
add_argument
(
'--cookie-secret'
,
help
=
'secret used to encrypt cookies'
,
default
=
'changeme'
)
# API auth options
argparser
.
add_argument
(
'--auth-type'
,
help
=
'Authentication type (text, ldap or ldapsasl)'
,
default
=
'text'
)
argparser
.
add_argument
(
'--auth-file'
,
help
=
'Path to the CSV file containing user,pass,role lines for text authentication'
,
default
=
'zoepass.csv'
)
argparser
.
add_argument
(
'--ldap-server-uri'
,
help
=
'LDAP server to use for authentication'
,
default
=
'ldap://localhost'
)
...
...
zoe_lib/state/user.py
View file @
8be21d18
...
...
@@ -158,9 +158,9 @@ class UserTable(BaseTable):
else
:
return
[
User
(
x
,
self
.
sql_manager
)
for
x
in
self
.
cursor
]
def
insert
(
self
,
username
,
fs_uid
,
role_id
,
quota_id
,
auth_source
):
def
insert
(
self
,
username
:
str
,
email
:
str
,
auth_source
:
str
,
role_id
:
int
,
quota_id
:
int
):
"""Adds a new user to the state."""
query
=
self
.
cursor
.
mogrify
(
'INSERT INTO "user" (id, username, fs_uid, email, priority, enabled, auth_source, role_id, quota_id) VALUES (DEFAULT, %s,
%s, NULL
, DEFAULT,
DEFAULT
, %s, %s, %s) RETURNING id'
,
(
username
,
fs_uid
,
auth_source
,
role_id
,
quota_id
))
query
=
self
.
cursor
.
mogrify
(
'INSERT INTO "user" (id, username, fs_uid, email, priority, enabled, auth_source, role_id, quota_id) VALUES (DEFAULT, %s,
(SELECT MAX("user".fs_uid)+1 FROM "user"), %s
, DEFAULT,
TRUE
, %s, %s, %s) RETURNING id'
,
(
username
,
email
,
auth_source
,
role_id
,
quota_id
))
self
.
cursor
.
execute
(
query
)
self
.
sql_manager
.
commit
()
return
self
.
cursor
.
fetchone
()[
0
]
...
...
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