def velruse_login_complete_view(context, request): provider = context.provider_name profile = context.profile username = profile['accounts'][0]['username'] root = root_factory(request) adapter = request.registry.queryMultiAdapter( (root, request), IUserLocator) if adapter is None: adapter = DefaultUserLocator(root, request) user = adapter.get_user_by_login(username) if user is None: registry = request.registry principals = find_service(root, 'principals') user = principals.add_user(username, registry=registry) performer = registry.content.create('Performer') root['performers'][username] = performer performer.title = profile['displayName'] addresses = profile.get('addresses') if addresses: user.email = performer.email = addresses[0]['formatted'] photos = profile.get('photos') if photos: performer.photo_url = photos[0]['value'] performer.age = colander.null performer.sex = user.favorite_genre = None performer.user = user set_acl(performer, [(Allow, user.__oid__, ['yss.edit-profile'])]) location = request.resource_url(performer, 'edit.html') else: location = request.resource_url(root['performers'][username]) headers = remember(request, get_oid(user)) return HTTPFound(location, headers=headers)
def finish_retime(self): request = self.request file_stream = self.request.params['data'].file song = self.context # XXX do this as methods of the song song.retiming = True song.retiming_blob = Blob() with song.retiming_blob.open("w") as saveto: shutil.copyfileobj(file_stream, saveto) redis = get_redis(self.request) redisval = f'{self.context.__oid__}|{time.time()}' redis.rpush("yss.new-retimings", redisval) event = ObjectModified(song) self.request.registry.subscribers((event, song), None) set_acl(song, [ (Allow, request.user.__oid__, ['yss.edit']), (Deny, Everyone, ['yss.indexed']), ] ) self.request.session.flash( 'This is gonna take a while. It\'s not magic. But after the ' 'retiming is done processing, listen and watch to see that your ' 'spoken lyrics line up with the song, and hit accept if ' 'you are happy with the result. Remember: it\'s just karaoke.', 'info') return self.request.resource_url(self.context, '@@retime')
def persona_login(context, request): check_csrf_token(request) email = verify_persona_assertion(request) root = root_factory(request) adapter = request.registry.queryMultiAdapter( (root, request), IUserLocator) if adapter is None: adapter = DefaultUserLocator(root, request) user = adapter.get_user_by_email(email) if user is None: registry = request.registry username = '******' % email principals = find_service(root, 'principals') user = principals.add_user(username, registry=registry) user.email = email performer = registry.content.create('Performer') root['performers'][username] = performer performer.user = user set_acl(performer, [(Allow, user.__oid__, ['yss.edit-profile'])]) location = request.resource_url(performer, 'edit.html') performer.title = email performer.email = email performer.photo_url = persona_gravatar_photo(request, email) performer.age = colander.null performer.sex = user.favorite_genre = None location = request.resource_url(performer, 'edit.html') else: location = request.resource_url(root['performers'][user.__name__]) headers = remember(request, get_oid(user)) request.response.headers.extend(headers) return {'redirect': location, 'success': True}
def change_acl_callback(content, workflow, transition, request): new_acl = [] current_acl = get_acl(content, []) admins = find_service(content, 'principals')['groups']['admins'] recording = content performer = getattr(recording, 'performer', None) if performer is None: return # eyeroll, foil workflow initialization via subscriber user = performer.user owner_id = user.__oid__ admins_id = admins.__oid__ for ace in current_acl: # preserve all permissions defined by other subsystems (like "like") if ace == DENY_ALL: continue _, _, perms = ace if perms is ALL_PERMISSIONS: continue if not is_nonstr_iter(perms): perms = [perms] if 'view' in perms or 'yss.indexed' in perms or 'yss.edit' in perms: continue new_acl.append(ace) PRIVATE_ACES = [ (Allow, admins_id, ALL_PERMISSIONS), (Allow, owner_id, ('view',)), (Allow, owner_id, ('yss.edit',)), DENY_ALL, ] if transition: # if not initial state if transition['name'].startswith('Make public'): new_acl.extend([ (Allow, Everyone, ('view',)), (Allow, Everyone, ('yss.indexed',)), (Allow, owner_id, ('yss.edit',)), ]) if transition['name'].startswith('Make private'): new_acl.extend(PRIVATE_ACES) if transition['name'].startswith('Make authenticated-only'): new_acl.extend([ (Allow, admins_id, ALL_PERMISSIONS), (Allow, 'system.Authenticated', ('view',)), (Allow, 'system.Authenticated', ('yss.indexed',)), (Allow, owner_id, ('yss.edit',)), DENY_ALL, ]) else: # initial state new_acl.extend(PRIVATE_ACES) set_acl(content, new_acl)
def after_create(self, inst, registry): request = get_current_request() if request is None: return user = request.user acl = getattr(self, '__acl__', []) acl.append( (Allow, get_oid(user), ('sdi.view', 'sdi.edit-properties', 'sdi.add-content', 'sdi.manage-contents'))) set_acl(inst, acl, registry=registry)
def root_added(event): registry = event.registry root = event.object acl = list(root.__acl__) acl.extend( [ (Allow, Everyone, 'view'), (Allow, Everyone, 'yss.indexed'), (Allow, Authenticated, 'yss.like'), ] ) set_acl(root, acl) root.title = root.sdi_title = 'You Should Sing' root.max_framerate = 30 root['catalogs'].add_catalog('yss') root['songs'] = registry.content.create('Songs') set_acl(root['songs'], [ (Allow, Authenticated, 'yss.upload'), (Allow, Authenticated, 'yss.record'), ]) performers = root['performers'] = registry.content.create('Performers') blameme = registry.content.create('Performer') performers['blameme'] = blameme blameme['recordings'] = registry.content.create('Recordings') blameme['photo'] = registry.content.create('File') blameme['photo_thumbnail'] = registry.content.create('File') blameme.user = root['principals']['users']['admin'] timings_json = pkg_resources.resource_string( 'yss', 'blackbird.json').decode('utf-8') song = registry.content.create( 'Song', 'Blackbird', 'The Beatles', timings=timings_json, lyrics=timings_json, audio_stream=pkg_resources.resource_stream('yss', 'blackbird.opus') ) root['songs']['blackbird'] = song song.mimetype = 'audio/opus' song.uploader = blameme
def accept_retime(self): song = self.context song.timings = song.alt_timings song.alt_timings = '' new_acl = [] acl = get_acl(song) for ace in acl: if ace[0] == Deny and ace[2] == ['yss.indexed']: continue new_acl.append(ace) set_acl(song, new_acl) event = ObjectModified(song) self.request.registry.subscribers((event, song), None) self.request.session.flash( 'Retime accepted, song will show up in searches, and may now be ' 'recorded by everyone. Nice work.', 'info') return self.request.resource_url(self.context, '@@retime')
def set_acms_for_app_root(event): """Set/update :term:`acm`s for the root object of the pyramid application. :param event: this function should be used as a subscriber for the :class:`pyramid.interfaces.IApplicationCreated` event. That way everytime the application starts the root `acm` is updated. The `root_acm` (:func:`root_acm_asset`) is extended by the :term:`acm` returned by the :class:`adhocracy_core.authorization.IRootACMExtension` adapter. In addition all permissions are granted the god user. """ root, closer = get_root(event.app) acl = [god_all_permission_ace] acl += _get_root_extension_acl(root, event.app.registry) acl += _get_root_base_acl() old_acl = get_acl(root, []) if old_acl == acl: return set_acl(root, acl, event.app.registry) transaction.commit() closer()
def _add_acl_to_app_root(context, registry): acl = acm_to_acl(root_acm, registry) set_acl(context, acl, registry=registry) set_god_all_permissions(context, registry)
def create_profile(context, request): schema = CreatePerformerSchema().bind(request=request, context=context) form = deform.Form(schema, buttons=('Save',)) rendered = None if 'Save' in request.POST: controls = request.POST.items() try: appstruct = form.validate(controls) except deform.ValidationFailure as e: rendered = e.render() else: registry = request.registry principals = find_service(context, 'principals') root = find_root(context) username = appstruct['username'] userid = request.session.get('userid', username) # socmed signups user = principals.add_user(userid, registry=registry) performer = registry.content.create('Performer') root['performers'][username] = performer performer['recordings'] = registry.content.create('Recordings') performer['invitations'] = registry.content.create('Invitations') performer['invitations'].add_more(10) phdata = appstruct['photo'] fp = phdata.get('fp') if fp is not None: for photoname, photosize in ( ('photo', (320, 320)), ('photo_thumbnail', (40, 40)), ): photo = registry.content.create('File') alsoProvides(photo, IPerformerPhoto) # for view lookup performer[photoname] = photo fp.seek(0) pil_image = PIL.Image.open(fp) if pil_image.size[0] != photosize[0]: # width pil_image.thumbnail(photosize, PIL.Image.ANTIALIAS) buffer = io.BytesIO() pil_image.save(buffer, 'png') buffer.seek(0) photo.upload(buffer) photo.mimetype = 'image/png' # NB: performer.user required before setting tzname and email performer.user = user performer.title = appstruct['title'] performer.email = appstruct['email'] performer.birthdate = appstruct['birthdate'] performer.sex = appstruct['sex'] performer.genre = appstruct['genre'] performer.tzname = appstruct['tzname'] performer.location = appstruct['location'] ctindex = find_index(context, 'system', 'content_type') nameindex = find_index(context, 'system', 'name') q = ctindex.eq('Invitation') & nameindex.eq( appstruct['invite_code'].upper()) results = list(q.execute()) if results: invitation = results[0] invitation.redeemer = performer invitation.redemption_date = datetime.datetime.utcnow( ).replace(tzinfo=pytz.UTC) set_acl(performer, [(Allow, user.__oid__, ['yss.edit'])]) headers = remember(request, get_oid(user)) request.session.flash('Your account is created. Welcome!', 'info') return HTTPFound(request.resource_url(performer), headers=headers) else: appstruct = { 'csrf_token': request.session.get_csrf_token(), 'username': request.session.get('profilename', ''), 'title': request.session.get('realname', ''), 'email': '', 'photo':colander.null, 'birthdate': colander.null, 'sex': colander.null, 'genre': colander.null, 'tzname': colander.null, 'location':colander.null, } if rendered is None: rendered = form.render(appstruct, readonly=False) return { 'form':rendered, }
def main(argv=sys.argv): def usage(msg): print (msg) sys.exit(2) description = "Import a set of video files into the songs folder" parser = optparse.OptionParser( "usage: %prog config_uri input_filenames", description=description ) parser.add_option( '-d', '--dir', dest='directory', help='Use this directory as working directory instead of a tempdir' ) parser.add_option( '-o', '--overwrite', dest='overwrite', help='Overwrite songs in the songs folder instead of skipping dupes', action='store_true', ) parser.add_option( '-a', '--av-only', dest='av_only', help='Overwrite audio/video of songs only in songs folder (not metadata)', action='store_true', ) opts, args = parser.parse_args(argv[1:]) overwrite = opts.overwrite av_only = opts.av_only try: config_uri = args[0] except KeyError: usage('Requires a config_uri as an argument') outdir = opts.directory or tempfile.mkdtemp() setup_logging(config_uri) env = bootstrap(config_uri) root = env['root'] registry = env['registry'] songs = root['songs'] restricted = songs.get('restricted') if restricted is None: restricted = registry.content.create('Folder') songs['restricted'] = restricted set_acl( restricted, [(Allow, 'system.Authenticated', ['view']), (Allow, 'system.Authenticated', ['yss.indexed']), (Deny, 'system.Everyone', ['view']), (Deny, 'system.Everyone', ['yss.indexed'])] ) try: for input_filename in args[1:]: logging.info(input_filename) md5 = hashlib.md5() f = open(input_filename, 'rb') while True: data = f.read(1<<19) if not data: break md5.update(data) hexdigest = md5.hexdigest() command = [ 'ffmpeg', '-i', input_filename, '-f', 'ffmetadata', 'pipe:1', ] print (' '.join([ shlex.quote(s) for s in command ])) proc = subprocess.Popen( command, universal_newlines=True, stdout=subprocess.PIPE, ) stdout, _ = proc.communicate() md = {} for line in stdout.split('\n'): if '=' in line: k, v = line.strip().split('=', 1) md[k.lower()] = v[1:-1] name = slug.slug(md['title']) title=md['title'] artist=md['artist'] name = '%s-%s' % (name, hexdigest) if name in restricted and not (overwrite or av_only): logging.info('Not overwriting %s' % name) continue stream = open(input_filename, 'rb') if name in restricted and av_only: logger.info('replacing video for %s' % title) song = restricted[name] song.upload(stream) song.mimetype = 'video/webm' else: try: del restricted[name] except KeyError: pass song = registry.content.create( 'Song', title=title, artist=artist, lyrics='', timings='', stream=stream, mimetype='video/webm', ) restricted[name] = song blameme = root['performers']['blameme'] song.uploader = blameme event = ObjectModified(song) registry.subscribers((event, song), None) print ('done %s, %s, %s' % (name, title, artist)) transaction.commit() songs._p_jar.sync() finally: if not opts.directory: shutil.rmtree(outdir, ignore_errors=True)
def load(self, context): if context.exists(self.fn): acl = context.load_yaml(self.fn) set_acl(context.resource, acl)
def upload(self): context = self.context request = self.request schema = SongUploadSchema().bind(request=request, context=context) form = deform.Form(schema, buttons=('Save',)) rendered = None if 'Save' in request.POST: controls = request.POST.items() try: appstruct = form.validate(controls) except deform.ValidationFailure as e: rendered = e.render() else: audio_file = appstruct['audio_file'] tmpdir = request.registry.settings['substanced.uploads_tempdir'] job = uuid.uuid4().hex jobdir = os.path.join(tmpdir, job) try: try: os.makedirs(jobdir) except FileExistsError: pass inputfn = os.path.join(jobdir, 'inputfile') inputfile = open(inputfn, 'wb') fp = audio_file['fp'] fp.seek(0) shutil.copyfileobj(fp, inputfile) M = 1024 * 1024 * 1024 md5 = hashlib.md5() f = open(inputfn, 'rb') while True: data = f.read(M) if not data: break md5.update(data) opus_filename = os.path.join(jobdir, 'output.opus') ffmpeg.input(inputfn).output( opus_filename, ar=48000).run() song = request.registry.content.create( 'Song', appstruct['title'], appstruct['artist'], appstruct['lyrics'], timings='', audio_stream=open(opus_filename, 'rb'), audio_mimetype='audio/opus', language=appstruct['language'], ) finally: shutil.rmtree(jobdir, ignore_errors=True) request.session.flash( 'Song uploaded. Now voice lyrics like William Shatner in ' 'rhythm with the song in order to time the karaoke ' 'display text.', 'info') song.language = appstruct['language'] song.genre = appstruct['genre'] song.year = appstruct['year'] songname = slug.slug(appstruct['title']) hashval = md5.hexdigest() songname = f'{songname}-{hashval}' if songname in self.context: request.session.flash('this song has already been uploaded') raise HTTPFound(request.resource_url(self.context)) self.context[songname] = song song.uploader = request.performer # NB must be after seating set_acl(song, [ (Allow, request.user.__oid__, ['yss.edit']), (Deny, Everyone, ['yss.indexed']), ] ) event = ObjectModified(song) self.request.registry.subscribers((event, song), None) return HTTPFound(request.resource_url(song, '@@retime')) else: appstruct = { 'title':colander.null, 'artist':colander.null, 'audio_file':colander.null, 'genre':colander.null, 'language':colander.null, 'lyrics':colander.null, 'year':colander.null, } if rendered is None: rendered = form.render(appstruct, readonly=False) return {'form':rendered, 'page_title':'Upload Song'}