def create_new_user(username, config): from mediadrop.model import DBSession, User, fetch_row, Group user = User.by_user_name(username) if user is None: try: print "MIDDLEWARE" print config l = ldap.initialize(config['ldap_url']) l.simple_bind_s(config['ldap_binddn'], config['ldap_pw']) filter = '(samaccountname=%s)' % username r = l.search_s(config['ldap_base'],ldap.SCOPE_SUBTREE, filter, ['displayname', 'mail']) l.unbind_s() user_attrs = {} for dn, entry in r: for attr, v in entry.iteritems(): user_attrs[attr] = v[0] except ldap.LDAPError: l.unbind_s() new_user = fetch_row(User, "new") new_user.display_name = user_attrs['displayName'] new_user.email_address = user_attrs['mail'] new_user.user_name = username query = DBSession.query(Group).filter(Group.group_name.in_(['authenticated'])) new_user.groups = list(query.all()) DBSession.add(new_user) DBSession.commit()
def inject_in_db(cls, enable_player=False): from mediadrop.model import DBSession from mediadrop.model.players import players as players_table, PlayerPrefs prefs = PlayerPrefs() prefs.name = cls.name prefs.enabled = enable_player # MySQL does not allow referencing the same table in a subquery # (i.e. insert, max): http://stackoverflow.com/a/14302701/138526 # Therefore we need to alias the table in max current_max_query = sql.select([sql.func.max(players_table.alias().c.priority)]) # sql.func.coalesce == "set default value if func.max does " # In case there are no players in the database the current max is NULL. With # coalesce we can set a default value. new_priority_query = sql.func.coalesce( current_max_query.as_scalar()+1, 1 ) prefs.priority = new_priority_query prefs.created_on = datetime.now() prefs.modified_on = datetime.now() prefs.data = cls.default_data DBSession.add(prefs) DBSession.commit()
def _update_settings(self, values): """Modify the settings associated with the given dictionary.""" for name, value in values.iteritems(): if name in tmpl_context.settings: setting = tmpl_context.settings[name] else: setting = Setting(key=name, value=value) if value is None: value = u'' else: value = unicode(value) if setting.value != value: setting.value = value DBSession.add(setting) DBSession.flush() # Clear the settings cache unless there are multiple processes. # We have no way of notifying the other processes that they need # to clear their caches too, so we've just gotta let it play out # until all the caches expire. if not request.environ.get('wsgi.multiprocess', False): app_globals.settings_cache.clear() else: # uWSGI provides an automagically included module # that we can use to call a graceful restart of all # the uwsgi processes. # http://projects.unbit.it/uwsgi/wiki/uWSGIReload try: import uwsgi uwsgi.reload() except ImportError: pass
def main(parser, options, args): app_globs = app_globals._current_obj() app_id = app_globals.settings['facebook_appid'] if not app_id: print 'No Facebook app_id configured, exiting' sys.exit(3) app_secret = options.app_secret fb = FacebookAPI(app_id, app_secret) from mediadrop.model import DBSession, Media # eager loading of 'meta' to speed up later check. all_media = Media.query.options(joinedload('_meta')).all() print 'Checking all media for existing Facebook comments' progress = ProgressBar(maxval=len(all_media)).start() for i, media in enumerate(all_media): progress.update(i+1) if 'facebook-comment-xid' not in media.meta: continue if not fb.has_xid_comments(media): continue media.meta[u'facebook-comment-xid'] = unicode(media.id) DBSession.add(media) DBSession.commit() progress.finish()
def add_external_file(self, media, url=u"http://site.example/videos.mp4"): previous_files = len(media.files) media_file = add_new_media_file(media, url=url) # add_new_media_file will set media_file.media AND media.files.append # so we have two files for the media until the session is refreshed. DBSession.refresh(media) assert_length(previous_files + 1, media.files) return media_file
def add_external_file(self, media, url=u'http://site.example/videos.mp4'): previous_files = len(media.files) media_file = add_new_media_file(media, url=url) # add_new_media_file will set media_file.media AND media.files.append # so we have two files for the media until the session is refreshed. DBSession.refresh(media) assert_length(previous_files + 1, media.files) return media_file
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))
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?? event = events.Admin.MediaForm 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( request.settings.get('wording_display_administrative_notes', '' ))], default=lambda: request.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 _create_user_without_groups(self): user = User() user.user_name = u"joe" user.email_address = u"*****@*****.**" user.display_name = u"Joe" user.groups = [] DBSession.add(user) DBSession.flush() return user
def _create_user_without_groups(self): user = User() user.user_name = u'joe' user.email_address = u'*****@*****.**' user.display_name = u'Joe' user.groups = [] DBSession.add(user) DBSession.flush() return user
def view(self, slug, podcast_slug=None, **kwargs): """Display the media player, info and comments. :param slug: The :attr:`~mediadrop.models.media.Media.slug` to lookup :param podcast_slug: The :attr:`~mediadrop.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:`~mediadrop.model.media.Media` instance for display. related_media A list of :class:`~mediadrop.model.media.Media` instances that rank as topically related to the given media item. comments A list of :class:`~mediadrop.model.comments.Comment` instances associated with the selected media item. 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:`~mediadrop.model.media.Media` instance. """ media = fetch_row(Media, slug=slug) request.perm.assert_permission(u'view', media.resource) 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) try: media.increment_views() DBSession.commit() except OperationalError: DBSession.rollback() if request.settings['comments_engine'] == 'facebook': response.facebook = Facebook(request.settings['facebook_appid']) related_media = viewable_media(Media.query.related(media))[:6] # TODO: finish implementation of different 'likes' buttons # e.g. the default one, plus a setting to use facebook. return dict( media=media, related_media=related_media, comments=media.comments.published().all(), comment_form_action=url_for(action='comment'), comment_form_values=kwargs, )
def view(self, slug, podcast_slug=None, **kwargs): """Display the media player, info and comments. :param slug: The :attr:`~mediadrop.models.media.Media.slug` to lookup :param podcast_slug: The :attr:`~mediadrop.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:`~mediadrop.model.media.Media` instance for display. related_media A list of :class:`~mediadrop.model.media.Media` instances that rank as topically related to the given media item. comments A list of :class:`~mediadrop.model.comments.Comment` instances associated with the selected media item. 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:`~mediadrop.model.media.Media` instance. """ media = fetch_row(Media, slug=slug) request.perm.assert_permission(u'view', media.resource) 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) try: media.increment_views() DBSession.commit() except OperationalError: DBSession.rollback() if request.settings['comments_engine'] == 'facebook': response.facebook = Facebook(request.settings['facebook_appid']) related_media = viewable_media(Media.query.related(media))[:6] # TODO: finish implementation of different 'likes' buttons # e.g. the default one, plus a setting to use facebook. return dict( media = media, related_media = related_media, comments = media.comments.published().all(), comment_form_action = url_for(action='comment'), comment_form_values = kwargs, )
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 = MediaDropPermissionSystem.permissions_for_user(admin, config) assert_true(perm.contains_permission(u'admin')) assert_false(perm.contains_permission(u'edit')) return admin
def delete(self, id, **kwargs): """Delete a StorageEngine. :param id: Storage ID. :type id: ``int`` :returns: Redirect back to :meth:`index` after successful delete. """ engine = fetch_row(StorageEngine, id) files = engine.files for f in files: engine.delete(f.unique_id) DBSession.delete(engine) redirect(action='index', id=None)
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_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, **kwargs): """List storage engines with pagination. :rtype: Dict :returns: engines The list of :class:`~mediadrop.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 save(self, id, **kwargs): player = fetch_row(PlayerPrefs, id) form = player.settings_form if id == 'new': DBSession.add(player) @validate(form, error_handler=self.edit) def save(id, **kwargs): # Allow the form to modify the player directly # since each can have radically different fields. save_func = getattr(form, 'save_data') save_func(player, **tmpl_context.form_values) redirect(controller='/admin/players', action='index') return save(id, **kwargs)
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)
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 delete(self, id, **kwargs): """Delete a PlayerPref. After deleting the PlayerPref, cleans up the players table, ensuring that each Player class is represented--if the deleted PlayerPref is the last example of that Player class, creates a new disabled PlayerPref for that Player class with the default settings. :param id: Player ID. :type id: ``int`` :returns: Redirect back to :meth:`index` after successful delete. """ player = fetch_row(PlayerPrefs, id) DBSession.delete(player) DBSession.flush() cleanup_players_table() redirect(action='index', id=None)
def _to_python(self, value, state): id = request.environ["pylons.routes_dict"]["id"] query = DBSession.query(Group).filter_by(group_name=value) if id != "new": query = query.filter(Group.group_id != id) if query.count() != 0: raise Invalid(_("Group name already exists"), value, state) return value
def save(self, id, engine_type=None, **kwargs): if id == 'new': assert engine_type is not None, 'engine_type must be specified when saving a new StorageEngine.' engine = self.fetch_engine(id, engine_type) form = engine.settings_form if id == 'new': DBSession.add(engine) @validate(form, error_handler=self.edit) def save_engine_params(id, general, **kwargs): # Allow the form to modify the StorageEngine directly # since each can have radically different fields. save_func = getattr(form, 'save_engine_params') save_func(engine, **tmpl_context.form_values) redirect(controller='/admin/storage', action='index') return save_engine_params(id, **kwargs)
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.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(Group).filter_by(group_name=value) if id != 'new': query = query.filter(Group.group_id != id) if query.count() != 0: raise Invalid(_('Group name already exists'), value, state) return value
def inject_in_db(cls, enable_player=False): from mediadrop.model import DBSession from mediadrop.model.players import players as players_table, PlayerPrefs prefs = PlayerPrefs() prefs.name = cls.name prefs.enabled = enable_player # didn't get direct SQL expression to work with SQLAlchemy # player_table = sql.func.max(player_table.c.priority) query = sql.select([sql.func.max(players_table.c.priority)]) max_priority = DBSession.execute(query).first()[0] if max_priority is None: max_priority = -1 prefs.priority = max_priority + 1 prefs.created_on = datetime.now() prefs.modified_on = datetime.now() prefs.data = cls.default_data DBSession.add(prefs) DBSession.commit()
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 mediadrop.model import DBSession, Media media = DBSession.query(Media) for m in media: m.update_status()
def save_media_obj(self, name, email, title, description, tags, uploaded_file, url): # create our media object as a status-less placeholder initially media_obj = Media() media_obj.author = Author(name, email) media_obj.title = title media_obj.slug = get_available_slug(Media, title) media_obj.description = description if request.settings['wording_display_administrative_notes']: media_obj.notes = request.settings['wording_administrative_notes'] media_obj.set_tags(tags) # Give the Media object an ID. DBSession.add(media_obj) DBSession.flush() # Create a MediaFile object, add it to the media_obj, and store the file permanently. media_file = add_new_media_file(media_obj, file=uploaded_file, url=url) # The thumbs may have been created already by add_new_media_file if not has_thumbs(media_obj): create_default_thumbs_for(media_obj) media_obj.update_status() DBSession.flush() return media_obj
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)
class fields(WidgetsList): podcast_include = SingleSelectField( 'podcast', label_text=N_('Include in the Podcast'), css_classes=['dropdown-select'], options=lambda: [(None, None)] + DBSession.query( Podcast.id, Podcast.title).all()) title = TextField(validator=validators['title'], label_text=N_('Title:'), maxlength=255) description = XHTMLTextArea(validator=validators['description'], label_text=N_('Description:'), attrs=dict(rows=5, cols=25)) file = FileField(validator=FieldStorageUploadConverter( if_missing=None, messages={'empty': N_('Oops! You forgot to enter a file.')})) submit = SubmitButton(default=N_('Submit'), css_classes=['mcore-btn', 'btn-submit'])
def map_migrate_version(self): migrate_version_query = migrate_table.select( migrate_table.c.repository_id == u'MediaCore Migrations' ) result = DBSession.execute(migrate_version_query).fetchone() db_migrate_version = result.version if db_migrate_version in migrate_to_alembic_mapping: return migrate_to_alembic_mapping[db_migrate_version] earliest_upgradable_version = sorted(migrate_to_alembic_mapping)[0] if db_migrate_version < earliest_upgradable_version: error_msg = ('Upgrading from such an old version of MediaDrop is not ' 'supported. Your database is at version %d but upgrades are only ' 'supported from MediaCore CE 0.9.0 (DB version %d). Please upgrade ' '0.9.0 first.') self.log.error(error_msg % (db_migrate_version, earliest_upgradable_version)) else: self.log.error('Unknown DB version %s. Can not upgrade to alembic' % db_migrate_version) raise AssertionError('unsupported DB migration version.')
def test_add_file_url(self): slug = u'test-add-file-url' title = u'Test Adding File by URL on Media Edit Page.' try: media = self._new_publishable_media(slug, title) media.publishable = False media.reviewed = False DBSession.add(media) DBSession.commit() media_id = media.id except SQLAlchemyError, e: DBSession.rollback() raise e
def submit(self, **kwargs): """ """ kwargs.setdefault('name') name = request.perm.user.display_name email_X = request.perm.user.email_address podcasts = DBSession.query(Podcast.id).filter(Podcast.author_name == name)\ .filter(Podcast.id == kwargs['podcast'])\ .all() if not podcasts: redirect(action='failure') # Save the media_obj! media_obj = self.save_media_obj(name, email_X, kwargs['title'], kwargs['description'], None, kwargs['file'], kwargs['podcast']) email.send_media_notification(media_obj) # Redirect to success page! redirect(action='success')
def index(self, **kwargs): """Display the upload form. :rtype: Dict :returns: legal_wording XHTML legal wording for rendering support_email An help contact address upload_form The :class:`~mediadrop.forms.uploader.UploadForm` instance form_values ``dict`` form values, if any """ name = request.perm.user.display_name support_emails = request.settings['email_support_requests'] support_emails = email.parse_email_string(support_emails) support_email = support_emails and support_emails[0] or None aux = DBSession.query( Podcast.id, Podcast.title).filter(Podcast.author_name == name) if 'podcast_include' in kwargs: aux = aux.filter(Podcast.id == kwargs['podcast_include']).all() else: aux = aux.all() s = SingleSelectField('podcast', label_text=N_('Include in the Podcast'), css_classes=['dropdown-select'], options=lambda: aux) upload_form.children._widget_lst[0] = s return dict( legal_wording=request.settings['wording_user_uploads'], support_email=support_email, upload_form=upload_form, form_values=kwargs, )
def test_edit_media(self): title = u'Edit Existing Media Test' slug = u'edit-existing-media-test' # this should be unique # Values that we will change during the edit process name = u'Frederick Awesomeson' email = u'*****@*****.**' description = u'This media item was created to test the "admin/media/edit/someID" method' htmlized_description = '<p>This media item was created to test the "admin/media/edit/someID" method</p>' notes = u'Some Notes!' try: media = self._new_publishable_media(slug, title) media.publishable = False media.reviewed = False DBSession.add(media) DBSession.commit() media_id = media.id except SQLAlchemyError, e: DBSession.rollback() raise e
def final_view(self, id, **kwargs): print('hello') try: csrf = kwargs['environ']['paste.cookies'][0]['csrftoken'].value # .filter(Views_Counter.csrftoken==csrf)\ temp = Views_Counter.query.filter(Views_Counter.media_id==id)\ .filter(Views_Counter.validated==False) print(csrf) if temp: temp = temp.one() media = fetch_row(Media, id=id) try: media.increment_views3() media.increment_views() DBSession.commit() except OperationalError: DBSession.rollback() return dict(success=False) temp.validated = True DBSession.flush() except: return dict(success=False) return dict(success=True)
def permissions(self): db_permissions = DBSession.query(Permission).all() return tuple([permission.permission_name for permission in db_permissions])
def comment(self, slug, name='', email=None, body='', **kwargs): """Post a comment from :class:`~mediadrop.forms.comments.PostCommentForm`. :param slug: The media :attr:`~mediadrop.model.media.Media.slug` :returns: Redirect to :meth:`view` page for media. """ def result(success, message=None, comment=None): if request.is_xhr: result = dict(success=success, message=message) if comment: result['comment'] = render('comments/_list.html', {'comment_to_render': comment}, method='xhtml') return result elif success: return redirect(action='view') else: return self.view(slug, name=name, email=email, body=body, **kwargs) if request.settings['comments_engine'] != 'builtin': abort(404) akismet_key = request.settings['akismet_key'] if akismet_key: akismet = Akismet(agent=USER_AGENT) akismet.key = akismet_key akismet.blog_url = request.settings['akismet_url'] or \ url_for('/', qualified=True) akismet.verify_key() data = {'comment_author': name.encode('utf-8'), 'user_ip': request.environ.get('REMOTE_ADDR'), 'user_agent': request.environ.get('HTTP_USER_AGENT', ''), 'referrer': request.environ.get('HTTP_REFERER', 'unknown'), 'HTTP_ACCEPT': request.environ.get('HTTP_ACCEPT')} if akismet.comment_check(body.encode('utf-8'), data): return result(False, _(u'Your comment has been rejected.')) media = fetch_row(Media, slug=slug) request.perm.assert_permission(u'view', media.resource) c = Comment() name = filter_vulgarity(name) c.author = AuthorWithIP(name, email, request.environ['REMOTE_ADDR']) c.subject = 'Re: %s' % media.title c.body = filter_vulgarity(body) require_review = request.settings['req_comment_approval'] if not require_review: c.reviewed = True c.publishable = True media.comments.append(c) DBSession.flush() send_comment_notification(media, c) if require_review: message = _('Thank you for your comment! We will post it just as ' 'soon as a moderator approves it.') return result(True, message=message) else: return result(True, comment=c)
def fetch_settings(): from mediadrop.model import DBSession, Setting settings_dict = dict(DBSession.query(Setting.key, Setting.value)) return settings_dict
def add_default_data(): log.info('Adding default data') settings = [ (u'email_media_uploaded', None), (u'email_comment_posted', None), (u'email_support_requests', None), (u'email_send_from', u'noreply@localhost'), (u'wording_user_uploads', N_(u"Upload your media using the form below. We'll review it and get back to you.")), (u'wording_administrative_notes', None), (u'wording_display_administrative_notes', u''), (u'popularity_decay_exponent', u'4'), (u'popularity_decay_lifetime', u'36'), (u'rich_text_editor', u'tinymce'), (u'google_analytics_uacct', u''), (u'featured_category', u'1'), (u'max_upload_size', u'314572800'), (u'ftp_storage', u'false'), (u'ftp_server', u'ftp.someserver.com'), (u'ftp_user', u'username'), (u'ftp_password', u'password'), (u'ftp_upload_directory', u'media'), (u'ftp_download_url', u'http://www.someserver.com/web/accessible/media/'), (u'ftp_upload_integrity_retries', u'10'), (u'akismet_key', u''), (u'akismet_url', u''), (u'req_comment_approval', u''), (u'use_embed_thumbnails', u'true'), (u'api_secret_key_required', u'true'), (u'api_secret_key', random_string(20)), (u'api_media_max_results', u'50'), (u'api_tree_max_depth', u'10'), (u'general_site_name', u'MediaDrop'), (u'general_site_title_display_order', u'prepend'), (u'sitemaps_display', u'True'), (u'rss_display', u'True'), (u'vulgarity_filtered_words', u''), (u'primary_language', u'en'), (u'advertising_banner_html', u''), (u'advertising_sidebar_html', u''), (u'comments_engine', u'builtin'), (u'facebook_appid', u''), (u'youtube_apikey', u''), ] settings.extend(appearance_settings) for key, value in settings: s = Setting() s.key = key s.value = value DBSession.add(s) admin_user = User() admin_user.user_name = u'admin' admin_user.display_name = u'Admin' admin_user.email_address = u'*****@*****.**' admin_user.password = u'admin' DBSession.add(admin_user) admin_group = Group(name=u'admins', display_name=u'Admins') admin_group.users.append(admin_user) DBSession.add(admin_group) editor_group = Group(name=u'editors', display_name=u'Editors') DBSession.add(editor_group) anonymous_group = Group(name=u'anonymous', display_name=u'Everyone (including guests)') DBSession.add(anonymous_group) authenticated_group = Group(name=u'authenticated', display_name=u'Logged in users') DBSession.add(authenticated_group) admin_perm = Permission(name=u'admin', groups=[admin_group], description=u'Grants access to the admin panel') DBSession.add(admin_perm) edit_perm = Permission(name=u'edit', groups=[admin_group, editor_group], description=u'Grants access to edit site content') DBSession.add(edit_perm) view_perm = Permission(name=u'view', groups=[admin_group, anonymous_group, editor_group], description=u'View published media') DBSession.add(view_perm) upload_perm = Permission(name=u'upload', groups=[admin_group, anonymous_group, editor_group], description=u'Can upload new media') DBSession.add(upload_perm) media_upload_perm = Permission() media_upload_perm.permission_name = u'MEDIA_UPLOAD' media_upload_perm.description = u'Grants the ability to upload new media' media_upload_perm.groups.append(admin_group) media_upload_perm.groups.append(editor_group) media_upload_perm.groups.append(anonymous_group) DBSession.add(edit_perm) category = Category(name=u'Featured', slug=u'featured') DBSession.add(category) category2 = Category(name=u'Instructional', slug=u'instructional') DBSession.add(category2) podcast = Podcast() podcast.slug = u'hello-world' podcast.title = u'Hello World' podcast.subtitle = u'My very first podcast!' podcast.description = u"""<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>""" podcast.category = u'Technology' podcast.author = Author(admin_user.display_name, admin_user.email_address) podcast.explicit = None podcast.copyright = u'Copyright 2009 Xyz' podcast.itunes_url = None podcast.feedburner_url = None DBSession.add(podcast) comment = Comment() comment.subject = u'Re: New Media' comment.author = AuthorWithIP(name=u'John Doe', ip=2130706433) comment.body = u'<p>Hello to you too!</p>' DBSession.add(comment) media = Media() media.type = None media.slug = u'new-media' media.reviewed = True media.encoded = False media.publishable = False media.title = u'New Media' media.subtitle = None media.description = u"""<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>""" media.description_plain = u"""Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.""" media.author = Author(admin_user.display_name, admin_user.email_address) media.categories.append(category) media.comments.append(comment) DBSession.add(media) #XXX The list of default players is actually defined in model.players # and should at some point be moved here to avoid inconsistency # between the default storage engines and default players. remote_url_storage = RemoteURLStorage() default_engines = [ SwiftStorage(), LocalFileStorage(), remote_url_storage, YoutubeStorage(), VimeoStorage(), BlipTVStorage(), DailyMotionStorage(), ] for engine in default_engines: DBSession.add(engine) import datetime instructional_media = [ (u'workflow-in-mediadrop', u'Workflow in MediaDrop', u'<p>This sceencast explains the publish status feature in MediaDrop.</p><p>Initially all videos uploaded through the front-end or admin panel are placed under "awaiting review" status. Once the administrator hits the "review complete" button, they can upload media. Videos can be added in any format, however, they can only be published if they are in a web-ready format such as FLV, M4V, MP3, or MP4. Alternatively, if they are published through Youtube or Vimeo the encoding step is skipped</p><p>Once uploaded and encoded the administrator can then publish the video.</p>', u'This sceencast explains the publish status feature in MediaDrop.\nInitially all videos uploaded through the front-end or admin panel are placed under \"awaiting review\" status. Once the administrator hits the \"review complete\" button, they can upload media. Videos can be added in any format, however, they can only be published if they are in a web-ready format such as FLV, M4V, MP3, or MP4. Alternatively, if they are published through Youtube or Vimeo the encoding step is skipped\nOnce uploaded and encoded the administrator can then publish the video.', datetime.datetime(2010, 5, 13, 2, 29, 40), 218, u'http://static.mediadrop.net/files/videos/tutorial-workflow-in-mediadrop.mp4', u'video', u'mp4', ), (u'creating-a-podcast-in-mediadrop', u'Creating a Podcast in MediaDrop', u'<p>This describes the process an administrator goes through in creating a podcast in MediaDrop. An administrator can enter information that will automatically generate the iTunes/RSS feed information. Any episodes published to a podcast will automatically publish to iTunes/RSS.</p>', u'This describes the process an administrator goes through in creating a podcast in MediaDrop. An administrator can enter information that will automatically generate the iTunes/RSS feed information. Any episodes published to a podcast will automatically publish to iTunes/RSS.', datetime.datetime(2010, 5, 13, 2, 33, 44), 100, u'http://static.mediadrop.net/files/videos/tutorial-create-podcast-in-mediadrop.mp4', u'video', u'mp4', ), (u'adding-a-video-in-mediadrop', u'Adding a Video in MediaDrop', u'<p>This screencast shows how video or audio can be added in MediaDrop.</p><p>MediaDrop supports a wide range of formats including (but not limited to): YouTube, Vimeo, Amazon S3, Bits on the Run, BrightCove, Kaltura, and either your own server or someone else\'s.</p><p>Videos can be uploaded in any format, but can only be published in web-ready formats such as FLV, MP3, M4V, MP4 etc.</p>', u'This screencast shows how video or audio can be added in MediaDrop.\nMediaDrop supports a wide range of formats including (but not limited to): YouTube, Vimeo, Amazon S3, Bits on the Run, BrightCove, Kaltura, and either your own server or someone else\'s.\nVideos can be uploaded in any format, but can only be published in web-ready formats such as FLV, MP3, M4V, MP4 etc.', datetime.datetime(2010, 5, 13, 02, 37, 36), 169, u'http://static.mediadrop.net/files/videos/tutorial-add-video-in-mediadrop.mp4', u'video', u'mp4', ), ] name = u'MediaDrop Team' email = u'*****@*****.**' for slug, title, desc, desc_plain, publish_on, duration, url, type_, container in instructional_media: media = Media() media.author = Author(name, email) media.description = desc media.description_plain = desc_plain media.duration = duration media.publish_on = publish_on media.slug = slug media.title = title media.type = type_ media_file = MediaFile() media_file.container = container media_file.created_on = publish_on media_file.display_name = os.path.basename(url) media_file.duration = duration media_file.type = type_ media_file.storage = remote_url_storage media_file.unique_id = url DBSession.add(media) DBSession.add(media_file) media.files.append(media_file) media.categories.append(category2) media.encoded = True media.reviewed = True media.publishable = True
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:`~mediadrop.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:`~mediadrop.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. """ sorted_engines = enabled_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) from mediadrop.model import DBSession, MediaFile 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) mf.tags = "one, two, three" 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) #Read id3 tag and extract the details from there from mediadrop.lib.storage import LocalFileStorage if (isinstance(engine, LocalFileStorage)): mf.id3tags = engine.get_id3_tags(unique_id) mf.extracted_tags = engine.get_id3_user_tags(unique_id) print("ID3 tags: ", mf.id3tags) if (mf.id3tags != None): mf.display_name = mf.id3tags['title'][0] 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 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. """ # paster just scans the source code for a "websetup.py". Due to our # compatibility module for the old "mediacore" namespace it actually finds # two modules (mediadrop.websetup and mediacore.websetup) even though both # actually point to the same source code. # Because of that "paster setup-app" actually runs "setup_app()" twice # which causes some bad stuff to happen (e.g. duplicate metadata # initialization. Until we get rid of the compat package we should make # sure the following code is only run once. global did_run_setup if did_run_setup: return config = load_environment(conf.global_conf, conf.local_conf) plugin_manager = config['pylons.app_globals'].plugin_mgr mediadrop_migrator = MediaDropMigrator.from_config(conf, log=log) engine = metadata.bind db_connection = engine.connect() # simplistic check to see if MediaDrop tables are present, just check for # the media_files table and assume that all other tables are there as well from mediadrop.model.media import media_files mediadrop_tables_exist = engine.dialect.has_table(db_connection, media_files.name) run_migrations = True if not mediadrop_tables_exist: head_revision = mediadrop_migrator.head_revision() log.info('Initializing new database with version %r' % head_revision) metadata.create_all(bind=DBSession.bind, checkfirst=True) mediadrop_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 mediadrop_migrator.alembic_table_exists(): if not mediadrop_migrator.migrate_table_exists(): log.error('No migration table found, probably your MediaDrop install ' 'is too old (< 0.9?). Please upgrade to MediaCore CE 0.9 first.') raise AssertionError('no migration table found') alembic_revision = mediadrop_migrator.map_migrate_version() mediadrop_migrator.stamp(alembic_revision) if run_migrations: mediadrop_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) if settings.count() == 0: error_msg = ( u"Unable to find any settings in the database. This may happen if a previous\n" u"setup did not complete successfully.\n" u"Please inspect your database contents. If you don't have any valuable data in\n" u"that db you can try to remove all tables and run the setup process again.\n" u"BE CAREFUL: REMOVING ALL TABLES MIGHT CAUSE DATA LOSS!\n" ) sys.stderr.write(error_msg) log.error(error_msg.replace('\n', u' ')) sys.exit(99) generate_appearance_css(settings, cache_dir=conf['cache_dir']) did_run_setup = True log.info('Successfully setup')