pam: use a pam object method instead of pam module function
[cascardo/ipsilon.git] / ipsilon / providers / saml2 / admin.py
index 931d096..c7a0289 100644 (file)
@@ -1,19 +1,4 @@
-# Copyright (C) 2014  Simo Sorce <simo@redhat.com>
-#
-# see file 'COPYING' for use and warranty information
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+# Copyright (C) 2014 Ipsilon project Contributors, for license see COPYING
 
 import cherrypy
 from ipsilon.util import config as pconfig
@@ -28,6 +13,9 @@ from ipsilon.providers.saml2.provider import ServiceProviderCreator
 from ipsilon.providers.saml2.provider import InvalidProviderId
 from copy import deepcopy
 import requests
+import logging
+import base64
+from urlparse import urlparse
 
 
 class NewSPAdminPage(AdminPage):
@@ -57,6 +45,10 @@ class NewSPAdminPage(AdminPage):
             #       set the owner in that case
             name = None
             meta = None
+            description = None
+            splink = None
+            visible = False
+            imagefile = None
             if 'content-type' not in cherrypy.request.headers:
                 self.debug("Invalid request, missing content-type")
                 message = "Malformed request"
@@ -69,6 +61,30 @@ class NewSPAdminPage(AdminPage):
             for key, value in kwargs.iteritems():
                 if key == 'name':
                     name = value
+                elif key == 'description':
+                    description = value
+                elif key == 'splink':
+                    # pylint: disable=unused-variable
+                    (scheme, netloc, path, params, query, frag) = urlparse(
+                        value
+                    )
+                    # minimum URL validation
+                    if (scheme not in ['http', 'https'] or not netloc):
+                        message = "Invalid URL for Service Provider link"
+                        message_type = ADMIN_STATUS_ERROR
+                        return self.form_new(message, message_type)
+                    splink = value
+                elif key == 'portalvisible' and value.lower() == 'on':
+                    visible = True
+                elif key == 'imagefile':
+                    if hasattr(value, 'content_type'):
+                        imagefile = value.fullvalue()
+                        if len(imagefile) == 0:
+                            imagefile = None
+                        else:
+                            imagefile = base64.b64encode(imagefile)
+                    else:
+                        self.debug("Invalid format for 'imagefile'")
                 elif key == 'metatext':
                     if len(value) > 0:
                         meta = value
@@ -92,7 +108,8 @@ class NewSPAdminPage(AdminPage):
             if name and meta:
                 try:
                     spc = ServiceProviderCreator(self.parent.cfg)
-                    sp = spc.create_from_buffer(name, meta)
+                    sp = spc.create_from_buffer(name, meta, description,
+                                                visible, imagefile, splink)
                     sp_page = self.parent.add_sp(name, sp)
                     message = "SP Successfully added"
                     message_type = ADMIN_STATUS_OK
@@ -156,6 +173,9 @@ class SPAdminPage(AdminPage):
                 value = kwargs[name]
                 if isinstance(option, pconfig.List):
                     value = [x.strip() for x in value.split('\n')]
+                    # for normal lists we want unordered comparison
+                    if set(value) == set(option.get_value()):
+                        continue
                 elif isinstance(option, pconfig.Condition):
                     value = True
             else:
@@ -167,9 +187,9 @@ class SPAdminPage(AdminPage):
                         aname = '%s_%s' % (name, a)
                         if aname in kwargs:
                             value.append(a)
-                elif type(option) is pconfig.ComplexList:
+                elif isinstance(option, pconfig.MappingList):
                     current = deepcopy(option.get_value())
-                    value = get_complex_list_value(name,
+                    value = get_mapping_list_value(name,
                                                    current,
                                                    **kwargs)
                     # if current value is None do nothing
@@ -177,9 +197,9 @@ class SPAdminPage(AdminPage):
                         if option.get_value() is None:
                             continue
                         # else pass and let it continue as None
-                elif type(option) is pconfig.MappingList:
+                elif isinstance(option, pconfig.ComplexList):
                     current = deepcopy(option.get_value())
-                    value = get_mapping_list_value(name,
+                    value = get_complex_list_value(name,
                                                    current,
                                                    **kwargs)
                     # if current value is None do nothing
@@ -191,11 +211,8 @@ class SPAdminPage(AdminPage):
                     continue
 
             if value != option.get_value():
-                if (type(option) is pconfig.List and
-                        set(value) == set(option.get_value())):
-                    continue
                 cherrypy.log.error("Storing %s = %s" %
-                                   (name, value))
+                                   (name, value), severity=logging.DEBUG)
                 new_db_values[name] = value
 
         if len(new_db_values) != 0:
@@ -206,8 +223,11 @@ class SPAdminPage(AdminPage):
                         if (not self.user.is_admin and
                                 self.user.name != self.sp.owner):
                             raise UnauthorizedUser("Unauthorized to set owner")
-                    elif key in ['Owner', 'Default NameID', 'Allowed NameIDs',
-                                 'Attribute Mapping', 'Allowed Attributes']:
+                    elif key in ['User Owner', 'Default NameID',
+                                 'Allowed NameIDs', 'Attribute Mapping',
+                                 'Allowed Attributes', 'Description',
+                                 'Service Provider link',
+                                 'Visible in Portal', 'Image File']:
                         if not self.user.is_admin:
                             raise UnauthorizedUser(
                                 "Unauthorized to set %s" % key
@@ -215,9 +235,12 @@ class SPAdminPage(AdminPage):
 
                 # Make changes in current config
                 for name, option in conf.iteritems():
+                    if name not in new_db_values:
+                        continue
                     value = new_db_values.get(name, False)
                     # A value of None means remove from the data store
-                    if value is False or value == []:
+                    if ((value is False or value == []) and
+                            name != 'Visible in Portal'):
                         continue
                     if name == 'Name':
                         if not self.sp.is_valid_name(value):
@@ -230,6 +253,12 @@ class SPAdminPage(AdminPage):
                         self.parent.rename_sp(option.get_value(), value)
                     elif name == 'User Owner':
                         self.sp.owner = value
+                    elif name == 'Description':
+                        self.sp.description = value
+                    elif name == 'Visible in Portal':
+                        self.sp.visible = value
+                    elif name == 'Service Provider link':
+                        self.sp.splink = value
                     elif name == 'Default NameID':
                         self.sp.default_nameid = value
                     elif name == 'Allowed NameIDs':
@@ -238,6 +267,17 @@ class SPAdminPage(AdminPage):
                         self.sp.attribute_mappings = value
                     elif name == 'Allowed Attributes':
                         self.sp.allowed_attributes = value
+                    elif name == 'Image File':
+                        if hasattr(value, 'content_type'):
+                            # pylint: disable=maybe-no-member
+                            blob = value.fullvalue()
+                            if len(blob) > 0:
+                                self.sp.imagefile = base64.b64encode(blob)
+                        else:
+                            raise InvalidValueFormat(
+                                'Invalid Image file format'
+                            )
+
             except InvalidValueFormat, e:
                 message = str(e)
                 message_type = ADMIN_STATUS_WARN
@@ -267,6 +307,9 @@ class SPAdminPage(AdminPage):
                                   message_type=message_type)
 
     def delete(self):
+        if (not self.user.is_admin and
+                self.user.name != self.sp.owner):
+            raise cherrypy.HTTPError(403)
         self.parent.del_sp(self.sp.name)
         self.sp.permanently_delete()
         return self.parent.root()