mirror of
https://github.com/GSA/notifications-api.git
synced 2026-02-04 02:11:11 -05:00
Merge branch 'master' into reset-password
This commit is contained in:
@@ -1,10 +1,14 @@
|
||||
from flask import current_app
|
||||
from app import db
|
||||
from app.models import Notification
|
||||
from app.models import Notification, Job
|
||||
from sqlalchemy import desc
|
||||
|
||||
|
||||
def dao_create_notification(notification):
|
||||
if notification.job_id:
|
||||
db.session.query(Job).filter_by(
|
||||
id=notification.job_id
|
||||
).update({Job.notifications_sent: Job.notifications_sent + 1})
|
||||
db.session.add(notification)
|
||||
db.session.commit()
|
||||
|
||||
@@ -19,12 +23,12 @@ def get_notification_for_job(service_id, job_id, notification_id):
|
||||
|
||||
|
||||
def get_notifications_for_job(service_id, job_id, page=1):
|
||||
query = Notification.query.filter_by(service_id=service_id, job_id=job_id)\
|
||||
.order_by(desc(Notification.created_at))\
|
||||
query = Notification.query.filter_by(service_id=service_id, job_id=job_id) \
|
||||
.order_by(desc(Notification.created_at)) \
|
||||
.paginate(
|
||||
page=page,
|
||||
per_page=current_app.config['PAGE_SIZE']
|
||||
)
|
||||
page=page,
|
||||
per_page=current_app.config['PAGE_SIZE']
|
||||
)
|
||||
return query
|
||||
|
||||
|
||||
|
||||
@@ -162,6 +162,7 @@ class Job(db.Model):
|
||||
onupdate=datetime.datetime.now)
|
||||
status = db.Column(db.Enum(*JOB_STATUS_TYPES, name='job_status_types'), nullable=False, default='pending')
|
||||
notification_count = db.Column(db.Integer, nullable=False)
|
||||
notifications_sent = db.Column(db.Integer, nullable=False, default=0)
|
||||
processing_started = db.Column(
|
||||
db.DateTime,
|
||||
index=False,
|
||||
|
||||
@@ -4,6 +4,7 @@ from flask import (
|
||||
request,
|
||||
current_app
|
||||
)
|
||||
import bleach
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
|
||||
from app.dao.templates_dao import (
|
||||
@@ -34,6 +35,7 @@ def create_template(service_id):
|
||||
if errors:
|
||||
return jsonify(result="error", message=errors), 400
|
||||
new_template.service = fetched_service
|
||||
new_template.content = _strip_html(new_template.content)
|
||||
try:
|
||||
dao_create_template(new_template)
|
||||
except IntegrityError as ex:
|
||||
@@ -55,6 +57,7 @@ def update_template(service_id, template_id):
|
||||
|
||||
current_data = dict(template_schema.dump(fetched_template).data.items())
|
||||
current_data.update(request.get_json())
|
||||
current_data['content'] = _strip_html(current_data['content'])
|
||||
|
||||
update_dict, errors = template_schema.load(current_data)
|
||||
if errors:
|
||||
@@ -79,3 +82,7 @@ def get_template_by_id_and_service_id(service_id, template_id):
|
||||
return jsonify(data=data)
|
||||
else:
|
||||
return jsonify(result="error", message="Template not found"), 404
|
||||
|
||||
|
||||
def _strip_html(content):
|
||||
return bleach.clean(content, tags=[], strip=True)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from datetime import datetime
|
||||
from flask import (jsonify, request, abort, Blueprint, current_app)
|
||||
from flask import (jsonify, request, abort, Blueprint)
|
||||
from app import encryption
|
||||
|
||||
from app.dao.users_dao import (
|
||||
@@ -77,6 +77,8 @@ def verify_user_password(user_id):
|
||||
result="error",
|
||||
message={'password': ['Required field missing data']}), 400
|
||||
if user_to_verify.check_password(txt_pwd):
|
||||
user_to_verify.logged_in_at = datetime.utcnow()
|
||||
save_model_user(user_to_verify)
|
||||
reset_failed_login_count(user_to_verify)
|
||||
return jsonify({}), 204
|
||||
else:
|
||||
|
||||
26
migrations/versions/0034_job_sent_count.py
Normal file
26
migrations/versions/0034_job_sent_count.py
Normal file
@@ -0,0 +1,26 @@
|
||||
"""empty message
|
||||
|
||||
Revision ID: 0034_job_sent_count
|
||||
Revises: 0033_correct_permission_enums
|
||||
Create Date: 2016-03-04 13:44:32.217058
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '0034_job_sent_count'
|
||||
down_revision = '0033_correct_permission_enums'
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
def upgrade():
|
||||
### commands auto generated by Alembic - please adjust! ###
|
||||
op.add_column('jobs', sa.Column('notifications_sent', sa.Integer(), nullable=True))
|
||||
### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_column('jobs', 'notifications_sent')
|
||||
### end Alembic commands ###
|
||||
27
migrations/versions/0035_default_sent_count.py
Normal file
27
migrations/versions/0035_default_sent_count.py
Normal file
@@ -0,0 +1,27 @@
|
||||
"""empty message
|
||||
|
||||
Revision ID: 0035_default_sent_count
|
||||
Revises: 0034_job_sent_count
|
||||
Create Date: 2016-03-08 09:08:55.721654
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '0035_default_sent_count'
|
||||
down_revision = '0034_job_sent_count'
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.execute('update jobs set notifications_sent = notification_count')
|
||||
op.alter_column('jobs', 'notifications_sent',
|
||||
existing_type=sa.INTEGER(),
|
||||
nullable=False)
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.alter_column('jobs', 'notifications_sent',
|
||||
existing_type=sa.INTEGER(),
|
||||
nullable=True)
|
||||
@@ -1,3 +1,4 @@
|
||||
bleach==1.4.2
|
||||
Flask==0.10.1
|
||||
Flask-Script==2.0.5
|
||||
Flask-Migrate==1.3.1
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from app.models import Notification
|
||||
from app.models import Notification, Job
|
||||
from datetime import datetime
|
||||
from app.dao.notifications_dao import (
|
||||
dao_create_notification,
|
||||
@@ -7,14 +7,70 @@ from app.dao.notifications_dao import (
|
||||
get_notification_for_job,
|
||||
get_notifications_for_job
|
||||
)
|
||||
from tests.app.conftest import sample_job
|
||||
|
||||
|
||||
def test_save_notification(sample_template, sample_job):
|
||||
def test_save_notification_and_increment_job(sample_template, sample_job):
|
||||
|
||||
assert Notification.query.count() == 0
|
||||
data = {
|
||||
'to': '+44709123456',
|
||||
'job_id': sample_job.id,
|
||||
'service': sample_template.service,
|
||||
'template': sample_template,
|
||||
'created_at': datetime.utcnow()
|
||||
}
|
||||
|
||||
notification = Notification(**data)
|
||||
dao_create_notification(notification)
|
||||
|
||||
assert Notification.query.count() == 1
|
||||
notification_from_db = Notification.query.all()[0]
|
||||
assert notification_from_db.id
|
||||
assert data['to'] == notification_from_db.to
|
||||
assert data['job_id'] == notification_from_db.job_id
|
||||
assert data['service'] == notification_from_db.service
|
||||
assert data['template'] == notification_from_db.template
|
||||
assert data['created_at'] == notification_from_db.created_at
|
||||
assert 'sent' == notification_from_db.status
|
||||
assert Job.query.get(sample_job.id).notifications_sent == 1
|
||||
|
||||
|
||||
def test_save_notification_and_increment_correct_job(notify_db, notify_db_session, sample_template):
|
||||
|
||||
job_1 = sample_job(notify_db, notify_db_session, sample_template.service)
|
||||
job_2 = sample_job(notify_db, notify_db_session, sample_template.service)
|
||||
|
||||
assert Notification.query.count() == 0
|
||||
data = {
|
||||
'to': '+44709123456',
|
||||
'job_id': job_1.id,
|
||||
'service': sample_template.service,
|
||||
'template': sample_template,
|
||||
'created_at': datetime.utcnow()
|
||||
}
|
||||
|
||||
notification = Notification(**data)
|
||||
dao_create_notification(notification)
|
||||
|
||||
assert Notification.query.count() == 1
|
||||
notification_from_db = Notification.query.all()[0]
|
||||
assert notification_from_db.id
|
||||
assert data['to'] == notification_from_db.to
|
||||
assert data['job_id'] == notification_from_db.job_id
|
||||
assert data['service'] == notification_from_db.service
|
||||
assert data['template'] == notification_from_db.template
|
||||
assert data['created_at'] == notification_from_db.created_at
|
||||
assert 'sent' == notification_from_db.status
|
||||
assert Job.query.get(job_1.id).notifications_sent == 1
|
||||
assert Job.query.get(job_2.id).notifications_sent == 0
|
||||
|
||||
|
||||
def test_save_notification_with_no_job(sample_template):
|
||||
|
||||
assert Notification.query.count() == 0
|
||||
data = {
|
||||
'to': '+44709123456',
|
||||
'job': sample_job,
|
||||
'service': sample_template.service,
|
||||
'template': sample_template,
|
||||
'created_at': datetime.utcnow()
|
||||
@@ -27,7 +83,6 @@ def test_save_notification(sample_template, sample_job):
|
||||
notification_from_db = Notification.query.all()[0]
|
||||
assert notification_from_db.id
|
||||
assert data['to'] == notification_from_db.to
|
||||
assert data['job'] == notification_from_db.job
|
||||
assert data['service'] == notification_from_db.service
|
||||
assert data['template'] == notification_from_db.template
|
||||
assert data['created_at'] == notification_from_db.created_at
|
||||
|
||||
@@ -10,7 +10,7 @@ def test_should_create_a_new_sms_template_for_a_service(notify_api, sample_servi
|
||||
data = {
|
||||
'name': 'my template',
|
||||
'template_type': 'sms',
|
||||
'content': 'template content',
|
||||
'content': 'template <b>content</b>',
|
||||
'service': str(sample_service.id)
|
||||
}
|
||||
data = json.dumps(data)
|
||||
@@ -42,7 +42,7 @@ def test_should_create_a_new_email_template_for_a_service(notify_api, sample_ser
|
||||
'name': 'my template',
|
||||
'template_type': 'email',
|
||||
'subject': 'subject',
|
||||
'content': 'template content',
|
||||
'content': 'template <b>content</b>',
|
||||
'service': str(sample_service.id)
|
||||
}
|
||||
data = json.dumps(data)
|
||||
@@ -222,7 +222,7 @@ def test_should_be_able_to_update_a_template(notify_api, sample_service):
|
||||
json_resp = json.loads(create_response.get_data(as_text=True))
|
||||
assert json_resp['data']['name'] == 'my template'
|
||||
data = {
|
||||
'name': 'my template has a new name'
|
||||
'content': 'my template has new content <script type="text/javascript">alert("foo")</script>'
|
||||
}
|
||||
data = json.dumps(data)
|
||||
auth_header = create_authorization_header(
|
||||
@@ -239,7 +239,7 @@ def test_should_be_able_to_update_a_template(notify_api, sample_service):
|
||||
|
||||
assert update_response.status_code == 200
|
||||
update_json_resp = json.loads(update_response.get_data(as_text=True))
|
||||
assert update_json_resp['data']['name'] == 'my template has a new name'
|
||||
assert update_json_resp['data']['content'] == 'my template has new content alert("foo")'
|
||||
|
||||
|
||||
def test_should_be_able_to_get_all_templates_for_a_service(notify_api, sample_service):
|
||||
|
||||
@@ -2,10 +2,11 @@ import json
|
||||
import moto
|
||||
from datetime import (datetime, timedelta)
|
||||
from flask import url_for
|
||||
from app.models import (VerifyCode)
|
||||
from app.models import (VerifyCode, User)
|
||||
import app.celery.tasks
|
||||
from app import db, encryption
|
||||
from tests import create_authorization_header
|
||||
from freezegun import freeze_time
|
||||
|
||||
|
||||
def test_user_verify_code_sms(notify_api,
|
||||
@@ -127,6 +128,7 @@ def test_user_verify_code_email_expired_code(notify_api,
|
||||
assert not VerifyCode.query.first().code_used
|
||||
|
||||
|
||||
@freeze_time("2016-01-01 10:00:00.000000")
|
||||
def test_user_verify_password(notify_api,
|
||||
notify_db,
|
||||
notify_db_session,
|
||||
@@ -146,6 +148,7 @@ def test_user_verify_password(notify_api,
|
||||
data=data,
|
||||
headers=[('Content-Type', 'application/json'), auth_header])
|
||||
assert resp.status_code == 204
|
||||
User.query.get(sample_user.id).logged_in_at == datetime.utcnow()
|
||||
|
||||
|
||||
def test_user_verify_password_invalid_password(notify_api,
|
||||
|
||||
Reference in New Issue
Block a user