3 # Copyright (C) 2014 Ipsilon contributors, see COPYING file for license
6 from ipsilon.info.common import InfoMapping
7 from ipsilon.login.common import LoginFormBase, LoginManagerBase
8 from ipsilon.login.common import FACILITY
9 from ipsilon.util.plugin import PluginObject
12 from fedora.client.fasproxy import FasProxyClient
13 from fedora.client import AuthError
17 import openid_cla.cla as cla
20 'cla_click': cla.CLA_URI_FEDORA_CLICK,
21 'cla_dell': cla.CLA_URI_FEDORA_DELL,
22 'cla_done': cla.CLA_URI_FEDORA_DONE,
23 'cla_fedora': cla.CLA_URI_FEDORA_FEDORA,
24 'cla_fpca': cla.CLA_URI_FEDORA_FPCA,
25 'cla_ibm': cla.CLA_URI_FEDORA_IBM,
26 'cla_intel': cla.CLA_URI_FEDORA_INTEL,
27 'cla_redhat': cla.CLA_URI_FEDORA_REDHAT,
33 'username': 'nickname',
35 'country_code': 'country',
36 'human_name': 'fullname',
38 'timezone': 'timezone',
42 class FAS(LoginFormBase):
44 def __init__(self, site, mgr, page):
45 super(FAS, self).__init__(site, mgr, page)
46 self.mapper = InfoMapping()
47 self.mapper.set_mapping(fas_mapping)
49 def POST(self, *args, **kwargs):
50 username = kwargs.get("login_name")
51 password = kwargs.get("login_password")
54 if username and password:
57 _, data = self.lm.fpc.login(username, password)
59 cherrypy.log.error("Authentication error [%s]" % str(e))
60 except Exception, e: # pylint: disable=broad-except
61 cherrypy.log.error("Unknown Error [%s]" % str(e))
62 if data and data.user:
63 userdata = self.make_userdata(data.user)
64 return self.lm.auth_successful(self.trans,
65 data.user['username'],
68 error = "Authentication failed"
69 cherrypy.log.error(error)
71 error = "Username or password is missing"
72 cherrypy.log.error("Error: " + error)
74 context = self.create_tmpl_context(
77 error_password=not password,
78 error_username=not username
80 # pylint: disable=star-args
81 return self._template(self.formtemplate, **context)
83 def make_userdata(self, fas_data):
84 userdata, fas_extra = self.mapper.map_attrs(fas_data)
86 # compute and store groups and cla groups
87 userdata['groups'] = []
88 userdata['extras'] = {'fas': fas_extra, 'cla': []}
89 for group in fas_data.get('approved_memberships', {}):
90 if 'name' not in group:
92 if group.get('group_type') == 'cla':
93 if group['name'] in CLA_GROUPS:
94 userdata['extras']['cla'].append(CLA_GROUPS[group['name']])
96 userdata['extras']['cla'].append(group['name'])
98 userdata['groups'].append(group['name'])
103 class LoginManager(LoginManagerBase):
105 def __init__(self, *args, **kwargs):
106 super(LoginManager, self).__init__(*args, **kwargs)
109 self.service_name = 'fas'
112 self.description = """
113 Form based login Manager that uses the Fedora Authentication Server
117 """ The text shown to guide the user at login time. """,
119 'Login wth your FAS credentials'
122 """ The text shown to ask for the username in the form. """,
127 """ The text shown to ask for the password in the form. """,
132 """ The FAS Url. """,
134 'https://admin.fedoraproject.org/accounts/'
136 'FAS Proxy client user Agent': [
137 """ The User Agent presented to the FAS Server. """,
141 'FAS Insecure Auth': [
142 """ If 'YES' skips FAS server cert verification. """,
147 self.conf_opt_order = ['FAS url', 'FAS Proxy client user Agent',
148 'FAS Insecure Auth', 'username text',
149 'password text', 'help text']
153 return self.get_config_value('help text')
156 def username_text(self):
157 return self.get_config_value('username text')
160 def password_text(self):
161 return self.get_config_value('password text')
165 return self.get_config_value('FAS url')
168 def user_agent(self):
169 return self.get_config_value('FAS Proxy client user Agent')
173 return self.get_config_value('FAS Insecure Auth')
175 def get_tree(self, site):
176 self.fpc = FasProxyClient(base_url=self.fas_url,
177 useragent=self.user_agent,
178 insecure=(self.insecure == 'YES'))
179 self.page = FAS(site, self, 'login/fas')
183 class Installer(object):
189 def install_args(self, group):
190 group.add_argument('--fas', choices=['yes', 'no'], default='no',
191 help='Configure FAS authentication')
193 def configure(self, opts):
194 if opts['fas'] != 'yes':
197 # Add configuration data to database
202 po.wipe_config_values(FACILITY)
204 # Update global config to add login plugin
207 globalconf = po.get_plugin_config(FACILITY)
208 if 'order' in globalconf:
209 order = globalconf['order'].split(',')
213 globalconf['order'] = ','.join(order)
214 po.set_config(globalconf)
215 po.save_plugin_config(FACILITY)