Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

# 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 version 3 for 

# more details. 

# 

# You should have received a copy of the GNU General Public License version 3 

# along with this program; if not, write to the Free Software Foundation, Inc., 51 

# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 

# 

# (c) 2015-2016 Valentin Samir 

"""forms for the app""" 

from .default_settings import settings 

 

from django import forms 

from django.forms import widgets 

from django.utils.translation import ugettext_lazy as _ 

 

import cas_server.utils as utils 

import cas_server.models as models 

 

 

class BootsrapForm(forms.Form): 

""" 

Bases: :class:`django.forms.Form` 

 

Form base class to use boostrap then rendering the form fields 

""" 

def __init__(self, *args, **kwargs): 

super(BootsrapForm, self).__init__(*args, **kwargs) 

for field in self.fields.values(): 

# Only tweak the field if it will be displayed 

if not isinstance(field.widget, widgets.HiddenInput): 

attrs = {} 

if ( 

isinstance(field.widget, (widgets.Input, widgets.Select, widgets.Textarea)) and 

not isinstance(field.widget, (widgets.CheckboxInput,)) 

): 

attrs['class'] = "form-control" 

if isinstance(field.widget, (widgets.Input, widgets.Textarea)) and field.label: 

attrs["placeholder"] = field.label 

if field.required: 

attrs["required"] = "required" 

field.widget.attrs.update(attrs) 

 

 

class BaseLogin(BootsrapForm): 

""" 

Bases: :class:`BootsrapForm` 

 

Base form with all field possibly hidden on the login pages 

""" 

#: The service url for which the user want a ticket 

service = forms.CharField(widget=forms.HiddenInput(), required=False) 

#: A valid LoginTicket to prevent POST replay 

lt = forms.CharField(widget=forms.HiddenInput(), required=False) 

#: Is the service asking the authentication renewal ? 

renew = forms.BooleanField(widget=forms.HiddenInput(), required=False) 

#: Url to redirect to if the authentication fail (user not authenticated or bad service) 

gateway = forms.CharField(widget=forms.HiddenInput(), required=False) 

method = forms.CharField(widget=forms.HiddenInput(), required=False) 

 

 

class WarnForm(BaseLogin): 

""" 

Bases: :class:`BaseLogin` 

 

Form used on warn page before emiting a ticket 

""" 

#: ``True`` if the user has been warned of the ticket emission 

warned = forms.BooleanField(widget=forms.HiddenInput(), required=False) 

 

 

class FederateSelect(BaseLogin): 

""" 

Bases: :class:`BaseLogin` 

 

Form used on the login page when ``settings.CAS_FEDERATE`` is ``True`` 

allowing the user to choose an identity provider. 

""" 

#: The providers the user can choose to be used as authentication backend 

provider = forms.ModelChoiceField( 

queryset=models.FederatedIendityProvider.objects.filter(display=True).order_by( 

"pos", 

"verbose_name", 

"suffix" 

), 

to_field_name="suffix", 

label=_('Identity provider'), 

) 

#: A checkbox to ask to be warn before emiting a ticket for another service 

warn = forms.BooleanField( 

label=_('Warn me before logging me into other sites.'), 

required=False 

) 

#: A checkbox to remember the user choices of :attr:`provider<FederateSelect.provider>` 

remember = forms.BooleanField(label=_('Remember the identity provider'), required=False) 

 

 

class UserCredential(BaseLogin): 

""" 

Bases: :class:`BaseLogin` 

 

Form used on the login page to retrive user credentials 

""" 

#: The user username 

username = forms.CharField( 

label=_('username'), 

widget=forms.TextInput(attrs={'autofocus': 'autofocus'}) 

) 

#: The user password 

password = forms.CharField(label=_('password'), widget=forms.PasswordInput) 

#: A checkbox to ask to be warn before emiting a ticket for another service 

warn = forms.BooleanField( 

label=_('Warn me before logging me into other sites.'), 

required=False 

) 

 

def clean(self): 

""" 

Validate that the submited :attr:`username` and :attr:`password` are valid 

 

:raises django.forms.ValidationError: if the :attr:`username` and :attr:`password` 

are not valid. 

:return: The cleaned POST data 

:rtype: dict 

""" 

cleaned_data = super(UserCredential, self).clean() 

if "username" in cleaned_data and "password" in cleaned_data: 

auth = utils.import_attr(settings.CAS_AUTH_CLASS)(cleaned_data["username"]) 

if auth.test_password(cleaned_data["password"]): 

cleaned_data["username"] = auth.username 

else: 

raise forms.ValidationError( 

_(u"The credentials you provided cannot be determined to be authentic.") 

) 

return cleaned_data 

 

 

class FederateUserCredential(UserCredential): 

""" 

Bases: :class:`UserCredential` 

 

Form used on a auto submited page for linking the views 

:class:`FederateAuth<cas_server.views.FederateAuth>` and 

:class:`LoginView<cas_server.views.LoginView>`. 

 

On successful authentication on a provider, in the view 

:class:`FederateAuth<cas_server.views.FederateAuth>` a 

:class:`FederatedUser<cas_server.models.FederatedUser>` is created by 

:meth:`cas_server.federate.CASFederateValidateUser.verify_ticket` and the user is redirected 

to :class:`LoginView<cas_server.views.LoginView>`. This form is then automatically filled 

with infos matching the created :class:`FederatedUser<cas_server.models.FederatedUser>` 

using the ``ticket`` as one time password and submited using javascript. If javascript is 

not enabled, a connect button is displayed. 

 

This stub authentication form, allow to implement the federated mode with very few 

modificatons to the :class:`LoginView<cas_server.views.LoginView>` view. 

""" 

 

def __init__(self, *args, **kwargs): 

super(FederateUserCredential, self).__init__(*args, **kwargs) 

# All fields are hidden and auto filled by the /login view logic 

for name, field in self.fields.items(): 

field.widget = forms.HiddenInput() 

self[name].display = False 

 

def clean(self): 

""" 

Validate that the submited :attr:`username` and :attr:`password` are valid using 

the :class:`CASFederateAuth<cas_server.auth.CASFederateAuth>` auth class. 

 

:raises django.forms.ValidationError: if the :attr:`username` and :attr:`password` 

do not correspond to a :class:`FederatedUser<cas_server.models.FederatedUser>`. 

:return: The cleaned POST data 

:rtype: dict 

""" 

cleaned_data = super(FederateUserCredential, self).clean() 

try: 

user = models.FederatedUser.get_from_federated_username(cleaned_data["username"]) 

user.ticket = "" 

user.save() 

# should not happed as if the FederatedUser do not exists, super should 

# raise before a ValidationError("bad user") 

except models.FederatedUser.DoesNotExist: # pragma: no cover (should not happend) 

raise forms.ValidationError( 

_(u"User not found in the temporary database, please try to reconnect") 

) 

return cleaned_data 

 

 

class TicketForm(forms.ModelForm): 

""" 

Bases: :class:`django.forms.ModelForm` 

 

Form for Tickets in the admin interface 

""" 

class Meta: 

model = models.Ticket 

exclude = [] 

service = forms.CharField(label=_('service'), widget=forms.TextInput)