def index(self, page=1, **kwargs): """List podcasts and podcast media. Our custom paginate decorator allows us to have fewer podcast episodes display on the first page than on the rest with the ``items_first_page`` param. See :class:`mediacore.lib.custompaginate.CustomPage`. :param page: Page number, defaults to 1. :type page: int :rtype: dict :returns: podcasts The :class:`~mediacore.model.podcasts.Podcast` instance episodes The list of :class:`~mediacore.model.media.Media` instances for this page. """ episodes = ( DBSession.query(Media) .filter(Media.podcast_id != None) .order_by(Media.publish_on.desc()) .options(orm.undefer("comment_count_published")) ) episodes = self._filter(episodes) podcasts = DBSession.query(Podcast).options(orm.undefer("published_media_count")).all() return dict(podcasts=podcasts, episodes=episodes)
def index(self, page=1, search=None, podcast_filter=None, **kwargs): """List media with pagination and filtering. :param page: Page number, defaults to 1. :type page: int :param search: Optional search term to filter by :type search: unicode or None :param podcast_filter: Optional podcast to filter by :type podcast_filter: int or None :rtype: dict :returns: media The list of :class:`~mediacore.model.media.Media` instances for this page. search The given search term, if any search_form The :class:`~mediacore.forms.admin.SearchForm` instance podcast_filter The given podcast ID to filter by, if any podcast_filter_title The podcast name for rendering if a ``podcast_filter`` was specified. podcast_filter_form The :class:`~mediacore.forms.media.PodcastFilterForm` instance. """ media = DBSession.query(Media)\ .filter(Media.status.excludes('trash'))\ .options(orm.undefer('comment_count_published'))\ .options(orm.undefer('comment_count_unreviewed'))\ .order_by(Media.status.desc(), Media.publish_on.desc(), Media.modified_on.desc()) if search is not None: like_search = '%' + search + '%' media = media.filter(sql.or_( Media.title.like(like_search), Media.description.like(like_search), Media.notes.like(like_search), Media.tags.any(Tag.name.like(like_search)), )) podcast_filter_title = podcast_filter if podcast_filter == 'Unfiled': media = media.filter(~Media.podcast.has()) elif podcast_filter is not None and podcast_filter != 'All Media': media = media.filter(Media.podcast.has(Podcast.id == podcast_filter)) podcast_filter_title = DBSession.query(Podcast.title).get(podcast_filter) podcast_filter = int(podcast_filter) return dict( media = media, podcast_filter = podcast_filter, podcast_filter_title = podcast_filter_title, podcast_filter_form = podcast_filter_form, search = search, search_form = search_form, )
class MediaForm(ListForm): template = 'admin/box-form.html' id = 'media-form' css_class = 'form' submit_text = None show_children_errors = True _name = 'media-form' # TODO: Figure out why this is required?? fields = [ SingleSelectField('podcast', label_text=N_('Include in the Podcast'), css_classes=['dropdown-select'], help_text=N_('Optional'), options=lambda: [(None, None)] + DBSession.query( Podcast.id, Podcast.title).all()), TextField('slug', label_text=N_('Permalink'), maxlength=50), TextField('title', label_text=N_('Title'), validator=TextField.validator(not_empty=True), maxlength=255), TextField('author_name', label_text=N_('Author Name'), maxlength=50), TextField('author_email', label_text=N_('Author Email'), validator=email_validator(not_empty=True), maxlength=255), XHTMLTextArea('description', label_text=N_('Description'), attrs=dict(rows=5, cols=25)), CategoryCheckBoxList( 'categories', label_text=N_('Categories'), options=lambda: DBSession.query(Category.id, Category.name).all()), TextArea('tags', label_text=N_('Tags'), attrs=dict(rows=3, cols=15), help_text=N_(u'e.g.: puppies, great dane, adorable')), TextArea('notes', label_text=N_('Administrative Notes'), attrs=dict(rows=3, cols=25), container_attrs=lambda: ({ 'class': 'hidden' }, {})[bool( app_globals.settings.get( 'wording_display_administrative_notes', ''))], default=lambda: app_globals.settings[ 'wording_administrative_notes']), SubmitButton('save', default=N_('Save'), named_button=True, css_classes=['btn', 'blue', 'f-rgt']), SubmitButton('delete', default=N_('Delete'), named_button=True, css_classes=['btn', 'f-lft']), ] def post_init(self, *args, **kwargs): events.Admin.MediaForm(self)
def index(self, page=1, search=None, media_filter=None, **kwargs): """List comments with pagination and filtering. :param page: Page number, defaults to 1. :type page: int :param search: Optional search term to filter by :type search: unicode or None :param media_filter: Optional media ID to filter by :type media_filter: int or None :rtype: dict :returns: comments The list of :class:`~mediacore.model.comments.Comment` instances for this page. edit_form The :class:`mediacore.forms.comments.EditCommentForm` instance, to be rendered for each instance in ``comments``. search The given search term, if any search_form The :class:`~mediacore.forms.admin.SearchForm` instance media_filter The given podcast ID to filter by, if any media_filter_title The media title for rendering if a ``media_filter`` was specified. """ comments = DBSession.query(Comment)\ .filter(Comment.status.excludes('trash'))\ .order_by(Comment.status.desc(), Comment.created_on.desc()) if search is not None: like_search = '%' + search + '%' comments = comments.filter(sql.or_( Comment.subject.like(like_search), Comment.body.like(like_search), )) media_filter_title = media_filter if media_filter is not None: comments = comments.filter(Comment.media.has(Media.id == media_filter)) media_filter_title = DBSession.query(Media.title).get(media_filter) media_filter = int(media_filter) return dict( comments = comments, edit_form = edit_form, media_filter = media_filter, media_filter_title = media_filter_title, search = search, search_form = search_form, )
def fetch_and_create_tags(tag_names): tag_dict = dict() for t in tag_names: tag_dict[slugify(t)] = t existing_tags = DBSession.query(Tag).filter(Tag.slug.in_(tag_dict.keys())).all() existing_slugs = [t.slug for t in existing_tags] new_slugs = [s for s in tag_dict.keys() if s not in existing_slugs] new_tags = [{'name': tag_dict[s], 'slug': s} for s in new_slugs] if new_tags: DBSession.connection().execute(tags.insert(), new_tags) DBSession.flush() existing_tags += DBSession.query(Tag).filter(Tag.slug.in_(new_slugs)).all() return existing_tags
def index(self, page=1, **kwargs): """List storage engines with pagination. :rtype: Dict :returns: engines The list of :class:`~mediacore.lib.storage.StorageEngine` instances for this page. """ engines = DBSession.query(StorageEngine)\ .options(orm.undefer('file_count'), orm.undefer('file_size_sum'))\ .all() engines = list(sort_engines(engines)) existing_types = set(ecls.engine_type for ecls in engines) addable_engines = [ ecls for ecls in StorageEngine if not ecls.is_singleton or ecls.engine_type not in existing_types ] return { 'engines': engines, 'addable_engines': addable_engines, }
def feed(self, slug, **kwargs): """Serve the feed as RSS 2.0. If :attr:`~mediacore.model.podcasts.Podcast.feedburner_url` is specified for this podcast, we redirect there. :param slug: A :attr:`~mediacore.model.podcasts.Podcast.slug` :param page: Page number, defaults to 1. :type page: int :rtype: dict :returns: podcast A :class:`~mediacore.model.podcasts.Podcast` instance. episodes A list of :class:`~mediacore.model.media.Media` instances that belong to the ``podcast``. podcasts A list of all the other podcasts """ podcast = fetch_row(Podcast, slug=slug) episodes = self._filter(podcast.media).order_by(Media.publish_on.desc()) podcasts = DBSession.query(Podcast).options(orm.undefer("published_media_count")).all() return dict(podcast=podcast, episodes=episodes, podcasts=podcasts)
def test_can_fake_logged_in_user(self): admin = DBSession.query(User).filter(User.user_name==u'admin').one() assert_true(admin.has_permission(u'admin')) self.init_fake_request() self.set_authenticated_user(admin) assert_true(has_permission(u'admin'))
def index(self, page=1, category='topics', **kwargs): """List topics or tags with pagination. :param category: ``topics`` or ``tags`` :param page: Page number, defaults to 1. :type page: int :rtype: Dict :returns: categories The list of :class:`~mediacore.model.tags.Tag` or :class:`~mediacore.model.topics.Topic` instances for this page. category ``topics`` or ``tags`` category_name ``Topics`` or ``Tags`` edit_form The :class:`~mediacore.forms.categories.EditCategoryForm` instance. """ model = self.select_model(category) categories = DBSession.query(model).order_by(model.name) return dict( categories = categories, category = category, category_name = category.capitalize(), edit_form = edit_form, )
def test_can_fake_logged_in_user(self): admin = DBSession.query(User).filter(User.user_name == u'admin').one() assert_true(admin.has_permission(u'admin')) self.init_fake_request() self.set_authenticated_user(admin) assert_true(has_permission(u'admin'))
def _published_media_query(self): """Helper method for getting published media""" return DBSession.query(Media)\ .filter(Media.status >= 'publish')\ .filter(Media.publish_on <= datetime.now())\ .filter(Media.status.excludes('trash'))\ .order_by(Media.publish_on.desc())
def index(self, page=1, **kwargs): """List storage engines with pagination. :rtype: Dict :returns: engines The list of :class:`~mediacore.lib.storage.StorageEngine` instances for this page. """ engines = DBSession.query(StorageEngine)\ .options(orm.undefer('file_count'), orm.undefer('file_size_sum'))\ .all() engines = list(sort_engines(engines)) existing_types = set(ecls.engine_type for ecls in engines) addable_engines = [ ecls for ecls in StorageEngine if not ecls.is_singleton or ecls.engine_type not in existing_types ] return { 'engines': engines, 'addable_engines': addable_engines, }
def permissions_for_request(cls, environ, config): identity = environ.get('repoze.who.identity', {}) user_id = identity.get('repoze.who.userid') user = None if user_id is not None: user = DBSession.query(User).filter(User.user_id==user_id).first() return cls.permissions_for_user(user, config)
def permissions_for_request(cls, environ, config): identity = environ.get('repoze.who.identity', {}) user_id = identity.get('repoze.who.userid') user = None if user_id is not None: user = DBSession.query(User).filter(User.id==user_id).first() return cls.permissions_for_user(user, config)
class GroupForm(ListForm): template = 'admin/box-form.html' id = 'group-form' css_class = 'form' submit_text = None show_children_errors = True event = events.Admin.GroupForm fields = [ TextField('display_name', label_text=N_('Display Name'), validator=TextField.validator(not_empty=True), maxlength=255), TextField('group_name', label_text=N_('Groupname'), validator=All(PlainText(not_empty=True), UniqueGroupname()), maxlength=16), CheckBoxList( 'permissions', label_text=N_('Group Permissions'), css_classes=['details_fieldset'], options=lambda: DBSession.query(Permission.permission_id, Permission.description).all()), SubmitButton('save', default=N_('Save'), named_button=True, css_classes=['btn', 'btn-save', 'blue', 'f-rgt']), SubmitButton('delete', default=N_('Delete'), named_button=True, css_classes=['btn', 'btn-delete']), ]
def test_can_restrict_query_if_user_does_not_have_the_required_permission(self): query = Media.query permission = u'view' perm = self.perm() view_permission = DBSession.query(Permission).filter(Permission.permission_name == permission).one() view_permission.groups = [] DBSession.flush() assert_none(self.policy.access_condition_for_query(query, permission, perm))
def _to_python(self, value, state): id = request.environ["pylons.routes_dict"]["id"] query = DBSession.query(User).filter_by(user_name=value) if id != "new": query = query.filter(User.user_id != id) if query.count() != 0: raise Invalid(_("User name already exists"), value, state) return value
def _to_python(self, value, state): id = request.environ['pylons.routes_dict']['id'] query = DBSession.query(User).filter_by(user_name=value) if id != 'new': query = query.filter(User.user_id != id) if query.count() != 0: raise Invalid(_('User name already exists'), value, state) return value
def _create_user_with_admin_permission_only(self): admin_perm = DBSession.query(Permission).filter(Permission.permission_name == u'admin').one() second_admin_group = Group.example(name=u'Second admin group') admin_perm.groups.append(second_admin_group) admin = User.example(groups=[second_admin_group]) DBSession.commit() perm = MediaCorePermissionSystem.permissions_for_user(admin, config) assert_true(perm.contains_permission(u'admin')) assert_false(perm.contains_permission(u'edit')) return admin
def add_custom_profiles(): # Add all the custom profiles to the first existing PandaStorage instance. from mediacore.model import DBSession from mediacoreext.simplestation.panda.lib.storage import PandaStorage ps = DBSession.query(PandaStorage).all()[0] profiles = ps.panda_helper().client.get_profiles() pnames = [p['name'] for p in profiles] for x in custom_profiles: if x['name'] not in pnames: ps.panda_helper().client.add_profile_from_preset(**x)
def _to_python(self, value, state): id = request.environ['pylons.routes_dict']['id'] query = DBSession.query(User).filter_by(user_name=value) if id != 'new': query = query.filter(User.user_id != id) if query.count() != 0: raise Invalid(_('User name already exists'), value, state) return value
def _create_user_with_admin_permission_only(self): admin_perm = DBSession.query(Permission).filter( Permission.permission_name == u'admin').one() second_admin_group = Group.example(name=u'Second admin group') admin_perm.groups.append(second_admin_group) admin = User.example(groups=[second_admin_group]) DBSession.commit() perm = MediaCorePermissionSystem.permissions_for_user(admin, config) assert_true(perm.contains_permission(u'admin')) assert_false(perm.contains_permission(u'edit')) return admin
def update_enabled_players(): """Ensure that the encoding status of all media is up to date with the new set of enabled players. The encoding status of Media objects is dependent on there being an enabled player that supports that format. Call this method after changing the set of enabled players, to ensure encoding statuses are up to date. """ from mediacore.model import DBSession, Media media = DBSession.query(Media) for m in media: m.update_status()
def test_can_restrict_query_if_user_does_not_have_the_required_permission( self): query = Media.query permission = u'view' perm = self.perm() view_permission = DBSession.query(Permission).filter( Permission.permission_name == permission).one() view_permission.groups = [] DBSession.flush() assert_none( self.policy.access_condition_for_query(query, permission, perm))
def update_enabled_players(): """Ensure that the encoding status of all media is up to date with the new set of enabled players. The encoding status of Media objects is dependent on there being an enabled player that supports that format. Call this method after changing the set of enabled players, to ensure encoding statuses are up to date. """ from mediacore.model import DBSession, Media media = DBSession.query(Media) for m in media: m.update_status()
def __init__(self, *args, **kwargs): """Populate the :obj:`pylons.tmpl_context` with topics. Used by :data:`mediacore.templates.helpers` to render the topic index flyout slider. """ super(MediaController, self).__init__(*args, **kwargs) tmpl_context.topics = DBSession.query(Topic)\ .options(orm.undefer('published_media_count'))\ .having(sql.text('published_media_count >= 1'))\ .order_by(Topic.name)\ .all()
def view(self, slug, podcast_slug=None, **kwargs): """Display the media player, info and comments. :param slug: The :attr:`~mediacore.models.media.Media.slug` to lookup :param podcast_slug: The :attr:`~mediacore.models.podcasts.Podcast.slug` for podcast this media belongs to. Although not necessary for looking up the media, it tells us that the podcast slug was specified in the URL and therefore we reached this action by the preferred route. :rtype dict: :returns: media The :class:`~mediacore.model.media.Media` instance for display. comment_form The :class:`~mediacore.forms.comments.PostCommentForm` instance. comment_form_action ``str`` comment form action comment_form_values ``dict`` form values next_episode The next episode in the podcast series, if this media belongs to a podcast, another :class:`~mediacore.model.media.Media` instance. """ media = fetch_row(Media, slug=slug) media.views += 1 next_episode = None if media.podcast_id is not None: # Always view podcast media from a URL that shows the context of the podcast if url_for() != url_for(podcast_slug=media.podcast.slug): redirect(podcast_slug=media.podcast.slug) if media.is_published: next_episode = DBSession.query(Media)\ .filter(Media.podcast_id == media.podcast.id)\ .filter(Media.publish_on > media.publish_on)\ .filter(Media.publish_on < datetime.now())\ .filter(Media.status >= 'publish')\ .filter(Media.status.excludes('trash'))\ .order_by(Media.publish_on)\ .first() return dict( media = media, comment_form = post_comment_form, comment_form_action = url_for(action='comment'), comment_form_values = kwargs, next_episode = next_episode, )
def index(self, page=1, **kwargs): """List users with pagination. :param page: Page number, defaults to 1. :type page: int :rtype: Dict :returns: users The list of :class:`~mediacore.model.auth.User` instances for this page. """ users = DBSession.query(User).order_by(User.display_name, User.email_address) return dict(users=users)
def random(self, **kwargs): """Redirect to a randomly selected media item.""" # TODO: Implement something more efficient than ORDER BY RAND(). # This method does a full table scan every time. media = Media.query.published()\ .order_by(sql.func.random())\ .first() if media is None: redirect(action='explore') if media.podcast_id: podcast_slug = DBSession.query(Podcast.slug).get(media.podcast_id) else: podcast_slug = None redirect(action='view', slug=media.slug, podcast_slug=podcast_slug)
def random(self, **kwargs): """Redirect to a randomly selected media item.""" # TODO: Implement something more efficient than ORDER BY RAND(). # This method does a full table scan every time. random_query = Media.query.published().order_by(sql.func.random()) media = viewable_media(random_query).first() if media is None: redirect(action='explore') if media.podcast_id: podcast_slug = DBSession.query(Podcast.slug).get(media.podcast_id) else: podcast_slug = None redirect(action='view', slug=media.slug, podcast_slug=podcast_slug)
def _fetch_page(self, type='awaiting_review', page=1, items_per_page=6): """Helper method for paginating media results""" query = DBSession.query(Media).order_by(Media.modified_on.desc()) if type == 'awaiting_review': query = query.filter(Media.status.intersects('unreviewed'))\ .filter(Media.status.excludes('trash')) elif type == 'awaiting_encoding': query = query.filter(Media.status.intersects('unencoded'))\ .filter(Media.status.excludes('trash,unreviewed')) elif type == 'awaiting_publishing': query = query.filter(Media.status.issubset('draft')) return webhelpers.paginate.Page(query, page, items_per_page)
def __init__(self, *args, **kwargs): """Populate the :obj:`pylons.tmpl_context`` with topics. Used by :data:`mediacore.templates.helpers` to render the topic index flyout slider. """ super(PodcastsController, self).__init__(*args, **kwargs) tmpl_context.topics = ( DBSession.query(Topic) .options(orm.undefer("published_media_count")) .filter(Topic.published_media_count >= 1) .order_by(Topic.name) .all() )
def most_popular(self, **kwargs): """Expose basic info of the latest media object. .. todo:: Work this into a more general, documented API scheme. :rtype: JSON dict """ media_query = DBSession.query(Media)\ .filter(Media.status >= 'publish')\ .filter(Media.publish_on <= datetime.now())\ .filter(Media.status.excludes('trash'))\ .order_by(Media.views.desc()) media = media_query.first() return self._jsonify(media)
def save_status(self, id, status, ids=None, **kwargs): """Approve or delete a comment or comments. :param id: A :attr:`~mediacore.model.comments.Comment.id` if we are acting on a single comment, or ``"bulk"`` if we should refer to ``ids``. :type id: ``int`` or ``"bulk"`` :param ids: An optional string of IDs separated by commas. :type ids: ``unicode`` or ``None`` :param status: ``"approve"`` or ``"trash"`` depending on what action the user requests. :rtype: JSON dict :returns: success bool ids A list of :attr:`~mediacore.model.comments.Comment.id` that have changed. """ if id == 'bulk': ids = ids.split(',') else: ids = [id] approve = status == 'approve' comments = DBSession.query(Comment)\ .filter(Comment.id.in_(ids))\ .all() for comment in comments: if approve: comment.status.discard('unreviewed') comment.status.add('publish') else: comment.status.add('trash') DBSession.add(comment) if request.is_xhr: return dict(success=True, ids=ids) else: redirect(action='index')
def tags(self, slug=None, page=1, **kwargs): if slug: tag = fetch_row(Tag, slug=slug) media_query = self._published_media_query\ .filter(Media.tags.contains(tag))\ .options(orm.undefer('comment_count_published')) media = media_query tags = None else: tag = None media = [] tags = DBSession.query(Tag)\ .options(orm.undefer('published_media_count'))\ .having(sql.text('published_media_count >= 1'))\ .order_by(Tag.name)\ .all() return dict( media = media, tag = tag, tags = tags, )
class ImportVideosForm(ListForm): template = 'admin/box-form.html' id = 'settings-form' css_class = 'form' submit_text = None fields = [ ListFieldSet( 'youtube', suppress_label=True, legend='', css_classes=['details_fieldset'], children=[ TextArea( 'channel_names', attrs=dict(rows=3, cols=20), label_text=_('Channel Name(s)'), help_text= _('One or more channel names (separated by commas) to import. Please enter only the channel/user name, not the full URL. Please be aware that it may take several minutes for the import to complete. When all videos have been imported, you will be returned to the Media page to manage your new videos.' ), validator=NotEmpty), CheckBox( 'auto_publish', label_text=_('Publish Videos'), help_text= _('When this is selected, videos are published automatically when they are imported. Otherwise the videos will be added, but will be waiting for review before being published.' )), CategoryCheckBoxList('categories', label_text=_('Categories'), options=lambda: DBSession.query( Category.id, Category.name).all()), TextArea('tags', label_text=_('Tags'), attrs=dict(rows=3, cols=15), help_text=_(u'e.g.: puppies, great dane, adorable')), SubmitButton('save', default=_('Import'), css_classes=['btn', 'btn-save', 'blue', 'f-rgt']), ]) ]
def view(self, slug, page=1, **kwargs): """View a podcast and the media that belongs to it. :param slug: A :attr:`~mediacore.model.podcasts.Podcast.slug` :param page: Page number, defaults to 1. :type page: int :rtype: dict :returns: podcast A :class:`~mediacore.model.podcasts.Podcast` instance. episodes A list of :class:`~mediacore.model.media.Media` instances that belong to the ``podcast``. podcasts A list of all the other podcasts """ podcast = fetch_row(Podcast, slug=slug) episodes = self._filter(podcast.media).order_by(Media.publish_on.desc()) podcasts = DBSession.query(Podcast).options(orm.undefer("published_media_count")).all() return dict(podcast=podcast, episodes=episodes, podcasts=podcasts)
def enabled_engines(): from mediacore.model import DBSession engines = DBSession.query(StorageEngine)\ .filter(StorageEngine.enabled == True)\ .all() return list(sort_engines(engines))
def __before__(self, *args, **kwargs): """Load all our settings before each request.""" BaseController.__before__(self, *args, **kwargs) from mediacore.model import Setting tmpl_context.settings = dict(DBSession.query(Setting.key, Setting))
def setup_app(command, conf, vars): """Called by ``paster setup-app``. This script is responsible for: * Creating the initial database schema and loading default data. * Executing any migrations necessary to bring an existing database up-to-date. Your data should be safe but, as always, be sure to make backups before using this. * Re-creating the default database for every run of the test suite. XXX: All your data will be lost IF you run the test suite with a config file named 'test.ini'. Make sure you have this configured to a different database than in your usual deployment.ini or development.ini file because all database tables are dropped a and recreated every time this script runs. XXX: If you are upgrading from MediaCore v0.7.2 or v0.8.0, run whichever one of these that applies: ``python batch-scripts/upgrade/upgrade_from_v072.py deployment.ini`` ``python batch-scripts/upgrade/upgrade_from_v080.py deployment.ini`` XXX: For search to work, we depend on a number of MySQL triggers which copy the data from our InnoDB tables to a MyISAM table for its fulltext indexing capability. Triggers can only be installed with a mysql superuser like root, so you must run the setup_triggers.sql script yourself. """ config = load_environment(conf.global_conf, conf.local_conf) plugin_manager = config['pylons.app_globals'].plugin_mgr mediacore_migrator = MediaCoreMigrator.from_config(conf, log=log) engine = metadata.bind db_connection = engine.connect() # simplistic check to see if MediaCore tables are present, just check for # the media_files table and assume that all other tables are there as well from mediacore.model.media import media_files mediacore_tables_exist = engine.dialect.has_table(db_connection, media_files.name) run_migrations = True if not mediacore_tables_exist: head_revision = mediacore_migrator.head_revision() log.info('Initializing new database with version %r' % head_revision) metadata.create_all(bind=DBSession.bind, checkfirst=True) mediacore_migrator.init_db(revision=head_revision) run_migrations = False add_default_data() for migrator in plugin_manager.migrators(): migrator.init_db() events.Environment.database_initialized() elif not mediacore_migrator.migrate_table_exists(): log.error('No migration table found, probably your MediaCore install ' 'is too old (< 0.9?). Please upgrade to MediaCore CE 0.9 first.') raise AssertionError('no migration table found') elif not mediacore_migrator.alembic_table_exists(): alembic_revision = mediacore_migrator.map_migrate_version() mediacore_migrator.stamp(alembic_revision) if run_migrations: mediacore_migrator.migrate_db() for migrator in plugin_manager.migrators(): migrator.migrate_db() events.Environment.database_migrated() cleanup_players_table(enabled=True) # Save everything, along with the dummy data if applicable DBSession.commit() events.Environment.database_ready() log.info('Generating appearance.css from your current settings') settings = DBSession.query(Setting.key, Setting.value) generate_appearance_css(settings, cache_dir=conf['cache_dir']) log.info('Successfully setup')
def add_new_media_file(media, file=None, url=None): """Create a MediaFile instance from the given file or URL. This function MAY modify the given media object. :type media: :class:`~mediacore.model.media.Media` instance :param media: The media object that this file or URL will belong to. :type file: :class:`cgi.FieldStorage` or None :param file: A freshly uploaded file object. :type url: unicode or None :param url: A remote URL string. :rtype: :class:`~mediacore.model.media.MediaFile` :returns: A newly created media file instance. :raises StorageError: If the input file or URL cannot be stored with any of the registered storage engines. """ from mediacore.model import DBSession, MediaFile engines = DBSession.query(StorageEngine)\ .filter(StorageEngine.enabled == True)\ .all() sorted_engines = list(sort_engines(engines)) for engine in sorted_engines: try: meta = engine.parse(file=file, url=url) log.debug('Engine %r returned meta %r', engine, meta) break except UnsuitableEngineError: log.debug('Engine %r unsuitable for %r/%r', engine, file, url) continue else: raise StorageError(_('Unusable file or URL provided.'), None, None) mf = MediaFile() mf.storage = engine mf.media = media mf.type = meta['type'] mf.display_name = meta.get('display_name', default_display_name(file, url)) mf.unique_id = meta.get('unique_id', None) mf.container = meta.get('container', None) mf.size = meta.get('size', None) mf.bitrate = meta.get('bitrate', None) mf.width = meta.get('width', None) mf.height = meta.get('height', None) media.files.append(mf) DBSession.flush() unique_id = engine.store(media_file=mf, file=file, url=url, meta=meta) if unique_id: mf.unique_id = unique_id elif not mf.unique_id: raise StorageError('Engine %r returned no unique ID.', engine) if not media.duration and meta.get('duration', 0): media.duration = meta['duration'] if not media.description and meta.get('description'): media.description = clean_xhtml(meta['description']) if not media.title: media.title = meta.get('title', None) or mf.display_name if media.type is None: media.type = mf.type if ('thumbnail_url' in meta or 'thumbnail_file' in meta) \ and (not has_thumbs(media) or has_default_thumbs(media)): thumb_file = meta.get('thumbnail_file', None) if thumb_file is not None: thumb_filename = thumb_file.filename else: thumb_url = meta['thumbnail_url'] thumb_filename = os.path.basename(thumb_url) # Download the image to a buffer and wrap it as a file-like object try: temp_img = urlopen(thumb_url) thumb_file = StringIO(temp_img.read()) temp_img.close() except URLError, e: log.exception(e) if thumb_file is not None: create_thumbs_for(media, thumb_file, thumb_filename) thumb_file.close()
def fetch_settings(): from mediacore.model import DBSession, Setting settings_dict = dict(DBSession.query(Setting.key, Setting.value)) return settings_dict
def fetch_settings(): from mediacore.model import DBSession, Setting settings_dict = dict(DBSession.query(Setting.key, Setting.value)) return settings_dict
def editor_group(self): return DBSession.query(Group).filter( Group.group_name == u'editors').one()
def permissions(self): db_permissions = DBSession.query(Permission).all() return tuple( [permission.permission_name for permission in db_permissions])
def __before__(self, *args, **kwargs): """Load all our settings before each request.""" BaseController.__before__(self, *args, **kwargs) from mediacore.model import Setting tmpl_context.settings = dict(DBSession.query(Setting.key, Setting))
def editor_group(self): return DBSession.query(Group).filter(Group.group_name == u'editors').one()
def enabled_engines(): from mediacore.model import DBSession engines = DBSession.query(StorageEngine)\ .filter(StorageEngine.enabled == True)\ .all() return list(sort_engines(engines))
def perm(self): system = MediaCorePermissionSystem(self.pylons_config) system.policies = [self.policy] user = DBSession.query(User).filter(User.user_name == u'admin').one() return UserPermissions(user, system)
def setup_app(command, conf, vars): """Called by ``paster setup-app``. This script is responsible for: * Creating the initial database schema and loading default data. * Executing any migrations necessary to bring an existing database up-to-date. Your data should be safe but, as always, be sure to make backups before using this. * Re-creating the default database for every run of the test suite. XXX: All your data will be lost IF you run the test suite with a config file named 'test.ini'. Make sure you have this configured to a different database than in your usual deployment.ini or development.ini file because all database tables are dropped a and recreated every time this script runs. XXX: If you are upgrading from MediaCore v0.7.2 or v0.8.0, run whichever one of these that applies: ``python batch-scripts/upgrade/upgrade_from_v072.py deployment.ini`` ``python batch-scripts/upgrade/upgrade_from_v080.py deployment.ini`` XXX: For search to work, we depend on a number of MySQL triggers which copy the data from our InnoDB tables to a MyISAM table for its fulltext indexing capability. Triggers can only be installed with a mysql superuser like root, so you must run the setup_triggers.sql script yourself. """ if pylons.test.pylonsapp: # NOTE: This extra filename check may be unnecessary, the example it is # from did not check for pylons.test.pylonsapp. Leaving it in for now # to make it harder for someone to accidentally delete their database. filename = os.path.split(conf.filename)[-1] if filename == 'test.ini': log.info('Dropping existing tables...') metadata.drop_all(checkfirst=True) drop_version_control(conf.local_conf['sqlalchemy.url'], migrate_repository) else: # Don't reload the app if it was loaded under the testing environment config = load_environment(conf.global_conf, conf.local_conf) # Create the migrate_version table if it doesn't exist. # If the table doesn't exist, we assume the schema was just setup # by this script and therefore must be the latest version. latest_version = version(migrate_repository) try: version_control(conf.local_conf['sqlalchemy.url'], migrate_repository, version=latest_version) except DatabaseAlreadyControlledError: log.info('Running any new migrations, if there are any') upgrade(conf.local_conf['sqlalchemy.url'], migrate_repository, version=latest_version) else: log.info('Initializing new database with version %r' % latest_version) metadata.create_all(bind=DBSession.bind, checkfirst=True) add_default_data() cleanup_players_table(enabled=True) # Save everything, along with the dummy data if applicable DBSession.commit() log.info('Generating appearance.css from your current settings') settings = DBSession.query(Setting.key, Setting.value) generate_appearance_css(settings, cache_dir=conf['cache_dir']) log.info('Successfully setup')
class UserForm(ListForm): template = 'admin/box-form.html' id = 'user-form' css_class = 'form' submit_text = None show_children_errors = True _name = 'user-form' # TODO: Figure out why this is required?? fields = [ TextField('display_name', label_text=N_('Display Name'), validator=TextField.validator(not_empty=True), maxlength=255), TextField('email_address', label_text=N_('Email Address'), validator=email_validator(not_empty=True), maxlength=255), ListFieldSet( 'login_details', suppress_label=True, legend=N_('Login Details:'), css_classes=['details_fieldset'], validator=Schema(chained_validators=[ FieldsMatch('password', 'confirm_password', messages={ 'invalidNoMatch': N_("Passwords do not match"), }) ]), children=[ SingleSelectField( 'group', label_text=N_('Group'), options=lambda: DBSession.query(Group.group_id, Group. display_name).all()), TextField('user_name', label_text=N_('Username'), maxlength=16, validator=All(PlainText(), UniqueUsername(not_empty=True))), PasswordField('password', label_text=N_('Password'), validators=NotEmpty, maxlength=80, attrs={'autocomplete': 'off'}), PasswordField('confirm_password', label_text=N_('Confirm password'), validators=NotEmpty, maxlength=80, attrs={'autocomplete': 'off'}), ]), SubmitButton('save', default=N_('Save'), named_button=True, css_classes=['btn', 'btn-save', 'blue', 'f-rgt']), SubmitButton('delete', default=N_('Delete'), named_button=True, css_classes=['btn', 'btn-delete']), ] def post_init(self, *args, **kwargs): events.Admin.UserForm(self)