Adjustments for initial public launch of OpenCloud
diff --git a/planetstack/syndicate/__init__.py b/planetstack/syndicate/__init__.py
new file mode 100644
index 0000000..2b86d97
--- /dev/null
+++ b/planetstack/syndicate/__init__.py
@@ -0,0 +1 @@
+from syndicate.models import *
diff --git a/planetstack/syndicate/admin.py b/planetstack/syndicate/admin.py
new file mode 100644
index 0000000..85c3ebd
--- /dev/null
+++ b/planetstack/syndicate/admin.py
@@ -0,0 +1,149 @@
+from django.contrib import admin
+
+from syndicate.models import *
+from django import forms
+from django.utils.safestring import mark_safe
+from django.contrib.auth.admin import UserAdmin
+from django.contrib.admin.widgets import FilteredSelectMultiple
+from django.contrib.auth.forms import ReadOnlyPasswordHashField
+from django.contrib.auth.signals import user_logged_in
+from django.utils import timezone
+from django.contrib.contenttypes import generic
+from suit.widgets import LinkedSelect
+from core.admin import ReadOnlyTabularInline,ReadOnlyAwareAdmin,SingletonAdmin,SliceInline,ServiceAttrAsTabInline,PlanetStackBaseAdmin, PlStackTabularInline,SliceROInline,ServiceAttrAsTabROInline
+from suit.widgets import LinkedSelect
+from bitfield import BitField
+from bitfield.forms import BitFieldCheckboxSelectMultiple
+
+class SyndicateServiceAdmin(SingletonAdmin,ReadOnlyAwareAdmin):
+ model = SyndicateService
+ verbose_name = "Syndicate Service"
+ verbose_name_plural = "Syndicate Service"
+ list_display = ("name","enabled")
+ fieldsets = [(None, {'fields': ['name','enabled','versionNumber', 'description',], 'classes':['suit-tab suit-tab-general']})]
+ inlines = [SliceInline,ServiceAttrAsTabInline]
+
+ user_readonly_fields = ['name','enabled','versionNumber','description']
+ user_readonly_inlines = [SliceROInline, ServiceAttrAsTabROInline]
+
+ suit_form_tabs =(('general', 'Syndicate Service Details'),
+ ('slices','Slices'),
+ ('serviceattrs','Additional Attributes'),
+ )
+
+class VolumeAccessRightForUserROInline(ReadOnlyTabularInline):
+ model = VolumeAccessRight
+ extra = 0
+ suit_classes = 'suit-tab suit-tab-volumeAccessRights'
+ fields = ['volume','gateway_caps']
+
+class VolumeAccessRightROInline(ReadOnlyTabularInline):
+ model = VolumeAccessRight
+ extra = 0
+ suit_classes = 'suit-tab suit-tab-volumeAccessRights'
+ fields = ['owner_id','gateway_caps']
+
+class VolumeAccessRightInline(PlStackTabularInline):
+ model = VolumeAccessRight
+ extra = 0
+ suit_classes = 'suit-tab suit-tab-volumeAccessRights'
+
+class VolumeAccessRightAdmin(ReadOnlyAwareAdmin):
+ model = VolumeAccessRight
+
+ formfield_overrides = { BitField: {'widget': BitFieldCheckboxSelectMultiple},}
+ list_display = ['owner_id', 'volume']
+ user_readonly_fields = ['owner_id','volume','gateway_caps']
+ user_readonly_inlines = []
+
+class VolumeAccessRequestForUserROInline(ReadOnlyTabularInline):
+ model = VolumeAccessRequest
+ extra = 0
+ suit_classes = 'suit-tab suit-tab-volumeAccessRequests'
+ fields = ['volume', 'message']
+
+class VolumeAccessRequestROInline(ReadOnlyTabularInline):
+ model = VolumeAccessRequest
+ extra = 0
+ suit_classes = 'suit-tab suit-tab-volumeAccessRequests'
+ fields = ['owner_id', 'message']
+
+class VolumeAccessRequestInline(PlStackTabularInline):
+ model = VolumeAccessRequest
+ extra = 0
+ suit_classes = 'suit-tab suit-tab-volumeAccessRequests'
+ fields = ['owner_id', 'message']
+
+class VolumeAccessRequestAdmin(ReadOnlyAwareAdmin):
+ model = VolumeAccessRequest
+
+ formfield_overrides = { BitField: {'widget': BitFieldCheckboxSelectMultiple},}
+ list_display = ['owner_id', 'volume', 'message']
+ user_readonly_fields = ['volume','owner_id','message','message', 'gateway_caps']
+ user_readonly_inlines = []
+
+class VolumeInline(PlStackTabularInline):
+ model = Volume
+ extra = 0
+ suit_classes = 'suit-tab suit-tab-volumes'
+ fields = ['name', 'owner_id']
+
+class VolumeROInline(ReadOnlyTabularInline):
+ model = Volume
+ extra = 0
+ suit_classes = 'suit-tab suit-tab-volumes'
+ fields = ['name', 'owner_id']
+
+class VolumeAdmin(ReadOnlyAwareAdmin):
+ model = Volume
+ read_only_fields = ['blockSize']
+ list_display = ['name', 'owner_id']
+
+ formfield_overrides = { BitField: {'widget': BitFieldCheckboxSelectMultiple},}
+
+ detailsFieldList = ['name', 'owner_id', 'description','file_quota','blocksize', 'private','archive', 'default_gateway_caps' ]
+ keyList = ['metadata_public_key','metadata_private_key','api_public_key']
+
+ fieldsets = [
+ (None, {'fields': detailsFieldList, 'classes':['suit-tab suit-tab-general']}),
+ (None, {'fields': keyList, 'classes':['suit-tab suit-tab-volumeKeys']}),
+ ]
+
+ inlines = [VolumeAccessRightInline, VolumeAccessRequestInline]
+
+ user_readonly_fields = ['name','owner_id','description','blocksize','private','metadata_public_key','metadata_private_key','api_public_key','file_quota','default_gateway_caps']
+ user_readonly_inlines = [VolumeAccessRightROInline, VolumeAccessRequestROInline]
+
+ suit_form_tabs =(('general', 'Volume Details'),
+ ('volumeKeys', 'Access Keys'),
+ ('volumeAccessRequests', 'Volume Access Requests'),
+ ('volumeAccessRights', 'Volume Access Rights'),
+ )
+
+
+
+class SyndicateUserAdmin(ReadOnlyAwareAdmin):
+ model = SyndicateUser
+ verbose_name = "Users"
+ verbose_name = "Users"
+ list_display = ['user','is_admin', 'max_volumes']
+ inlines = [VolumeInline,VolumeAccessRequestInline,VolumeAccessRightInline]
+ user_readonly_fields = ['user','is_admin','max_volumes','max_UGs','max_RGs','max_AGs']
+ user_readonly_inlines = [VolumeROInline,VolumeAccessRequestForUserROInline,VolumeAccessRightForUserROInline]
+
+ fieldsets = [
+ (None, {'fields': ['user','is_admin','max_volumes','max_UGs','max_RGs','max_AGs'], 'classes':['suit-tab suit-tab-general']}),
+ ]
+
+ suit_form_tabs =(('general', 'Volume Details'),
+ ('volumes', 'Volumes'),
+ ('volumeAccessRequests', 'Volume Access Requests'),
+ ('volumeAccessRights', 'Volume Access Rights'),
+ )
+
+admin.site.register(SyndicateService, SyndicateServiceAdmin)
+admin.site.register(VolumeAccessRight, VolumeAccessRightAdmin)
+admin.site.register(VolumeAccessRequest, VolumeAccessRequestAdmin)
+admin.site.register(Volume, VolumeAdmin)
+admin.site.register(SyndicateUser, SyndicateUserAdmin)
+
diff --git a/planetstack/syndicate/models.py b/planetstack/syndicate/models.py
new file mode 100644
index 0000000..efc08c6
--- /dev/null
+++ b/planetstack/syndicate/models.py
@@ -0,0 +1,64 @@
+from core.models import User,Site,Service,SingletonModel,PlCoreBase
+import os
+from django.db import models
+from django.forms.models import model_to_dict
+from bitfield import BitField
+
+# Create your models here.
+
+class SyndicateService(SingletonModel,Service):
+ class Meta:
+ app_label = "syndicate"
+ verbose_name = "Syndicate Service"
+ verbose_name_plural = "Syndicate Service"
+
+ def __unicode__(self): return u'Syndicate Service'
+
+class SyndicateUser(models.Model):
+
+ user = models.ForeignKey(User)
+ is_admin = models.BooleanField(default=False, help_text="Indicates this user has Administrative purposes for the Syndicate Service")
+ max_volumes = models.PositiveIntegerField(help_text="Maximum number of Volumes this user may create.", default=1)
+ max_UGs = models.PositiveIntegerField(help_text="Maximum number of User Gateways this user may create.", default=500)
+ max_RGs = models.PositiveIntegerField(help_text="Maximum number of Replica Gateways this user may create.", default=500)
+ max_AGs = models.PositiveIntegerField(help_text="Maximum number of Aquisition Gateways this user may create.", default=10)
+
+ def __unicode__(self): return self.user.email
+
+class Volume(models.Model):
+ name = models.CharField(max_length=64, help_text="Human-readable, searchable name of the Volume")
+ owner_id = models.ForeignKey(SyndicateUser, verbose_name='Owner')
+ description = models.TextField(null=True, blank=True,max_length=130, help_text="Human-readable description of what this Volume is used for.")
+ blocksize = models.PositiveIntegerField(help_text="Number of bytes per block.")
+ private = models.BooleanField(default=True, help_text="Indicates if the Volume is visible to users other than the Volume Owner and Syndicate Administrators.")
+ archive = models.BooleanField(default=True, help_text="Indicates if this Volume is read-only, and only an Aquisition Gateway owned by the Volume owner (or Syndicate admin) can write to it.")
+ metadata_public_key = models.TextField(null=True, blank=True, max_length=1024, help_text="Public key Gateways will use to verify the authenticity of metadata from this Volume")
+ metadata_private_key = models.TextField(null=True, blank=True, max_length=1024, help_text="Private key the Volume should use to sign metadata served to Gateways")
+ api_public_key = models.TextField(null=True, blank=True, max_length=1024, help_text="Public key used to verify writes to these fields from Volume owner")
+
+ file_quota = models.IntegerField(help_text='Maximum number of files and directories allowed in this Volume (-1 means "unlimited")')
+
+ default_gateway_caps = BitField(flags=('GATEWAY_CAP_READ_DATA','GATEWAY_CAP_READ_METADATA', 'GATEWAY_CAP_WRITE_DATA', 'GATEWAY_CAP_WRITE_METADATA', 'GATEWAY_CAP_COORDINATE'), verbose_name='Default Gateway Capabilities')
+ #default_gateway_caps = models.PositiveIntegerField(verbose_name='Default Gateway Capabilities')
+ #default_gateway_caps2 = models.CharField(max_length=32,null=True,default = "readonly", verbose_name='Default Gateway Capabilities')
+
+ def __unicode__(self): return self.name
+
+class VolumeAccessRight(models.Model):
+ owner_id = models.ForeignKey(SyndicateUser, verbose_name='user')
+ volume = models.ForeignKey(Volume)
+ gateway_caps = BitField(flags=('GATEWAY_CAP_READ_DATA','GATEWAY_CAP_READ_METADATA', 'GATEWAY_CAP_WRITE_DATA', 'GATEWAY_CAP_WRITE_METADATA', 'GATEWAY_CAP_COORDINATE'), verbose_name='Gateway Capabilities')
+ #gateway_caps = models.PositiveIntegerField(verbose_name='Gateway Capabilities')
+ #gateway_caps2 = models.CharField(max_length=32, default='readonly',null=True,verbose_name='Default Gateway Capabilities')
+
+ def __unicode__(self): return self.owner_id.user.email
+
+class VolumeAccessRequest(models.Model):
+ owner_id = models.ForeignKey(SyndicateUser, verbose_name='user')
+ volume = models.ForeignKey(Volume)
+ message = models.TextField(null=True, blank=True, max_length=1024, help_text="Description of why the user wants access to the volume.")
+ gateway_caps = BitField(flags=('GATEWAY_CAP_READ_DATA','GATEWAY_CAP_READ_METADATA', 'GATEWAY_CAP_WRITE_DATA', 'GATEWAY_CAP_WRITE_METADATA', 'GATEWAY_CAP_COORDINATE'), verbose_name='Gateway Capabilities')
+ #gateway_caps = models.PositiveIntegerField(verbose_name='Gateway Capabilities')
+ #gateway_caps2 = models.CharField(max_length=32,default='readonly',null=True,verbose_name='Default Gateway Capabilities')
+
+ def __unicode__(self): return self.owner_id.user.email