def joined_cohort(user, project_cohort): """Notify program and super admins.""" # This always happens along with creating a program. pc = project_cohort program_admins = User.get(owned_programs=pc.program_label) super_admins = User.get(user_type='super_admin') organization = Organization.get_by_id(pc.organization_id) program_config = Program.get_config(pc.program_label) cohort_name = program_config['cohorts'][pc.cohort_label]['name'] notes = [] for admin in program_admins + super_admins: note = Notification.create( parent=admin, context_id=pc.uid, subject=u"{org} joined a cohort".format(org=organization.name), body=( u"{org} joined {cohort} in {program}. The organization is " "currently {status}." ).format( org=organization.name, cohort=cohort_name, program=program_config['name'], status=organization.status, ), link='/organizations/{}'.format(organization.short_uid), autodismiss=True, ) notes.append(note) ndb.put_multi(notes)
def changed_project_task(user, project, task, project_cohort_id=None): """If change made by an org admin, notify related account manager, or all the program owners. Otherwise, notify project liaison, or all the org admins. """ t_dict = task.to_client_dict() program_config = Program.get_config(project.program_label) if project_cohort_id: link = '/dashboard/{pc}/tasks/{ckpt}/{task}'.format( pc=DatastoreModel.convert_uid(project_cohort_id), ckpt=DatastoreModel.convert_uid(task.checkpoint_id), task=task.uid ) else: link = '/dashboard' params = { 'task_id': task.uid, 'context_id': project.uid, 'subject': "Task updated", 'body': u"{} updated \"{}\" in {}.".format( user.name, t_dict['name'], program_config['name']), 'link': link, 'autodismiss': True, } if user.non_admin: # Send to account managers (usu. set via program config -> # default_account_manager). parents = get_project_program_recipients(project) else: parents = get_project_organization_recipients(project) notes = [Notification.create(parent=p, **params) for p in parents] filtered_notes = Notification.filter_redundant(notes) ndb.put_multi(filtered_notes)
def received_invitation(user, inviter, context_id=None): note = Notification.create( parent=user, context_id=context_id, subject="You've been invited to PERTS.", body=u"{} invited you to create an account.".format(inviter.name), link='/dashboard', autodismiss=True, ) note.put()
def received_data_request(user, data_request): """Notify just recipient.""" note = Notification.create( parent=user, context_id=data_request.uid, subject=data_request.title, body=data_request.description, # obv. needs to be extended later link=data_request.link, ) note.put()
def joined_organization(approver, joiner, organization): """Notify joiner that existing owners approved the join.""" note = Notification.create( parent=joiner, context_id=organization.uid, subject="You have been approved", body=u"{} approved you to join {}.".format( approver.name, organization.name), link='/organizations/{}'.format(organization.uid), autodismiss=True, ) note.put()
def test_create(self, user=None, note_type='generic', template_params={}): params = { 'url': 'http://www.example.com', 'message': "Single item goes here.", 'first_name': "Henry", 'program_name': "Foo Program", } params.update(**template_params) n = Notification.create( user_id=user.uid if user else 'User_foo', type=note_type, template_params=params, ) return n
def rejected_from_organization(rejecter, rejectee, organization): """Notify rejectee that existing owners rejected them.""" note = Notification.create( parent=rejectee, context_id=organization.uid, subject="You were not admitted", body=u"{} rejected your request to join {}.".format( rejecter.name, organization.name), # Doesn't make sense to send them to an org page which they're not # permitted to access. Provide no link at all. autodismiss=True, viewable=False, ) note.put()
def requested_to_join_organization(user, organization): """Notify existing org admins.""" # Joining user won't appear here b/c they have assc_organizations. owners = User.get(owned_organizations=organization.uid, n=float('inf')) notes = [] for owner in owners: note = Notification.create( parent=owner, context_id=organization.uid, subject="New user in your organization", body=u"{} would like to join {}.".format( user.name, organization.name), link='/organizations/{}/users'.format(organization.short_uid), autodismiss=True, ) notes.append(note) ndb.put_multi(notes)
def notify_for_single_report(self, program, team, classroom=None): """Notifications for class contact or all members re: one report.""" if not team.report_reminders: logging.info( "{} has report reminders disabled; not notifying".format( team.uid)) return if classroom: recipients = [User.get_by_id(classroom.contact_id)] else: recipients = User.query_by_team(team.uid) protocol = 'http' if util.is_localhost() else 'https' # Note that reports are hosted by the local _backend_ gae sdk, not the # react-app dev server on :3000. But for now we're just pointing to the # list of a team's reports, which _is_ on :3000. domain = ('localhost:3000' if util.is_localhost() else os.environ['HOSTING_DOMAIN']) reports_page = '{}://{}/teams/{}/reports'.format( protocol, domain, team.short_uid) # If we do want to link directly to the report, we'll have to wrestle # with authentication and what that looks like. We can either generate # a token right here (but that would be the link was shareable, and it # would expire, both of which seem wrong) or build some additional # client code that would know how to redirect an unauthed user to # login and back. notes = [] for user in recipients: notes.append( Notification.create( user_id=user.uid, type='report', template_params={ 'context_name': classroom.name if classroom else team.name, 'first_name': user.first_name, 'program_name': program.name, 'url': reports_page, })) return notes
def downloaded_identifiers(user, project_cohort_id): supers = User.get(user_type='super_admin') notes = [] project_cohort = ProjectCohort.get_by_id(project_cohort_id) organization = Organization.get_by_id(project_cohort.organization_id) program = Program.get_config(project_cohort.program_label) cohort_name = program['cohorts'][project_cohort.cohort_label]['name'] for sup in supers: note = Notification.create( parent=sup, context_id=project_cohort_id, subject="IDs Downloaded", body=u"{} ({}) downloaded IDs for {}: {} {}.".format( user.name, user.email, organization.name, program['name'], cohort_name), link='/dashboard/{}'.format(project_cohort.short_uid), autodismiss=True, ) notes.append(note) ndb.put_multi(notes)
def changed_organization_task(user, organization, task, project_cohort_id=None): """Notify the other type of user, not one's own type: org or super.""" t_dict = task.to_client_dict() if project_cohort_id: link = '/dashboard/{pc}/tasks/{ckpt}/{task}'.format( pc=DatastoreModel.convert_uid(project_cohort_id), ckpt=DatastoreModel.convert_uid(task.checkpoint_id), task=task.uid ) else: link = '/dashboard' params = { 'task_id': task.uid, 'context_id': organization.uid, 'subject': "Task updated", 'body': u"{} updated \"{}\" in {}.".format( user.name, t_dict['name'], organization.name), 'link': link, 'autodismiss': True, } notes = [] if user.super_admin: # Notify anyone who owns the organization. admins = User.get( user_type='user', owned_organizations=organization.uid) notes += [Notification.create(parent=a, **params) for a in admins] if user.non_admin: # Super admins are too busy to care. pass # # Old code for sending to supers. # supers = User.get(user_type='super_admin') # notes += [Notification.create(parent=s, **params) for s in supers] # else program admin? Program admins are largely not implemented, and likely # won't have rights to modify/approve organizations anyway. filtered_notes = Notification.filter_redundant(notes) ndb.put_multi(filtered_notes)
def test_get_notifications(self): user = User.create(email='*****@*****.**') user.put() admin = User.create(email='*****@*****.**', user_type='super_admin') admin.put() notes = [ Notification.create( # intentionally created in reverse time order, to demonstrate # that we can query them in correct time order. created=datetime.datetime(2018, 8, 10 + x), parent=user, context_id='Org_foo', subject='Thing one.', body='The thing is thingish.', link='/organizations/foo', ) for x in range(3) ] ndb.put_multi(notes) user_response = self.testapp.get( '/api/users/{}/notifications?dismissed=false'.format(user.uid), headers=login_headers(user.uid), ) admin_response = self.testapp.get( '/api/notifications?dismissed=false', headers=login_headers(admin.uid), ) # All responses should be ordered with newest first by default. for response in (user_response, admin_response): response_notes = json.loads(response.body) previous_time = response_notes[0]['created'] for note_dict in response_notes[1:]: self.assertLess(note_dict['created'], previous_time) previous_time = note_dict['created']