Skip to content

Commit

Permalink
#31 New Github Settings screen
Browse files Browse the repository at this point in the history
  • Loading branch information
tonylampada committed Oct 14, 2012
1 parent 5b76aaf commit 599fec5
Show file tree
Hide file tree
Showing 19 changed files with 366 additions and 14 deletions.
7 changes: 7 additions & 0 deletions djangoproject/core/models.py
Expand Up @@ -72,6 +72,12 @@ def getUserInfo(self):
def getSocialAuths(self):
return UserSocialAuth.objects.filter(user=self)

def github_username(self):
for social_auth in self.getSocialAuths():
if social_auth.provider == 'github' and social_auth.extra_data.has_key('social_username'):
return social_auth.extra_data['social_username']
return None

def getOffers(self):
return Offer.objects.filter(sponsor=self).order_by('status','-price')

Expand Down Expand Up @@ -129,6 +135,7 @@ def getStats(self):
User.gravatar_url_big = gravatar_url_big
User.getUserInfo = getUserInfo
User.getSocialAuths = getSocialAuths
User.github_username = github_username
User.getOffers = getOffers
User.getSolutions = getSolutions
User.getStats = getStats
Expand Down
1 change: 0 additions & 1 deletion djangoproject/core/tests/test_watch_views.py
@@ -1,4 +1,3 @@
from core.models import *
from django.utils import unittest
from core.services import watch_services
from helpers import test_data, email_asserts
Expand Down
2 changes: 1 addition & 1 deletion djangoproject/coverage.sh
Expand Up @@ -2,7 +2,7 @@
# Coverage utility script

coverage -e
coverage -x manage.py test core --settings=frespo.test_settings
coverage -x manage.py test core gh_frespo_integration --settings=frespo.test_settings
coverage -r -m > report.xml
rm -Rf coverage_html_report
coverage html '--include=core/*' '--omit=core/migrations/*'
8 changes: 1 addition & 7 deletions djangoproject/frespo/urls.py
@@ -1,23 +1,17 @@
from django.conf.urls import patterns, include, url
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
# Uncomment the next two lines to enable the admin:
from django.contrib import admin
import registration

admin.autodiscover()

urlpatterns = patterns('',
# Examples:
url(r'^$', 'core.views.main_views.home', name='home'),
# url(r'^frespo/', include('frespo.foo.urls')),
url(r'^core/', include('core.urls')),

url(r'^github/', include('gh_frespo_integration.urls')),
url(r'^bladmin/doc/', include('django.contrib.admindocs.urls')),

url(r'^bladmin/', include(admin.site.urls)),

url(r'^accounts/', include('registration.backends.default.urls')),

url(r'', include('social_auth.urls')),
url(r'', include('emailmgr.urls')),
)
Expand Down
20 changes: 20 additions & 0 deletions djangoproject/gh_frespo_integration/migrations/0001_initial.py
@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models


class Migration(SchemaMigration):

def forwards(self, orm):
pass

def backwards(self, orm):
pass

models = {

}

complete_apps = ['gh_frespo_integration']
@@ -0,0 +1,118 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models


class Migration(SchemaMigration):

def forwards(self, orm):
# Adding model 'IssueAlreadyCommented'
db.create_table('gh_frespo_integration_issuealreadycommented', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('repo', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['gh_frespo_integration.Repo'])),
('number', self.gf('django.db.models.fields.IntegerField')()),
))
db.send_create_signal('gh_frespo_integration', ['IssueAlreadyCommented'])

# Adding model 'Repo'
db.create_table('gh_frespo_integration_repo', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('owner', self.gf('django.db.models.fields.CharField')(max_length=256)),
('owner_type', self.gf('django.db.models.fields.CharField')(max_length=32)),
('name', self.gf('django.db.models.fields.CharField')(max_length=256)),
('gh_id', self.gf('django.db.models.fields.CharField')(max_length=32)),
('createdByUser', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])),
('creationDate', self.gf('django.db.models.fields.DateTimeField')()),
))
db.send_create_signal('gh_frespo_integration', ['Repo'])

# Adding model 'UserRepoConfig'
db.create_table('gh_frespo_integration_userrepoconfig', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])),
('repo', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['gh_frespo_integration.Repo'])),
('add_links', self.gf('django.db.models.fields.BooleanField')(default=False)),
('new_only', self.gf('django.db.models.fields.BooleanField')(default=False)),
('creationDate', self.gf('django.db.models.fields.DateTimeField')()),
))
db.send_create_signal('gh_frespo_integration', ['UserRepoConfig'])


def backwards(self, orm):
# Deleting model 'IssueAlreadyCommented'
db.delete_table('gh_frespo_integration_issuealreadycommented')

# Deleting model 'Repo'
db.delete_table('gh_frespo_integration_repo')

# Deleting model 'UserRepoConfig'
db.delete_table('gh_frespo_integration_userrepoconfig')


models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'gh_frespo_integration.issuealreadycommented': {
'Meta': {'object_name': 'IssueAlreadyCommented'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'number': ('django.db.models.fields.IntegerField', [], {}),
'repo': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['gh_frespo_integration.Repo']"})
},
'gh_frespo_integration.repo': {
'Meta': {'object_name': 'Repo'},
'createdByUser': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
'creationDate': ('django.db.models.fields.DateTimeField', [], {}),
'gh_id': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '256'}),
'owner': ('django.db.models.fields.CharField', [], {'max_length': '256'}),
'owner_type': ('django.db.models.fields.CharField', [], {'max_length': '32'})
},
'gh_frespo_integration.userrepoconfig': {
'Meta': {'object_name': 'UserRepoConfig'},
'add_links': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'creationDate': ('django.db.models.fields.DateTimeField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'new_only': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'repo': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['gh_frespo_integration.Repo']"}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
}
}

complete_apps = ['gh_frespo_integration']
Empty file.
46 changes: 46 additions & 0 deletions djangoproject/gh_frespo_integration/models.py
@@ -0,0 +1,46 @@
from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone

class Repo(models.Model):
owner = models.CharField(max_length=256)
owner_type = models.CharField(max_length=32)
name = models.CharField(max_length=256)
gh_id = models.CharField(max_length=32)
createdByUser = models.ForeignKey(User)
creationDate = models.DateTimeField()

USER = "USER"
ORG = "ORG"

@classmethod
def newRepo(cls, owner, owner_type, name, gh_id, createdByUser):
repo = cls()
repo.owner = owner
repo.owner_type = owner_type
repo.name = name
repo.gh_id = gh_id
repo.createdByUser = createdByUser
repo.creationDate = timezone.now()
return repo

class UserRepoConfig(models.Model):
user = models.ForeignKey(User)
repo = models.ForeignKey(Repo)
add_links = models.BooleanField()
new_only = models.BooleanField()
creationDate = models.DateTimeField()

@classmethod
def newConfig(cls, user, repo):
config = cls()
config.user = user
config.repo = repo
config.add_links = False
config.new_only = False
config.creationDate = timezone.now()
return config

class IssueAlreadyCommented(models.Model):
repo = models.ForeignKey(Repo)
number = models.IntegerField()
1 change: 1 addition & 0 deletions djangoproject/gh_frespo_integration/services/__init__.py
@@ -0,0 +1 @@
__author__ = 'tony'
63 changes: 63 additions & 0 deletions djangoproject/gh_frespo_integration/services/github_services.py
@@ -0,0 +1,63 @@
from gh_frespo_integration.utils import github_adapter
from gh_frespo_integration.models import *
import logging

__author__ = 'tony'

logger = logging.getLogger(__name__)

def get_repos_and_configs(user):
repos = []
github_username = user.github_username()
if github_username:
repos = github_adapter.fetch_repos(github_username)
for repo_dict in repos:
gh_id = repo_dict['id']
repodb = get_repodb_by_githubid(gh_id)
if repodb:
user_repo_config = get_repo_config_by_repo_and_user(repodb, user)
if user_repo_config:
repo_dict['add_links'] = user_repo_config.add_links
repo_dict['new_only'] = user_repo_config.new_only
return repos

def get_repodb_by_githubid(gh_id):
repos = Repo.objects.filter(gh_id = gh_id)
if repos.count() > 1:
logger.error('Database inconsistency: multiple repos found with gh_id:%s'%gh_id)
elif repos.count() == 1:
return repos[0]
else:
return None

def get_repo_config_by_repo_and_user(repo, user):
configs = UserRepoConfig.objects.filter(repo__id = repo.id, user__id = user.id)
if configs.count() > 1:
logger.error('Database inconsistency: multiple configs found for repo:%s / user:%s'%(repo.id, user.id))
elif configs.count() == 1:
return configs[0]
else:
return None

def update_user_configs(user, dict):
github_username = user.github_username()
if github_username:
repos = github_adapter.fetch_repos(github_username)
my_repo_ids = []
for repo_dict in repos:
gh_id = repo_dict['id']
repodb = get_repodb_by_githubid(gh_id)
if not repodb:
owner = repo_dict['owner']['login']
owner_type = repo_dict['owner']['type']
name = repo_dict['name']
repodb = Repo.newRepo(owner, owner_type, name, gh_id, user)
repodb.save()
config = get_repo_config_by_repo_and_user(repodb, user)
if not config:
config = UserRepoConfig.newConfig(user, repodb)
config.add_links = dict.has_key('check_addlink_%s' % gh_id)
config.new_only = dict.has_key('check_newonly_%s' % gh_id)
config.save()
my_repo_ids.append(gh_id)
UserRepoConfig.objects.filter(user__id = user.id).exclude(repo__gh_id__in = my_repo_ids).delete()
2 changes: 1 addition & 1 deletion djangoproject/gh_frespo_integration/tests/__init__.py
@@ -1 +1 @@
from test_github_adapter import *
from test_github_adapter import *
9 changes: 9 additions & 0 deletions djangoproject/gh_frespo_integration/urls.py
@@ -0,0 +1,9 @@
from django.conf.urls import patterns, include, url
from django.views.generic import TemplateView
from django.conf import settings

urlpatterns = patterns('gh_frespo_integration.views.main_views',
url(r'^configure/$', 'configure'),
url(r'^configure/submit/$', 'configure_submit'),
)

8 changes: 5 additions & 3 deletions djangoproject/gh_frespo_integration/utils/github_adapter.py
@@ -1,10 +1,8 @@
import httplib2
from urlparse import urlparse
import re
from xml.dom.minidom import parseString
import json
import requests
from django.conf import settings
from gh_frespo_integration.models import *

BOT_AUTH = (settings.GITHUB_BOT_USERNAME, settings.GITHUB_BOT_PASSWORD)

Expand All @@ -22,9 +20,13 @@ def _fetch_json_objects_from_url(h, url):
def fetch_repos(username):
h = httplib2.Http(disable_ssl_certificate_validation=True)
repos = _fetch_json_objects_from_url(h, "https://api.github.com/users/%s/repos"%username)
for repo in repos:
repo['owner']['type'] = Repo.USER
orgs = _fetch_json_objects_from_url(h, "https://api.github.com/users/%s/orgs"%username)
for org in orgs:
org_repos = _fetch_json_objects_from_url(h,"https://api.github.com/orgs/%s/repos"%org['login'])
for repo in org_repos:
repo['owner']['type'] = Repo.ORG
repos.extend(org_repos)
return repos

Expand Down
Empty file.
18 changes: 18 additions & 0 deletions djangoproject/gh_frespo_integration/views/main_views.py
@@ -0,0 +1,18 @@
from django.template import RequestContext
from django.shortcuts import render_to_response, redirect
from gh_frespo_integration.services import github_services
from django.contrib.auth.decorators import login_required

@login_required
def configure(request):
repos = github_services.get_repos_and_configs(request.user)
return render_to_response('github/configure.html',
{"repos" : repos},
context_instance = RequestContext(request))

@login_required
def configure_submit(request):
github_services.update_user_configs(request.user, request.POST)
return redirect('/github/configure')


2 changes: 2 additions & 0 deletions djangoproject/migrate.sh
@@ -1,2 +1,4 @@
./manage.py migrate core
./manage.py migrate emailmgr
./manage.py migrate gh_frespo_integration

4 changes: 4 additions & 0 deletions djangoproject/templates/core/navbar.html
Expand Up @@ -23,6 +23,10 @@
{% if user and user.is_authenticated %}
<li class="divider"></li>
<li><a href="/core/myissues">My issues</a></li>
{% if user.github_username %}
<li class="divider"></li>
<li><a href="/github/configure">Github Settings</a></li>
{% endif %}
{% endif %}
<li class="divider"></li>
<li><a href="/core/logout">Sign Out</a></li>
Expand Down

0 comments on commit 599fec5

Please sign in to comment.