Format project

This commit is contained in:
richard-dds
2018-08-23 16:25:36 -04:00
parent e9fa4d9ecb
commit daa8634cb4
48 changed files with 415 additions and 282 deletions

View File

@@ -85,7 +85,9 @@ def map_config(config):
"SQLALCHEMY_DATABASE_URI": config["default"]["DATABASE_URI"],
"SQLALCHEMY_TRACK_MODIFICATIONS": False,
"WTF_CSRF_ENABLED": config.getboolean("default", "WTF_CSRF_ENABLED"),
"PERMANENT_SESSION_LIFETIME": config.getint("default", "PERMANENT_SESSION_LIFETIME"),
"PERMANENT_SESSION_LIFETIME": config.getint(
"default", "PERMANENT_SESSION_LIFETIME"
),
}
@@ -127,8 +129,10 @@ def make_config():
return map_config(config)
def make_redis(config):
return redis.Redis.from_url(config['REDIS_URI'])
return redis.Redis.from_url(config["REDIS_URI"])
def make_crl_validator(app):
crl_locations = []
@@ -136,5 +140,6 @@ def make_crl_validator(app):
crl_locations.append(filename.absolute())
app.crl_cache = CRLCache(app.config["CA_CHAIN"], crl_locations, logger=app.logger)
def make_eda_client(app):
app.eda_client = MockEDAClient()

View File

@@ -3,14 +3,10 @@ from flask_assets import Environment, Bundle
environment = Environment()
css = Bundle(
"../static/assets/index.css",
output="../static/assets/index.%(version)s.css",
"../static/assets/index.css", output="../static/assets/index.%(version)s.css"
)
environment.register("css", css)
js = Bundle(
'../static/assets/index.js',
output='../static/assets/index.%(version)s.js'
)
environment.register('js_all', js)
js = Bundle("../static/assets/index.js", output="../static/assets/index.%(version)s.js")
environment.register("js_all", js)

View File

@@ -3,7 +3,14 @@ from flask import g, redirect, url_for, session, request
from atst.domain.users import Users
UNPROTECTED_ROUTES = ["atst.root", "dev.login_dev", "atst.login_redirect", "atst.unauthorized", "static"]
UNPROTECTED_ROUTES = [
"atst.root",
"dev.login_dev",
"atst.login_redirect",
"atst.unauthorized",
"static",
]
def apply_authentication(app):
@app.before_request
@@ -26,7 +33,7 @@ def get_current_user():
else:
return False
def _unprotected_route(request):
if request.endpoint in UNPROTECTED_ROUTES:
return True

View File

@@ -4,8 +4,7 @@ from .utils import parse_sdn, email_from_certificate
from .crl import CRLRevocationException
class AuthenticationContext():
class AuthenticationContext:
def __init__(self, crl_cache, auth_status, sdn, cert):
if None in locals().values():
raise UnauthenticatedError(

View File

@@ -9,14 +9,16 @@ class CRLRevocationException(Exception):
pass
class CRLCache():
class CRLCache:
_PEM_RE = re.compile(
b"-----BEGIN CERTIFICATE-----\r?.+?\r?-----END CERTIFICATE-----\r?\n?",
re.DOTALL,
)
def __init__(self, root_location, crl_locations=[], store_class=crypto.X509Store, logger=None):
def __init__(
self, root_location, crl_locations=[], store_class=crypto.X509Store, logger=None
):
self.store_class = store_class
self.certificate_authorities = {}
self._load_roots(root_location)
@@ -57,7 +59,11 @@ class CRLCache():
with open(crl_location, "rb") as crl_file:
crl = crypto.load_crl(crypto.FILETYPE_ASN1, crl_file.read())
store.add_crl(crl)
self.log_info("STORE ID: {}. Adding CRL with issuer {}".format(id(store), crl.get_issuer()))
self.log_info(
"STORE ID: {}. Adding CRL with issuer {}".format(
id(store), crl.get_issuer()
)
)
store = self._add_certificate_chain_to_store(store, crl.get_issuer())
return store
@@ -75,7 +81,11 @@ class CRLCache():
def _add_certificate_chain_to_store(self, store, issuer):
ca = self.certificate_authorities.get(issuer.der())
store.add_cert(ca)
self.log_info("STORE ID: {}. Adding CA with subject {}".format(id(store), ca.get_subject()))
self.log_info(
"STORE ID: {}. Adding CA with subject {}".format(
id(store), ca.get_subject()
)
)
if issuer == ca.get_issuer():
# i.e., it is the root CA and we are at the end of the chain

View File

@@ -25,7 +25,15 @@ def email_from_certificate(cert_file):
return email[0]
else:
raise ValueError("No email available for certificate with serial {}".format(cert.serial_number))
raise ValueError(
"No email available for certificate with serial {}".format(
cert.serial_number
)
)
except x509.extensions.ExtensionNotFound:
raise ValueError("No subjectAltName available for certificate with serial {}".format(cert.serial_number))
raise ValueError(
"No subjectAltName available for certificate with serial {}".format(
cert.serial_number
)
)

View File

@@ -6,7 +6,6 @@ from .exceptions import NotFoundError
class PENumbers(object):
@classmethod
def get(cls, number):
pe_number = db.session.query(PENumber).get(number)

View File

@@ -73,9 +73,10 @@ class Requests(object):
filters.append(Request.creator == creator)
requests = (
db.session.query(Request).filter(*filters).order_by(
Request.time_created.desc()
).all()
db.session.query(Request)
.filter(*filters)
.order_by(Request.time_created.desc())
.all()
)
return requests
@@ -113,9 +114,10 @@ class Requests(object):
# Query for request matching id, acquiring a row-level write lock.
# https://www.postgresql.org/docs/10/static/sql-select.html#SQL-FOR-UPDATE-SHARE
return (
db.session.query(Request).filter_by(id=request_id).with_for_update(
of=Request
).one()
db.session.query(Request)
.filter_by(id=request_id)
.with_for_update(of=Request)
.one()
)
except NoResultFound:
@@ -153,9 +155,7 @@ class Requests(object):
RequestStatus.STARTED: "mission_owner",
RequestStatus.PENDING_FINANCIAL_VERIFICATION: "mission_owner",
RequestStatus.PENDING_CCPO_APPROVAL: "ccpo",
}.get(
request.status
)
}.get(request.status)
@classmethod
def should_auto_approve(cls, request):
@@ -167,13 +167,16 @@ class Requests(object):
return dollar_value < cls.AUTO_APPROVE_THRESHOLD
_VALID_SUBMISSION_STATUSES = [
RequestStatus.STARTED, RequestStatus.CHANGES_REQUESTED
RequestStatus.STARTED,
RequestStatus.CHANGES_REQUESTED,
]
@classmethod
def should_allow_submission(cls, request):
all_request_sections = [
"details_of_use", "information_about_you", "primary_poc"
"details_of_use",
"information_about_you",
"primary_poc",
]
existing_request_sections = request.body.keys()
return request.status in Requests._VALID_SUBMISSION_STATUSES and all(

View File

@@ -6,7 +6,6 @@ from .exceptions import NotFoundError
class Roles(object):
@classmethod
def get(cls, role_name):
try:

View File

@@ -9,7 +9,6 @@ from .exceptions import NotFoundError, AlreadyExistsError
class Users(object):
@classmethod
def get(cls, user_id):
try:

View File

@@ -11,7 +11,6 @@ from .exceptions import NotFoundError
class WorkspaceUsers(object):
@classmethod
def get(cls, workspace_id, user_id):
try:

View File

@@ -64,8 +64,6 @@ class Workspaces(object):
@classmethod
def _create_workspace_role(cls, user, workspace, role_name):
role = Roles.get(role_name)
workspace_role = WorkspaceRole(
user=user, role=role, workspace=workspace
)
workspace_role = WorkspaceRole(user=user, role=role, workspace=workspace)
db.session.add(workspace_role)
return workspace_role

View File

@@ -1,7 +1,8 @@
import re
def iconSvg(name):
with open('static/icons/'+name+'.svg') as contents:
with open("static/icons/" + name + ".svg") as contents:
return contents.read()
@@ -14,8 +15,8 @@ def dollars(value):
def usPhone(number):
phone = re.sub(r'\D', '', number)
return '+1 ({}) {} - {}'.format(phone[0:3], phone[3:6], phone[6:])
phone = re.sub(r"\D", "", number)
return "+1 ({}) {} - {}".format(phone[0:3], phone[3:6], phone[6:])
def readableInteger(value):
@@ -31,9 +32,8 @@ def getOptionLabel(value, options):
def register_filters(app):
app.jinja_env.filters['iconSvg'] = iconSvg
app.jinja_env.filters['dollars'] = dollars
app.jinja_env.filters['usPhone'] = usPhone
app.jinja_env.filters['readableInteger'] = readableInteger
app.jinja_env.filters['getOptionLabel'] = getOptionLabel
app.jinja_env.filters["iconSvg"] = iconSvg
app.jinja_env.filters["dollars"] = dollars
app.jinja_env.filters["usPhone"] = usPhone
app.jinja_env.filters["readableInteger"] = readableInteger
app.jinja_env.filters["getOptionLabel"] = getOptionLabel

View File

@@ -3,7 +3,10 @@ SERVICE_BRANCHES = [
("Air Force, Department of the", "Air Force, Department of the"),
("Army and Air Force Exchange Service", "Army and Air Force Exchange Service"),
("Army, Department of the", "Army, Department of the"),
("Defense Advanced Research Projects Agency", "Defense Advanced Research Projects Agency"),
(
"Defense Advanced Research Projects Agency",
"Defense Advanced Research Projects Agency",
),
("Defense Commissary Agency", "Defense Commissary Agency"),
("Defense Contract Audit Agency", "Defense Contract Audit Agency"),
("Defense Contract Management Agency", "Defense Contract Management Agency"),
@@ -19,31 +22,55 @@ SERVICE_BRANCHES = [
("Defense Security Cooperation Agency", "Defense Security Cooperation Agency"),
("Defense Security Service", "Defense Security Service"),
("Defense Technical Information Center", "Defense Technical Information Center"),
("Defense Technology Security Administration", "Defense Technology Security Administration"),
(
"Defense Technology Security Administration",
"Defense Technology Security Administration",
),
("Defense Threat Reduction Agency", "Defense Threat Reduction Agency"),
("DoD Education Activity", "DoD Education Activity"),
("DoD Human Recourses Activity", "DoD Human Recourses Activity"),
("DoD Inspector General", "DoD Inspector General"),
("DoD Test Resource Management Center", "DoD Test Resource Management Center"),
("Headquarters Defense Human Resource Activity ", "Headquarters Defense Human Resource Activity "),
(
"Headquarters Defense Human Resource Activity ",
"Headquarters Defense Human Resource Activity ",
),
("Joint Staff", "Joint Staff"),
("Missile Defense Agency", "Missile Defense Agency"),
("National Defense University", "National Defense University"),
("National Geospatial Intelligence Agency (NGA)", "National Geospatial Intelligence Agency (NGA)"),
("National Oceanic and Atmospheric Administration (NOAA)", "National Oceanic and Atmospheric Administration (NOAA)"),
(
"National Geospatial Intelligence Agency (NGA)",
"National Geospatial Intelligence Agency (NGA)",
),
(
"National Oceanic and Atmospheric Administration (NOAA)",
"National Oceanic and Atmospheric Administration (NOAA)",
),
("National Reconnaissance Office", "National Reconnaissance Office"),
("National Reconnaissance Office (NRO)", "National Reconnaissance Office (NRO)"),
("National Security Agency (NSA)", "National Security Agency (NSA)"),
("National Security Agency-Central Security Service", "National Security Agency-Central Security Service"),
(
"National Security Agency-Central Security Service",
"National Security Agency-Central Security Service",
),
("Navy, Department of the", "Navy, Department of the"),
("Office of Economic Adjustment", "Office of Economic Adjustment"),
("Office of the Secretary of Defense", "Office of the Secretary of Defense"),
("Pentagon Force Protection Agency", "Pentagon Force Protection Agency"),
("Uniform Services University of the Health Sciences", "Uniform Services University of the Health Sciences"),
(
"Uniform Services University of the Health Sciences",
"Uniform Services University of the Health Sciences",
),
("US Cyber Command (USCYBERCOM)", "US Cyber Command (USCYBERCOM)"),
("US Special Operations Command (USSOCOM)", "US Special Operations Command (USSOCOM)"),
(
"US Special Operations Command (USSOCOM)",
"US Special Operations Command (USSOCOM)",
),
("US Strategic Command (USSTRATCOM)", "US Strategic Command (USSTRATCOM)"),
("US Transportation Command (USTRANSCOM)", "US Transportation Command (USTRANSCOM)"),
(
"US Transportation Command (USTRANSCOM)",
"US Transportation Command (USTRANSCOM)",
),
("Washington Headquarters Services", "Washington Headquarters Services"),
]

View File

@@ -24,7 +24,7 @@ class NewlineListField(Field):
def _value(self):
if isinstance(self.data, list):
return '\n'.join(self.data)
return "\n".join(self.data)
elif self.data:
return self.data
else:
@@ -46,8 +46,5 @@ class NewlineListField(Field):
class SelectField(SelectField_):
def __init__(self, *args, **kwargs):
render_kw = kwargs.get("render_kw", {})
kwargs["render_kw"] = {
**render_kw,
"required": False
}
kwargs["render_kw"] = {**render_kw, "required": False}
super().__init__(*args, **kwargs)

View File

@@ -26,6 +26,7 @@ TREASURY_CODE_REGEX = re.compile(r"^0*([1-9]{4}|[1-9]{6})$")
BA_CODE_REGEX = re.compile(r"^0*[1-9]{2}\w?$")
def suggest_pe_id(pe_id):
suggestion = pe_id
match = PE_REGEX.match(pe_id)
@@ -94,19 +95,26 @@ class BaseFinancialForm(ValidatedForm):
task_order_number = StringField(
"Task Order Number associated with this request",
description="Include the original Task Order number (including the 000X at the end). Do not include any modification numbers. Note that there may be a lag between approving a task order and when it becomes available in our system.",
validators=[Required()]
validators=[Required()],
)
uii_ids = NewlineListField(
"Unique Item Identifier (UII)s related to your application(s) if you already have them",
validators=[Required()]
validators=[Required()],
)
pe_id = StringField("Program Element (PE) Number related to your request", validators=[Required()])
pe_id = StringField(
"Program Element (PE) Number related to your request", validators=[Required()]
)
treasury_code = StringField("Program Treasury Code", validators=[Required(), Regexp(TREASURY_CODE_REGEX)])
treasury_code = StringField(
"Program Treasury Code", validators=[Required(), Regexp(TREASURY_CODE_REGEX)]
)
ba_code = StringField("Program Budget Activity (BA) Code", validators=[Required(), Regexp(BA_CODE_REGEX)])
ba_code = StringField(
"Program Budget Activity (BA) Code",
validators=[Required(), Regexp(BA_CODE_REGEX)],
)
fname_co = StringField("Contracting Officer First Name", validators=[Required()])
lname_co = StringField("Contracting Officer Last Name", validators=[Required()])
@@ -160,7 +168,7 @@ class ExtendedFinancialForm(BaseFinancialForm):
("OTHER", "Other"),
],
validators=[Required()],
render_kw={"required": False}
render_kw={"required": False},
)
funding_type_other = StringField("If other, please specify")
@@ -169,40 +177,40 @@ class ExtendedFinancialForm(BaseFinancialForm):
"<dl><dt>CLIN 0001</dt> - <dd>Unclassified IaaS and PaaS Amount</dd></dl>",
validators=[Required()],
description="Review your task order document, the amounts for each CLIN must match exactly here",
filters=[number_to_int]
filters=[number_to_int],
)
clin_0003 = StringField(
"<dl><dt>CLIN 0003</dt> - <dd>Unclassified Cloud Support Package</dd></dl>",
validators=[Required()],
description="Review your task order document, the amounts for each CLIN must match exactly here",
filters=[number_to_int]
filters=[number_to_int],
)
clin_1001 = StringField(
"<dl><dt>CLIN 1001</dt> - <dd>Unclassified IaaS and PaaS Amount <br> OPTION PERIOD 1</dd></dl>",
validators=[Required()],
description="Review your task order document, the amounts for each CLIN must match exactly here",
filters=[number_to_int]
filters=[number_to_int],
)
clin_1003 = StringField(
"<dl><dt>CLIN 1003</dt> - <dd>Unclassified Cloud Support Package <br> OPTION PERIOD 1</dd></dl>",
validators=[Required()],
description="Review your task order document, the amounts for each CLIN must match exactly here",
filters=[number_to_int]
filters=[number_to_int],
)
clin_2001 = StringField(
"<dl><dt>CLIN 2001</dt> - <dd>Unclassified IaaS and PaaS Amount <br> OPTION PERIOD 2</dd></dl>",
validators=[Required()],
description="Review your task order document, the amounts for each CLIN must match exactly here",
filters=[number_to_int]
filters=[number_to_int],
)
clin_2003 = StringField(
"<dl><dt>CLIN 2003</dt> - <dd>Unclassified Cloud Support Package <br> OPTION PERIOD 2</dd></dl>",
validators=[Required()],
description="Review your task order document, the amounts for each CLIN must match exactly here",
filters=[number_to_int]
filters=[number_to_int],
)

View File

@@ -16,9 +16,11 @@ class OrgForm(ValidatedForm):
email_request = EmailField("E-mail Address", validators=[Required(), Email()])
phone_number = TelField("Phone Number",
description='Enter a 10-digit phone number',
validators=[Required(), PhoneNumber()])
phone_number = TelField(
"Phone Number",
description="Enter a 10-digit phone number",
validators=[Required(), PhoneNumber()],
)
service_branch = SelectField(
"Service Branch or Agency",
@@ -49,7 +51,7 @@ class OrgForm(ValidatedForm):
date_latest_training = DateField(
"Latest Information Assurance (IA) Training Completion Date",
description="To complete the training, you can find it in <a class=\"icon-link\" href=\"https://iatraining.disa.mil/eta/disa_cac2018/launchPage.htm\" target=\"_blank\">Information Assurance Cyber Awareness Challange</a> website.",
description='To complete the training, you can find it in <a class="icon-link" href="https://iatraining.disa.mil/eta/disa_cac2018/launchPage.htm" target="_blank">Information Assurance Cyber Awareness Challange</a> website.',
validators=[
Required(),
DateRange(

View File

@@ -6,7 +6,6 @@ from .validators import IsNumber
class POCForm(ValidatedForm):
def validate(self, *args, **kwargs):
if self.am_poc.data:
# Prepend Optional validators so that the validation chain
@@ -18,11 +17,10 @@ class POCForm(ValidatedForm):
return super().validate(*args, **kwargs)
am_poc = BooleanField(
"I am the Workspace Owner",
default=False,
false_values=(False, "false", "False", "no", "")
false_values=(False, "false", "False", "no", ""),
)
fname_poc = StringField("First Name", validators=[Required()])

View File

@@ -4,22 +4,26 @@ from wtforms.validators import Optional, Required
from .fields import DateField, SelectField
from .forms import ValidatedForm
from .data import SERVICE_BRANCHES, ASSISTANCE_ORG_TYPES, DATA_TRANSFER_AMOUNTS, COMPLETION_DATE_RANGES
from .data import (
SERVICE_BRANCHES,
ASSISTANCE_ORG_TYPES,
DATA_TRANSFER_AMOUNTS,
COMPLETION_DATE_RANGES,
)
from atst.domain.requests import Requests
class RequestForm(ValidatedForm):
def validate(self, *args, **kwargs):
if self.jedi_migration.data == 'no':
if self.jedi_migration.data == "no":
self.rationalization_software_systems.validators.append(Optional())
self.technical_support_team.validators.append(Optional())
self.organization_providing_assistance.validators.append(Optional())
self.engineering_assessment.validators.append(Optional())
self.data_transfers.validators.append(Optional())
self.expected_completion_date.validators.append(Optional())
elif self.jedi_migration.data == 'yes':
if self.technical_support_team.data == 'no':
elif self.jedi_migration.data == "yes":
if self.technical_support_team.data == "no":
self.organization_providing_assistance.validators.append(Optional())
self.cloud_native.validators.append(Optional())
@@ -39,16 +43,15 @@ class RequestForm(ValidatedForm):
"DoD Component",
description="Identify the DoD component that is requesting access to the JEDI Cloud",
choices=SERVICE_BRANCHES,
validators=[Required()]
validators=[Required()],
)
jedi_usage = TextAreaField(
"JEDI Usage",
description="Your answer will help us provide tangible examples to DoD leadership how and why commercial cloud resources are accelerating the Department's missions",
validators=[Required()]
validators=[Required()],
)
# Details of Use: Cloud Readiness
num_software_systems = IntegerField(
"Number of Software Systems",
@@ -121,16 +124,15 @@ class RequestForm(ValidatedForm):
average_daily_traffic = IntegerField(
"Average Daily Traffic (Number of Requests)",
description="What is the average daily traffic you expect the systems under this cloud contract to use?"
description="What is the average daily traffic you expect the systems under this cloud contract to use?",
)
average_daily_traffic_gb = IntegerField(
"Average Daily Traffic (GB)",
description="What is the average daily traffic you expect the systems under this cloud contract to use?"
description="What is the average daily traffic you expect the systems under this cloud contract to use?",
)
start_date = DateField(
description="When do you expect to start using the JEDI Cloud (not for billing purposes)?",
validators=[
Required()]
validators=[Required()],
)

View File

@@ -60,5 +60,3 @@ def ListItemRequired(message="Please provide at least one.", empty_values=("", N
raise ValidationError(message)
return _list_item_required

View File

@@ -2,6 +2,12 @@ from sqlalchemy import Column, func, TIMESTAMP
class TimestampsMixin(object):
time_created = Column(TIMESTAMP(timezone=True), nullable=False, server_default=func.now())
time_updated = Column(TIMESTAMP(timezone=True), nullable=False, server_default=func.now(), onupdate=func.current_timestamp())
time_created = Column(
TIMESTAMP(timezone=True), nullable=False, server_default=func.now()
)
time_updated = Column(
TIMESTAMP(timezone=True),
nullable=False,
server_default=func.now(),
onupdate=func.current_timestamp(),
)

View File

@@ -4,6 +4,7 @@ from sqlalchemy import Column, Integer, String, Enum as SQLAEnum
from atst.models import Base
class Source(Enum):
MANUAL = "Manual"
EDA = "eda"

View File

@@ -25,21 +25,21 @@ def styleguide():
return render_template("styleguide.html")
@bp.route('/<path:path>')
@bp.route("/<path:path>")
def catch_all(path):
return render_template("{}.html".format(path))
def _make_authentication_context():
return AuthenticationContext(
crl_cache=app.crl_cache,
auth_status=request.environ.get("HTTP_X_SSL_CLIENT_VERIFY"),
sdn=request.environ.get("HTTP_X_SSL_CLIENT_S_DN"),
cert=request.environ.get("HTTP_X_SSL_CLIENT_CERT")
crl_cache=app.crl_cache,
auth_status=request.environ.get("HTTP_X_SSL_CLIENT_VERIFY"),
sdn=request.environ.get("HTTP_X_SSL_CLIENT_S_DN"),
cert=request.environ.get("HTTP_X_SSL_CLIENT_CERT"),
)
@bp.route('/login-redirect')
@bp.route("/login-redirect")
def login_redirect():
auth_context = _make_authentication_context()
auth_context.authenticate()
@@ -53,7 +53,7 @@ def login_redirect():
def _is_valid_certificate(request):
cert = request.environ.get('HTTP_X_SSL_CLIENT_CERT')
cert = request.environ.get("HTTP_X_SSL_CLIENT_CERT")
if cert:
result = app.crl_validator.validate(cert.encode())
return result

View File

@@ -10,45 +10,46 @@ _DEV_USERS = {
"first_name": "Sam",
"last_name": "Seeceepio",
"atat_role_name": "ccpo",
"email": "sam@test.com"
"email": "sam@test.com",
},
"amanda": {
"dod_id": "2345678901",
"first_name": "Amanda",
"last_name": "Adamson",
"atat_role_name": "default",
"email": "amanda@test.com"
"email": "amanda@test.com",
},
"brandon": {
"dod_id": "3456789012",
"first_name": "Brandon",
"last_name": "Buchannan",
"atat_role_name": "default",
"email": "brandon@test.com"
"email": "brandon@test.com",
},
"christina": {
"dod_id": "4567890123",
"first_name": "Christina",
"last_name": "Collins",
"atat_role_name": "default",
"email": "christina@test.com"
"email": "christina@test.com",
},
"dominick": {
"dod_id": "5678901234",
"first_name": "Dominick",
"last_name": "Domingo",
"atat_role_name": "default",
"email": "dominick@test.com"
"email": "dominick@test.com",
},
"erica": {
"dod_id": "6789012345",
"first_name": "Erica",
"last_name": "Eichner",
"atat_role_name": "default",
"email": "erica@test.com"
"email": "erica@test.com",
},
}
@bp.route("/login-dev")
def login_dev():
role = request.args.get("username", "amanda")
@@ -58,7 +59,7 @@ def login_dev():
atat_role_name=user_data["atat_role_name"],
first_name=user_data["first_name"],
last_name=user_data["last_name"],
email=user_data["email"]
email=user_data["email"],
)
session["user_id"] = user.id

View File

@@ -11,11 +11,10 @@ def make_error_pages(app):
app.logger.error(e.message)
return render_template("not_found.html"), 404
@app.errorhandler(exceptions.UnauthenticatedError)
# pylint: disable=unused-variable
def unauthorized(e):
app.logger.error(e.message)
return render_template('unauthenticated.html'), 401
return render_template("unauthenticated.html"), 401
return app

View File

@@ -8,6 +8,7 @@ from . import index
from . import requests_form
from . import financial_verification
@requests_bp.context_processor
def annual_spend_threshold():
return { "annual_spend_threshold": Requests.ANNUAL_SPEND_THRESHOLD }
return {"annual_spend_threshold": Requests.ANNUAL_SPEND_THRESHOLD}

View File

@@ -43,7 +43,13 @@ def update_financial_verification(request_id):
if valid:
Requests.submit_financial_verification(request_id)
new_workspace = Requests.approve_and_create_workspace(updated_request)
return redirect(url_for("workspaces.workspace_projects", workspace_id=new_workspace.id, newWorkspace=True))
return redirect(
url_for(
"workspaces.workspace_projects",
workspace_id=new_workspace.id,
newWorkspace=True,
)
)
else:
form.reset()

View File

@@ -24,15 +24,18 @@ def map_request(request):
"date": time_created.format("M/DD/YYYY"),
"full_name": request.creator.full_name,
"annual_usage": annual_usage,
"edit_link": verify_url if Requests.is_pending_financial_verification(
request
) else update_url,
"edit_link": verify_url
if Requests.is_pending_financial_verification(request)
else update_url,
}
@requests_bp.route("/requests", methods=["GET"])
def requests_index():
if Permissions.REVIEW_AND_APPROVE_JEDI_WORKSPACE_REQUEST in g.current_user.atat_permissions:
if (
Permissions.REVIEW_AND_APPROVE_JEDI_WORKSPACE_REQUEST
in g.current_user.atat_permissions
):
return _ccpo_view()
else:

View File

@@ -129,7 +129,9 @@ class JEDIRequestFlow(object):
if section == "primary_poc":
if data.get("am_poc", False):
try:
request_user_info = self.existing_request.body.get("information_about_you", {})
request_user_info = self.existing_request.body.get(
"information_about_you", {}
)
except AttributeError:
request_user_info = {}

View File

@@ -6,7 +6,12 @@ from atst.routes.requests.jedi_request_flow import JEDIRequestFlow
from atst.models.permissions import Permissions
from atst.models.request_status_event import RequestStatus
from atst.domain.exceptions import UnauthorizedError
from atst.forms.data import SERVICE_BRANCHES, ASSISTANCE_ORG_TYPES, DATA_TRANSFER_AMOUNTS, COMPLETION_DATE_RANGES
from atst.forms.data import (
SERVICE_BRANCHES,
ASSISTANCE_ORG_TYPES,
DATA_TRANSFER_AMOUNTS,
COMPLETION_DATE_RANGES,
)
@requests_bp.route("/requests/new/<int:screen>", methods=["GET"])
@@ -27,6 +32,7 @@ def requests_form_new(screen):
completion_date_ranges=COMPLETION_DATE_RANGES,
)
@requests_bp.route(
"/requests/new/<int:screen>", methods=["GET"], defaults={"request_id": None}
)
@@ -36,7 +42,9 @@ def requests_form_update(screen=1, request_id=None):
_check_can_view_request(request_id)
request = Requests.get(request_id) if request_id is not None else None
jedi_flow = JEDIRequestFlow(screen, request=request, request_id=request_id, current_user=g.current_user)
jedi_flow = JEDIRequestFlow(
screen, request=request, request_id=request_id, current_user=g.current_user
)
return render_template(
"requests/screen-%d.html" % int(screen),
@@ -114,10 +122,12 @@ def requests_submit(request_id=None):
# TODO: generalize this, along with other authorizations, into a policy-pattern
# for authorization in the application
def _check_can_view_request(request_id):
if Permissions.REVIEW_AND_APPROVE_JEDI_WORKSPACE_REQUEST in g.current_user.atat_permissions:
if (
Permissions.REVIEW_AND_APPROVE_JEDI_WORKSPACE_REQUEST
in g.current_user.atat_permissions
):
pass
elif Requests.exists(request_id, g.current_user):
pass
else:
raise UnauthorizedError(g.current_user, "view request {}".format(request_id))