RESTful for the win

This commit is contained in:
Kload 2013-06-30 16:13:26 +00:00
parent cdfae10d40
commit 92b0761c8f
3 changed files with 48 additions and 37 deletions

View file

@ -51,7 +51,7 @@ user:
### user_list() ### user_list()
list: list:
action_help: List users action_help: List users
api: GET /user/list api: GET /users
arguments: arguments:
--fields: --fields:
help: fields to fetch help: fields to fetch
@ -69,7 +69,7 @@ user:
### user_create() ### user_create()
create: create:
action_help: Create user action_help: Create user
api: POST /user api: POST /users
arguments: arguments:
-u: -u:
full: --username full: --username
@ -95,7 +95,7 @@ user:
### user_delete() ### user_delete()
delete: delete:
action_help: Delete user action_help: Delete user
api: DELETE /user api: 'DELETE /users/(?P<users>[^/]+)'
arguments: arguments:
-u: -u:
full: --users full: --users
@ -109,7 +109,7 @@ user:
### user_update() ### user_update()
update: update:
action_help: Update user informations action_help: Update user informations
api: PUT /user api: 'PUT /users/(?P<username>[^/]+)'
arguments: arguments:
username: username:
help: Username of user to update help: Username of user to update
@ -143,9 +143,9 @@ user:
### user_info() ### user_info()
info: info:
action_help: Get user informations action_help: Get user informations
api: GET /user api: 'GET /users/(?P<username>[^/]+)'
arguments: arguments:
user-or-mail: username:
help: Username or mail to get informations help: Username or mail to get informations
@ -159,7 +159,7 @@ domain:
### domain_list() ### domain_list()
list: list:
action_help: List domains action_help: List domains
api: GET /domain/list api: GET /domains
arguments: arguments:
-f: -f:
full: --filter full: --filter
@ -174,7 +174,7 @@ domain:
### domain_add() ### domain_add()
add: add:
action_help: Create a custom domain action_help: Create a custom domain
api: POST /domain api: POST /domains
arguments: arguments:
domains: domains:
help: Domain name to add help: Domain name to add
@ -188,7 +188,7 @@ domain:
### domain_remove() ### domain_remove()
remove: remove:
action_help: Delete domains action_help: Delete domains
api: DELETE /domain api: 'DELETE /domains/(?P<domains>[^/]+)'
arguments: arguments:
domains: domains:
help: Domain(s) to delete help: Domain(s) to delete
@ -198,7 +198,7 @@ domain:
### domain_info() ### domain_info()
info: info:
action_help: Get domain informations action_help: Get domain informations
api: GET /domain api: 'GET /domains/(?P<domain>[^/]+)'
arguments: arguments:
domain: domain:
help: "" help: ""

View file

@ -21,7 +21,7 @@ gettext.install('YunoHost')
action_dict = {} action_dict = {}
api = APIResource() api = APIResource()
def http_exec(request): def http_exec(request, **kwargs):
global win global win
request.setHeader('Access-Control-Allow-Origin', '*') # Allow cross-domain requests request.setHeader('Access-Control-Allow-Origin', '*') # Allow cross-domain requests
@ -46,45 +46,56 @@ def http_exec(request):
request.setHeader('www-authenticate', 'Basic realm="Restricted Area"') request.setHeader('www-authenticate', 'Basic realm="Restricted Area"')
return 'Unauthorized' return 'Unauthorized'
path = request.path
given_args = request.args
if kwargs:
for k, v in kwargs.iteritems():
dynamic_key = path.split('/')[-1]
path = path.replace(dynamic_key, '(?P<'+ k +'>[^/]+)')
given_args[k] = [v]
print given_args
# Sanitize arguments # Sanitize arguments
dict = action_dict[request.method+' '+request.path] dict = action_dict[request.method +' '+ path]
if 'arguments' in dict: args = dict['arguments'] if 'arguments' in dict: possible_args = dict['arguments']
else: args = {} else: possible_args = {}
for arg, params in args.items(): for arg, params in possible_args.items():
sanitized_key = arg.replace('-', '_') sanitized_key = arg.replace('-', '_')
if sanitized_key is not arg: if sanitized_key is not arg:
args[sanitized_key] = args[arg] possible_args[sanitized_key] = possible_args[arg]
del args[arg] del possible_args[arg]
arg = sanitized_key arg = sanitized_key
if arg[0] == '_': if arg[0] == '_':
if 'nargs' not in params: if 'nargs' not in params:
args[arg]['nargs'] = '*' possible_args[arg]['nargs'] = '*'
if 'full' in params: if 'full' in params:
new_key = params['full'][2:] new_key = params['full'][2:]
else: else:
new_key = arg[2:] new_key = arg[2:]
args[new_key] = args[arg] possible_args[new_key] = possible_args[arg]
del args[arg] del possible_args[arg]
try: try:
# Validate arguments # Validate arguments
validated_args = {} validated_args = {}
for key, value in request.args.items(): for key, value in given_args.items():
if key in args: if key in possible_args:
# Validate args # Validate args
if 'pattern' in args[key]: if 'pattern' in possible_args[key]:
validate(args[key]['pattern'], value) validate(possible_args[key]['pattern'], value)
if 'nargs' not in args[key] or ('nargs' != '*' and 'nargs' != '+'): if 'nargs' not in possible_args[key] or ('nargs' != '*' and 'nargs' != '+'):
value = value[0] value = value[0]
if 'choices' in args[key] and value not in args[key]['choices']: if 'choices' in possible_args[key] and value not in possible_args[key]['choices']:
raise YunoHostError(22, _('Invalid argument') + ' ' + value) raise YunoHostError(22, _('Invalid argument') + ' ' + value)
if 'action' in args[key] and args[key]['action'] == 'store_true': if 'action' in possible_args[key] and possible_args[key]['action'] == 'store_true':
yes = ['true', 'True', 'yes', 'Yes'] yes = ['true', 'True', 'yes', 'Yes']
value = value in yes value = value in yes
validated_args[key] = value validated_args[key] = value
func = str_to_func(dict['function']) func = str_to_func(dict['function'])
if func is None:
raise YunoHostError(168, _('Function not yet implemented : ') + dict['function'].split('.')[1])
# Execute requested function # Execute requested function
with YunoHostLDAP(password=request.getPassword()): with YunoHostLDAP(password=request.getPassword()):
@ -106,13 +117,14 @@ def http_exec(request):
except YunoHostError, error: except YunoHostError, error:
# Set response code with function's raised code # Set response code with function's raised code
server_errors = [1, 111, 169] server_errors = [1, 111, 168, 169]
client_errors = [13, 17, 22, 87, 122, 125, 167, 168] client_errors = [13, 17, 22, 87, 122, 125, 167]
if error.code in client_errors: if error.code in client_errors:
request.setResponseCode(400, 'Bad Request') request.setResponseCode(400, 'Bad Request')
else: else:
request.setResponseCode(500, 'Internal Server Error') request.setResponseCode(500, 'Internal Server Error')
result = { 'error' : error.message }
result = { 'error' : error.message }
return json.dumps(result) return json.dumps(result)

View file

@ -269,13 +269,12 @@ def user_update(username, firstname=None, lastname=None, mail=None, change_passw
def user_info(user_or_mail): def user_info(username):
""" """
Fetch user informations from LDAP Fetch user informations from LDAP
Keyword argument: Keyword argument:
username username -- Username or mail to get info
mail
Returns: Returns:
Dict Dict
@ -283,17 +282,17 @@ def user_info(user_or_mail):
with YunoHostLDAP() as yldap: with YunoHostLDAP() as yldap:
user_attrs = ['cn', 'mail', 'uid', 'maildrop'] user_attrs = ['cn', 'mail', 'uid', 'maildrop']
if len(user_or_mail.split('@')) is 2: if len(username.split('@')) is 2:
filter = 'mail='+ user_or_mail filter = 'mail='+ username
else: else:
filter = 'uid='+ user_or_mail filter = 'uid='+ username
result = yldap.search('ou=users,dc=yunohost,dc=org', filter, user_attrs) result = yldap.search('ou=users,dc=yunohost,dc=org', filter, user_attrs)
if result: if result:
user = result[0] user = result[0]
else: else:
raise YunoHostError(22, _("Unknown user/mail")) raise YunoHostError(22, _("Unknown user/mail : ") + username)
result_dict = { result_dict = {
'Username': user['uid'][0], 'Username': user['uid'][0],