Mercurial > public > sg101
comparison wiki/middleware.py @ 626:a6bc1e2efa63
Created wiki app to provide integration with MoinMoin.
This commit has a working middleware & test.
author | Brian Neal <bgneal@gmail.com> |
---|---|
date | Wed, 07 Nov 2012 20:17:33 -0600 |
parents | |
children | a4300639c6e7 |
comparison
equal
deleted
inserted
replaced
625:08d905e38a86 | 626:a6bc1e2efa63 |
---|---|
1 """Middleware for wiki integration. | |
2 | |
3 """ | |
4 import datetime | |
5 import hashlib | |
6 import logging | |
7 import random | |
8 import string | |
9 import time | |
10 | |
11 from django.conf import settings | |
12 import redis | |
13 | |
14 from core.services import get_redis_connection | |
15 | |
16 | |
17 SESSION_KEY = 'wiki_redis_key' | |
18 logger = logging.getLogger(__name__) | |
19 | |
20 | |
21 def cookie_value(user, now): | |
22 """Creates the value for the external wiki cookie.""" | |
23 | |
24 # The key part of the cookie is just a string that would make things | |
25 # difficult for a spoofer; something that can't be easily made up: | |
26 | |
27 h = hashlib.sha256() | |
28 h.update(user.username + user.email) | |
29 h.update(now.isoformat()) | |
30 h.update(''.join(random.sample(string.printable, 64))) | |
31 h.update(settings.SECRET_KEY) | |
32 key = h.hexdigest() | |
33 | |
34 parts = (user.username, user.email, key) | |
35 return '#'.join(parts) | |
36 | |
37 | |
38 def create_wiki_session(request, response): | |
39 """Sets up the session for the external wiki application. | |
40 | |
41 Creates the external cookie for the Wiki. | |
42 Updates the Redis set so the Wiki can verify the cookie. | |
43 | |
44 """ | |
45 now = datetime.datetime.utcnow() | |
46 value = cookie_value(request.user, now) | |
47 response.set_cookie(settings.WIKI_COOKIE_NAME, | |
48 value=value, | |
49 max_age=settings.WIKI_COOKIE_AGE, | |
50 domain=settings.WIKI_COOKIE_DOMAIN) | |
51 | |
52 # Update a sorted set in Redis with a hash of our cookie and a score | |
53 # of the current time as a timestamp. This allows us to delete old | |
54 # entries by score periodically. To verify the cookie, the external wiki | |
55 # application computes a hash of the cookie value and checks to see if | |
56 # it is in our Redis set. | |
57 | |
58 h = hashlib.sha256() | |
59 h.update(value) | |
60 name = h.hexdigest() | |
61 score = time.mktime(now.utctimetuple()) | |
62 conn = get_redis_connection() | |
63 | |
64 try: | |
65 conn.zadd(settings.WIKI_REDIS_SET, score, name) | |
66 except redis.RedisError: | |
67 logger.error("Error adding wiki cookie key") | |
68 | |
69 # Store the set member name in the session so we can delete it when the | |
70 # user logs out: | |
71 request.session[SESSION_KEY] = name | |
72 | |
73 | |
74 def destroy_wiki_session(request, response): | |
75 """Destroys the session for the external wiki application. | |
76 | |
77 Delete the external cookie. | |
78 Deletes the key from the Redis set as this entry is no longer valid. | |
79 | |
80 """ | |
81 response.delete_cookie(settings.WIKI_COOKIE_NAME, | |
82 domain=settings.WIKI_COOKIE_DOMAIN) | |
83 | |
84 try: | |
85 key = request.session[SESSION_KEY] | |
86 except KeyError: | |
87 # Hmmm, perhaps user logged in before this application was installed. | |
88 return | |
89 | |
90 conn = get_redis_connection() | |
91 try: | |
92 conn.zrem(settings.WIKI_REDIS_SET, key) | |
93 except redis.RedisError: | |
94 logger.error("Error deleting wiki cookie key") | |
95 | |
96 del request.session[SESSION_KEY] | |
97 | |
98 | |
99 class WikiMiddleware(object): | |
100 """ | |
101 Check for flags set in the session to determine when to set or delete an | |
102 external cookie for the wiki application. When creating a cookie, also | |
103 set an entry in Redis that the wiki application can validate to prevent | |
104 spoofing. | |
105 | |
106 """ | |
107 | |
108 def process_response(self, request, response): | |
109 | |
110 if request.session.get('wiki_set_cookie', False): | |
111 del request.session['wiki_set_cookie'] | |
112 | |
113 create_wiki_session(request, response) | |
114 | |
115 elif request.session.get('wiki_delete_cookie', False): | |
116 del request.session['wiki_delete_cookie'] | |
117 | |
118 destroy_wiki_session(request, response) | |
119 | |
120 return response |