def list_artists(self): web_user = WebUser.current_web_user(self.request) _party_id = web_user.party.id return { 'solo_artists': Artist.search_solo_artists_by_party(_party_id), 'group_artists': Artist.search_group_artists_by_party(_party_id) }
def current_artists_select_widget(node, kw): request = kw.get('request') web_user = WebUser.current_web_user(request) artists = Artist.search_by_party(web_user.party.id) artist_options = [(artist.id, artist.name) for artist in artists] widget = deform.widget.Select2Widget(values=artist_options) return widget
def whoami(self): """ View returning the authenticated user's credentials. """ login = self.request.unauthenticated_userid principals = WebUser.current_roles(self.request) return {"login": login, "principals": principals}
def verify_email(self): # sanity checks opt_in_uuid = False if self.request.subpath: opt_in_uuid = self.request.subpath[-1] # new email activation web_user = WebUser.search_by_opt_in_uuid(str(opt_in_uuid)) if web_user: if web_user.new_email: web_user.email = web_user.new_email web_user.new_email = '' web_user.save() self.request.session.flash( _(u"Your email verification was successful. " u"Now login with your new email address!"), 'main-alert-success' ) log.info("email activation successful: %s" % web_user.email) return self.redirect( FrontendResource ) else: self.request.session.flash( _( u"Your email verification was not successful " u"(no validation code)." ), 'main-alert-danger' ) return self.redirect()
def list_creations(self): web_user = WebUser.current_web_user(self.request) _creations = sorted( Creation.search_by_party(web_user.party.id), key=lambda creation: creation.artist.name ) return {'creations': _creations}
def validate_unique_user_email(node, values, **kwargs): # multifield validator """Check for valid email and prevent duplicate usernames.""" request = node.bindings["request"] email_value = values["email"] current_web_user = WebUser.current_web_user(request) if email_value != current_web_user.email: # email has been changed: check if it conflicts with other webuser found_conflicting_web_user = WebUser.search_by_email(email_value) if found_conflicting_web_user: raise colander.Invalid(node, _(u"Email address already taken")) # finally, check email format if len(email_value) > 7: if re.match('^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+' + # noqa: W605 '(\.[a-z0-9-]+)*(\.[a-z]{2,4})$', email_value) is not None: return raise colander.Invalid(node, "Invalid email address")
def objects_view(self): web_users_all = WebUser.search_all() _clients = Client.search_all() _utilisations = CreationUtilisationIMP.search_all() _artists = Artist.search_all() return { 'web_users': web_users_all, 'clients': _clients, 'artists': _artists, 'utilisations': _utilisations, }
def test_030_validate_user_registration(self): """ validate user registration succeeds and logs user in """ webuser = WebUser.search_by_email('*****@*****.**') self.assertEqual(webuser.opt_in_state, "mail-sent") self.url("verify_email/" + webuser.opt_in_uuid) self.screenshot() self.assertTrue( self.cli.find_elements_by_class_name('cs-backend') )
def validate_unique_user_email(node, values, **kwargs): # multifield validator """Check for valid email and prevent duplicate usernames.""" request = node.bindings["request"] email_value = values["email"] current_web_user = WebUser.current_web_user(request) if email_value != current_web_user.email: # email has been changed: check if it conflicts with other webuser found_conflicting_web_user = WebUser.search_by_email(email_value) if found_conflicting_web_user: raise colander.Invalid(node, _(u"Email address already taken")) # finally, check email format if len(email_value) > 7: if re.match( '^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+' + # noqa: W605 '(\.[a-z0-9-]+)*(\.[a-z]{2,4})$', email_value) is not None: return raise colander.Invalid(node, "Invalid email address")
def current_orphans(cls, request, category='all'): """ Searches orphan content in category of current web user. Args: request (pyramid.request.Request): Current request. category (str): optional - Category of content. Returns: list (content): List of content. None: If no match is found. """ party = WebUser.current_web_user(request).party return cls.search_orphans(party.id, category)
def create_artist(self): email = self.request.unauthenticated_userid party = WebUser.current_party(self.request) _artist = { 'party': party, 'group': False, 'name': self.appstruct['artist']['name'], 'description': self.appstruct['artist']['description'] or '' } if self.appstruct['artist']['picture']: picture_data = self.appstruct['artist']['picture']['fp'].read() mimetype = self.appstruct['artist']['picture']['mimetype'] _artist['picture_data'] = picture_data _artist['picture_data_mime_type'] = mimetype artists = Artist.create([_artist]) if not artists: log.info("artist add failed for %s: %s" % (email, _artist)) self.request.session.flash( _(u"Artist could not be added: ") + _artist['name'], 'main-alert-danger' ) self.redirect(ArtistResource, 'list') return artist = artists[0] if self.appstruct['bank_account']['type']: _bank_account_number = { 'bic': self.appstruct['bank_account']['bic'], 'type': self.appstruct['bank_account']['type'], } if self.appstruct['bank_account']['type'] == 'iban': number = self.appstruct['bank_account']['number'] _bank_account_number['number'] = number bank_account_number = BankAccountNumber.create( artist.party, [_bank_account_number] )[0] artist.bank_account_number = bank_account_number artist.save() log.info("artist add successful for %s: %s" % (email, artist)) self.request.session.flash( _(u"Artist added: ") + artist.name + " (" + artist.code + ")", 'main-alert-success' ) self.redirect(ArtistResource, 'list')
def ban(request): request.session['abuse_rank']['banned'] = True request.session['abuse_rank']['bantime'] = time.time() web_user = WebUser.current_web_user(request) if not web_user.abuse_rank: web_user.abuse_rank = 0 web_user.abuse_rank += 1 web_user.save() log.info( ( "banned upload for user %s (db abuse rank: %s)\n" ) % ( web_user, web_user.abuse_rank ) )
def create_client(self): uuid = self.appstruct['uuid'] email = self.appstruct['email'] if Client.search_by_uuid(uuid, active=False): self.request.session.flash( _('Client already exists: ') + uuid, 'main-alert-warning' ) self.redirect( ClientResource, 'list', headers=remember(self.request, email) ) return _client = { 'web_user': WebUser.search_by_email(email), 'uuid': uuid, 'player_name': 'Clementine', 'player_version': '1.2', 'plugin_name': 'Clementine IMP Prototyp', 'plugin_version': '0.5', 'plugin_vendor': 'C3S', 'active': True } clients = Client.create([_client]) if not clients: log.info("client add failed for %s: %s" % (email, _client)) self.request.session.flash( _(u"Client could not be added: ") + uuid, 'main-alert-danger' ) self.redirect( ClientResource, 'list', headers=remember(self.request, email) ) return client = clients[0] log.info("client add successful for %s: %s" % (email, client.uuid)) self.request.session.flash( _(u"Client added: ") + client.uuid, 'main-alert-success' ) self.redirect( ClientResource, 'list', headers=remember(self.request, email) )
def current_rejects(cls, request, reason, category='all'): """ Searches rejected content (optionally in category) of current web user. Args: request (pyramid.request.Request): Current request. reason (str): Reason for rejected content. category (str): optional - Category of content. Returns: list (content): List of content. None: If no match is found. """ party = WebUser.current_web_user(request).party return cls.search_rejects(party.id, reason, category)
def verify_email(self): # sanity checks opt_in_uuid = False if self.request.subpath: opt_in_uuid = self.request.subpath[-1] # change opt in state if opt_in_uuid: web_user = WebUser.search_by_opt_in_uuid(str(opt_in_uuid)) if web_user: if web_user.opt_in_state != 'opted-in': web_user.opt_in_state = 'opted-in' else: # already opted in? then this is a new email activation if web_user.new_email: web_user.email = web_user.new_email web_user.new_email = '' web_user.save() self.request.session.flash( _(u"Your email verification was successful."), 'main-alert-success' ) log.info("web_user login successful: %s" % web_user.email) return self.redirect( BackendResource, '', headers=remember(self.request, web_user.email) ) else: self.request.session.flash( _( u"Your email verification was not successful " u"(wrong validation code)." ), 'main-alert-danger' ) else: self.request.session.flash( _( u"Your email verification was not successful " u"(no validation code)." ), 'main-alert-danger' ) return self.redirect()
def change_profile(self): web_user = self.request.web_user web_user.party.firstname = self.appstruct['firstname'] # save separate web_user.party.lastname = self.appstruct['lastname'] # for clarity web_user.party.name = (web_user.party.firstname + ' ' + web_user.party.lastname) # self.appstruct['name'] TODO: generate name using a tryton trigger if self.appstruct['email'] != web_user.email: web_user.new_email = self.appstruct['email'] # email verification! web_user.save() template_variables = { 'link': self.request.resource_url( self.request.root, 'verify_email', WebUser.get_opt_in_uuid_by_id(web_user.id) ) } send_mail( self.request, template="new_email_verification", variables=template_variables, recipients=[web_user.new_email] ) web_user.party.save() if self.appstruct['email'] == web_user.email: log.info( "edit profile add successful for %s" % (web_user.party.name)) self.request.session.flash( _(u"Profile changed for: ${name}", mapping={'name': web_user.party.name}), 'main-alert-success' ) else: log.info( "edit profile add successful for %s, activation email sent." % (web_user.party.name)) self.request.session.flash( _(u"Profile changed for: ${name}" " -- activation email for new email address sent." " Please check your (new) email inbox.", mapping={'name': web_user.party.name}), 'main-alert-success' ) self.redirect()
def controller(self): self.form = edit_profile_form(self.request) if self.submitted(): # submit validated data from form if self.validate(): self.change_profile() else: # initialize form web_user = WebUser.current_web_user(self.request) self.appstruct = { 'name': web_user.party.name or "", 'firstname': web_user.party.firstname or "", 'lastname': web_user.party.lastname or "", 'email': web_user['email'] or "" } self.render(self.appstruct) return self.response
def search_by_web_user(cls, web_user_id): """ Searches a content by web user id. Args: web_user_id (int): Id of the user. Returns: list (content): List of content. """ if web_user_id is None: return None web_user = WebUser.search_by_id(web_user_id) if web_user is None: return None result = cls.get().search([ ('active', '=', True), ('entity_creator', '=', web_user.party.id) ]) return result
def change_profile(self): web_user = self.request.web_user web_user.party.firstname = self.appstruct['firstname'] # save separate web_user.party.lastname = self.appstruct['lastname'] # for clarity web_user.party.name = (web_user.party.firstname + ' ' + web_user.party.lastname) # self.appstruct['name'] TODO: generate name using a tryton trigger if self.appstruct['email'] != web_user.email: web_user.new_email = self.appstruct['email'] # email verification! web_user.save() template_variables = { 'link': self.request.resource_url( self.request.root, 'verify_email', WebUser.get_opt_in_uuid_by_id(web_user.id)) } send_mail(self.request, template="new_email_verification", variables=template_variables, recipients=[web_user.new_email]) web_user.party.save() if self.appstruct['email'] == web_user.email: log.info("edit profile add successful for %s" % (web_user.party.name)) self.request.session.flash( _(u"Profile changed for: ${name}", mapping={'name': web_user.party.name}), 'main-alert-success') else: log.info( "edit profile add successful for %s, activation email sent." % (web_user.party.name)) self.request.session.flash( _( u"Profile changed for: ${name}" " -- activation email for new email address sent." " Please check your (new) email inbox.", mapping={'name': web_user.party.name}), 'main-alert-success') self.redirect()
def pocket_widget(request): heading = _(u'Pocket') web_user = WebUser.current_web_user(request) pocket_balance = web_user.party.pocket_balance pocket_budget = web_user.party.pocket_budget log.debug( ( "pocket_balance: %s\n" ) % ( pocket_balance ) ) body = render( '../../templates/widgets/pocket.pt', { 'pocket_balance': pocket_balance, 'pocket_budget': pocket_budget }, request=request ) return {'heading': heading, 'body': body}
def is_banned(request): if 'abuse_rank' not in request.session: request.session['abuse_rank'] = { 'current': 0, 'banned': False, 'bantime': None } banned = request.session['abuse_rank']['banned'] if not banned: return False currenttime = time.time() bantime = int(request.session['abuse_rank']['bantime']) removeban = int(request.registry.settings['abuse_rank.removeban']) if currenttime > bantime + removeban: request.session['abuse_rank']['banned'] = False request.session['abuse_rank']['current'] = 0 web_user = WebUser.current_web_user(request) log.debug( ( "removed upload ban for user %s (db abuse rank: %s)\n" ) % ( web_user, web_user.abuse_rank ) ) return request.session['abuse_rank']['banned']
def musician_list(self): web_user = WebUser.current_web_user(self.request) utilisations = CreationUtilisationIMP.search_by_musician( web_user.party.id ) return {'utilisations': utilisations}
def list_clients(self): web_user = WebUser.current_web_user(self.request) return { 'player_names': Client.get_player_names_by_web_user(web_user.id), 'clients': Client.search_by_web_user(web_user.id) }
def is_registered(self, web_user): if WebUser.search_by_email(web_user['email']): return True return False
def passes_authentication(self, web_user): if WebUser.authenticate(web_user['email'], web_user['password']): return True return False
def create_artist(self): email = self.request.unauthenticated_userid party = WebUser.current_party(self.request) # generate vlist _artist = { 'group': self.appstruct['group'], 'party': party, 'entity_creator': party, 'entity_origin': 'direct', 'claim_state': 'claimed', 'name': self.appstruct['name'], 'description': self.appstruct['description'] or '', } # picture if self.appstruct['picture']: with open(self.appstruct['picture']['fp'].name, mode='rb') as picfile: picture_data = picfile.read() mimetype = self.appstruct['picture']['mimetype'] _artist['picture_data'] = picture_data _artist['picture_data_mime_type'] = mimetype # members if self.appstruct['group']: members_add = [] members_create = [] for member in self.appstruct['members']: # add existing artists if member['mode'] == "add": member_artist = Artist.search_by_oid(member['oid']) # sanity checks if not member_artist: continue if member_artist.group: continue # append artist id members_add.append(member_artist.id) # create new artists if member['mode'] == "create": # create new party member_party = Party.create([{ 'name': member['name'], 'contact_mechanisms': [( 'create', [{ 'type': 'email', 'value': member['email'] }] )] }]) member_party = member_party[0] # append member data members_create.append({ 'group': False, 'description': "", 'party': member_party.id, 'entity_creator': party.id, 'entity_origin': 'indirect', 'claim_state': 'unclaimed', 'name': member['name'] }) # append actions _artist['solo_artists'] = [] if members_create: _artist['solo_artists'].append(('create', members_create)) if members_add: _artist['solo_artists'].append(('add', members_add)) # create artist artists = Artist.create([_artist]) # user feedback if not artists: log.info("artist add failed for %s: %s" % (email, _artist)) self.request.session.flash( _(u"Artist could not be added: ${arna}", mapping={'arna': _artist['name']}), 'main-alert-danger' ) self.redirect() return artist = artists[0] log.info("artist add successful for %s: %s" % (email, artist)) self.request.session.flash( _(u"Artist added: ${arna} (${arco})", mapping={'arna': artist.name, 'arco': artist.code}), 'main-alert-success' ) # redirect self.redirect(artist.code)
def register(self): _create = False _web_user = { 'email': self.data['email'], 'password': self.data['password'], 'roles': [('add', [WebUserRole.search_by_code('licenser').id])] } _c3smembership = self.context.registry['services']['c3smembership'] template_variables = {} # user is already registered if self.is_registered(_web_user): # user passes authentication (accidently registered to login) if self.passes_authentication(_web_user): opt_in_state = WebUser.get_opt_in_state_by_email( _web_user['email'] ) if opt_in_state == 'opted-in': self.request.session.flash( _(u"You are already registered with your " u"credentials."), 'main-alert-info') self.login() return else: self.request.session.flash( _(u"Your email address is not verified yet. Please " u"follow the instructions in our email."), 'main-alert-info') return # user fails authentication (email already registered) else: template_name = "registration-fail_registered" # user is not registered yet else: # user claims to be a c3s member if self.is_claiming_membership(self.data): # TODO: Change back, when membership is integrated # # user is a c3s member # if self.is_member(_c3smembership, _web_user): # _create = True # template_name = "registration-member_success" # # user is not a c3s member # else: # template_name = "registration-member_fail_nomatch" _create = True template_name = "registration-member_success" # user claims not to be a c3s member else: # TODO: Change back, when membership is integrated # # user is a c3s member # if self.is_member(_c3smembership, _web_user): # template_name = "registration-nonmember_fail_reserved" # # user is not a c3s member # else: # _create = True # template_name = "registration-nonmember_success" _create = True template_name = "registration-nonmember_success" # create if _create: web_users = WebUser.create([_web_user]) # creation failed if not web_users or len(web_users) is not 1: log.info("web_user creation not successful: %s" % _web_user) self.request.session.flash( _( u"There was an error during the registration process. " u"Please try again later and contact us, if this " u"error occurs again. Sorry for the inconveniece." ), 'main-alert-danger' ) return False # creation successful web_user = web_users[0] if self.is_member(_c3smembership, _web_user): # c3s membership web_user.party.member_c3s = True response = _c3smembership.generate_member_token( service='repertoire', email=web_user.email ) if not response or 'token' not in response: log.debug( "web_user c3s membership token error: %s, %s" % ( _web_user, response ) ) web_user.party.member_c3s_token = response['token'] web_user.party.save() else: # save values of non-c3s-member form fields web_user.party.repertoire_terms_accepted = self.data[ 'terms_accepted'] web_user.party.name = self.data['firstname'] + ' ' + self.data[ 'lastname'] # also save separately for clarity web_user.party.firstname = self.data['firstname'] web_user.party.lastname = self.data['lastname'] web_user.party.birthdate = self.data['birthdate'] web_user.party.save() template_variables = { 'link': self.request.resource_url( self.request.root, 'verify_email', WebUser.get_opt_in_uuid_by_id(web_user.id) ) } log.info("web_user creation successful: %s" % web_user.email) # flash message self.request.session.flash( _( u"Thank you for your registration. We are now processing your " u"request and will send you an email with further " u"instructions." ), 'main-alert-success' ) # send mail send_mail( self.request, template=template_name, variables=template_variables, recipients=[_web_user['email']] ) if _create: web_user.opt_in_state = "mail-sent" web_user.save() # reset form self.redirect(FrontendResource)
def post_repertoire_upload(request): # create paths create_paths(request) # upload files files = [] for name, fieldStorage in request.POST.items(): # check fieldStorage if not isinstance(fieldStorage, FieldStorage): continue # configure upload rank = (request.registry.settings['abuse_rank.active'] == 'true') rank_max = int(request.registry.settings['abuse_rank.max']) hostname = get_hostname() descriptor = fieldStorage.file filename = os.path.basename(fieldStorage.filename).encode('utf-8') filename_hash = _hash_algorithm(filename).hexdigest() temporary_path = get_path(request, _path_temporary, filename_hash) contentrange = ContentRange.parse( request.headers.get('Content-Range', None) ) contentlength = request.headers.get('Content-Length', None) # create checksum with benchmark(request, name='checksum', uid=filename, normalize=descriptor, scale=100*1024*1024): checksum = create_checksum( descriptor=descriptor, algorithm=_checksum_algorithm ) save_checksum( path=temporary_path + _checksum_postfix, algorithm=_checksum_algorithm.__name__, checksum=checksum.hexdigest(), contentrange=contentrange or (0, contentlength, contentlength) ) # abuse rank if rank: if is_banned(request): # TODO: number wont be replaced, also see # BirthdateField line 300+ in register_webuser.py files.append({ 'name': fieldStorage.filename, 'error': _( u"Abuse detected. Wait for {number}" u" seconds before trying another" u" upload.", mapping={'number': int(still_banned_for(request))} )}) continue if is_collision(contentrange, checksum): raise_abuse_rank(request) current_rank = request.session['abuse_rank']['current'] if current_rank == rank_max: ban(request) # save to filesystem (-> temporary) ok, complete = save_upload_to_fs( descriptor=descriptor, absolute_path=temporary_path, contentrange=contentrange ) if not ok: pass if not complete: # client feedback files.append({ 'name': fieldStorage.filename, 'size': os.path.getsize(temporary_path) }) continue # get content uuid content_uuid = get_content_uuid() # get uuid paths uploaded_path = get_path(request, _path_uploaded, content_uuid) rejected_path = get_path(request, _path_rejected, content_uuid) file_category = get_category_from_mimetype(temporary_path) file_size = os.path.getsize(temporary_path) mime_type = str(mime.from_file(temporary_path)) # validate file error = validate_upload(filename, temporary_path) if error: # move files (temporary -> rejected) ok = move_files_with_prefixes( source=temporary_path, target=rejected_path ) if not ok: panic( request, reason="Files could not be moved.", identifiers=[filename_hash, content_uuid] ) # save file to database _content = { 'uuid': content_uuid, 'processing_hostname': hostname, 'processing_state': "rejected", 'rejection_reason': "format_error", 'entity_origin': "direct", 'entity_creator': WebUser.current_web_user(request).party, 'name': str(name), 'category': file_category, 'mime_type': mime_type, 'size': file_size, 'path': rejected_path } content = save_upload_to_db(_content) if not content: panic( request, reason="Content could not be created.", identifiers=[filename_hash, content_uuid] ) # save checksums to database # admin feedback # 2DO: Mail log.info( ( "Content rejected (format error): %s\n" ) % ( rejected_path ) ) # client feedback files.append({ 'name': fieldStorage.filename, 'error': error }) continue # we used to create a preview, now done in repertoire processing # this is only for displaying some file properties # audio = AudioSegment.from_file(temporary_path) file_category = get_category_from_mimetype(temporary_path) # move files (temporary -> uploaded) ok = move_files_with_prefixes( source=temporary_path, target=uploaded_path ) if not ok: panic( request, reason="Files could not be moved.", identifiers=[filename_hash, content_uuid] ) # save file to database _content = { 'uuid': content_uuid, 'processing_hostname': hostname, 'processing_state': "uploaded", 'entity_origin': "direct", 'entity_creator': WebUser.current_web_user(request).party, 'name': str(filename), 'category': file_category, 'mime_type': str(mime.from_file(uploaded_path)), 'size': os.path.getsize(uploaded_path), 'path': uploaded_path, # 'length': "%.6f" % audio.duration_seconds, # 'channels': int(audio.channels), # 'sample_rate': int(audio.frame_rate), # 'sample_width': int(audio.sample_width * 8) } content = save_upload_to_db(_content) if not content: panic( request, reason="Content could not be created.", identifiers=[filename_hash, content_uuid] ) # save checksums to database save_checksums_to_db( content=content, path=uploaded_path + _checksum_postfix ) # client feedback files.append(get_content_info(request, content)) # finally, see if there are old temporary files in the temp folder # structure cleanup_temp_directory(request) # TODO: add timestamp file in temp folder to track if cleanup run # was already started this day return {'files': files}