def list_policies_for_community_admin(self, context: Context, community_id) -> Tuple[list, MassEnergizeAPIError]: try: if context.user_is_super_admin: return self.list_policies_for_super_admin(context) elif not context.user_is_community_admin: return None, CustomMassenergizeError("Sign in as a valid community admin") if not community_id: user = UserProfile.objects.get(pk=context.user_id) admin_groups = user.communityadmingroup_set.all() communities = [ag.community.policies for ag in admin_groups] policies = None for ag in admin_groups: if not policies: policies = ag.community.policies.all().filter(is_deleted=False) else: policies |= ag.community.policies.all().filter(is_deleted=False) return policies, None community: Community = Community.objects.get(pk=community_id) policies = community.policies.all().filter(is_deleted=False) policies |= Policy.objects.filter(is_global=True, is_deleted=False) return policies, None except Exception as e: capture_message(str(e), level="error") return None, CustomMassenergizeError(e)
def verify(request): try: payload = get_request_contents(request) firebase_id_token = payload.get('idToken', None) if firebase_id_token: decoded_token = auth.verify_id_token(firebase_id_token) user_email = decoded_token["email"] user = UserProfile.objects.filter(email=user_email).first() if (not user): return CustomMassenergizeError("Please create an account") payload = { "user_id": str(user.id), "email": user.email, "is_super_admin": user.is_super_admin, "is_community_admin": user.is_community_admin, "iat": decoded_token.get("iat"), "exp": decoded_token.get("exp"), } massenergize_jwt_token = jwt.encode( payload, SECRET_KEY, algorithm='HS256').decode('utf-8') return MassenergizeResponse( data={"idToken": str(massenergize_jwt_token)}) else: return CustomMassenergizeError("Invalid Auth") except Exception as e: return CustomMassenergizeError(e)
def list_subscribers_for_community_admin( self, context: Context, community_id) -> (list, MassEnergizeAPIError): try: if context.user_is_super_admin: return self.list_subscribers_for_super_admin(context) elif not context.user_is_community_admin: return None, CustomMassenergizeError( "Sign in as a valid community admin") if not community_id: user = UserProfile.objects.get(pk=context.user_id) admin_groups = user.communityadmingroup_set.all() communities = [ag.community for ag in admin_groups] subscribers = None for ag in admin_groups: if not subscribers: subscribers = ag.community.subscriber_set.all().filter( is_deleted=False) else: subscribers |= ag.community.subscriber_set.all( ).filter(is_deleted=False) return subscribers, None community: Community = Community.objects.get(pk=community_id) subscribers = community.subscriber_set.all().filter( is_deleted=False) return subscribers, None except Exception as e: print(e) return None, CustomMassenergizeError(e)
def list_subscribers_for_community_admin(self, context: Context, community_id) -> Tuple[list, MassEnergizeAPIError]: try: if context.user_is_super_admin: return self.list_subscribers_for_super_admin(context) elif not context.user_is_community_admin: return None, CustomMassenergizeError("Sign in as a valid community admin") # gets pass from admin portal as "null" # TODO: Owen clean this up with validator if not community_id or community_id=="null": user = UserProfile.objects.get(pk=context.user_id) admin_groups = user.communityadmingroup_set.all() communities = [ag.community for ag in admin_groups] subscribers = None for ag in admin_groups: if not subscribers: subscribers = ag.community.subscriber_set.all().filter(is_deleted=False) else: subscribers |= ag.community.subscriber_set.all().filter(is_deleted=False) return subscribers, None community: Community = Community.objects.get(pk=community_id) subscribers = community.subscriber_set.all().filter(is_deleted=False) return subscribers, None except Exception as e: capture_message(str(e), level="error") return None, CustomMassenergizeError(e)
def add_team_member(self, context: Context, args) -> (Team, MassEnergizeAPIError): try: team_id = args.pop('team_id', None) user = get_user_or_die(context, args) status = args.pop('is_admin', None) == 'true' if not team_id: return None, CustomMassenergizeError("Missing team_id") team_member: TeamMember = TeamMember.objects.filter( team__id=team_id, user=user).first() if team_member: team_member.is_admin = status team_member.save() else: team = Team.objects.filter(pk=team_id).first() if not team_id and not user: return None, CustomMassenergizeError( "Invalid team or user") team_member = TeamMember.objects.create(is_admin=status, team=team, user=user) return team_member, None except Exception as e: capture_message(str(e), level="error") return None, CustomMassenergizeError(e)
def edit_household(self, context: Context, args) -> Tuple[dict, MassEnergizeAPIError]: try: user = get_user_or_die(context, args) name = args.pop('name', None) unit_type = args.pop('unit_type', None) household_id = args.get('household_id', None) if not household_id: return None, CustomMassenergizeError( "Please provide household_id") reuloc = _get_or_create_reu_location(args, user) reu = RealEstateUnit.objects.get(pk=household_id) reu.name = name reu.unit_type = args.get("unit_type", "RESIDENTIAL") reu.address = reuloc verbose = DEBUG community = find_reu_community(reu, verbose) if community: if verbose: print("Updating the REU with zipcode " + reu.address.zipcode + " to the community " + community.name) reu.community = community reu.save() return reu, None except Exception as e: capture_message(str(e), level="error") return None, CustomMassenergizeError(str(e))
def list_community_admin(self, context: Context, args) -> Tuple[list, MassEnergizeAPIError]: try: community = get_community_or_die(context, args) if not community: return None, CustomMassenergizeError( "Please provide a community_id or subdomain") community_admin_group = CommunityAdminGroup.objects.filter( community=community).first() if not community_admin_group: if community: comm_admin = CommunityAdminGroup.objects.create( name=f"{community.name}-Admin-Group", community=community) comm_admin.save() community_admin_group = comm_admin else: return None, CustomMassenergizeError( "No community exists with that ID or subdomain") return community_admin_group, None except Exception as e: capture_message(str(e), level="error") return None, CustomMassenergizeError(e)
def edit_household(self, context: Context, args) -> (dict, MassEnergizeAPIError): try: user = get_user_or_die(context, args) name = args.pop('name', None) household_id = args.get('household_id', None) unit_type=args.pop('unit_type', None) location=args.pop('location', None) communityId = args.pop('community_id', None) or args.pop('community', None) if not household_id: return None, CustomMassenergizeError("Please provide household_id") new_unit = RealEstateUnit.objects.get(pk=household_id) new_unit.name = name new_unit.unit_type = unit_type new_unit.location = location if communityId: community = Community.objects.get(id=communityId) new_unit.community = community new_unit.save() return new_unit, None except Exception as e: return None, CustomMassenergizeError(str(e))
def add_action_completed(self, context: Context, args) -> (dict, MassEnergizeAPIError): try: # if not context.user_is_logged_in: # return None, CustomMassenergizeError("Sign in required") user_id = context.user_id or args.get('user_id') user_email = context.user_email or args.get('user_email') action_id = args.get("action_id", None) household_id = args.get("household_id", None) vendor_id = args.get("vendor_id", None) user = None if user_id: user = UserProfile.objects.get(id=user_id) elif user_email: user = UserProfile.objects.get(email=user_email) if not user: return None, CustomMassenergizeError("Sign in required / Provide user_id") action = Action.objects.get(id=action_id) if not action: return None, CustomMassenergizeError("Please provide an action_id") household = RealEstateUnit.objects.get(id=household_id) if not household: return None, CustomMassenergizeError("Please provide a household_id") # update all data points for t in action.tags.all(): data = Data.objects.filter(community=action.community, tag=t) if data: data.update(value=F("value") + 1) else: #data for this community, action does not exist so create one d = Data(tag=t, community=action.community, value=1, name=f"{t.name}") d.save() #if this already exists as a todo just move it over completed = UserActionRel.objects.filter(user=user, real_estate_unit=household, action=action) if completed: completed.update(status="DONE") return completed.first(), None # create a new one since we didn't find it existed before new_user_action_rel = UserActionRel(user=user, action=action, real_estate_unit=household, status="DONE") if vendor_id: vendor = Vendor.objects.get(id=vendor_id) #not required new_user_action_rel.vendor = vendor new_user_action_rel.save() return new_user_action_rel, None except Exception as e: return None, CustomMassenergizeError(str(e))
def verify(request): try: payload = get_request_contents(request) firebase_id_token = payload.get('idToken', None) if firebase_id_token: decoded_token = auth.verify_id_token(firebase_id_token) user_email = decoded_token["email"] user = UserProfile.objects.filter(email=user_email).first() if (not user): return CustomMassenergizeError("authenticated_but_needs_registration") payload = { "user_id": str(user.id), "email": user.email, "is_super_admin": user.is_super_admin, "is_community_admin": user.is_community_admin, "iat": decoded_token.get("iat"), "exp": decoded_token.get("exp"), } massenergize_jwt_token = jwt.encode(payload, SECRET_KEY, algorithm='HS256').decode('utf-8') response = MassenergizeResponse(data=payload) response.set_cookie("token", str(massenergize_jwt_token)) return response else: return CustomMassenergizeError("Invalid Auth") except Exception as e: capture_message(str(e), level="error") return CustomMassenergizeError(e)
def list_actions_for_community_admin( self, context: Context, community_id) -> Tuple[list, MassEnergizeAPIError]: try: if context.user_is_super_admin: return self.list_actions_for_super_admin(context) elif not context.user_is_community_admin: return None, CustomMassenergizeError( "Sign in as a valid community admin") if not community_id: user = UserProfile.objects.get(pk=context.user_id) admin_groups = user.communityadmingroup_set.all() comm_ids = [ag.community.id for ag in admin_groups] actions = Action.objects.filter( Q(community__id__in=comm_ids) | Q(is_global=True)).select_related( 'image', 'community').prefetch_related( 'tags', 'vendors').filter(is_deleted=False) return actions, None actions = Action.objects.filter( Q(community__id=community_id) | Q(is_global=True)).select_related( 'image', 'community').prefetch_related( 'tags', 'vendors').filter(is_deleted=False) return actions, None except Exception as e: capture_message(str(e), level="error") return None, CustomMassenergizeError(e)
def add_super_admin(self, context: Context, args) -> (UserProfile, MassEnergizeAPIError): try: if not context.user_is_super_admin: return None, CustomMassenergizeError( "You must be a super Admin to add another Super Admin") email = args.pop("email", None) user_id = args.pop("user_id", None) if email: user = UserProfile.objects.filter(email=email).first() elif user_id: user = UserProfile.objects.filter(email=email).first() else: user = None if not user: return None, CustomMassenergizeError( "The user you are trying to add does not have an account yet" ) user.is_super_admin = True user.save() return user, None except Exception as e: return None, CustomMassenergizeError(e)
def list_goals_for_community_admin( self, context, community_id) -> (list, MassEnergizeAPIError): try: if context.user_is_super_admin: return self.list_goals_for_super_admin() elif not context.user_is_community_admin: return None, CustomMassenergizeError( "Sign in as a valid community admin") goals = [] if not community_id: user = UserProfile.objects.get(pk=context.user_id) admin_groups = user.communityadmingroup_set.all() for ag in admin_groups: goals.extend(self._get_goals_from_community(ag.community)) else: community: Community = Community.objects.get(pk=community_id) goals.extend(self._get_goals_from_community(community)) return goals, None except Exception as e: print(e) import traceback traceback.print_exc() return None, CustomMassenergizeError(e)
def remove_super_admin(self, context: Context, args) -> Tuple[UserProfile, MassEnergizeAPIError]: try: if not context.user_is_super_admin: return None, CustomMassenergizeError( "You must be a super Admin to add another Super Admin") email = args.pop("email", None) user_id = args.pop("user_id", None) if email: user = UserProfile.objects.filter(email=email).first() elif user_id: user = UserProfile.objects.filter(pk=user_id).first() else: user = None if not user: return None, CustomMassenergizeError( "The user you are trying to add does not have an account yet" ) user.is_super_admin = False user.save() return user, None except Exception as e: capture_message(str(e), level="error") return None, CustomMassenergizeError(e)
def create_event(self, context: Context, args) -> (dict, MassEnergizeAPIError): try: image = args.pop('image', None) tags = args.pop('tags', []) community = args.pop("community_id", None) have_address = args.pop('have_address', False) if not have_address: args['location'] = None if community: community = Community.objects.get(pk=community) if not community: return None, CustomMassenergizeError( "Please provide a valid community_id") new_event: Event = Event.objects.create(**args) if community: new_event.community = community if image: media = Media.objects.create( file=image, name=f"ImageFor{args.get('name', '')}Event") new_event.image = media new_event.save() if tags: new_event.tags.set(tags) return new_event, None except Exception as e: capture_message(str(e), level="error") return None, CustomMassenergizeError(e)
def graph_communities_impact(self, context: Context, args) -> Tuple[Graph, MassEnergizeAPIError]: try: subdomain = args.get('subdomain', None) community_id = args.get('community_id', None) if not community_id and not subdomain: return None, CustomMassenergizeError( "Missing community_id or subdomain field") community: Community = Community.objects.get( Q(pk=community_id) | Q(subdomain=subdomain)) if not community: return None, InvalidResourceError() res = [get_households_engaged(community)] limit = 10 for c in Community.objects.filter(is_deleted=False, is_published=True)[:limit]: if c.id != community.id: res.append(get_households_engaged(c)) return { "id": 1, "title": "Communities Impact", "graph_type": "bar_chart", "data": res }, None except Exception as e: capture_message(str(e), level="error") return None, CustomMassenergizeError(e)
def add_community_admin(self, context: Context, args) -> Tuple[UserProfile, MassEnergizeAPIError]: try: if not context.user_is_super_admin and not context.user_is_community_admin: return None, CustomMassenergizeError( "You must be a community or super Admin to add another community Admin" ) name = args.pop("name", None) email = args.pop("email", None) user_id = args.pop("user_id", None) community = get_community_or_die(context, args) if not community: return None, CustomMassenergizeError( "Please provide a community_id or subdomain") admin_group: CommunityAdminGroup = CommunityAdminGroup.objects.filter( community=community).first() if email: user: UserProfile = UserProfile.objects.filter( email=email).first() elif user_id: user: UserProfile = UserProfile.objects.filter( user_id=user_id).first() else: user: UserProfile = None if user: admin_group.members.add(user) if not user.is_super_admin and not user.is_super_admin: user.is_community_admin = True user.save() else: return None, CustomMassenergizeError( "The user you are trying to add does not have an account yet" ) admin_group.save() # make sure admin is a member of the community, if not add them self.communityStore.join_community(context, { "community_id": community.id, "user_id": user.id }) res = { "name": user.preferred_name, "email": user.email, "subdomain": community.subdomain, "community_name": community.name } return res, None except Exception as e: capture_message(str(e), level="error") return None, CustomMassenergizeError(e)
def remove_community_admin( self, context: Context, args) -> Tuple[UserProfile, MassEnergizeAPIError]: try: if not context.user_is_super_admin and not context.user_is_community_admin: return None, CustomMassenergizeError( "You must be a super or community Admin to remove a community Admin" ) email = args.pop("email", None) user_id = args.pop("user_id", None) community_id = args.pop("community_id", None) subdomain = args.pop("subdomain", None) if community_id: admin_group: CommunityAdminGroup = CommunityAdminGroup.objects.filter( community__id=community_id).first() elif subdomain: admin_group: CommunityAdminGroup = CommunityAdminGroup.objects.filter( community__subdomain=subdomain).first() else: return None, CustomMassenergizeError( "Please provide a community_id or subdomain") if email: user = UserProfile.objects.filter(email=email).first() elif user_id: user = UserProfile.objects.filter(id=user_id).first() else: user = None if user and user in admin_group.members.all(): admin_group.members.remove(user) admin_group.save() admin_at = user.communityadmingroup_set.all() if not (admin_at): # this user has been kicked off all communities they are on user.is_community_admin = False user.save() else: return None, CustomMassenergizeError( "The user you are trying to remove does not exist") # if admin_group.pending_admins: # data = admin_group.pending_admins.get("data", []) # for u in data: # if u.get("email", None) == email: # data.remove(u) # admin_group.pending_admins = {"data": data} admin_group.save() return admin_group, None except Exception as e: capture_message(str(e), level="error") return None, CustomMassenergizeError(e)
def add_action_todo(self, context: Context, args) -> (dict, MassEnergizeAPIError): try: user = get_user_or_die(context, args) action_id = args.get("action_id", None) household_id = args.get("household_id", None) vendor_id = args.get("vendor_id", None) if not user: return None, CustomMassenergizeError( "sign_in_required / provide user_id or user_email") action: Action = Action.objects.get(id=action_id) if not action: return None, CustomMassenergizeError( "Please provide a valid action_id") if household_id: household: RealEstateUnit = RealEstateUnit.objects.get( id=household_id) else: household = user.real_estate_units.all().first() if not household: household = RealEstateUnit( name=f"{user.preferred_name}'s Home'") household.save() user.real_estate_units.add(household) if vendor_id: vendor = Vendor.objects.get(id=vendor_id) #not required #if this already exists as a todo just move it over completed = UserActionRel.objects.filter( user=user, real_estate_unit=household, action=action) if completed: #TODO: update action stats completed.update(status="TODO") return completed.first(), None # create a new one since we didn't find it existed before new_user_action_rel = UserActionRel(user=user, action=action, real_estate_unit=household, status="TODO") if vendor_id: new_user_action_rel.vendor = vendor new_user_action_rel.save() return new_user_action_rel, None except Exception as e: capture_message(str(e), level="error") import traceback traceback.print_exc() return None, CustomMassenergizeError(str(e))
def get_user(user_id, email): try: if email: return UserProfile.objects.filter(email=email).first(), None elif user_id: return UserProfile.objects.filter(pk=user_id).first(), None return None, CustomMassenergizeError("Missing user_id or email field") except Exception as e: return None, CustomMassenergizeError(e)
def check_length(args, field, min_length=5, max_length=40): data = args.get(field, None) if not data: return False, CustomMassenergizeError(f"Please provide a {field} field") data_length = len(data) if data_length < min_length or data_length > max_length: return False, CustomMassenergizeError(f"{field} has to be between {min_length} and {max_length}") return True, None
def remove_household(self, context: Context, args) -> (dict, MassEnergizeAPIError): try: household_id = args.get('household_id', None) or args.get('household_id', None) if not household_id: return None, CustomMassenergizeError("Please provide household_id") return RealEstateUnit.objects.get(pk=household_id).delete(), None except Exception as e: return None, CustomMassenergizeError(str(e))
def graph_actions_completed_by_team( self, context: Context, args) -> Tuple[Graph, MassEnergizeAPIError]: try: team_id = args.get('team_id', None) if not team_id: return None, CustomMassenergizeError("Missing team_id field") team: Team = Team.objects.get(id=team_id) if not team: return None, InvalidResourceError() if not context.is_sandbox and not context.user_is_admin(): if not team.is_published: return None, CustomMassenergizeError( "Content Not Available Yet") users = get_team_users(team) completed_action_rels = [] for user in users: completed_action_rels.extend( user.useractionrel_set.filter(status="DONE").all()) categories = TagCollection.objects.get( name="Category").tag_set.order_by("name").all() prefetch_related_objects(completed_action_rels, "action__tags") data = [] for category in categories: data.append({ "id": category.id, "name": category.name, "value": len( list( filter( lambda action_rel: category in action_rel. action.tags.all(), completed_action_rels))) }) res = { "data": data, "title": "Actions Completed By Members Of Team", "team": team.info() } return res, None except Exception as e: capture_message(str(e), level="error") return None, CustomMassenergizeError(e)
def get_community(community_id=None, subdomain=None): try: if community_id: return Community.objects.filter(pk=community_id).first(), None elif subdomain: return Community.objects.filter(subdomain=subdomain).first(), None except Exception as e: return None, CustomMassenergizeError(e) return None, CustomMassenergizeError("Missing community_id or subdomain field")
def get_user(user_id, email=None): try: if email: return UserProfile.objects.filter(email=email).first(), None elif user_id: return UserProfile.objects.filter(pk=user_id).first(), None return None, CustomMassenergizeError("Missing user_id or email field") except Exception as e: capture_message(str(e), level="error") return None, CustomMassenergizeError(e)
def who_am_i(request): try: user_id = request.context.user_id if not user_id: return CustomMassenergizeError(f"No user exists with ID: {user_id}") user = UserProfile.objects.get(pk=user_id) return MassenergizeResponse(user.full_json()) except Exception as e: capture_message(str(e), level="error") return CustomMassenergizeError(e)
def get_tag_collection_info(self, args) -> (dict, MassEnergizeAPIError): try: tag_collection_id = args.pop('tag_collection_id', None) if not tag_collection_id: return CustomMassenergizeError("Please provide a valid id") tag_collection = TagCollection.objects.filter(id=tag_collection_id).first() if not tag_collection: return None, InvalidResourceError() return tag_collection, None except Exception as e: return None, CustomMassenergizeError(e)
def graph_actions_completed(self, context: Context, args) -> (Graph, MassEnergizeAPIError): try: subdomain = args.get('subdomain', None) community_id = args.get('community_id', None) if not community_id and not subdomain: return None, CustomMassenergizeError( "Missing community_id or subdomain field") community: Community = Community.objects.get( Q(pk=community_id) | Q(subdomain=subdomain)) if not community: return None, InvalidResourceError() if context.is_prod and not context.user_is_admin(): if not community.is_published: return None, CustomMassenergizeError( "Content Available Yet") graph = Graph.objects.prefetch_related('data').select_related( 'community').filter( community=community, title="Number of Actions Completed by Category").first() if not graph: graph = Graph.objects.create( community=community, title="Number of Actions Completed") graph.save() category, ok = TagCollection.objects.get_or_create(name="Category") for t in category.tag_set.all(): d = Data.objects.filter(tag=t, community=community).first() if not d: d = Data.objects.create(tag=t, community=community, name=f"{t.name}", value=0) if not d.pk: d.save() if d.name != t.name: d.name = t.name d.save() graph.data.add(d) graph.save() res = graph.full_json() res['community'] = community.info() return res, None except Exception as e: import traceback traceback.print_exc() return None, CustomMassenergizeError(e)
def get_team_admins(self, context, team_id): try: if not team_id: return None, CustomMassenergizeError("provide_team_id") team_admins = TeamMember.objects.filter(is_admin=True, team__id=team_id, is_deleted=False) team_admins = [a.user for a in team_admins if a.user] return team_admins, None except Exception as e: capture_message(str(e), level="error") return None, CustomMassenergizeError(e)
def import_from_csv(self, context, args) -> Tuple[dict, MassEnergizeAPIError]: first_name_field = args.get('first_name_field', None) last_name_field = args.get('last_name_field', None) email_field = args.get('email_field', None) custom_message = args.get('message', "") csv_ref = args.get('csv', None) if csv_ref: csv_ref = csv_ref.file else: return None, CustomMassenergizeError("csv file not specified") filecontents, err = _parse_import_file(csv_ref) if err: return None, CustomMassenergizeError(err) invalid_emails = [] line = 0 for csv_row in filecontents: line += 1 column_list = list(csv_row.keys()) try: # prevents the first row (headers) from being read in as a user first_name = csv_row[first_name_field].strip() last_name = csv_row[last_name_field] email = csv_row[email_field].lower() if first_name == column_list[0]: continue # verify correctness of email address # improved regex for validating e-mails regex = '^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$' if (re.search(regex, email)): info, err = self.store.add_invited_user( context, args, first_name, last_name, email) # send invitation e-mail to each new user _send_invitation_email(info, custom_message) else: if filecontents.index(csv_row) != 0: invalid_emails.append({"line": line, "email": email}) except Exception as e: print("Error string: " + str(e)) return None, CustomMassenergizeError(str(e)) if err: return None, err return {'invalidEmails': invalid_emails}, None