Merge lp:~mhall119/summit/add-auditing into lp:summit
- add-auditing
- Merge into trunk
Proposed by
Michael Hall
Status: | Needs review |
---|---|
Proposed branch: | lp:~mhall119/summit/add-auditing |
Merge into: | lp:summit |
Diff against target: |
417 lines (+321/-0) 9 files modified
summit/common/admin/__init__.py (+1/-0) summit/common/admin/auditadmin.py (+12/-0) summit/common/audit.py (+131/-0) summit/common/migrations/0003_add_audit_model.py (+125/-0) summit/common/models.py (+36/-0) summit/schedule/models/agendamodel.py (+5/-0) summit/schedule/models/meetingmodel.py (+5/-0) summit/schedule/models/summitmodel.py (+5/-0) summit/settings.py (+1/-0) |
To merge this branch: | bzr merge lp:~mhall119/summit/add-auditing |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Summit Hackers | Pending | ||
Review via email:
|
Commit message
Description of the change
Adds change auditing to Summit, Meeting and Agenda
To post a comment you must log in.
Unmerged revisions
- 484. By Michael Hall
-
Add auditing
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'summit/common/admin/__init__.py' | |||
2 | --- summit/common/admin/__init__.py 2012-03-08 01:55:17 +0000 | |||
3 | +++ summit/common/admin/__init__.py 2013-02-24 22:47:21 +0000 | |||
4 | @@ -15,3 +15,4 @@ | |||
5 | 15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | 15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
6 | 16 | 16 | ||
7 | 17 | from menuadmin import * | 17 | from menuadmin import * |
8 | 18 | from auditadmin import * | ||
9 | 18 | 19 | ||
10 | === added file 'summit/common/admin/auditadmin.py' | |||
11 | --- summit/common/admin/auditadmin.py 1970-01-01 00:00:00 +0000 | |||
12 | +++ summit/common/admin/auditadmin.py 2013-02-24 22:47:21 +0000 | |||
13 | @@ -0,0 +1,12 @@ | |||
14 | 1 | from django.contrib import admin | ||
15 | 2 | from common.models import AuditRecord, AuditChange | ||
16 | 3 | |||
17 | 4 | class AuditChangeInline(admin.TabularInline): | ||
18 | 5 | model = AuditChange | ||
19 | 6 | |||
20 | 7 | class AuditAdmin(admin.ModelAdmin): | ||
21 | 8 | inlines = [AuditChangeInline] | ||
22 | 9 | list_display = ('audit_date', 'change_type', 'app_name', 'model_name', 'model_id', 'user') | ||
23 | 10 | list_filter = ('change_type', 'app_name', 'model_name') | ||
24 | 11 | |||
25 | 12 | admin.site.register(AuditRecord, AuditAdmin) | ||
26 | 0 | 13 | ||
27 | === added file 'summit/common/audit.py' | |||
28 | --- summit/common/audit.py 1970-01-01 00:00:00 +0000 | |||
29 | +++ summit/common/audit.py 2013-02-24 22:47:21 +0000 | |||
30 | @@ -0,0 +1,131 @@ | |||
31 | 1 | """ | ||
32 | 2 | Hook existing objects into auditing sytem through Django signals | ||
33 | 3 | |||
34 | 4 | Use: | ||
35 | 5 | |||
36 | 6 | from common.audit import auditSave, auditDelete | ||
37 | 7 | from django.db.models.signals import pre_save, pre_delete | ||
38 | 8 | |||
39 | 9 | pre_save.connect(auditSave, sender=YourObject) | ||
40 | 10 | pre_delete.connect(auditDelete, sender=YourObject) | ||
41 | 11 | |||
42 | 12 | """ | ||
43 | 13 | import django | ||
44 | 14 | from models import AuditRecord, AuditChange | ||
45 | 15 | |||
46 | 16 | |||
47 | 17 | try: | ||
48 | 18 | from threading import local | ||
49 | 19 | except ImportError: | ||
50 | 20 | from django.utils._threading_local import local | ||
51 | 21 | |||
52 | 22 | _thread_locals = local() | ||
53 | 23 | |||
54 | 24 | |||
55 | 25 | def get_current_user(): | ||
56 | 26 | "Return the owner of the current thread" | ||
57 | 27 | return getattr(_thread_locals, 'user', None) | ||
58 | 28 | |||
59 | 29 | def get_current_user_id(): | ||
60 | 30 | user = get_current_user() | ||
61 | 31 | if (user != None): | ||
62 | 32 | return getattr(user, 'id', 0) | ||
63 | 33 | else: | ||
64 | 34 | return 0 | ||
65 | 35 | |||
66 | 36 | def set_current_user(user): | ||
67 | 37 | "Set the owner of the current thread" | ||
68 | 38 | _thread_locals.user = user | ||
69 | 39 | |||
70 | 40 | |||
71 | 41 | class CaptureRequestUser(object): | ||
72 | 42 | "Middleware that captures the current HTTP request user for auditing purposes" | ||
73 | 43 | |||
74 | 44 | def process_request(self, request): | ||
75 | 45 | set_current_user(getattr(request, 'user', None)) | ||
76 | 46 | |||
77 | 47 | |||
78 | 48 | def auditSave(sender, **kwargs): | ||
79 | 49 | instance = kwargs['instance'] | ||
80 | 50 | if (instance.pk is not None and instance.pk > 0): | ||
81 | 51 | try: | ||
82 | 52 | old = instance.__class__.objects.get(id=instance.pk) | ||
83 | 53 | except: | ||
84 | 54 | old = instance.__class__() | ||
85 | 55 | else: | ||
86 | 56 | old = instance.__class__() | ||
87 | 57 | |||
88 | 58 | rec = AuditRecord() | ||
89 | 59 | rec.user = get_current_user() | ||
90 | 60 | rec.app_name = instance._meta.app_label; | ||
91 | 61 | rec.model_name = instance.__class__.__name__ | ||
92 | 62 | rec.model_id = instance.id or 0 | ||
93 | 63 | if instance.id: | ||
94 | 64 | rec.change_type = rec.AUDIT_MODIFY | ||
95 | 65 | else: | ||
96 | 66 | rec.change_type = rec.AUDIT_CREATE | ||
97 | 67 | |||
98 | 68 | rec.save() | ||
99 | 69 | |||
100 | 70 | fields_changed = rec.change_type == rec.AUDIT_CREATE | ||
101 | 71 | |||
102 | 72 | for f in get_audit_fields(instance): | ||
103 | 73 | try: | ||
104 | 74 | oldval = getattr(old, f, None) | ||
105 | 75 | except: | ||
106 | 76 | oldval = None | ||
107 | 77 | newval = getattr(instance, f) | ||
108 | 78 | |||
109 | 79 | # For some reason oldval will be an int, when the field is infact a | ||
110 | 80 | # boolean, so this will force oldval to be the right type | ||
111 | 81 | if isinstance(newval, bool) and isinstance(oldval, int): | ||
112 | 82 | oldval = bool(oldval) | ||
113 | 83 | |||
114 | 84 | if (isinstance(oldval, django.db.models.Model)): | ||
115 | 85 | oldval = getattr(oldval, 'pk', oldval) | ||
116 | 86 | if (isinstance(newval, django.db.models.Model)): | ||
117 | 87 | newval = getattr(newval, 'pk', newval) | ||
118 | 88 | |||
119 | 89 | if ((oldval and oldval.__str__().strip() != '') or (newval and newval.__str__().strip() != '')) and not (oldval and newval and oldval.__str__().strip() == newval.__str__().strip()): | ||
120 | 90 | if hasattr(instance, 'audit_censor') and f in instance.audit_censor: | ||
121 | 91 | oldval = '*****' | ||
122 | 92 | newval = '*****' | ||
123 | 93 | change = AuditChange() | ||
124 | 94 | change.record = rec | ||
125 | 95 | change.field_name = f[0:50] | ||
126 | 96 | change.old_val = str(oldval)[0:255] | ||
127 | 97 | change.new_val = str(newval)[0:255] | ||
128 | 98 | change.save() | ||
129 | 99 | fields_changed = True | ||
130 | 100 | if not fields_changed: | ||
131 | 101 | rec.delete() | ||
132 | 102 | |||
133 | 103 | |||
134 | 104 | def auditDelete(sender, **kwargs): | ||
135 | 105 | |||
136 | 106 | instance = kwargs['instance'] | ||
137 | 107 | |||
138 | 108 | rec = AuditRecord() | ||
139 | 109 | rec.user = get_current_user() | ||
140 | 110 | rec.app_name = instance._meta.app_label; | ||
141 | 111 | rec.model_name = instance.__class__.__name__ | ||
142 | 112 | rec.model_id = instance.id or 0 | ||
143 | 113 | rec.change_type = rec.AUDIT_DELETE | ||
144 | 114 | rec.save() | ||
145 | 115 | |||
146 | 116 | def recordChange(rec, fieldname, oldval, newval): | ||
147 | 117 | change = AuditChange() | ||
148 | 118 | change.record = rec | ||
149 | 119 | change.field_name = fieldname[0:50] | ||
150 | 120 | change.old_val = str(oldval)[0:255] | ||
151 | 121 | change.new_val = str(newval)[0:255] | ||
152 | 122 | change.save() | ||
153 | 123 | |||
154 | 124 | def get_audit_fields(instance): | ||
155 | 125 | "Get a list of fields from a model for which value changes should be audited" | ||
156 | 126 | # The use of _meta is not encouraged, as it is not an external API for Django | ||
157 | 127 | # But I don't see any other reliable way to get a list of a model's fields. | ||
158 | 128 | if hasattr(instance, 'audit_ignore'): | ||
159 | 129 | return [f.column for f in instance._meta.fields if f.name not in instance.audit_ignore] | ||
160 | 130 | else: | ||
161 | 131 | return [f.column for f in instance._meta.fields] | ||
162 | 0 | 132 | ||
163 | === added file 'summit/common/migrations/0003_add_audit_model.py' | |||
164 | --- summit/common/migrations/0003_add_audit_model.py 1970-01-01 00:00:00 +0000 | |||
165 | +++ summit/common/migrations/0003_add_audit_model.py 2013-02-24 22:47:21 +0000 | |||
166 | @@ -0,0 +1,125 @@ | |||
167 | 1 | # encoding: utf-8 | ||
168 | 2 | import datetime | ||
169 | 3 | from south.db import db | ||
170 | 4 | from south.v2 import SchemaMigration | ||
171 | 5 | from django.db import models | ||
172 | 6 | |||
173 | 7 | class Migration(SchemaMigration): | ||
174 | 8 | |||
175 | 9 | def forwards(self, orm): | ||
176 | 10 | |||
177 | 11 | # Adding model 'AuditChange' | ||
178 | 12 | db.create_table('common_auditchange', ( | ||
179 | 13 | ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), | ||
180 | 14 | ('record', self.gf('django.db.models.fields.related.ForeignKey')(related_name='changes', to=orm['common.AuditRecord'])), | ||
181 | 15 | ('field_name', self.gf('django.db.models.fields.CharField')(max_length=50)), | ||
182 | 16 | ('old_val', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)), | ||
183 | 17 | ('new_val', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)), | ||
184 | 18 | )) | ||
185 | 19 | db.send_create_signal('common', ['AuditChange']) | ||
186 | 20 | |||
187 | 21 | # Adding model 'AuditRecord' | ||
188 | 22 | db.create_table('common_auditrecord', ( | ||
189 | 23 | ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), | ||
190 | 24 | ('audit_date', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), | ||
191 | 25 | ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True)), | ||
192 | 26 | ('app_name', self.gf('django.db.models.fields.CharField')(max_length=50)), | ||
193 | 27 | ('model_name', self.gf('django.db.models.fields.CharField')(max_length=50)), | ||
194 | 28 | ('model_id', self.gf('django.db.models.fields.PositiveIntegerField')()), | ||
195 | 29 | ('change_type', self.gf('django.db.models.fields.PositiveIntegerField')()), | ||
196 | 30 | )) | ||
197 | 31 | db.send_create_signal('common', ['AuditRecord']) | ||
198 | 32 | |||
199 | 33 | |||
200 | 34 | def backwards(self, orm): | ||
201 | 35 | |||
202 | 36 | # Deleting model 'AuditChange' | ||
203 | 37 | db.delete_table('common_auditchange') | ||
204 | 38 | |||
205 | 39 | # Deleting model 'AuditRecord' | ||
206 | 40 | db.delete_table('common_auditrecord') | ||
207 | 41 | |||
208 | 42 | |||
209 | 43 | models = { | ||
210 | 44 | 'auth.group': { | ||
211 | 45 | 'Meta': {'object_name': 'Group'}, | ||
212 | 46 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
213 | 47 | 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), | ||
214 | 48 | 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) | ||
215 | 49 | }, | ||
216 | 50 | 'auth.permission': { | ||
217 | 51 | 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, | ||
218 | 52 | 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
219 | 53 | 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), | ||
220 | 54 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
221 | 55 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | ||
222 | 56 | }, | ||
223 | 57 | 'auth.user': { | ||
224 | 58 | 'Meta': {'ordering': "['username']", 'object_name': 'User'}, | ||
225 | 59 | 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
226 | 60 | 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), | ||
227 | 61 | 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
228 | 62 | 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), | ||
229 | 63 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
230 | 64 | 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||
231 | 65 | 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
232 | 66 | 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
233 | 67 | 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
234 | 68 | 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
235 | 69 | 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), | ||
236 | 70 | 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), | ||
237 | 71 | 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) | ||
238 | 72 | }, | ||
239 | 73 | 'common.auditchange': { | ||
240 | 74 | 'Meta': {'object_name': 'AuditChange'}, | ||
241 | 75 | 'field_name': ('django.db.models.fields.CharField', [], {'max_length': '50'}), | ||
242 | 76 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
243 | 77 | 'new_val': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), | ||
244 | 78 | 'old_val': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), | ||
245 | 79 | 'record': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'changes'", 'to': "orm['common.AuditRecord']"}) | ||
246 | 80 | }, | ||
247 | 81 | 'common.auditrecord': { | ||
248 | 82 | 'Meta': {'ordering': "['-audit_date']", 'object_name': 'AuditRecord'}, | ||
249 | 83 | 'app_name': ('django.db.models.fields.CharField', [], {'max_length': '50'}), | ||
250 | 84 | 'audit_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), | ||
251 | 85 | 'change_type': ('django.db.models.fields.PositiveIntegerField', [], {}), | ||
252 | 86 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
253 | 87 | 'model_id': ('django.db.models.fields.PositiveIntegerField', [], {}), | ||
254 | 88 | 'model_name': ('django.db.models.fields.CharField', [], {'max_length': '50'}), | ||
255 | 89 | 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'}) | ||
256 | 90 | }, | ||
257 | 91 | 'common.menu': { | ||
258 | 92 | 'Meta': {'object_name': 'Menu'}, | ||
259 | 93 | 'base_url': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), | ||
260 | 94 | 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), | ||
261 | 95 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
262 | 96 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
263 | 97 | 'site': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sites.Site']"}), | ||
264 | 98 | 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}) | ||
265 | 99 | }, | ||
266 | 100 | 'common.menuitem': { | ||
267 | 101 | 'Meta': {'object_name': 'MenuItem'}, | ||
268 | 102 | 'anonymous_only': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
269 | 103 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
270 | 104 | 'link_url': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
271 | 105 | 'login_required': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
272 | 106 | 'menu': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['common.Menu']"}), | ||
273 | 107 | 'order': ('django.db.models.fields.IntegerField', [], {}), | ||
274 | 108 | 'title': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | ||
275 | 109 | }, | ||
276 | 110 | 'contenttypes.contenttype': { | ||
277 | 111 | 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, | ||
278 | 112 | 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
279 | 113 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
280 | 114 | 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
281 | 115 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | ||
282 | 116 | }, | ||
283 | 117 | 'sites.site': { | ||
284 | 118 | 'Meta': {'ordering': "('domain',)", 'object_name': 'Site', 'db_table': "'django_site'"}, | ||
285 | 119 | 'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
286 | 120 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
287 | 121 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | ||
288 | 122 | } | ||
289 | 123 | } | ||
290 | 124 | |||
291 | 125 | complete_apps = ['common'] | ||
292 | 0 | 126 | ||
293 | === modified file 'summit/common/models.py' | |||
294 | --- summit/common/models.py 2012-10-02 18:07:24 +0000 | |||
295 | +++ summit/common/models.py 2013-02-24 22:47:21 +0000 | |||
296 | @@ -2,6 +2,7 @@ | |||
297 | 2 | 2 | ||
298 | 3 | from django.contrib.sites.models import Site | 3 | from django.contrib.sites.models import Site |
299 | 4 | from django.contrib.sites.managers import CurrentSiteManager | 4 | from django.contrib.sites.managers import CurrentSiteManager |
300 | 5 | from django.contrib.auth.models import User | ||
301 | 5 | 6 | ||
302 | 6 | class Menu(models.Model): | 7 | class Menu(models.Model): |
303 | 7 | name = models.CharField(max_length=100) | 8 | name = models.CharField(max_length=100) |
304 | @@ -42,3 +43,38 @@ | |||
305 | 42 | 43 | ||
306 | 43 | def __unicode__(self): | 44 | def __unicode__(self): |
307 | 44 | return "%s %s. %s" % (self.menu.slug, self.order, self.title) | 45 | return "%s %s. %s" % (self.menu.slug, self.order, self.title) |
308 | 46 | |||
309 | 47 | class AuditRecord(models.Model): | ||
310 | 48 | audit_date = models.DateTimeField("Date", auto_now_add=True) | ||
311 | 49 | user = models.ForeignKey(User, null=True) | ||
312 | 50 | app_name = models.CharField("Application", max_length = 50) | ||
313 | 51 | model_name = models.CharField("Model", max_length = 50) | ||
314 | 52 | model_id = models.PositiveIntegerField("Model ID") | ||
315 | 53 | AUDIT_CREATE = 0 | ||
316 | 54 | AUDIT_MODIFY = 1 | ||
317 | 55 | AUDIT_DELETE = 2 | ||
318 | 56 | AUDIT_CHANGE_TYPES = ( | ||
319 | 57 | (AUDIT_CREATE, 'create'), | ||
320 | 58 | (AUDIT_MODIFY, 'modify'), | ||
321 | 59 | (AUDIT_DELETE, 'delete'), | ||
322 | 60 | ) | ||
323 | 61 | change_type = models.PositiveIntegerField("Change Type", choices = AUDIT_CHANGE_TYPES) | ||
324 | 62 | |||
325 | 63 | class Meta: | ||
326 | 64 | ordering = ['-audit_date'] | ||
327 | 65 | verbose_name = "Audit Record" | ||
328 | 66 | |||
329 | 67 | def __unicode__(self): | ||
330 | 68 | return "%s.%s[%s] @ %s" % (self.app_name, self.model_name, self.model_id, self.audit_date) | ||
331 | 69 | |||
332 | 70 | class AuditChange(models.Model): | ||
333 | 71 | record = models.ForeignKey(AuditRecord, related_name='changes') | ||
334 | 72 | field_name = models.CharField("Field", max_length = 50) | ||
335 | 73 | old_val = models.CharField("From", max_length = 255, blank=True, null=True) | ||
336 | 74 | new_val = models.CharField("To", max_length = 255, blank=True, null=True) | ||
337 | 75 | |||
338 | 76 | class Meta: | ||
339 | 77 | verbose_name = "Audit Change" | ||
340 | 78 | |||
341 | 79 | def __unicode__(self): | ||
342 | 80 | return "%s: %s -> %s" % (self.field_name, self.old_val, self.new_val) | ||
343 | 45 | 81 | ||
344 | === modified file 'summit/schedule/models/agendamodel.py' | |||
345 | --- summit/schedule/models/agendamodel.py 2012-01-23 01:18:55 +0000 | |||
346 | +++ summit/schedule/models/agendamodel.py 2013-02-24 22:47:21 +0000 | |||
347 | @@ -20,6 +20,9 @@ | |||
348 | 20 | from summit.schedule.models.roommodel import Room | 20 | from summit.schedule.models.roommodel import Room |
349 | 21 | from summit.schedule.models.meetingmodel import Meeting | 21 | from summit.schedule.models.meetingmodel import Meeting |
350 | 22 | 22 | ||
351 | 23 | from common.audit import auditSave, auditDelete | ||
352 | 24 | from django.db.models.signals import pre_save, pre_delete | ||
353 | 25 | |||
354 | 23 | __all__ = ( | 26 | __all__ = ( |
355 | 24 | 'Agenda', | 27 | 'Agenda', |
356 | 25 | ) | 28 | ) |
357 | @@ -48,3 +51,5 @@ | |||
358 | 48 | 51 | ||
359 | 49 | def __unicode__(self): | 52 | def __unicode__(self): |
360 | 50 | return "%s" % self.meeting | 53 | return "%s" % self.meeting |
361 | 54 | pre_save.connect(auditSave, sender=Agenda) | ||
362 | 55 | pre_delete.connect(auditDelete, sender=Agenda) | ||
363 | 51 | 56 | ||
364 | === modified file 'summit/schedule/models/meetingmodel.py' | |||
365 | --- summit/schedule/models/meetingmodel.py 2013-02-20 13:57:06 +0000 | |||
366 | +++ summit/schedule/models/meetingmodel.py 2013-02-24 22:47:21 +0000 | |||
367 | @@ -33,6 +33,9 @@ | |||
368 | 33 | 33 | ||
369 | 34 | from summit.schedule.autoslug import AutoSlugMixin | 34 | from summit.schedule.autoslug import AutoSlugMixin |
370 | 35 | 35 | ||
371 | 36 | from common.audit import auditSave, auditDelete | ||
372 | 37 | from django.db.models.signals import pre_save, pre_delete | ||
373 | 38 | |||
374 | 36 | __all__ = ( | 39 | __all__ = ( |
375 | 37 | 'Meeting', | 40 | 'Meeting', |
376 | 38 | ) | 41 | ) |
377 | @@ -601,3 +604,5 @@ | |||
378 | 601 | print "-- could not schedule %s in %s at %s (%s)" % (self, room, slot, e) | 604 | print "-- could not schedule %s in %s at %s (%s)" % (self, room, slot, e) |
379 | 602 | 605 | ||
380 | 603 | return False | 606 | return False |
381 | 607 | pre_save.connect(auditSave, sender=Meeting) | ||
382 | 608 | pre_delete.connect(auditDelete, sender=Meeting) | ||
383 | 604 | 609 | ||
384 | === modified file 'summit/schedule/models/summitmodel.py' | |||
385 | --- summit/schedule/models/summitmodel.py 2013-02-21 23:10:17 +0000 | |||
386 | +++ summit/schedule/models/summitmodel.py 2013-02-24 22:47:21 +0000 | |||
387 | @@ -40,6 +40,9 @@ | |||
388 | 40 | from summit.schedule.fields import NameField | 40 | from summit.schedule.fields import NameField |
389 | 41 | from summit.common import launchpad | 41 | from summit.common import launchpad |
390 | 42 | 42 | ||
391 | 43 | from common.audit import auditSave, auditDelete | ||
392 | 44 | from django.db.models.signals import pre_save, pre_delete | ||
393 | 45 | |||
394 | 43 | __all__ = ( | 46 | __all__ = ( |
395 | 44 | 'Summit', | 47 | 'Summit', |
396 | 45 | 'SummitSprint', | 48 | 'SummitSprint', |
397 | @@ -512,6 +515,8 @@ | |||
398 | 512 | if attendee is not None: | 515 | if attendee is not None: |
399 | 513 | return self.lead_set.filter(lead=attendee).exists() | 516 | return self.lead_set.filter(lead=attendee).exists() |
400 | 514 | return False | 517 | return False |
401 | 518 | pre_save.connect(auditSave, sender=Summit) | ||
402 | 519 | pre_delete.connect(auditDelete, sender=Summit) | ||
403 | 515 | 520 | ||
404 | 516 | 521 | ||
405 | 517 | class SummitSprint(models.Model): | 522 | class SummitSprint(models.Model): |
406 | 518 | 523 | ||
407 | === modified file 'summit/settings.py' | |||
408 | --- summit/settings.py 2013-02-04 23:22:10 +0000 | |||
409 | +++ summit/settings.py 2013-02-24 22:47:21 +0000 | |||
410 | @@ -108,6 +108,7 @@ | |||
411 | 108 | 'django.middleware.locale.LocaleMiddleware', | 108 | 'django.middleware.locale.LocaleMiddleware', |
412 | 109 | 'django.contrib.sessions.middleware.SessionMiddleware', | 109 | 'django.contrib.sessions.middleware.SessionMiddleware', |
413 | 110 | 'django.contrib.auth.middleware.AuthenticationMiddleware', | 110 | 'django.contrib.auth.middleware.AuthenticationMiddleware', |
414 | 111 | 'common.audit.CaptureRequestUser', | ||
415 | 111 | ) | 112 | ) |
416 | 112 | 113 | ||
417 | 113 | ROOT_URLCONF = 'summit.urls' | 114 | ROOT_URLCONF = 'summit.urls' |