def create_profile(sender, instance, created, *args, **kw): """ Create an empty profile for a new user. XXX TODO: Handle particular LDAP attributes? See http://packages.python.org/django-auth-ldap/#user-objects for more info """ if created: # Here we check if AdminCommunity exists. # If it doesn't, that probably means we're inside the bootstrap process, # and in such case we don't want to create a profile now. import community if not community.AdminCommunity.objects.__booster__.exists(): log.debug("Admin community doesn't exist (yet)") return # We consider we're the SystemAccount now. __account__ = SystemAccount.get() # Actually create profile log.info("Automatic creation of a UserAccount for %s" % instance) profile = UserAccount( user = instance, slug = slugify.slugify(instance.username), ) profile.save()
def create_profile(sender, instance, created, *args, **kw): """ Create an empty profile for a new user. XXX TODO: Handle particular LDAP attributes? See http://packages.python.org/django-auth-ldap/#user-objects for more info """ if created: # Here we check if AdminCommunity exists. # If it doesn't, that probably means we're inside the bootstrap process, # and in such case we don't want to create a profile now. import community if not community.AdminCommunity.objects.__booster__.exists(): log.debug("Admin community doesn't exist (yet)") return # We consider we're the SystemAccount now. __account__ = SystemAccount.get() # Actually create profile log.info("Automatic creation of a UserAccount for %s" % instance) profile = UserAccount( user=instance, slug=slugify.slugify(instance.username), ) profile.save()
def save(self, *args, **kw): """ Populate special content information before saving it. """ # Don't allow direct saving here if self.__class__ == Account: raise ValueError("You're not allowed to save an Account object. Save the derived object instead") # Validate title / slug if not self.title: if not self.slug: raise ValidationError("You must provide either a slug or a title for an account") self.title = self.slug elif not self.slug: self.slug = slugify.slugify(self.title) # Call parent and do post-save stuff return super(Account, self).save(*args, **kw)
def save(self, *args, **kw): """ Populate special content information before saving it. """ # Don't allow direct saving here if self.__class__ == Account: raise ValueError( "You're not allowed to save an Account object. Save the derived object instead" ) # Validate title / slug if not self.title: if not self.slug: raise ValidationError( "You must provide either a slug or a title for an account") self.title = self.slug elif not self.slug: self.slug = slugify.slugify(self.title) # Call parent and do post-save stuff return super(Account, self).save(*args, **kw)
def save(self, *args, **kw): """ Set various object attributes """ import account import community auth = Twistable.objects._getAuthenticatedAccount() # Check if we're saving a real object and not a generic Content one (which is prohibited). # This must be a programming error, then. if self.__class__.__name__ == Twistable.__name__: raise ValidationError( "You cannot save a raw content object. Use a derived class instead." ) # Set information used to retreive the actual subobject self.model_name = self._meta.object_name self.app_label = self._meta.app_label # Set owner, publisher upon object creation. Publisher is NEVER set as None by default. if self.id is None: # If self.owner is already set, ensure it's done by SystemAccount if self.owner_id: if not isinstance(auth, account.SystemAccount): raise PermissionDenied( "You're not allowed to set the content owner by yourself." ) else: self.owner = self.getDefaultOwner() if not self.publisher_id: self.publisher = self.getDefaultPublisher() else: if not self.publisher.can_publish: raise PermissionDenied( "You're not allowed to publish on %s" % self.publisher) else: # XXX TODO: Check that nobody sets /unsets the owner or the publisher of an object # raise PermissionDenied("You're not allowed to set the content owner by yourself.") if not self.can_edit: raise PermissionDenied( "You're not allowed to edit this content.") # Set created_by and modified_by fields if self.id is None: self.created_by = auth self.modified_by = auth # Check if publisher is set. Only GlobalCommunity may have its publisher to None to make a site visible on the internet. if not self.publisher_id: if not self.__class__._ALLOW_NO_PUBLISHER: raise ValueError( "Only the Global Community can have no publisher, not %s" % self) # Set permissions; we will apply them last to ensure we have an id. # We also ensure that the right permissions are set on the right object if not self.permissions: perm_template = self.model_class.permission_templates if not perm_template: raise ValueError( "permission_templates not defined on class %s" % self.__class__.__name__) self.permissions = perm_template.get_default() tpl = [ t for t in self.permission_templates.permissions() if t["id"] == self.permissions ] if not tpl: # Didn't find? We restore default setting. XXX Should log/alert something here! tpl = [ t for t in self.permission_templates.permissions() if t["id"] == self.model_class.permission_templates.get_default() ] log.warning("Restoring default permissions. Problem here.") log.warning( "Unable to find %s permission template %s in %s" % (self, self.permissions, self.permission_templates.perm_dict)) if tpl[0].get("disabled_for_community") and issubclass( self.publisher.model_class, community.Community): raise ValueError( "Invalid permission setting %s for this object (%s/%s)" % (tpl, self, self.title_or_description)) elif tpl[0].get("disabled_for_useraccount") and issubclass( self.publisher.model_class, account.UserAccount): raise ValueError( "Invalid permission setting %s for this object (%s/%s)" % (tpl, self, self.title_or_description)) for perm, role in tpl[0].items(): if perm.startswith("can_"): if callable(role): role = role(self) setattr(self, "_p_%s" % perm, role) # Check if we're creating or not created = not self.id # Generate slug (or not !) if not self.slug and self.__class__._FORCE_SLUG_CREATION: if self.title: self.slug = slugify(self.title) elif self.description: self.slug = slugify(self.description) else: self.slug = slugify(self.model_name) self.slug = self.slug[:40] if created and self.__class__._FORCE_SLUG_CREATION: while Twistable.objects.__booster__.filter( slug=self.slug).exists(): match = re.search("_(?P<num>[0-9]+)$", self.slug) if match: root = self.slug[:match.start()] num = int(match.groupdict()['num']) + 1 else: root = self.slug num = 1 self.slug = "%s_%i" % ( root, num, ) # Perform a full_clean on the model just to be sure it validates correctly self.full_clean() # Save and update access network information ret = super(Twistable, self).save(*args, **kw) self._update_access_network() # Send TN's post-save signal twistable_post_save.send(sender=self.__class__, instance=self, created=created) return ret
def bootstrap(): """ Load initial data if it's not present. This method is SAFE, ie. it won't destroy any existing data, only add missing stuff`. This should be called every time twistranet is started! """ try: # Let's log in. __account__ = SystemAccount.objects.__booster__.get() except SystemAccount.DoesNotExist: log.info( "No SystemAccount available. That means this instance has never been bootstraped, so let's do it now." ) raise RuntimeError( "Please sync your databases with 'manage.py syncdb' before bootstraping." ) except: # Default fixture probably not installed yet. Don't do anything yet. log.info( "DatabaseError while bootstraping. Your tables are probably not created yet." ) traceback.print_exc() return # Now create the bootstrap / default / help fixture objects. # Import your fixture there, if you don't do so they may not be importable. from twistranet.fixtures.bootstrap import FIXTURES as BOOTSTRAP_FIXTURES from twistranet.fixtures.help_en import FIXTURES as HELP_EN_FIXTURES # XXX TODO: Make a fixture registry? Or fix fixture import someway? try: from twistrans.fixtures.help_fr import FIXTURES as HELP_FR_FIXTURES from twistrans.fixtures.bootstrap_fr import FIXTURES as BOOTSTRAP_FR_FIXTURES except ImportError: HELP_FR_FIXTURES = [] BOOTSTRAP_FR_FIXTURES = [] log.info("twistrans not installed, translations are not installed.") # Load fixtures for obj in BOOTSTRAP_FIXTURES: obj.apply() # Special treatment for bootstrap: Set the GlobalCommunity owner = AdminCommunity glob = GlobalCommunity.objects.get() admin_cty = AdminCommunity.objects.get() glob.owner = admin_cty glob.publisher = glob glob.save() admin_cty.publisher = glob admin_cty.save() # Create default resources by associating them to the SystemAccount and publishing them on GlobalCommunity. default_resources_dir = os.path.abspath( os.path.join( os.path.split(twistranet.__file__)[0], 'fixtures', 'resources', )) log.debug("Default res. dir: %s" % default_resources_dir) for root, dirs, files in os.walk(default_resources_dir): for fname in files: slug = os.path.splitext(os.path.split(fname)[1])[0] objects = Resource.objects.filter(slug=slug) if objects: if len(objects) > 1: raise IntegrityError( "More than one resource with '%s' slug" % slug) r = objects[0] else: r = Resource() # Copy file to its actual location with the storage API source_fn = os.path.join(root, fname) r.publisher = glob r.resource_file = File(open(source_fn, "rb"), fname) r.slug = slugify(slug) r.save() break # XXX We don't handle subdirs yet. # Set SystemAccount picture (which is a way to check if things are working properly). __account__.picture = Resource.objects.get(slug="default_tn_picture") __account__.save() # Install HELP fixture. for obj in HELP_EN_FIXTURES: obj.apply() # Have we got an admin account? If not, we generate one now. django_admins = UserAccount.objects.filter(user__is_superuser=True) admin_password = None if not django_admins.exists(): admin_password = "" for i in range(6): admin_password = "******" % (admin_password, random.choice(string.lowercase + string.digits)) admin = User.objects.create( username=settings.TWISTRANET_DEFAULT_ADMIN_USERNAME, first_name=settings.TWISTRANET_DEFAULT_ADMIN_FIRSTNAME, last_name=settings.TWISTRANET_DEFAULT_ADMIN_LASTNAME, email=settings.TWISTRANET_ADMIN_EMAIL, is_superuser=True, is_active=True, ) admin.set_password(admin_password) admin.save() # Sample data only imported if asked to in settings.py if settings.TWISTRANET_IMPORT_SAMPLE_DATA: from twistranet.fixtures import sample sample.create_users() for obj in sample.get_fixtures(): obj.apply() # Add relations bwn sample users # A <=> admin # B => admin # A = UserAccount.objects.get(slug = "a") # B = UserAccount.objects.get(slug = "b") # admin = UserAccount.objects.get(slug = "admin") # A.follow(admin) # admin.follow(A) # B.follow(admin) # Import COGIP sample (if requested) if settings.TWISTRANET_IMPORT_COGIP: fixtures_module = "twistranet.project_templates.cogip.fixtures" fixtures_module = import_module(fixtures_module) # We disable email sending backup_EMAIL_BACKEND = settings.EMAIL_BACKEND settings.EMAIL_BACKEND = 'django.core.mail.backends.dummy.EmailBackend' fixtures_module.load() settings.EMAIL_BACKEND = backup_EMAIL_BACKEND # Repair permissions repair() # Display admin password if admin_password is not None: print "\n\n" \ " You can now run your server with 'manage.py runserver'.\n" \ " Your initial administrator login/password are '%s / %s'" % (settings.TWISTRANET_DEFAULT_ADMIN_USERNAME, admin_password)
def prepare_view(self): """ Render the import form or do the import (from csv file posted). """ if self.request.method == "POST" and \ self.request.FILES.get("csv_file", None): csv_file = self.request.FILES.get("csv_file") reader = csv.reader(csv_file, dialect=CSVDialect) for line in reader: if not line: continue # firstname;lastname;email firstname = line[0].decode('utf8') lastname = line[1].decode('utf8') email = line[2] username = email.split('@')[0] username = slugify(username).replace('_','-') if User.objects.filter(username = username).exists(): u = User.objects.get(username = username) useraccount = UserAccount.objects.get(user = u) log.info( "User account '%s' already exixts" %useraccount.title ) else: # create user try: __account__ = SystemAccount.get() u = User.objects.create( username = username, first_name = firstname, last_name = lastname, email = email, is_superuser = False, is_active = True, ) chars = string.ascii_letters + string.digits random.seed = (os.urandom(1024)) password = ''.join(random.choice(chars) for i in range(6)) u.set_password(password) u.save() useraccount = UserAccount.objects.get(user = u) useraccount.title = u"%s %s" % (firstname, lastname) useraccount.save() log.info( "User account '%s' for %s %s (%s) created !" %(username, firstname, lastname, email)) # notify imported user (a mail is sent to prevent user) h = "%s%s%s%s" % (settings.SECRET_KEY, email, password, time.strftime("%Y%m%d")) h = hashlib.md5(h).hexdigest() reset_link = reverse(ResetPassword.name, args = (h, urllib.quote_plus(email))) user_imported.send( sender = self.__class__, target = useraccount, reset_password_url = reset_link, ) del __account__ except: log.warning( "Impossible to create account '%s' for %s %s (%s)" %(username, firstname, lastname, email)) continue community_title = line[3].decode('utf8') cid = slugify(community_title) if Community.objects.filter(slug = cid).exists(): log.info( "Community %s already exists !" %community ) else: c = Community.objects.create( slug = cid, title = community_title, permissions = "workgroup" ) c.save() com = Community.objects.get(slug= cid) com.join(account=useraccount) log.info( "user %s join the community %s !" %(useraccount.title, community_title) ) messages.info( self.request, u"import finished",)
def prepare_view(self, check_hash, email): """ Render the join form. """ # Check if hash and email AND admin priviledge match is_admin = False admin_string = "?make_admin=1" h = "%s%s%s" % (settings.SECRET_KEY, email, admin_string) h = hashlib.md5(h).hexdigest() if check_hash == h: is_admin = True else: # Check if hash and email match. h = "%s%s" % (settings.SECRET_KEY, email) h = hashlib.md5(h).hexdigest() if not check_hash == h: raise ValidationError("Invalid email. This invitation has been manually edited.") # If user is already registered, return to login form if User.objects.filter(email = email).exists(): raise MustRedirect(reverse(AccountLogin.name)) # Call form processing. Prepare all arguments, esp. email and username username = email.split('@')[0] username = slugify(username) self.initial = { "email": email, "username": username, } super(AccountJoin, self).prepare_view() # Now save user info. But before, double-check that stuff is still valid if self.form_is_valid: cleaned_data = self.form.cleaned_data # Check password and username if not cleaned_data["password"] == cleaned_data["password_confirm"]: messages.warning(self.request, _("Password and confirmation do not match")) elif User.objects.filter(username = cleaned_data["username"]).exists(): messages.warning(self.request, _("A user with this name already exists.")) else: # Create user and set information __account__ = SystemAccount.get() u = User.objects.create( username = cleaned_data["username"], first_name = cleaned_data["first_name"], last_name = cleaned_data["last_name"], email = cleaned_data["email"], is_superuser = is_admin, is_active = True, ) u.set_password(cleaned_data["password"]) u.save() useraccount = UserAccount.objects.get(user = u) useraccount.title = u"%s %s" % (cleaned_data["first_name"], cleaned_data["last_name"]) useraccount.save() if is_admin: admin_community = AdminCommunity.objects.get() if not admin_community in useraccount.communities: admin_community.join(useraccount, is_manager = True) del __account__ # Display a nice success message and redirect to login page messages.success(self.request, _("Your account is now created. You can login to twistranet.")) raise MustRedirect(reverse(AccountLogin.name))
def load_cogip(): """ WARNING: THIS IS MEANT TO BE LOAD FROM AN EMPTY DATABASE! We didn't bother testing it with a pre-populated one as it doesn't make that much sense. """ # Just to be sure, we log as system account __account__ = SystemAccount.get() # Create tags # Import the whole file, creating all needed fixtures, including Service as communities. f = open(os.path.join(HERE_COGIP, "cogip.csv"), "rU") c = csv.DictReader(f, delimiter=';', fieldnames=[ 'firstname', 'lastname', 'sex', 'service', 'function', 'email', 'picture_file', 'tags', 'network' ]) services = [] for useraccount in c: # Create the user if necessary username = slugify("%s" % (useraccount['lastname'].decode('utf-8'), )) # username = slugify(useraccount['lastname']).lower() password = username if not User.objects.filter(username=username).exists(): u = User.objects.create( username=username, email=useraccount['email'], ) u.set_password(password) u.save() # Create the user account u = Fixture( UserAccount, slug=username, title="%s %s" % ( useraccount['firstname'], useraccount['lastname'], ), description=useraccount['function'], permissions="public", user=User.objects.get(username=username), force_update=True, ).apply() # Create a community matching user's service or make him join the service. And put it in a menu! service_slug = slugify(useraccount['service']) if not service_slug in services: services.append(service_slug) service = Fixture( Community, slug=service_slug, title=useraccount['service'], permissions="blog", logged_account=username, force_update=True, ).apply() # Add default picture in the community source_fn = os.path.join(HERE_COGIP, 'cogip.png') r = Resource( publisher=service, resource_file=DjangoFile(open(source_fn, "rb"), 'cogip.png'), ) r.save() service.picture = r service.save() # Create the menu item if not MenuItem.objects.filter(slug="cogip_menu").exists(): cogip_menu = MenuItem.objects.create( slug="cogip_menu", order=5, title="La COGIP", parent=Menu.objects.get(), link_url="/", ) cogip_menu.save() else: cogip_menu = MenuItem.objects.get(slug="cogip_menu") item = MenuItem.objects.create(parent=cogip_menu, target=service) item.save() else: Community.objects.get(slug=service_slug).join( UserAccount.objects.get(slug=username)) # Set tags for tag in generate_tags(useraccount['tags']): u.tags.add(tag) # Create / Replace the profile picture if the image file is available. source_fn = os.path.join(HERE_COGIP, "images", useraccount['picture_file']) if os.path.isfile(source_fn): picture_slug = slugify("pict_%s" % useraccount['picture_file']) Resource.objects.filter(slug=picture_slug).delete() r = Resource( publisher=UserAccount.objects.get(slug=username), resource_file=DjangoFile(open(source_fn, "rb"), useraccount['picture_file']), slug=picture_slug, ) r.save() u = UserAccount.objects.get(slug=username) u.picture = Resource.objects.get(slug=picture_slug) u.save() # Add friends in the network (with pending request status) if useraccount['network']: for friend in [ s.strip() for s in useraccount['network'].split(',') ]: if friend.startswith('-'): approved = False friend = friend[1:] else: approved = True log.debug("Put '%s' and '%s' in their network." % (username, friend)) current_account = UserAccount.objects.get(slug=username) __account__ = UserAccount.objects.get(slug=username) friend_account = UserAccount.objects.get(slug=friend) friend_account.add_to_my_network() if approved: __account__ = UserAccount.objects.get(slug=friend) current_account.add_to_my_network() __account__ = SystemAccount.objects.get() # Create communities and join ppl from there f = open(os.path.join(HERE_COGIP, "communities.csv"), "rU") c = csv.DictReader(f, delimiter=';', fieldnames=[ 'title', 'description', 'permissions', 'tags', 'members', ]) for community in c: if not community['members']: continue member_slugs = [ slug.strip() for slug in community['members'].split(',') ] if not member_slugs: continue service_slug = slugify(community['title']) com = Fixture( Community, slug=service_slug, title=community['title'], description=community['description'], permissions=community['permissions'], logged_account=member_slugs[0], ).apply() for member in member_slugs: log.debug("Make %s join %s" % (member, com.slug)) com.join(UserAccount.objects.get(slug=member)) # Set tags for tag in generate_tags(community['tags']): com.tags.add(tag) # Create content updates f = open(os.path.join(HERE_COGIP, "content.csv"), "rU") contents = csv.DictReader(f, delimiter=';', fieldnames=[ 'type', 'owner', 'publisher', 'permissions', 'text', 'filename', 'tags', ]) for content in contents: log.debug("Importing %s" % content) __account__ = UserAccount.objects.get(slug=content['owner']) if content['type'].lower() == "status": log.debug("Publisher: %s" % content['publisher']) status = StatusUpdate( publisher=Account.objects.get(slug=content['publisher']), permissions=content['permissions'], description=content['text'], ) status.save() log.debug("Adding status update: %s" % status) elif content['type'].lower() == 'document': source_fn = os.path.join(HERE_COGIP, "documents", content['filename']) file_content = "" if os.path.isfile(source_fn): f = open(source_fn, 'rU') file_content = f.read() article = Document.objects.create( slug=slugify(content['filename']), title=content['text'], publisher=Account.objects.get(slug=content['publisher']), permissions=content['permissions'], text=file_content or "(empty file)", ) for tag in generate_tags(content['tags']): article.tags.add(tag) elif content['type'].lower() == "comment": comment = Comment.objects.create( in_reply_to=status, description=content['text'], ) elif content['type'].lower() == "resource": source_fn = os.path.join(HERE_COGIP, content['filename']) r = Resource.objects.create( publisher=Account.objects.get(slug=content['publisher']), resource_file=DjangoFile(open(source_fn, "rb"), content['filename']), slug=slugify(content['filename']), ) for tag in generate_tags(content['tags']): r.tags.add(tag) else: raise ValueError("Invalid content type: %s" % content['type']) __account__ = SystemAccount.get() # Special stuff cogip_menu = MenuItem.objects.get(slug="cogip_menu") cogip_menu.target = Document.objects.get(slug="presentation_cogip_html") cogip_menu.link_url = None cogip_menu.save()
def save(self, *args, **kw): """ Set various object attributes """ import account import community auth = Twistable.objects._getAuthenticatedAccount() # Check if we're saving a real object and not a generic Content one (which is prohibited). # This must be a programming error, then. if self.__class__.__name__ == Twistable.__name__: raise ValidationError("You cannot save a raw content object. Use a derived class instead.") # Set information used to retreive the actual subobject self.model_name = self._meta.object_name self.app_label = self._meta.app_label # Set owner, publisher upon object creation. Publisher is NEVER set as None by default. if self.id is None: # If self.owner is already set, ensure it's done by SystemAccount if self.owner_id: if not isinstance(auth, account.SystemAccount): raise PermissionDenied("You're not allowed to set the content owner by yourself.") else: self.owner = self.getDefaultOwner() if not self.publisher_id: self.publisher = self.getDefaultPublisher() else: if not self.publisher.can_publish: raise PermissionDenied("You're not allowed to publish on %s" % self.publisher) else: # XXX TODO: Check that nobody sets /unsets the owner or the publisher of an object # raise PermissionDenied("You're not allowed to set the content owner by yourself.") if not self.can_edit: raise PermissionDenied("You're not allowed to edit this content.") # Set created_by and modified_by fields if self.id is None: self.created_by = auth self.modified_by = auth # Check if publisher is set. Only GlobalCommunity may have its publisher to None to make a site visible on the internet. if not self.publisher_id: if not self.__class__._ALLOW_NO_PUBLISHER: raise ValueError("Only the Global Community can have no publisher, not %s" % self) # Set permissions; we will apply them last to ensure we have an id. # We also ensure that the right permissions are set on the right object if not self.permissions: perm_template = self.model_class.permission_templates if not perm_template: raise ValueError("permission_templates not defined on class %s" % self.__class__.__name__) self.permissions = perm_template.get_default() tpl = [ t for t in self.permission_templates.permissions() if t["id"] == self.permissions ] if not tpl: # Didn't find? We restore default setting. XXX Should log/alert something here! tpl = [ t for t in self.permission_templates.permissions() if t["id"] == self.model_class.permission_templates.get_default() ] log.warning("Restoring default permissions. Problem here.") log.warning("Unable to find %s permission template %s in %s" % (self, self.permissions, self.permission_templates.perm_dict)) if tpl[0].get("disabled_for_community") and issubclass(self.publisher.model_class, community.Community): raise ValueError("Invalid permission setting %s for this object (%s/%s)" % (tpl, self, self.title_or_description)) elif tpl[0].get("disabled_for_useraccount") and issubclass(self.publisher.model_class, account.UserAccount): raise ValueError("Invalid permission setting %s for this object (%s/%s)" % (tpl, self, self.title_or_description)) for perm, role in tpl[0].items(): if perm.startswith("can_"): if callable(role): role = role(self) setattr(self, "_p_%s" % perm, role) # Check if we're creating or not created = not self.id # Generate slug (or not !) if not self.slug and self.__class__._FORCE_SLUG_CREATION: if self.title: self.slug = slugify(self.title) elif self.description: self.slug = slugify(self.description) else: self.slug = slugify(self.model_name) self.slug = self.slug[:40] if created and self.__class__._FORCE_SLUG_CREATION: while Twistable.objects.__booster__.filter(slug = self.slug).exists(): match = re.search("_(?P<num>[0-9]+)$", self.slug) if match: root = self.slug[:match.start()] num = int(match.groupdict()['num']) + 1 else: root = self.slug num = 1 self.slug = "%s_%i" % (root, num, ) # Perform a full_clean on the model just to be sure it validates correctly self.full_clean() # Save and update access network information ret = super(Twistable, self).save(*args, **kw) self._update_access_network() # Send TN's post-save signal twistable_post_save.send(sender = self.__class__, instance = self, created = created) return ret
def load_cogip(): """ WARNING: THIS IS MEANT TO BE LOAD FROM AN EMPTY DATABASE! We didn't bother testing it with a pre-populated one as it doesn't make that much sense. """ # Just to be sure, we log as system account __account__ = SystemAccount.get() # Create tags # Import the whole file, creating all needed fixtures, including Service as communities. f = open(os.path.join(HERE_COGIP, "cogip.csv"), "rU") c = csv.DictReader(f, delimiter = ';', fieldnames = ['firstname', 'lastname', 'sex', 'service', 'function', 'email', 'picture_file', 'tags', 'network']) services = [] for useraccount in c: # Create the user if necessary username = slugify("%s" % (useraccount['lastname'].decode('utf-8'), )) # username = slugify(useraccount['lastname']).lower() password = username if not User.objects.filter(username = username).exists(): u = User.objects.create( username = username, email = useraccount['email'], ) u.set_password(password) u.save() # Create the user account u = Fixture( UserAccount, slug = username, title = "%s %s" % (useraccount['firstname'], useraccount['lastname'], ), description = useraccount['function'], permissions = "public", user = User.objects.get(username = username), force_update = True, ).apply() # Create a community matching user's service or make him join the service. And put it in a menu! service_slug = slugify(useraccount['service']) if not service_slug in services: services.append(service_slug) service = Fixture( Community, slug = service_slug, title = useraccount['service'], permissions = "blog", logged_account = username, force_update = True, ).apply() # Add default picture in the community source_fn = os.path.join(HERE_COGIP, 'cogip.png') r = Resource( publisher = service, resource_file = DjangoFile(open(source_fn, "rb"), 'cogip.png'), ) r.save() service.picture = r service.save() # Create the menu item if not MenuItem.objects.filter(slug = "cogip_menu").exists(): cogip_menu = MenuItem.objects.create( slug = "cogip_menu", order = 5, title = "La COGIP", parent = Menu.objects.get(), link_url = "/", ) cogip_menu.save() else: cogip_menu = MenuItem.objects.get(slug = "cogip_menu") item = MenuItem.objects.create(parent = cogip_menu, target = service) item.save() else: Community.objects.get(slug = service_slug).join(UserAccount.objects.get(slug = username)) # Set tags for tag in generate_tags(useraccount['tags']): u.tags.add(tag) # Create / Replace the profile picture if the image file is available. source_fn = os.path.join(HERE_COGIP, "images", useraccount['picture_file']) if os.path.isfile(source_fn): picture_slug = slugify("pict_%s" % useraccount['picture_file']) Resource.objects.filter(slug = picture_slug).delete() r = Resource( publisher = UserAccount.objects.get(slug = username), resource_file = DjangoFile(open(source_fn, "rb"), useraccount['picture_file']), slug = picture_slug, ) r.save() u = UserAccount.objects.get(slug = username) u.picture = Resource.objects.get(slug = picture_slug) u.save() # Add friends in the network (with pending request status) if useraccount['network']: for friend in [ s.strip() for s in useraccount['network'].split(',') ]: if friend.startswith('-'): approved = False friend = friend[1:] else: approved = True log.debug("Put '%s' and '%s' in their network." % (username, friend)) current_account = UserAccount.objects.get(slug = username) __account__ = UserAccount.objects.get(slug = username) friend_account = UserAccount.objects.get(slug = friend) friend_account.add_to_my_network() if approved: __account__ = UserAccount.objects.get(slug = friend) current_account.add_to_my_network() __account__ = SystemAccount.objects.get() # Create communities and join ppl from there f = open(os.path.join(HERE_COGIP, "communities.csv"), "rU") c = csv.DictReader(f, delimiter = ';', fieldnames = ['title', 'description', 'permissions', 'tags', 'members', ]) for community in c: if not community['members']: continue member_slugs = [ slug.strip() for slug in community['members'].split(',') ] if not member_slugs: continue service_slug = slugify(community['title']) com = Fixture( Community, slug = service_slug, title = community['title'], description = community['description'], permissions = community['permissions'], logged_account = member_slugs[0], ).apply() for member in member_slugs: log.debug("Make %s join %s" % (member, com.slug)) com.join(UserAccount.objects.get(slug = member)) # Set tags for tag in generate_tags(community['tags']): com.tags.add(tag) # Create content updates f = open(os.path.join(HERE_COGIP, "content.csv"), "rU") contents = csv.DictReader(f, delimiter = ';', fieldnames = ['type', 'owner', 'publisher', 'permissions', 'text', 'filename', 'tags', ]) for content in contents: log.debug("Importing %s" % content) __account__ = UserAccount.objects.get(slug = content['owner']) if content['type'].lower() == "status": log.debug("Publisher: %s" % content['publisher']) status = StatusUpdate( publisher = Account.objects.get(slug = content['publisher']), permissions = content['permissions'], description = content['text'], ) status.save() log.debug("Adding status update: %s" % status) elif content['type'].lower() == 'document': source_fn = os.path.join(HERE_COGIP, "documents", content['filename']) file_content = "" if os.path.isfile(source_fn): f = open(source_fn, 'rU') file_content = f.read() article = Document.objects.create( slug = slugify(content['filename']), title = content['text'], publisher = Account.objects.get(slug = content['publisher']), permissions = content['permissions'], text = file_content or "(empty file)", ) for tag in generate_tags(content['tags']): article.tags.add(tag) elif content['type'].lower() == "comment": comment = Comment.objects.create(in_reply_to = status, description = content['text'], ) else: raise ValueError("Invalid content type: %s" % content['type']) __account__ = SystemAccount.get() # Special stuff cogip_menu = MenuItem.objects.get(slug = "cogip_menu") cogip_menu.target = Document.objects.get(slug = "presentation_cogip_html") cogip_menu.link_url = None cogip_menu.save()
def bootstrap(): """ Load initial data if it's not present. This method is SAFE, ie. it won't destroy any existing data, only add missing stuff`. This should be called every time twistranet is started! """ try: # Let's log in. __account__ = SystemAccount.objects.__booster__.get() except SystemAccount.DoesNotExist: log.info("No SystemAccount available. That means this instance has never been bootstraped, so let's do it now.") raise RuntimeError("Please sync your databases with 'manage.py syncdb' before bootstraping.") except: # Default fixture probably not installed yet. Don't do anything yet. log.info("DatabaseError while bootstraping. Your tables are probably not created yet.") traceback.print_exc() return # Now create the bootstrap / default / help fixture objects. # Import your fixture there, if you don't do so they may not be importable. from twistranet.fixtures.bootstrap import FIXTURES as BOOTSTRAP_FIXTURES from twistranet.fixtures.help_en import FIXTURES as HELP_EN_FIXTURES # XXX TODO: Make a fixture registry? Or fix fixture import someway? try: from twistrans.fixtures.help_fr import FIXTURES as HELP_FR_FIXTURES from twistrans.fixtures.bootstrap_fr import FIXTURES as BOOTSTRAP_FR_FIXTURES except ImportError: HELP_FR_FIXTURES = [] BOOTSTRAP_FR_FIXTURES = [] log.info("twistrans not installed, translations are not installed.") # Load fixtures for obj in BOOTSTRAP_FIXTURES: obj.apply() # Special treatment for bootstrap: Set the GlobalCommunity owner = AdminCommunity glob = GlobalCommunity.objects.get() admin_cty = AdminCommunity.objects.get() glob.owner = admin_cty glob.publisher = glob glob.save() admin_cty.publisher = glob admin_cty.save() # Create default resources by associating them to the SystemAccount and publishing them on GlobalCommunity. default_resources_dir = os.path.abspath( os.path.join( os.path.split(twistranet.__file__)[0], 'fixtures', 'resources', ) ) log.debug("Default res. dir: %s" % default_resources_dir) for root, dirs, files in os.walk(default_resources_dir): for fname in files: slug = os.path.splitext(os.path.split(fname)[1])[0] objects = Resource.objects.filter(slug = slug) if objects: if len(objects) > 1: raise IntegrityError("More than one resource with '%s' slug" % slug) r = objects[0] else: r = Resource() # Copy file to its actual location with the storage API source_fn = os.path.join(root, fname) r.publisher = glob r.resource_file = File(open(source_fn, "rb"), fname) r.slug = slugify(slug) r.save() break # XXX We don't handle subdirs yet. # Set SystemAccount picture (which is a way to check if things are working properly). __account__.picture = Resource.objects.get(slug = "default_tn_picture") __account__.save() # Install HELP fixture. for obj in HELP_EN_FIXTURES: obj.apply() # Have we got an admin account? If not, we generate one now. django_admins = UserAccount.objects.filter(user__is_superuser = True) admin_password = None if not django_admins.exists(): admin_password = "" for i in range(6): admin_password = "******" % (admin_password, random.choice(string.lowercase + string.digits)) admin = User.objects.create( username = settings.TWISTRANET_DEFAULT_ADMIN_USERNAME, first_name = settings.TWISTRANET_DEFAULT_ADMIN_FIRSTNAME, last_name = settings.TWISTRANET_DEFAULT_ADMIN_LASTNAME, email = settings.TWISTRANET_ADMIN_EMAIL, is_superuser = True, is_active = True, ) admin.set_password(admin_password) admin.save() # Sample data only imported if asked to in settings.py if settings.TWISTRANET_IMPORT_SAMPLE_DATA: from twistranet.fixtures import sample sample.create_users() for obj in sample.get_fixtures(): obj.apply() # Add relations bwn sample users # A <=> admin # B => admin # A = UserAccount.objects.get(slug = "a") # B = UserAccount.objects.get(slug = "b") # admin = UserAccount.objects.get(slug = "admin") # A.follow(admin) # admin.follow(A) # B.follow(admin) # Import COGIP sample (if requested) if settings.TWISTRANET_IMPORT_COGIP: fixtures_module = "twistranet.project_templates.cogip.fixtures" fixtures_module = import_module(fixtures_module) # We disable email sending backup_EMAIL_BACKEND = settings.EMAIL_BACKEND settings.EMAIL_BACKEND = 'django.core.mail.backends.dummy.EmailBackend' fixtures_module.load() settings.EMAIL_BACKEND = backup_EMAIL_BACKEND # Repair permissions repair() # Display admin password if admin_password is not None: print "\n\n" \ " You can now run your server with 'manage.py runserver'.\n" \ " Your initial administrator login/password are '%s / %s'" % (settings.TWISTRANET_DEFAULT_ADMIN_USERNAME, admin_password)