moulinette/yunohost.tac
2013-06-28 23:05:28 +00:00

155 lines
5.2 KiB
Python
Executable file

# -*- mode: python -*-
import os
import sys
import gettext
import ldap
import yaml
import json
from twisted.python import log
from twisted.web.server import Site
from twisted.web.resource import IResource
from twisted.web.guard import HTTPAuthSessionWrapper, BasicCredentialFactory
from twisted.internet import reactor, defer
from twisted.cred.portal import IRealm, Portal
from twisted.cred.checkers import ICredentialsChecker
from twisted.cred.credentials import IUsernamePassword
from twisted.cred.error import UnauthorizedLogin
from zope.interface import implements
from txrestapi.resource import APIResource
from yunohost import YunoHostError, YunoHostLDAP, str_to_func, colorize, pretty_print_dict, display_error, validate, win, parse_dict
if not __debug__:
import traceback
gettext.install('YunoHost')
class LDAPHTTPAuth():
implements (ICredentialsChecker)
credentialInterfaces = IUsernamePassword,
def requestAvatarId(self, credentials):
try:
if credentials.username != "admin":
raise YunoHostError(22, _("Invalid username") + ': ' + credentials.username)
YunoHostLDAP(password=credentials.password)
return credentials.username
except Exception as e:
return defer.fail(UnauthorizedLogin())
class SimpleRealm(object):
implements(IRealm)
_api = None
def __init__(self, api):
self._api = api
def requestAvatar(self, avatarId, mind, *interfaces):
if IResource in interfaces:
return IResource, self._api, lambda: None
raise NotImplementedError()
action_dict = {}
def http_exec(request):
global win
dict = action_dict[request.method+' '+request.path]
if 'arguments' in dict: args = dict['arguments']
else: args = {}
for arg, params in args.items():
sanitized_key = arg.replace('-', '_')
if sanitized_key is not arg:
args[sanitized_key] = args[arg]
del args[arg]
arg = sanitized_key
if arg[0] == '_':
if 'nargs' not in params:
args[arg]['nargs'] = '*'
if 'full' in params:
new_key = params['full'][2:]
else:
new_key = arg[2:]
args[new_key] = args[arg]
del args[arg]
try:
validated_args = {}
for key, value in request.args.items():
if key in args:
# Validate args
if 'pattern' in args[key]: validate(args[key]['pattern'], value)
if 'nargs' not in args[key] or ('nargs' != '*' and 'nargs' != '+'): value = value[0]
if 'action' in args[key] and args[key]['action'] == 'store_true':
yes = ['true', 'True', 'yes', 'Yes']
value = value in yes
validated_args[key] = value
func = str_to_func(dict['function'])
with YunoHostLDAP(password=request.getPassword()):
result = func(**validated_args)
if result is None:
result = {}
if win:
result['win'] = win
win = []
if request.method == 'POST':
request.setResponseCode(201, 'Created')
elif request.method == 'DELETE':
request.setResponseCode(204, 'No Content')
else:
request.setResponseCode(200, 'OK')
except YunoHostError, error:
server_errors = [1, 111, 169]
client_errors = [13, 17, 22, 87, 122, 125, 167, 168]
if error.code in client_errors:
request.setResponseCode(400, 'Bad Request')
else:
request.setResponseCode(500, 'Internal Server Error')
result = { 'error' : error.message }
request.setHeader('Content-Type', 'application/json')
return json.dumps(result)
def main():
global action_dict
log.startLogging(sys.stdout)
api = APIResource()
with open('action_map.yml') as f:
action_map = yaml.load(f)
del action_map['general_arguments']
for category, category_params in action_map.items():
for action, action_params in category_params['actions'].items():
if 'help' not in action_params:
action_params['help'] = ''
if 'api' not in action_params:
action_params['api'] = 'GET /'+ category +'/'+ action
method, path = action_params['api'].split(' ')
api.register(method, path, http_exec)
action_dict[action_params['api']] = {
'function': 'yunohost_'+ category +'.'+ category +'_'+ action,
'help' : action_params['help']
}
if 'arguments' in action_params:
action_dict[action_params['api']]['arguments'] = action_params['arguments']
ldap_auth = LDAPHTTPAuth()
credentialFactory = BasicCredentialFactory("Restricted Area")
resource = HTTPAuthSessionWrapper(Portal(SimpleRealm(api), [ldap_auth]), [credentialFactory])
try:
with open('/etc/yunohost/installed') as f: pass
except IOError:
resource = APIResource()
resource.register('POST', '/postinstall', http_exec)
reactor.listenTCP(6767, Site(resource, timeout=None))
reactor.run()
if __name__ == '__main__':
main()