e4d54ef776aed0c88a012390cb135170e6be784e
[cascardo/ipsilon.git] / ipsilon / login / authfas.py
1 #!/usr/bin/python
2 #
3 # Copyright (C) 2014 Ipsilon contributors, see COPYING file for license
4
5
6 from ipsilon.login.common import LoginPageBase, LoginManagerBase
7 from ipsilon.login.common import FACILITY
8 from ipsilon.util.plugin import PluginObject
9 import cherrypy
10
11 from fedora.client.fasproxy import FasProxyClient
12 from fedora.client import AuthError
13
14
15 class FAS(LoginPageBase):
16
17     def GET(self, *args, **kwargs):
18         context = self.create_tmpl_context()
19         # pylint: disable=star-args
20         return self._template('login/fas.html', **context)
21
22     def POST(self, *args, **kwargs):
23         username = kwargs.get("login_name")
24         password = kwargs.get("login_password")
25         error = None
26
27         if username and password:
28             data = None
29             try:
30                 _, data = self.lm.fpc.login(username, password)
31             except AuthError, e:
32                 cherrypy.log.error("Authentication error [%s]" % str(e))
33             except Exception, e:  # pylint: disable=broad-except
34                 cherrypy.log.error("Unknown Error [%s]" % str(e))
35             if data and data.user:
36                 return self.lm.auth_successful(data.user['username'],
37                                                userdata={'fas': data.user})
38             else:
39                 error = "Authentication failed"
40                 cherrypy.log.error(error)
41         else:
42             error = "Username or password is missing"
43             cherrypy.log.error("Error: " + error)
44
45         context = self.create_tmpl_context(
46             username=username,
47             error=error,
48             error_password=not password,
49             error_username=not username
50         )
51         # pylint: disable=star-args
52         return self._template('login/fas.html', **context)
53
54     def root(self, *args, **kwargs):
55         op = getattr(self, cherrypy.request.method, self.GET)
56         if callable(op):
57             return op(*args, **kwargs)
58
59     def create_tmpl_context(self, **kwargs):
60         next_url = None
61         if self.lm.next_login is not None:
62             next_url = self.lm.next_login.path
63
64         context = {
65             "title": 'Login',
66             "action": '%s/login/fas' % self.basepath,
67             "service_name": self.lm.service_name,
68             "username_text": self.lm.username_text,
69             "password_text": self.lm.password_text,
70             "description": self.lm.help_text,
71             "next_url": next_url,
72         }
73         context.update(kwargs)
74         return context
75
76
77 class LoginManager(LoginManagerBase):
78
79     def __init__(self, *args, **kwargs):
80         super(LoginManager, self).__init__(*args, **kwargs)
81         self.name = 'fas'
82         self.path = 'fas'
83         self.page = None
84         self.fpc = None
85         self.description = """
86 Form based login Manager that uses the Fedora Authentication Server
87 """
88         self._options = {
89             'service name': [
90                 """ The name of the PAM service used to authenticate. """,
91                 'string',
92                 'remote'
93             ],
94             'help text': [
95                 """ The text shown to guide the user at login time. """,
96                 'string',
97                 'Login wth your FAS credentials'
98             ],
99             'username text': [
100                 """ The text shown to ask for the username in the form. """,
101                 'string',
102                 'FAS Username'
103             ],
104             'password text': [
105                 """ The text shown to ask for the password in the form. """,
106                 'string',
107                 'Password'
108             ],
109             'FAS url': [
110                 """ The FAS Url. """,
111                 'string',
112                 'https://admin.fedoraproject.org/accounts/'
113             ],
114             'FAS Proxy client user Agent': [
115                 """ The User Agent presented to the FAS Server. """,
116                 'string',
117                 'Ipsilon v1.0'
118             ],
119             'FAS Insecure Auth': [
120                 """ If 'YES' skips FAS server cert verification. """,
121                 'string',
122                 ''
123             ],
124         }
125
126     @property
127     def service_name(self):
128         return self.get_config_value('service name')
129
130     @property
131     def help_text(self):
132         return self.get_config_value('help text')
133
134     @property
135     def username_text(self):
136         return self.get_config_value('username text')
137
138     @property
139     def password_text(self):
140         return self.get_config_value('password text')
141
142     @property
143     def fas_url(self):
144         return self.get_config_value('FAS url')
145
146     @property
147     def user_agent(self):
148         return self.get_config_value('FAS Proxy client user Agent')
149
150     @property
151     def insecure(self):
152         return self.get_config_value('FAS Insecure Auth')
153
154     def get_tree(self, site):
155         self.fpc = FasProxyClient(base_url=self.fas_url,
156                                   useragent=self.user_agent,
157                                   insecure=(self.insecure == 'YES'))
158         self.page = FAS(site, self)
159         return self.page
160
161
162 class Installer(object):
163
164     def __init__(self):
165         self.name = 'fas'
166         self.ptype = 'login'
167
168     def install_args(self, group):
169         group.add_argument('--fas', choices=['yes', 'no'], default='no',
170                            help='Configure FAS authentication')
171
172     def configure(self, opts):
173         if opts['fas'] != 'yes':
174             return
175
176         # Add configuration data to database
177         po = PluginObject()
178         po.name = 'fas'
179         po.wipe_data()
180
181         po.wipe_config_values(FACILITY)
182
183         # Update global config to add login plugin
184         po = PluginObject()
185         po.name = 'global'
186         globalconf = po.get_plugin_config(FACILITY)
187         if 'order' in globalconf:
188             order = globalconf['order'].split(',')
189         else:
190             order = []
191         order.append('fas')
192         globalconf['order'] = ','.join(order)
193         po.set_config(globalconf)
194         po.save_plugin_config(FACILITY)