Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 41 additions & 53 deletions efile_app/efile/api/auth_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,45 +21,31 @@ class AuthAPIViews(APIResponseMixin):
"""API views for authentication"""

@staticmethod
def get_state_from_request(request):
"""Extract state from request URL or parameters"""
# Try to get state from query parameters first
state = request.GET.get("state")
if state:
return state.lower()

# Try to extract from URL path (e.g., /jurisdictions/illinois/)
path = request.path
if "/jurisdictions/" in path:
path_parts = path.split("/jurisdictions/")
if len(path_parts) > 1:
state_part = path_parts[1].split("/")[0]
if state_part:
return state_part.lower()

# Default to Illinois if no state found
return "illinois"
def get_jurisdiction_from_request(request):
"""Extract jurisdiction from request URL or parameters"""
# Try to get jurisdiction from query parameters first
jurisdiction = request.GET.get("jurisdiction")
if jurisdiction:
return jurisdiction.lower()
return None

@staticmethod
def get_tyler_token(request, state=None):
def get_tyler_token(request, jurisdiction=None):
"""Helper method to retrieve Tyler token from various sources"""
if state is None:
state = AuthAPIViews.get_state_from_request(request)
if jurisdiction is None:
jurisdiction = AuthAPIViews.get_jurisdiction_from_request(request)

auth_tokens = request.session.get("auth_tokens", {})
logger.debug(f"Auth tokens in session: {auth_tokens}")

# Try different Tyler token key formats
tyler_token = (
auth_tokens.get(f"TYLER-TOKEN-{state.upper()}")
or auth_tokens.get(f"tyler_token_{state}")
or auth_tokens.get(f"tyler-token-{state}")
auth_tokens.get(f"TYLER-TOKEN-{jurisdiction.upper()}")
or auth_tokens.get(f"tyler_token_{jurisdiction}")
or auth_tokens.get(f"tyler-token-{jurisdiction}")
)

if tyler_token:
return tyler_token

return None
return tyler_token

@staticmethod
@require_http_methods(["POST"])
Expand Down Expand Up @@ -107,25 +93,25 @@ def user_profile(request):
"""Get current user profile from external Suffolk eFile API"""
try:
try:
# Get state and Tyler token dynamically
state = AuthAPIViews.get_state_from_request(request)
tyler_token = AuthAPIViews.get_tyler_token(request, state)
# Get jurisdiction and Tyler token dynamically
jurisdiction = AuthAPIViews.get_jurisdiction_from_request(request)
tyler_token = AuthAPIViews.get_tyler_token(request, jurisdiction)
api_key = getattr(settings, "SUFFOLK_EFILE_API_KEY", None)

headers = {
"Content-Type": "application/json",
"User-Agent": f"{state.title()}-eFile-Client/1.0",
"User-Agent": f"{jurisdiction.title()}-eFile-Client/1.0",
"X-API-Key": api_key if api_key else "",
}

# Add Tyler token if available
if tyler_token:
headers[f"tyler-token-{state}"] = tyler_token
headers[f"tyler-token-{jurisdiction}"] = tyler_token
else:
# Log that no token was found for debugging
logger.info("No Tyler token found for state '%s' in Suffolk eFile API request", state)
logger.info("No Tyler token found for state '%s' in Suffolk eFile API request", jurisdiction)

url = f"{settings.EFSP_URL}/jurisdictions/{state}/firmattorneyservice/firm"
url = f"{settings.EFSP_URL}/jurisdictions/{jurisdiction}/firmattorneyservice/firm"
logger.debug("GET %s header keys=%s", url, list(headers.keys()))
api_response = requests.get(url, headers=headers, timeout=10)
logger.debug(
Expand Down Expand Up @@ -293,11 +279,11 @@ def external_auth(request):
return AuthAPIViews.error_response("Username and password required")

# Authenticate with Suffolk eFile API
state = AuthAPIViews.get_state_from_request(request)
jurisdiction = AuthAPIViews.get_jurisdiction_from_request(request)
auth_response = requests.post(
f"{settings.EFSP_URL}/jurisdictions/{state}/auth/login",
f"{settings.EFSP_URL}/jurisdictions/{jurisdiction}/auth/login",
json={"username": username, "password": password},
headers={"Content-Type": "application/json", "User-Agent": f"{state.title()}-eFile-Client/1.0"},
headers={"Content-Type": "application/json", "User-Agent": f"{jurisdiction.title()}-eFile-Client/1.0"},
)

if auth_response.status_code == 200:
Expand All @@ -307,17 +293,17 @@ def external_auth(request):
request.session["auth_tokens"] = {
"access_token": auth_data.get("access_token"),
"refresh_token": auth_data.get("refresh_token"),
f"tyler_token_{state}": auth_data.get(f"tyler_token_{state}"),
f"tyler_token_{jurisdiction}": auth_data.get(f"tyler_token_{jurisdiction}"),
"expires_in": auth_data.get("expires_in"),
"state": state, # Store the state for future reference
"state": jurisdiction, # Store the state for future reference
}

return AuthAPIViews.success_response(
{
"authenticated": True,
"user": auth_data.get("user", {}),
"state": state,
"has_tyler_token": f"tyler_token_{state}" in auth_data,
"state": jurisdiction,
"has_tyler_token": f"tyler_token_{jurisdiction}" in auth_data,
},
"External authentication successful",
)
Expand Down Expand Up @@ -364,12 +350,14 @@ def external_profile(request):
def tyler_token(request):
"""Get Tyler token and API key for external form submissions"""
try:
# Get state and Tyler token dynamically
state = AuthAPIViews.get_state_from_request(request)
tyler_token = AuthAPIViews.get_tyler_token(request, state)
# Get jurisdiction and Tyler token dynamically
jurisdiction = AuthAPIViews.get_jurisdiction_from_request(request)
tyler_token = AuthAPIViews.get_tyler_token(request, jurisdiction)
api_key = getattr(settings, "SUFFOLK_EFILE_API_KEY", None)

return AuthAPIViews.success_response({"tyler_token": tyler_token, "api_key": api_key, "state": state})
return AuthAPIViews.success_response(
{"tyler_token": tyler_token, "api_key": api_key, "state": jurisdiction}
)
except Exception as e:
return AuthAPIViews.error_response(f"Error: {str(e)}")

Expand All @@ -378,28 +366,28 @@ def tyler_token(request):
def payment_accounts(request):
"""Get payment accounts from Suffolk eFile API with proper authentication"""
try:
# Get state and Tyler token dynamically
state = AuthAPIViews.get_state_from_request(request)
tyler_token = AuthAPIViews.get_tyler_token(request, state)
# Get jurisdiction and Tyler token dynamically
jurisdiction = AuthAPIViews.get_jurisdiction_from_request(request)
tyler_token = AuthAPIViews.get_tyler_token(request, jurisdiction)
api_key = getattr(settings, "SUFFOLK_EFILE_API_KEY", None)

headers = {
"Content-Type": "application/json",
"User-Agent": f"{state.title()}-eFile-Client/1.0",
"User-Agent": f"{jurisdiction.title()}-eFile-Client/1.0",
"X-API-Key": api_key if api_key else "",
}

# Add Tyler token if available
if tyler_token:
headers[f"tyler-token-{state}"] = tyler_token
headers[f"tyler-token-{jurisdiction}"] = tyler_token
else:
# Log that no token was found for debugging
logger.info(
"No Tyler token found for state '%s' in Suffolk eFile payment accounts request",
state,
jurisdiction,
)

url = f"{settings.EFSP_URL}/jurisdictions/{state}/payments/payment-accounts/"
url = f"{settings.EFSP_URL}/jurisdictions/{jurisdiction}/payments/payment-accounts/"
logger.debug("GET %s header keys=%s", url, list(headers.keys()))
api_response = requests.get(url, headers=headers, timeout=10)
logger.debug(
Expand Down
6 changes: 3 additions & 3 deletions efile_app/efile/api/dropdown_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ def get_filing_types(request):
court_code = request.GET.get("court")
case_type_id = request.GET.get("case_type") or request.GET.get("parent") # Support both flows
case_category_id = request.GET.get("case_category")
jurisdiction = request.GET.get("jurisdiction", "illinois")
jurisdiction = request.GET.get("jurisdiction")
existing_case = request.GET.get("existing_case")

# Set initial flag based on existing_case parameter:
Expand Down Expand Up @@ -205,12 +205,12 @@ def get_courts(request):
try:
auth_tokens = get_auth_tokens(request)

jurisdiction = request.GET.get("jurisdiction", "illinois")
jurisdiction = request.GET.get("jurisdiction", "")
user_zip = request.GET.get("user_zip")
user_county = request.GET.get("user_county")

# Make API call to external jurisdiction endpoint
api_url = f"https://efile.suffolklitlab.org/jurisdictions/{jurisdiction}/codes/courts/?with_names=True"
api_url = f"{settings.EFSP_URL}/jurisdictions/{jurisdiction}/codes/courts/?with_names=True"

try:
# Make the API request with auth tokens if available
Expand Down
2 changes: 1 addition & 1 deletion efile_app/efile/context_processors.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def jurisdiction_context(request):
}

return {
"current_jurisdiction": current_jurisdiction,
"jurisdiction": current_jurisdiction,
# Returns just a subset of the keys in the config
"jurisdiction_config": config,
"available_jurisdictions": short_configs,
Expand Down
1 change: 1 addition & 0 deletions efile_app/efile/settings_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
AWS_SECRET_ACCESS_KEY = os.getenv("AWS_SECRET_ACCESS_KEY", "")
AWS_S3_BUCKET_NAME = os.getenv("AWS_S3_BUCKET_NAME", "")
AWS_S3_REGION_NAME = os.getenv("AWS_S3_REGION_NAME", "us-east-1")
AWS_S3_ENDPOINT_URL = os.getenv("AWS_S3_ENDPOINT_URL", None)

# File Upload Settings
MAX_FILE_SIZE = 10 * 1024 * 1024 # 10MB
Expand Down
20 changes: 20 additions & 0 deletions efile_app/efile/static/config/states/vermont.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

jurisdiction:
name: "Vermont eFile"
code: "vermont"
display_name: "Vermont"
icon: "fas fa-balance-scale"
api_endpoint: "/api/vermont"

# State metadata, for the address
state:
code: "VT"
name: "Vermont"
jurisdiction: "vermont"

# Inherit from base case types and customize
inherits_from: "base-case-types.yaml"

case_types:
name_change:
extends: "base_case_types.name_change"
28 changes: 27 additions & 1 deletion efile_app/efile/static/js/api-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,32 @@ class ApiUtils {
this.clearExpiredCache();
}

/**
* Get current jurisdiction from session or default to Illinois
* @returns {string} Current jurisdiction code
*/
getCurrentJurisdiction() {
// TODO(brycew): should we make a server query? Probably not necessary?
//const response = await fetch('/api/jurisdiction/current/');
//const result = await response.json();

// Try to get from jurisdiction selector first
const jurisdictionSelect = document.getElementById("jurisdictionSelect");
if (jurisdictionSelect && jurisdictionSelect.value) {
return jurisdictionSelect.value;
}

// Try to get from profile modal selector
const profileSelect = document.getElementById("profileJurisdictionSelect");
if (profileSelect && profileSelect.value) {
return profileSelect.value;
}

// Default to Illinois if nothing found
console.log("Returning illinois for current, likely shouldn't")
return "illinois";
}

getCache() {
try {
const cached = localStorage.getItem('apiResponseCache');
Expand Down Expand Up @@ -166,7 +192,7 @@ class ApiUtils {
case '500':
return new Error('Server error. Please try again later.');
default:
return new Error('An unexpected error occurred.');
return new Error(`An unexpected error occurred (${status}).`);
}
}
return error;
Expand Down
28 changes: 3 additions & 25 deletions efile_app/efile/static/js/cascading-dropdowns.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class CascadingDropdowns {

async loadCourtsWithUserContext() {
const params = {};
const currentJurisdiction = this.getCurrentJurisdiction();
const currentJurisdiction = apiUtils.getCurrentJurisdiction();

// Set the jurisdiction parameter
params.jurisdiction = currentJurisdiction;
Expand Down Expand Up @@ -83,7 +83,6 @@ class CascadingDropdowns {
} else {
console.warn("No user profile available for courts loading");
}

await this.loadDropdownData("court", "/api/dropdowns/courts/", params);
}

Expand All @@ -97,7 +96,7 @@ class CascadingDropdowns {
'<i class="fas fa-spinner fa-spin"></i> Loading your information...';
}

const response = await this.makeRequest("/api/auth/profile/");
const response = await this.makeRequest("/api/auth/profile/", {"jurisdiction": apiUtils.getCurrentJurisdiction()});

if (response.success) {
if (statusElement) {
Expand Down Expand Up @@ -207,7 +206,7 @@ class CascadingDropdowns {
let params = {};

// Always add jurisdiction
params.jurisdiction = this.getCurrentJurisdiction();
params.jurisdiction = apiUtils.getCurrentJurisdiction();

// Add additional context parameters based on the field
if (fieldId === "court") {
Expand Down Expand Up @@ -990,27 +989,6 @@ class CascadingDropdowns {
dynamicSections.innerHTML = '';
}
}

/**
* Get current jurisdiction from session or default to Illinois
* @returns {string} Current jurisdiction code
*/
getCurrentJurisdiction() {
// Try to get from jurisdiction selector first
const jurisdictionSelect = document.getElementById("jurisdictionSelect");
if (jurisdictionSelect && jurisdictionSelect.value) {
return jurisdictionSelect.value;
}

// Try to get from profile modal selector
const profileSelect = document.getElementById("profileJurisdictionSelect");
if (profileSelect && profileSelect.value) {
return profileSelect.value;
}

// Default to Illinois if nothing found
return "illinois";
}
}

// Export for module use or make globally available
Expand Down
5 changes: 3 additions & 2 deletions efile_app/efile/static/js/form-validation.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

/**
* FormValidation - Handles form validation and user interactions
* Features: Real-time validation, draft saving, submission handling, API caching
Expand Down Expand Up @@ -161,7 +162,7 @@ class FormValidation {
// Collect form data and add friendly names
const formData = this.collectFormData();
const enhancedFormData = this.addFriendlyNames(formData);

const currentJurisdiction = apiUtils.getCurrentJurisdiction();

try {
// Save case data to session via API
Expand All @@ -181,7 +182,7 @@ class FormValidation {
this.showNotification("Case data saved successfully!", "success");


window.location.replace("/upload/");
window.location.replace(`/${currentJurisdiction}/upload/`);
} else {
const error = await response.json();
console.error("Failed to save case data - Status:", response.status);
Expand Down
Loading