From 1e7861daedeaa731a40e293d6ab64ee7cf7dc5a6 Mon Sep 17 00:00:00 2001 From: Gust Date: Fri, 1 Aug 2014 17:16:18 -0300 Subject: [PATCH] Separeted trac migration from colab --- src/accounts/search_indexes.py | 2 +- src/accounts/views.py | 2 +- src/api/resources.py | 2 +- src/badger/utils.py | 2 +- src/colab/custom_settings.py | 3 +++ src/home/views.py | 16 +++++++++------- src/proxy/migrations/0001_initial.py | 248 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- src/proxy/migrations/__init__.py | 0 src/proxy/models.py | 179 +++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- src/proxy/search_indexes.py | 2 +- src/proxy/trac/__init__.py | 0 src/proxy/trac/admin.py | 3 +++ src/proxy/trac/migrations/0001_initial.py | 248 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/proxy/trac/migrations/__init__.py | 0 src/proxy/trac/models.py | 178 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/proxy/trac/tests.py | 3 +++ src/proxy/trac/views.py | 3 +++ src/proxy/views.py | 2 +- src/search/views.py | 2 +- 19 files changed, 457 insertions(+), 438 deletions(-) delete mode 100644 src/proxy/migrations/0001_initial.py delete mode 100644 src/proxy/migrations/__init__.py create mode 100644 src/proxy/trac/__init__.py create mode 100644 src/proxy/trac/admin.py create mode 100644 src/proxy/trac/migrations/0001_initial.py create mode 100644 src/proxy/trac/migrations/__init__.py create mode 100644 src/proxy/trac/models.py create mode 100644 src/proxy/trac/tests.py create mode 100644 src/proxy/trac/views.py diff --git a/src/accounts/search_indexes.py b/src/accounts/search_indexes.py index 9700310..5315713 100644 --- a/src/accounts/search_indexes.py +++ b/src/accounts/search_indexes.py @@ -3,7 +3,7 @@ from haystack import indexes from django.db.models import Count -from proxy.models import Revision, Ticket, Wiki +from proxy.trac.models import Revision, Ticket, Wiki from badger.utils import get_users_counters from .models import User diff --git a/src/accounts/views.py b/src/accounts/views.py index 7745da7..c8a250c 100644 --- a/src/accounts/views.py +++ b/src/accounts/views.py @@ -25,7 +25,7 @@ from haystack.query import SearchQuerySet from super_archives.models import EmailAddress, Message from super_archives.utils.email import send_email_lists from search.utils import trans -from proxy.models import WikiCollabCount, TicketCollabCount +from proxy.trac.models import WikiCollabCount, TicketCollabCount from .forms import (UserCreationForm, ListsForm, UserUpdateForm, ChangeXMPPPasswordForm) from .errors import XMPPChangePwdException diff --git a/src/api/resources.py b/src/api/resources.py index 9395432..002f983 100644 --- a/src/api/resources.py +++ b/src/api/resources.py @@ -7,7 +7,7 @@ from tastypie.constants import ALL_WITH_RELATIONS, ALL from tastypie.resources import ModelResource from super_archives.models import Message, EmailAddress -from proxy.models import Revision, Ticket, Wiki +from proxy.trac.models import Revision, Ticket, Wiki User = get_user_model() diff --git a/src/badger/utils.py b/src/badger/utils.py index dd3f70f..94ac88f 100644 --- a/src/badger/utils.py +++ b/src/badger/utils.py @@ -2,7 +2,7 @@ from django.db.models import Count -from proxy.models import (Revision, Ticket, Wiki, +from proxy.trac.models import (Revision, Ticket, Wiki, WikiCollabCount, TicketCollabCount) from accounts.models import User diff --git a/src/colab/custom_settings.py b/src/colab/custom_settings.py index b308a9a..fe91bb7 100644 --- a/src/colab/custom_settings.py +++ b/src/colab/custom_settings.py @@ -262,6 +262,9 @@ TRAC_ENABLED = False if TRAC_ENABLED: from trac_settings import * DATABASES['trac'] = TRAC_DATABASE + INSTALLED_APPS = INSTALLED_APPS + ( + 'proxy.trac', + ) ### Feedzilla (planet) diff --git a/src/home/views.py b/src/home/views.py index 5ff89cf..ef0c3d3 100644 --- a/src/home/views.py +++ b/src/home/views.py @@ -9,7 +9,7 @@ from django.http import HttpResponse, Http404 from search.utils import trans from haystack.query import SearchQuerySet -from proxy.models import WikiCollabCount, TicketCollabCount +from proxy.trac.models import WikiCollabCount, TicketCollabCount from super_archives.models import Thread @@ -28,13 +28,15 @@ def index(request): type=type, ).count() - count_types['ticket'] = sum([ - ticket.count for ticket in TicketCollabCount.objects.all() - ]) + if settings.TRAC_ENABLED: + count_types['ticket'] = sum([ + ticket.count for ticket in TicketCollabCount.objects.all() + ]) - count_types['wiki'] = sum([ - wiki.count for wiki in WikiCollabCount.objects.all() - ]) + count_types['wiki'] = sum([ + wiki.count for wiki in WikiCollabCount.objects.all() + ]) + cache.set('home_chart', count_types) for key in count_types.keys(): diff --git a/src/proxy/migrations/0001_initial.py b/src/proxy/migrations/0001_initial.py deleted file mode 100644 index 6b2355f..0000000 --- a/src/proxy/migrations/0001_initial.py +++ /dev/null @@ -1,248 +0,0 @@ -# -*- coding: utf-8 -*- -import datetime -from django.db import connections -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - - -class Migration(SchemaMigration): - - def forwards(self, orm): - connection = connections['trac'] - - cursor = connection.cursor() - cursor.execute(''' - CREATE OR REPLACE VIEW wiki_view AS SELECT - wiki.name AS name, - (SELECT wiki2.text FROM wiki AS wiki2 WHERE wiki2.name = wiki.name - AND wiki2.version = MAX(wiki.version)) AS wiki_text, - (SELECT wiki3.author FROM wiki AS wiki3 WHERE wiki3.name = wiki.name - AND wiki3.version = 1) AS author, - string_agg(DISTINCT wiki.author, ', ') AS collaborators, - TIMESTAMP WITH TIME ZONE 'epoch' + (MAX(wiki.time)/1000000) * INTERVAL '1s' AS created, - TIMESTAMP WITH TIME ZONE 'epoch' + (MIN(wiki.time)/1000000) * INTERVAL '1s' AS modified - FROM wiki - GROUP BY wiki.name; - - CREATE OR REPLACE VIEW ticket_view AS SELECT - ticket.id AS id, - ticket.summary as summary, - ticket.description as description, - ticket.milestone as milestone, - ticket.priority as priority, - ticket.component as component, - ticket.version as version, - ticket.severity as severity, - ticket.reporter as reporter, - ticket.reporter as author, - ticket.status as status, - ticket.keywords as keywords, - (SELECT - string_agg(DISTINCT ticket_change.author, ', ') - FROM ticket_change WHERE ticket_change.ticket = ticket.id - GROUP BY ticket_change.ticket) as collaborators, - TIMESTAMP WITH TIME ZONE 'epoch' + (time/1000000)* INTERVAL '1s' AS created, - TIMESTAMP WITH TIME ZONE 'epoch' + (changetime/1000000) * INTERVAL '1s' AS modified - FROM ticket; - - CREATE OR REPLACE VIEW revision_view AS SELECT - revision.rev, - revision.author, - revision.message, - repository.value AS repository_name, - TIMESTAMP WITH TIME ZONE 'epoch' + (revision.time/1000000) * INTERVAL '1s' AS created - FROM revision - INNER JOIN repository ON( - repository.id = revision.repos - AND repository.name = 'name' - AND repository.value != '' - ); - ''') - cursor.execute(''' -CREATE OR REPLACE VIEW revision_view AS SELECT -revision.rev, -revision.author, -revision.message, -repository.value AS repository_name, -TIMESTAMP WITH TIME ZONE 'epoch' + (revision.time/1000000) * INTERVAL '1s' AS created, -CONCAT(revision.repos, '-', revision.rev) AS key -FROM revision -INNER JOIN repository ON( -repository.id = revision.repos -AND repository.name = 'name' -AND repository.value != '' -); -''') - cursor.execute(''' -CREATE OR REPLACE VIEW attachment_view AS SELECT -CONCAT(attachment.type, '/' , attachment.id, '/', attachment.filename) AS url, -attachment.type AS used_by, -attachment.filename AS filename, -attachment.id as attach_id, -(SELECT LOWER(SUBSTRING(attachment.filename FROM '\.(\w+)$'))) AS mimetype, -attachment.author AS author, -attachment.description AS description, -attachment.size AS size, -TIMESTAMP WITH TIME ZONE 'epoch' + (attachment.time/1000000)* INTERVAL '1s' AS created -FROM attachment; -''') - cursor.execute(''' -CREATE OR REPLACE VIEW wiki_view AS SELECT -wiki.name AS name, -(SELECT wiki2.text FROM wiki AS wiki2 WHERE wiki2.name = wiki.name -AND wiki2.version = MAX(wiki.version)) AS wiki_text, -(SELECT wiki3.author FROM wiki AS wiki3 WHERE wiki3.name = wiki.name -AND wiki3.version = 1) AS author, -string_agg(DISTINCT wiki.author, ', ') AS collaborators, -TIMESTAMP WITH TIME ZONE 'epoch' + (MIN(wiki.time)/1000000) * INTERVAL '1s' AS created, -TIMESTAMP WITH TIME ZONE 'epoch' + (MAX(wiki.time)/1000000) * INTERVAL '1s' AS modified -FROM wiki -GROUP BY wiki.name; -''') - cursor.execute(''' -CREATE OR REPLACE VIEW wiki_view AS SELECT -wiki.name AS name, -(SELECT wiki2.text FROM wiki AS wiki2 WHERE wiki2.name = wiki.name -AND wiki2.version = MAX(wiki.version)) AS wiki_text, -(SELECT wiki3.author FROM wiki AS wiki3 WHERE wiki3.name = wiki.name -AND wiki3.version = 1) AS author, -string_agg(DISTINCT wiki.author, ', ') AS collaborators, -TIMESTAMP WITH TIME ZONE 'epoch' + (MIN(wiki.time)/1000000) * INTERVAL '1s' AS created, -TIMESTAMP WITH TIME ZONE 'epoch' + (MAX(wiki.time)/1000000) * INTERVAL '1s' AS modified, -(SELECT wiki4.author FROM wiki AS wiki4 WHERE wiki4.name = wiki.name -AND wiki4.version = MAX(wiki.version)) AS modified_by -FROM wiki -GROUP BY wiki.name; - -CREATE OR REPLACE VIEW ticket_view AS SELECT -ticket.id AS id, -ticket.summary as summary, -ticket.description as description, -ticket.milestone as milestone, -ticket.priority as priority, -ticket.component as component, -ticket.version as version, -ticket.severity as severity, -ticket.reporter as reporter, -ticket.reporter as author, -ticket.status as status, -ticket.keywords as keywords, -(SELECT -string_agg(DISTINCT ticket_change.author, ', ') -FROM ticket_change WHERE ticket_change.ticket = ticket.id -GROUP BY ticket_change.ticket) as collaborators, -TIMESTAMP WITH TIME ZONE 'epoch' + (time/1000000)* INTERVAL '1s' AS created, -TIMESTAMP WITH TIME ZONE 'epoch' + (changetime/1000000) * INTERVAL '1s' AS modified, -(SELECT -ticket_change.author -FROM ticket_change -WHERE ticket_change.ticket = ticket.id -AND ticket_change.time = ticket.changetime -LIMIT 1 -) AS modified_by -FROM ticket; -''') - cursor.execute(''' -CREATE OR REPLACE VIEW ticket_collab_count_view AS -SELECT -COALESCE (t1.author, t2.author) as author, -(COALESCE(t1.count, 0) + COALESCE(t2.count, 0)) as count -FROM -(SELECT author, count(*) as count -FROM ticket_change -GROUP BY author -ORDER BY author -) AS t1 -FULL OUTER JOIN -(SELECT reporter as author, count(*) as count -FROM ticket -GROUP BY reporter -ORDER BY reporter -) AS t2 -ON t1.author = t2.author; - -CREATE OR REPLACE VIEW wiki_collab_count_view AS -SELECT author, count(*) from wiki GROUP BY author; -''') - - pass - - def backwards(self, orm): - connection = connections['trac'] - - cursor = connection.cursor() - cursor.execute(''' -DROP VIEW IF EXISTS revision_view; -DROP VIEW IF EXISTS ticket_view; -DROP VIEW IF EXISTS wiki_view; -''') - cursor.execute('DROP VIEW IF EXISTS attachment_view;') - - pass - - models = { - u'proxy.attachment': { - 'Meta': {'object_name': 'Attachment', 'db_table': "'attachment_view'", 'managed': 'False'}, - 'attach_id': ('django.db.models.fields.TextField', [], {}), - 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'created': ('django.db.models.fields.DateTimeField', [], {'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'filename': ('django.db.models.fields.TextField', [], {}), - 'mimetype': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'size': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}), - 'url': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}), - 'used_by': ('django.db.models.fields.TextField', [], {}) - }, - u'proxy.revision': { - 'Meta': {'object_name': 'Revision', 'db_table': "'revision_view'", 'managed': 'False'}, - 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'created': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'key': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}), - 'message': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'repository_name': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'rev': ('django.db.models.fields.TextField', [], {'blank': 'True'}) - }, - u'proxy.ticket': { - 'Meta': {'object_name': 'Ticket', 'db_table': "'ticket_view'", 'managed': 'False'}, - 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'collaborators': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'component': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'created': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'id': ('django.db.models.fields.IntegerField', [], {'primary_key': 'True'}), - 'keywords': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'milestone': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'modified': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'modified_by': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'priority': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'reporter': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'severity': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'status': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'version': ('django.db.models.fields.TextField', [], {'blank': 'True'}) - }, - u'proxy.ticketcollabcount': { - 'Meta': {'object_name': 'TicketCollabCount', 'db_table': "'ticket_collab_count_view'", 'managed': 'False'}, - 'author': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}), - 'count': ('django.db.models.fields.IntegerField', [], {}) - }, - u'proxy.wiki': { - 'Meta': {'object_name': 'Wiki', 'db_table': "'wiki_view'", 'managed': 'False'}, - 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'collaborators': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'created': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'modified': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), - 'modified_by': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'name': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}), - 'wiki_text': ('django.db.models.fields.TextField', [], {'blank': 'True'}) - }, - u'proxy.wikicollabcount': { - 'Meta': {'object_name': 'WikiCollabCount', 'db_table': "'wiki_collab_count_view'", 'managed': 'False'}, - 'author': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}), - 'count': ('django.db.models.fields.IntegerField', [], {}) - } - } - - complete_apps = ['proxy'] - symmetrical = True diff --git a/src/proxy/migrations/__init__.py b/src/proxy/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/src/proxy/migrations/__init__.py +++ /dev/null diff --git a/src/proxy/models.py b/src/proxy/models.py index 5d4ef3d..20a46b0 100644 --- a/src/proxy/models.py +++ b/src/proxy/models.py @@ -1,179 +1,6 @@ # -*- coding: utf-8 -*- - -import os -import urllib2 - +from django.db import models from django.conf import settings -from django.db import models, connections -from django.db.models.signals import post_save -from django.dispatch import receiver - -from accounts.models import User -from hitcounter.models import HitCounterModelMixin - - -class Attachment(models.Model, HitCounterModelMixin): - url = models.TextField(primary_key=True) - attach_id = models.TextField() - used_by = models.TextField() - filename = models.TextField() - author = models.TextField(blank=True) - description = models.TextField(blank=True) - created = models.DateTimeField(blank=True) - mimetype = models.TextField(blank=True) - size = models.IntegerField(blank=True) - - class Meta: - managed = False - db_table = 'attachment_view' - - @property - def filepath(self): - return os.path.join( - settings.ATTACHMENTS_FOLDER_PATH, - self.used_by, - self.attach_id, - urllib2.quote(self.filename.encode('utf8')) - ) - - def get_absolute_url(self): - return u'/raw-attachment/{}'.format(self.url) - - def get_author(self): - try: - return User.objects.get(username=self.author) - except User.DoesNotExist: - return None - - -class Revision(models.Model, HitCounterModelMixin): - key = models.TextField(blank=True, primary_key=True) - rev = models.TextField(blank=True) - author = models.TextField(blank=True) - message = models.TextField(blank=True) - repository_name = models.TextField(blank=True) - created = models.DateTimeField(blank=True, null=True) - - class Meta: - managed = False - db_table = 'revision_view' - - def get_absolute_url(self): - return u'/changeset/{}/{}'.format(self.rev, self.repository_name) - - def get_author(self): - try: - return User.objects.get(username=self.author) - except User.DoesNotExist: - return None - -class Ticket(models.Model, HitCounterModelMixin): - id = models.IntegerField(primary_key=True) - summary = models.TextField(blank=True) - description = models.TextField(blank=True) - milestone = models.TextField(blank=True) - priority = models.TextField(blank=True) - component = models.TextField(blank=True) - version = models.TextField(blank=True) - severity = models.TextField(blank=True) - reporter = models.TextField(blank=True) - author = models.TextField(blank=True) - status = models.TextField(blank=True) - keywords = models.TextField(blank=True) - collaborators = models.TextField(blank=True) - created = models.DateTimeField(blank=True, null=True) - modified = models.DateTimeField(blank=True, null=True) - modified_by = models.TextField(blank=True) - - class Meta: - managed = False - db_table = 'ticket_view' - - def get_absolute_url(self): - return u'/ticket/{}'.format(self.id) - - def get_author(self): - try: - return User.objects.get(username=self.author) - except User.DoesNotExist: - return None - - def get_modified_by(self): - try: - return User.objects.get(username=self.modified_by) - except User.DoesNotExist: - return None - - -class Wiki(models.Model, HitCounterModelMixin): - name = models.TextField(primary_key=True) - wiki_text = models.TextField(blank=True) - author = models.TextField(blank=True) - collaborators = models.TextField(blank=True) - created = models.DateTimeField(blank=True, null=True) - modified = models.DateTimeField(blank=True, null=True) - modified_by = models.TextField(blank=True) - - class Meta: - managed = False - db_table = 'wiki_view' - - def get_absolute_url(self): - return u'/wiki/{}'.format(self.name) - - def get_author(self): - try: - return User.objects.get(username=self.author) - except User.DoesNotExist: - return None - - def get_modified_by(self): - try: - return User.objects.get(username=self.modified_by) - except User.DoesNotExist: - return None - - -class WikiCollabCount(models.Model): - author = models.TextField(primary_key=True) - count = models.IntegerField() - - class Meta: - managed = False - db_table = 'wiki_collab_count_view' - - -class TicketCollabCount(models.Model): - author = models.TextField(primary_key=True) - count = models.IntegerField() - - class Meta: - managed = False - db_table = 'ticket_collab_count_view' - - -@receiver(post_save, sender=User) -def change_session_attribute_email(sender, instance, **kwargs): - cursor = connections['trac'].cursor() - - cursor.execute(("UPDATE session_attribute SET value=%s " - "WHERE name='email' AND sid=%s"), - [instance.email, instance.username]) - cursor.execute(("UPDATE session_attribute SET value=%s " - "WHERE name='name' AND sid=%s"), - [instance.get_full_name(), instance.username]) - - cursor.execute(("INSERT INTO session_attribute " - "(sid, authenticated, name, value) " - "SELECT %s, '1', 'email', %s WHERE NOT EXISTS " - "(SELECT 1 FROM session_attribute WHERE sid=%s " - "AND name='email')"), - [instance.username, instance.email, instance.username]) - cursor.execute(("INSERT INTO session_attribute " - "(sid, authenticated, name, value) " - "SELECT %s, '1', 'name', %s WHERE NOT EXISTS " - "(SELECT 1 FROM session_attribute WHERE sid=%s " - "AND name='name')"), - [instance.username, instance.get_full_name(), - instance.username]) +if settings.TRAC_ENABLED: + import trac.trac.models diff --git a/src/proxy/search_indexes.py b/src/proxy/search_indexes.py index c7c413f..088fc5b 100644 --- a/src/proxy/search_indexes.py +++ b/src/proxy/search_indexes.py @@ -9,7 +9,7 @@ from haystack import indexes from haystack.utils import log as logging from search.base_indexes import BaseIndex -from .models import Attachment, Ticket, Wiki, Revision +from trac.models import Attachment, Ticket, Wiki, Revision logger = logging.getLogger('haystack') diff --git a/src/proxy/trac/__init__.py b/src/proxy/trac/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/proxy/trac/__init__.py diff --git a/src/proxy/trac/admin.py b/src/proxy/trac/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/src/proxy/trac/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/src/proxy/trac/migrations/0001_initial.py b/src/proxy/trac/migrations/0001_initial.py new file mode 100644 index 0000000..6b2355f --- /dev/null +++ b/src/proxy/trac/migrations/0001_initial.py @@ -0,0 +1,248 @@ +# -*- coding: utf-8 -*- +import datetime +from django.db import connections +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + connection = connections['trac'] + + cursor = connection.cursor() + cursor.execute(''' + CREATE OR REPLACE VIEW wiki_view AS SELECT + wiki.name AS name, + (SELECT wiki2.text FROM wiki AS wiki2 WHERE wiki2.name = wiki.name + AND wiki2.version = MAX(wiki.version)) AS wiki_text, + (SELECT wiki3.author FROM wiki AS wiki3 WHERE wiki3.name = wiki.name + AND wiki3.version = 1) AS author, + string_agg(DISTINCT wiki.author, ', ') AS collaborators, + TIMESTAMP WITH TIME ZONE 'epoch' + (MAX(wiki.time)/1000000) * INTERVAL '1s' AS created, + TIMESTAMP WITH TIME ZONE 'epoch' + (MIN(wiki.time)/1000000) * INTERVAL '1s' AS modified + FROM wiki + GROUP BY wiki.name; + + CREATE OR REPLACE VIEW ticket_view AS SELECT + ticket.id AS id, + ticket.summary as summary, + ticket.description as description, + ticket.milestone as milestone, + ticket.priority as priority, + ticket.component as component, + ticket.version as version, + ticket.severity as severity, + ticket.reporter as reporter, + ticket.reporter as author, + ticket.status as status, + ticket.keywords as keywords, + (SELECT + string_agg(DISTINCT ticket_change.author, ', ') + FROM ticket_change WHERE ticket_change.ticket = ticket.id + GROUP BY ticket_change.ticket) as collaborators, + TIMESTAMP WITH TIME ZONE 'epoch' + (time/1000000)* INTERVAL '1s' AS created, + TIMESTAMP WITH TIME ZONE 'epoch' + (changetime/1000000) * INTERVAL '1s' AS modified + FROM ticket; + + CREATE OR REPLACE VIEW revision_view AS SELECT + revision.rev, + revision.author, + revision.message, + repository.value AS repository_name, + TIMESTAMP WITH TIME ZONE 'epoch' + (revision.time/1000000) * INTERVAL '1s' AS created + FROM revision + INNER JOIN repository ON( + repository.id = revision.repos + AND repository.name = 'name' + AND repository.value != '' + ); + ''') + cursor.execute(''' +CREATE OR REPLACE VIEW revision_view AS SELECT +revision.rev, +revision.author, +revision.message, +repository.value AS repository_name, +TIMESTAMP WITH TIME ZONE 'epoch' + (revision.time/1000000) * INTERVAL '1s' AS created, +CONCAT(revision.repos, '-', revision.rev) AS key +FROM revision +INNER JOIN repository ON( +repository.id = revision.repos +AND repository.name = 'name' +AND repository.value != '' +); +''') + cursor.execute(''' +CREATE OR REPLACE VIEW attachment_view AS SELECT +CONCAT(attachment.type, '/' , attachment.id, '/', attachment.filename) AS url, +attachment.type AS used_by, +attachment.filename AS filename, +attachment.id as attach_id, +(SELECT LOWER(SUBSTRING(attachment.filename FROM '\.(\w+)$'))) AS mimetype, +attachment.author AS author, +attachment.description AS description, +attachment.size AS size, +TIMESTAMP WITH TIME ZONE 'epoch' + (attachment.time/1000000)* INTERVAL '1s' AS created +FROM attachment; +''') + cursor.execute(''' +CREATE OR REPLACE VIEW wiki_view AS SELECT +wiki.name AS name, +(SELECT wiki2.text FROM wiki AS wiki2 WHERE wiki2.name = wiki.name +AND wiki2.version = MAX(wiki.version)) AS wiki_text, +(SELECT wiki3.author FROM wiki AS wiki3 WHERE wiki3.name = wiki.name +AND wiki3.version = 1) AS author, +string_agg(DISTINCT wiki.author, ', ') AS collaborators, +TIMESTAMP WITH TIME ZONE 'epoch' + (MIN(wiki.time)/1000000) * INTERVAL '1s' AS created, +TIMESTAMP WITH TIME ZONE 'epoch' + (MAX(wiki.time)/1000000) * INTERVAL '1s' AS modified +FROM wiki +GROUP BY wiki.name; +''') + cursor.execute(''' +CREATE OR REPLACE VIEW wiki_view AS SELECT +wiki.name AS name, +(SELECT wiki2.text FROM wiki AS wiki2 WHERE wiki2.name = wiki.name +AND wiki2.version = MAX(wiki.version)) AS wiki_text, +(SELECT wiki3.author FROM wiki AS wiki3 WHERE wiki3.name = wiki.name +AND wiki3.version = 1) AS author, +string_agg(DISTINCT wiki.author, ', ') AS collaborators, +TIMESTAMP WITH TIME ZONE 'epoch' + (MIN(wiki.time)/1000000) * INTERVAL '1s' AS created, +TIMESTAMP WITH TIME ZONE 'epoch' + (MAX(wiki.time)/1000000) * INTERVAL '1s' AS modified, +(SELECT wiki4.author FROM wiki AS wiki4 WHERE wiki4.name = wiki.name +AND wiki4.version = MAX(wiki.version)) AS modified_by +FROM wiki +GROUP BY wiki.name; + +CREATE OR REPLACE VIEW ticket_view AS SELECT +ticket.id AS id, +ticket.summary as summary, +ticket.description as description, +ticket.milestone as milestone, +ticket.priority as priority, +ticket.component as component, +ticket.version as version, +ticket.severity as severity, +ticket.reporter as reporter, +ticket.reporter as author, +ticket.status as status, +ticket.keywords as keywords, +(SELECT +string_agg(DISTINCT ticket_change.author, ', ') +FROM ticket_change WHERE ticket_change.ticket = ticket.id +GROUP BY ticket_change.ticket) as collaborators, +TIMESTAMP WITH TIME ZONE 'epoch' + (time/1000000)* INTERVAL '1s' AS created, +TIMESTAMP WITH TIME ZONE 'epoch' + (changetime/1000000) * INTERVAL '1s' AS modified, +(SELECT +ticket_change.author +FROM ticket_change +WHERE ticket_change.ticket = ticket.id +AND ticket_change.time = ticket.changetime +LIMIT 1 +) AS modified_by +FROM ticket; +''') + cursor.execute(''' +CREATE OR REPLACE VIEW ticket_collab_count_view AS +SELECT +COALESCE (t1.author, t2.author) as author, +(COALESCE(t1.count, 0) + COALESCE(t2.count, 0)) as count +FROM +(SELECT author, count(*) as count +FROM ticket_change +GROUP BY author +ORDER BY author +) AS t1 +FULL OUTER JOIN +(SELECT reporter as author, count(*) as count +FROM ticket +GROUP BY reporter +ORDER BY reporter +) AS t2 +ON t1.author = t2.author; + +CREATE OR REPLACE VIEW wiki_collab_count_view AS +SELECT author, count(*) from wiki GROUP BY author; +''') + + pass + + def backwards(self, orm): + connection = connections['trac'] + + cursor = connection.cursor() + cursor.execute(''' +DROP VIEW IF EXISTS revision_view; +DROP VIEW IF EXISTS ticket_view; +DROP VIEW IF EXISTS wiki_view; +''') + cursor.execute('DROP VIEW IF EXISTS attachment_view;') + + pass + + models = { + u'proxy.attachment': { + 'Meta': {'object_name': 'Attachment', 'db_table': "'attachment_view'", 'managed': 'False'}, + 'attach_id': ('django.db.models.fields.TextField', [], {}), + 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'filename': ('django.db.models.fields.TextField', [], {}), + 'mimetype': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'size': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}), + 'url': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}), + 'used_by': ('django.db.models.fields.TextField', [], {}) + }, + u'proxy.revision': { + 'Meta': {'object_name': 'Revision', 'db_table': "'revision_view'", 'managed': 'False'}, + 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'key': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}), + 'message': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'repository_name': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'rev': ('django.db.models.fields.TextField', [], {'blank': 'True'}) + }, + u'proxy.ticket': { + 'Meta': {'object_name': 'Ticket', 'db_table': "'ticket_view'", 'managed': 'False'}, + 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'collaborators': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'component': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'id': ('django.db.models.fields.IntegerField', [], {'primary_key': 'True'}), + 'keywords': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'milestone': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'modified_by': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'priority': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'reporter': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'severity': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'status': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'version': ('django.db.models.fields.TextField', [], {'blank': 'True'}) + }, + u'proxy.ticketcollabcount': { + 'Meta': {'object_name': 'TicketCollabCount', 'db_table': "'ticket_collab_count_view'", 'managed': 'False'}, + 'author': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}), + 'count': ('django.db.models.fields.IntegerField', [], {}) + }, + u'proxy.wiki': { + 'Meta': {'object_name': 'Wiki', 'db_table': "'wiki_view'", 'managed': 'False'}, + 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'collaborators': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'modified_by': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'name': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}), + 'wiki_text': ('django.db.models.fields.TextField', [], {'blank': 'True'}) + }, + u'proxy.wikicollabcount': { + 'Meta': {'object_name': 'WikiCollabCount', 'db_table': "'wiki_collab_count_view'", 'managed': 'False'}, + 'author': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}), + 'count': ('django.db.models.fields.IntegerField', [], {}) + } + } + + complete_apps = ['proxy'] + symmetrical = True diff --git a/src/proxy/trac/migrations/__init__.py b/src/proxy/trac/migrations/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/proxy/trac/migrations/__init__.py diff --git a/src/proxy/trac/models.py b/src/proxy/trac/models.py new file mode 100644 index 0000000..360a90d --- /dev/null +++ b/src/proxy/trac/models.py @@ -0,0 +1,178 @@ +# -*- coding: utf-8 -*- + +import os +import urllib2 + +from django.conf import settings +from django.db import models, connections +from django.db.models.signals import post_save +from django.dispatch import receiver + +from accounts.models import User +from hitcounter.models import HitCounterModelMixin + + +class Attachment(models.Model, HitCounterModelMixin): + url = models.TextField(primary_key=True) + attach_id = models.TextField() + used_by = models.TextField() + filename = models.TextField() + author = models.TextField(blank=True) + description = models.TextField(blank=True) + created = models.DateTimeField(blank=True) + mimetype = models.TextField(blank=True) + size = models.IntegerField(blank=True) + + class Meta: + managed = False + db_table = 'attachment_view' + + @property + def filepath(self): + return os.path.join( + settings.ATTACHMENTS_FOLDER_PATH, + self.used_by, + self.attach_id, + urllib2.quote(self.filename.encode('utf8')) + ) + + def get_absolute_url(self): + return u'/raw-attachment/{}'.format(self.url) + + def get_author(self): + try: + return User.objects.get(username=self.author) + except User.DoesNotExist: + return None + + +class Revision(models.Model, HitCounterModelMixin): + key = models.TextField(blank=True, primary_key=True) + rev = models.TextField(blank=True) + author = models.TextField(blank=True) + message = models.TextField(blank=True) + repository_name = models.TextField(blank=True) + created = models.DateTimeField(blank=True, null=True) + + class Meta: + managed = False + db_table = 'revision_view' + + def get_absolute_url(self): + return u'/changeset/{}/{}'.format(self.rev, self.repository_name) + + def get_author(self): + try: + return User.objects.get(username=self.author) + except User.DoesNotExist: + return None + +class Ticket(models.Model, HitCounterModelMixin): + id = models.IntegerField(primary_key=True) + summary = models.TextField(blank=True) + description = models.TextField(blank=True) + milestone = models.TextField(blank=True) + priority = models.TextField(blank=True) + component = models.TextField(blank=True) + version = models.TextField(blank=True) + severity = models.TextField(blank=True) + reporter = models.TextField(blank=True) + author = models.TextField(blank=True) + status = models.TextField(blank=True) + keywords = models.TextField(blank=True) + collaborators = models.TextField(blank=True) + created = models.DateTimeField(blank=True, null=True) + modified = models.DateTimeField(blank=True, null=True) + modified_by = models.TextField(blank=True) + + class Meta: + managed = False + db_table = 'ticket_view' + + def get_absolute_url(self): + return u'/ticket/{}'.format(self.id) + + def get_author(self): + try: + return User.objects.get(username=self.author) + except User.DoesNotExist: + return None + + def get_modified_by(self): + try: + return User.objects.get(username=self.modified_by) + except User.DoesNotExist: + return None + +class Wiki(models.Model, HitCounterModelMixin): + name = models.TextField(primary_key=True) + wiki_text = models.TextField(blank=True) + author = models.TextField(blank=True) + collaborators = models.TextField(blank=True) + created = models.DateTimeField(blank=True, null=True) + modified = models.DateTimeField(blank=True, null=True) + modified_by = models.TextField(blank=True) + + class Meta: + managed = False + db_table = 'wiki_view' + + def get_absolute_url(self): + return u'/wiki/{}'.format(self.name) + + def get_author(self): + try: + return User.objects.get(username=self.author) + except User.DoesNotExist: + return None + + def get_modified_by(self): + try: + return User.objects.get(username=self.modified_by) + except User.DoesNotExist: + return None + + +class WikiCollabCount(models.Model): + author = models.TextField(primary_key=True) + count = models.IntegerField() + + class Meta: + managed = False + db_table = 'wiki_collab_count_view' + + +class TicketCollabCount(models.Model): + author = models.TextField(primary_key=True) + count = models.IntegerField() + + class Meta: + managed = False + db_table = 'ticket_collab_count_view' + + +@receiver(post_save, sender=User) +def change_session_attribute_email(sender, instance, **kwargs): + cursor = connections['trac'].cursor() + + cursor.execute(("UPDATE session_attribute SET value=%s " + "WHERE name='email' AND sid=%s"), + [instance.email, instance.username]) + cursor.execute(("UPDATE session_attribute SET value=%s " + "WHERE name='name' AND sid=%s"), + [instance.get_full_name(), instance.username]) + + cursor.execute(("INSERT INTO session_attribute " + "(sid, authenticated, name, value) " + "SELECT %s, '1', 'email', %s WHERE NOT EXISTS " + "(SELECT 1 FROM session_attribute WHERE sid=%s " + "AND name='email')"), + [instance.username, instance.email, instance.username]) + + cursor.execute(("INSERT INTO session_attribute " + "(sid, authenticated, name, value) " + "SELECT %s, '1', 'name', %s WHERE NOT EXISTS " + "(SELECT 1 FROM session_attribute WHERE sid=%s " + "AND name='name')"), + [instance.username, instance.get_full_name(), + instance.username]) diff --git a/src/proxy/trac/tests.py b/src/proxy/trac/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/src/proxy/trac/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/src/proxy/trac/views.py b/src/proxy/trac/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/src/proxy/trac/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/src/proxy/views.py b/src/proxy/views.py index 56d864b..cdea939 100644 --- a/src/proxy/views.py +++ b/src/proxy/views.py @@ -4,7 +4,7 @@ import os from django.conf import settings from revproxy.views import ProxyView -from .models import Wiki, Ticket, Revision +from trac.models import Wiki, Ticket, Revision from hitcounter.views import HitCounterViewMixin diff --git a/src/search/views.py b/src/search/views.py index 41adf9f..da3b84f 100644 --- a/src/search/views.py +++ b/src/search/views.py @@ -5,7 +5,7 @@ from django.utils.translation import ugettext as _ from haystack.views import SearchView -from proxy.models import Attachment +from proxy.trac.models import Attachment class ColabSearchView(SearchView): -- libgit2 0.21.2