Project

General

Profile

Download (3.65 KB) Statistics
| Branch: | Tag: | Revision:

organization_api / ckanext / ozwillo_organization_api / plugin.py @ cb821f25

1 5c8cfd17 Serghei MIHAI
from hashlib import sha1
2
import hmac
3
4
import ckan.plugins as plugins
5 cb821f25 Serghei MIHAI
import ckan.plugins.toolkit as toolkit
6
7 5c8cfd17 Serghei MIHAI
import ckan.logic as logic
8
9
from pylons import config
10
from ckan.common import request, _
11
from ckan.logic.action.create import _group_or_org_create as group_or_org_create
12
13 cb821f25 Serghei MIHAI
plugin_config_prefix = 'ckanext.ozwillo_organization_api.'
14
15 5c8cfd17 Serghei MIHAI
def valid_signature_required(func):
16 cb821f25 Serghei MIHAI
17 5c8cfd17 Serghei MIHAI
    signature_header_name = config.get(plugin_config_prefix + 'signature_header_name',
18
                                       'X-Hub-Signature')
19
    instantiated_secret = config.get(plugin_config_prefix + 'instantiated_secret',
20
                                     'secret')
21
22
    def wrapper(context, data):
23
        if signature_header_name in request.headers:
24
            if request.headers[signature_header_name].startswith('sha1='):
25 cb821f25 Serghei MIHAI
                algo, received_hmac = request.headers[signature_header_name].rsplit('=')
26
                computed_hmac = hmac.new(instantiated_secret, str(data), sha1).hexdigest()
27
                # the received hmac is uppercase according to
28
                # http://doc.ozwillo.com/#ref-3-2-1
29
                if received_hmac != computed_hmac.upper():
30 5c8cfd17 Serghei MIHAI
                    raise logic.NotAuthorized(_('Invalid HMAC'))
31
            else:
32
                raise logic.ValidationError(_('Invalid HMAC algo'))
33
        else:
34
            raise logic.NotAuthorized(_("No HMAC in the header"))
35
        return func(context, data)
36
    return wrapper
37
38
@valid_signature_required
39
def create_organization(context, data_dict):
40 cb821f25 Serghei MIHAI
41
    destruction_secret = config.get(plugin_config_prefix + 'destruction_secret',
42
                                       'changeme')
43
44
    client_id = data_dict.pop('client_id')
45
    client_secret = data_dict.pop('client_secret')
46
    instance_id = data_dict.pop('instance_id')
47
48
    # re-mapping received dict
49
    registration_uri = data_dict.pop('instance_registration_uri')
50
    organization = data_dict['organization']
51
    org_dict = {
52
        'type': 'organization',
53
        'name': organization['organization_name'].lower(),
54
        'id': organization['id'],
55
        'title': organization['organization_name'],
56
        'description': organization['type'],
57
    }
58
    try:
59
        delete_uri = toolkit.url_for(controller='api', action='action',
60
                                     logic_function="delete-organization",
61
                                     ver=context['api_version'],
62
                                     qualified=True)
63
64
        group_or_org_create(context, org_dict, is_org=True)
65
66
        # notify about organization creation
67
        services = {'services': [{
68
            'local_id': 'organization',
69
            'name': 'Organization ' + org_dict['name'] + ' on CKAN',
70
            'service_uri': '/organization/' + org_dict['name'],
71
            'visible': True}],
72
            'instance_id': instance_id,
73
            'destruction_uri': delete_uri,
74
            'destruction_secret': destruction_secret,
75
            'needed_scopes': [{
76
                'scope_id': 'profile',
77
                'motivation': 'Used to link user to the organization'
78
            }]
79
        }
80
        requests.post(registration_uri,
81
                      data = services,
82
                      auth=(client_id, client_secret)
83
                  )
84
    except:
85
        request.delete(registration_uri)
86
87 5c8cfd17 Serghei MIHAI
88
@valid_signature_required
89
def delete_organization(context, data_dict):
90
    pass
91
92
93
class OzwilloOrganizationApiPlugin(plugins.SingletonPlugin):
94
    """
95
    API for OASIS to create and delete an organization
96
    """
97
    plugins.implements(plugins.IActions)
98
99
    def get_actions(self):
100
        return {
101
            'create-organization': create_organization,
102
            'delete-organization': delete_organization
103
        }