コード例 #1
0
ファイル: site_config.py プロジェクト: criswell/noink
class _SiteConfig:
    __borg_state = {}

    def __init__(self):
        self.__dict__ = self.__borg_state

        try:
            self._setup
        except AttributeError:
            self._setup = False

        if not self._setup:
            self.event_log = EventLog()
            self._setup = True

    def add(self, version, name=None, email=None):
        """
        Adds an entry to the site config database.
        """
        sc = SiteConfig(version)
        sc.version = version
        if name:
            sc.site_name = name
            self.event_log.add('update_sitename', -1, False, '', name)
        if email:
            sc.admin_email = email

        mainDB.session.add(sc)
        mainDB.session.commit()
        self.event_log.add('update_siteconf', -1, False, '', str(version))

    def getCurrent(self):
        return SiteConfig.query.order_by(SiteConfig.id.desc()).first()
コード例 #2
0
ファイル: admin_static.py プロジェクト: criswell/noink
def static_page():
    """
    Render the administrative static page
    """
    user_db = UserDB()
    role_db = RoleDB()
    event_log = EventLog()
    icebox = Icebox()

    if current_user.is_authenticated() and current_user.is_active():
        is_admin = user_db.in_group(current_user, mainApp.config['ADMIN_GROUP'])
        all_activities = set()
        for m in role_db.get_roles(current_user):
            acts = role_db.get_activities(m.role_id)
            for act in acts:
                if acts[act]:
                    all_activities.add(act)

        can_admin_static = 'make_static' in all_activities
        can_admin_static_now = 'make_static_now' in all_activities

        if is_admin or can_admin_static:
            if request.method == 'POST':
                if 'sched_rebuild' in request.form:
                    event_log.add('rebuild_static', current_user.id)
                    flash(_('Full site rebuild scheduled.'))
                elif 'incr_build' in request.form:
                    icebox.generate_pages()
                    flash(_('New/updated pages generated.'))
                elif 'rebuild_now' in request.form:
                    if can_admin_static_now:
                        icebox.generate_pages(True)
                        flash(_('Full site rebuilt'))
                    else:
                        flash(_('Not authorized for full site rebuild',
                            'error'))
            return render_template('admin_static.html', state=get_state(),
                    can_admin_static=can_admin_static,
                    can_admin_static_now=can_admin_static_now,
                    title=_('Administrate Static Site'),
                    sched_rebuild_text=_('Schedule a full site rebuild'),
                    sched_rebuild_button=_('Schedule'),
                    incr_build_text=_('Perform an incremental build'),
                    incr_build_button=_('Incremental'),
                    rebuild_now_text=_('Perform a full rebuild now'),
                    rebuild_now_button=_('Rebuild'))
        else:
            return _not_auth()
    else:
        return _not_auth()
コード例 #3
0
ファイル: _setupDB.py プロジェクト: criswell/noink
def setup_DB():
    """
    Called when the DB is to be initialized. Should only be called once.
    """
    event_log = EventLog()
    sc = _SiteConfig()
    userDB = UserDB()
    roleDB = RoleDB()
    mainDB.create_all()
    event_log.add('db_setup', -1, True)
    default_group = userDB.add_group(mainApp.config['DEFAULT_GROUP'],
            mainApp.config['DEFAULT_GROUP_DESC'])
    default_acts = get_activity_dict(False)
    default_acts.update(mainApp.config['DEFAULT_ROLE_ACTIVITIES'])

    dummy = roleDB.add_role(
            mainApp.config['DEFAULT_ROLE_NAME'],
            mainApp.config['DEFAULT_ROLE_DESC'],
            default_acts)

    user = userDB.add(mainApp.config['ADMIN_USER'],
        mainApp.config["ADMIN_PASSWD"], mainApp.config['ADMIN_FULLNAME'])
    admin_group = userDB.add_group(mainApp.config['ADMIN_GROUP'],
        mainApp.config['ADMIN_GROUP_DESC'], user.id)
    if not userDB.update_primary(user, admin_group):
        raise SetupError(
            'Could not assign the admin user "{0}" primary group to the ' \
            'admin group "{1}"!'.format(user, admin_group))

    # By default, the admin is part of the top level group as well as default
    dummy = userDB.add_group(mainApp.config['TOP_LEVEL_GROUP'],
        mainApp.config['TOP_LEVEL_GROUP_DESC'], user.id)
    userDB.add_to_group(user, default_group)

    admin_role = get_activity_dict(True)
    role = roleDB.add_role(
            mainApp.config['ADMIN_ROLE_NAME'],
            mainApp.config['ADMIN_ROLE_DESC'],
            admin_role)

    roleDB.assign_role(user, mainApp.config['ADMIN_GROUP'], role)
    roleDB.assign_role(user, mainApp.config['TOP_LEVEL_GROUP'], role)
    roleDB.assign_role(user, mainApp.config['DEFAULT_GROUP'], role)

    sc.add(mainApp.noink_version, mainApp.config['SITE_NAME'],
            mainApp.config['SITE_ADMIN_EMAIL'])

    event_log.add('db_finish', -1, True)
コード例 #4
0
ファイル: user_db.py プロジェクト: criswell/noink
    def __init__(self):
        self.__dict__ = self.__borg_state

        try:
            self._setup
        except AttributeError:
            self._setup = False

        if not self._setup:
            self.eventLog = EventLog()
            self._setup = True
コード例 #5
0
ファイル: admin_events.py プロジェクト: criswell/noink
def event_viewer():
    """
    Render the event viewer.
    """
    page_num = int(request.args.get('page', 0))
    per_page = int(request.args.get('per_page', 20))
    user_db = UserDB()
    role_db = RoleDB()
    event_log = EventLog()

    if current_user.is_authenticated() and current_user.is_active():
        is_admin = user_db.in_group(current_user, mainApp.config['ADMIN_GROUP'])
        all_activities = set()
        for m in role_db.get_roles(current_user):
            acts = role_db.get_activities(m.role_id)
            for act in acts:
                if acts[act]:
                    all_activities.add(act)

        can_view_logs = 'view_logs' in all_activities

        if is_admin or can_view_logs:
            events = event_log.find_recent_by_num(per_page, page_num * per_page)
            count = event_log.count()

            total_pages = 0
            if count > per_page:
                total_pages = int(ceil(float(count) / float(per_page)))

            return render_template('admin_events.html', events=events,
                state=get_state(), page_num=page_num, per_page=per_page,
                title=_('Event log'), total_pages=total_pages)
        else:
            return _not_auth()
    else:
        return _not_auth()
コード例 #6
0
ファイル: icebox.py プロジェクト: criswell/noink
    def __init__(self):
        self.__dict__ = self.__borg_state

        try:
            self._setup
        except AttributeError:
            self._setup = False

        if not self._setup:
            self.event_log = EventLog()
            self.entry_db = EntryDB()
            self.icebox_path = abspath(mainApp.config['ICEBOX_PATH'])
            if mainApp.config['ICEBOX_STATIC_PATH'] is not None:
                self.static_path = abspath(mainApp.config['ICEBOX_STATIC_PATH'])
            else:
                self.static_path = None
            self.client = mainApp.test_client()
            self._setup = True
コード例 #7
0
ファイル: user_db.py プロジェクト: criswell/noink
class UserDB:
    __borg_state = {}

    def __init__(self):
        self.__dict__ = self.__borg_state

        try:
            self._setup
        except AttributeError:
            self._setup = False

        if not self._setup:
            self.eventLog = EventLog()
            self._setup = True

    def find_user_by_name(self, username):
        '''
        Finds a user by their username

        @param username: The username to find.

        @return The user objects found
        '''
        return User.query.filter_by(name=username).all()

    def find_user_by_id(self, uid):
        '''
        Finds a user by their user ID.

        @param uid: The user's ID to find.

        @return The user object found
        '''
        return User.query.get(uid)

    def get_users(self, u):
        '''
        Given user information, returns the user object

        @param u: The user to find. Can be an integer uid, username string, or
                  even a user object.

        @return the user objects found
        '''
        users = [u]
        if isinstance(u, IntType):
            users = [self.find_user_by_id(u)]
        elif isinstance(u, string_types):
            users = self.find_user_by_name(u)

        return users

    def get_all_users(self, g=None):
        """
        Get all users. Given an optional group, only find users in that
        primary group.
        """
        if g is None:
            return User.query.all()
        else:
            group = self.get_group(g)
            return User.query.filter_by(primary_group=group).all()

    def get_user(self, u):
        '''
        Given user information, returns the user object

        @param u: The user to find. Can be an integer uid, username string, or
                  even a user object.

        @return the user object found
        '''
        user = u
        if isinstance(u, IntType):
            user = self.find_user_by_id(u)
        elif isinstance(u, string_types):
            tu = self.find_user_by_name(u)
            if len(tu) > 0:
                user = tu[0]
            else:
                user = None

        return user

    def add(self, username, password, fullname, bio="", group=None,
            active=False):
        '''
        Adds a user to the database.

        @param username: The username to add, must be unique.
        @param password: The password to use.
        @param fullname: The user's full name
        @param bio: The user's bio (optional)
        @param group: The user's primary group (optional)
        @param active: Whether the user is active or not

        @return The user object for the user crated.
        '''
        try:
            exists = self.find_user_by_name(username)
        except:
            exists = False

        if exists:
            raise DuplicateUser("{0} already exists in database with id '{1}'".
                format(username, str(exists)))
        else:
            from noink.role_db import RoleDB
            role_db = RoleDB()
            passHash = mainCrypt.generate_password_hash(password)
            u = User(username, fullname, bio, passHash)
            if group is None:
                group = self.get_group(mainApp.config['DEFAULT_GROUP'])
            u.primary_group = group
            u.active = active
            mainDB.session.add(u)
            mainDB.session.commit()
            self.eventLog.add('add_user', u.id, True, None, username)
            self.add_to_group(u, group)
            role_db.assign_role(u, group, mainApp.config['DEFAULT_ROLE_NAME'])
            return u

    def create_temp_empty_user(self):
        """
        Returns a temporary, empty user object.
        """
        return User(None, None, None, None)

    def create_temp_empty_group(self):
        """
        Returns a temporary, empty group object.
        """
        return Group(None, None)

    def add_group(self, group_name, description='', user_id=None):
        '''
        Adds a new group to the database.

        @param group_name: The group name to add, must be unique.
        @param description: (Optional) The group description.
        @param user_id: (Optional) Single or multiple user IDs to associate
                        with this group.

        @return The group object created
        '''

        exists = Group.query.filter_by(name=group_name).first()

        if exists:
            raise DuplicateGroup("{0} already exists in database with id '{0}'".
                format(group_name, exists.id))
        else:
            g = Group(group_name, description)
            mainDB.session.add(g)
            mainDB.session.flush()
            if user_id:
                exists = User.query.filter_by(id=user_id).first()
                if exists:
                    gm = GroupMapping(g, exists)
                    mainDB.session.add(gm)
                else:
                    raise UserNotFound(
                        "%s not found in database to match with new group".
                        format(user_id))

            mainDB.session.commit()
            self.eventLog.add('add_group', 0, True, None, group_name)
            return g

    def add_to_group(self, u, g):
        '''
        Adds a user to a group.

        @param u: The user to link. Can be an integer for the uid or a user
                  object
        @param g: The group to link. Can be an integer for the gid, a string for
                  group name, or a group object
        '''
        user = self.get_user(u)
        group = self.get_group(g)

        exist = GroupMapping.query.filter_by(user=user).filter_by(
                group=group).all()

        if exist == []:
            gm = GroupMapping(group, user)
            mainDB.session.add(gm)

        mainDB.session.commit()

    def get_group(self, g):
        '''
        Given a group identifier, return the group object.

        @param g: The group to return. Can be an integer for the gid or a string
                  of the group's name.

        @return The group object found, or None.
        '''
        group = g
        if isinstance(g, IntType):
            group = Group.query.filter_by(id=g).first()
        elif isinstance(g, string_types):
            group = Group.query.filter_by(name=g).first()

        return group

    def get_all_groups(self):
        '''
        Return all possible groups.
        '''
        return Group.query.all()

    def get_users_groups(self, u):
        '''
        Given a user identifier, return the groups it is a member of.

        @param u: The user. Can be an integer for the uid, a string for the
                  username, or a user object

        @return A list of groups the user is a member of.
        '''
        user = self.get_user(u)

        gms = GroupMapping.query.filter_by(user=user)

        if gms is None:
            raise UserHasNoGroups(
                "{0} does not have any group mappings! Every user should be "\
                "a member of at least one group!".format(user))

        groups = []
        for m in gms:
            groups.append(m.group)

        return groups

    def update_primary(self, u, g):
        '''
        Updates the primary group a user belongs to. If the user is not already
        in that group, they are added to it.

        @param u: The user to update. Can be an integer for the uid, a username,
                  or a user object
        @param g: The group to use. Can be an integer for the gid, a group name,
                  or a group object.

        @return True on success, False on failure
        '''
        user = self.get_user(u)
        group = self.get_group(g)

        if isinstance(user, User) and isinstance(group, Group):
            exists = GroupMapping.query.filter_by(
                    user=user).filter_by(group=group).first()
            if exists == []:
                self.add_to_group(u, g)
            user.primary_group = group
            mainDB.session.commit()
            return True
        else:
            return False

    def remove_from_group(self, u, g):
        """
        Removes a group association from a user.
        """
        user = self.get_user(u)
        group = self.get_group(g)

        if isinstance(user, User) and isinstance(group, Group):
            if user.primary_group == group:
                raise CannotRemovePrimaryGroup(
                    'Cannot remove {0} from their primary group {1}'.format(
                    user, group))

            gm = GroupMapping.query.filter_by(user=user).filter_by(
                    group=group).first()
            if gm == []:
                raise UserNotInGroup(
                    'User {0} was not a member of the group {1}'.format(
                    user, group))

            mainDB.session.delete(gm)
            mainDB.session.commit()
            self.eventLog.add('rm_from_group', user.id, True, None, user, group)
            return True
        return False

    def update_password(self, u, newpass):
        '''
        Updates the user's password. Assumes that the password has been
        validated.

        @param u: The user to update. Can be an integer for the uid, a username,
                  or a user object.
        @param newpass: The new password.
        '''
        user = self.get_user(u)

        if user is not None:
            user.passhash = mainCrypt.generate_password_hash(newpass)
            mainDB.session.commit()
        else:
            raise UserNotFound("User not found in database")

    def update_user(self, u):
        '''
        Given a user object, update the database with whatever changes it
        contains.

        @param u: A user object.
        '''
        if isinstance(u, User):
            exists = User.query.get(u.id)
            if exists == []:
                mainDB.session.add(u)
            mainDB.session.commit()

    def update_group(self, g):
        """
        Given a group object, update the database with whatever changes it
        contains.
        """
        if isinstance(g, Group):
            exists = Group.query.get(g.id)
            if exists == []:
                mainDB.session.add(g)
            mainDB.session.commit()

    def in_group(self, u, g):
        '''
        Checks if a user is in a group

        @param u: The user to link. Can be an integer for the uid or a user
                  object
        @param g: The group to link. Can be an integer for the gid, a string for
                  group name, or a group object
        '''
        user = self.get_user(u)
        group = self.get_group(g)

        exist = GroupMapping.query.filter_by(user=user).filter_by(
                group=group).first()

        if exist is None:
            return False

        return True

    def delete(self, u):
        '''
        Deletes a user from the database.

        @param u: A user to delete. Can be an integer for the uid or a user
                  object
        '''

        user = self.get_user(u)
        if user is not None:
            uid = int(user.id)
            uname = str(user.name)
            mainDB.session.delete(user)
            mainDB.session.commit()
            self.eventLog.add('del_user', uid, True, None, uname)
        else:
            raise UserNotFound("User not found in database")

    def delete_group(self, g):
        """
        Deletes a group from the database. Group can be integer, string, or
        group object.
        """
        group = self.get_group(g)
        if group is not None:
            gid = int(group.id)
            gname = group.name
            mainDB.session.delete(group)
            mainDB.session.commit()
            self.eventLog.add('del_group', gid, True, None, gname)
        else:
            raise GroupNotFound('Group not found in database')

    def authenticate(self, username, passwd, remember):
        '''
        Authenticates a user.
        '''
        try:
            users = self.find_user_by_name(username)
            if len(users) < 1:
                return False
            u = users[0]
            if mainCrypt.check_password_hash(u.passhash, passwd):
                u.authenticated = True
                u.active = True
                mainDB.session.commit()
                return login_user(u, remember=remember)
            else:
                u.authenticated = False
                u.active = False
                mainDB.session.commit()
                return False
        except:
            raise
        return False

    def logout(self, u):
        '''
        Given a user, will log them out. Returns True on success, False on
        failure.

        @param u: A user to logout. Can be a uid or a user object.
        '''
        user = self.get_user(u)
        if user.authenticated or user.active:
            user.authenticated = False
            user.active = False
            mainDB.session.commit()
            logout_user()
            return True
        else:
            logout_user()
            return False
コード例 #8
0
class EntryDB:
    __borg_state = {}

    def __init__(self):
        self.__dict__ = self.__borg_state

        try:
            self._setup
        except AttributeError:
            self._setup = False

        if not self._setup:
            self.event_log = EventLog()
            self._setup = True

    def add(self, title, entry, author, group=None, weight=0, url=None,
            html=False, parent=None, static=False,
            postdate=datetime.datetime.now()):
        """
        Adds an entry to the system.

        Will not perform any checks, it will just add this entry. It's not
        this method's responsibility to check whether or not your entry is a
        duplicate. The one check it does do is to verify whether a URL is
        unique or not.

        :param title: The title of the post.
        :param entry: The entry of the post.
        :param author: The user object for the post's author
        :param group: The (optional) group this post will belong to. If None,
                      use the author's primary group
        :param url: The (optional) URL for this post.
        :param html: Flag detailing whether this post is in HTML or not
        :param parent: The (optional) parent for this post.
        :param static: (Optional) Whether or not the post is static.
        :param postdate: (Optional) The date of the post, current date default.

        :returns: New entry object just added
        """
        if group is None:
            group = author.primary_group

        e = Entry(title, author, group, postdate, entry, weight, url, html,
                parent, static)

        if type(url) is StringType:
            if self.find_by_URL(url):
                raise DuplicateURL(
                        'The URL "%s" was already found in the UrlDB!' % url)
            else:
                mainDB.session.add(e)
                mainDB.session.commit()
        else:
            mainDB.session.add(e)
            mainDB.session.commit()

        # FIXME
        # When a child is added, we need to also trigger page refreshes for
        # each member of the parent's children

        pe = PEntry(e)
        self.event_log.add('add_entry', author.id, False,
                pickle(pe), repr(e.title))
        return e

    def add_entry_object(self, entry):
        """
        Given an entry object, add it to the system.

        :param entry: The entry object to add.
        """
        mainDB.session.add(entry)
        mainDB.session.commit()
        pe = PEntry(entry)
        self.event_log.add('add_entry', entry.author.id, False, pickle(pe),
            repr(entry.title))

    def update_entry(self, entry):
        """
        Given an entry object, update it.

        :param entry: The entry object to update.
        """
        mainDB.session.commit()
        pe = PEntry(entry)
        self.event_log.add('update_entry', entry.author.id, False, pickle(pe),
            repr(entry.title))

    def create_temp_entry(self, title, entry, author, group=None, weight=0,
            url=None, html=False, parent=None, static=False,
            postdate=datetime.datetime.now()):
        '''
        Create a temporary entry object. Will not add it to the database.

        Will not perform any checks, it will just add this entry. It's not
        this method's responsibility to check whether or not your entry is a
        duplicate. The one check it does do is to verify whether a URL is
        unique or not.

        :param title: The title of the post.
        :param entry: The entry of the post.
        :param author: The user object for the post's author
        :param group: The (optional) group this post will belong to. If None,
                      use the author's primary group
        :param url: The (optional) URL for this post.
        :param html: Flag detailing whether this post is in HTML or not
        :param parent: The (optional) parent for this post.
        :param static: (Optional) Whether or not the post is static.

        :returns: New entry object
        '''
        if group is None:
            group = author.primary_group

        e = Entry(title, author, group, postdate, entry, weight, url, html,
                parent, static)

        if type(url) is StringType:
            if self.find_by_URL(url):
                raise DuplicateURL(
                        'The URL "%s" was already found in the UrlDB!' % url)

        return e

    def add_tag(self, tags, entry):
        """
        Adds one or more tags to be associated with an entry. Or, if tags
        already exist, updates them to also point to the entry.

        :param tags: Array of one or more tags.
        :param entry: An entry to associate with the tags.
        """
        for tag in tags:
            if tag != '':
                t = Tag.query.filter_by(tag=tag).first()
                if t == None:
                    t = Tag(tag)
                    mainDB.session.add(t)
                    self.event_log.add('add_tag', entry.author_id, False, tag,
                        tag)
                exist = TagMapping.query.filter_by(tag_id=t.id).filter_by(
                    entry_id=entry.id).all()
                if exist == []:
                    tm = TagMapping(t, entry)
                    mainDB.session.add(tm)

        mainDB.session.commit()
        tags = self.find_tags_by_entry(entry)

    def get_tags(self):
        """
        Obtain the tags currently in the system.
        """
        return Tag.query.order_by(Tag.id).all()

    def update_editor(self, u, e):
        """
        Given a user and an entry, update that entry's editors with that user.

        :param u: The user who edited the entry. Can be a user object, a uid,
                  or a string representing the username.
        :param e: The entry. Can be an entry id or an entry object.
        """
        now = datetime.datetime.now()
        entry = e
        if type(e) is IntType:
            entry = Entry.query.filter_by(id=e).first()

        users = UserDB().get_users(u)
        if len(users) > 0:
            user = users[0]
            editor = Editor.query.filter_by(entry_id=e.id).filter_by(
                user_id=user.id).first()
            if editor is None:
                editor = Editor(user, entry, now)
                mainDB.session.add(editor)
            else:
                editor.date = now

            mainDB.session.commit()
            pe = PEntry(entry)
            self.event_log.add('update_entry', user.id, False, pickle(
                pe), entry.title)

    def find_editors_by_entry(self, entry):
        """
        Given an entry, find all editors associated with it.

        :param entry: The entry. Either an Entry object or entry id.

        :return Array containing zero or more editors.
        """
        eid = entry
        if type(entry) is not IntType:
            eid = entry.id

        return Editor.query.filter_by(entry_id=eid).all()

    def find_by_URL(self, url):
        """
        Given a URL, find all entries associated with it.

        :param url: The URL string.

        :returns: Array containing one or more entries.
        """
        return Entry.query.filter_by(url=url).all()

    def find_tags_by_entry(self, entry):
        """
        Given an entry, find all tags associated with it.

        :param entry: The entry. Either an Entry object or entry id.

        :returns: Array containing one or more tag objects.
        """
        e = entry
        if type(entry) is IntType:
            e = self.find_by_id(entry)
        tags = []
        for tm in TagMapping.query.filter_by(entry_id=e.id).all():
            tags.append(tm.tag)

        return tags

    def find_by_tags(self, tags):
        """
        Given one or more tags, find all entries tagged with them.

        :param tags: One or more tags. Tags can be tag ids, tag objects, or
                     tag strings. Tags must be iterable.

        :returns: Array contating the entry objects.
        """
        # FIXME - The following should order them by weight and date, instead
        # it will cluster them first by tags.
        e = []
        clauses = []
        for tag in tags:
            tagObj = tag
            if type(tag) is IntType:
                tagObj = Tag.query.filter_by(id=tag).first()
            elif type(tag) is StringType:
                tagObj = Tag.query.filter_by(tag=tag).first()
            if tagObj != None:
                clauses.append(TagMapping.tag == tagObj)

        # Yeah, double loops is bad
        if len(clauses) > 0:
            where = mainDB.or_(*clauses)
            # XXX - Is this the best way to do this?
            for mapping in TagMapping.query.filter(where).join(Entry).order_by(
                    Entry.weight).order_by(Entry.date).all():
                e.append(Entry.query.get(mapping.entry_id))

        return e

    def find_recent_by_num(self, num, offset=0, weight=True):
        """
        Finds the most recent entries with a maximum of 'num'.

        :param num: The number of entries to find
        :param offset: The offset for the entries to find.
        :param weight: If the weight should be taken into account (defaults to
                       true.

        :returns: Array containing the entry objects.
        """
        if type(num) is IntType:
            if weight:
                return Entry.query.order_by(Entry.date.desc(),
                        Entry.weight).offset(offset).limit(num).all()
            else:
                return Entry.query.order_by(Entry.date.desc()).offset(
                        offset).limit(num).all()
        else:
            raise TypeError("Expected integer for num")

    def count(self):
        """
        Returns the number of possible entries.
        """
        return Entry.query.order_by(Entry.date.desc(), Entry.weight).count()

    def find_by_title(self, title):
        """
        Finds entries based upon the title. Can search using sub-strings.

        :param title: The title of the post (or sub-string of title).

        :returns: Array containing one or more entry objects, or None.
        """
        return Entry.query.filter(Entry.Entry.title.like("%%%s%%" %
            title)).all()

    def find_by_id(self, num):
        """
        Finds entries based upon the ID.

        :param num: The numerical ID of the post.

        :returns: The entry objects, or None.
        """
        return Entry.query.get(num)

    def delete(self, e):
        """
        Deletes an entry from the database.

        :param e: An entry to delete. Can be an integer for the entry id or an
                  entry object.
        """
        # FIXME
        # Should deal with parents and children so as not to leave orphans
        entry = e
        if type(e) is IntType:
            entry = Entry.query.filter_by(id=e).first()

        pe = PEntry(e)
        mainDB.session.delete(entry)
        mainDB.session.commit()
        self.event_log.add('del_entry', 0, False, pickle(pe), entry.title)
コード例 #9
0
ファイル: role_db.py プロジェクト: criswell/noink
class RoleDB:
    __borg_state = {}

    def __init__(self):
        self.__dict__ = self.__borg_state

        try:
            self._setup
        except AttributeError:
            self._setup = False

        if not self._setup:
            self.eventLog = EventLog()
            self._setup = True

    def find_role_by_name(self, rolename):
        """
        Finds a role by it's name.

        @param rolename: The name of the role.

        @return The role object found.
        """
        return Role.query.filter_by(name=rolename).first()

    def find_role_by_id(self, rid):
        """
        Find a role by its role ID.

        @param rid: The role ID to find.

        @return The role object found.
        """
        return Role.query.get(rid)

    def get_role(self, role):
        """
        Given a role identifier, return the role object.

        @param role: The role. Can be role object, rid, or string name.
        """
        r = role
        if isinstance(role, IntType):
            r = self.find_role_by_id(role)
        elif isinstance(role, string_types):
            r = self.find_role_by_name(role)

        return r

    def get_rolemapping(self, user, group, role):
        """
        Given a user, group and role, will return the rolemap of the three,
        if it exists. Otherwise will return None.

        FIXME - Docstring
        """
        r = self.get_role(role)
        user_db = UserDB()
        u = user_db.get_user(user)
        g = user_db.get_group(group)

        return RoleMapping.query.filter_by(user=u).filter_by(group=g).filter_by(role=r).first()

    def add_role(self, name, description, activities=None):
        """
        Add a new role to the DB.

        @param name: Short, descriptive name of the role. Must be unique.
        @param description: Longer description of the role.
        @param activities: An activity dict defining the role's activities.
                           If parameter is omitted, then a default dict is used.
        """
        try:
            exists = self.find_role_by_name(name)
        except:
            exists = False

        if exists:
            raise DuplicateRole("{0} already exists as a role with id " "'{1}'".format(name, str(exists)))

        if activities is None:
            activities = get_activity_dict(False)

        now = datetime.datetime.now()
        pact = pickle(activities)
        role = Role(name, description, pact, now)
        mainDB.session.add(role)
        mainDB.session.commit()
        blob = pickle({"id": role.id})
        # XXX - Do we want to use the user ID of the person adding this role?
        self.eventLog.add("add_role", -1, True, blob, role.name)
        return role

    def update_role(self, role):
        """
        Given a role object, update the database with whatever changes it
        contains.
        """
        if isinstance(role, Role):
            exists = Role.query.get(role.id)
            if exists == []:
                mainDB.session.add(role)
            mainDB.session.commit()

    def create_temp_empty_role(self):
        """
        Returns a temporary, empty role object.
        """
        pact = pickle(get_activity_dict(False))
        return Role(None, None, pact, None)

    def update_temp_role_activities(self, role, acts):
        """
        Given a temportary role and updated activies for it, update it.

        Retuns updated role.
        """
        pact = pickle(acts)
        role.activities = pact
        return role

    def get_activities(self, role):
        """
        Given a role, return the activities that role can do.

        @param role: The role to use. Can be a role object, a role.id, or a
                     role name.

        @return Decoded/decoupled activity dictionary
        """
        r = self.get_role(role)

        if r is not None:
            return depickle(r.activities)
        else:
            return None

    def assign_role(self, user, group, role):
        """
        Given a user, group and role, assign the user as the role when part of
        the group.

        @param user: The user. Can be user object, uid, or string name of the
                     user.
        @param group: The group. Can be group object, gid, or string name.
        @param role: The role. Can be role object, rid, or string name.
        """
        userDB = UserDB()
        u = userDB.get_user(user)
        g = userDB.get_group(group)
        r = self.get_role(role)

        exist = RoleMapping.query.filter_by(user=u).filter_by(group=g).filter_by(role=r).all()

        if exist == []:
            rm = RoleMapping(r, u, g)
            mainDB.session.add(rm)

        mainDB.session.commit()

    def revoke_role(self, user, group, role):
        """
        Given a user, group and role, revoke the user's rights to that role
        when part of the group.

        @param user: The user. Can be a user object, uid, or string name of
                     the user.
        @param group: The group. Can be a group object, gid, or string name.
        @param role: The role. Can be role object, rid, or string name.
        """
        user_db = UserDB()
        u = user_db.get_user(user)
        g = user_db.get_group(group)
        r = self.get_role(role)
        rmaps = RoleMapping.query.filter_by(user=u).filter_by(group=g).filter_by(role=r).all()

        for rm in rmaps:
            mainDB.session.delete(rm)

        mainDB.session.commit()

    def delete_role(self, role):
        """
        Given a role, delete it from the database. Role can be integer,
        string or role object.
        """
        r = self.get_role(role)
        if role is not None:
            rid = int(r.id)
            rname = r.name
            mainDB.session.delete(r)
            mainDB.session.commit()
            self.eventLog.add("del_role", rid, True, None, rname)
        else:
            raise RoleNotFound("Role not found in database")

    def get_roles(self, user, group=None):
        """
        Get the roles a given user has. Optionally, limit by group.

        @param user: The user. Can be user object, uid, or string name.
        @param group: Group to limit by. Can be group object, gid, or string
                      name.

        @return A list of role mappings.
        """
        userDB = UserDB()
        u = userDB.get_user(user)
        rm = RoleMapping.query.filter_by(user=u)
        if group is not None:
            g = userDB.get_group(group)
            rm = rm.filter_by(group=g)

        return rm.all()

    def get_all_roles(self):
        """
        Get all the available roles
        """
        return Role.query.all()
コード例 #10
0
ファイル: icebox.py プロジェクト: criswell/noink
class Icebox:

    __borg_state = {}

    def __init__(self):
        self.__dict__ = self.__borg_state

        try:
            self._setup
        except AttributeError:
            self._setup = False

        if not self._setup:
            self.event_log = EventLog()
            self.entry_db = EntryDB()
            self.icebox_path = abspath(mainApp.config['ICEBOX_PATH'])
            if mainApp.config['ICEBOX_STATIC_PATH'] is not None:
                self.static_path = abspath(mainApp.config['ICEBOX_STATIC_PATH'])
            else:
                self.static_path = None
            self.client = mainApp.test_client()
            self._setup = True

    def generate_pages(self, all_pages=False):
        """
        Generate the pages.

        If all_pages is True, will regenerate the entire site.
        """
        if not isdir(self.icebox_path):
            makedirs(self.icebox_path)

        state = State()
        state.icebox = True

        if all_pages:
            self._rebuild_site()
        else:
            for e in self.event_log.get_unprocessed():
                if e.event in ('add_entry', 'update_entry'):
                    pe = depickle(e.blob)
                    entry = self.entry_db.find_by_id(pe.id)
                    if entry is not None:
                        self._generate_page(entry)
                elif e.event == 'rebuild_static':
                    self._rebuild_site()
                elif e.event == 'del_entry':
                    pe = depickle(e.blob)
                    self._remove_page(pe.id, pe.url)
                self.event_log.mark_as_processed(e)

        # Regenerate index
        self._generate_index()

        # Regenerate tags
        self._generate_tags()

        # Sync static pages
        if self.static_path:
            self.sync_static()

    def _rebuild_site(self):
        """
        Rebuild the entire site
        """
        self.clear_icebox_path()
        count = self.entry_db.count()
        per_page = mainApp.config['NUM_ENTRIES_PER_PAGE'][0]
        total_pages = int(ceil(float(count) / float(per_page)))
        for i in range(total_pages):
            entries = self.entry_db.find_recent_by_num(per_page,
                    i * per_page)
            for e in entries:
                self._generate_page(e)

    def _generate_tags(self):
        """
        Generate the tag pages.
        """
        # Clean up old tags
        rmfiles = glob('{0}/tag/*'.format(self.icebox_path))
        for f in rmfiles:
            if isfile(f):
                remove(f)

        all_tags = self.entry_db.get_tags()
        for t in all_tags:
            response = self.client.get("/tag/{0}".format(t.id),
                follow_redirects=True)
            html = response.data
            filename = 'tag/{0}.html'.format(t.id)
            self._write_page(html, filename)

    def sync_static(self):
        """
        Synchronize static content
        """
        base_dir = "{0}/s".format(self.icebox_path)
        if not isdir(base_dir):
            makedirs(base_dir)
        for root, dummy, files in walk(join(self.icebox_path, 's')):
            for f in files:
                if isfile(join(root, f)):
                    remove(join(root, f))

        for root, dummy, files in walk(self.static_path):
            for f in files:
                source_name = join(root, f)
                dest_name = join(join(
                    '{0}/s'.format(self.icebox_path),
                    relpath(root, self.static_path)), f)
                base_dest = dirname(dest_name)
                if not isdir(base_dest):
                    makedirs(base_dest)
                link(source_name, dest_name)

    def clear_icebox_path(self):
        """
        Will clear the icebox path.

        WARNING: This is destructive, and should only be used when you know
        what you're doing. This will nuke the contents of the icebox path.
        """
        rmfiles = []
        for root, dirs, files in walk(self.icebox_path):
            for d in dirs:
                rmfiles.append(join(root, d))
            for f in files:
                rmfiles.append(join(root, f))
        rmfiles.sort(key=len)
        rmfiles.reverse()

        for f in rmfiles:
            if isfile(f):
                remove(f)
            elif isdir(f):
                rmdir(f)

    def _convert_url_to_path(self, url):
        """
        Given a URL, convert it to a filepath.

        Return filepath.
        """
        if url.endswith('/'):
            url += 'index.html'
        else:
            url += '.html'

        if url.startswith('/'):
            return url[1:]
        else:
            return url

    def _generate_page(self, entry):
        """
        Given an entry, will generate the page for it (including any
        aliases).
        """
        response = self.client.get('/node/{0}'.format(entry.id),
            follow_redirects=True)
        html = response.data
        # First, generate the node
        filename = 'node/{0}.html'.format(entry.id)
        self._write_page(html, filename)

        if entry.url:
            filename = self._convert_url_to_path(entry.url)
            self._write_page(html, filename)

    def _generate_index(self):
        """
        Generate the main index
        """
        # First clear the old indexes out of the way
        rmfiles = ['{0}/index.html'.format(self.icebox_path)]
        rmfiles.extend(glob('{0}/index_page_*'.format(self.icebox_path)))
        for f in rmfiles:
            if isfile(f):
                remove(f)

        per_page = mainApp.config['NUM_ENTRIES_PER_PAGE'][0]
        count = self.entry_db.count()
        total_pages = 0
        if count > per_page:
            total_pages = int(ceil(float(count) / float(per_page)))

        response = self.client.get('/', follow_redirects=True)
        html = response.data
        filename = 'index.html'
        self._write_page(html, filename)

        for i in range(total_pages):
            response = self.client.get('/?page={0}'.format(i),
                follow_redirects=True)
            html = response.data
            filename = 'index_page_{0}.html'.format(i)
            self._write_page(html, filename)

    def _write_page(self, html, filename):
        """
        Write the actual page to filename
        """
        fullname = "{0}/{1}".format(self.icebox_path, filename)
        base_dir = dirname(fullname)
        if not isdir(base_dir):
            makedirs(base_dir)

        with open(fullname, 'wb') as fd:
            fd.write(html)

    def _remove_page(self, entry_id, entry_url):
        """
        Given an entry, will remove the page for it.
        """
        node_fn = 'node/{0}.html'.format(entry_id)
        if isfile(node_fn):
            remove(node_fn)

        if entry_url:
            filename = self._convert_url_to_path(entry_url)
            if isfile(filename):
                remove(filename)