views.py 8.67 KB
Newer Older
1
from go.models import URL, RegisteredUser
Jean Michel Rouly's avatar
Jean Michel Rouly committed
2
from go.forms import URLForm, SignupForm
3
from datetime import timedelta
4
from django.conf import settings
5
from django.http import Http404, HttpResponseServerError
6
from django.utils import timezone
Jean Michel Rouly's avatar
Jean Michel Rouly committed
7
from django.contrib.auth.models import User
8
from django.core.exceptions import PermissionDenied, ValidationError
9
from django.core.mail import send_mail
10
11
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.contrib.auth.decorators import user_passes_test, login_required
Jean Michel Rouly's avatar
Jean Michel Rouly committed
12
from django.shortcuts import render, get_object_or_404, redirect
13
import os
14

Jean Michel Rouly's avatar
Jean Michel Rouly committed
15
16
17
18
19
20
21

##############################################################################
"""
Define useful helper methods here.
"""


22
def is_registered( user ):
Jean Michel Rouly's avatar
Jean Michel Rouly committed
23
24
25
26
27
    """
    This function checks if a user account has a corresponding RegisteredUser,
    thus checking if the user is registered.
    """

28
    try:
29
        registered = RegisteredUser.objects.get( username=user.username )
30
        return registered.approved
31
32
33
    except RegisteredUser.DoesNotExist:
        return False

Jean Michel Rouly's avatar
Jean Michel Rouly committed
34
35
36
37
38
39
40

##############################################################################
"""
Define error page handling here.
"""


41
def error_404(request):
Jean Michel Rouly's avatar
Jean Michel Rouly committed
42
43
44
45
    """
    Error 404 view, in case a url is not found.
    """

46
47
48
49
50
    return render(request, '404.html', {
    },
    )

def error_500(request):
Jean Michel Rouly's avatar
Jean Michel Rouly committed
51
52
53
54
    """
    Error 500 view, in case a server error occurs.
    """

55
56
57
58
    return render(request, '500.html', {
    },
    )

Jean Michel Rouly's avatar
Jean Michel Rouly committed
59
60
61
62
63
64
##############################################################################
"""
Define user views here.
"""


65
@login_required
Jean Michel Rouly's avatar
Jean Michel Rouly committed
66
def index(request):
Jean Michel Rouly's avatar
Jean Michel Rouly committed
67
68
69
70
71
72
73
    """
    This view handles the homepage that the user is presented with when
    they request '/'. If they're not logged in, they're redirected to
    login. If they're logged in but not registered, they're given the
    not_registered error page. If they are logged in AND registered, they
    get the URL registration form.
    """
Jean Michel Rouly's avatar
Jean Michel Rouly committed
74

Jean Michel Rouly's avatar
Jean Michel Rouly committed
75
    # If the user isn't registered, don't give them any leeway.
76
77
78
    if not is_registered(request.user):
        return render(request, 'not_registered.html')

79
80
81
82
83
84
    url_form = URLForm() # unbound form

    if request.method == 'POST':
        url_form = URLForm( request.POST ) # bind dat form
        if url_form.is_valid():

Jean Michel Rouly's avatar
Jean Michel Rouly committed
85
86
            # We don't commit the url object yet because we need to add its
            # owner, and parse its date field.
87
88
89
            url = url_form.save(commit=False)
            url.owner = request.user

Jean Michel Rouly's avatar
Jean Michel Rouly committed
90
            # If the user entered a short url, it's already been validated,
Jean Michel Rouly's avatar
Jean Michel Rouly committed
91
92
            # so accept it. If they did not, however, then generate a
            # random one and use that instead.
93
            short = url_form.cleaned_data.get('short').strip()
94
95
96
            if len(short) > 0:
                url.short = short
            else:
97
98
99
100
101
102
103
104
105
106
                # If the user didn't enter a short url, generate a random
                # one. However, if a random one can't be generated, return
                # a 500 server error.
                random_short = URL.generate_valid_short()
                if random_short is None:
                    return HttpResponseServerError(
                        render(request, '500.html', {})
                    )
                else:
                    url.short = random_short
107

Jean Michel Rouly's avatar
Jean Michel Rouly committed
108
109
110
            # Grab the expiration field value. It's currently an unsable
            # string value, so we need to parse it into a datetime object
            # relative to right now.
111
            expires = url_form.cleaned_data.get('expires')
112
113
114
115
116
117
118
119
120
121

            if expires == URLForm.DAY:
                url.expires = timezone.now() + timedelta(days=1)
            elif expires == URLForm.WEEK:
                url.expires = timezone.now() + timedelta(weeks=1)
            elif expires == URLForm.MONTH:
                url.expires = timezone.now() + timedelta(weeks=3)
            else:
                pass # leave the field NULL

Jean Michel Rouly's avatar
Jean Michel Rouly committed
122
123
            # Make sure that our new URL object is clean, then save it and
            # let's redirect to view this baby.
124
125
            url.full_clean()
            url.save()
Jean Michel Rouly's avatar
Jean Michel Rouly committed
126
            return redirect('view', url.short)
127
128
129

    return render(request, 'index.html', {
        'form': url_form,
Jean Michel Rouly's avatar
Jean Michel Rouly committed
130
131
132
    },
    )

Jean Michel Rouly's avatar
Jean Michel Rouly committed
133

Jean Michel Rouly's avatar
Jean Michel Rouly committed
134
def view(request, short):
Jean Michel Rouly's avatar
Jean Michel Rouly committed
135
136
137
138
139
    """
    This view allows the user to view details about a URL. Note that they
    do not need to be logged in to view info.
    """

Jean Michel Rouly's avatar
Jean Michel Rouly committed
140
    url = get_object_or_404(URL, short__iexact = short)
141

Jean Michel Rouly's avatar
Jean Michel Rouly committed
142
    return render(request, 'view.html', {
143
144
145
146
        'url': url,
    },
    )

Jean Michel Rouly's avatar
Jean Michel Rouly committed
147

148
@login_required
149
def my_links(request):
Jean Michel Rouly's avatar
Jean Michel Rouly committed
150
151
152
153
154
    """
    This view displays all the information about all of your URLs. You
    obviously need to be logged in to view your URLs.
    """

155
156
    if not is_registered(request.user):
        return render(request, 'not_registered.html')
Jean Michel Rouly's avatar
Jean Michel Rouly committed
157

158
    urls = URL.objects.filter( owner = request.user )
159
    return render(request, 'my_links.html', {
160
        'urls' : urls,
161
162
163
    },
    )

Jean Michel Rouly's avatar
Jean Michel Rouly committed
164

165
@login_required
166
def delete(request, short):
Jean Michel Rouly's avatar
Jean Michel Rouly committed
167
168
169
170
171
    """
    This view deletes a URL if you have the permission to. User must be
    logged in and registered, and must also be the owner of the URL.
    """

172
173
    if not is_registered(request.user):
        return render(request, 'not_registered.html')
Jean Michel Rouly's avatar
Jean Michel Rouly committed
174

Jean Michel Rouly's avatar
Jean Michel Rouly committed
175
    url = get_object_or_404(URL, short__iexact = short )
176
177
    if url.owner == request.user:
        url.delete()
178
179
        return redirect('my_links')
    else:
180
        raise PermissionDenied()
181

Jean Michel Rouly's avatar
Jean Michel Rouly committed
182

183
@login_required
Jean Michel Rouly's avatar
Jean Michel Rouly committed
184
def signup(request):
Jean Michel Rouly's avatar
Jean Michel Rouly committed
185
186
187
188
189
190
    """
    This view presents the user with a registration form. You can register
    yourself, or another person.

    """

191
    signup_form = SignupForm()
Jean Michel Rouly's avatar
Jean Michel Rouly committed
192
193

    if request.method == 'POST':
194
195
196
197
198
        signup_form = SignupForm(request.POST, initial={'approved': False})
        if signup_form.is_valid():
            username = signup_form.cleaned_data.get('username')
            full_name = signup_form.cleaned_data.get('full_name')
            description = signup_form.cleaned_data.get('description')
199

200
201
202
203
204
205
            send_mail('Signup from %s' % (username), '%s signed up at %s\n'
                'Username: %s\nMessage: %s\nPlease attend to this request at '
                'your earliest convenience.' % (str(full_name),
                str(timezone.now()).strip(), str(username), str(description)),
                settings.EMAIL_FROM, [settings.EMAIL_TO])

206
207
            signup_form.save()

208
            return redirect('registered')
Jean Michel Rouly's avatar
Jean Michel Rouly committed
209

Jean Michel Rouly's avatar
Jean Michel Rouly committed
210
    return render(request, 'signup.html', {
211
        'form': signup_form,
Jean Michel Rouly's avatar
Jean Michel Rouly committed
212
213
    },
    )
Jean Michel Rouly's avatar
Jean Michel Rouly committed
214

Jean Michel Rouly's avatar
Jean Michel Rouly committed
215

Jean Michel Rouly's avatar
Jean Michel Rouly committed
216
def redirection(request, short):
Jean Michel Rouly's avatar
Jean Michel Rouly committed
217
218
219
    """
    This view redirects a user based on the short URL they requested.
    """
Jean Michel Rouly's avatar
Jean Michel Rouly committed
220

Jean Michel Rouly's avatar
Jean Michel Rouly committed
221
    url = get_object_or_404( URL, short__iexact = short )
Jean Michel Rouly's avatar
Jean Michel Rouly committed
222
223
    url.clicks = url.clicks + 1
    url.save()
224

Jean Michel Rouly's avatar
Jean Michel Rouly committed
225
226
227
228
229
    """
    Include server-side tracking because there is no template displayed to
    the user which would include javascript tracking.
    """

230
231
    from piwikapi.tracking import PiwikTracker
    from django.conf import settings
232
233
234
235
236
237
238
239
240
    # First, if PIWIK variables are undefined, don't try to push
    if settings.PIWIK_SITE_ID is not "" and settings.PIWIK_URL is not "":
        try:
            piwiktracker = PiwikTracker(settings.PIWIK_SITE_ID, request)
            piwiktracker.set_api_url(settings.PIWIK_URL)
            piwiktracker.do_track_page_view('Redirect to %s' % url.target)
        # Second, if we do get an error, don't let that keep us from redirecting
        except:
            pass
241
242

    return redirect( url.target )
Jean Michel Rouly's avatar
Jean Michel Rouly committed
243
244


245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
def staff_member_required(view_func, redirect_field_name=REDIRECT_FIELD_NAME, login_url='about'):
    """
    Decorator for views that checks that the user is logged in and is a staff
    member, displaying the login page if necessary.
    """
    return user_passes_test(
        lambda u: u.is_active and u.is_staff,
        login_url=login_url,
        redirect_field_name=redirect_field_name
    )(view_func)


@staff_member_required
def adminpanel(request):
    """
    This view is a simplified admin panel, so that staff don't need to log in
    to approve links
    """
    if request.POST:
        if '_approve' in request.POST:
            toapprove = RegisteredUser.objects.get(username=request.POST['username'])
            toapprove.approved = True
            toapprove.save()
        elif '_deny' in request.POST:
            todeny = RegisteredUser.objects.get(username=request.POST['username'])
            todeny.delete()
    need_approval = RegisteredUser.objects.filter(approved=False)
    return render(request, 'adminpanel.html',{
        'need_approval': need_approval
    },
    )


Jean Michel Rouly's avatar
Jean Michel Rouly committed
278
279
280
281
282
283
284
285
286
287
288
##############################################################################
"""
Define static user views here.
"""


def about(request):
    return render(request, 'about.html', {
    },
    )

289
290
291
292
def registered(request):
    return render(request, 'registered.html', {
    },
    )