mirror of
https://github.com/nikdoof/test-auth.git
synced 2025-12-13 22:32:15 +00:00
Reorganise the file structure into a project tree
This commit is contained in:
0
app/sso/__init__.py
Normal file
0
app/sso/__init__.py
Normal file
39
app/sso/admin.py
Normal file
39
app/sso/admin.py
Normal file
@@ -0,0 +1,39 @@
|
||||
from django.contrib import admin
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.auth.admin import UserAdmin
|
||||
from sso.models import Service, ServiceAccount, SSOUser, SSOUserNote
|
||||
|
||||
|
||||
class ServiceAdmin(admin.ModelAdmin):
|
||||
list_display = ('name', 'url', 'api', 'active')
|
||||
search_fields = ['name']
|
||||
list_filter = ('active',)
|
||||
|
||||
|
||||
class ServiceAccountAdmin(admin.ModelAdmin):
|
||||
list_display = ('service', 'service_uid', 'user', 'active')
|
||||
search_fields = ['service_uid', 'user__username']
|
||||
list_filter = ('service', 'active')
|
||||
|
||||
|
||||
class SSOUserProfileInline(admin.StackedInline):
|
||||
model = SSOUser
|
||||
fk_name = 'user'
|
||||
max_num = 1
|
||||
|
||||
|
||||
# Define a new UserAdmin class
|
||||
class SSOUserAdmin(UserAdmin):
|
||||
inlines = [SSOUserProfileInline, ]
|
||||
|
||||
|
||||
class SSOUserNoteAdmin(admin.ModelAdmin):
|
||||
list_display = ('user', 'note', 'date_created', 'created_by')
|
||||
search_fields = ['user__username']
|
||||
|
||||
|
||||
admin.site.register(Service, ServiceAdmin)
|
||||
admin.site.register(ServiceAccount, ServiceAccountAdmin)
|
||||
admin.site.unregister(User)
|
||||
admin.site.register(User, SSOUserAdmin)
|
||||
admin.site.register(SSOUserNote, SSOUserNoteAdmin)
|
||||
27
app/sso/backends.py
Normal file
27
app/sso/backends.py
Normal file
@@ -0,0 +1,27 @@
|
||||
from django.contrib.auth.backends import ModelBackend
|
||||
from django.contrib.auth.models import User
|
||||
from hashlib import sha1
|
||||
|
||||
|
||||
class SimpleHashModelBackend(ModelBackend):
|
||||
|
||||
supports_anonymous_user = False
|
||||
supports_object_permissions = False
|
||||
supports_inactive_user = False
|
||||
|
||||
def authenticate(self, username=None, password=None):
|
||||
try:
|
||||
user = User.objects.get(username=username)
|
||||
except User.DoesNotExist:
|
||||
return None
|
||||
|
||||
if '$' in user.password:
|
||||
if user.check_password(password):
|
||||
user.password = sha1(password).hexdigest()
|
||||
user.save()
|
||||
return user
|
||||
else:
|
||||
if user.password == sha1(password).hexdigest():
|
||||
return user
|
||||
|
||||
return None
|
||||
110
app/sso/forms.py
Normal file
110
app/sso/forms.py
Normal file
@@ -0,0 +1,110 @@
|
||||
import re
|
||||
|
||||
from django import forms
|
||||
from django.contrib.auth.models import User
|
||||
from django.conf import settings
|
||||
|
||||
from utils import installed
|
||||
|
||||
from eve_api.models import EVEAccount, EVEPlayerCharacter, EVEPlayerCorporation
|
||||
from sso.models import ServiceAccount, Service
|
||||
from registration.forms import RegistrationForm
|
||||
|
||||
|
||||
class RegistrationFormUniqueEmailBlocked(RegistrationForm):
|
||||
"""
|
||||
Subclass of ``RegistrationForm`` which disallows registration from certain
|
||||
domains and also makes sure that the email address is unique in the DB
|
||||
"""
|
||||
|
||||
def clean_email(self):
|
||||
"""
|
||||
Check the supplied email address against a list of known free
|
||||
webmail domains.
|
||||
"""
|
||||
|
||||
if User.objects.filter(email__iexact=self.cleaned_data['email']):
|
||||
raise forms.ValidationError("This email address is already in use. Please supply a different email address.")
|
||||
return self.cleaned_data['email']
|
||||
|
||||
email_domain = self.cleaned_data['email'].split('@')[1]
|
||||
if email_domain in settings.BANNED_EMAIL_DOMAINS:
|
||||
raise forms.ValidationError("Your email provider (%s) is banned from registering, please use a different address.")
|
||||
return self.cleaned_data['email']
|
||||
|
||||
|
||||
def UserServiceAccountForm(user):
|
||||
""" Generate a Service Account form based on the user's permissions """
|
||||
|
||||
services = Service.objects.filter(groups__in=user.groups.all(), active=1).exclude(id__in=ServiceAccount.objects.filter(user=user).values('service')).distinct()
|
||||
chars = EVEPlayerCharacter.objects.filter(eveaccount__user=user)
|
||||
|
||||
class ServiceAccountForm(forms.Form):
|
||||
""" Service Account Form """
|
||||
|
||||
character = forms.ModelChoiceField(queryset=chars, required=True, empty_label=None)
|
||||
service = forms.ModelChoiceField(queryset=services, required=True, empty_label=None)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ServiceAccountForm, self).__init__(*args, **kwargs)
|
||||
if not settings.GENERATE_SERVICE_PASSWORD:
|
||||
self.password = forms.CharField(widget=forms.PasswordInput, label="Password")
|
||||
self.fields['password'] = self.password
|
||||
|
||||
def clean(self):
|
||||
|
||||
form_data = self.cleaned_data
|
||||
service = form_data.get('service')
|
||||
character = form_data.get('character')
|
||||
|
||||
if not service or not character:
|
||||
raise forms.ValidationError('Error while processing the form, please try again')
|
||||
|
||||
service_groups = service.groups.all()
|
||||
|
||||
# If the service's assigned groups are linked to corps, do a character/corp check
|
||||
if len(EVEPlayerCorporation.objects.filter(group__in=service_groups)):
|
||||
corp_group = character.corporation.group
|
||||
if character.corporation.alliance:
|
||||
alliance_group = character.corporation.alliance.group
|
||||
else:
|
||||
alliance_group = None
|
||||
|
||||
if not (corp_group in service_groups or alliance_group in service_groups):
|
||||
raise forms.ValidationError("%s is not in a corporation or alliance allowed to register for %s" % (self.cleaned_data['character'].name, self.cleaned_data['service']))
|
||||
|
||||
return self.cleaned_data
|
||||
|
||||
return ServiceAccountForm
|
||||
|
||||
|
||||
class ServiceAccountResetForm(forms.Form):
|
||||
""" Password reset form for Services """
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ServiceAccountResetForm, self).__init__(*args, **kwargs)
|
||||
if not settings.GENERATE_SERVICE_PASSWORD:
|
||||
self.password = forms.CharField(widget=forms.PasswordInput, label="Password")
|
||||
self.fields['password'] = self.password
|
||||
|
||||
|
||||
class UserLookupForm(forms.Form):
|
||||
""" User Lookup Form """
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(UserLookupForm, self).__init__(*args, **kwargs)
|
||||
choices = [(1, "Auth Username"),
|
||||
(2, "Character"),
|
||||
(4, "Email Address"),
|
||||
(5, "EVE API User ID"), ]
|
||||
if installed('reddit'):
|
||||
choices.append((3, "Reddit ID"))
|
||||
|
||||
self.fields['type'] = forms.ChoiceField(label=u'Search type', choices=choices)
|
||||
self.fields['username'] = forms.CharField(label=u'User ID', max_length=64)
|
||||
|
||||
|
||||
class APIPasswordForm(forms.Form):
|
||||
""" API Password reset form """
|
||||
|
||||
password = forms.CharField(widget=forms.PasswordInput, label="Password")
|
||||
52
app/sso/middleware.py
Normal file
52
app/sso/middleware.py
Normal file
@@ -0,0 +1,52 @@
|
||||
|
||||
class IGBMiddleware(object):
|
||||
"""
|
||||
Middleware to detect the EVE IGB
|
||||
"""
|
||||
|
||||
def process_request(self, request):
|
||||
|
||||
request.is_igb = False
|
||||
request.is_igb_trusted = False
|
||||
|
||||
header_map = [
|
||||
('HTTP_EVE_SERVERIP', 'eve_server_ip'),
|
||||
('HTTP_EVE_CHARNAME', 'eve_charname'),
|
||||
('HTTP_EVE_CHARID', 'eve_charid'),
|
||||
('HTTP_EVE_CORPNAME', 'eve_corpname'),
|
||||
('HTTP_EVE_CORPID', 'eve_corpid'),
|
||||
('HTTP_EVE_ALLIANCENAME', 'eve_alliancename'),
|
||||
('HTTP_EVE_ALLIANCEID', 'eve_allianceid'),
|
||||
('HTTP_EVE_REGIONNAME', 'eve_regionid'),
|
||||
('HTTP_EVE_CONSTELLATIONNAME', 'eve_constellationname'),
|
||||
('HTTP_EVE_SOLARSYSTEMNAME', 'eve_systemname'),
|
||||
('HTTP_EVE_STATIONNAME,' 'eve_stationname'),
|
||||
('HTTP_EVE_STATIONID,' 'eve_stationid'),
|
||||
('HTTP_EVE_CORPROLE,' 'eve_corprole'),
|
||||
]
|
||||
|
||||
if request.META.has_key('HTTP_EVE_TRUSTED'):
|
||||
request.is_igb = True
|
||||
if request.META.get('HTTP_EVE_TRUSTED') == 'Yes':
|
||||
request.is_igb_trusted = True
|
||||
|
||||
for header, map in header_map:
|
||||
if request.META.get(header, None):
|
||||
setattr(request, map, request.META.get(header, None))
|
||||
|
||||
|
||||
from sso.models import SSOUserIPAddress
|
||||
from datetime import datetime
|
||||
|
||||
class IPTrackingMiddleware(object):
|
||||
"""
|
||||
Middleware to track user's IPs and insert them into the database
|
||||
"""
|
||||
|
||||
def process_request(self, request):
|
||||
|
||||
if request.user and not request.user.is_anonymous():
|
||||
ip, created = SSOUserIPAddress.objects.get_or_create(user=request.user, ip_address=request.META['REMOTE_ADDR'])
|
||||
if not created:
|
||||
ip.last_seen = datetime.utcnow()
|
||||
ip.save()
|
||||
139
app/sso/migrations/0001_initial.py
Normal file
139
app/sso/migrations/0001_initial.py
Normal file
@@ -0,0 +1,139 @@
|
||||
# encoding: 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 'SSOUser'
|
||||
db.create_table('sso_ssouser', (
|
||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='profile', unique=True, to=orm['auth.User'])),
|
||||
('default_service_passwd', self.gf('django.db.models.fields.CharField')(max_length=200, blank=True)),
|
||||
('default_service_username', self.gf('django.db.models.fields.CharField')(max_length=200, blank=True)),
|
||||
('website', self.gf('django.db.models.fields.CharField')(max_length=200, blank=True)),
|
||||
('aim', self.gf('django.db.models.fields.CharField')(max_length=64, blank=True)),
|
||||
('msn', self.gf('django.db.models.fields.CharField')(max_length=200, blank=True)),
|
||||
('icq', self.gf('django.db.models.fields.CharField')(max_length=15, blank=True)),
|
||||
('xmpp', self.gf('django.db.models.fields.CharField')(max_length=200, blank=True)),
|
||||
))
|
||||
db.send_create_signal('sso', ['SSOUser'])
|
||||
|
||||
# Adding model 'Service'
|
||||
db.create_table('sso_service', (
|
||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
('name', self.gf('django.db.models.fields.CharField')(max_length=200)),
|
||||
('url', self.gf('django.db.models.fields.CharField')(max_length=200, blank=True)),
|
||||
('active', self.gf('django.db.models.fields.BooleanField')(default=True, blank=True)),
|
||||
('api', self.gf('django.db.models.fields.CharField')(max_length=200)),
|
||||
('settings_json', self.gf('jsonfield.fields.JSONField')(blank=True)),
|
||||
))
|
||||
db.send_create_signal('sso', ['Service'])
|
||||
|
||||
# Adding M2M table for field groups on 'Service'
|
||||
db.create_table('sso_service_groups', (
|
||||
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
|
||||
('service', models.ForeignKey(orm['sso.service'], null=False)),
|
||||
('group', models.ForeignKey(orm['auth.group'], null=False))
|
||||
))
|
||||
db.create_unique('sso_service_groups', ['service_id', 'group_id'])
|
||||
|
||||
# Adding model 'ServiceAccount'
|
||||
db.create_table('sso_serviceaccount', (
|
||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])),
|
||||
('service', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['sso.Service'])),
|
||||
('service_uid', self.gf('django.db.models.fields.CharField')(max_length=200)),
|
||||
('active', self.gf('django.db.models.fields.BooleanField')(default=True, blank=True)),
|
||||
))
|
||||
db.send_create_signal('sso', ['ServiceAccount'])
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
|
||||
# Deleting model 'SSOUser'
|
||||
db.delete_table('sso_ssouser')
|
||||
|
||||
# Deleting model 'Service'
|
||||
db.delete_table('sso_service')
|
||||
|
||||
# Removing M2M table for field groups on 'Service'
|
||||
db.delete_table('sso_service_groups')
|
||||
|
||||
# Deleting model 'ServiceAccount'
|
||||
db.delete_table('sso_serviceaccount')
|
||||
|
||||
|
||||
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': {'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', 'blank': 'True'}),
|
||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||
'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': {'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'})
|
||||
},
|
||||
'sso.service': {
|
||||
'Meta': {'object_name': 'Service'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
|
||||
'api': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
|
||||
'settings_json': ('jsonfield.fields.JSONField', [], {'blank': 'True'}),
|
||||
'url': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'})
|
||||
},
|
||||
'sso.serviceaccount': {
|
||||
'Meta': {'object_name': 'ServiceAccount'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'service': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sso.Service']"}),
|
||||
'service_uid': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
},
|
||||
'sso.ssouser': {
|
||||
'Meta': {'object_name': 'SSOUser'},
|
||||
'aim': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'default_service_passwd': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
|
||||
'default_service_username': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
|
||||
'icq': ('django.db.models.fields.CharField', [], {'max_length': '15', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'msn': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'profile'", 'unique': 'True', 'to': "orm['auth.User']"}),
|
||||
'website': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
|
||||
'xmpp': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['sso']
|
||||
@@ -0,0 +1,126 @@
|
||||
# encoding: 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):
|
||||
|
||||
# Deleting field 'SSOUser.website'
|
||||
db.delete_column('sso_ssouser', 'website')
|
||||
|
||||
# Deleting field 'SSOUser.xmpp'
|
||||
db.delete_column('sso_ssouser', 'xmpp')
|
||||
|
||||
# Deleting field 'SSOUser.default_service_username'
|
||||
db.delete_column('sso_ssouser', 'default_service_username')
|
||||
|
||||
# Deleting field 'SSOUser.aim'
|
||||
db.delete_column('sso_ssouser', 'aim')
|
||||
|
||||
# Deleting field 'SSOUser.msn'
|
||||
db.delete_column('sso_ssouser', 'msn')
|
||||
|
||||
# Deleting field 'SSOUser.default_service_passwd'
|
||||
db.delete_column('sso_ssouser', 'default_service_passwd')
|
||||
|
||||
# Deleting field 'SSOUser.icq'
|
||||
db.delete_column('sso_ssouser', 'icq')
|
||||
|
||||
# Adding field 'SSOUser.api_service_password'
|
||||
db.add_column('sso_ssouser', 'api_service_password', self.gf('django.db.models.fields.CharField')(default='', max_length=200, blank=True), keep_default=False)
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
|
||||
# Adding field 'SSOUser.website'
|
||||
db.add_column('sso_ssouser', 'website', self.gf('django.db.models.fields.CharField')(default='', max_length=200, blank=True), keep_default=False)
|
||||
|
||||
# Adding field 'SSOUser.xmpp'
|
||||
db.add_column('sso_ssouser', 'xmpp', self.gf('django.db.models.fields.CharField')(default='', max_length=200, blank=True), keep_default=False)
|
||||
|
||||
# Adding field 'SSOUser.default_service_username'
|
||||
db.add_column('sso_ssouser', 'default_service_username', self.gf('django.db.models.fields.CharField')(default='', max_length=200, blank=True), keep_default=False)
|
||||
|
||||
# Adding field 'SSOUser.aim'
|
||||
db.add_column('sso_ssouser', 'aim', self.gf('django.db.models.fields.CharField')(default='', max_length=64, blank=True), keep_default=False)
|
||||
|
||||
# Adding field 'SSOUser.msn'
|
||||
db.add_column('sso_ssouser', 'msn', self.gf('django.db.models.fields.CharField')(default='', max_length=200, blank=True), keep_default=False)
|
||||
|
||||
# Adding field 'SSOUser.default_service_passwd'
|
||||
db.add_column('sso_ssouser', 'default_service_passwd', self.gf('django.db.models.fields.CharField')(default='', max_length=200, blank=True), keep_default=False)
|
||||
|
||||
# Adding field 'SSOUser.icq'
|
||||
db.add_column('sso_ssouser', 'icq', self.gf('django.db.models.fields.CharField')(default='', max_length=15, blank=True), keep_default=False)
|
||||
|
||||
# Deleting field 'SSOUser.api_service_password'
|
||||
db.delete_column('sso_ssouser', 'api_service_password')
|
||||
|
||||
|
||||
models = {
|
||||
'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '80', 'unique': 'True'}),
|
||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
'auth.permission': {
|
||||
'Meta': {'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', 'blank': 'True'}),
|
||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||
'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', [], {'max_length': '30', 'unique': 'True'})
|
||||
},
|
||||
'contenttypes.contenttype': {
|
||||
'Meta': {'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'})
|
||||
},
|
||||
'sso.service': {
|
||||
'Meta': {'object_name': 'Service'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
|
||||
'api': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
|
||||
'settings_json': ('jsonfield.fields.JSONField', [], {'blank': 'True'}),
|
||||
'url': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'})
|
||||
},
|
||||
'sso.serviceaccount': {
|
||||
'Meta': {'object_name': 'ServiceAccount'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'service': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sso.Service']"}),
|
||||
'service_uid': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
},
|
||||
'sso.ssouser': {
|
||||
'Meta': {'object_name': 'SSOUser'},
|
||||
'api_service_password': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'profile'", 'unique': 'True', 'to': "orm['auth.User']"})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['sso']
|
||||
99
app/sso/migrations/0003_auto__add_ssousernote.py
Normal file
99
app/sso/migrations/0003_auto__add_ssousernote.py
Normal file
@@ -0,0 +1,99 @@
|
||||
# encoding: 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 'SSOUserNote'
|
||||
db.create_table('sso_ssousernote', (
|
||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='notes', to=orm['auth.User'])),
|
||||
('note', self.gf('django.db.models.fields.TextField')()),
|
||||
('created_by', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])),
|
||||
('date_created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
|
||||
))
|
||||
db.send_create_signal('sso', ['SSOUserNote'])
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
|
||||
# Deleting model 'SSOUserNote'
|
||||
db.delete_table('sso_ssousernote')
|
||||
|
||||
|
||||
models = {
|
||||
'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '80', 'unique': 'True'}),
|
||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
'auth.permission': {
|
||||
'Meta': {'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', 'blank': 'True'}),
|
||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||
'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', [], {'max_length': '30', 'unique': 'True'})
|
||||
},
|
||||
'contenttypes.contenttype': {
|
||||
'Meta': {'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'})
|
||||
},
|
||||
'sso.service': {
|
||||
'Meta': {'object_name': 'Service'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
|
||||
'api': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
|
||||
'settings_json': ('jsonfield.fields.JSONField', [], {'blank': 'True'}),
|
||||
'url': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'})
|
||||
},
|
||||
'sso.serviceaccount': {
|
||||
'Meta': {'object_name': 'ServiceAccount'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'service': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sso.Service']"}),
|
||||
'service_uid': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
},
|
||||
'sso.ssouser': {
|
||||
'Meta': {'object_name': 'SSOUser'},
|
||||
'api_service_password': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'profile'", 'unique': 'True', 'to': "orm['auth.User']"})
|
||||
},
|
||||
'sso.ssousernote': {
|
||||
'Meta': {'object_name': 'SSOUserNote'},
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
|
||||
'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'note': ('django.db.models.fields.TextField', [], {}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'notes'", 'to': "orm['auth.User']"})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['sso']
|
||||
@@ -0,0 +1,155 @@
|
||||
# encoding: 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 field 'ServiceAccount.character'
|
||||
db.add_column('sso_serviceaccount', 'character', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['eve_api.EVEPlayerCharacter'], null=True), keep_default=False)
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
|
||||
# Deleting field 'ServiceAccount.character'
|
||||
db.delete_column('sso_serviceaccount', 'character_id')
|
||||
|
||||
|
||||
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': {'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', 'blank': 'True'}),
|
||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||
'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': {'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'})
|
||||
},
|
||||
'eve_api.eveplayeralliance': {
|
||||
'Meta': {'object_name': 'EVEPlayerAlliance'},
|
||||
'api_last_updated': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'date_founded': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.Group']", 'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'member_count': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'ticker': ('django.db.models.fields.CharField', [], {'max_length': '15', 'blank': 'True'})
|
||||
},
|
||||
'eve_api.eveplayercharacter': {
|
||||
'Meta': {'object_name': 'EVEPlayerCharacter'},
|
||||
'api_last_updated': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'attrib_charisma': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'attrib_intelligence': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'attrib_memory': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'attrib_perception': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'attrib_willpower': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'balance': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'corporation': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['eve_api.EVEPlayerCorporation']", 'null': 'True', 'blank': 'True'}),
|
||||
'current_location_id': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'director': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||
'gender': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'last_logoff': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'race': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'roles': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['eve_api.EVEPlayerCharacterRole']", 'null': 'True', 'blank': 'True'}),
|
||||
'total_sp': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'eve_api.eveplayercharacterrole': {
|
||||
'Meta': {'object_name': 'EVEPlayerCharacterRole'},
|
||||
'api_last_updated': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'roleid': ('django.db.models.fields.CharField', [], {'max_length': '64'})
|
||||
},
|
||||
'eve_api.eveplayercorporation': {
|
||||
'Meta': {'object_name': 'EVEPlayerCorporation'},
|
||||
'alliance': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['eve_api.EVEPlayerAlliance']", 'null': 'True', 'blank': 'True'}),
|
||||
'alliance_join_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'api_last_updated': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'applications': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
|
||||
'ceo_character': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['eve_api.EVEPlayerCharacter']", 'null': 'True', 'blank': 'True'}),
|
||||
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.Group']", 'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'logo_color1': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'logo_color2': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'logo_color3': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'logo_graphic_id': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'logo_shape1': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'logo_shape2': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'logo_shape3': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'member_count': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
'shares': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'tax_rate': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'ticker': ('django.db.models.fields.CharField', [], {'max_length': '15', 'null': 'True', 'blank': 'True'}),
|
||||
'url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'sso.service': {
|
||||
'Meta': {'object_name': 'Service'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
|
||||
'api': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
|
||||
'settings_json': ('jsonfield.fields.JSONField', [], {'default': '{}', 'blank': 'True'}),
|
||||
'url': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'})
|
||||
},
|
||||
'sso.serviceaccount': {
|
||||
'Meta': {'object_name': 'ServiceAccount'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
|
||||
'character': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['eve_api.EVEPlayerCharacter']", 'null': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'service': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sso.Service']"}),
|
||||
'service_uid': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
},
|
||||
'sso.ssouser': {
|
||||
'Meta': {'object_name': 'SSOUser'},
|
||||
'api_service_password': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'profile'", 'unique': 'True', 'to': "orm['auth.User']"})
|
||||
},
|
||||
'sso.ssousernote': {
|
||||
'Meta': {'object_name': 'SSOUserNote'},
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
|
||||
'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'note': ('django.db.models.fields.TextField', [], {}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'notes'", 'to': "orm['auth.User']"})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['sso']
|
||||
193
app/sso/migrations/0005_auto__add_ssouseripaddress.py
Normal file
193
app/sso/migrations/0005_auto__add_ssouseripaddress.py
Normal file
@@ -0,0 +1,193 @@
|
||||
# encoding: 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 'SSOUserIPAddress'
|
||||
db.create_table('sso_ssouseripaddress', (
|
||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
('first_seen', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
|
||||
('last_seen', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
|
||||
('ip_address', self.gf('django.db.models.fields.CharField')(max_length=200)),
|
||||
('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='ip_addresses', to=orm['auth.User'])),
|
||||
))
|
||||
db.send_create_signal('sso', ['SSOUserIPAddress'])
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
|
||||
# Deleting model 'SSOUserIPAddress'
|
||||
db.delete_table('sso_ssouseripaddress')
|
||||
|
||||
|
||||
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'})
|
||||
},
|
||||
'eve_api.eveplayeralliance': {
|
||||
'Meta': {'ordering': "['date_founded']", 'object_name': 'EVEPlayerAlliance'},
|
||||
'api_last_updated': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'date_founded': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'executor': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['eve_api.EVEPlayerCorporation']", 'null': 'True', 'blank': 'True'}),
|
||||
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.Group']", 'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'member_count': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'ticker': ('django.db.models.fields.CharField', [], {'max_length': '15', 'blank': 'True'})
|
||||
},
|
||||
'eve_api.eveplayercharacter': {
|
||||
'Meta': {'object_name': 'EVEPlayerCharacter'},
|
||||
'api_last_updated': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'attrib_charisma': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'attrib_intelligence': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'attrib_memory': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'attrib_perception': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'attrib_willpower': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'balance': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'corporation': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['eve_api.EVEPlayerCorporation']", 'null': 'True', 'blank': 'True'}),
|
||||
'corporation_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'current_location_id': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'director': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'gender': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'last_logoff': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'race': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'roles': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['eve_api.EVEPlayerCharacterRole']", 'null': 'True', 'blank': 'True'}),
|
||||
'security_status': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'skills': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['eve_api.EVESkill']", 'through': "orm['eve_api.EVEPlayerCharacterSkill']", 'symmetrical': 'False'}),
|
||||
'total_sp': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'eve_api.eveplayercharacterrole': {
|
||||
'Meta': {'object_name': 'EVEPlayerCharacterRole'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'roleid': ('django.db.models.fields.CharField', [], {'max_length': '64'})
|
||||
},
|
||||
'eve_api.eveplayercharacterskill': {
|
||||
'Meta': {'object_name': 'EVEPlayerCharacterSkill'},
|
||||
'character': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['eve_api.EVEPlayerCharacter']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'skill': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['eve_api.EVESkill']"}),
|
||||
'skillpoints': ('django.db.models.fields.IntegerField', [], {'default': '0'})
|
||||
},
|
||||
'eve_api.eveplayercorporation': {
|
||||
'Meta': {'object_name': 'EVEPlayerCorporation'},
|
||||
'alliance': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['eve_api.EVEPlayerAlliance']", 'null': 'True', 'blank': 'True'}),
|
||||
'alliance_join_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'api_last_updated': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'applications': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'ceo_character': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['eve_api.EVEPlayerCharacter']", 'null': 'True', 'blank': 'True'}),
|
||||
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.Group']", 'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'logo_color1': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'logo_color2': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'logo_color3': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'logo_graphic_id': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'logo_shape1': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'logo_shape2': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'logo_shape3': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'member_count': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
'shares': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'tax_rate': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'ticker': ('django.db.models.fields.CharField', [], {'max_length': '15', 'null': 'True', 'blank': 'True'}),
|
||||
'url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'eve_api.eveskill': {
|
||||
'Meta': {'object_name': 'EVESkill'},
|
||||
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['eve_api.EVESkillGroup']", 'null': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'})
|
||||
},
|
||||
'eve_api.eveskillgroup': {
|
||||
'Meta': {'object_name': 'EVESkillGroup'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'})
|
||||
},
|
||||
'sso.service': {
|
||||
'Meta': {'ordering': "['id']", 'object_name': 'Service'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'api': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
|
||||
'settings_json': ('jsonfield.fields.JSONField', [], {'default': '{}', 'blank': 'True'}),
|
||||
'url': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'})
|
||||
},
|
||||
'sso.serviceaccount': {
|
||||
'Meta': {'ordering': "['user']", 'object_name': 'ServiceAccount'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'character': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['eve_api.EVEPlayerCharacter']", 'null': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'service': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sso.Service']"}),
|
||||
'service_uid': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
|
||||
},
|
||||
'sso.ssouser': {
|
||||
'Meta': {'object_name': 'SSOUser'},
|
||||
'api_service_password': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'profile'", 'unique': 'True', 'to': "orm['auth.User']"})
|
||||
},
|
||||
'sso.ssouseripaddress': {
|
||||
'Meta': {'ordering': "['user']", 'object_name': 'SSOUserIPAddress'},
|
||||
'first_seen': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'ip_address': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
|
||||
'last_seen': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ip_addresses'", 'to': "orm['auth.User']"})
|
||||
},
|
||||
'sso.ssousernote': {
|
||||
'Meta': {'ordering': "['date_created']", 'object_name': 'SSOUserNote'},
|
||||
'created_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
|
||||
'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'note': ('django.db.models.fields.TextField', [], {}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'notes'", 'to': "orm['auth.User']"})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['sso']
|
||||
0
app/sso/migrations/__init__.py
Normal file
0
app/sso/migrations/__init__.py
Normal file
186
app/sso/models.py
Normal file
186
app/sso/models.py
Normal file
@@ -0,0 +1,186 @@
|
||||
import re
|
||||
import unicodedata
|
||||
import logging
|
||||
import types
|
||||
|
||||
from django.db import models
|
||||
from django.db.models import signals
|
||||
from django.contrib.auth.models import User, UserManager, Group
|
||||
from django.utils import simplejson as json
|
||||
|
||||
from jsonfield.fields import JSONField
|
||||
from eve_api.models import EVEAccount, EVEPlayerCorporation, EVEPlayerAlliance, EVEPlayerCharacter
|
||||
|
||||
from services import get_api
|
||||
|
||||
## Exceptions
|
||||
|
||||
|
||||
class CorporateOnlyService(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class ExistingUser(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class ServiceError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class SSOUser(models.Model):
|
||||
""" Extended SSO User Profile options """
|
||||
|
||||
user = models.ForeignKey(User, unique=True, related_name='profile')
|
||||
|
||||
api_service_password = models.CharField("API Services Password", max_length=200, blank=True)
|
||||
|
||||
def __unicode__(self):
|
||||
return self.user.__unicode__()
|
||||
|
||||
@staticmethod
|
||||
def create_user_profile(sender, instance, created, **kwargs):
|
||||
if created:
|
||||
profile, created = SSOUser.objects.get_or_create(user=instance)
|
||||
|
||||
signals.post_save.connect(SSOUser.create_user_profile, sender=User)
|
||||
|
||||
|
||||
class SSOUserNote(models.Model):
|
||||
""" Notes bound to a user's account. Used to store information regarding the user """
|
||||
|
||||
user = models.ForeignKey(User, blank=False, null=False, related_name='notes')
|
||||
note = models.TextField("Note", blank=False, null=False)
|
||||
created_by = models.ForeignKey(User, blank=False, null=False)
|
||||
date_created = models.DateTimeField(auto_now_add=True, blank=False, null=False,
|
||||
verbose_name="Date/Time the note was added",
|
||||
help_text="Shows the date and time the note was added to the account")
|
||||
|
||||
class Meta:
|
||||
verbose_name = 'User Note'
|
||||
verbose_name_plural = 'User Notes'
|
||||
ordering = ['date_created']
|
||||
|
||||
|
||||
class SSOUserIPAddress(models.Model):
|
||||
"""
|
||||
Stores User Related IP Addresses
|
||||
"""
|
||||
first_seen = models.DateTimeField(auto_now_add=True, blank=False, null=False,
|
||||
verbose_name="First sighting date/time",
|
||||
help_text="Shows the first the user was seen at this IP.")
|
||||
last_seen = models.DateTimeField(auto_now_add=True, blank=False, null=False,
|
||||
verbose_name="First sighting date/time",
|
||||
help_text="Shows the most recent time the user has been seen at this IP.")
|
||||
ip_address = models.CharField("IP Address", max_length=200, blank=False)
|
||||
user = models.ForeignKey(User, blank=False, null=False, related_name='ip_addresses')
|
||||
|
||||
def __unicode__(self):
|
||||
return self.ip_address
|
||||
|
||||
class Meta:
|
||||
verbose_name = 'User IP Addresse'
|
||||
verbose_name_plural = 'User IP Addresses'
|
||||
ordering = ['user']
|
||||
|
||||
|
||||
class Service(models.Model):
|
||||
"""
|
||||
Service model represents a service available to users, either a website or
|
||||
a connection service like Jabber or IRC.
|
||||
"""
|
||||
|
||||
name = models.CharField("Service Name", max_length=200)
|
||||
url = models.CharField("Service URL", max_length=200, blank=True)
|
||||
active = models.BooleanField(default=True)
|
||||
api = models.CharField("API", max_length=200)
|
||||
groups = models.ManyToManyField(Group, blank=True)
|
||||
settings_json = JSONField("Service Settings", blank=True, default={})
|
||||
|
||||
class Meta:
|
||||
verbose_name = 'Service'
|
||||
verbose_name_plural = 'Services'
|
||||
ordering = ['id']
|
||||
|
||||
@property
|
||||
def provide_login(self):
|
||||
return self.settings['provide_login']
|
||||
|
||||
@property
|
||||
def api_class(self):
|
||||
api = get_api(self.api)
|
||||
api.settings = self.settings
|
||||
return api
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
def save(self):
|
||||
if not self.settings_json or self.settings_json == {}:
|
||||
if self.api:
|
||||
self.settings_json = self.settings
|
||||
else:
|
||||
self.settings_json = {}
|
||||
else:
|
||||
if isinstance(self.settings_json, types.StringTypes):
|
||||
self.settings_json = eval(self.settings_json)
|
||||
|
||||
return models.Model.save(self)
|
||||
|
||||
@property
|
||||
def settings(self):
|
||||
|
||||
if self.settings_json:
|
||||
setdict = self.settings_json
|
||||
else:
|
||||
setdict = {}
|
||||
|
||||
# Load defaults from the module's settings dict
|
||||
if self.api:
|
||||
modset = get_api(self.api).settings
|
||||
for k in modset:
|
||||
if not k in setdict:
|
||||
setdict[k] = modset[k]
|
||||
|
||||
return setdict
|
||||
|
||||
|
||||
class ServiceAccount(models.Model):
|
||||
"""
|
||||
ServiceAccount represents the user's account on a Service.
|
||||
"""
|
||||
user = models.ForeignKey(User, blank=False)
|
||||
service = models.ForeignKey(Service, blank=False)
|
||||
service_uid = models.CharField("Service UID", max_length=200, blank=False)
|
||||
active = models.BooleanField(default=True)
|
||||
|
||||
character = models.ForeignKey(EVEPlayerCharacter, null=True)
|
||||
username = None
|
||||
password = None
|
||||
|
||||
class Meta:
|
||||
verbose_name = 'Service Account'
|
||||
verbose_name_plural = 'Service Accounts'
|
||||
ordering = ['user']
|
||||
|
||||
def __unicode__(self):
|
||||
return u"%s: %s (%s)" % (self.service.name, self.user.username, self.service_uid)
|
||||
|
||||
def save(self):
|
||||
if self.id:
|
||||
org = ServiceAccount.objects.get(id=self.pk)
|
||||
|
||||
if org.active != self.active and self.service_uid:
|
||||
if self.active:
|
||||
self.service.api_class.enable_user(self.service_uid, '')
|
||||
else:
|
||||
self.service.api_class.disable_user(self.service_uid)
|
||||
|
||||
models.Model.save(self)
|
||||
|
||||
@staticmethod
|
||||
def pre_delete_listener(**kwargs):
|
||||
if not kwargs['instance'].service.api_class.delete_user(kwargs['instance'].service_uid):
|
||||
raise ServiceError('Unable to delete account on related service')
|
||||
|
||||
signals.pre_delete.connect(ServiceAccount.pre_delete_listener, sender=ServiceAccount)
|
||||
84
app/sso/services/__init__.py
Normal file
84
app/sso/services/__init__.py
Normal file
@@ -0,0 +1,84 @@
|
||||
import settings
|
||||
from django.db import connections
|
||||
|
||||
def get_api(api):
|
||||
|
||||
if settings.DISABLE_SERVICES:
|
||||
return BaseService()
|
||||
|
||||
try:
|
||||
mod = __import__(api)
|
||||
except ImportError:
|
||||
raise Exception('Error creating service')
|
||||
|
||||
for i in api.split(".")[1:]:
|
||||
mod = getattr(mod, i)
|
||||
|
||||
return getattr(mod, mod.ServiceClass)()
|
||||
|
||||
def list_apis():
|
||||
import os.path, pkgutil
|
||||
pkgpath = os.path.dirname(__file__)
|
||||
return [name for _, name, _ in pkgutil.iter_modules([pkgpath])]
|
||||
|
||||
class BaseService():
|
||||
"""
|
||||
Base Service class, all service classes should inherit from this
|
||||
|
||||
"""
|
||||
|
||||
settings = { 'require_user': True,
|
||||
'require_password': True,
|
||||
'provide_login': False }
|
||||
|
||||
def add_user(self, username, password, **kwargs):
|
||||
""" Add a user, returns a dict for that user """
|
||||
return { 'username': username, 'password': password }
|
||||
|
||||
def check_user(self, username):
|
||||
""" Check if the username exists """
|
||||
return False
|
||||
|
||||
def check_uid(self, uid):
|
||||
""" Check if a UID exists """
|
||||
return self.check_user(uid)
|
||||
|
||||
def delete_user(self, uid):
|
||||
""" Delete a user by uid """
|
||||
return True
|
||||
|
||||
def disable_user(self, uid):
|
||||
""" Disable a user by uid """
|
||||
return True
|
||||
|
||||
def enable_user(self, uid, password):
|
||||
""" Enable a user by uid """
|
||||
return True
|
||||
|
||||
def reset_password(self, uid, password):
|
||||
""" Reset the user's password """
|
||||
return True
|
||||
|
||||
def login(self, uid):
|
||||
""" Login the user and provide cookies back """
|
||||
pass
|
||||
|
||||
def update_groups(self, uid, groups, character=None):
|
||||
"""" Update the UID's groups based on the provided list """
|
||||
pass
|
||||
|
||||
|
||||
class BaseDBService(BaseService):
|
||||
|
||||
@property
|
||||
def db(self):
|
||||
if not hasattr(self, '_db'):
|
||||
self._db = connections[self.settings['database_name']]
|
||||
return self._db
|
||||
|
||||
@property
|
||||
def dbcursor(self):
|
||||
if not hasattr(self, '_dbcursor'):
|
||||
self._dbcursor = self.db.cursor()
|
||||
return self._dbcursor
|
||||
|
||||
8
app/sso/services/dummy/__init__.py
Normal file
8
app/sso/services/dummy/__init__.py
Normal file
@@ -0,0 +1,8 @@
|
||||
from sso.services import BaseService
|
||||
|
||||
class DummyService(BaseService):
|
||||
""" Always passes, good for a test service """
|
||||
pass
|
||||
|
||||
|
||||
ServiceClass = 'DummyService'
|
||||
87
app/sso/services/ipb/__init__.py
Normal file
87
app/sso/services/ipb/__init__.py
Normal file
@@ -0,0 +1,87 @@
|
||||
import xmlrpclib
|
||||
from sso.services import BaseService
|
||||
import settings
|
||||
from hashlib import md5
|
||||
|
||||
class IPBService(BaseService):
|
||||
|
||||
settings = { 'require_user': True,
|
||||
'require_password': True,
|
||||
'provide_login': False,
|
||||
'use_auth_username': True,
|
||||
'ipb_display_name': "[%(corp)s] - %(name)s",
|
||||
'ipb_endpoint': 'http://testboard.aevumdecessus.com/interface/board/index.php',
|
||||
'ipb_api_key': '51242ecca069b986106f04db1047cfc4',
|
||||
'ipb_api_module': 'ipb' }
|
||||
|
||||
def exec_xmlrpc(self, func, **kwargs):
|
||||
""" Send a XMLRPC request """
|
||||
if not hasattr(self, '_server'):
|
||||
self._server = xmlrpclib.Server(self.settings['ipb_endpoint'], verbose=True)
|
||||
params = {}
|
||||
for i in kwargs:
|
||||
params[i] = kwargs[i]
|
||||
params['api_key'] = self.settings['ipb_api_key']
|
||||
params['api_module'] = self.settings['ipb_api_module']
|
||||
|
||||
return getattr(self._server, func)(params)
|
||||
|
||||
def _create_group(self, name):
|
||||
""" Creates a IPB membergroup """
|
||||
ret = self.exec_xmlrpc('createGroup', group_name=name)
|
||||
if ret:
|
||||
return {'name': name, 'id': ret['changeSuccessful']}
|
||||
|
||||
def add_user(self, username, password, **kwargs):
|
||||
""" Add user to service """
|
||||
|
||||
password = md5(password).hexdigest()
|
||||
details = { 'name': kwargs['character'].name,
|
||||
'alli': kwargs['character'].corporation.alliance.ticker,
|
||||
'corp': kwargs['character'].corporation.ticker }
|
||||
display = self.settings['ipb_display_name'] % details
|
||||
ret = self.exec_xmlrpc('createUser', username=username, email=kwargs['user'].email, display_name=display, password=password)
|
||||
|
||||
return username
|
||||
|
||||
def delete_user(self, uid):
|
||||
""" Delete a user """
|
||||
pass
|
||||
|
||||
def check_user(self, username):
|
||||
""" Check if the username exists """
|
||||
ret = self.exec_xmlrpc('fetchMember', search_type='email', search_string=username)
|
||||
|
||||
return ret
|
||||
|
||||
def disable_user(self, uid):
|
||||
""" Disable a user """
|
||||
pass
|
||||
|
||||
def enable_user(self, uid, password):
|
||||
""" Enable a user """
|
||||
pass
|
||||
|
||||
def reset_password(self, uid, password):
|
||||
""" Reset the user's password """
|
||||
pass
|
||||
|
||||
def update_groups(self, uid, groups, character=None):
|
||||
|
||||
user_id = self.check_user(uid)
|
||||
|
||||
# Get all IPB groups
|
||||
|
||||
# Iterate through the provided group list and create any missing ones
|
||||
grplist = []
|
||||
for g in groups:
|
||||
if not g.name in grplist:
|
||||
ret = self._create_group(g.name)
|
||||
if ret:
|
||||
grplist[ret['name']] = ret['id']
|
||||
|
||||
# Assign each group to the user id
|
||||
for gk in grplist:
|
||||
self.exec_xmlrpc('updateUserGroup', user_id=user_id, group_name=gk, action='ADD')
|
||||
|
||||
ServiceClass = 'IPBService'
|
||||
151
app/sso/services/jabber/__init__.py
Normal file
151
app/sso/services/jabber/__init__.py
Normal file
@@ -0,0 +1,151 @@
|
||||
import xmlrpclib
|
||||
from sso.services import BaseService
|
||||
import settings
|
||||
|
||||
|
||||
class JabberService(BaseService):
|
||||
|
||||
settings = { 'require_user': True,
|
||||
'require_password': True,
|
||||
'provide_login': False,
|
||||
'use_auth_username': False,
|
||||
'jabber_server': 'dredd.it',
|
||||
'jabber_xmlrpc_url': 'http://127.0.0.1:4560',
|
||||
'jabber_annouce_from': 'announcebot@pleaseignore.com'}
|
||||
|
||||
def exec_xmlrpc(self, func, **kwargs):
|
||||
""" Send a XMLRPC request """
|
||||
if not hasattr(self, '_server'):
|
||||
self._server = xmlrpclib.Server(self.settings['jabber_xmlrpc_url'])
|
||||
params = {}
|
||||
for i in kwargs:
|
||||
params[i] = kwargs[i]
|
||||
|
||||
return getattr(self._server, func)(params)
|
||||
|
||||
def add_user(self, username, password, **kwargs):
|
||||
""" Add user to service """
|
||||
username = username.lower()
|
||||
res = self.exec_xmlrpc('register', user=username, host=self.settings['jabber_server'], password=password)
|
||||
if res['res'] == 0:
|
||||
if 'character' in kwargs:
|
||||
self.exec_xmlrpc('set_nickname', user=username, host=self.settings['jabber_server'], nickname=kwargs['character'].name)
|
||||
self.exec_xmlrpc('set_vcard2', user=username, host=self.settings['jabber_server'], name='ORG', subname='ORGNAME', content=kwargs['character'].corporation.name)
|
||||
uid = "%s@%s" % (username.lower(), self.settings['jabber_server'])
|
||||
if 'user' in kwargs:
|
||||
self.update_groups(uid, kwargs['user'].groups.all())
|
||||
return { 'username': uid, 'password': password }
|
||||
else:
|
||||
return False
|
||||
|
||||
def delete_user(self, uid):
|
||||
""" Delete a user """
|
||||
username, server = uid.lower().split("@")
|
||||
|
||||
for group in self.get_user_groups(uid):
|
||||
self.exec_xmlrpc('srg_user_del', user=username, host=server, group=group, grouphost=server)
|
||||
|
||||
res = self.exec_xmlrpc('unregister', user=username, host=server)
|
||||
if res['res'] == 0:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def check_user(self, username):
|
||||
""" Check if the username exists """
|
||||
if '@' in username:
|
||||
username, server = username.lower().split("@")
|
||||
else:
|
||||
server = self.settings['jabber_server']
|
||||
res = self.exec_xmlrpc('check_account', user=username, host=server)
|
||||
if res['res'] == 0:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def disable_user(self, uid):
|
||||
""" Disable a user """
|
||||
username, server = uid.lower().split("@")
|
||||
res = self.exec_xmlrpc('ban_account', host=server, user=username, reason='Auth account disable')
|
||||
if res['res'] == 0:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def enable_user(self, uid, password):
|
||||
""" Enable a user """
|
||||
self.reset_password(uid, password)
|
||||
|
||||
def reset_password(self, uid, password):
|
||||
""" Reset the user's password """
|
||||
username, server = uid.lower().split("@")
|
||||
res = self.exec_xmlrpc('change_password', user=username, host=server, newpass=password)
|
||||
if res['res'] == 0:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def get_group_list(self, server):
|
||||
srvgrp = self.exec_xmlrpc('srg_list', host=server)
|
||||
return [grp['id'].lower() for grp in srvgrp['groups']]
|
||||
|
||||
def get_group_members(self, server, group):
|
||||
members = self.exec_xmlrpc('srg_get_members', group=group, host=server)
|
||||
return [x['member'].lower() for x in members['members']]
|
||||
|
||||
def get_user_groups(self, uid):
|
||||
grouplist = []
|
||||
username, server = uid.lower().split("@")
|
||||
for grp in self.get_group_list(server):
|
||||
if uid in self.get_group_members(server, grp):
|
||||
grouplist.append(grp)
|
||||
return grouplist
|
||||
|
||||
def update_groups(self, uid, groups, character=None):
|
||||
username, server = uid.lower().split("@")
|
||||
|
||||
current_groups = self.get_user_groups(uid)
|
||||
valid_groups = []
|
||||
|
||||
for group in groups:
|
||||
groupname = group.name.lower().replace(' ', '-')
|
||||
self.exec_xmlrpc('srg_create', group=groupname, host=server, name=group.name, description='', display='')
|
||||
self.exec_xmlrpc('srg_user_add', user=username, host=server, group=groupname, grouphost=server)
|
||||
valid_groups.append(groupname)
|
||||
|
||||
for group in (set(current_groups) - set(valid_groups)):
|
||||
self.exec_xmlrpc('srg_user_del', user=username, host=server, group=groupname, grouphost=server)
|
||||
|
||||
def send_message(self, jid, msg):
|
||||
# send_stanza_c2s user host resource stanza
|
||||
username, server = jid.lower().split("@")
|
||||
self.exec_xmlrpc('send_stanza_c2s', user=username, host=server, resource='auth', stanza=str(msg))
|
||||
|
||||
def announce(self, server, message, subject=None, all=False, users=[], groups=[]):
|
||||
import xmpp
|
||||
msg = xmpp.protocol.Message()
|
||||
msg.setFrom(self.settings['jabber_announce_from'])
|
||||
msg.setBody(message)
|
||||
if subject:
|
||||
msg.setSubject(subject)
|
||||
|
||||
if all:
|
||||
msg.setTo('%s/announce/all-hosts/online' % server)
|
||||
self.send_message(self.settings['jabber_announce_from'], msg)
|
||||
return True
|
||||
else:
|
||||
if len(users):
|
||||
for u in set(users):
|
||||
msg.setTo(u)
|
||||
self.send_message(self.settings['jabber_announce_from'], msg)
|
||||
return True
|
||||
|
||||
elif len(groups):
|
||||
tolist = []
|
||||
for g in groups:
|
||||
tolist.extend([x for x in self.get_group_members(server, g)])
|
||||
return self.announce(server, message, subject, users=tolist)
|
||||
else:
|
||||
return False
|
||||
|
||||
ServiceClass = 'JabberService'
|
||||
86
app/sso/services/miningbuddy/__init__.py
Normal file
86
app/sso/services/miningbuddy/__init__.py
Normal file
@@ -0,0 +1,86 @@
|
||||
import crypt
|
||||
import random
|
||||
import time
|
||||
from django.db import transaction
|
||||
from sso.services import BaseDBService
|
||||
import settings
|
||||
|
||||
class MiningBuddyService(BaseDBService):
|
||||
"""
|
||||
Mining Buddy Class, allows registration and sign-in
|
||||
|
||||
"""
|
||||
|
||||
settings = { 'require_user': False,
|
||||
'require_password': False,
|
||||
'provide_login': False,
|
||||
'use_auth_username': False,
|
||||
'database_name': 'dreddit_mining',
|
||||
'password_salt': 's98ss7fsc7fd2rf62ctcrlwztstnzve9toezexcsdhfgviuinusxcdtsvbrg' }
|
||||
|
||||
|
||||
SQL_ADD_USER = r"INSERT INTO users (username, password, email, emailvalid, confirmed, rank) VALUES (%s, %s, %s, 1, 1, 2)"
|
||||
SQL_ADD_API = r"INSERT INTO api_keys (userid, time, apiID, apiKey, api_valid, charid) values (%s, %s, %s, %s, 1, %s)"
|
||||
SQL_DIS_USER = r"UPDATE users SET canLogin = 0 WHERE username = %s"
|
||||
SQL_ENABLE_USER = r"UPDATE users SET canLogin = 1, password = %s WHERE username = %s"
|
||||
SQL_CHECK_USER = r"SELECT username from users WHERE username = %s and deleted = 0"
|
||||
SQL_DEL_USER = r"UPDATE users set deleted = 1 WHERE username = %s"
|
||||
|
||||
def _gen_salt(self):
|
||||
return self.settings['password_salt']
|
||||
|
||||
def _gen_mb_hash(self, password, salt=None):
|
||||
if not salt:
|
||||
salt = self._gen_salt()
|
||||
return crypt.crypt(password, salt)
|
||||
|
||||
def _clean_username(self, username):
|
||||
username = username.strip()
|
||||
return username
|
||||
|
||||
def add_user(self, username, password, **kwargs):
|
||||
""" Add a user """
|
||||
pwhash = self._gen_mb_hash(password)
|
||||
if 'user' in kwargs:
|
||||
email = kwargs['user'].email
|
||||
else:
|
||||
email = ''
|
||||
|
||||
self.dbcursor.execute(self.SQL_ADD_USER, [self._clean_username(username), pwhash, email])
|
||||
|
||||
userid = self.dbcursor.lastrowid
|
||||
api = kwargs['character'].eveaccount_set.all()[0]
|
||||
self.dbcursor.execute(self.SQL_ADD_API, [userid, int(time.time()), api.api_user_id, api.api_key, kwargs['character'].id])
|
||||
|
||||
return { 'username': self._clean_username(username), 'password': password }
|
||||
|
||||
def check_user(self, username):
|
||||
""" Check if the username exists """
|
||||
self.dbcursor.execute(self.SQL_CHECK_USER, [self._clean_username(username)])
|
||||
row = self.dbcursor.fetchone()
|
||||
if row:
|
||||
return True
|
||||
return False
|
||||
|
||||
def delete_user(self, uid):
|
||||
""" Delete a user """
|
||||
self.dbcursor.execute(self.SQL_DEL_USER, [uid])
|
||||
return True
|
||||
|
||||
def disable_user(self, uid):
|
||||
""" Disable a user """
|
||||
self.dbcursor.execute(self.SQL_DIS_USER, [uid])
|
||||
return True
|
||||
|
||||
def enable_user(self, uid, password):
|
||||
""" Enable a user """
|
||||
pwhash = self._gen_mb_hash(password)
|
||||
self.dbcursor.execute(self.SQL_ENABLE_USER, [pwhash, uid])
|
||||
return True
|
||||
|
||||
def reset_password(self, uid, password):
|
||||
""" Reset the user's password """
|
||||
return self.enable_user(uid, password)
|
||||
|
||||
|
||||
ServiceClass = 'MiningBuddyService'
|
||||
610
app/sso/services/mumble/MumbleCtlIce.py
Normal file
610
app/sso/services/mumble/MumbleCtlIce.py
Normal file
@@ -0,0 +1,610 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
* Copyright © 2009, withgod <withgod@sourceforge.net>
|
||||
* 2009-2010, Michael "Svedrin" Ziegler <diese-addy@funzt-halt.net>
|
||||
*
|
||||
* Mumble-Django is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This package is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
"""
|
||||
|
||||
from time import time
|
||||
from functools import wraps
|
||||
from StringIO import StringIO
|
||||
from os.path import exists, join
|
||||
from os import unlink, name as os_name
|
||||
from PIL import Image
|
||||
from struct import pack, unpack
|
||||
from zlib import compress, decompress, error
|
||||
|
||||
from mctl import MumbleCtlBase
|
||||
|
||||
import Ice, IcePy, tempfile
|
||||
|
||||
class ObjectInfo( object ):
|
||||
""" Wraps arbitrary information to be easily accessed. """
|
||||
|
||||
def __init__( self, **kwargs ):
|
||||
self.__dict__ = kwargs;
|
||||
|
||||
def __str__( self ):
|
||||
return unicode( self );
|
||||
|
||||
def __repr__( self ):
|
||||
return unicode( self );
|
||||
|
||||
def __unicode__( self ):
|
||||
return unicode( self.__dict__ );
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self.__dict__[key]
|
||||
|
||||
def protectDjangoErrPage( func ):
|
||||
""" Catch and reraise Ice exceptions to prevent the Django page from failing.
|
||||
|
||||
Since I need to "import Murmur", Django would try to read a murmur.py file
|
||||
which doesn't exist, and thereby produce an IndexError exception. This method
|
||||
erases the exception's traceback, preventing Django from trying to read any
|
||||
non-existant files and borking.
|
||||
"""
|
||||
|
||||
@wraps(func)
|
||||
def protection_wrapper( self, *args, **kwargs ):
|
||||
""" Call the original function and catch Ice exceptions. """
|
||||
try:
|
||||
return func( self, *args, **kwargs );
|
||||
except Ice.Exception, err:
|
||||
raise err;
|
||||
protection_wrapper.innerfunc = func
|
||||
|
||||
return protection_wrapper;
|
||||
|
||||
|
||||
@protectDjangoErrPage
|
||||
def MumbleCtlIce( connstring, slicefile=None, icesecret=None ):
|
||||
""" Choose the correct Ice handler to use (1.1.8 or 1.2.x), and make sure the
|
||||
Murmur version matches the slice Version.
|
||||
|
||||
Optional parameters are the path to the slice file and the Ice secret
|
||||
necessary to authenticate to Murmur.
|
||||
|
||||
The path can be omitted only if running Murmur 1.2.3 or later, which
|
||||
exports a getSlice method to retrieve the Slice from.
|
||||
"""
|
||||
|
||||
prop = Ice.createProperties([])
|
||||
prop.setProperty("Ice.ImplicitContext", "Shared")
|
||||
|
||||
idd = Ice.InitializationData()
|
||||
idd.properties = prop
|
||||
|
||||
ice = Ice.initialize(idd)
|
||||
|
||||
if icesecret:
|
||||
ice.getImplicitContext().put( "secret", icesecret.encode("utf-8") )
|
||||
|
||||
prx = ice.stringToProxy( connstring.encode("utf-8") )
|
||||
|
||||
try:
|
||||
prx.ice_ping()
|
||||
except Ice.Exception:
|
||||
raise EnvironmentError( "Murmur does not appear to be listening on this address (Ice ping failed)." )
|
||||
|
||||
try:
|
||||
import Murmur
|
||||
except ImportError:
|
||||
# Try loading the Slice from Murmur directly via its getSlice method.
|
||||
# See scripts/testdynamic.py in Mumble's Git repository.
|
||||
try:
|
||||
slice = IcePy.Operation( 'getSlice',
|
||||
Ice.OperationMode.Idempotent, Ice.OperationMode.Idempotent,
|
||||
True, (), (), (), IcePy._t_string, ()
|
||||
).invoke(prx, ((), None))
|
||||
except (TypeError, Ice.OperationNotExistException):
|
||||
if not slicefile:
|
||||
raise EnvironmentError(
|
||||
"You didn't configure a slice file. Please set the SLICE variable in settings.py." )
|
||||
if not exists( slicefile ):
|
||||
raise EnvironmentError(
|
||||
"The slice file does not exist: '%s' - please check the settings." % slicefile )
|
||||
if " " in slicefile:
|
||||
raise EnvironmentError(
|
||||
"You have a space char in your Slice path. This will confuse Ice, please check." )
|
||||
if not slicefile.endswith( ".ice" ):
|
||||
raise EnvironmentError( "The slice file name MUST end with '.ice'." )
|
||||
|
||||
try:
|
||||
Ice.loadSlice( slicefile )
|
||||
except RuntimeError:
|
||||
raise RuntimeError( "Slice preprocessing failed. Please check your server's error log." )
|
||||
else:
|
||||
if os_name == "nt":
|
||||
# It weren't Windows if it didn't need to be treated differently. *sigh*
|
||||
temppath = join( tempfile.gettempdir(), "Murmur.ice" )
|
||||
slicetemp = open( temppath, "w+b" )
|
||||
try:
|
||||
slicetemp.write( slice )
|
||||
finally:
|
||||
slicetemp.close()
|
||||
try:
|
||||
Ice.loadSlice( temppath )
|
||||
except RuntimeError:
|
||||
raise RuntimeError( "Slice preprocessing failed. Please check your server's error log." )
|
||||
finally:
|
||||
unlink(temppath)
|
||||
else:
|
||||
slicetemp = tempfile.NamedTemporaryFile( suffix='.ice' )
|
||||
try:
|
||||
slicetemp.write( slice )
|
||||
slicetemp.flush()
|
||||
Ice.loadSlice( slicetemp.name )
|
||||
except RuntimeError:
|
||||
raise RuntimeError( "Slice preprocessing failed. Please check your server's error log." )
|
||||
finally:
|
||||
slicetemp.close()
|
||||
|
||||
import Murmur
|
||||
|
||||
meta = Murmur.MetaPrx.checkedCast(prx)
|
||||
|
||||
murmurversion = meta.getVersion()[:3]
|
||||
|
||||
if murmurversion == (1, 1, 8):
|
||||
return MumbleCtlIce_118( connstring, meta );
|
||||
|
||||
elif murmurversion[:2] == (1, 2):
|
||||
if murmurversion[2] < 2:
|
||||
return MumbleCtlIce_120( connstring, meta );
|
||||
|
||||
elif murmurversion[2] == 2:
|
||||
return MumbleCtlIce_122( connstring, meta );
|
||||
|
||||
elif murmurversion[2] == 3:
|
||||
return MumbleCtlIce_123( connstring, meta );
|
||||
|
||||
raise NotImplementedError( "No ctl object available for Murmur version %d.%d.%d" % tuple(murmurversion) )
|
||||
|
||||
|
||||
class MumbleCtlIce_118(MumbleCtlBase):
|
||||
method = "ICE";
|
||||
|
||||
def __init__( self, connstring, meta ):
|
||||
self.proxy = connstring;
|
||||
self.meta = meta;
|
||||
|
||||
@protectDjangoErrPage
|
||||
def _getIceServerObject(self, srvid):
|
||||
return self.meta.getServer(srvid);
|
||||
|
||||
@protectDjangoErrPage
|
||||
def getBootedServers(self):
|
||||
ret = []
|
||||
for x in self.meta.getBootedServers():
|
||||
ret.append(x.id())
|
||||
return ret
|
||||
|
||||
@protectDjangoErrPage
|
||||
def getVersion( self ):
|
||||
return self.meta.getVersion();
|
||||
|
||||
@protectDjangoErrPage
|
||||
def getAllServers(self):
|
||||
ret = []
|
||||
for x in self.meta.getAllServers():
|
||||
ret.append(x.id())
|
||||
return ret
|
||||
|
||||
@protectDjangoErrPage
|
||||
def getRegisteredPlayers(self, srvid, filter = ''):
|
||||
users = self._getIceServerObject(srvid).getRegisteredPlayers( filter.encode( "UTF-8" ) )
|
||||
ret = {};
|
||||
|
||||
for user in users:
|
||||
ret[user.playerid] = ObjectInfo(
|
||||
userid = int( user.playerid ),
|
||||
name = unicode( user.name, "utf8" ),
|
||||
email = unicode( user.email, "utf8" ),
|
||||
pw = unicode( user.pw, "utf8" )
|
||||
);
|
||||
|
||||
return ret
|
||||
|
||||
@protectDjangoErrPage
|
||||
def getChannels(self, srvid):
|
||||
return self._getIceServerObject(srvid).getChannels();
|
||||
|
||||
@protectDjangoErrPage
|
||||
def getPlayers(self, srvid):
|
||||
users = self._getIceServerObject(srvid).getPlayers()
|
||||
|
||||
ret = {};
|
||||
|
||||
for useridx in users:
|
||||
user = users[useridx];
|
||||
ret[ user.session ] = ObjectInfo(
|
||||
session = user.session,
|
||||
userid = user.playerid,
|
||||
mute = user.mute,
|
||||
deaf = user.deaf,
|
||||
suppress = user.suppressed,
|
||||
selfMute = user.selfMute,
|
||||
selfDeaf = user.selfDeaf,
|
||||
channel = user.channel,
|
||||
name = user.name,
|
||||
onlinesecs = user.onlinesecs,
|
||||
bytespersec = user.bytespersec
|
||||
);
|
||||
|
||||
return ret;
|
||||
|
||||
@protectDjangoErrPage
|
||||
def getDefaultConf(self):
|
||||
return self.setUnicodeFlag(self.meta.getDefaultConf())
|
||||
|
||||
@protectDjangoErrPage
|
||||
def getAllConf(self, srvid):
|
||||
conf = self.setUnicodeFlag(self._getIceServerObject(srvid).getAllConf())
|
||||
|
||||
info = {};
|
||||
for key in conf:
|
||||
if key == "playername":
|
||||
info['username'] = conf[key];
|
||||
else:
|
||||
info[str(key)] = conf[key];
|
||||
return info;
|
||||
|
||||
@protectDjangoErrPage
|
||||
def newServer(self):
|
||||
return self.meta.newServer().id()
|
||||
|
||||
@protectDjangoErrPage
|
||||
def isBooted( self, srvid ):
|
||||
return bool( self._getIceServerObject(srvid).isRunning() );
|
||||
|
||||
@protectDjangoErrPage
|
||||
def start( self, srvid ):
|
||||
self._getIceServerObject(srvid).start();
|
||||
|
||||
@protectDjangoErrPage
|
||||
def stop( self, srvid ):
|
||||
self._getIceServerObject(srvid).stop();
|
||||
|
||||
@protectDjangoErrPage
|
||||
def deleteServer( self, srvid ):
|
||||
if self._getIceServerObject(srvid).isRunning():
|
||||
self._getIceServerObject(srvid).stop()
|
||||
self._getIceServerObject(srvid).delete()
|
||||
|
||||
@protectDjangoErrPage
|
||||
def setSuperUserPassword(self, srvid, value):
|
||||
self._getIceServerObject(srvid).setSuperuserPassword( value.encode( "UTF-8" ) )
|
||||
|
||||
@protectDjangoErrPage
|
||||
def getConf(self, srvid, key):
|
||||
if key == "username":
|
||||
key = "playername";
|
||||
|
||||
return self._getIceServerObject(srvid).getConf( key )
|
||||
|
||||
@protectDjangoErrPage
|
||||
def setConf(self, srvid, key, value):
|
||||
if key == "username":
|
||||
key = "playername";
|
||||
if value is None:
|
||||
value = ''
|
||||
self._getIceServerObject(srvid).setConf( key, value.encode( "UTF-8" ) )
|
||||
|
||||
@protectDjangoErrPage
|
||||
def registerPlayer(self, srvid, name, email, password):
|
||||
mumbleid = self._getIceServerObject(srvid).registerPlayer( name.encode( "UTF-8" ) )
|
||||
self.setRegistration( srvid, mumbleid, name, email, password );
|
||||
return mumbleid;
|
||||
|
||||
@protectDjangoErrPage
|
||||
def unregisterPlayer(self, srvid, mumbleid):
|
||||
self._getIceServerObject(srvid).unregisterPlayer(mumbleid)
|
||||
|
||||
@protectDjangoErrPage
|
||||
def getRegistration(self, srvid, mumbleid):
|
||||
user = self._getIceServerObject(srvid).getRegistration(mumbleid)
|
||||
return ObjectInfo(
|
||||
userid = mumbleid,
|
||||
name = user.name,
|
||||
email = user.email,
|
||||
pw = '',
|
||||
);
|
||||
|
||||
@protectDjangoErrPage
|
||||
def setRegistration(self, srvid, mumbleid, name, email, password):
|
||||
import Murmur
|
||||
user = Murmur.Player()
|
||||
user.playerid = mumbleid;
|
||||
user.name = name.encode( "UTF-8" )
|
||||
user.email = email.encode( "UTF-8" )
|
||||
user.pw = password.encode( "UTF-8" )
|
||||
# update*r*egistration r is lowercase...
|
||||
return self._getIceServerObject(srvid).updateregistration(user)
|
||||
|
||||
@protectDjangoErrPage
|
||||
def getACL(self, srvid, channelid):
|
||||
# need to convert acls to say "userid" instead of "playerid". meh.
|
||||
raw_acls, raw_groups, raw_inherit = self._getIceServerObject(srvid).getACL(channelid)
|
||||
|
||||
acls = [ ObjectInfo(
|
||||
applyHere = rule.applyHere,
|
||||
applySubs = rule.applySubs,
|
||||
inherited = rule.inherited,
|
||||
userid = rule.playerid,
|
||||
group = rule.group,
|
||||
allow = rule.allow,
|
||||
deny = rule.deny,
|
||||
)
|
||||
for rule in raw_acls
|
||||
];
|
||||
|
||||
return acls, raw_groups, raw_inherit;
|
||||
|
||||
@protectDjangoErrPage
|
||||
def setACL(self, srvid, channelid, acls, groups, inherit):
|
||||
import Murmur
|
||||
|
||||
ice_acls = [];
|
||||
|
||||
for rule in acls:
|
||||
ice_rule = Murmur.ACL();
|
||||
ice_rule.applyHere = rule.applyHere;
|
||||
ice_rule.applySubs = rule.applySubs;
|
||||
ice_rule.inherited = rule.inherited;
|
||||
ice_rule.playerid = rule.userid;
|
||||
ice_rule.group = rule.group;
|
||||
ice_rule.allow = rule.allow;
|
||||
ice_rule.deny = rule.deny;
|
||||
ice_acls.append(ice_rule);
|
||||
|
||||
return self._getIceServerObject(srvid).setACL( channelid, ice_acls, groups, inherit );
|
||||
|
||||
@protectDjangoErrPage
|
||||
def getTexture(self, srvid, mumbleid):
|
||||
texture = self._getIceServerObject(srvid).getTexture(mumbleid)
|
||||
if len(texture) == 0:
|
||||
raise ValueError( "No Texture has been set." );
|
||||
# this returns a list of bytes.
|
||||
try:
|
||||
decompressed = decompress( texture );
|
||||
except error, err:
|
||||
raise ValueError( err )
|
||||
# iterate over 4 byte chunks of the string
|
||||
imgdata = "";
|
||||
for idx in range( 0, len(decompressed), 4 ):
|
||||
# read 4 bytes = BGRA and convert to RGBA
|
||||
# manual wrote getTexture returns "Textures are stored as zlib compress()ed 600x60 32-bit RGBA data."
|
||||
# http://mumble.sourceforge.net/slice/Murmur/Server.html#getTexture
|
||||
# but return values BGRA X(
|
||||
bgra = unpack( "4B", decompressed[idx:idx+4] );
|
||||
imgdata += pack( "4B", bgra[2], bgra[1], bgra[0], bgra[3] );
|
||||
|
||||
# return an 600x60 RGBA image object created from the data
|
||||
return Image.fromstring( "RGBA", ( 600, 60 ), imgdata );
|
||||
|
||||
@protectDjangoErrPage
|
||||
def setTexture(self, srvid, mumbleid, infile):
|
||||
# open image, convert to RGBA, and resize to 600x60
|
||||
img = infile.convert( "RGBA" ).transform( ( 600, 60 ), Image.EXTENT, ( 0, 0, 600, 60 ) );
|
||||
# iterate over the list and pack everything into a string
|
||||
bgrastring = "";
|
||||
for ent in list( img.getdata() ):
|
||||
# ent is in RGBA format, but Murmur wants BGRA (ARGB inverse), so stuff needs
|
||||
# to be reordered when passed to pack()
|
||||
bgrastring += pack( "4B", ent[2], ent[1], ent[0], ent[3] );
|
||||
# compress using zlib
|
||||
compressed = compress( bgrastring );
|
||||
# pack the original length in 4 byte big endian, and concat the compressed
|
||||
# data to it to emulate qCompress().
|
||||
texture = pack( ">L", len(bgrastring) ) + compressed;
|
||||
# finally call murmur and set the texture
|
||||
self._getIceServerObject(srvid).setTexture(mumbleid, texture)
|
||||
|
||||
@protectDjangoErrPage
|
||||
def verifyPassword(self, srvid, username, password):
|
||||
return self._getIceServerObject(srvid).verifyPassword(username, password);
|
||||
|
||||
@staticmethod
|
||||
def setUnicodeFlag(data):
|
||||
ret = ''
|
||||
if isinstance(data, tuple) or isinstance(data, list) or isinstance(data, dict):
|
||||
ret = {}
|
||||
for key in data.keys():
|
||||
ret[MumbleCtlIce_118.setUnicodeFlag(key)] = MumbleCtlIce_118.setUnicodeFlag(data[key])
|
||||
else:
|
||||
ret = unicode(data, 'utf-8')
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
|
||||
|
||||
class MumbleCtlIce_120(MumbleCtlIce_118):
|
||||
@protectDjangoErrPage
|
||||
def getRegisteredPlayers(self, srvid, filter = ''):
|
||||
users = self._getIceServerObject( srvid ).getRegisteredUsers( filter.encode( "UTF-8" ) )
|
||||
ret = {};
|
||||
|
||||
for id in users:
|
||||
ret[id] = ObjectInfo(
|
||||
userid = id,
|
||||
name = unicode( users[id], "utf8" ),
|
||||
email = '',
|
||||
pw = ''
|
||||
);
|
||||
|
||||
return ret
|
||||
|
||||
@protectDjangoErrPage
|
||||
def getPlayers(self, srvid):
|
||||
userdata = self._getIceServerObject(srvid).getUsers();
|
||||
for key in userdata:
|
||||
if isinstance( userdata[key], str ):
|
||||
userdata[key] = userdata[key].decode( "UTF-8" )
|
||||
return userdata
|
||||
|
||||
@protectDjangoErrPage
|
||||
def getState(self, srvid, sessionid):
|
||||
userdata = self._getIceServerObject(srvid).getState(sessionid);
|
||||
for key in userdata.__dict__:
|
||||
attr = getattr( userdata, key )
|
||||
if isinstance( attr, str ):
|
||||
setattr( userdata, key, attr.decode( "UTF-8" ) )
|
||||
return userdata
|
||||
|
||||
@protectDjangoErrPage
|
||||
def registerPlayer(self, srvid, name, email, password):
|
||||
# To get the real values of these ENUM entries, try
|
||||
# Murmur.UserInfo.UserX.value
|
||||
import Murmur
|
||||
user = {
|
||||
Murmur.UserInfo.UserName: name.encode( "UTF-8" ),
|
||||
Murmur.UserInfo.UserEmail: email.encode( "UTF-8" ),
|
||||
Murmur.UserInfo.UserPassword: password.encode( "UTF-8" ),
|
||||
};
|
||||
return self._getIceServerObject(srvid).registerUser( user );
|
||||
|
||||
@protectDjangoErrPage
|
||||
def unregisterPlayer(self, srvid, mumbleid):
|
||||
self._getIceServerObject(srvid).unregisterUser(mumbleid)
|
||||
|
||||
@protectDjangoErrPage
|
||||
def getRegistration(self, srvid, mumbleid):
|
||||
reg = self._getIceServerObject( srvid ).getRegistration( mumbleid )
|
||||
user = ObjectInfo( userid=mumbleid, name="", email="", comment="", hash="", pw="" );
|
||||
import Murmur
|
||||
if Murmur.UserInfo.UserName in reg: user.name = reg[Murmur.UserInfo.UserName];
|
||||
if Murmur.UserInfo.UserEmail in reg: user.email = reg[Murmur.UserInfo.UserEmail];
|
||||
if Murmur.UserInfo.UserComment in reg: user.comment = reg[Murmur.UserInfo.UserComment];
|
||||
if Murmur.UserInfo.UserHash in reg: user.hash = reg[Murmur.UserInfo.UserHash];
|
||||
return user;
|
||||
|
||||
@protectDjangoErrPage
|
||||
def setRegistration(self, srvid, mumbleid, name, email, password):
|
||||
import Murmur
|
||||
user = {
|
||||
Murmur.UserInfo.UserName: name.encode( "UTF-8" ),
|
||||
Murmur.UserInfo.UserEmail: email.encode( "UTF-8" ),
|
||||
Murmur.UserInfo.UserPassword: password.encode( "UTF-8" ),
|
||||
};
|
||||
return self._getIceServerObject( srvid ).updateRegistration( mumbleid, user )
|
||||
|
||||
@protectDjangoErrPage
|
||||
def getAllConf(self, srvid):
|
||||
conf = self.setUnicodeFlag(self._getIceServerObject(srvid).getAllConf())
|
||||
|
||||
info = {};
|
||||
for key in conf:
|
||||
if key == "playername" and conf[key]:
|
||||
# Buggy database transition from 1.1.8 -> 1.2.0
|
||||
# Store username as "username" field and set playername field to empty
|
||||
info['username'] = conf[key];
|
||||
self.setConf( srvid, "playername", "" );
|
||||
self.setConf( srvid, "username", conf[key] );
|
||||
else:
|
||||
info[str(key)] = conf[key];
|
||||
|
||||
return info;
|
||||
|
||||
@protectDjangoErrPage
|
||||
def getConf(self, srvid, key):
|
||||
return self._getIceServerObject(srvid).getConf( key )
|
||||
|
||||
@protectDjangoErrPage
|
||||
def setConf(self, srvid, key, value):
|
||||
if value is None:
|
||||
value = ''
|
||||
self._getIceServerObject(srvid).setConf( key, value.encode( "UTF-8" ) )
|
||||
|
||||
@protectDjangoErrPage
|
||||
def getACL(self, srvid, channelid):
|
||||
return self._getIceServerObject(srvid).getACL(channelid)
|
||||
|
||||
@protectDjangoErrPage
|
||||
def setACL(self, srvid, channelid, acls, groups, inherit):
|
||||
return self._getIceServerObject(srvid).setACL( channelid, acls, groups, inherit );
|
||||
|
||||
@protectDjangoErrPage
|
||||
def getBans(self, srvid):
|
||||
return self._getIceServerObject(srvid).getBans();
|
||||
|
||||
@protectDjangoErrPage
|
||||
def setBans(self, srvid, bans):
|
||||
return self._getIceServerObject(srvid).setBans(bans);
|
||||
|
||||
@protectDjangoErrPage
|
||||
def addBanForSession(self, srvid, sessionid, **kwargs):
|
||||
session = self.getState(srvid, sessionid);
|
||||
if "bits" not in kwargs:
|
||||
kwargs["bits"] = 128;
|
||||
if "start" not in kwargs:
|
||||
kwargs["start"] = int(time());
|
||||
if "duration" not in kwargs:
|
||||
kwargs["duration"] = 3600;
|
||||
return self.addBan(srvid, address=session.address, **kwargs);
|
||||
|
||||
@protectDjangoErrPage
|
||||
def addBan(self, srvid, **kwargs):
|
||||
for key in kwargs:
|
||||
if isinstance( kwargs[key], unicode ):
|
||||
kwargs[key] = kwargs[key].encode("UTF-8")
|
||||
|
||||
from Murmur import Ban
|
||||
srvbans = self.getBans(srvid);
|
||||
srvbans.append( Ban( **kwargs ) );
|
||||
return self.setBans(srvid, srvbans);
|
||||
|
||||
@protectDjangoErrPage
|
||||
def kickUser(self, srvid, userid, reason=""):
|
||||
return self._getIceServerObject(srvid).kickUser( userid, reason.encode("UTF-8") );
|
||||
|
||||
|
||||
class MumbleCtlIce_122(MumbleCtlIce_120):
|
||||
@protectDjangoErrPage
|
||||
def getTexture(self, srvid, mumbleid):
|
||||
raise ValueError( "This method is buggy in 1.2.2, sorry dude." );
|
||||
|
||||
@protectDjangoErrPage
|
||||
def setTexture(self, srvid, mumbleid, infile):
|
||||
buf = StringIO()
|
||||
infile.save( buf, "PNG" )
|
||||
buf.seek(0)
|
||||
self._getIceServerObject(srvid).setTexture(mumbleid, buf.read())
|
||||
|
||||
|
||||
class MumbleCtlIce_123(MumbleCtlIce_120):
|
||||
|
||||
@protectDjangoErrPage
|
||||
def getRawTexture(self, srvid, mumbleid):
|
||||
return self._getIceServerObject(srvid).getTexture(mumbleid)
|
||||
|
||||
@protectDjangoErrPage
|
||||
def getTexture(self, srvid, mumbleid):
|
||||
texture = self.getRawTexture(srvid, mumbleid)
|
||||
if len(texture) == 0:
|
||||
raise ValueError( "No Texture has been set." );
|
||||
from StringIO import StringIO
|
||||
try:
|
||||
return Image.open( StringIO( texture ) )
|
||||
except IOError, err:
|
||||
raise ValueError( err )
|
||||
|
||||
@protectDjangoErrPage
|
||||
def setTexture(self, srvid, mumbleid, infile):
|
||||
buf = StringIO()
|
||||
infile.save( buf, "PNG" )
|
||||
buf.seek(0)
|
||||
self._getIceServerObject(srvid).setTexture(mumbleid, buf.read())
|
||||
|
||||
|
||||
164
app/sso/services/mumble/__init__.py
Normal file
164
app/sso/services/mumble/__init__.py
Normal file
@@ -0,0 +1,164 @@
|
||||
from sso.services import BaseService
|
||||
from MumbleCtlIce import MumbleCtlIce
|
||||
import Ice
|
||||
|
||||
class MumbleService(BaseService):
|
||||
|
||||
settings = { 'require_user': True,
|
||||
'require_password': True,
|
||||
'provide_login': False,
|
||||
'use_auth_username': False,
|
||||
'mumble_server_id': 2,
|
||||
'name_format': r'%(alliance)s - %(corporation)s - %(name)s',
|
||||
'connection_string': 'Meta:tcp -h 127.0.0.1 -p 6502',
|
||||
'ice_file': 'Murmur.ice' }
|
||||
|
||||
def __init__(self):
|
||||
try:
|
||||
Ice.loadSlice(self.settings['ice_file'])
|
||||
import Murmur
|
||||
self.mur = Murmur
|
||||
except:
|
||||
pass
|
||||
|
||||
@property
|
||||
def mumblectl(self):
|
||||
if not hasattr(self, '_mumblectl'):
|
||||
try:
|
||||
self._mumblectl = MumbleCtlIce(self.settings['connection_string'], self.settings['ice_file'])
|
||||
except:
|
||||
self._mumblectl = None
|
||||
return self._mumblectl
|
||||
|
||||
def add_user(self, username, password, **kwargs):
|
||||
""" Add a user, returns a UID for that user """
|
||||
|
||||
details = { 'name': username,
|
||||
'alliance': kwargs['character'].corporation.alliance.ticker,
|
||||
'corporation': kwargs['character'].corporation.ticker }
|
||||
|
||||
username = self.settings['name_format'] % details
|
||||
|
||||
if self.raw_add_user(username, kwargs['user'].email, password):
|
||||
self.update_groups(username, kwargs['user'].groups.all())
|
||||
return { 'username': username, 'password': password }
|
||||
else:
|
||||
return False
|
||||
|
||||
def raw_add_user(self, username, email, password):
|
||||
if self.mumblectl and self.mumblectl.registerPlayer(self.settings['mumble_server_id'], username, email, password):
|
||||
return username
|
||||
|
||||
return False
|
||||
|
||||
def check_user(self, username):
|
||||
""" Check if the username exists """
|
||||
if self.mumblectl and len(self.mumblectl.getRegisteredPlayers(self.settings['mumble_server_id'], username)):
|
||||
return True
|
||||
return False
|
||||
|
||||
def delete_user(self, uid):
|
||||
""" Delete a user by uid """
|
||||
if self.mumblectl:
|
||||
ids = self.mumblectl.getRegisteredPlayers(self.settings['mumble_server_id'], uid)
|
||||
if len(ids) > 0:
|
||||
for accid in ids:
|
||||
acc = ids[accid]
|
||||
self.mumblectl.unregisterPlayer(self.settings['mumble_server_id'], acc['userid'])
|
||||
|
||||
return True
|
||||
|
||||
def disable_user(self, uid):
|
||||
""" Disable a user by uid """
|
||||
self.delete_user(uid)
|
||||
return True
|
||||
|
||||
def enable_user(self, uid, password):
|
||||
""" Enable a user by uid """
|
||||
if self.mumblectl:
|
||||
ids = self.mumblectl.getRegisteredPlayers(self.settings['mumble_server_id'], uid)
|
||||
if len(ids) > 0:
|
||||
for accid in ids:
|
||||
acc = ids[accid]
|
||||
self.mumblectl.setRegistration(self.settings['mumble_server_id'], acc['userid'], acc['name'], acc['email'], password)
|
||||
return True
|
||||
else:
|
||||
if self.raw_add_user(uid, '', password):
|
||||
return True
|
||||
return False
|
||||
|
||||
def set_user(self, uid, name = ''):
|
||||
""" Set values ona user by uid """
|
||||
if self.mumblectl:
|
||||
ids = self.mumblectl.getRegisteredPlayers(self.settings['mumble_server_id'], uid)
|
||||
if len(ids) > 0:
|
||||
for accid in ids:
|
||||
acc = ids[accid]
|
||||
self.mumblectl.setRegistration(self.settings['mumble_server_id'], acc['userid'], name, acc['email'], acc['pw'])
|
||||
return True
|
||||
return False
|
||||
|
||||
def reset_password(self, uid, password):
|
||||
""" Reset the user's password """
|
||||
return self.enable_user(uid, password)
|
||||
|
||||
def login(uid):
|
||||
""" Login the user and provide cookies back """
|
||||
pass
|
||||
|
||||
def _create_groups(self, groups):
|
||||
""" Processes a list of groups and makes sure that related mumble groups exist """
|
||||
|
||||
acls = self.mumblectl.getACL(self.settings['mumble_server_id'], 0)
|
||||
glist = []
|
||||
for mgroup in acls[1]:
|
||||
glist.append(mgroup.name)
|
||||
|
||||
newgroups = False
|
||||
for agroup in groups:
|
||||
if not str(agroup.name.replace(' ', '').lower()) in glist:
|
||||
group = self.mur.Group()
|
||||
group.name = str(agroup.name.replace(' ', '').lower())
|
||||
group.members = []
|
||||
group.add = []
|
||||
group.remove = []
|
||||
group.inheritable = True
|
||||
group.inherit = True
|
||||
group.inherited = False
|
||||
acls[1].append(group)
|
||||
newgroups = True
|
||||
|
||||
if newgroups:
|
||||
self.mumblectl.setACL(self.settings['mumble_server_id'], 0, acls[0], acls[1], acls[2])
|
||||
|
||||
return acls
|
||||
|
||||
def update_groups(self, uid, groups, character=None):
|
||||
""" Update the UID's groups based on the provided list """
|
||||
|
||||
user = self.mumblectl.getRegisteredPlayers(self.settings['mumble_server_id'], uid)
|
||||
if not user:
|
||||
return False
|
||||
|
||||
user = user.values()[0]
|
||||
|
||||
acls = self._create_groups(groups)
|
||||
#acls = self.mumblectl.getACL(self.settings['mumble_server_id'], 0)
|
||||
|
||||
for agroup in groups:
|
||||
gid = 0
|
||||
for mgroup in acls[1]:
|
||||
if mgroup.name == agroup.name.replace(' ', '').lower():
|
||||
if not user['userid'] in acls[1][gid].members:
|
||||
acls[1][gid].add.append(user['userid'])
|
||||
acls[1][gid].members.append(user['userid'])
|
||||
else:
|
||||
if user['userid'] in acls[1][gid].members:
|
||||
acls[1][gid].remove.append(user['userid'])
|
||||
acls[1][gid].remove.remove(user['userid'])
|
||||
gid = gid + 1
|
||||
|
||||
self.mumblectl.setACL(self.settings['mumble_server_id'], 0, acls[0], acls[1], acls[2])
|
||||
return True
|
||||
|
||||
ServiceClass = 'MumbleService'
|
||||
58
app/sso/services/mumble/mctl.py
Normal file
58
app/sso/services/mumble/mctl.py
Normal file
@@ -0,0 +1,58 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
* Copyright © 2009, withgod <withgod@sourceforge.net>
|
||||
* 2009-2010, Michael "Svedrin" Ziegler <diese-addy@funzt-halt.net>
|
||||
*
|
||||
* Mumble-Django is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This package is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
"""
|
||||
|
||||
import re
|
||||
|
||||
class MumbleCtlBase(object):
|
||||
""" This class defines the base interface that the Mumble model expects. """
|
||||
|
||||
cache = {};
|
||||
|
||||
@staticmethod
|
||||
def newInstance( connstring, slicefile=None, icesecret=None ):
|
||||
""" Create a new CTL object for the given connstring.
|
||||
|
||||
Optional parameters are the path to the slice file and the
|
||||
Ice secret necessary to authenticate to Murmur.
|
||||
|
||||
The path can be omitted only if using DBus or running Murmur
|
||||
1.2.3 or later, which exports a getSlice method to retrieve
|
||||
the Slice from.
|
||||
"""
|
||||
|
||||
# check cache
|
||||
if connstring in MumbleCtlBase.cache:
|
||||
return MumbleCtlBase.cache[connstring];
|
||||
|
||||
# connstring defines whether to connect via ICE or DBus.
|
||||
# Dbus service names: some.words.divided.by.periods
|
||||
# ICE specs are WAY more complex, so if DBus doesn't match, use ICE.
|
||||
rd = re.compile( r'^(\w+\.)*\w+$' );
|
||||
|
||||
if rd.match( connstring ):
|
||||
from MumbleCtlDbus import MumbleCtlDbus
|
||||
ctl = MumbleCtlDbus( connstring )
|
||||
else:
|
||||
from MumbleCtlIce import MumbleCtlIce
|
||||
ctl = MumbleCtlIce( connstring, slicefile, icesecret )
|
||||
|
||||
MumbleCtlBase.cache[connstring] = ctl;
|
||||
return ctl;
|
||||
|
||||
@staticmethod
|
||||
def clearCache():
|
||||
MumbleCtlBase.cache = {};
|
||||
98
app/sso/services/phpbb/__init__.py
Normal file
98
app/sso/services/phpbb/__init__.py
Normal file
@@ -0,0 +1,98 @@
|
||||
import hashlib
|
||||
import random
|
||||
from django.db import load_backend, transaction, IntegrityError
|
||||
from sso.services import BaseDBService
|
||||
import settings
|
||||
|
||||
class PhpBBService(BaseDBService):
|
||||
"""
|
||||
PHPBB Class, allows registration and sign-in
|
||||
|
||||
"""
|
||||
|
||||
settings = { 'require_user': False,
|
||||
'require_password': False,
|
||||
'provide_login': False,
|
||||
'use_auth_username': False }
|
||||
|
||||
SQL_ADD_USER = r"INSERT INTO phpbb_users (username, username_clean, user_password, user_email) VALUES (%s, %s, %s, %s)"
|
||||
SQL_DIS_USER = r"DELETE FROM phpbb_user_groups where user_id = (SELECT user_id FROM phpbb_user WHERE username = %s)"
|
||||
SQL_CHECK_USER = r"SELECT username from phpbb_user WHERE username = %s"
|
||||
|
||||
SQL_ADD_USER_GROUP = r"INSERT INTO phpbb_user_group (group_id, user_id) VALUES (%s, %s)"
|
||||
SQL_GET_GROUP = r"SELECT group_id from phpbb_groups WHERE group_name = %s"
|
||||
SQL_ADD_GROUP = r"INSERT INTO phpbb_groups (group_name) VALUES (%s)"
|
||||
|
||||
def _gen_salt(self):
|
||||
return "%x" % random.randint(0, 2147483647)
|
||||
|
||||
def _gen_hash(self, password, salt=None):
|
||||
if not salt:
|
||||
salt = self._gen_salt()
|
||||
hash = hashlib.md5('%s-%s' % (salt, hashlib.md5(password).hexdigest())).hexdigest()
|
||||
return ":B:%s:%s" % (salt, hash)
|
||||
|
||||
def add_user(self, username, password, **kwargs):
|
||||
""" Add a user """
|
||||
if 'user' in kwargs:
|
||||
email = kwargs['user'].email
|
||||
groups = kwargs['user'].groups.all()
|
||||
else:
|
||||
email = ''
|
||||
pwhash = self._gen_hash(password)
|
||||
|
||||
self._dbcursor.execute(self.SQL_ADD_USER, [username, pwhash, email])
|
||||
|
||||
self.update_groups(username)
|
||||
return { 'username': username, 'password': password }
|
||||
|
||||
def update_groups(self, username, groups, character=None):
|
||||
self._dbcursor.execute(self.SQL_CHECK_USER, [self._clean_username(username)])
|
||||
row = self._dbcursor.fetchone()
|
||||
user_id = row['user_id']
|
||||
|
||||
for group in groups:
|
||||
self._dbcursor.execute(self.SQL_GET_GROUP, [group.name])
|
||||
row = self._dbcursor.fetchone()
|
||||
if not row:
|
||||
self._dbcursor.execute(self.SQL_ADD_GROUP, [group.name])
|
||||
self._dbcursor.execute(self.SQL_GET_GROUP, [group.name])
|
||||
row = self._dbcursor.fetchone()
|
||||
|
||||
self._dbcursor.execute(self.SQL_ADD_USER_GROUP, [row['group_id'], user_id])
|
||||
|
||||
def check_user(self, username):
|
||||
""" Check if the username exists """
|
||||
self._dbcursor.execute(self.SQL_CHECK_USER, [self._clean_username(username)])
|
||||
row = self._dbcursor.fetchone()
|
||||
if row:
|
||||
return True
|
||||
return False
|
||||
|
||||
def delete_user(self, uid):
|
||||
""" Delete a user """
|
||||
return True
|
||||
|
||||
def disable_user(self, uid):
|
||||
""" Disable a user """
|
||||
#self._dbcursor.execute(self.SQL_DIS_USER, [self._gen_user_token(), uid])
|
||||
try:
|
||||
self._dbcursor.execute(self.SQL_DIS_GROUP, [uid])
|
||||
except IntegrityError:
|
||||
# Record already exists, skip it
|
||||
pass
|
||||
return True
|
||||
|
||||
def enable_user(self, uid, password):
|
||||
""" Enable a user """
|
||||
pwhash = self._gen_mw_hash(password)
|
||||
self._dbcursor.execute(self.SQL_ENABLE_USER, [pwhash, uid])
|
||||
self._dbcursor.execute(self.SQL_ENABLE_GROUP, [uid])
|
||||
return True
|
||||
|
||||
def reset_password(self, uid, password):
|
||||
""" Reset the user's password """
|
||||
return self.enable_user(uid, password)
|
||||
|
||||
|
||||
ServiceClass = 'PhpBBService'
|
||||
77
app/sso/services/postracker/__init__.py
Normal file
77
app/sso/services/postracker/__init__.py
Normal file
@@ -0,0 +1,77 @@
|
||||
import hashlib
|
||||
import random
|
||||
from django.db import transaction, IntegrityError
|
||||
from sso.services import BaseDBService
|
||||
import settings
|
||||
|
||||
class POSTrackerService(BaseDBService):
|
||||
"""
|
||||
POS Tracker Class, allows registration.
|
||||
|
||||
"""
|
||||
|
||||
settings = { 'require_user': False,
|
||||
'require_password': False,
|
||||
'provide_login': False,
|
||||
'use_auth_username': False,
|
||||
'database_name': 'dreddit_pos' }
|
||||
|
||||
SQL_ADD_USER = r"INSERT INTO pos3_user (eve_id, name, pass, email, access, corp, alliance_id) VALUES (%s, %s, %s, %s, 1, %s, %s)"
|
||||
SQL_DIS_USER = r"UPDATE pos3_user SET pass = '', away = 1 WHERE name = %s"
|
||||
SQL_DEL_USER = r"DELETE FROM pos3_user WHERE name = %s"
|
||||
SQL_ENABLE_USER = r"UPDATE pos3_user SET pass = %s, away = 0 WHERE name = %s"
|
||||
SQL_CHECK_USER = r"SELECT name from pos3_user WHERE name = %s"
|
||||
|
||||
def _gen_salt(self):
|
||||
return hashlib.md5("%x" % random.randint(0, 2147483647)).hexdigest()[:8]
|
||||
|
||||
def _gen_pwhash(self, password, salt=None):
|
||||
if not salt:
|
||||
salt = self._gen_salt()
|
||||
pwhash = hashlib.md5("%s%s" % (salt, password)).hexdigest()
|
||||
return (pwhash, salt)
|
||||
|
||||
def add_user(self, username, password, **kwargs):
|
||||
""" Add a user """
|
||||
email = kwargs['user'].email
|
||||
pwhash, salt = self._gen_pwhash(password)
|
||||
eveid = kwargs['character'].eveaccount_set.all()[0].api_user_id
|
||||
|
||||
corpname = kwargs['character'].corporation.name
|
||||
if kwargs['character'].corporation and kwargs['character'].corporation.alliance:
|
||||
allianceid = kwargs['character'].corporation.alliance.id
|
||||
else:
|
||||
allianceid = 0
|
||||
|
||||
self.dbcursor.execute(self.SQL_ADD_USER, [eveid, username, "%s%s" % (salt, pwhash) , email, corpname, allianceid])
|
||||
return { 'username': username, 'password': password }
|
||||
|
||||
def check_user(self, username):
|
||||
""" Check if the username exists """
|
||||
self.dbcursor.execute(self.SQL_CHECK_USER, [username])
|
||||
row = self.dbcursor.fetchone()
|
||||
if row:
|
||||
return True
|
||||
return False
|
||||
|
||||
def delete_user(self, uid):
|
||||
""" Delete a user """
|
||||
self.dbcursor.execute(self.SQL_DEL_USER, [uid])
|
||||
return True
|
||||
|
||||
def disable_user(self, uid):
|
||||
""" Disable a user """
|
||||
self.dbcursor.execute(self.SQL_DIS_USER, [uid])
|
||||
return True
|
||||
|
||||
def enable_user(self, uid, password):
|
||||
""" Enable a user """
|
||||
pwhash, salt = self._gen_pwhash(password)
|
||||
self.dbcursor.execute(self.SQL_ENABLE_USER, ["%s%s" % (salt, pwhash), uid])
|
||||
return True
|
||||
|
||||
def reset_password(self, uid, password):
|
||||
""" Reset the user's password """
|
||||
return self.enable_user(uid, password)
|
||||
|
||||
ServiceClass = 'POSTrackerService'
|
||||
70
app/sso/services/qms/__init__.py
Normal file
70
app/sso/services/qms/__init__.py
Normal file
@@ -0,0 +1,70 @@
|
||||
import hashlib
|
||||
import random
|
||||
from django.db import load_backend, transaction, IntegrityError
|
||||
from sso.services import BaseDBService
|
||||
import settings
|
||||
|
||||
class QMSService(BaseDBService):
|
||||
"""
|
||||
QMS Class, allows registration and sign-in
|
||||
|
||||
"""
|
||||
|
||||
settings = { 'require_user': False,
|
||||
'require_password': False,
|
||||
'provide_login': False,
|
||||
'use_auth_username': False,
|
||||
'database_name': 'dreddit_qms' }
|
||||
|
||||
SQL_ADD_USER = r"INSERT INTO users (ssoid, Name, passhash, salt, Email, certificate) VALUES (%s, %s, %s, %s, %s, %s)"
|
||||
SQL_DIS_USER = r"UPDATE users SET passhash = '' WHERE ssoid = %s"
|
||||
SQL_ENABLE_USER = r"UPDATE users SET passhash = %s, salt = %s, certificate = %s WHERE ssoid = %s"
|
||||
SQL_CHECK_USER = r"SELECT ssoid from users WHERE ssoid = %s"
|
||||
|
||||
def _gen_salt(self):
|
||||
return hashlib.md5("%x" % random.randint(0, 2147483647)).hexdigest()[:6]
|
||||
|
||||
def _gen_pwhash(self, password, salt=None):
|
||||
if not salt:
|
||||
salt = self._gen_salt()
|
||||
pwhash = hashlib.md5(password).hexdigest()
|
||||
cert = hashlib.md5('%s%s' % (pwhash, salt)).hexdigest()
|
||||
return (pwhash, salt, cert)
|
||||
|
||||
def add_user(self, username, password, **kwargs):
|
||||
""" Add a user """
|
||||
email = kwargs['user'].email
|
||||
pwhash, salt, cert = self._gen_pwhash(password)
|
||||
self.dbcursor.execute(self.SQL_ADD_USER, [username, username, pwhash, salt, email, cert])
|
||||
return { 'username': username, 'password': password }
|
||||
|
||||
def check_user(self, username):
|
||||
""" Check if the username exists """
|
||||
self.dbcursor.execute(self.SQL_CHECK_USER, [username])
|
||||
row = self.dbcursor.fetchone()
|
||||
if row:
|
||||
return True
|
||||
return False
|
||||
|
||||
def delete_user(self, uid):
|
||||
""" Delete a user """
|
||||
#self.dbcursor.execute(self.SQL_DEL_REV, [uid])
|
||||
#self.dbcursor.execute(self.SQL_DEL_USER, [uid])
|
||||
return True
|
||||
|
||||
def disable_user(self, uid):
|
||||
""" Disable a user """
|
||||
self.dbcursor.execute(self.SQL_DIS_USER, [uid])
|
||||
return True
|
||||
|
||||
def enable_user(self, uid, password):
|
||||
""" Enable a user """
|
||||
pwhash, salt, cert = self._gen_pwhash(password)
|
||||
self.dbcursor.execute(self.SQL_ENABLE_USER, [pwhash, salt, cert, uid])
|
||||
return True
|
||||
|
||||
def reset_password(self, uid, password):
|
||||
""" Reset the user's password """
|
||||
return self.enable_user(uid, password)
|
||||
|
||||
ServiceClass = 'QMSService'
|
||||
78
app/sso/services/smf/__init__.py
Normal file
78
app/sso/services/smf/__init__.py
Normal file
@@ -0,0 +1,78 @@
|
||||
import hashlib
|
||||
import random
|
||||
from sso.services import BaseDBService
|
||||
import settings
|
||||
|
||||
class SMFService(BaseDBService):
|
||||
"""
|
||||
SMF Class, allows registration and sign-in
|
||||
|
||||
"""
|
||||
|
||||
settings = { 'require_user': True,
|
||||
'require_password': True,
|
||||
'provide_login': False,
|
||||
'use_auth_username': False
|
||||
'can_delete': False }
|
||||
|
||||
SQL_ADD_USER = r"INSERT INTO phpbb_users (username, username_clean, user_password, user_email) VALUES (%s, %s, %s, %s)"
|
||||
SQL_DIS_USER = r"DELETE FROM phpbb_user_groups where user_id = (SELECT user_id FROM phpbb_user WHERE username = %s)"
|
||||
SQL_CHECK_USER = r"SELECT username from phpbb_user WHERE username = %s"
|
||||
|
||||
SQL_ADD_USER_GROUP = r"INSERT INTO phpbb_user_group (group_id, user_id) VALUES (%s, %s)"
|
||||
SQL_GET_GROUP = r"SELECT group_id from phpbb_groups WHERE group_name = %s"
|
||||
SQL_ADD_GROUP = r"INSERT INTO phpbb_groups (group_name) VALUES (%s)"
|
||||
|
||||
def _gen_salt(self):
|
||||
return "%x" % random.randint(0, 2147483647)
|
||||
|
||||
def _gen_hash(self, password, salt=None):
|
||||
if not salt:
|
||||
salt = self._gen_salt()
|
||||
hash = hashlib.md5('%s-%s' % (salt, hashlib.md5(password).hexdigest())).hexdigest()
|
||||
return ":B:%s:%s" % (salt, hash)
|
||||
|
||||
def add_user(self, username, password, **kwargs):
|
||||
""" Add a user """
|
||||
if 'user' in kwargs:
|
||||
email = kwargs['user'].email
|
||||
else:
|
||||
email = ''
|
||||
pwhash = self._gen_hash(password)
|
||||
|
||||
self._dbcursor.execute(self.SQL_ADD_USER, [username, pwhash, email])
|
||||
|
||||
self.update_groups(username)
|
||||
return { 'username': username, 'password': password }
|
||||
|
||||
def update_groups(self, username, groups, character=None):
|
||||
self._dbcursor.execute(self.SQL_CHECK_USER, [self._clean_username(username)])
|
||||
row = self._dbcursor.fetchone()
|
||||
user_id = row['id_member']
|
||||
|
||||
smfgrps = self._get_smf_groups()
|
||||
|
||||
grpids = []
|
||||
for group in groups:
|
||||
if group.name in smfgrps:
|
||||
grpids.append(smfgrps[group.name])
|
||||
else:
|
||||
grpids.append(self._create_smf_group(group.name))
|
||||
|
||||
# Update DB with grouplist
|
||||
self._dbcursor.execute(self.SQL_UPDATE_GROUPS, [user_id, ','.join(groupids)])
|
||||
|
||||
def check_user(self, username):
|
||||
""" Check if the username exists """
|
||||
self._dbcursor.execute(self.SQL_CHECK_USER, [self._clean_username(username)])
|
||||
row = self._dbcursor.fetchone()
|
||||
if row:
|
||||
return True
|
||||
return False
|
||||
|
||||
def reset_password(self, uid, password):
|
||||
""" Reset the user's password """
|
||||
return self.enable_user(uid, password)
|
||||
|
||||
|
||||
ServiceClass = 'SMFService'
|
||||
195
app/sso/services/ts3/__init__.py
Normal file
195
app/sso/services/ts3/__init__.py
Normal file
@@ -0,0 +1,195 @@
|
||||
import urllib
|
||||
from sso.services import BaseService
|
||||
from ts3 import TS3Server
|
||||
|
||||
class TS3Service(BaseService):
|
||||
|
||||
settings = { 'require_user': True,
|
||||
'require_password': False,
|
||||
'provide_login': False,
|
||||
'use_auth_username': False,
|
||||
'host': 'mumble.pleaseignore.com',
|
||||
'port': 10011,
|
||||
'sa_login': 'serveradmin',
|
||||
'sa_password': '',
|
||||
'vhost_id': 0,
|
||||
'authed_sgid': 12,
|
||||
'name_format': '%(alliance)s - %(corporation)s - %(name)s',
|
||||
'bookmark_name': 'TEST Alliance TS3',
|
||||
'ignore_groups': [6]}
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@property
|
||||
def conn(self):
|
||||
if not hasattr(self, '_conn'):
|
||||
self._conn = TS3Server(self.settings['host'], self.settings['port'])
|
||||
self._conn.login(self.settings['sa_login'], self.settings['sa_password'])
|
||||
self._conn.use(self.settings['vhost_id'])
|
||||
|
||||
return self._conn
|
||||
|
||||
def add_user(self, username, password, **kwargs):
|
||||
""" Add a user, returns a UID for that user """
|
||||
|
||||
details = { 'name': username,
|
||||
'corporation': kwargs['character'].corporation.ticker }
|
||||
|
||||
if kwargs['character'].corporation.alliance:
|
||||
details['alliance'] = kwargs['character'].corporation.alliance.ticker
|
||||
else:
|
||||
details['alliance'] = None
|
||||
|
||||
username = self.settings['name_format'] % details
|
||||
ret = self.conn.send_command('tokenadd', {'tokentype': 0, 'tokenid1': self.settings['authed_sgid'], 'tokenid2': 0, 'tokendescription': kwargs['character'].name.replace(' ', ''), 'tokencustomset': "ident=sso_uid value=%s|ident=sso_userid value=%s|ident=eve_charid value=%s" % (kwargs['character'].name.replace(' ', ''), kwargs['user'].id, kwargs['character'].id) })
|
||||
if 'keys' in ret and 'token' in ret['keys']:
|
||||
token = ret['keys']['token']
|
||||
url = "<a href='ts3server://%s?token=%s'>Click this link to connect and register on TS3</a>" % (self.settings['host'], token)
|
||||
return { 'username': kwargs['character'].name.replace(' ', ''), 'display name': username, 'permission token': token, 'registration url': url }
|
||||
|
||||
return None
|
||||
|
||||
def check_user(self, uid):
|
||||
""" Check if the username exists """
|
||||
# Lookup user using customsearch with sso_uid=uid
|
||||
return self._get_userid(uid)
|
||||
|
||||
def delete_user(self, uid):
|
||||
""" Delete a user by uid """
|
||||
user = self._get_userid(uid)
|
||||
if user:
|
||||
for client in self.conn.send_command('clientlist'):
|
||||
if client['keys']['client_database_id'] == user:
|
||||
self.conn.send_command('clientkick', {'clid': client['keys']['clid'], 'reasonid': 5, 'reasonmsg': 'Auth service deleted'})
|
||||
|
||||
ret = self.conn.send_command('clientdbdelete', {'cldbid': user })
|
||||
if ret == '0':
|
||||
return True
|
||||
else:
|
||||
return True
|
||||
|
||||
def disable_user(self, uid):
|
||||
""" Disable a user by uid """
|
||||
user = self._get_userid(uid)
|
||||
if user:
|
||||
ret = self.conn.send_command('servergroupdelclient', {'sgid': self.settings['authed_sgid'], 'cldbid': user })
|
||||
if ret == '0':
|
||||
|
||||
groups = self._user_group_list(user)
|
||||
for group in groups:
|
||||
self.conn.send_command('servergroupdelclient', {'sgid': groups[group], 'cldbid': user })
|
||||
|
||||
return True
|
||||
return False
|
||||
|
||||
def enable_user(self, uid, password):
|
||||
""" Enable a user by uid """
|
||||
|
||||
user = self._get_userid(uid)
|
||||
if user:
|
||||
ret = self.conn.send_command('servergroupaddclient', {'sgid': self.settings['authed_sgid'], 'cldbid': user })
|
||||
if ret == '0':
|
||||
return True
|
||||
|
||||
def reset_password(self, uid, password):
|
||||
""" Reset the user's password """
|
||||
pass
|
||||
|
||||
def login(uid):
|
||||
""" Login the user and provide cookies back """
|
||||
pass
|
||||
|
||||
def _group_by_name(self, groupname):
|
||||
if not hasattr(self, '__group_cache') or not self.__group_cache:
|
||||
self.__group_cache = self.conn.send_command('servergrouplist')
|
||||
for group in self.__group_cache:
|
||||
if group['keys']['name'] == groupname:
|
||||
return group['keys']['sgid']
|
||||
|
||||
return None
|
||||
|
||||
def _get_userid(self, uid):
|
||||
""" Finds the TS3 ID of a user from their UID """
|
||||
|
||||
ret = self.conn.send_command('customsearch', {'ident': 'sso_uid', 'pattern': uid})
|
||||
if ret and 'keys' in ret and 'cldbid' in ret['keys']:
|
||||
return ret['keys']['cldbid']
|
||||
|
||||
def _create_group(self, groupname):
|
||||
""" Creates a Server Group and returns the SGID """
|
||||
|
||||
sgid = self._group_by_name(groupname)
|
||||
if not sgid:
|
||||
ret = self.conn.send_command('servergroupadd', { 'name': groupname })
|
||||
self.__group_cache = None
|
||||
sgid = ret['keys']['sgid']
|
||||
self.conn.send_command('servergroupaddperm', { 'sgid': sgid, 'permsid': 'i_group_needed_modify_power', 'permvalue': 75, 'permnegated': 0, 'permskip': 0 })
|
||||
self.conn.send_command('servergroupaddperm', { 'sgid': sgid, 'permsid': 'i_group_needed_member_add_power', 'permvalue': 100, 'permnegated': 0, 'permskip': 0 })
|
||||
self.conn.send_command('servergroupaddperm', { 'sgid': sgid, 'permsid': 'i_group_needed_member_remove_power', 'permvalue': 100, 'permnegated': 0, 'permskip': 0 })
|
||||
return sgid
|
||||
|
||||
def _group_list(self):
|
||||
""" List of all groups on the TS server """
|
||||
|
||||
if not hasattr(self, '__group_cache') or not self.__group_cache:
|
||||
self.__group_cache = self.conn.send_command('servergrouplist')
|
||||
outlist = {}
|
||||
for group in self.__group_cache:
|
||||
outlist[group['keys']['name']] = group['keys']['sgid']
|
||||
return outlist
|
||||
|
||||
def _user_group_list(self, cldbid):
|
||||
""" List of all groups assigned to a user """
|
||||
|
||||
groups = self.conn.send_command('servergroupsbyclientid', {'cldbid': cldbid })
|
||||
outlist = {}
|
||||
|
||||
if type(groups) == list:
|
||||
for group in groups:
|
||||
outlist[group['keys']['name']] = group['keys']['sgid']
|
||||
elif type(groups) == dict:
|
||||
outlist[groups['keys']['name']] = groups['keys']['sgid']
|
||||
|
||||
return outlist
|
||||
|
||||
def update_groups(self, uid, groups, character=None):
|
||||
""" Update the UID's groups based on the provided list """
|
||||
|
||||
cldbid = self._get_userid(uid)
|
||||
|
||||
if cldbid:
|
||||
tsgrplist = self._group_list()
|
||||
usrgrplist = self._user_group_list(cldbid)
|
||||
|
||||
# Add groups
|
||||
if groups.count():
|
||||
for g in groups:
|
||||
if not g.name in tsgrplist:
|
||||
tsgrplist[g.name] = self._create_group(g.name)
|
||||
if not g.name in usrgrplist:
|
||||
self.conn.send_command('servergroupaddclient', {'sgid': tsgrplist[g.name], 'cldbid': cldbid })
|
||||
usrgrplist[g.name] = tsgrplist[g.name]
|
||||
|
||||
# Add to corporation groups
|
||||
if character and character.corporation:
|
||||
if character.corporation.ticker in usrgrplist:
|
||||
del usrgrplist[character.corporation.ticker]
|
||||
else:
|
||||
if not character.corporation.ticker in tsgrplist:
|
||||
tsgrplist[character.corporation.ticker] = self._create_group(character.corporation.ticker)
|
||||
self.conn.send_command('servergroupaddclient', {'sgid': tsgrplist[character.corporation.ticker], 'cldbid': cldbid })
|
||||
|
||||
# Remove OKed groups from the delete list
|
||||
for g in groups:
|
||||
if g.name in usrgrplist:
|
||||
del usrgrplist[g.name]
|
||||
|
||||
# Remove ignored and admin groups
|
||||
for k, v in usrgrplist.items():
|
||||
if not int(v) == self.settings['authed_sgid'] and not int(v) in self.settings['ignore_groups']:
|
||||
self.conn.send_command('servergroupdelclient', {'sgid': v, 'cldbid': cldbid })
|
||||
|
||||
return True
|
||||
|
||||
ServiceClass = 'TS3Service'
|
||||
257
app/sso/services/ts3/ts3.py
Normal file
257
app/sso/services/ts3/ts3.py
Normal file
@@ -0,0 +1,257 @@
|
||||
import time
|
||||
import socket
|
||||
import logging
|
||||
|
||||
class ConnectionError():
|
||||
|
||||
def __init__(self, ip, port):
|
||||
self.ip = ip
|
||||
self.port = port
|
||||
|
||||
def __str__():
|
||||
return 'Error connecting to host %s port %s' % (self.ip, self.port)
|
||||
|
||||
ts3_escape = { '/': r"\/",
|
||||
' ': r'\s',
|
||||
'|': r'\p',
|
||||
"\a": r'\a',
|
||||
"\b": r'\b',
|
||||
"\f": r'\f',
|
||||
"\n": r'\n',
|
||||
"\r": r'\r',
|
||||
"\t": r'\t',
|
||||
"\v": r'\v' }
|
||||
|
||||
|
||||
class TS3Proto():
|
||||
|
||||
bytesin = 0
|
||||
bytesout = 0
|
||||
|
||||
_connected = False
|
||||
|
||||
def __init__(self):
|
||||
self._log = logging.getLogger('%s.%s' % (__name__, self.__class__.__name__))
|
||||
pass
|
||||
|
||||
def connect(self, ip, port):
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
try:
|
||||
s.connect((ip, port))
|
||||
except:
|
||||
#raise ConnectionError(ip, port)
|
||||
raise
|
||||
else:
|
||||
self._sock = s
|
||||
self._sockfile = s.makefile('r', 0)
|
||||
|
||||
data = self._sockfile.readline()
|
||||
if data.strip() == "TS3":
|
||||
self._sockfile.readline()
|
||||
self._connected = True
|
||||
return True
|
||||
|
||||
def disconnect(self):
|
||||
self.send_command("quit")
|
||||
self._sock.close()
|
||||
self._sock = None
|
||||
self._connected = False
|
||||
self._log.info('Disconnected')
|
||||
|
||||
def send_command(self, command, keys=None, opts=None):
|
||||
cmd = self.construct_command(command, keys=keys, opts=opts)
|
||||
self.send('%s\n' % cmd)
|
||||
|
||||
data = []
|
||||
|
||||
while True:
|
||||
resp = self._sockfile.readline()
|
||||
resp = self.parse_command(resp)
|
||||
if not 'command' in resp:
|
||||
data.append(resp)
|
||||
else:
|
||||
break
|
||||
|
||||
if resp['command'] == 'error':
|
||||
if data and resp['keys']['id'] == '0':
|
||||
if len(data) > 1:
|
||||
return data
|
||||
else:
|
||||
return data[0]
|
||||
else:
|
||||
return resp['keys']['id']
|
||||
|
||||
def construct_command(self, command, keys=None, opts=None):
|
||||
"""
|
||||
Constructs a TS3 formatted command string
|
||||
|
||||
Keys can have a single nested list to construct a nested parameter
|
||||
|
||||
@param command: Command list
|
||||
@type command: string
|
||||
@param keys: Key/Value pairs
|
||||
@type keys: dict
|
||||
@param opts: Options
|
||||
@type opts: list
|
||||
"""
|
||||
|
||||
cstr = [command]
|
||||
|
||||
# Add the keys and values, escape as needed
|
||||
if keys:
|
||||
for key in keys:
|
||||
if isinstance(keys[key], list):
|
||||
ncstr = []
|
||||
for nest in keys[key]:
|
||||
ncstr.append("%s=%s" % (key, self._escape_str(nest)))
|
||||
cstr.append("|".join(ncstr))
|
||||
else:
|
||||
cstr.append("%s=%s" % (key, self._escape_str(keys[key])))
|
||||
|
||||
# Add in options
|
||||
if opts:
|
||||
for opt in opts:
|
||||
cstr.append("-%s" % opt)
|
||||
|
||||
return " ".join(cstr)
|
||||
|
||||
def parse_command(self, commandstr):
|
||||
"""
|
||||
Parses a TS3 command string into command/keys/opts tuple
|
||||
|
||||
@param commandstr: Command string
|
||||
@type commandstr: string
|
||||
"""
|
||||
|
||||
if len(commandstr.split('|')) > 1:
|
||||
vals = []
|
||||
for cmd in commandstr.split('|'):
|
||||
vals.append(self.parse_command(cmd))
|
||||
return vals
|
||||
|
||||
cmdlist = commandstr.strip().split(' ')
|
||||
command = None
|
||||
keys = {}
|
||||
opts = []
|
||||
|
||||
for key in cmdlist:
|
||||
v = key.strip().split('=')
|
||||
if len(v) > 1:
|
||||
# Key
|
||||
if len > 2:
|
||||
# Fix the stupidities in TS3 escaping
|
||||
v = [v[0], '='.join(v[1:])]
|
||||
key, value = v
|
||||
keys[key] = self._unescape_str(value)
|
||||
elif v[0][0] == '-':
|
||||
# Option
|
||||
opts.append(v[0][1:])
|
||||
else:
|
||||
command = v[0]
|
||||
|
||||
d = {'keys': keys, 'opts': opts}
|
||||
if command:
|
||||
d['command'] = command
|
||||
return d
|
||||
|
||||
@staticmethod
|
||||
def _escape_str(value):
|
||||
"""
|
||||
Escape a value into a TS3 compatible string
|
||||
|
||||
@param value: Value
|
||||
@type value: string/int
|
||||
|
||||
"""
|
||||
|
||||
if isinstance(value, int): return "%d" % value
|
||||
value = value.replace("\\", r'\\')
|
||||
for i, j in ts3_escape.iteritems():
|
||||
value = value.replace(i, j)
|
||||
return value
|
||||
|
||||
@staticmethod
|
||||
def _unescape_str(value):
|
||||
"""
|
||||
Unescape a TS3 compatible string into a normal string
|
||||
|
||||
@param value: Value
|
||||
@type value: string/int
|
||||
|
||||
"""
|
||||
|
||||
if isinstance(value, int): return "%d" % value
|
||||
value = value.replace(r"\\", "\\")
|
||||
for i, j in ts3_escape.iteritems():
|
||||
value = value.replace(j, i)
|
||||
return value
|
||||
|
||||
|
||||
def send(self, payload):
|
||||
if self._connected:
|
||||
self._log.debug('Sent: %s' % payload)
|
||||
self._sockfile.write(payload)
|
||||
|
||||
|
||||
class TS3Server(TS3Proto):
|
||||
def __init__(self, ip, port, id=0, sock=None):
|
||||
"""
|
||||
Abstraction class for TS3 Servers
|
||||
|
||||
@param ip: IP Address
|
||||
@type ip: str
|
||||
@param port: Port Number
|
||||
@type port: int
|
||||
|
||||
"""
|
||||
TS3Proto.__init__(self)
|
||||
|
||||
if not sock:
|
||||
if self.connect(ip, port) and id > 0:
|
||||
self.use(id)
|
||||
else:
|
||||
self._sock = sock
|
||||
self._sockfile = sock.makefile('r', 0)
|
||||
self._connected = True
|
||||
|
||||
def login(self, username, password):
|
||||
"""
|
||||
Login to the TS3 Server
|
||||
|
||||
@param username: Username
|
||||
@type username: str
|
||||
@param password: Password
|
||||
@type password: str
|
||||
"""
|
||||
d = self.send_command('login', keys={'client_login_name': username, 'client_login_password': password })
|
||||
if d == 0:
|
||||
self._log.info('Login Successful')
|
||||
return True
|
||||
return False
|
||||
|
||||
def serverlist(self):
|
||||
"""
|
||||
Get a list of all Virtual Servers on the connected TS3 instance
|
||||
"""
|
||||
if self._connected:
|
||||
return self.send_command('serverlist')
|
||||
|
||||
def gm(self, msg):
|
||||
"""
|
||||
Send a global message to the current Virtual Server
|
||||
|
||||
@param msg: Message
|
||||
@type ip: str
|
||||
"""
|
||||
if self._connected:
|
||||
return self.send_command('gm', keys={'msg': msg})
|
||||
|
||||
def use(self, id):
|
||||
"""
|
||||
Use a particular Virtual Server instance
|
||||
|
||||
@param id: Virtual Server ID
|
||||
@type id: int
|
||||
"""
|
||||
if self._connected and id > 0:
|
||||
self.send_command('use', keys={'sid': id})
|
||||
95
app/sso/services/wiki/__init__.py
Normal file
95
app/sso/services/wiki/__init__.py
Normal file
@@ -0,0 +1,95 @@
|
||||
import hashlib
|
||||
import random
|
||||
from django.db import load_backend, transaction, IntegrityError
|
||||
from sso.services import BaseDBService
|
||||
import settings
|
||||
|
||||
class MediawikiService(BaseDBService):
|
||||
"""
|
||||
Mediawiki Class, allows registration and sign-in
|
||||
|
||||
"""
|
||||
|
||||
settings = { 'require_user': False,
|
||||
'require_password': False,
|
||||
'provide_login': False,
|
||||
'use_auth_username': False,
|
||||
'database_name': 'dreddit_wiki' }
|
||||
|
||||
default_options = 'rows=80\ncols=50'
|
||||
|
||||
|
||||
SQL_ADD_USER = r"INSERT INTO user (user_name, user_password, user_newpassword, user_email, user_options) VALUES (%s, %s, '', %s, %s)"
|
||||
SQL_DIS_USER = r"UPDATE user SET user_password = '', user_email = '', user_token = %s WHERE user_name = %s"
|
||||
SQL_DIS_GROUP = r"INSERT INTO user_groups (ug_user, ug_group) VALUES ((SELECT user_id FROM user WHERE user_name = %s), 'Disabled')"
|
||||
SQL_ENABLE_USER = r"UPDATE user SET user_password = %s WHERE user_name = %s"
|
||||
SQL_ENABLE_GROUP = r"DELETE FROM user_groups where ug_user = (SELECT user_id FROM user WHERE user_name = %s) AND ug_group = 'Disabled'"
|
||||
SQL_CHECK_USER = r"SELECT user_name from user WHERE user_name = %s"
|
||||
|
||||
SQL_DEL_REV = r"UPDATE revision SET rev_user = (SELECT user_id FROM user WHERE user_name = 'DeletedUser'), rev_user_text = 'DeletedUser' WHERE rev_user = (SELECT user_id FROM user WHERE user_name = %s)"
|
||||
SQL_DEL_USER = r"DELETE FROM user WHERE user_name = %s"
|
||||
|
||||
def _gen_salt(self):
|
||||
return "%x" % random.randint(0, 2147483647)
|
||||
|
||||
def _gen_mw_hash(self, password, salt=None):
|
||||
if not salt:
|
||||
salt = self._gen_salt()
|
||||
hash = hashlib.md5('%s-%s' % (salt, hashlib.md5(password).hexdigest())).hexdigest()
|
||||
return ":B:%s:%s" % (salt, hash)
|
||||
|
||||
def _gen_user_token(self):
|
||||
hash = hashlib.md5(self._gen_salt()).hexdigest()
|
||||
return hash
|
||||
|
||||
def _clean_username(self, username):
|
||||
username = username.strip()
|
||||
return username[0].upper() + username[1:]
|
||||
|
||||
def add_user(self, username, password, **kwargs):
|
||||
""" Add a user """
|
||||
if 'user' in kwargs:
|
||||
email = kwargs['user'].email
|
||||
else:
|
||||
email = ''
|
||||
pwhash = self._gen_mw_hash(password)
|
||||
self.dbcursor.execute(self.SQL_ADD_USER, [self._clean_username(username), pwhash, email, self.default_options])
|
||||
return { 'username': self._clean_username(username), 'password': password }
|
||||
|
||||
def check_user(self, username):
|
||||
""" Check if the username exists """
|
||||
self.dbcursor.execute(self.SQL_CHECK_USER, [self._clean_username(username)])
|
||||
row = self.dbcursor.fetchone()
|
||||
if row:
|
||||
return True
|
||||
return False
|
||||
|
||||
def delete_user(self, uid):
|
||||
""" Delete a user """
|
||||
self.dbcursor.execute(self.SQL_DEL_REV, [uid])
|
||||
self.dbcursor.execute(self.SQL_DEL_USER, [uid])
|
||||
return True
|
||||
|
||||
def disable_user(self, uid):
|
||||
""" Disable a user """
|
||||
#self.dbcursor.execute(self.SQL_DIS_USER, [self._gen_user_token(), uid])
|
||||
try:
|
||||
self.dbcursor.execute(self.SQL_DIS_GROUP, [uid])
|
||||
except IntegrityError:
|
||||
# Record already exists, skip it
|
||||
pass
|
||||
return True
|
||||
|
||||
def enable_user(self, uid, password):
|
||||
""" Enable a user """
|
||||
pwhash = self._gen_mw_hash(password)
|
||||
self.dbcursor.execute(self.SQL_ENABLE_USER, [pwhash, uid])
|
||||
self.dbcursor.execute(self.SQL_ENABLE_GROUP, [uid])
|
||||
return True
|
||||
|
||||
def reset_password(self, uid, password):
|
||||
""" Reset the user's password """
|
||||
return self.enable_user(uid, password)
|
||||
|
||||
|
||||
ServiceClass = 'MediawikiService'
|
||||
95
app/sso/tasks.py
Normal file
95
app/sso/tasks.py
Normal file
@@ -0,0 +1,95 @@
|
||||
from celery.decorators import task
|
||||
from eve_api.models import EVEAccount, EVEPlayerCorporation, EVEPlayerAlliance
|
||||
from sso.models import ServiceAccount
|
||||
from django.contrib.auth.models import User
|
||||
from django.db.models import signals
|
||||
from utils import installed
|
||||
|
||||
|
||||
# Signals that the tasks need to listen for
|
||||
def eveapi_deleted(sender, instance, **kwargs):
|
||||
if instance.user:
|
||||
update_user_access.delay(user=instance.user.id)
|
||||
|
||||
signals.post_delete.connect(eveapi_deleted, sender=EVEAccount)
|
||||
|
||||
|
||||
@task()
|
||||
def update_user_access(user, **kwargs):
|
||||
"""
|
||||
Process all corporate and alliance entries and correct
|
||||
access groups.
|
||||
"""
|
||||
|
||||
user = User.objects.get(id=user)
|
||||
|
||||
# Create a list of all Corp and Alliance groups
|
||||
corpgroups = []
|
||||
for corp in EVEPlayerCorporation.objects.filter(group__isnull=False):
|
||||
if corp.group:
|
||||
corpgroups.append(corp.group)
|
||||
for alliance in EVEPlayerAlliance.objects.filter(group__isnull=False):
|
||||
if alliance.group:
|
||||
corpgroups.append(alliance.group)
|
||||
|
||||
# Create a list of Char groups
|
||||
chargroups = []
|
||||
for eacc in EVEAccount.objects.filter(user=user):
|
||||
if eacc.api_status in [1, 3]:
|
||||
for char in eacc.characters.all():
|
||||
if char.corporation.group:
|
||||
chargroups.append(char.corporation.group)
|
||||
if char.corporation.alliance and char.corporation.alliance.group:
|
||||
chargroups.append(char.corporation.alliance.group)
|
||||
|
||||
# Generate the list of groups to add/remove
|
||||
delgroups = set(set(user.groups.all()) & set(corpgroups)) - set(chargroups)
|
||||
addgroups = set(chargroups) - set(set(user.groups.all()) & set(corpgroups))
|
||||
|
||||
# Check that user's groups fufil requirements
|
||||
if installed('groups'):
|
||||
for g in user.groups.filter(groupinformation__parent__isnull=False):
|
||||
print g
|
||||
if not g in delgroups and not g.groupinformation.parent in user.groups.all():
|
||||
delgroups.add(g)
|
||||
|
||||
for g in delgroups:
|
||||
if g in user.groups.all():
|
||||
user.groups.remove(g)
|
||||
|
||||
for g in addgroups:
|
||||
if not g in user.groups.all():
|
||||
user.groups.add(g)
|
||||
|
||||
# For users set to not active, delete all accounts
|
||||
if not user.is_active:
|
||||
for servacc in ServiceAccount.objects.filter(user=user):
|
||||
servacc.active = 0
|
||||
servacc.save()
|
||||
pass
|
||||
|
||||
# For each of the user's services, check they're in a valid group for it and enable/disable as needed.
|
||||
for servacc in ServiceAccount.objects.filter(user=user):
|
||||
if not (set(user.groups.all()) & set(servacc.service.groups.all())):
|
||||
if servacc.active:
|
||||
servacc.active = 0
|
||||
servacc.save()
|
||||
pass
|
||||
else:
|
||||
if not servacc.active:
|
||||
servacc.active = 1
|
||||
servacc.save()
|
||||
pass
|
||||
|
||||
update_service_groups.delay(user_id=user.id)
|
||||
|
||||
|
||||
@task(ignore_result=True)
|
||||
def update_service_groups(user_id):
|
||||
for service in ServiceAccount.objects.filter(user=user_id, active=True).select_related('service__api'):
|
||||
api = service.service.api_class
|
||||
try:
|
||||
api.update_groups(service.service_uid, service.user.groups.all(), service.character)
|
||||
except:
|
||||
print "Error updating %s %s" % (service.service, service.service_uid)
|
||||
pass
|
||||
0
app/sso/templatetags/__init__.py
Normal file
0
app/sso/templatetags/__init__.py
Normal file
20
app/sso/templatetags/installed.py
Normal file
20
app/sso/templatetags/installed.py
Normal file
@@ -0,0 +1,20 @@
|
||||
from django import template
|
||||
from django.conf import settings
|
||||
from django.template.defaultfilters import stringfilter
|
||||
|
||||
register = template.Library()
|
||||
|
||||
@register.filter
|
||||
@stringfilter
|
||||
def installed(value):
|
||||
apps = settings.INSTALLED_APPS
|
||||
if "." in value:
|
||||
for app in apps:
|
||||
if app == value:
|
||||
return True
|
||||
else:
|
||||
for app in apps:
|
||||
fields = app.split(".")
|
||||
if fields[-1] == value:
|
||||
return True
|
||||
return False
|
||||
33
app/sso/templatetags/naturaltimediff.py
Normal file
33
app/sso/templatetags/naturaltimediff.py
Normal file
@@ -0,0 +1,33 @@
|
||||
from django import template
|
||||
|
||||
register = template.Library()
|
||||
|
||||
MOMENT = 120 # duration in seconds within which the time difference
|
||||
# will be rendered as 'a moment ago'
|
||||
|
||||
@register.filter
|
||||
def naturaltimediff(value):
|
||||
"""
|
||||
Finds the difference between the datetime value given and now()
|
||||
and returns appropriate humanize form
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
if isinstance(value, datetime):
|
||||
delta = datetime.now() - value
|
||||
if delta.days > 6:
|
||||
return value.strftime("%b %d") # May 15
|
||||
if delta.days > 1:
|
||||
return value.strftime("%A") # Wednesday
|
||||
elif delta.days == 1:
|
||||
return 'yesterday' # yesterday
|
||||
elif delta.seconds > 3600:
|
||||
return str(delta.seconds / 3600 ) + ' hours ago' # 3 hours ago
|
||||
elif delta.seconds > MOMENT:
|
||||
return str(delta.seconds/60) + ' minutes ago' # 29 minutes ago
|
||||
else:
|
||||
return 'a moment ago' # a moment ago
|
||||
return defaultfilters.date(value)
|
||||
else:
|
||||
return str(value)
|
||||
23
app/sso/tests.py
Normal file
23
app/sso/tests.py
Normal file
@@ -0,0 +1,23 @@
|
||||
"""
|
||||
This file demonstrates two different styles of tests (one doctest and one
|
||||
unittest). These will both pass when you run "manage.py test".
|
||||
|
||||
Replace these with more appropriate tests for your application.
|
||||
"""
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
class SimpleTest(TestCase):
|
||||
def test_basic_addition(self):
|
||||
"""
|
||||
Tests that 1 + 1 always equals 2.
|
||||
"""
|
||||
self.failUnlessEqual(1 + 1, 2)
|
||||
|
||||
__test__ = {"doctest": """
|
||||
Another way to test that 1 + 1 is equal to 2.
|
||||
|
||||
>>> 1 + 1 == 2
|
||||
True
|
||||
"""}
|
||||
|
||||
23
app/sso/urls.py
Normal file
23
app/sso/urls.py
Normal file
@@ -0,0 +1,23 @@
|
||||
from django.conf.urls.defaults import *
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
from sso import views
|
||||
|
||||
urlpatterns = patterns('',
|
||||
('^$', views.profile),
|
||||
(r'^profile/$', views.profile),
|
||||
(r'^profile/add/service', views.service_add),
|
||||
(r'^profile/del/service/$', views.service_del),
|
||||
(r'^profile/del/service/(?P<serviceid>\d+)/$', views.service_del),
|
||||
(r'^profile/reset/service/(?P<serviceid>\d+)/$', views.service_reset),
|
||||
(r'^profile/reset/service/(?P<serviceid>\d+)/(?P<accept>\d+)$', views.service_reset),
|
||||
(r'^profile/apipassword/', views.set_apipasswd),
|
||||
(r'^profile/refresh/', views.refresh_access),
|
||||
(r'^profile/refresh/(?P<userid>\d+)/', views.refresh_access),
|
||||
(r'^users/(?P<username>.*)/$', views.user_view),
|
||||
(r'^users/$', views.user_lookup),
|
||||
)
|
||||
|
||||
urlpatterns += patterns('django.views.generic.simple',
|
||||
('^$', 'redirect_to', {'url': reverse('sso.views.profile')}),
|
||||
)
|
||||
246
app/sso/views.py
Normal file
246
app/sso/views.py
Normal file
@@ -0,0 +1,246 @@
|
||||
import hashlib
|
||||
import random
|
||||
import re
|
||||
import unicodedata
|
||||
import celery
|
||||
|
||||
from django.http import HttpResponse
|
||||
from django.shortcuts import render_to_response, get_object_or_404, redirect
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.template import RequestContext
|
||||
from django.core import serializers
|
||||
from django.conf import settings
|
||||
|
||||
from utils import installed
|
||||
|
||||
from eve_api.models import EVEAccount, EVEPlayerCharacter
|
||||
from eve_api.tasks import import_apikey, import_apikey_result, update_user_access
|
||||
|
||||
from eve_proxy.models import ApiAccessLog
|
||||
|
||||
from sso.models import ServiceAccount, Service, SSOUser, ExistingUser, ServiceError
|
||||
from sso.forms import UserServiceAccountForm, ServiceAccountResetForm, UserLookupForm, APIPasswordForm
|
||||
|
||||
@login_required
|
||||
def profile(request):
|
||||
""" Displays the user's profile page """
|
||||
|
||||
user = request.user
|
||||
try:
|
||||
profile = request.user.get_profile()
|
||||
except SSOUser.DoesNotExist:
|
||||
profile = SSOUser(user=request.user)
|
||||
profile.save()
|
||||
|
||||
return render_to_response('sso/profile.html', locals(), context_instance=RequestContext(request))
|
||||
|
||||
|
||||
@login_required
|
||||
def service_add(request):
|
||||
""" Add a service to a user's account """
|
||||
|
||||
clsform = UserServiceAccountForm(request.user)
|
||||
|
||||
if request.method == 'POST':
|
||||
form = clsform(request.POST)
|
||||
if form.is_valid():
|
||||
|
||||
acc = ServiceAccount(user=request.user, service=form.cleaned_data['service'])
|
||||
acc.character = form.cleaned_data['character']
|
||||
|
||||
if acc.service.settings['require_password']:
|
||||
if settings.GENERATE_SERVICE_PASSWORD:
|
||||
acc.password = hashlib.sha1('%s%s%s' % (form.cleaned_data['character'].name, settings.SECRET_KEY, random.randint(0, 2147483647))).hexdigest()
|
||||
else:
|
||||
acc.password = form.cleaned_data['password']
|
||||
else:
|
||||
acc.password = None
|
||||
|
||||
if acc.service.settings['use_auth_username']:
|
||||
username = request.user.username
|
||||
else:
|
||||
# Decode unicode and remove invalid characters
|
||||
username = re.sub('[^a-zA-Z0-9_-]+', '', unicodedata.normalize('NFKD', acc.character.name).encode('ASCII', 'ignore'))
|
||||
|
||||
if acc.service.api_class.check_user(username):
|
||||
error = "Username already exists on the target service, please contact an admin."
|
||||
else:
|
||||
ret = acc.service.api_class.add_user(username, acc.password, user=request.user, character=acc.character)
|
||||
if ret:
|
||||
acc.service_uid = ret['username']
|
||||
acc.save()
|
||||
error = None
|
||||
else:
|
||||
error = "Error creating account on the service, please retry or contact an admin if the error persists."
|
||||
|
||||
return render_to_response('sso/serviceaccount/created.html', locals(), context_instance=RequestContext(request))
|
||||
|
||||
else:
|
||||
availserv = Service.objects.filter(groups__in=request.user.groups.all()).exclude(id__in=ServiceAccount.objects.filter(user=request.user).values('service'))
|
||||
if len(availserv) == 0:
|
||||
return render_to_response('sso/serviceaccount/noneavailable.html', locals(), context_instance=RequestContext(request))
|
||||
else:
|
||||
form = clsform() # An unbound form
|
||||
|
||||
return render_to_response('sso/serviceaccount/index.html', locals())
|
||||
|
||||
|
||||
@login_required
|
||||
def service_del(request, serviceid=0):
|
||||
""" Delete a service from a user's account """
|
||||
|
||||
if serviceid > 0:
|
||||
try:
|
||||
acc = ServiceAccount.objects.get(id=serviceid)
|
||||
except ServiceAccount.DoesNotExist:
|
||||
return redirect('sso.views.profile')
|
||||
|
||||
if not acc.user == request.user:
|
||||
return redirect('sso.views.profile')
|
||||
|
||||
if request.method == 'POST':
|
||||
if 'confirm-delete' in request.POST:
|
||||
try:
|
||||
acc.delete()
|
||||
except ServiceError:
|
||||
messages.add_message(request, messages.ERROR, "Error deleting the service account, try again later.")
|
||||
else:
|
||||
messages.add_message(request, messages.INFO, "Service account successfully deleted.")
|
||||
else:
|
||||
return render_to_response('sso/serviceaccount/deleteconfirm.html', locals(), context_instance=RequestContext(request))
|
||||
|
||||
return redirect('sso.views.profile')
|
||||
|
||||
|
||||
@login_required
|
||||
def service_reset(request, serviceid=0):
|
||||
""" Reset a user's password on a service """
|
||||
|
||||
if serviceid > 0:
|
||||
try:
|
||||
acc = ServiceAccount.objects.get(id=serviceid)
|
||||
except ServiceAccount.DoesNotExist:
|
||||
return redirect('sso.views.profile')
|
||||
|
||||
# If the account is inactive, or the service doesn't require a password, redirect
|
||||
if not acc.active or ('require_password' in acc.service.settings and not acc.service.settings['require_password']):
|
||||
return redirect('sso.views.profile')
|
||||
|
||||
if acc.user == request.user:
|
||||
if not request.method == 'POST':
|
||||
form = ServiceAccountResetForm()
|
||||
return render_to_response('sso/serviceaccount/reset.html', locals(), context_instance=RequestContext(request))
|
||||
|
||||
form = ServiceAccountResetForm(request.POST)
|
||||
if form.is_valid():
|
||||
if settings.GENERATE_SERVICE_PASSWORD:
|
||||
passwd = hashlib.sha1('%s%s%s' % (acc.service_uid, settings.SECRET_KEY, random.randint(0, 2147483647))).hexdigest()
|
||||
else:
|
||||
passwd = form.cleaned_data['password']
|
||||
|
||||
api = acc.service.api_class
|
||||
if not api.reset_password(acc.service_uid, passwd):
|
||||
error = True
|
||||
return render_to_response('sso/serviceaccount/resetcomplete.html', locals(), context_instance=RequestContext(request))
|
||||
else:
|
||||
return render_to_response('sso/serviceaccount/reset.html', locals(), context_instance=RequestContext(request))
|
||||
|
||||
return redirect('sso.views.profile')
|
||||
|
||||
|
||||
@login_required
|
||||
def user_view(request, username=None):
|
||||
""" View a user's profile as a admin """
|
||||
|
||||
if username:
|
||||
try:
|
||||
user = User.objects.get(username=username)
|
||||
except User.DoesNotExist:
|
||||
return redirect('sso.views.user_lookup')
|
||||
else:
|
||||
return redirect('sso.views.user_lookup')
|
||||
|
||||
profile = user.get_profile()
|
||||
is_admin = request.user.is_staff
|
||||
if is_admin:
|
||||
services = ServiceAccount.objects.select_related('service').filter(user=user).only('service__name', 'service_uid', 'active')
|
||||
characters = EVEPlayerCharacter.objects.select_related('corporation').filter(eveaccount__user=user).only('id', 'name', 'corporation__name')
|
||||
|
||||
return render_to_response('sso/lookup/user.html', locals(), context_instance=RequestContext(request))
|
||||
|
||||
|
||||
@login_required
|
||||
def user_lookup(request):
|
||||
""" Lookup a user's account by providing a matching criteria """
|
||||
|
||||
form = UserLookupForm()
|
||||
|
||||
if request.method == 'POST':
|
||||
form = UserLookupForm(request.POST)
|
||||
if form.is_valid():
|
||||
users = None
|
||||
uids = []
|
||||
if form.cleaned_data['type'] == '1':
|
||||
users = User.objects.filter(username__icontains=form.cleaned_data['username']).only('username')
|
||||
elif form.cleaned_data['type'] == '2':
|
||||
uid = EVEAccount.objects.filter(characters__name__icontains=form.cleaned_data['username']).values('user')
|
||||
for u in uid:
|
||||
uids.append(u['user'])
|
||||
users = User.objects.filter(id__in=uids).only('username')
|
||||
elif installed('reddit') and form.cleaned_data['type'] == '3':
|
||||
from reddit.models import RedditAccount
|
||||
uid = RedditAccount.objects.filter(username__icontains=form.cleaned_data['username']).values('user')
|
||||
for u in uid:
|
||||
uids.append(u['user'])
|
||||
users = User.objects.filter(id__in=uids).only('username')
|
||||
elif form.cleaned_data['type'] == '4':
|
||||
users = User.objects.filter(email__icontains=form.cleaned_data['username']).only('username')
|
||||
elif form.cleaned_data['type'] == '5':
|
||||
uids = EVEAccount.objects.filter(id__icontains=form.cleaned_data['username']).values_list('user', flat=True)
|
||||
users = User.objects.filter(id__in=uids).only('username')
|
||||
else:
|
||||
messages.add_message(request, messages.ERROR, "Error parsing form, Type: %s, Value: %s" % (form.cleaned_data['type'], form.cleaned_data['username']))
|
||||
return redirect('sso.views.user_lookup')
|
||||
|
||||
if users and len(users) == 1:
|
||||
return redirect(user_view, username=users[0].username)
|
||||
elif users and len(users) > 1:
|
||||
return render_to_response('sso/lookup/lookuplist.html', locals(), context_instance=RequestContext(request))
|
||||
else:
|
||||
messages.add_message(request, messages.INFO, "No results found")
|
||||
return redirect('sso.views.user_lookup')
|
||||
|
||||
return render_to_response('sso/lookup/userlookup.html', locals(), context_instance=RequestContext(request))
|
||||
|
||||
|
||||
@login_required
|
||||
def set_apipasswd(request):
|
||||
""" Sets the user's auth API password """
|
||||
|
||||
if request.method == 'POST':
|
||||
form = APIPasswordForm(request.POST)
|
||||
if form.is_valid():
|
||||
profile = request.user.get_profile()
|
||||
profile.api_service_password = hashlib.sha1(form.cleaned_data['password']).hexdigest()
|
||||
profile.save()
|
||||
messages.add_message(request, messages.INFO, "Your API Services password has been set.")
|
||||
return redirect('sso.views.profile') # Redirect after POST
|
||||
else:
|
||||
form = APIPasswordForm() # An unbound form
|
||||
|
||||
return render_to_response('sso/apipassword.html', locals(), context_instance=RequestContext(request))
|
||||
|
||||
|
||||
@login_required
|
||||
def refresh_access(request, userid=0):
|
||||
""" Refreshes the user's access """
|
||||
|
||||
if userid > 0 and request.user.is_staff:
|
||||
update_user_access(userid)
|
||||
elif request.user:
|
||||
update_user_access(request.user.id)
|
||||
messages.add_message(request, messages.INFO, "User access updated.")
|
||||
return redirect('sso.views.profile')
|
||||
Reference in New Issue
Block a user