def get_membership_tree(group, member, iter = 0): if iter > 5: return None member = get_member(member) group = get_group(group) if not (member and group): return None try: return Session.query(GroupMembership).filter( and_( GroupMembership.group_id == group.id, GroupMembership.member_id == member.id ) ).one() except NoResultFound: try: groups = Session.query(GroupMembership).filter( and_( GroupMembership.group_id == group.id, GroupMembership.member_id != member.id, # isinstance(GroupMembership.member, Group) ) ).all() for p_group in groups: p_result = get_membership_tree(p_group.member.id, member.id, iter + 1) if p_result: return p_result return None except NoResultFound: return None
def get_user_and_check_password(username, password): """ Called by account controller and/or AuthKit valid_password to return a user from local db """ try: q = Session.query(User).select_from( join(User, UserLogin, User.login_details)) q = q.filter(User.id == make_username(username)) q = q.filter(User.status == 'active') q = q.filter(UserLogin.type == 'password') q = q.filter(UserLogin.token == encode_plain_text_password(password)) return q.one() except NoResultFound: # AllanC - Added fallback to search for email as some users get confised as to how to identify themselfs # emails are not indexed? performance? using this should be safe as our username policy prohibits '@' and '.' try: q = Session.query(User).select_from( join(User, UserLogin, User.login_details)) q = q.filter(User.email == username) q = q.filter(User.status == 'active') q = q.filter(UserLogin.type == 'password') q = q.filter( UserLogin.token == encode_plain_text_password(password)) return q.one() except NoResultFound: return None
def worker_workout(): print "worker_workout():" print '*** Session ***' print '>>> Session.query(Content).first()' print Session.query(Content).first() print '*** I18n ***' print '>>> _("This is a workout of internationalisation in the worker")' print _("This is a workout of internationalisation in the worker") print '*** Config ***' print '>>> cbutils.worker.config["debug"]' import cbutils.worker print cbutils.worker.config["debug"] print '*** Template ***' print '>>> ?' print '*** URL Generation ***' print '>>> url(controller="misc", action="about", id="civicboom")' print url(controller="misc", action="about", id="civicboom") print url(host='moo', controller="misc", action="about", id="civicboom") print url(protocol='test', host='cake', controller="misc", action="about", id="civicboom") print url(protocol='test', controller="misc", action="about", id="civicboom") print url(sub_domain='subdom', controller="misc", action="about", id="civicboom") return True
def get_media(id=None, hash=None): if id: return Session.query(Media).get(id) if hash: try: return Session.query(Media).filter_by(hash=hash).first() except NoResultFound: return None
def test_delete_content(self): self.assertEqual(self.num_content_public('delete_cascade'), 0) num_content_start = self.num_content_public() # Step 1: Create content self.content_id = self.create_content(type='assignment') # Step 2: Create responses, comments and accept self.log_in_as('unitfriend') #self.accept_assignment(self.content_id) # Accepting should now be done automatically when responding response_1_id = self.create_content(parent_id=self.content_id, title='response 1', content='delete_cascade') response_2_id = self.create_content(parent_id=self.content_id, title='response 2', content='delete_cascade') self.comment(self.content_id, 'delete_cascade comment') self.comment(response_1_id, 'delete_cascade response comment') response = self.app.get(url('content', id=self.content_id, format='json'), status=200) response_json = json.loads(response.body) self.assertEqual(response_json['data']['responses']['count'], 2) self.assertEqual(response_json['data']['comments']['count'], 1) self.assertEqual(response_json['data']['accepted_status']['count'], 1) # Step 3: Delete content content_delete_cascade = get_content(self.content_id) content_delete_cascade.delete() # Step 4: Check deleted response = self.app.get(url('content', id=response_1_id, format='json'), status=200) self.assertIn('delete_cascade response comment', response) response = self.app.get(url('content', id=response_2_id, format='json'), status=200) self.assertEqual( Session.query(Content).filter_by( parent_id=self.content_id).count(), 0) self.assertEqual( Session.query(Tag).filter_by(name=u'delete_cascade').count(), 1 ) #Tag remains at the end, this could be tidyed witha delete orphan cascade self.assertEqual( Session.query(MemberAssignment).filter_by( content_id=self.content_id).count(), 0)
def _to_python(self, value, state): value = unicode(value) from pylons import tmpl_context as c if c.logged_in_persona and c.logged_in_persona.email == value: # If the current user has this email then bypass the validator return value email_count = Session.query(User).filter(User.email == value).count() if self.check_unverifyed_emails: email_count += Session.query(User).filter( User.email_unverified == value).count() if email_count > 0: raise formencode.Invalid( _('This email address is already registered with us. Please use a different address, or retrieve your password using the password recovery link.' ), value, state) return value
def rate_content(content, member, rating): content = get_content(content) member = get_member(member) rating_value = int(rating) if not content: raise action_error(_('unable to find content'), code=404) if not member: raise action_error(_('unable to find member'), code=404) if rating and rating_value < 0 or rating_value > 5: raise action_error(_("Ratings can only be in the range 0 to 5"), code=400) # remove any existing ratings # we need to commit after removal, otherwise SQLAlchemy # will optimise remove->add as modify-existing, and the # SQL trigger will break try: existing = Session.query(Rating).filter( Rating.content == content).filter(Rating.member == member).one() Session.delete(existing) Session.commit() except NoResultFound: pass # rating = 0 = remove vote # add a new one if rating_value > 0: r = Rating() r.content = content r.member = member r.rating = rating_value Session.add(r) Session.commit()
def unfollow(follower, followed, delay_commit=False): followed = get_member(followed) follower = get_member(follower) if not followed: raise action_error(_('unable to find followed'), code=404) if not follower: raise action_error(_('unable to find follower'), code=404) #if followed not in follower.following: # GregM: can unfollow to remove trusted invite if not follower.is_following( followed) and not follower.is_follow_trusted_inviter(followed): raise action_error(_('not currently following'), code=400) #follower.following.remove(followed) follow = Session.query(Follow).filter( Follow.member_id == followed.id).filter( Follow.follower_id == follower.id).one() Session.delete(follow) if not delay_commit: Session.commit() #invalidate_member(follower) #invalidate_member(followed) followed.send_notification( messages.follow_stop(member=follower, you=followed)) return True
def respond_assignment(parent_content, member, delay_commit=False): """ When creating a response, the accepted record should be flagged as responded """ member = get_member(member) parent_content = get_content(parent_content) if not member: raise action_error(_("cant find user"), code=404) if not parent_content: raise action_error(_("cant find parent content"), code=404) if parent_content.__type__ != 'assignment': return # Nothing to do if parent is not assignment try: # upgrade an 'accepted' record to 'responded' member_assignment = Session.query(MemberAssignment).filter_by( member_id=member.id, content_id=parent_content.id).one() member_assignment.status = "responded" except: # otherwise create 'responded' record member_assignment = MemberAssignment() member_assignment.content = parent_content member_assignment.member = member #assignment_accepted.member_id = member.id member_assignment.status = "responded" Session.add(member_assignment) if not delay_commit: Session.commit() #invalidate_accepted_assignment(member) return True
def withdraw_assignemnt(assignment, member, delay_commit=False): member = get_member(member) assignment = get_content(assignment) if not member: raise action_error(_("cant find user"), code=404) if not assignment: raise action_error(_("cant find assignment"), code=404) try: assignment_accepted = Session.query(MemberAssignment).filter_by( member_id=member.id, content_id=assignment.id, status="accepted").one() assignment_accepted.status = "withdrawn" #Session.update(assignment_accepted) Session.commit() #invalidate_accepted_assignment(member) assignment.creator.send_notification( messages.assignment_interest_withdrawn(member=member, assignment=assignment, you=assignment.creator)) return True except: pass return False
def follower_distrust(followed, follower, delay_commit=False): followed = get_member(followed) follower = get_member(follower) if not followed: raise action_error(_('unable to find followed'), code=404) if not follower: raise action_error(_('unable to find follower'), code=404) if not follower.is_following(followed): raise action_error(_('not currently following'), code=400) follow = Session.query(Follow).filter( Follow.member_id == followed.id).filter( Follow.follower_id == follower.id).one() if not follow: raise action_error(_('member is not a follower'), code=404) if follow.type == 'trusted': follow.type = 'normal' elif follow.type == 'trusted_invite': raise action_error(_('follower still has pending invite'), code=400) elif follow.type == 'normal': raise action_error(_('follower was not trusted'), code=400) if not delay_commit: Session.commit() # invalidate_member(follower) # GregM: Needed? # invalidate_member(followed) # GregM: Needed? follower.send_notification( messages.follower_distrusted(member=followed, you=follower)) return True
def associate_janrain_account(user, type, token): """ Associate a login record for a Janrain account This is called at: 1.) Registration 2.) Linking multiple login accounts to a single Civicboom account """ login = None try: login = Session.query(UserLogin).filter(UserLogin.token == token).filter(UserLogin.type == type).one() except: pass if login: if login.user == user: return # If login already belongs to this user then abort if login.user: # Warn existing user that account is being reallocated login.user.send_email(subject=_('login account reallocated'), content_text=_('your %s account has been allocated to the user %s') % (type, user.username)) if not config['development_mode']: janrain('unmap', identifier=login.token, primaryKey=login.member_id) login.user = user else: login = UserLogin() login.user = user login.type = type login.token = token Session.add(login) Session.commit() if not config['development_mode']: janrain('map', identifier=login.token, primaryKey=login.member_id) # Let janrain know this users primary key id, this is needed for agrigation posts
def assignment_previously_accepted_by(assignment, member): try: previously_accepted_query = Session.query(MemberAssignment).filter_by( content_id=assignment.id, member_id=member.id) except: return False if previously_accepted_query.count() > 0: return previously_accepted_query.one().status return False
def get_member_email(member): if not member: return None if isinstance(member, Member): return member assert type(member) in [str, unicode], debug_type(member) try: return Session.query(User).filter_by(email=member).one() except NoResultFound: return None
def has_boomed(content, member): """ Return boom_object or None for - has this member boomed this content """ content = get_content(content) member = get_member(member) try: return Session.query(Boom).filter(Boom.member_id == member.id).filter( Boom.content_id == content.id).one() except: return None
def has_account_without_password(user): user = get_member(user) or get_member_email(user) password_login = None if user: try: password_login = Session.query(UserLogin).filter(UserLogin.user==user).filter(UserLogin.type == 'password').one() except Exception: pass if not password_login: return True return False
def get_content_nocache(content_id): #http://www.sqlalchemy.org/docs/mappers.html#controlling-which-tables-are-queried # could use .with_polymorphic([DraftContent, ArticleContent, AssignmentContent]), will see if this is needed #assert str(content_id).isdigit(), debug_type(content_id) try: result = Session.query(Content).with_polymorphic('*').get(content_id) #Session.query(Content).with_polymorphic('*').filter_by(id=int(content_id)).one() #Session.expunge(result) return result except NoResultFound: return None # used to have NoResultFound but didnt want a 500 error raised, the caller code can detect NONE and just say "not found" neatly
def get_tag(tag): """ Returns a tag object for the string passed to it If it does not appear in the database then return a new tag object If it does exisit in the data then return the database object """ tag = tag.lower() try: return Session.query(Tag).filter_by(name=unicode(tag)).one() except NoResultFound as nrf: t = Tag(unicode(tag)) Session.add(t) return t
def test_flag_member(self): self.sign_up_as('spam_man') self.log_in_as('unittest') num_emails = getNumEmails() response = self.app.post( url('member_action', action='flag', id='spam_man', format='json'), params={ '_authentication_token': self.auth_token, 'type': 'spam', 'comment': 'This member says they are bulgarian royaly and wants my account details. I think not.', }, ) self.assertEqual(getNumEmails(), num_emails + 1) email_response = getLastEmail() self.assertEquals(email_response.email_to, config['email.moderator']) self.assertIn('wants my account details', email_response.content_text) self.assertEquals( Session.query(FlaggedEntity).filter( FlaggedEntity.raising_member_id == 'unittest').filter( FlaggedEntity.offending_member_id == 'spam_man').count(), 1) # AllanC - TODO - follow the whole flow though? self.delete_member('spam_man') # Double check delete cascade self.assertEquals( Session.query(FlaggedEntity).filter( FlaggedEntity.raising_member_id == 'unittest').filter( FlaggedEntity.offending_member_id == 'spam_man').count(), 0)
def get_user_from_openid_identifyer(identifyer): """ Called by account controller to return a user from our db from an openid identifyer """ try: q = Session.query(User).select_from( join(User, UserLogin, User.login_details)) #q = q.filter(User.status == 'active' ) # the base controler checks for pending status and redirects to login page accordingly q = q.filter(UserLogin.token == identifyer) q = q.one() return q except NoResultFound: return None
def delete_content(self, id, force=False): if force: # ignore logged in user and just get rid of it Session.delete(Session.query(Content).get(id)) Session.commit() else: self.assertIn('delete', self.get_actions(id)) response = self.app.post(url('content', id=id, format="json"), params={ '_method': 'delete', '_authentication_token': self.auth_token, }, status=200)
def part_setup(self): # notifications can't be created manually n1 = Message() n1.target = Session.query(Member).get("unittest") n1.subject = u"Notification! A test" n1.content = u"A test is happening now :O" n2 = Message() n2.target = Session.query(Member).get("unitfriend") n2.subject = u"Another notification! A test" n2.content = u"A test part 2 is happening now :O" n3 = Message() n3.target = Session.query(Member).get("unittest") n3.subject = u"deleteme" n3.content = u"This is a notification to test deletion with" Session.add_all([n1, n2, n3]) Session.commit() self.n1_id = n1.id self.n2_id = n2.id self.n3_id = n3.id
def get_members(members, expand_group_members=True): """ Aquire a list of all submembers e.g Group Test1 has 3 members Group Test2 has 2 members passing [Test1,Test2] will return 5 member objects of the submembers members can be group object - All user member users (including recursive sub members) of a group list of username strings a comma separated list of strings AllanC - Note ignors and does not error on members that do not exist? is this right? TODO - optimisation - lazy load settings and other large feilds from these users """ if not members: return [] # split comma list of string members if isinstance(members, basestring): members = [member.strip() for member in members.split(',')] #if len(members) == 1 and expand_group_members: # member list has one member, check if this single member is a group # member = get_member(members[0]) # if member and member.__type__ == 'group': # members = member # else it's a user and is valid, do nothing if isinstance(members, Group) and expand_group_members: members = get_group_member_username_list(members) # No need to process members list if members is a single member # note: any group object will have been converted into a member list above is needed if isinstance(members, Member): return [members] # normalize member names members = [member if not hasattr(member, 'id') else member.id for member in members] member_objects = Session.query(Member).with_polymorphic('*').filter(Member.id.in_(members)).filter(Member.status=='active').all() if expand_group_members: group_members = [] for group in [member for member in member_objects if isinstance(member, Group)]: group_members += get_group_member_username_list(group) # , exclude_list=group_members member_objects += get_members(list(set(group_members))) member_objects = list(set(member_objects)) return member_objects
def test_tags(self): content_id = self.create_content(tags_string='test ,tests, pylons ') self.check_tags(content_id, ['test', 'tests', 'pylons']) self.update_content(content_id, tags_string='test, tests , pyramid') self.check_tags(content_id, ['test', 'tests', 'pyramid']) self.update_content(content_id, tags_string='test') self.check_tags(content_id, ['test']) self.update_content(content_id, tags_string='test , bob , monkey') self.check_tags(content_id, ['test', 'bob', 'monkey']) self.delete_content(content_id) tags_in_db = Session.query(Tag).all() tags_in_db = set([tag.name for tag in tags_in_db]) assert self.tags_used <= tags_in_db # Check every tag used in this test is a subset of all tags in DB
def test_index_order(self): contents = [] for i in range(3): contents.append(self.create_content()) # Change the order of the content to check the index action is sorting by default correctly from civicboom.model.meta import Session from civicboom.model import Content import datetime content_2 = Session.query(Content).get(contents[2]) content_2.update_date = content_2.update_date - datetime.timedelta( weeks=10) content_0 = Session.query(Content).get(contents[0]) content_0.update_date = content_0.update_date + datetime.timedelta( weeks=10) Session.commit() # Check order # There could be other items of content in the list. We want to check for the order of our contents 0,1,2 to be in the order 0 (Newest) then 1 (Now) then 2 (Oldest) response = self.app.get( url('contents', creator='unittest', limit='100', format='json')) response_json = json.loads(response.body) next_index = 0 for content_id in [ content_item['id'] for content_item in response_json['data']['list']['items'] ]: if content_id == contents[next_index]: next_index += 1 self.assertEquals( next_index, len(contents)) # It found the id's in the oder of contents for content_id in contents: self.delete_content(content_id)
def get_assigned_to(content, member): content = get_content(content) member = get_member(member) if not (content and member): return None try: return Session.query(MemberAssignment).filter( and_( MemberAssignment.content_id == content.id, MemberAssignment.member_id == member.id ) ).one() except NoResultFound: return None
def get_follower_type(member, follower): member = get_member(member) follower = get_member(follower) if not (member and follower): return None try: return Session.query(Follow).filter( and_( Follow.member_id == member.id, Follow.follower_id == follower.id, ) ).one().type except NoResultFound: return None
def get_membership(group, member): member = get_member(member) group = get_group(group) if not (member and group): return None try: return Session.query(GroupMembership).filter( and_( GroupMembership.group_id == group.id, GroupMembership.member_id == member.id ) ).one() except NoResultFound: return None
def mark_messages_as_read(self, **kwargs): """ POST /profile/{id}/mark_messages_as_read: Mark messages as read @type action @api contents 1.0 (WIP) @param type type of message object to mark as read from all, to, notification """ list_type = kwargs.get('list', 'all') if list_type in list_filters and list_type in ['all','to','notification']: results = Session.query(Message).filter(Message.target_id==c.logged_in_persona.id) results = list_filters[list_type](results) for message in results.all(): message.read = True Session.commit() return action_ok(message='%s marked as read' % type, code=201) raise action_error(_('list %s not supported') % kwargs.get('list'), code=400)
def is_follow_trusted_invitee(a, b): # Was is_follower_invited_trust """ True if 'b' has been invited to follow 'a' as a trusted follower True if 'b' is the invitee to follow 'a' as a trusted follower """ a = get_member(a) b = get_member(b) if not a or not b: return False try: if Session.query(Follow).filter(Follow.member_id == a.id).filter( Follow.follower_id == b.id).filter( Follow.type == 'trusted_invite').one(): return True except: pass return False