30e09f5e4fd8c4d8471101a3267c087199cd796c
[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             "username_text": self.lm.username_text,
68             "password_text": self.lm.password_text,
69             "description": self.lm.help_text,
70             "next_url": next_url,
71         }
72         context.update(kwargs)
73         return context
74
75
76 class LoginManager(LoginManagerBase):
77
78     def __init__(self, *args, **kwargs):
79         super(LoginManager, self).__init__(*args, **kwargs)
80         self.name = 'fas'
81         self.path = 'fas'
82         self.page = None
83         self.fpc = None
84         self.description = """
85 Form based login Manager that uses the Fedora Authentication Server
86 """
87         self._options = {
88             'help text': [
89                 """ The text shown to guide the user at login time. """,
90                 'string',
91                 'Login wth your FAS credentials'
92             ],
93             'username text': [
94                 """ The text shown to ask for the username in the form. """,
95                 'string',
96                 'FAS Username'
97             ],
98             'password text': [
99                 """ The text shown to ask for the password in the form. """,
100                 'string',
101                 'Password'
102             ],
103             'FAS url': [
104                 """ The FAS Url. """,
105                 'string',
106                 'https://admin.fedoraproject.org/accounts/'
107             ],
108             'FAS Proxy client user Agent': [
109                 """ The User Agent presented to the FAS Server. """,
110                 'string',
111                 'Ipsilon v1.0'
112             ],
113             'FAS Insecure Auth': [
114                 """ If 'YES' skips FAS server cert verification. """,
115                 'string',
116                 ''
117             ],
118         }
119
120     @property
121     def help_text(self):
122         return self.get_config_value('help text')
123
124     @property
125     def username_text(self):
126         return self.get_config_value('username text')
127
128     @property
129     def password_text(self):
130         return self.get_config_value('password text')
131
132     @property
133     def fas_url(self):
134         return self.get_config_value('FAS url')
135
136     @property
137     def user_agent(self):
138         return self.get_config_value('FAS Proxy client user Agent')
139
140     @property
141     def insecure(self):
142         return self.get_config_value('FAS Insecure Auth')
143
144     def get_tree(self, site):
145         self.fpc = FasProxyClient(base_url=self.fas_url,
146                                   useragent=self.user_agent,
147                                   insecure=(self.insecure == 'YES'))
148         self.page = FAS(site, self)
149         return self.page
150
151
152 class Installer(object):
153
154     def __init__(self):
155         self.name = 'fas'
156         self.ptype = 'login'
157
158     def install_args(self, group):
159         group.add_argument('--fas', choices=['yes', 'no'], default='no',
160                            help='Configure FAS authentication')
161
162     def configure(self, opts):
163         if opts['fas'] != 'yes':
164             return
165
166         # Add configuration data to database
167         po = PluginObject()
168         po.name = 'fas'
169         po.wipe_data()
170
171         po.wipe_config_values(FACILITY)
172
173         # Update global config to add login plugin
174         po = PluginObject()
175         po.name = 'global'
176         globalconf = po.get_plugin_config(FACILITY)
177         if 'order' in globalconf:
178             order = globalconf['order'].split(',')
179         else:
180             order = []
181         order.append('fas')
182         globalconf['order'] = ','.join(order)
183         po.set_config(globalconf)
184         po.save_plugin_config(FACILITY)