Commit 1e7861daedeaa731a40e293d6ab64ee7cf7dc5a6

Authored by Gust
1 parent 5dcd8f29

Separeted trac migration from colab

src/accounts/search_indexes.py
... ... @@ -3,7 +3,7 @@
3 3 from haystack import indexes
4 4 from django.db.models import Count
5 5  
6   -from proxy.models import Revision, Ticket, Wiki
  6 +from proxy.trac.models import Revision, Ticket, Wiki
7 7 from badger.utils import get_users_counters
8 8 from .models import User
9 9  
... ...
src/accounts/views.py
... ... @@ -25,7 +25,7 @@ from haystack.query import SearchQuerySet
25 25 from super_archives.models import EmailAddress, Message
26 26 from super_archives.utils.email import send_email_lists
27 27 from search.utils import trans
28   -from proxy.models import WikiCollabCount, TicketCollabCount
  28 +from proxy.trac.models import WikiCollabCount, TicketCollabCount
29 29 from .forms import (UserCreationForm, ListsForm, UserUpdateForm,
30 30 ChangeXMPPPasswordForm)
31 31 from .errors import XMPPChangePwdException
... ...
src/api/resources.py
... ... @@ -7,7 +7,7 @@ from tastypie.constants import ALL_WITH_RELATIONS, ALL
7 7 from tastypie.resources import ModelResource
8 8  
9 9 from super_archives.models import Message, EmailAddress
10   -from proxy.models import Revision, Ticket, Wiki
  10 +from proxy.trac.models import Revision, Ticket, Wiki
11 11  
12 12  
13 13 User = get_user_model()
... ...
src/badger/utils.py
... ... @@ -2,7 +2,7 @@
2 2  
3 3 from django.db.models import Count
4 4  
5   -from proxy.models import (Revision, Ticket, Wiki,
  5 +from proxy.trac.models import (Revision, Ticket, Wiki,
6 6 WikiCollabCount, TicketCollabCount)
7 7 from accounts.models import User
8 8  
... ...
src/colab/custom_settings.py
... ... @@ -262,6 +262,9 @@ TRAC_ENABLED = False
262 262 if TRAC_ENABLED:
263 263 from trac_settings import *
264 264 DATABASES['trac'] = TRAC_DATABASE
  265 + INSTALLED_APPS = INSTALLED_APPS + (
  266 + 'proxy.trac',
  267 + )
265 268  
266 269  
267 270 ### Feedzilla (planet)
... ...
src/home/views.py
... ... @@ -9,7 +9,7 @@ from django.http import HttpResponse, Http404
9 9 from search.utils import trans
10 10 from haystack.query import SearchQuerySet
11 11  
12   -from proxy.models import WikiCollabCount, TicketCollabCount
  12 +from proxy.trac.models import WikiCollabCount, TicketCollabCount
13 13 from super_archives.models import Thread
14 14  
15 15  
... ... @@ -28,13 +28,15 @@ def index(request):
28 28 type=type,
29 29 ).count()
30 30  
31   - count_types['ticket'] = sum([
32   - ticket.count for ticket in TicketCollabCount.objects.all()
33   - ])
  31 + if settings.TRAC_ENABLED:
  32 + count_types['ticket'] = sum([
  33 + ticket.count for ticket in TicketCollabCount.objects.all()
  34 + ])
34 35  
35   - count_types['wiki'] = sum([
36   - wiki.count for wiki in WikiCollabCount.objects.all()
37   - ])
  36 + count_types['wiki'] = sum([
  37 + wiki.count for wiki in WikiCollabCount.objects.all()
  38 + ])
  39 +
38 40 cache.set('home_chart', count_types)
39 41  
40 42 for key in count_types.keys():
... ...
src/proxy/migrations/0001_initial.py
... ... @@ -1,248 +0,0 @@
1   -# -*- coding: utf-8 -*-
2   -import datetime
3   -from django.db import connections
4   -from south.db import db
5   -from south.v2 import SchemaMigration
6   -from django.db import models
7   -
8   -
9   -class Migration(SchemaMigration):
10   -
11   - def forwards(self, orm):
12   - connection = connections['trac']
13   -
14   - cursor = connection.cursor()
15   - cursor.execute('''
16   - CREATE OR REPLACE VIEW wiki_view AS SELECT
17   - wiki.name AS name,
18   - (SELECT wiki2.text FROM wiki AS wiki2 WHERE wiki2.name = wiki.name
19   - AND wiki2.version = MAX(wiki.version)) AS wiki_text,
20   - (SELECT wiki3.author FROM wiki AS wiki3 WHERE wiki3.name = wiki.name
21   - AND wiki3.version = 1) AS author,
22   - string_agg(DISTINCT wiki.author, ', ') AS collaborators,
23   - TIMESTAMP WITH TIME ZONE 'epoch' + (MAX(wiki.time)/1000000) * INTERVAL '1s' AS created,
24   - TIMESTAMP WITH TIME ZONE 'epoch' + (MIN(wiki.time)/1000000) * INTERVAL '1s' AS modified
25   - FROM wiki
26   - GROUP BY wiki.name;
27   -
28   - CREATE OR REPLACE VIEW ticket_view AS SELECT
29   - ticket.id AS id,
30   - ticket.summary as summary,
31   - ticket.description as description,
32   - ticket.milestone as milestone,
33   - ticket.priority as priority,
34   - ticket.component as component,
35   - ticket.version as version,
36   - ticket.severity as severity,
37   - ticket.reporter as reporter,
38   - ticket.reporter as author,
39   - ticket.status as status,
40   - ticket.keywords as keywords,
41   - (SELECT
42   - string_agg(DISTINCT ticket_change.author, ', ')
43   - FROM ticket_change WHERE ticket_change.ticket = ticket.id
44   - GROUP BY ticket_change.ticket) as collaborators,
45   - TIMESTAMP WITH TIME ZONE 'epoch' + (time/1000000)* INTERVAL '1s' AS created,
46   - TIMESTAMP WITH TIME ZONE 'epoch' + (changetime/1000000) * INTERVAL '1s' AS modified
47   - FROM ticket;
48   -
49   - CREATE OR REPLACE VIEW revision_view AS SELECT
50   - revision.rev,
51   - revision.author,
52   - revision.message,
53   - repository.value AS repository_name,
54   - TIMESTAMP WITH TIME ZONE 'epoch' + (revision.time/1000000) * INTERVAL '1s' AS created
55   - FROM revision
56   - INNER JOIN repository ON(
57   - repository.id = revision.repos
58   - AND repository.name = 'name'
59   - AND repository.value != ''
60   - );
61   - ''')
62   - cursor.execute('''
63   -CREATE OR REPLACE VIEW revision_view AS SELECT
64   -revision.rev,
65   -revision.author,
66   -revision.message,
67   -repository.value AS repository_name,
68   -TIMESTAMP WITH TIME ZONE 'epoch' + (revision.time/1000000) * INTERVAL '1s' AS created,
69   -CONCAT(revision.repos, '-', revision.rev) AS key
70   -FROM revision
71   -INNER JOIN repository ON(
72   -repository.id = revision.repos
73   -AND repository.name = 'name'
74   -AND repository.value != ''
75   -);
76   -''')
77   - cursor.execute('''
78   -CREATE OR REPLACE VIEW attachment_view AS SELECT
79   -CONCAT(attachment.type, '/' , attachment.id, '/', attachment.filename) AS url,
80   -attachment.type AS used_by,
81   -attachment.filename AS filename,
82   -attachment.id as attach_id,
83   -(SELECT LOWER(SUBSTRING(attachment.filename FROM '\.(\w+)$'))) AS mimetype,
84   -attachment.author AS author,
85   -attachment.description AS description,
86   -attachment.size AS size,
87   -TIMESTAMP WITH TIME ZONE 'epoch' + (attachment.time/1000000)* INTERVAL '1s' AS created
88   -FROM attachment;
89   -''')
90   - cursor.execute('''
91   -CREATE OR REPLACE VIEW wiki_view AS SELECT
92   -wiki.name AS name,
93   -(SELECT wiki2.text FROM wiki AS wiki2 WHERE wiki2.name = wiki.name
94   -AND wiki2.version = MAX(wiki.version)) AS wiki_text,
95   -(SELECT wiki3.author FROM wiki AS wiki3 WHERE wiki3.name = wiki.name
96   -AND wiki3.version = 1) AS author,
97   -string_agg(DISTINCT wiki.author, ', ') AS collaborators,
98   -TIMESTAMP WITH TIME ZONE 'epoch' + (MIN(wiki.time)/1000000) * INTERVAL '1s' AS created,
99   -TIMESTAMP WITH TIME ZONE 'epoch' + (MAX(wiki.time)/1000000) * INTERVAL '1s' AS modified
100   -FROM wiki
101   -GROUP BY wiki.name;
102   -''')
103   - cursor.execute('''
104   -CREATE OR REPLACE VIEW wiki_view AS SELECT
105   -wiki.name AS name,
106   -(SELECT wiki2.text FROM wiki AS wiki2 WHERE wiki2.name = wiki.name
107   -AND wiki2.version = MAX(wiki.version)) AS wiki_text,
108   -(SELECT wiki3.author FROM wiki AS wiki3 WHERE wiki3.name = wiki.name
109   -AND wiki3.version = 1) AS author,
110   -string_agg(DISTINCT wiki.author, ', ') AS collaborators,
111   -TIMESTAMP WITH TIME ZONE 'epoch' + (MIN(wiki.time)/1000000) * INTERVAL '1s' AS created,
112   -TIMESTAMP WITH TIME ZONE 'epoch' + (MAX(wiki.time)/1000000) * INTERVAL '1s' AS modified,
113   -(SELECT wiki4.author FROM wiki AS wiki4 WHERE wiki4.name = wiki.name
114   -AND wiki4.version = MAX(wiki.version)) AS modified_by
115   -FROM wiki
116   -GROUP BY wiki.name;
117   -
118   -CREATE OR REPLACE VIEW ticket_view AS SELECT
119   -ticket.id AS id,
120   -ticket.summary as summary,
121   -ticket.description as description,
122   -ticket.milestone as milestone,
123   -ticket.priority as priority,
124   -ticket.component as component,
125   -ticket.version as version,
126   -ticket.severity as severity,
127   -ticket.reporter as reporter,
128   -ticket.reporter as author,
129   -ticket.status as status,
130   -ticket.keywords as keywords,
131   -(SELECT
132   -string_agg(DISTINCT ticket_change.author, ', ')
133   -FROM ticket_change WHERE ticket_change.ticket = ticket.id
134   -GROUP BY ticket_change.ticket) as collaborators,
135   -TIMESTAMP WITH TIME ZONE 'epoch' + (time/1000000)* INTERVAL '1s' AS created,
136   -TIMESTAMP WITH TIME ZONE 'epoch' + (changetime/1000000) * INTERVAL '1s' AS modified,
137   -(SELECT
138   -ticket_change.author
139   -FROM ticket_change
140   -WHERE ticket_change.ticket = ticket.id
141   -AND ticket_change.time = ticket.changetime
142   -LIMIT 1
143   -) AS modified_by
144   -FROM ticket;
145   -''')
146   - cursor.execute('''
147   -CREATE OR REPLACE VIEW ticket_collab_count_view AS
148   -SELECT
149   -COALESCE (t1.author, t2.author) as author,
150   -(COALESCE(t1.count, 0) + COALESCE(t2.count, 0)) as count
151   -FROM
152   -(SELECT author, count(*) as count
153   -FROM ticket_change
154   -GROUP BY author
155   -ORDER BY author
156   -) AS t1
157   -FULL OUTER JOIN
158   -(SELECT reporter as author, count(*) as count
159   -FROM ticket
160   -GROUP BY reporter
161   -ORDER BY reporter
162   -) AS t2
163   -ON t1.author = t2.author;
164   -
165   -CREATE OR REPLACE VIEW wiki_collab_count_view AS
166   -SELECT author, count(*) from wiki GROUP BY author;
167   -''')
168   -
169   - pass
170   -
171   - def backwards(self, orm):
172   - connection = connections['trac']
173   -
174   - cursor = connection.cursor()
175   - cursor.execute('''
176   -DROP VIEW IF EXISTS revision_view;
177   -DROP VIEW IF EXISTS ticket_view;
178   -DROP VIEW IF EXISTS wiki_view;
179   -''')
180   - cursor.execute('DROP VIEW IF EXISTS attachment_view;')
181   -
182   - pass
183   -
184   - models = {
185   - u'proxy.attachment': {
186   - 'Meta': {'object_name': 'Attachment', 'db_table': "'attachment_view'", 'managed': 'False'},
187   - 'attach_id': ('django.db.models.fields.TextField', [], {}),
188   - 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
189   - 'created': ('django.db.models.fields.DateTimeField', [], {'blank': 'True'}),
190   - 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
191   - 'filename': ('django.db.models.fields.TextField', [], {}),
192   - 'mimetype': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
193   - 'size': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}),
194   - 'url': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}),
195   - 'used_by': ('django.db.models.fields.TextField', [], {})
196   - },
197   - u'proxy.revision': {
198   - 'Meta': {'object_name': 'Revision', 'db_table': "'revision_view'", 'managed': 'False'},
199   - 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
200   - 'created': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
201   - 'key': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}),
202   - 'message': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
203   - 'repository_name': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
204   - 'rev': ('django.db.models.fields.TextField', [], {'blank': 'True'})
205   - },
206   - u'proxy.ticket': {
207   - 'Meta': {'object_name': 'Ticket', 'db_table': "'ticket_view'", 'managed': 'False'},
208   - 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
209   - 'collaborators': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
210   - 'component': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
211   - 'created': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
212   - 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
213   - 'id': ('django.db.models.fields.IntegerField', [], {'primary_key': 'True'}),
214   - 'keywords': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
215   - 'milestone': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
216   - 'modified': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
217   - 'modified_by': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
218   - 'priority': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
219   - 'reporter': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
220   - 'severity': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
221   - 'status': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
222   - 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
223   - 'version': ('django.db.models.fields.TextField', [], {'blank': 'True'})
224   - },
225   - u'proxy.ticketcollabcount': {
226   - 'Meta': {'object_name': 'TicketCollabCount', 'db_table': "'ticket_collab_count_view'", 'managed': 'False'},
227   - 'author': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}),
228   - 'count': ('django.db.models.fields.IntegerField', [], {})
229   - },
230   - u'proxy.wiki': {
231   - 'Meta': {'object_name': 'Wiki', 'db_table': "'wiki_view'", 'managed': 'False'},
232   - 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
233   - 'collaborators': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
234   - 'created': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
235   - 'modified': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
236   - 'modified_by': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
237   - 'name': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}),
238   - 'wiki_text': ('django.db.models.fields.TextField', [], {'blank': 'True'})
239   - },
240   - u'proxy.wikicollabcount': {
241   - 'Meta': {'object_name': 'WikiCollabCount', 'db_table': "'wiki_collab_count_view'", 'managed': 'False'},
242   - 'author': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}),
243   - 'count': ('django.db.models.fields.IntegerField', [], {})
244   - }
245   - }
246   -
247   - complete_apps = ['proxy']
248   - symmetrical = True
src/proxy/migrations/__init__.py
src/proxy/models.py
1 1 # -*- coding: utf-8 -*-
2   -
3   -import os
4   -import urllib2
5   -
  2 +from django.db import models
6 3 from django.conf import settings
7   -from django.db import models, connections
8   -from django.db.models.signals import post_save
9   -from django.dispatch import receiver
10   -
11   -from accounts.models import User
12   -from hitcounter.models import HitCounterModelMixin
13   -
14   -
15   -class Attachment(models.Model, HitCounterModelMixin):
16   - url = models.TextField(primary_key=True)
17   - attach_id = models.TextField()
18   - used_by = models.TextField()
19   - filename = models.TextField()
20   - author = models.TextField(blank=True)
21   - description = models.TextField(blank=True)
22   - created = models.DateTimeField(blank=True)
23   - mimetype = models.TextField(blank=True)
24   - size = models.IntegerField(blank=True)
25   -
26   - class Meta:
27   - managed = False
28   - db_table = 'attachment_view'
29   -
30   - @property
31   - def filepath(self):
32   - return os.path.join(
33   - settings.ATTACHMENTS_FOLDER_PATH,
34   - self.used_by,
35   - self.attach_id,
36   - urllib2.quote(self.filename.encode('utf8'))
37   - )
38   -
39   - def get_absolute_url(self):
40   - return u'/raw-attachment/{}'.format(self.url)
41   -
42   - def get_author(self):
43   - try:
44   - return User.objects.get(username=self.author)
45   - except User.DoesNotExist:
46   - return None
47   -
48   -
49   -class Revision(models.Model, HitCounterModelMixin):
50   - key = models.TextField(blank=True, primary_key=True)
51   - rev = models.TextField(blank=True)
52   - author = models.TextField(blank=True)
53   - message = models.TextField(blank=True)
54   - repository_name = models.TextField(blank=True)
55   - created = models.DateTimeField(blank=True, null=True)
56   -
57   - class Meta:
58   - managed = False
59   - db_table = 'revision_view'
60   -
61   - def get_absolute_url(self):
62   - return u'/changeset/{}/{}'.format(self.rev, self.repository_name)
63   -
64   - def get_author(self):
65   - try:
66   - return User.objects.get(username=self.author)
67   - except User.DoesNotExist:
68   - return None
69   -
70   -class Ticket(models.Model, HitCounterModelMixin):
71   - id = models.IntegerField(primary_key=True)
72   - summary = models.TextField(blank=True)
73   - description = models.TextField(blank=True)
74   - milestone = models.TextField(blank=True)
75   - priority = models.TextField(blank=True)
76   - component = models.TextField(blank=True)
77   - version = models.TextField(blank=True)
78   - severity = models.TextField(blank=True)
79   - reporter = models.TextField(blank=True)
80   - author = models.TextField(blank=True)
81   - status = models.TextField(blank=True)
82   - keywords = models.TextField(blank=True)
83   - collaborators = models.TextField(blank=True)
84   - created = models.DateTimeField(blank=True, null=True)
85   - modified = models.DateTimeField(blank=True, null=True)
86   - modified_by = models.TextField(blank=True)
87   -
88   - class Meta:
89   - managed = False
90   - db_table = 'ticket_view'
91   -
92   - def get_absolute_url(self):
93   - return u'/ticket/{}'.format(self.id)
94   -
95   - def get_author(self):
96   - try:
97   - return User.objects.get(username=self.author)
98   - except User.DoesNotExist:
99   - return None
100   -
101   - def get_modified_by(self):
102   - try:
103   - return User.objects.get(username=self.modified_by)
104   - except User.DoesNotExist:
105   - return None
106   -
107   -
108   -class Wiki(models.Model, HitCounterModelMixin):
109   - name = models.TextField(primary_key=True)
110   - wiki_text = models.TextField(blank=True)
111   - author = models.TextField(blank=True)
112   - collaborators = models.TextField(blank=True)
113   - created = models.DateTimeField(blank=True, null=True)
114   - modified = models.DateTimeField(blank=True, null=True)
115   - modified_by = models.TextField(blank=True)
116   -
117   - class Meta:
118   - managed = False
119   - db_table = 'wiki_view'
120   -
121   - def get_absolute_url(self):
122   - return u'/wiki/{}'.format(self.name)
123   -
124   - def get_author(self):
125   - try:
126   - return User.objects.get(username=self.author)
127   - except User.DoesNotExist:
128   - return None
129   -
130   - def get_modified_by(self):
131   - try:
132   - return User.objects.get(username=self.modified_by)
133   - except User.DoesNotExist:
134   - return None
135   -
136   -
137   -class WikiCollabCount(models.Model):
138   - author = models.TextField(primary_key=True)
139   - count = models.IntegerField()
140   -
141   - class Meta:
142   - managed = False
143   - db_table = 'wiki_collab_count_view'
144   -
145   -
146   -class TicketCollabCount(models.Model):
147   - author = models.TextField(primary_key=True)
148   - count = models.IntegerField()
149   -
150   - class Meta:
151   - managed = False
152   - db_table = 'ticket_collab_count_view'
153   -
154   -
155   -@receiver(post_save, sender=User)
156   -def change_session_attribute_email(sender, instance, **kwargs):
157   - cursor = connections['trac'].cursor()
158   -
159   - cursor.execute(("UPDATE session_attribute SET value=%s "
160   - "WHERE name='email' AND sid=%s"),
161   - [instance.email, instance.username])
162   - cursor.execute(("UPDATE session_attribute SET value=%s "
163   - "WHERE name='name' AND sid=%s"),
164   - [instance.get_full_name(), instance.username])
165   -
166   - cursor.execute(("INSERT INTO session_attribute "
167   - "(sid, authenticated, name, value) "
168   - "SELECT %s, '1', 'email', %s WHERE NOT EXISTS "
169   - "(SELECT 1 FROM session_attribute WHERE sid=%s "
170   - "AND name='email')"),
171   - [instance.username, instance.email, instance.username])
172 4  
173   - cursor.execute(("INSERT INTO session_attribute "
174   - "(sid, authenticated, name, value) "
175   - "SELECT %s, '1', 'name', %s WHERE NOT EXISTS "
176   - "(SELECT 1 FROM session_attribute WHERE sid=%s "
177   - "AND name='name')"),
178   - [instance.username, instance.get_full_name(),
179   - instance.username])
  5 +if settings.TRAC_ENABLED:
  6 + import trac.trac.models
... ...
src/proxy/search_indexes.py
... ... @@ -9,7 +9,7 @@ from haystack import indexes
9 9 from haystack.utils import log as logging
10 10  
11 11 from search.base_indexes import BaseIndex
12   -from .models import Attachment, Ticket, Wiki, Revision
  12 +from trac.models import Attachment, Ticket, Wiki, Revision
13 13  
14 14  
15 15 logger = logging.getLogger('haystack')
... ...
src/proxy/trac/__init__.py 0 → 100644
src/proxy/trac/admin.py 0 → 100644
... ... @@ -0,0 +1,3 @@
  1 +from django.contrib import admin
  2 +
  3 +# Register your models here.
... ...
src/proxy/trac/migrations/0001_initial.py 0 → 100644
... ... @@ -0,0 +1,248 @@
  1 +# -*- coding: utf-8 -*-
  2 +import datetime
  3 +from django.db import connections
  4 +from south.db import db
  5 +from south.v2 import SchemaMigration
  6 +from django.db import models
  7 +
  8 +
  9 +class Migration(SchemaMigration):
  10 +
  11 + def forwards(self, orm):
  12 + connection = connections['trac']
  13 +
  14 + cursor = connection.cursor()
  15 + cursor.execute('''
  16 + CREATE OR REPLACE VIEW wiki_view AS SELECT
  17 + wiki.name AS name,
  18 + (SELECT wiki2.text FROM wiki AS wiki2 WHERE wiki2.name = wiki.name
  19 + AND wiki2.version = MAX(wiki.version)) AS wiki_text,
  20 + (SELECT wiki3.author FROM wiki AS wiki3 WHERE wiki3.name = wiki.name
  21 + AND wiki3.version = 1) AS author,
  22 + string_agg(DISTINCT wiki.author, ', ') AS collaborators,
  23 + TIMESTAMP WITH TIME ZONE 'epoch' + (MAX(wiki.time)/1000000) * INTERVAL '1s' AS created,
  24 + TIMESTAMP WITH TIME ZONE 'epoch' + (MIN(wiki.time)/1000000) * INTERVAL '1s' AS modified
  25 + FROM wiki
  26 + GROUP BY wiki.name;
  27 +
  28 + CREATE OR REPLACE VIEW ticket_view AS SELECT
  29 + ticket.id AS id,
  30 + ticket.summary as summary,
  31 + ticket.description as description,
  32 + ticket.milestone as milestone,
  33 + ticket.priority as priority,
  34 + ticket.component as component,
  35 + ticket.version as version,
  36 + ticket.severity as severity,
  37 + ticket.reporter as reporter,
  38 + ticket.reporter as author,
  39 + ticket.status as status,
  40 + ticket.keywords as keywords,
  41 + (SELECT
  42 + string_agg(DISTINCT ticket_change.author, ', ')
  43 + FROM ticket_change WHERE ticket_change.ticket = ticket.id
  44 + GROUP BY ticket_change.ticket) as collaborators,
  45 + TIMESTAMP WITH TIME ZONE 'epoch' + (time/1000000)* INTERVAL '1s' AS created,
  46 + TIMESTAMP WITH TIME ZONE 'epoch' + (changetime/1000000) * INTERVAL '1s' AS modified
  47 + FROM ticket;
  48 +
  49 + CREATE OR REPLACE VIEW revision_view AS SELECT
  50 + revision.rev,
  51 + revision.author,
  52 + revision.message,
  53 + repository.value AS repository_name,
  54 + TIMESTAMP WITH TIME ZONE 'epoch' + (revision.time/1000000) * INTERVAL '1s' AS created
  55 + FROM revision
  56 + INNER JOIN repository ON(
  57 + repository.id = revision.repos
  58 + AND repository.name = 'name'
  59 + AND repository.value != ''
  60 + );
  61 + ''')
  62 + cursor.execute('''
  63 +CREATE OR REPLACE VIEW revision_view AS SELECT
  64 +revision.rev,
  65 +revision.author,
  66 +revision.message,
  67 +repository.value AS repository_name,
  68 +TIMESTAMP WITH TIME ZONE 'epoch' + (revision.time/1000000) * INTERVAL '1s' AS created,
  69 +CONCAT(revision.repos, '-', revision.rev) AS key
  70 +FROM revision
  71 +INNER JOIN repository ON(
  72 +repository.id = revision.repos
  73 +AND repository.name = 'name'
  74 +AND repository.value != ''
  75 +);
  76 +''')
  77 + cursor.execute('''
  78 +CREATE OR REPLACE VIEW attachment_view AS SELECT
  79 +CONCAT(attachment.type, '/' , attachment.id, '/', attachment.filename) AS url,
  80 +attachment.type AS used_by,
  81 +attachment.filename AS filename,
  82 +attachment.id as attach_id,
  83 +(SELECT LOWER(SUBSTRING(attachment.filename FROM '\.(\w+)$'))) AS mimetype,
  84 +attachment.author AS author,
  85 +attachment.description AS description,
  86 +attachment.size AS size,
  87 +TIMESTAMP WITH TIME ZONE 'epoch' + (attachment.time/1000000)* INTERVAL '1s' AS created
  88 +FROM attachment;
  89 +''')
  90 + cursor.execute('''
  91 +CREATE OR REPLACE VIEW wiki_view AS SELECT
  92 +wiki.name AS name,
  93 +(SELECT wiki2.text FROM wiki AS wiki2 WHERE wiki2.name = wiki.name
  94 +AND wiki2.version = MAX(wiki.version)) AS wiki_text,
  95 +(SELECT wiki3.author FROM wiki AS wiki3 WHERE wiki3.name = wiki.name
  96 +AND wiki3.version = 1) AS author,
  97 +string_agg(DISTINCT wiki.author, ', ') AS collaborators,
  98 +TIMESTAMP WITH TIME ZONE 'epoch' + (MIN(wiki.time)/1000000) * INTERVAL '1s' AS created,
  99 +TIMESTAMP WITH TIME ZONE 'epoch' + (MAX(wiki.time)/1000000) * INTERVAL '1s' AS modified
  100 +FROM wiki
  101 +GROUP BY wiki.name;
  102 +''')
  103 + cursor.execute('''
  104 +CREATE OR REPLACE VIEW wiki_view AS SELECT
  105 +wiki.name AS name,
  106 +(SELECT wiki2.text FROM wiki AS wiki2 WHERE wiki2.name = wiki.name
  107 +AND wiki2.version = MAX(wiki.version)) AS wiki_text,
  108 +(SELECT wiki3.author FROM wiki AS wiki3 WHERE wiki3.name = wiki.name
  109 +AND wiki3.version = 1) AS author,
  110 +string_agg(DISTINCT wiki.author, ', ') AS collaborators,
  111 +TIMESTAMP WITH TIME ZONE 'epoch' + (MIN(wiki.time)/1000000) * INTERVAL '1s' AS created,
  112 +TIMESTAMP WITH TIME ZONE 'epoch' + (MAX(wiki.time)/1000000) * INTERVAL '1s' AS modified,
  113 +(SELECT wiki4.author FROM wiki AS wiki4 WHERE wiki4.name = wiki.name
  114 +AND wiki4.version = MAX(wiki.version)) AS modified_by
  115 +FROM wiki
  116 +GROUP BY wiki.name;
  117 +
  118 +CREATE OR REPLACE VIEW ticket_view AS SELECT
  119 +ticket.id AS id,
  120 +ticket.summary as summary,
  121 +ticket.description as description,
  122 +ticket.milestone as milestone,
  123 +ticket.priority as priority,
  124 +ticket.component as component,
  125 +ticket.version as version,
  126 +ticket.severity as severity,
  127 +ticket.reporter as reporter,
  128 +ticket.reporter as author,
  129 +ticket.status as status,
  130 +ticket.keywords as keywords,
  131 +(SELECT
  132 +string_agg(DISTINCT ticket_change.author, ', ')
  133 +FROM ticket_change WHERE ticket_change.ticket = ticket.id
  134 +GROUP BY ticket_change.ticket) as collaborators,
  135 +TIMESTAMP WITH TIME ZONE 'epoch' + (time/1000000)* INTERVAL '1s' AS created,
  136 +TIMESTAMP WITH TIME ZONE 'epoch' + (changetime/1000000) * INTERVAL '1s' AS modified,
  137 +(SELECT
  138 +ticket_change.author
  139 +FROM ticket_change
  140 +WHERE ticket_change.ticket = ticket.id
  141 +AND ticket_change.time = ticket.changetime
  142 +LIMIT 1
  143 +) AS modified_by
  144 +FROM ticket;
  145 +''')
  146 + cursor.execute('''
  147 +CREATE OR REPLACE VIEW ticket_collab_count_view AS
  148 +SELECT
  149 +COALESCE (t1.author, t2.author) as author,
  150 +(COALESCE(t1.count, 0) + COALESCE(t2.count, 0)) as count
  151 +FROM
  152 +(SELECT author, count(*) as count
  153 +FROM ticket_change
  154 +GROUP BY author
  155 +ORDER BY author
  156 +) AS t1
  157 +FULL OUTER JOIN
  158 +(SELECT reporter as author, count(*) as count
  159 +FROM ticket
  160 +GROUP BY reporter
  161 +ORDER BY reporter
  162 +) AS t2
  163 +ON t1.author = t2.author;
  164 +
  165 +CREATE OR REPLACE VIEW wiki_collab_count_view AS
  166 +SELECT author, count(*) from wiki GROUP BY author;
  167 +''')
  168 +
  169 + pass
  170 +
  171 + def backwards(self, orm):
  172 + connection = connections['trac']
  173 +
  174 + cursor = connection.cursor()
  175 + cursor.execute('''
  176 +DROP VIEW IF EXISTS revision_view;
  177 +DROP VIEW IF EXISTS ticket_view;
  178 +DROP VIEW IF EXISTS wiki_view;
  179 +''')
  180 + cursor.execute('DROP VIEW IF EXISTS attachment_view;')
  181 +
  182 + pass
  183 +
  184 + models = {
  185 + u'proxy.attachment': {
  186 + 'Meta': {'object_name': 'Attachment', 'db_table': "'attachment_view'", 'managed': 'False'},
  187 + 'attach_id': ('django.db.models.fields.TextField', [], {}),
  188 + 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  189 + 'created': ('django.db.models.fields.DateTimeField', [], {'blank': 'True'}),
  190 + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  191 + 'filename': ('django.db.models.fields.TextField', [], {}),
  192 + 'mimetype': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  193 + 'size': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}),
  194 + 'url': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}),
  195 + 'used_by': ('django.db.models.fields.TextField', [], {})
  196 + },
  197 + u'proxy.revision': {
  198 + 'Meta': {'object_name': 'Revision', 'db_table': "'revision_view'", 'managed': 'False'},
  199 + 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  200 + 'created': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
  201 + 'key': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}),
  202 + 'message': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  203 + 'repository_name': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  204 + 'rev': ('django.db.models.fields.TextField', [], {'blank': 'True'})
  205 + },
  206 + u'proxy.ticket': {
  207 + 'Meta': {'object_name': 'Ticket', 'db_table': "'ticket_view'", 'managed': 'False'},
  208 + 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  209 + 'collaborators': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  210 + 'component': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  211 + 'created': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
  212 + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  213 + 'id': ('django.db.models.fields.IntegerField', [], {'primary_key': 'True'}),
  214 + 'keywords': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  215 + 'milestone': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  216 + 'modified': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
  217 + 'modified_by': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  218 + 'priority': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  219 + 'reporter': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  220 + 'severity': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  221 + 'status': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  222 + 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  223 + 'version': ('django.db.models.fields.TextField', [], {'blank': 'True'})
  224 + },
  225 + u'proxy.ticketcollabcount': {
  226 + 'Meta': {'object_name': 'TicketCollabCount', 'db_table': "'ticket_collab_count_view'", 'managed': 'False'},
  227 + 'author': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}),
  228 + 'count': ('django.db.models.fields.IntegerField', [], {})
  229 + },
  230 + u'proxy.wiki': {
  231 + 'Meta': {'object_name': 'Wiki', 'db_table': "'wiki_view'", 'managed': 'False'},
  232 + 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  233 + 'collaborators': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  234 + 'created': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
  235 + 'modified': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
  236 + 'modified_by': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  237 + 'name': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}),
  238 + 'wiki_text': ('django.db.models.fields.TextField', [], {'blank': 'True'})
  239 + },
  240 + u'proxy.wikicollabcount': {
  241 + 'Meta': {'object_name': 'WikiCollabCount', 'db_table': "'wiki_collab_count_view'", 'managed': 'False'},
  242 + 'author': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}),
  243 + 'count': ('django.db.models.fields.IntegerField', [], {})
  244 + }
  245 + }
  246 +
  247 + complete_apps = ['proxy']
  248 + symmetrical = True
... ...
src/proxy/trac/migrations/__init__.py 0 → 100644
src/proxy/trac/models.py 0 → 100644
... ... @@ -0,0 +1,178 @@
  1 +# -*- coding: utf-8 -*-
  2 +
  3 +import os
  4 +import urllib2
  5 +
  6 +from django.conf import settings
  7 +from django.db import models, connections
  8 +from django.db.models.signals import post_save
  9 +from django.dispatch import receiver
  10 +
  11 +from accounts.models import User
  12 +from hitcounter.models import HitCounterModelMixin
  13 +
  14 +
  15 +class Attachment(models.Model, HitCounterModelMixin):
  16 + url = models.TextField(primary_key=True)
  17 + attach_id = models.TextField()
  18 + used_by = models.TextField()
  19 + filename = models.TextField()
  20 + author = models.TextField(blank=True)
  21 + description = models.TextField(blank=True)
  22 + created = models.DateTimeField(blank=True)
  23 + mimetype = models.TextField(blank=True)
  24 + size = models.IntegerField(blank=True)
  25 +
  26 + class Meta:
  27 + managed = False
  28 + db_table = 'attachment_view'
  29 +
  30 + @property
  31 + def filepath(self):
  32 + return os.path.join(
  33 + settings.ATTACHMENTS_FOLDER_PATH,
  34 + self.used_by,
  35 + self.attach_id,
  36 + urllib2.quote(self.filename.encode('utf8'))
  37 + )
  38 +
  39 + def get_absolute_url(self):
  40 + return u'/raw-attachment/{}'.format(self.url)
  41 +
  42 + def get_author(self):
  43 + try:
  44 + return User.objects.get(username=self.author)
  45 + except User.DoesNotExist:
  46 + return None
  47 +
  48 +
  49 +class Revision(models.Model, HitCounterModelMixin):
  50 + key = models.TextField(blank=True, primary_key=True)
  51 + rev = models.TextField(blank=True)
  52 + author = models.TextField(blank=True)
  53 + message = models.TextField(blank=True)
  54 + repository_name = models.TextField(blank=True)
  55 + created = models.DateTimeField(blank=True, null=True)
  56 +
  57 + class Meta:
  58 + managed = False
  59 + db_table = 'revision_view'
  60 +
  61 + def get_absolute_url(self):
  62 + return u'/changeset/{}/{}'.format(self.rev, self.repository_name)
  63 +
  64 + def get_author(self):
  65 + try:
  66 + return User.objects.get(username=self.author)
  67 + except User.DoesNotExist:
  68 + return None
  69 +
  70 +class Ticket(models.Model, HitCounterModelMixin):
  71 + id = models.IntegerField(primary_key=True)
  72 + summary = models.TextField(blank=True)
  73 + description = models.TextField(blank=True)
  74 + milestone = models.TextField(blank=True)
  75 + priority = models.TextField(blank=True)
  76 + component = models.TextField(blank=True)
  77 + version = models.TextField(blank=True)
  78 + severity = models.TextField(blank=True)
  79 + reporter = models.TextField(blank=True)
  80 + author = models.TextField(blank=True)
  81 + status = models.TextField(blank=True)
  82 + keywords = models.TextField(blank=True)
  83 + collaborators = models.TextField(blank=True)
  84 + created = models.DateTimeField(blank=True, null=True)
  85 + modified = models.DateTimeField(blank=True, null=True)
  86 + modified_by = models.TextField(blank=True)
  87 +
  88 + class Meta:
  89 + managed = False
  90 + db_table = 'ticket_view'
  91 +
  92 + def get_absolute_url(self):
  93 + return u'/ticket/{}'.format(self.id)
  94 +
  95 + def get_author(self):
  96 + try:
  97 + return User.objects.get(username=self.author)
  98 + except User.DoesNotExist:
  99 + return None
  100 +
  101 + def get_modified_by(self):
  102 + try:
  103 + return User.objects.get(username=self.modified_by)
  104 + except User.DoesNotExist:
  105 + return None
  106 +
  107 +class Wiki(models.Model, HitCounterModelMixin):
  108 + name = models.TextField(primary_key=True)
  109 + wiki_text = models.TextField(blank=True)
  110 + author = models.TextField(blank=True)
  111 + collaborators = models.TextField(blank=True)
  112 + created = models.DateTimeField(blank=True, null=True)
  113 + modified = models.DateTimeField(blank=True, null=True)
  114 + modified_by = models.TextField(blank=True)
  115 +
  116 + class Meta:
  117 + managed = False
  118 + db_table = 'wiki_view'
  119 +
  120 + def get_absolute_url(self):
  121 + return u'/wiki/{}'.format(self.name)
  122 +
  123 + def get_author(self):
  124 + try:
  125 + return User.objects.get(username=self.author)
  126 + except User.DoesNotExist:
  127 + return None
  128 +
  129 + def get_modified_by(self):
  130 + try:
  131 + return User.objects.get(username=self.modified_by)
  132 + except User.DoesNotExist:
  133 + return None
  134 +
  135 +
  136 +class WikiCollabCount(models.Model):
  137 + author = models.TextField(primary_key=True)
  138 + count = models.IntegerField()
  139 +
  140 + class Meta:
  141 + managed = False
  142 + db_table = 'wiki_collab_count_view'
  143 +
  144 +
  145 +class TicketCollabCount(models.Model):
  146 + author = models.TextField(primary_key=True)
  147 + count = models.IntegerField()
  148 +
  149 + class Meta:
  150 + managed = False
  151 + db_table = 'ticket_collab_count_view'
  152 +
  153 +
  154 +@receiver(post_save, sender=User)
  155 +def change_session_attribute_email(sender, instance, **kwargs):
  156 + cursor = connections['trac'].cursor()
  157 +
  158 + cursor.execute(("UPDATE session_attribute SET value=%s "
  159 + "WHERE name='email' AND sid=%s"),
  160 + [instance.email, instance.username])
  161 + cursor.execute(("UPDATE session_attribute SET value=%s "
  162 + "WHERE name='name' AND sid=%s"),
  163 + [instance.get_full_name(), instance.username])
  164 +
  165 + cursor.execute(("INSERT INTO session_attribute "
  166 + "(sid, authenticated, name, value) "
  167 + "SELECT %s, '1', 'email', %s WHERE NOT EXISTS "
  168 + "(SELECT 1 FROM session_attribute WHERE sid=%s "
  169 + "AND name='email')"),
  170 + [instance.username, instance.email, instance.username])
  171 +
  172 + cursor.execute(("INSERT INTO session_attribute "
  173 + "(sid, authenticated, name, value) "
  174 + "SELECT %s, '1', 'name', %s WHERE NOT EXISTS "
  175 + "(SELECT 1 FROM session_attribute WHERE sid=%s "
  176 + "AND name='name')"),
  177 + [instance.username, instance.get_full_name(),
  178 + instance.username])
... ...
src/proxy/trac/tests.py 0 → 100644
... ... @@ -0,0 +1,3 @@
  1 +from django.test import TestCase
  2 +
  3 +# Create your tests here.
... ...
src/proxy/trac/views.py 0 → 100644
... ... @@ -0,0 +1,3 @@
  1 +from django.shortcuts import render
  2 +
  3 +# Create your views here.
... ...
src/proxy/views.py
... ... @@ -4,7 +4,7 @@ import os
4 4 from django.conf import settings
5 5  
6 6 from revproxy.views import ProxyView
7   -from .models import Wiki, Ticket, Revision
  7 +from trac.models import Wiki, Ticket, Revision
8 8 from hitcounter.views import HitCounterViewMixin
9 9  
10 10  
... ...
src/search/views.py
... ... @@ -5,7 +5,7 @@ from django.utils.translation import ugettext as _
5 5  
6 6 from haystack.views import SearchView
7 7  
8   -from proxy.models import Attachment
  8 +from proxy.trac.models import Attachment
9 9  
10 10  
11 11 class ColabSearchView(SearchView):
... ...