def change_password(request, format=None): data = request.data if 'password' not in data or 'new_password' not in data: return Response( status=404, data={"error": "Expects password and new_password fields"}) if request.user.check_password(data['password']): # Verified password request.user.set_password(data['new_password']) try: request.user.save() send_mail({ "user": request.user, "subject": "Reset password", "content": "Someone has reset your password. If this was not you, please contact us at: [email protected]", }) except: return Response({"error": "Could not save password"}, status=404) else: print( "Error, user %s attempted to reset password with incorrect password" % (request.user.username)) return Response({"error": "Incorrect password"})
def test_mail_util_func(self): root_dir = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) static = 'PDF_Reports' full_path = os.path.join(root_dir, static) attachment_file_path = str(full_path) + "/test_pdf_report.pdf" print(attachment_file_path) result = send_mail({'user': {'email': '*****@*****.**'}, 'subject': 'test', 'content': '<html><body>Testing</body></html>', 'attachment_file_path': attachment_file_path, 'attachment_file_name': 'test_pdf_report.pdf'}) self.assertTrue(result)
def addMessage(request, format=None): log.error(request.data) session_key = request.session.get('session_key', None) if (session_key is None): session_key = str(uuid.uuid1()) request.session['session_key'] = session_key request.session.modified = True '''Add a new message to list to be sent to city council''' now = datetime.now() message_info = request.data if 'ag_item' not in message_info or 'committee' not in message_info or 'content' not in message_info or 'pro' not in message_info: return Response( status=400, data={"error": "Missing or incorrect body parameters?"}) committee = Committee.objects.get(name__contains=message_info['committee']) if committee is None: return Response(data={ "error": "Could not find committee matching:" + message_info['committee'] }, status=404) agenda_item = AgendaItem.objects.get(pk=message_info['ag_item']) if agenda_item is None: return Response(data={ "error": "Could not find agenda item matching:" + message_info['ag_item'] }, status=404) if not settings.TEST and not isCommentAllowed( agenda_item.meeting_time, committee.cutoff_offset_days, committee.cutoff_hour, committee.cutoff_minute, committee.location_tz): return Response( status=401, data={ "error": "Could not add comment about agenda item because past the cutoff time" }) content = message_info['content'] pro = message_info['pro'] first_name = None last_name = None zipcode = 90401 user = None email = None user = None home_owner = False business_owner = False resident = False works = False school = False child_school = False CODE_LENGTH = 8 rand_begin = random.randint(0, 32 - CODE_LENGTH) authcode_hashed = None if (isinstance(request.user, AnonymousUser)): if 'first_name' not in message_info or message_info['first_name'] is None or \ 'last_name' not in message_info or message_info['last_name'] is None or \ 'zipcode' not in message_info or message_info['zipcode'] is None or \ 'email' not in message_info or message_info['email'] is None or \ 'home_owner' not in message_info or message_info['home_owner'] is None or \ 'business_owner' not in message_info or message_info['business_owner'] is None or \ 'resident' not in message_info or message_info['resident'] is None or \ 'works' not in message_info or message_info['works'] is None or \ 'school' not in message_info or message_info['school'] is None or \ 'child_school' not in message_info or message_info['child_school'] is None or \ 'token' not in message_info or message_info['token'] is None: return Response( status=400, data={"error": "Missing or incorrect body parameters"}) messages = Message.objects.filter(session_key=session_key) authcode = str(uuid.uuid1()).replace( "-", "")[rand_begin:rand_begin + CODE_LENGTH].encode('utf-8') if len(messages) == 0: verify_token = message_info['token'] result = verify_recaptcha(verify_token) if not result: return Response(status=401) authcode_hashed = bcrypt.hashpw(authcode, bcrypt.gensalt()).decode('utf-8') else: authcode_hashed = messages[0].authcode first_name = message_info['first_name'] last_name = message_info['last_name'] zipcode = message_info['zipcode'] email = message_info['email'] home_owner = message_info['home_owner'] business_owner = message_info['business_owner'] resident = message_info['resident'] works = message_info['works'] school = message_info['school'] child_school = message_info['child_school'] new_message = Message(agenda_item=agenda_item, user=user, first_name=first_name, last_name=last_name, zipcode=zipcode, email=email, committee=committee, content=content, pro=pro, authcode=authcode_hashed, date=now.timestamp(), sent=0, home_owner=home_owner, business_owner=business_owner, resident=resident, works=works, school=school, child_school=child_school, session_key=session_key) new_message.save() if len(messages) == 0: query_parameters = urllib.parse.urlencode({ "code": authcode, "email": email, "type": "email", "id": str(new_message.id) }) query_string = 'https://sm.engage.town/#/emailConfirmation?' + query_parameters content = '<h3>Thanks for voicing your opinion,</h3> Before we process your comments, please click <a href="' + \ query_string + '">here</a> to authenticate.<br/><br/> Thank you for your interest in your local government!<br/><br/> If you are receiving this in error, please email: <a href="mailto:[email protected]">[email protected]</a>. ' response = send_mail({ "user": { "email": email }, "subject": "Verify message regarding agenda item: " + agenda_item.agenda_item_id, "content": content }) if (not response): new_message.delete() return Response( status=500, data={ 'error': "Something happened sending you your confirmation email, please contact [email protected]" }) else: user = request.user profile = EngageUserProfile.objects.get(user_id=request.user.id) home_owner = profile.home_owner business_owner = profile.business_owner resident = profile.resident works = profile.works school = profile.school child_school = profile.child_school if profile.authcode != None: authcode_hashed = profile.authcode new_message = Message(agenda_item=agenda_item, user=user, first_name=first_name, last_name=last_name, zipcode=zipcode, email=email, committee=committee, content=content, pro=pro, authcode=authcode_hashed, date=now.timestamp(), sent=0, home_owner=home_owner, business_owner=business_owner, resident=resident, works=works, school=school, child_school=child_school, session_key=session_key) new_message.save() # Default to unsent, will send on weekly basis all sent=0 return Response(status=201, data={ "success": True, "message": "Message added" })
def writePdfForAgendaItems(agenda_items, committee, agenda): root_dir = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) static = 'PDF_Reports' full_path = os.path.join(root_dir, static) today = datetime.today() if not os.path.exists(full_path): os.mkdir(full_path) try: doc = SimpleDocTemplate(str(full_path) + "/Meeting_" + str( datetime.fromtimestamp( agenda_items[0].agenda.meeting_time).strftime('%Y%m%d')) + ".pdf", pagesize=letter, rightMargin=72, leftMargin=72, topMargin=72, bottomMargin=18) contents = [] # Paragraph styles ps_title = ParagraphStyle("title", fontSize=14, spaceAfter=0.2 * inch, leading=14) ps_id = ParagraphStyle("id", fontSize=10) ps_pro = ParagraphStyle('pro', fontSize=10, backColor='#27ae60', textColor="#FFFFFF", spaceBefore=7, borderPadding=(5, 5, 5, 5)) ps_con = ParagraphStyle('con', fontSize=10, backColor='#c0392b', textColor='#FFFFFF', spaceBefore=7, borderPadding=(5, 5, 5, 5)) ps_need_info = ParagraphStyle('need_info', fontSize=10, backColor='#000000', textColor='#FFFFFF', spaceBefore=7, borderPadding=(5, 5, 5, 5)) ps_need_info = ParagraphStyle('need_info', fontSize=10, backColor='#000000', textColor='#FFFFFF', spaceBefore=7, borderPadding=(5, 5, 5, 5)) ps_no_comments = ParagraphStyle('no_comments', fontSize=10, backColor="rgba(100,100,100,0.20)", textColor="#000000", spaceBefore=7, borderPadding=(5, 5, 5, 5), borderColor="#FFFFFF", borderWidth=2, borderRadius=5) cover_page_title = ParagraphStyle("cover", fontSize=21, alignment=TA_CENTER, textColor="#000000") cover_page_subtitle = ParagraphStyle("cover", fontSize=16, spaceBefore=15, alignment=TA_CENTER, textColor="#000000") cover_page_subtitle_leading = ParagraphStyle("cover", fontSize=12, spaceBefore=50, alignment=TA_CENTER, textColor="#000000") contents.append(Spacer(0, 3 * inch)) contents.append( Paragraph("Agenda Items - Comment Submissions", cover_page_title)) contents.append( Paragraph( f"{datetime.fromtimestamp(agenda_items[0].agenda.meeting_time).strftime('%m/%d/%Y')} {committee.name} - Submissions for {today.strftime('%m/%d/%Y')}", cover_page_subtitle)) contents.append( Paragraph( "Report generated by <a href='http://engage.town/'><u>Engage.town</u></a>", cover_page_subtitle_leading)) contents.append(PageBreak()) for upcoming_agenda_item in agenda_items: contents.append(Paragraph(upcoming_agenda_item.title, ps_title)) contents.append( Paragraph("ID: " + upcoming_agenda_item.agenda_item_id, ps_id)) pro_comments_on_agenda_item = Message.objects.filter( agenda_item=upcoming_agenda_item, pro=0) con_comments_on_agenda_item = Message.objects.filter( agenda_item=upcoming_agenda_item, pro=1) need_info_comments_on_agenda_item = Message.objects.filter( agenda_item=upcoming_agenda_item, pro=2) contents.append( Paragraph("Comments agreeing with the recommendations:", ps_pro)) contents.append(Spacer(1, 0.2 * inch)) if len(pro_comments_on_agenda_item) > 0: paragraphize_comments(pro_comments_on_agenda_item, contents) else: contents.append( Paragraph( "No comments agreeing with recommendations on this item.", ps_no_comments)) contents.append(Spacer(1, 0.5 * inch)) contents.append( Paragraph("Comments disagreeing with the recommendations:", ps_con)) contents.append(Spacer(1, 0.2 * inch)) if len(con_comments_on_agenda_item) > 0: paragraphize_comments(con_comments_on_agenda_item, contents) else: contents.append( Paragraph( "No comments disagreeing with recommendations on this item.", ps_no_comments)) contents.append(Spacer(1, 0.5 * inch)) contents.append( Paragraph("Need more information comments", ps_need_info)) contents.append(Spacer(1, 0.2 * inch)) if len(need_info_comments_on_agenda_item) > 0: paragraphize_comments(need_info_comments_on_agenda_item, contents) else: contents.append( Paragraph( "No needs more information comments on this item.", ps_no_comments)) contents.append(Spacer(1, 0.5 * inch)) contents.append(PageBreak()) doc.build(contents) attachment_file_path = str(full_path) + "/Meeting_" + str( datetime.fromtimestamp(agenda_items[0].agenda.meeting_time). strftime('%Y%m%d')) + ".pdf" attachment_name = "Agenda_Comments_Council_Meeting_" + \ str(datetime.fromtimestamp( agenda_items[0].agenda.meeting_time).strftime('%Y%m%d')) + f".pdf" email_body = """<html> <head> <style> body { font-family: sans-serif; font-size: 12px; color: #000; } </style> </head> <body> <p>Greetings from Engage</p> <p>Please find attached the latest report for the upcoming Council Meeting.</p> <p>Thank you,</p> <p>Your Engage team</p> <hr> <p><i>This is an automated message, for any questions please contact <a hrek=mailto:[email protected]?subject=Feedback%20Agenda%20Comments%20Report>[email protected]</a></i></p> </body </html> """ subject = f"Council Meeting {datetime.fromtimestamp(agenda_items[0].agenda.meeting_time).strftime('%m/%d/%Y')} - Agenda Recommendations, Comment Submissions for {today.strftime('%m/%d/%Y')}" send_mail({ "user": committee, "subject": subject, "content": email_body, "attachment_file_path": attachment_file_path, "attachment_file_name": attachment_name }) agenda.processed = True agenda.save() return True except: return False
def post(self, request): '''Add a new message to list to be sent to city council''' now = datetime.now().timestamp() message_info = request.data if 'ag_item' not in message_info or 'committee' not in message_info or 'content' not in message_info or 'token' not in message_info or 'pro' not in message_info: return Response( status=400, data={"error": "Missing or incorrect body parameters"}) committee = Committee.objects.filter( name__contains=message_info['committee']) print(committee) if committee is None: return Response(data={ "error": "Could not find committee matching:" + data['committee'] }, status=404) agenda_item = AgendaItem.objects.get(pk=message_info['ag_item']) if agenda_item is None: return Response(data={ "error": "Could not find agenda item matching:" + data['ag_item'] }, status=404) content = message_info['content'] verify_token = message_info['token'] pro = message_info['pro'] result = verify_recaptcha(verify_token) if not result: return Response(status=401) first_name = None last_name = None zipcode = 90401 user = None ethnicity = None email = None user = None home_owner = False business_owner = False resident = False works = False school = False child_school = False CODE_LENGTH = 8 rand_begin = random.randint(0, 32 - CODE_LENGTH) authcode = str(uuid.uuid1()).replace( "-", "")[rand_begin:rand_begin + CODE_LENGTH].encode('utf-8') authcode_hashed = bcrypt.hashpw(authcode, bcrypt.gensalt()).decode('utf-8') if (isinstance(request.user, AnonymousUser)): if 'first_name' not in message_info or message_info['first_name'] is None or \ 'last_name' not in message_info or message_info['last_name'] is None or \ 'zipcode' not in message_info or message_info['zipcode'] is None or \ 'email' not in message_info or message_info['email'] is None or \ 'home_owner' not in message_info or message_info['home_owner'] is None or \ 'business_owner' not in message_info or message_info['business_owner'] is None or \ 'resident' not in message_info or message_info['resident'] is None or \ 'works' not in message_info or message_info['works'] is None or \ 'school' not in message_info or message_info['school'] is None or \ 'child_school' not in message_info or message_info['child_school'] is None: return Response( status=400, data={"error": "Missing or incorrect body parameters"}) first_name = message_info['first_name'] last_name = message_info['last_name'] zipcode = message_info['zipcode'] email = message_info['email'] home_owner = message_info['home_owner'] business_owner = message_info['business_owner'] resident = message_info['resident'] works = message_info['works'] school = message_info['school'] child_school = message_info['child_school'] else: user = request.user profile = EngageUserProfile.objects.get(user_id=request.user.id) home_owner = profile.home_owner business_owner = profile.business_owner resident = profile.resident works = profile.works school = profile.school child_school = profile.child_school if profile.authcode == None: authcode_hashed = None new_message = Message(agenda_item=agenda_item, user=user, first_name=first_name, last_name=last_name, zipcode=zipcode, email=email, ethnicity=ethnicity, committee=committee, content=content, pro=pro, authcode=authcode_hashed, date=now, sent=0, home_owner=home_owner, business_owner=business_owner, resident=resident, works=works, school=school, child_school=child_school) new_message.save() print(new_message.id) if authcode_hashed is not None: query_parameters = urllib.parse.urlencode({ "code": authcode, "email": email, "type": "email", "id": str(new_message.id) }) query_string = 'https://engage-santa-monica.herokuapp.com/#/emailConfirmation?' + query_parameters content = '<h3>Thanks for voicing your opinion,</h3> Before we process your comment, please click <a href="' + \ query_string + '">here</a> to authenticate.<br/><br/>If you create and authenticate an account you will never have to authenticate for messages again.<br/><br/> Thank you for your interest in your local government!<br/><br/> If you are receiving this in error, please email: <a href="mailto:[email protected]">[email protected]</a>. ' send_mail({ "user": { "email": email }, "subject": "Verify message regarding agenda item: " + agenda_item.agenda_item_id, "content": content }) # Default to unsent, will send on weekly basis all sent=0 return Response(status=201)
def post(self, request): ''' Signup new user. Must be unique username and email. Will create authcode and email to user. ''' data = request.data if 'first_name' not in data or 'last_name' not in data or 'username' not in data or 'password' not in data or 'email' not in data: return Response(data={ "error": "Data object must contain first_name, last_name, username, password, and email" }, status=400) email = data['email'] password = data['password'] username = data['username'] first_name = data['first_name'] last_name = data['last_name'] CODE_LENGTH = 8 rand_begin = random.randint(0, 32 - CODE_LENGTH) authcode = str(uuid.uuid1()).replace( "-", "")[rand_begin:rand_begin + CODE_LENGTH].encode('utf-8') authcode_hashed = bcrypt.hashpw(authcode, bcrypt.gensalt()).decode('utf-8') if 'home_owner' in data and data['home_owner']: home_owner = True else: home_owner = False if 'resident' in data and data['resident']: resident = True else: resident = False if 'business_owner' in data and data['business_owner']: business_owner = True else: business_owner = False if 'works' in data and data['works']: works = True else: works = False if 'school' in data and data['school']: school = True else: school = False if 'child_school' in data and data['child_school']: child_school = True else: child_school = False try: user = User.objects.create_user(username, email, password) user.first_name = first_name user.last_name = last_name user.save() # Don't need to save any values from it EngageUserProfile.objects.create(user=user, home_owner=home_owner, resident=resident, business_owner=business_owner, works=works, school=school, child_school=child_school, authcode=authcode_hashed) query_parameters = urllib.parse.urlencode({ "code": authcode, "email": email, "type": "signup", "id": "" }) print("ZXY:", query_parameters) query_string = 'https://engage-santa-monica.herokuapp.com/#/emailConfirmation?' + query_parameters content = '<html><body><h3>Welcome to the Engage platform for Santa Monica,</h3> Please click <a href="' + \ query_string + '">here</a> to authenticate.<br/><br/>Thank you for your interest in your local government!<br/><br/> If you are receiving this in error, please email: <a href="mailto:[email protected]">[email protected]</a>.</body></html>' print(content) sent_mail = send_mail({ "user": user, "subject": "Please authenticate your email for the Engage platform", "content": content }) print("SENT MAIL:", sent_mail) token = jwt.encode({"username": user.email}, settings.SECRET_KEY) return Response({"token": token}, status=201) except: print("Unexpected error:", sys.exc_info()[0]) return Response(status=404)