Project

General

Profile

0003-wf-roles-handle-case-when-user-attributes-are-manage.patch

Benjamin Dauvergne, 04 February 2016 04:11 PM

Download (5.09 KB)

View differences:

Subject: [PATCH 3/4] wf/roles: handle case when user attributes are managed by
 the idp (#9210)

If the user's attributes are managed by an idp, we add/remove roles by calling
the idp role management web-services. It only works with authentic2.
 wcs/wf/roles.py | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 82 insertions(+), 2 deletions(-)
wcs/wf/roles.py
14 14
# You should have received a copy of the GNU General Public License
15 15
# along with this program; if not, see <http://www.gnu.org/licenses/>.
16 16

  
17
from quixote import get_request, get_publisher
17
import urlparse
18
import urllib
19
import sys
20

  
21
from quixote import get_request, get_publisher, get_response
18 22
from qommon.form import *
19 23
from wcs.workflows import WorkflowStatusItem, register_item_class
20
from wcs.roles import get_user_roles
24
from wcs.roles import get_user_roles, Role
25
from qommon.ident.idp import is_idp_managing_user_attributes
26
from qommon.misc import http_post_request, http_delete_request
27
from qommon.publisher import get_cfg, get_logger
28
from wcs.api import sign_url
29

  
30

  
31
class MissingSecret(Exception):
32
    pass
33

  
34

  
35
def get_secret(url):
36
    domain = urlparse.urlparse(url).netloc.split(':')[0]
37
    secret = get_publisher().get_site_option(domain, 'wscall-secrets')
38
    if not secret:
39
        raise MissingSecret()
40
    return secret
41

  
42

  
43
def roles_ws_url(role_uuid, user_uuid):
44
    idps = get_cfg('idp', {})
45
    entity_id = idps.values()[0]['metadata_url']
46
    base_url = entity_id.split('idp/saml2/metadata')[0]
47
    url = urlparse.urljoin(base_url, '/api/roles/%s/members/%s/' % (urllib.quote(role_uuid),
48
                                                                     urllib.quote(user_uuid)))
49
    secret = get_secret(url)
50
    orig = get_request().get_server().split(':')[0]
51
    url += '?orig=%s' % orig
52
    return sign_url(url, secret)
53

  
21 54

  
22 55
class AddRoleWorkflowStatusItem(WorkflowStatusItem):
23 56
    description = N_('Add Role to User')
......
50 83
            # we can't work on anonymous or user_hash'ed forms
51 84
            return
52 85
        user = get_publisher().user_class.get(formdata.user_id)
86
        self.perform_local(user, formdata)
87
        if user.name_identifiers and is_idp_managing_user_attributes():
88
            self.perform_idp(user, formdata)
89

  
90
    def perform_local(self, user, formdata):
53 91
        if not user.roles:
54 92
            user.roles = []
55 93
        if not self.role_id in user.roles:
......
60 98
            # changes.
61 99
            get_request().user = user
62 100

  
101
    def perform_idp(self, user, formdata):
102
        role = Role.get(self.role_id)
103
        role_uuid = role.slug
104
        user_uuid = user.name_identifiers[0]
105
        try:
106
            url = roles_ws_url(role_uuid, user_uuid)
107
        except MissingSecret:
108
            get_publisher().notify_of_exception(sys.exc_info(), context='[ROLES]')
109
            return
110
        def after_job(job):
111
            response, status, data, auth_header = http_post_request(url)
112
            if status != 201:
113
                get_logger().error('failed to add role %r to user %r',
114
                                   role, user)
115
        get_response().add_after_job(
116
            str(N_('Adding role')),
117
            after_job)
118

  
119

  
63 120
register_item_class(AddRoleWorkflowStatusItem)
64 121

  
65 122

  
......
86 143
            # we can't work on anonymous or user_hash'ed forms
87 144
            return
88 145
        user = get_publisher().user_class.get(formdata.user_id)
146
        self.perform_local(user, formdata)
147
        if user.name_identifiers and is_idp_managing_user_attributes():
148
            self.perform_idp(user, formdata)
149

  
150
    def perform_local(self, user, formdata):
89 151
        if user.roles and self.role_id in user.roles:
90 152
            user.roles.remove(self.role_id)
91 153
            user.store()
......
94 156
                # with the changes.
95 157
                get_request().user = user
96 158

  
159
    def perform_idp(self, user, formdata):
160
        role = Role.get(self.role_id)
161
        role_uuid = role.slug
162
        user_uuid = user.name_identifiers[0]
163
        try:
164
            url = roles_ws_url(role_uuid, user_uuid)
165
        except MissingSecret:
166
            get_publisher().notify_of_exception(sys.exc_info(), context='[ROLES]')
167
            return
168
        def after_job(job):
169
            response, status, data, auth_header = http_delete_request(url)
170
            if status != 200:
171
                get_logger().error('failed to remove role %r from user %r',
172
                                   role, user)
173
        get_response().add_after_job(
174
            str(N_('Removing role')),
175
            after_job)
176

  
97 177
register_item_class(RemoveRoleWorkflowStatusItem)
98
-