Ejemplo n.º 1
0
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()
Ejemplo n.º 2
0
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()
Ejemplo n.º 3
0
 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)
Ejemplo n.º 4
0
    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)
Ejemplo n.º 5
0
    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
Ejemplo n.º 6
0
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)
Ejemplo n.º 7
0
    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",)
Ejemplo n.º 8
0
 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))
Ejemplo n.º 9
0
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()
Ejemplo n.º 10
0
    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
Ejemplo n.º 11
0
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()
Ejemplo n.º 12
0
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)