├── lambda ├── __init__.py ├── upload_pdf │ ├── __init__.py │ ├── requirements.txt │ ├── .env │ └── lambda_function.py └── create_officer_zip │ ├── __init__.py │ ├── tests │ ├── __init__.py │ ├── pdf │ │ ├── 2646152 │ │ └── 2646153 │ └── xlsx │ │ ├── accused.xlsx │ │ ├── investigator.xlsx │ │ └── use_of_force.xlsx │ ├── .env │ └── requirements.txt ├── cpdb ├── alias │ ├── __init__.py │ ├── tests │ │ └── __init__.py │ ├── serializers.py │ ├── utils.py │ └── constants.py ├── cms │ ├── __init__.py │ ├── tests │ │ ├── __init__.py │ │ ├── views │ │ │ └── __init__.py │ │ ├── management │ │ │ ├── __init__.py │ │ │ └── commands │ │ │ │ └── __init__.py │ │ ├── serializers │ │ │ └── __init__.py │ │ ├── files │ │ │ └── reporting.csv │ │ ├── test_factories.py │ │ └── test_utils.py │ ├── management │ │ ├── __init__.py │ │ └── commands │ │ │ └── __init__.py │ ├── migrations │ │ ├── __init__.py │ │ ├── 0012_delete_faqpage.py │ │ ├── 0006_faqpage_order.py │ │ ├── 0008_faqpage_starred.py │ │ ├── 0013_remove_report_page_model.py │ │ └── 0009_reportpage_officers.py │ ├── models │ │ ├── __init__.py │ │ └── slug_page.py │ ├── utils.py │ └── permissions.py ├── config │ ├── __init__.py │ ├── settings │ │ ├── __init__.py │ │ ├── circleci.py │ │ └── test_without_migrations.py │ ├── tests │ │ ├── __init__.py │ │ └── test_urls.py │ ├── logging_filters.py │ └── wsgi.py ├── cr │ ├── __init__.py │ ├── tests │ │ ├── __init__.py │ │ ├── views │ │ │ └── __init__.py │ │ └── serializers │ │ │ └── __init__.py │ └── serializers │ │ └── __init__.py ├── data │ ├── __init__.py │ ├── tests │ │ ├── __init__.py │ │ ├── admin │ │ │ └── __init__.py │ │ ├── utils │ │ │ └── __init__.py │ │ ├── management │ │ │ ├── __init__.py │ │ │ └── commands │ │ │ │ ├── __init__.py │ │ │ │ ├── test_cache_data.py │ │ │ │ └── test_import_cr_summary.py │ │ ├── models │ │ │ ├── __init__.py │ │ │ ├── test_officer_history.py │ │ │ ├── test_officer_badge_number.py │ │ │ ├── test_victim.py │ │ │ ├── test_complainant.py │ │ │ ├── test_involvement.py │ │ │ └── test_salary.py │ │ ├── cache_managers │ │ │ └── __init__.py │ │ └── data_sample │ │ │ ├── __init__.py │ │ │ ├── units.csv │ │ │ └── cr_summary.csv │ ├── utils │ │ ├── __init__.py │ │ ├── round.py │ │ ├── subqueries.py │ │ ├── attachment_file.py │ │ └── interpolate.py │ ├── management │ │ ├── __init__.py │ │ └── commands │ │ │ ├── __init__.py │ │ │ ├── clear_cache.py │ │ │ ├── cache_data.py │ │ │ └── fix_community_area_type.py │ ├── migrations │ │ ├── __init__.py │ │ ├── 0110_merge_20190108_0253.py │ │ ├── 0090_merge_20181129_2015.py │ │ ├── 0097_merge_20190101_2250.py │ │ ├── 0004_merge.py │ │ ├── 0008_merge.py │ │ ├── 0003_merge.py │ │ ├── 0029_merge_20180207_2137.py │ │ ├── 0028_merge_20180131_1334.py │ │ ├── 0058_merge_20180617_2214.py │ │ ├── 0060_merge_058_and_059.py │ │ ├── 0098_attachmentfile_text_content.py │ │ ├── 0112_attachmentfile_show.py │ │ ├── 0133_auto_20240716_1545.py │ │ ├── 0134_auto_20240716_1556.py │ │ ├── 0095_rename_timestamp_to_created_at.py │ │ ├── 0122_attachmentfile_is_external_ocr.py │ │ ├── 0118_attachmentfile_reprocess_text_count.py │ │ ├── 0135_add_investigating_agency_column.py │ │ ├── 0129_add_db_index_to_allegation_category.py │ │ ├── 0020_rename_field_type_to_award_type.py │ │ ├── 0036_policeunit_active.py │ │ ├── 0106_add_field_police_witnesses.py │ │ ├── 0119_add_is_extracted_summary_field_to_allegation.py │ │ ├── 0128_officer_allegations.py │ │ ├── 0019_auto_20171019_0153.py │ │ ├── 0009_officer_rank_increase_length.py │ │ ├── 0099_attachmentrequest_noti_email_sent.py │ │ ├── 0006_officer_rank_freeform.py │ │ ├── 0007_policeunit_description.py │ │ ├── 0021_officer_resignation_date.py │ │ ├── 0107_remove_area_line_area_from_allegation.py │ │ ├── 0024_allegation_is_officer_complaint.py │ │ ├── 0032_officer_middle_initial2.py │ │ ├── 0083_salary_rank_changed.py │ │ ├── 0095_attachmenrequest_bulk_objects_manager.py │ │ ├── 0085_officer_has_unique_name.py │ │ ├── 0058_allegation_old_complaint_address.py │ │ ├── 0084_attachmentrequest_added_to_foia_airtable.py │ │ ├── 0068_attachmentfile_external_id.py │ │ ├── 0027_officer_complaint_percentile.py │ │ └── 0103_remove_attachment_allegation_old_fk.py │ ├── admin │ │ └── __init__.py │ ├── models │ │ ├── race_population.py │ │ ├── attachment_ocr.py │ │ ├── officer_alias.py │ │ ├── line_area.py │ │ ├── police_witness.py │ │ ├── common.py │ │ └── attachment_narrative.py │ ├── templates │ │ └── attachment_changelist.html │ ├── validators.py │ └── cache_managers │ │ └── __init__.py ├── popup │ ├── __init__.py │ ├── tests │ │ ├── __init__.py │ │ └── test_models.py │ ├── migrations │ │ └── __init__.py │ ├── models │ │ ├── __init__.py │ │ └── popup.py │ ├── admin.py │ ├── serializers.py │ ├── factories.py │ └── views.py ├── search │ ├── urls.py │ ├── tests │ │ ├── __init__.py │ │ ├── commands │ │ │ └── __init__.py │ │ └── serializers │ │ │ └── __init__.py │ ├── management │ │ ├── __init__.py │ │ └── commands │ │ │ └── __init__.py │ ├── pagination.py │ ├── __init__.py │ ├── constants.py │ ├── indices.py │ ├── serializers │ │ ├── __init__.py │ │ ├── trr_recent_serializer.py │ │ └── lawsuit_recent_serializer.py │ └── utils.py ├── shared │ ├── __init__.py │ ├── tests │ │ └── __init__.py │ ├── browsable_api_renderder_without_form.py │ └── aws.py ├── status │ ├── __init__.py │ ├── tests │ │ ├── __init__.py │ │ └── test_views.py │ └── views.py ├── toast │ ├── __init__.py │ ├── tests │ │ ├── __init__.py │ │ └── test_models.py │ ├── migrations │ │ └── __init__.py │ ├── models │ │ ├── __init__.py │ │ └── toast.py │ ├── constants.py │ ├── factories.py │ ├── admin.py │ └── serializers.py ├── trr │ ├── __init__.py │ ├── tests │ │ ├── __init__.py │ │ ├── models │ │ │ └── __init__.py │ │ ├── views │ │ │ └── __init__.py │ │ └── serializers │ │ │ └── __init__.py │ ├── migrations │ │ ├── __init__.py │ │ ├── 0021_auto_20240610_2200.py │ │ ├── 0018_auto_20240527_1741.py │ │ ├── 0019_auto_20240610_2108.py │ │ ├── 0020_auto_20240610_2151.py │ │ ├── 0016_rename_timestamp_to_created_at.py │ │ └── 0002_alter_trr_subject_id_type.py │ ├── serializers │ │ └── __init__.py │ ├── admin.py │ └── models │ │ ├── __init__.py │ │ ├── subject_weapon.py │ │ └── charge.py ├── units │ ├── __init__.py │ ├── tests │ │ ├── __init__.py │ │ └── mixins.py │ ├── index_aliases.py │ ├── doc_types.py │ └── views.py ├── utils │ ├── __init__.py │ ├── tests │ │ ├── __init__.py │ │ └── models │ │ │ └── __init__.py │ ├── models │ │ └── __init__.py │ └── raw_query_utils.py ├── vftg │ ├── __init__.py │ ├── tests │ │ └── __init__.py │ └── views.py ├── xlsx │ ├── __init__.py │ ├── tests │ │ ├── __init__.py │ │ ├── management │ │ │ ├── __init__.py │ │ │ ├── commands │ │ │ │ └── __init__.py │ │ │ └── utils │ │ │ │ ├── __init__.py │ │ │ │ └── test_export_officer_xlsx │ │ │ │ └── csv │ │ │ │ ├── accused_8562 │ │ │ │ ├── Victim.csv │ │ │ │ ├── Beat.csv │ │ │ │ └── Police Witness.csv │ │ │ │ └── investigator_1234 │ │ │ │ ├── Victim.csv │ │ │ │ ├── Beat.csv │ │ │ │ └── Police Witness.csv │ │ └── writers │ │ │ ├── __init__.py │ │ │ ├── test_accused_xlsx_writer │ │ │ └── csv │ │ │ │ ├── empty │ │ │ │ ├── Victim.csv │ │ │ │ ├── Beat.csv │ │ │ │ ├── Allegation.csv │ │ │ │ ├── Police Witness.csv │ │ │ │ └── Coaccused Officer.csv │ │ │ │ └── accused_8562 │ │ │ │ ├── Victim.csv │ │ │ │ ├── Beat.csv │ │ │ │ ├── Police Witness.csv │ │ │ │ └── Allegation.csv │ │ │ ├── test_officer_xlsx_writer │ │ │ └── csv │ │ │ │ ├── Allegation.csv │ │ │ │ └── Officer.csv │ │ │ ├── test_investigator_xlsx_writer │ │ │ └── csv │ │ │ │ ├── empty │ │ │ │ ├── Victim.csv │ │ │ │ ├── Beat.csv │ │ │ │ ├── Allegation.csv │ │ │ │ ├── Accused Officer.csv │ │ │ │ └── Police Witness.csv │ │ │ │ └── investigator_1234 │ │ │ │ ├── Victim.csv │ │ │ │ ├── Beat.csv │ │ │ │ └── Police Witness.csv │ │ │ ├── test_documents_xlsx_writer │ │ │ └── csv │ │ │ │ ├── empty │ │ │ │ ├── Complaint Documents.csv │ │ │ │ └── Investigation Documents.csv │ │ │ │ └── documents_1 │ │ │ │ ├── Complaint Documents.csv │ │ │ │ └── Investigation Documents.csv │ │ │ └── test_use_of_force_xlsx_writer │ │ │ └── csv │ │ │ └── empty │ │ │ └── Use Of Force.csv │ ├── management │ │ ├── __init__.py │ │ └── commands │ │ │ └── __init__.py │ ├── serializers │ │ ├── __init__.py │ │ ├── victim_xlsx_serializer.py │ │ ├── area_xlsx_serializer.py │ │ └── attachment_xlsx_serializer.py │ ├── writers │ │ └── __init__.py │ └── constants.py ├── analytics │ ├── __init__.py │ ├── tests │ │ ├── __init__.py │ │ ├── management │ │ │ ├── __init__.py │ │ │ └── commands │ │ │ │ └── __init__.py │ │ ├── models │ │ │ └── __init__.py │ │ └── test_utils │ │ │ └── __init__.py │ ├── utils │ │ ├── __init__.py │ │ └── clicky_tracking.py │ ├── management │ │ ├── __init__.py │ │ └── commands │ │ │ └── __init__.py │ ├── migrations │ │ ├── __init__.py │ │ └── 0004_alter_searchtracking_query_type.py │ ├── models │ │ ├── __init__.py │ │ ├── event.py │ │ └── search_tracking.py │ ├── filters.py │ ├── serializers.py │ └── constants.py ├── app_config │ ├── __init__.py │ ├── tests │ │ ├── __init__.py │ │ └── management │ │ │ ├── __init__.py │ │ │ └── commands │ │ │ └── __init__.py │ ├── management │ │ ├── __init__.py │ │ └── commands │ │ │ ├── __init__.py │ │ │ └── create_initial_app_config.py │ ├── migrations │ │ └── __init__.py │ ├── validators │ │ ├── __init__.py │ │ └── visual_token_color_validators.py │ ├── admin │ │ ├── __init__.py │ │ ├── app_config_admin.py │ │ └── visual_token_color_admin.py │ ├── serializers │ │ ├── __init__.py │ │ └── visual_token_color_serializer.py │ ├── models │ │ ├── __init__.py │ │ └── app_config.py │ └── constants.py ├── heatmap │ ├── __init__.py │ ├── tests │ │ ├── __init__.py │ │ └── management │ │ │ ├── __init__.py │ │ │ └── commands │ │ │ └── __init__.py │ └── management │ │ ├── __init__.py │ │ └── commands │ │ └── __init__.py ├── lawsuit │ ├── __init__.py │ ├── tests │ │ ├── __init__.py │ │ ├── models │ │ │ └── __init__.py │ │ ├── importers │ │ │ └── __init__.py │ │ ├── management │ │ │ ├── __init__.py │ │ │ └── commands │ │ │ │ └── __init__.py │ │ ├── serializers │ │ │ └── __init__.py │ │ └── cache_managers │ │ │ └── __init__.py │ ├── management │ │ ├── __init__.py │ │ └── commands │ │ │ └── __init__.py │ ├── migrations │ │ ├── __init__.py │ │ ├── 0003_lawsuit_primary_cause.py │ │ ├── 0009_change_lawsuit_location_max_length.py │ │ ├── 0010_remove_lawsuit_plaintiff_unique_constraint.py │ │ ├── 0006_lawsuit_total_payments.py │ │ ├── 0002_lawsuit_point.py │ │ └── 0007_alter_officers_fields_in_lawsuits.py │ ├── cache_managers │ │ └── __init__.py │ ├── importers │ │ └── __init__.py │ ├── serializers │ │ ├── __init__.py │ │ └── top_lawsuit_serializer.py │ └── models │ │ └── __init__.py ├── officers │ ├── __init__.py │ ├── tests │ │ ├── __init__.py │ │ ├── test_indexers.py │ │ ├── views │ │ │ └── __init__.py │ │ ├── indexers │ │ │ └── __init__.py │ │ └── serializers │ │ │ └── __init__.py │ ├── serializers │ │ ├── __init__.py │ │ └── doc_serializers.py │ ├── query_helpers │ │ └── __init__.py │ ├── index_aliases.py │ └── indexers │ │ └── __init__.py ├── pinboard │ ├── __init__.py │ ├── tests │ │ ├── __init__.py │ │ ├── views │ │ │ └── __init__.py │ │ ├── serializers │ │ │ ├── __init__.py │ │ │ ├── desktop │ │ │ │ ├── __init__.py │ │ │ │ ├── admin │ │ │ │ │ └── __init__.py │ │ │ │ ├── common │ │ │ │ │ ├── __init__.py │ │ │ │ │ └── test_victim_serializer.py │ │ │ │ ├── pinned │ │ │ │ │ └── __init__.py │ │ │ │ └── relevant │ │ │ │ │ └── __init__.py │ │ │ └── mobile │ │ │ │ ├── __init__.py │ │ │ │ ├── common │ │ │ │ └── __init__.py │ │ │ │ ├── pinned │ │ │ │ └── __init__.py │ │ │ │ └── relevant │ │ │ │ └── __init__.py │ │ └── models │ │ │ └── __init__.py │ ├── migrations │ │ ├── __init__.py │ │ └── 0002_add_trrs_to_pinboard.py │ ├── serializers │ │ ├── __init__.py │ │ ├── desktop │ │ │ ├── __init__.py │ │ │ ├── admin │ │ │ │ ├── __init__.py │ │ │ │ ├── officer_serializer.py │ │ │ │ ├── trr_serializer.py │ │ │ │ └── allegation_serializer.py │ │ │ ├── pinned │ │ │ │ ├── officer_serializer.py │ │ │ │ └── __init__.py │ │ │ ├── common │ │ │ │ ├── __init__.py │ │ │ │ └── victim_serializer.py │ │ │ └── relevant │ │ │ │ ├── __init__.py │ │ │ │ ├── document_serializer.py │ │ │ │ └── allegation_serializer.py │ │ ├── mobile │ │ │ ├── __init__.py │ │ │ ├── pinned │ │ │ │ ├── officer_serializer.py │ │ │ │ └── __init__.py │ │ │ ├── common │ │ │ │ └── __init__.py │ │ │ └── relevant │ │ │ │ ├── officer_serializer.py │ │ │ │ ├── __init__.py │ │ │ │ ├── document_serializer.py │ │ │ │ └── allegation_serializer.py │ │ └── example_pinboard.py │ ├── constants.py │ └── utils.py ├── sitemap │ ├── __init__.py │ ├── sitemaps │ │ ├── __init__.py │ │ ├── trr_sitemap.py │ │ ├── unit_sitemap.py │ │ ├── officer_sitemap.py │ │ ├── allegation_sitemap.py │ │ ├── base_sitemap.py │ │ ├── attachment_sitemap.py │ │ └── static_page_sitemap.py │ └── tests │ │ ├── __init__.py │ │ └── sitemaps │ │ └── __init__.py ├── tracker │ ├── __init__.py │ ├── tests │ │ ├── __init__.py │ │ ├── management │ │ │ ├── __init__.py │ │ │ └── commands │ │ │ │ └── __init__.py │ │ ├── serializers │ │ │ └── __init__.py │ │ └── mixins.py │ ├── management │ │ ├── __init__.py │ │ └── commands │ │ │ └── __init__.py │ ├── constants.py │ └── index_aliases.py ├── twitterbot │ ├── __init__.py │ ├── models.py │ ├── tests │ │ ├── __init__.py │ │ ├── handlers │ │ │ └── __init__.py │ │ ├── utils │ │ │ └── __init__.py │ │ ├── management │ │ │ ├── __init__.py │ │ │ └── commands │ │ │ │ └── __init__.py │ │ └── mixins.py │ ├── utils │ │ ├── __init__.py │ │ ├── user_input.py │ │ └── cryptography.py │ ├── management │ │ ├── __init__.py │ │ └── commands │ │ │ ├── __init__.py │ │ │ ├── list_webhooks.py │ │ │ └── list_subscriptions.py │ ├── migrations │ │ ├── __init__.py │ │ └── 0003_auto_20171019_2145.py │ ├── models │ │ ├── twitter_bot_visit_log.py │ │ ├── respone_template.py │ │ └── __init__.py │ ├── serializers.py │ └── constants.py ├── activity_grid │ ├── __init__.py │ ├── tests │ │ ├── __init__.py │ │ ├── models │ │ │ └── __init__.py │ │ └── cache_managers │ │ │ └── __init__.py │ ├── migrations │ │ ├── __init__.py │ │ ├── 0007_activitypaircard_coaccusal_count.py │ │ └── 0002_activitycard_important.py │ ├── cache_managers │ │ ├── __init__.py │ │ └── activity_pair_card_cache_manager.py │ └── models │ │ ├── __init__.py │ │ └── activity_card.py ├── activity_log │ ├── __init__.py │ ├── tests │ │ └── __init__.py │ ├── migrations │ │ └── __init__.py │ ├── apps.py │ └── constants.py ├── authentication │ ├── __init__.py │ └── tests │ │ └── __init__.py ├── data_importer │ ├── __init__.py │ ├── tests │ │ ├── __init__.py │ │ ├── management │ │ │ └── __init__.py │ │ └── copa_crawler │ │ │ └── __init__.py │ ├── copa_crawler │ │ └── __init__.py │ └── management │ │ ├── __init__.py │ │ └── commands │ │ └── __init__.py ├── document_cloud │ ├── __init__.py │ ├── tests │ │ ├── __init__.py │ │ ├── management │ │ │ ├── __init__.py │ │ │ └── commands │ │ │ │ └── __init__.py │ │ ├── models │ │ │ └── __init__.py │ │ └── services │ │ │ └── __init__.py │ ├── management │ │ ├── __init__.py │ │ └── commands │ │ │ └── __init__.py │ ├── migrations │ │ ├── __init__.py │ │ ├── 0006_merge_20181129_2015.py │ │ ├── 0007_rename_timestamp_to_created_at.py │ │ └── 0011_documentcrawler_log_key.py │ ├── models │ │ ├── __init__.py │ │ └── document_cloud_search_query.py │ └── constants.py ├── email_service │ ├── __init__.py │ ├── tests │ │ └── __init__.py │ ├── migrations │ │ └── __init__.py │ ├── backend.py │ ├── constants.py │ └── admin.py ├── es_index │ ├── tests │ │ ├── __init__.py │ │ ├── commands │ │ │ └── __init__.py │ │ └── test_register_indexer.py │ ├── management │ │ ├── __init__.py │ │ └── commands │ │ │ ├── __init__.py │ │ │ └── rebuild_index_daily.py │ ├── constants.py │ ├── analyzers.py │ ├── utils.py │ ├── indices.py │ └── __init__.py ├── search_mobile │ ├── __init__.py │ ├── tests │ │ ├── __init__.py │ │ └── serializers │ │ │ ├── __init__.py │ │ │ └── test_trr_recent_serializer.py │ ├── apps.py │ ├── serializers │ │ ├── lawsuit_recent_serializer.py │ │ ├── trr_recent_serializer.py │ │ ├── lawsuit_serializer.py │ │ ├── officer_recent_serializer.py │ │ └── __init__.py │ └── queries.py ├── search_terms │ ├── __init__.py │ ├── tests │ │ ├── __init__.py │ │ └── views │ │ │ └── __init__.py │ ├── migrations │ │ ├── __init__.py │ │ ├── 0009_make_slug_unique.py │ │ ├── 0003_alter_nullable_description.py │ │ ├── 0007_alter_uuid.py │ │ └── 0010_change_link_to_char.py │ ├── models │ │ └── __init__.py │ ├── views.py │ └── factories.py ├── social_graph │ ├── __init__.py │ ├── tests │ │ ├── __init__.py │ │ ├── queries │ │ │ └── __init__.py │ │ ├── views │ │ │ └── __init__.py │ │ └── serializers │ │ │ ├── __init__.py │ │ │ └── test_victim_serializer.py │ ├── serializers │ │ ├── allegation_serializer.py │ │ ├── officer_serializer.py │ │ ├── victim_serializer.py │ │ └── accused_serializer.py │ └── queries │ │ └── __init__.py ├── airtable_integration │ ├── __init__.py │ ├── tests │ │ ├── __init__.py │ │ ├── services │ │ │ └── __init__.py │ │ └── management │ │ │ ├── __init__.py │ │ │ └── commands │ │ │ └── __init__.py │ ├── management │ │ ├── __init__.py │ │ └── commands │ │ │ └── __init__.py │ └── services │ │ └── __init__.py ├── package-lock.json └── data-updates │ ├── awards │ └── awards.csv │ ├── trrs │ ├── trr_main.csv │ ├── trr_statuses.csv │ ├── trr_subjects.csv │ ├── trr_subject_weapons.csv │ ├── trr_weapon_discharges.csv │ └── trr_actions_responses.csv │ ├── complaints │ ├── victims.csv │ ├── complainants.csv │ ├── cpd_witnesses.csv │ ├── investigators.csv │ ├── civilian_witnesses.csv │ ├── complaints-accused.csv │ └── complaints-complaints.csv │ ├── salaries │ └── salaries.csv │ ├── officers │ └── final-profiles.csv │ └── unit_history │ └── unit-history.csv ├── .gitsecret ├── keys │ ├── mapping.cfg │ ├── crls.d │ │ └── DIR.txt │ ├── pubring.kbx │ └── pubring.kbx~ └── paths │ └── mapping.cfg ├── docker ├── cpdpbot │ ├── VERSION │ └── requirements.txt ├── postgres │ ├── init-scripts │ │ └── create-data-folder.sh │ └── Dockerfile ├── google-cloud-sdk │ └── Dockerfile └── remote_syslog2 │ └── log_files.yml ├── ansible ├── inventory │ └── notebook ├── roles │ └── notebook │ │ ├── handlers │ │ └── main.yml │ │ ├── templates │ │ ├── pam_environment.j2 │ │ ├── jupyter_notebook_config.json.j2 │ │ ├── start_jupyter.sh.j2 │ │ └── jupyter.conf.j2 │ │ ├── tasks │ │ └── main.yml │ │ ├── defaults │ │ └── main.yml │ │ └── files │ │ ├── install-python.sh │ │ └── create-env.sh └── notebook.yml ├── .gitattributes ├── beta.env.secret ├── prod.env.secret ├── staging.env.secret ├── bin ├── build_apiary.sh ├── setup_notebook.sh ├── test.sh ├── coverage.sh └── shows_pr_since_last_deploy ├── pg-credentials.json.secret ├── kubernetes ├── secrets-beta.yml.secret ├── secrets-staging.yml.secret ├── secrets-production.yml.secret └── namespaces.yml ├── .pre-commit-config.yaml ├── requirements ├── local.txt └── test.txt ├── .coveragerc ├── setup.cfg ├── apiary ├── app_config.md ├── officer_create_zip_file.md ├── city_summary.md ├── analytic_events.md ├── pinboard_latest_retrieved.md ├── officer_request_download.md ├── officer_timeline_mini_map.md └── toast_mobile.md ├── .dockerignore └── .editorconfig /lambda/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/alias/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/cms/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/config/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/cr/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/data/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/popup/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/search/urls.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/shared/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/status/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/toast/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/trr/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/units/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/utils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/vftg/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/xlsx/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitsecret/keys/mapping.cfg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/alias/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/analytics/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/app_config/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/cms/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/cr/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/data/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/data/utils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/heatmap/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/lawsuit/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/officers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/pinboard/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/popup/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/sitemap/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/toast/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/tracker/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/trr/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/twitterbot/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/twitterbot/models.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/units/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/utils/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/vftg/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/activity_grid/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/activity_log/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/analytics/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/analytics/utils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/app_config/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/authentication/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/cms/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/cms/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/cms/tests/views/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/config/settings/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/config/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/cr/serializers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/cr/tests/views/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/data/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/data/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/data/tests/admin/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/data/tests/utils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/data_importer/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/document_cloud/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/email_service/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/es_index/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/heatmap/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/lawsuit/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/officers/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/pinboard/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/popup/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/search/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/search_mobile/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/search_terms/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/shared/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/sitemap/sitemaps/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/sitemap/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/social_graph/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/status/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/toast/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/tracker/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/trr/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/trr/serializers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/trr/tests/models/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/trr/tests/views/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/twitterbot/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/twitterbot/utils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/utils/models/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/xlsx/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/xlsx/serializers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/xlsx/writers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docker/cpdpbot/VERSION: -------------------------------------------------------------------------------- 1 | 0.1.2 2 | -------------------------------------------------------------------------------- /lambda/upload_pdf/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/activity_grid/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/activity_log/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/airtable_integration/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/analytics/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/analytics/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/app_config/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/app_config/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/authentication/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/cms/tests/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/cms/tests/serializers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/cr/tests/serializers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/data/tests/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/data/tests/models/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/data_importer/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/document_cloud/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/email_service/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/es_index/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/heatmap/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/lawsuit/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/lawsuit/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/lawsuit/tests/models/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/officers/serializers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/officers/tests/test_indexers.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/officers/tests/views/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/pinboard/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/pinboard/serializers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/pinboard/tests/views/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/search/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/search/tests/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/search_mobile/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/search_terms/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/social_graph/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/tracker/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/trr/tests/serializers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/twitterbot/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/twitterbot/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/utils/tests/models/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/writers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lambda/create_officer_zip/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lambda/upload_pdf/requirements.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitsecret/keys/crls.d/DIR.txt: -------------------------------------------------------------------------------- 1 | v:1: 2 | -------------------------------------------------------------------------------- /cpdb/activity_grid/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/activity_grid/tests/models/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/activity_log/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/airtable_integration/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/analytics/tests/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/analytics/tests/models/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/analytics/tests/test_utils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/cms/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/data/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/data/tests/cache_managers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/data/tests/data_sample/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/data_importer/copa_crawler/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/data_importer/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/document_cloud/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/document_cloud/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/email_service/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/es_index/tests/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/heatmap/tests/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/lawsuit/cache_managers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/lawsuit/tests/importers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/lawsuit/tests/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/lawsuit/tests/serializers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/officers/query_helpers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/officers/tests/indexers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/officers/tests/serializers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/pinboard/tests/serializers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/search/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/search/tests/serializers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/search_terms/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/search_terms/tests/views/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/sitemap/tests/sitemaps/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/social_graph/tests/queries/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/social_graph/tests/views/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/tracker/tests/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/tracker/tests/serializers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/twitterbot/tests/handlers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/twitterbot/tests/utils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/xlsx/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lambda/create_officer_zip/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/activity_grid/cache_managers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/airtable_integration/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/airtable_integration/services/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/analytics/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/app_config/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/app_config/tests/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/cms/tests/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/data/tests/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/data_importer/tests/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/document_cloud/tests/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/document_cloud/tests/models/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/document_cloud/tests/services/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/es_index/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/heatmap/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/lawsuit/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/lawsuit/tests/cache_managers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/officers/serializers/doc_serializers.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/pinboard/serializers/desktop/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/pinboard/serializers/mobile/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/search_mobile/tests/serializers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/social_graph/tests/serializers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/tracker/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/twitterbot/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/twitterbot/tests/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/management/utils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/activity_grid/tests/cache_managers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/airtable_integration/tests/services/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/analytics/tests/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/app_config/tests/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/data_importer/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/data_importer/tests/copa_crawler/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/document_cloud/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/heatmap/tests/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/lawsuit/tests/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/pinboard/serializers/desktop/admin/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/pinboard/tests/serializers/desktop/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/pinboard/tests/serializers/mobile/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/tracker/constants.py: -------------------------------------------------------------------------------- 1 | TAG_MAX_LENGTH = 20 2 | -------------------------------------------------------------------------------- /cpdb/tracker/tests/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/twitterbot/tests/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lambda/upload_pdf/.env: -------------------------------------------------------------------------------- 1 | FUNCTION_NAME=uploadPdf 2 | -------------------------------------------------------------------------------- /ansible/inventory/notebook: -------------------------------------------------------------------------------- 1 | [notebook] 2 | 52.230.80.72 3 | -------------------------------------------------------------------------------- /cpdb/airtable_integration/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/airtable_integration/tests/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/document_cloud/tests/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/pinboard/tests/serializers/desktop/admin/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/pinboard/tests/serializers/desktop/common/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/pinboard/tests/serializers/desktop/pinned/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/pinboard/tests/serializers/mobile/common/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/pinboard/tests/serializers/mobile/pinned/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/social_graph/serializers/allegation_serializer.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/airtable_integration/tests/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "lockfileVersion": 1 3 | } 4 | -------------------------------------------------------------------------------- /cpdb/pinboard/tests/serializers/desktop/relevant/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cpdb/pinboard/tests/serializers/mobile/relevant/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lambda/create_officer_zip/.env: -------------------------------------------------------------------------------- 1 | FUNCTION_NAME=createOfficerZipFile 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | cpdb/data-updates/**/*.csv filter=lfs diff=lfs merge=lfs -text 2 | -------------------------------------------------------------------------------- /beta.env.secret: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/invinst/CPDBv2_backend/HEAD/beta.env.secret -------------------------------------------------------------------------------- /cpdb/popup/models/__init__.py: -------------------------------------------------------------------------------- 1 | from .popup import Popup 2 | 3 | __all__ = ['Popup'] 4 | -------------------------------------------------------------------------------- /cpdb/toast/models/__init__.py: -------------------------------------------------------------------------------- 1 | from .toast import Toast 2 | 3 | __all__ = ['Toast'] 4 | -------------------------------------------------------------------------------- /lambda/create_officer_zip/requirements.txt: -------------------------------------------------------------------------------- 1 | zipstream==1.1.4 2 | smart_open==1.7.1 3 | -------------------------------------------------------------------------------- /prod.env.secret: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/invinst/CPDBv2_backend/HEAD/prod.env.secret -------------------------------------------------------------------------------- /cpdb/pinboard/constants.py: -------------------------------------------------------------------------------- 1 | PINBOARD_TITLE_DUPLICATE_PATTERN = '(.*) copy(?: (\d+))?$' 2 | -------------------------------------------------------------------------------- /cpdb/app_config/validators/__init__.py: -------------------------------------------------------------------------------- 1 | from .visual_token_color_validators import * # NOQA 2 | -------------------------------------------------------------------------------- /cpdb/cms/models/__init__.py: -------------------------------------------------------------------------------- 1 | from .slug_page import SlugPage 2 | 3 | __all__ = ['SlugPage'] 4 | -------------------------------------------------------------------------------- /staging.env.secret: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/invinst/CPDBv2_backend/HEAD/staging.env.secret -------------------------------------------------------------------------------- /bin/build_apiary.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | hercule apiary/apiary.md -o apiary.apib && echo "Done" 3 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/writers/test_accused_xlsx_writer/csv/empty/Victim.csv: -------------------------------------------------------------------------------- 1 | crid,gender,race,birth_year 2 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/writers/test_officer_xlsx_writer/csv/Allegation.csv: -------------------------------------------------------------------------------- 1 | crid,summary 2 | 123456,Heaven 3 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/writers/test_investigator_xlsx_writer/csv/empty/Victim.csv: -------------------------------------------------------------------------------- 1 | crid,gender,race,birth_year 2 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/writers/test_officer_xlsx_writer/csv/Officer.csv: -------------------------------------------------------------------------------- 1 | name,gender 2 | Jerome Finnigan,Male 3 | -------------------------------------------------------------------------------- /.gitsecret/keys/pubring.kbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/invinst/CPDBv2_backend/HEAD/.gitsecret/keys/pubring.kbx -------------------------------------------------------------------------------- /cpdb/twitterbot/utils/user_input.py: -------------------------------------------------------------------------------- 1 | def get_user_input(msg): # pragma: no cover 2 | return input(msg) 3 | -------------------------------------------------------------------------------- /pg-credentials.json.secret: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/invinst/CPDBv2_backend/HEAD/pg-credentials.json.secret -------------------------------------------------------------------------------- /.gitsecret/keys/pubring.kbx~: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/invinst/CPDBv2_backend/HEAD/.gitsecret/keys/pubring.kbx~ -------------------------------------------------------------------------------- /cpdb/data/tests/data_sample/units.csv: -------------------------------------------------------------------------------- 1 | Unit No.,Unit Description,Status 2 | 000,AREA 0,Y 3 | 001,DISTRICT 001,Y 4 | -------------------------------------------------------------------------------- /ansible/roles/notebook/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: reload nginx 4 | service: name=nginx state=reloaded 5 | -------------------------------------------------------------------------------- /docker/postgres/init-scripts/create-data-folder.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | mkdir -p $PGDATA 4 | chown postgres $PGDATA 5 | -------------------------------------------------------------------------------- /cpdb/data/admin/__init__.py: -------------------------------------------------------------------------------- 1 | from .attachment_request_admin import * # NOQA 2 | from .attachment_file_admin import * # NOQA 3 | -------------------------------------------------------------------------------- /cpdb/data/tests/data_sample/cr_summary.csv: -------------------------------------------------------------------------------- 1 | crid,summary 2 | 001,"Summary Text 01 is here" 3 | 002,"Summary Text 02 is here" 4 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/writers/test_documents_xlsx_writer/csv/empty/Complaint Documents.csv: -------------------------------------------------------------------------------- 1 | title,url,date_discovered,text_content 2 | -------------------------------------------------------------------------------- /kubernetes/secrets-beta.yml.secret: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/invinst/CPDBv2_backend/HEAD/kubernetes/secrets-beta.yml.secret -------------------------------------------------------------------------------- /ansible/roles/notebook/templates/pam_environment.j2: -------------------------------------------------------------------------------- 1 | NOTEBOOK_DB_PASSWORD={{notebook_db_password}} 2 | NOTEBOOK_DB_USER=notebook 3 | -------------------------------------------------------------------------------- /cpdb/units/index_aliases.py: -------------------------------------------------------------------------------- 1 | from es_index.index_aliases import IndexAlias 2 | 3 | 4 | units_index_alias = IndexAlias('units') 5 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/writers/test_accused_xlsx_writer/csv/empty/Beat.csv: -------------------------------------------------------------------------------- 1 | name,area_type,median_income,commander,alderman,police_hq 2 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/writers/test_documents_xlsx_writer/csv/empty/Investigation Documents.csv: -------------------------------------------------------------------------------- 1 | title,url,date_discovered,text_content 2 | -------------------------------------------------------------------------------- /kubernetes/secrets-staging.yml.secret: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/invinst/CPDBv2_backend/HEAD/kubernetes/secrets-staging.yml.secret -------------------------------------------------------------------------------- /cpdb/config/settings/circleci.py: -------------------------------------------------------------------------------- 1 | from .test_without_migrations import * # NOQA 2 | 3 | SELENIUM_URL = 'http://localhost:4444/wd/hub' 4 | -------------------------------------------------------------------------------- /cpdb/tracker/index_aliases.py: -------------------------------------------------------------------------------- 1 | from es_index.index_aliases import IndexAlias 2 | 3 | 4 | tracker_index_alias = IndexAlias('tracker') 5 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/writers/test_investigator_xlsx_writer/csv/empty/Beat.csv: -------------------------------------------------------------------------------- 1 | name,area_type,median_income,commander,alderman,police_hq 2 | -------------------------------------------------------------------------------- /kubernetes/secrets-production.yml.secret: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/invinst/CPDBv2_backend/HEAD/kubernetes/secrets-production.yml.secret -------------------------------------------------------------------------------- /cpdb/activity_log/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class ActivityLogConfig(AppConfig): 5 | name = 'activity_log' 6 | -------------------------------------------------------------------------------- /cpdb/lawsuit/importers/__init__.py: -------------------------------------------------------------------------------- 1 | from .lawsuit_importer import LawsuitImporter 2 | 3 | 4 | __all__ = [ 5 | 'LawsuitImporter' 6 | ] 7 | -------------------------------------------------------------------------------- /cpdb/officers/index_aliases.py: -------------------------------------------------------------------------------- 1 | from es_index.index_aliases import IndexAlias 2 | 3 | 4 | officers_index_alias = IndexAlias('officers') 5 | -------------------------------------------------------------------------------- /cpdb/es_index/constants.py: -------------------------------------------------------------------------------- 1 | from tracker.indexers import AttachmentFileIndexer 2 | 3 | DAILY_INDEXERS = [ 4 | AttachmentFileIndexer, 5 | ] 6 | -------------------------------------------------------------------------------- /lambda/create_officer_zip/tests/pdf/2646152: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/invinst/CPDBv2_backend/HEAD/lambda/create_officer_zip/tests/pdf/2646152 -------------------------------------------------------------------------------- /lambda/create_officer_zip/tests/pdf/2646153: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/invinst/CPDBv2_backend/HEAD/lambda/create_officer_zip/tests/pdf/2646153 -------------------------------------------------------------------------------- /ansible/roles/notebook/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - include: setup_pyenv.yml 4 | 5 | - include: setup_notebook.yml 6 | 7 | - include: setup_nginx.yml 8 | -------------------------------------------------------------------------------- /bin/setup_notebook.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ansible-playbook ansible/notebook.yml -i ansible/inventory/notebook --vault-password-file ../vault_pass.txt 3 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/writers/test_accused_xlsx_writer/csv/accused_8562/Victim.csv: -------------------------------------------------------------------------------- 1 | crid,gender,race,birth_year 2 | 1009678,Male,Hispanic,1973 3 | 1012803,,, 4 | -------------------------------------------------------------------------------- /lambda/create_officer_zip/tests/xlsx/accused.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/invinst/CPDBv2_backend/HEAD/lambda/create_officer_zip/tests/xlsx/accused.xlsx -------------------------------------------------------------------------------- /cpdb/app_config/admin/__init__.py: -------------------------------------------------------------------------------- 1 | from .app_config_admin import AppConfigAdmin # NOQA 2 | from .visual_token_color_admin import VisualTokenColorAdmin # NOQA 3 | -------------------------------------------------------------------------------- /cpdb/app_config/serializers/__init__.py: -------------------------------------------------------------------------------- 1 | from .visual_token_color_serializer import VisualTokenColorSerializer 2 | 3 | __all__ = ['VisualTokenColorSerializer'] 4 | -------------------------------------------------------------------------------- /cpdb/toast/constants.py: -------------------------------------------------------------------------------- 1 | TOAST_DESKTOP_TEMPLATE_NAMES = ['OFFICER', 'CR', 'TRR'] 2 | TOAST_MOBILE_TEMPLATE_NAMES = ['MOBILE OFFICER', 'MOBILE CR', 'MOBILE TRR'] 3 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/management/utils/test_export_officer_xlsx/csv/accused_8562/Victim.csv: -------------------------------------------------------------------------------- 1 | crid,gender,race,birth_year 2 | 1009678,Male,Hispanic,1973 3 | 1012803,,, 4 | -------------------------------------------------------------------------------- /cpdb/search/pagination.py: -------------------------------------------------------------------------------- 1 | from es_index.pagination import ESQueryPagination 2 | 3 | 4 | class SearchQueryPagination(ESQueryPagination): 5 | default_limit = 30 6 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/management/utils/test_export_officer_xlsx/csv/investigator_1234/Victim.csv: -------------------------------------------------------------------------------- 1 | crid,gender,race,birth_year 2 | 1009678,Male,Hispanic,1973 3 | 1012803,,, 4 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/writers/test_investigator_xlsx_writer/csv/investigator_1234/Victim.csv: -------------------------------------------------------------------------------- 1 | crid,gender,race,birth_year 2 | 1009678,Male,Hispanic,1973 3 | 1012803,,, 4 | -------------------------------------------------------------------------------- /lambda/create_officer_zip/tests/xlsx/investigator.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/invinst/CPDBv2_backend/HEAD/lambda/create_officer_zip/tests/xlsx/investigator.xlsx -------------------------------------------------------------------------------- /lambda/create_officer_zip/tests/xlsx/use_of_force.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/invinst/CPDBv2_backend/HEAD/lambda/create_officer_zip/tests/xlsx/use_of_force.xlsx -------------------------------------------------------------------------------- /bin/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | bin/manage.sh --local makemigrations --dry-run && docker-compose run web python -m lambda.test && bin/manage.sh --local test $@ 4 | -------------------------------------------------------------------------------- /cpdb/app_config/models/__init__.py: -------------------------------------------------------------------------------- 1 | from .app_config import AppConfig 2 | from .visual_token_color import VisualTokenColor 3 | 4 | __all__ = ['AppConfig', 'VisualTokenColor'] 5 | -------------------------------------------------------------------------------- /cpdb/data-updates/awards/awards.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:894fcbb7363c38f84394f5be466df330f62198cb8d6bf10f0f49030ba3587ebc 3 | size 78897483 4 | -------------------------------------------------------------------------------- /cpdb/data-updates/trrs/trr_main.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:489530728dd60e5367ede7c3ed17acc956b99c7c270fd97ebf086012a473999a 3 | size 26518225 4 | -------------------------------------------------------------------------------- /ansible/roles/notebook/templates/jupyter_notebook_config.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "NotebookApp": { 3 | "password": "sha1:c1e15b14d995:ef01b00fa9cf0da7df12ba22c47878a60b6bbd52" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /cpdb/data-updates/complaints/victims.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:31a8af93952d73aea6b710dc5485319a91581384c63ed39bae9d133fd8837f09 3 | size 13118445 4 | -------------------------------------------------------------------------------- /cpdb/data-updates/salaries/salaries.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9a9079106bc7d0f4592592c5cc0efee173ba8d9aa86959e3b260b1854b2c5e96 3 | size 34706349 4 | -------------------------------------------------------------------------------- /cpdb/data-updates/trrs/trr_statuses.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:783b0919e807190203d69bf41dfac8082369db87f8e5284773f0fd11913411db 3 | size 37979798 4 | -------------------------------------------------------------------------------- /cpdb/data-updates/trrs/trr_subjects.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:706526e98992ddcc35f0fb0bdfd3900953b78f16a6fa8f1599b766af11aaee07 3 | size 24325754 4 | -------------------------------------------------------------------------------- /cpdb/activity_grid/models/__init__.py: -------------------------------------------------------------------------------- 1 | from .activity_card import ActivityCard 2 | from .activity_pair_card import ActivityPairCard 3 | 4 | __all__ = ['ActivityCard', 'ActivityPairCard'] 5 | -------------------------------------------------------------------------------- /cpdb/data-updates/complaints/complainants.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d4fea4b48072db2923e602b8d5454ec653e366409211c9edb5788fdf65e592d7 3 | size 15645159 4 | -------------------------------------------------------------------------------- /cpdb/data-updates/complaints/cpd_witnesses.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9aca0f0ca544229dfe2740d8d59fed564ba7a3dec7441b49af4d635099cf386d 3 | size 15295963 4 | -------------------------------------------------------------------------------- /cpdb/data-updates/complaints/investigators.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:30916fb8031904d0e236fe20037a454ff65fcad2ba0a52392072adeb59c0ff84 3 | size 34059864 4 | -------------------------------------------------------------------------------- /cpdb/data-updates/officers/final-profiles.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0bd11e91f8155c68875568b51527b194ba5ac4c2d3f7024b562abe9c3ab2a4a6 3 | size 77198083 4 | -------------------------------------------------------------------------------- /cpdb/data-updates/trrs/trr_subject_weapons.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:30eefe30260a2067875944c6181d4d9615a4d8b0b4db5beaa3294564f85438ad 3 | size 5947011 4 | -------------------------------------------------------------------------------- /cpdb/data-updates/trrs/trr_weapon_discharges.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:1ff8840b2663223566fa0c9d4a50e896d741b901b54d3c55361906104177627b 3 | size 1256274 4 | -------------------------------------------------------------------------------- /cpdb/data-updates/unit_history/unit-history.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:18c4d05f965d7ef9afcc44e93945a060e28b14e5cd3ef561eb59fe4e129f9254 3 | size 4288254 4 | -------------------------------------------------------------------------------- /cpdb/data/utils/round.py: -------------------------------------------------------------------------------- 1 | from django.db.models import Func 2 | 3 | 4 | class Round(Func): 5 | function = 'ROUND' 6 | template = '%(function)s(CAST(%(expressions)s as numeric), 4)' 7 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/writers/test_accused_xlsx_writer/csv/accused_8562/Beat.csv: -------------------------------------------------------------------------------- 1 | name,area_type,median_income,commander,alderman,police_hq 2 | 0823,school-grounds,,,, 3 | 2511,school-grounds,,,, 4 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | repos: 3 | - repo: git://github.com/pre-commit/pre-commit-hooks 4 | rev: v2.0.0 5 | hooks: 6 | - id: flake8 7 | language_version: python3 8 | -------------------------------------------------------------------------------- /cpdb/data-updates/complaints/civilian_witnesses.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:de59454f9668a81be7769104168ea39dbd84df2888ec1f2514c2da4384ff1f24 3 | size 6783419 4 | -------------------------------------------------------------------------------- /cpdb/data-updates/complaints/complaints-accused.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:11a202b5f6855b28cf2a2bfd60f745803ad6223186da6e57aa660e20aa473abe 3 | size 78619861 4 | -------------------------------------------------------------------------------- /cpdb/data-updates/trrs/trr_actions_responses.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9477439b3854ba0db00d228a2fd096cac5efb3cc2400204b404a594122261f43 3 | size 143033840 4 | -------------------------------------------------------------------------------- /cpdb/search_mobile/apps.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | 3 | from django.apps import AppConfig 4 | 5 | 6 | class SearchMobileConfig(AppConfig): 7 | name = 'search_mobile' 8 | -------------------------------------------------------------------------------- /requirements/local.txt: -------------------------------------------------------------------------------- 1 | -r base.txt 2 | -r test.txt 3 | 4 | # imported REPL 5 | ipdb==0.13.13 6 | 7 | django-extensions==1.9.0 8 | pre-commit==0.8.0 9 | django-debug-toolbar==1.9.1 10 | -------------------------------------------------------------------------------- /cpdb/data-updates/complaints/complaints-complaints.csv: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ae6c8f073157a63727dd7d11fd43937db6a8667a2f8267211f76cb216bb68319 3 | size 86550922 4 | -------------------------------------------------------------------------------- /cpdb/search_terms/models/__init__.py: -------------------------------------------------------------------------------- 1 | from .search_term_category import SearchTermCategory 2 | from .search_term_item import SearchTermItem 3 | 4 | __all__ = ['SearchTermCategory', 'SearchTermItem'] 5 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/management/utils/test_export_officer_xlsx/csv/accused_8562/Beat.csv: -------------------------------------------------------------------------------- 1 | name,area_type,median_income,commander,alderman,police_hq 2 | 0823,school-grounds,,,, 3 | 2511,school-grounds,,,, 4 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/writers/test_investigator_xlsx_writer/csv/investigator_1234/Beat.csv: -------------------------------------------------------------------------------- 1 | name,area_type,median_income,commander,alderman,police_hq 2 | 0823,school-grounds,,,, 3 | 2511,school-grounds,,,, 4 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/management/utils/test_export_officer_xlsx/csv/investigator_1234/Beat.csv: -------------------------------------------------------------------------------- 1 | name,area_type,median_income,commander,alderman,police_hq 2 | 0823,school-grounds,,,, 3 | 2511,school-grounds,,,, 4 | -------------------------------------------------------------------------------- /bin/coverage.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | docker-compose run web sh -c "cpdb/manage.py makemigrations --dry-run && python -m lambda.test && coverage run cpdb/manage.py test && coverage report && coverage html" 3 | -------------------------------------------------------------------------------- /cpdb/alias/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework.serializers import Serializer, ListField, CharField 2 | 3 | 4 | class AliasSerializer(Serializer): 5 | aliases = ListField(child=CharField(max_length=20)) 6 | -------------------------------------------------------------------------------- /cpdb/lawsuit/serializers/__init__.py: -------------------------------------------------------------------------------- 1 | from .lawsuit_serializer import LawsuitSerializer 2 | from .top_lawsuit_serializer import TopLawsuitSerializer 3 | 4 | __all__ = ['LawsuitSerializer', 'TopLawsuitSerializer'] 5 | -------------------------------------------------------------------------------- /.coveragerc: -------------------------------------------------------------------------------- 1 | [report] 2 | omit = 3 | */migrations/* 4 | ~/.virtualenvs/* 5 | ~/virtualenvs/* 6 | manage.py 7 | */tests/* 8 | */site-packages/* 9 | visual_token/figures.py 10 | show_missing=True 11 | -------------------------------------------------------------------------------- /cpdb/data/utils/subqueries.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | 4 | class SQCount(models.Subquery): 5 | template = "(SELECT count(*) FROM (%(subquery)s) _count)" 6 | output_field = models.IntegerField() 7 | -------------------------------------------------------------------------------- /cpdb/utils/raw_query_utils.py: -------------------------------------------------------------------------------- 1 | def dict_fetch_all(cursor): 2 | columns = [col[0] for col in cursor.description] 3 | return [ 4 | dict(zip(columns, row)) 5 | for row in cursor.fetchall() 6 | ] 7 | -------------------------------------------------------------------------------- /cpdb/document_cloud/models/__init__.py: -------------------------------------------------------------------------------- 1 | from .document_cloud_search_query import DocumentCloudSearchQuery 2 | from .document_crawler import DocumentCrawler 3 | 4 | __all__ = ['DocumentCloudSearchQuery', 'DocumentCrawler'] 5 | -------------------------------------------------------------------------------- /cpdb/units/doc_types.py: -------------------------------------------------------------------------------- 1 | from elasticsearch_dsl import DocType, Keyword 2 | from .index_aliases import units_index_alias 3 | 4 | 5 | @units_index_alias.doc_type 6 | class UnitDocType(DocType): 7 | unit_name = Keyword() 8 | -------------------------------------------------------------------------------- /cpdb/analytics/models/__init__.py: -------------------------------------------------------------------------------- 1 | from .event import Event 2 | from .search_tracking import SearchTracking 3 | from .attachment_tracking import AttachmentTracking 4 | 5 | __all__ = ['Event', 'SearchTracking', 'AttachmentTracking'] 6 | -------------------------------------------------------------------------------- /cpdb/status/views.py: -------------------------------------------------------------------------------- 1 | from rest_framework import viewsets 2 | from rest_framework.response import Response 3 | 4 | 5 | class StatusViewSet(viewsets.ViewSet): 6 | def list(self, request): 7 | return Response({'ok': True}) 8 | -------------------------------------------------------------------------------- /cpdb/officers/indexers/__init__.py: -------------------------------------------------------------------------------- 1 | from .officers_indexer import OfficersIndexer 2 | from .officer_coaccusals_indexer import OfficerCoaccusalsIndexer 3 | 4 | 5 | __all__ = [ 6 | 'OfficersIndexer', 'OfficerCoaccusalsIndexer' 7 | ] 8 | -------------------------------------------------------------------------------- /cpdb/data/management/commands/clear_cache.py: -------------------------------------------------------------------------------- 1 | from django.core.management import BaseCommand 2 | from django.core.cache import cache 3 | 4 | 5 | class Command(BaseCommand): 6 | def handle(self, *args, **kwargs): 7 | cache.clear() 8 | -------------------------------------------------------------------------------- /cpdb/sitemap/sitemaps/trr_sitemap.py: -------------------------------------------------------------------------------- 1 | from sitemap.sitemaps.base_sitemap import BaseSitemap 2 | from trr.models import TRR 3 | 4 | 5 | class TRRSitemap(BaseSitemap): 6 | def items(self): 7 | return TRR.objects.all().order_by('id') 8 | -------------------------------------------------------------------------------- /ansible/notebook.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Create notebook instance 4 | hosts: all 5 | become: yes 6 | become_user: root 7 | remote_user: ansible 8 | vars_files: 9 | - env_vars/secrets.yml 10 | roles: 11 | - notebook 12 | -------------------------------------------------------------------------------- /cpdb/lawsuit/models/__init__.py: -------------------------------------------------------------------------------- 1 | from .lawsuit import Lawsuit 2 | from .lawsuit_plaintiff import LawsuitPlaintiff 3 | from .payment import Payment 4 | 5 | __all__ = [ 6 | 'Lawsuit', 7 | 'LawsuitPlaintiff', 8 | 'Payment' 9 | ] 10 | -------------------------------------------------------------------------------- /docker/google-cloud-sdk/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM google/cloud-sdk 2 | 3 | RUN echo "deb https://dl.bintray.com/sobolevn/deb git-secret main" | tee -a /etc/apt/sources.list && \ 4 | curl https://api.bintray.com/users/sobolevn/keys/gpg/public.key | apt-key add - 5 | -------------------------------------------------------------------------------- /docker/remote_syslog2/log_files.yml: -------------------------------------------------------------------------------- 1 | files: 2 | - /logfiles/django-error.log 3 | - /logfiles/twitterbot-webhook.log 4 | destination: 5 | host: logs7.papertrailapp.com 6 | port: 41386 7 | protocol: tls 8 | pid_file: /var/run/remote_syslog.pid 9 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [flake8] 2 | extend-ignore = W605 3 | max-line-length = 120 4 | exclude = 5 | .tox, 6 | .git, 7 | */migrations/*, 8 | */static/CACHE/*, 9 | docs, 10 | node_modules, 11 | bin, 12 | 13 | [nosetests] 14 | py3where = cpdb 15 | -------------------------------------------------------------------------------- /cpdb/pinboard/tests/models/__init__.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | from pinboard.fields import HexField 4 | 5 | 6 | class HexModel(models.Model): 7 | id = HexField(primary_key=True) 8 | nonauto_hex = HexField(auto_gen_add=False, null=True) 9 | -------------------------------------------------------------------------------- /ansible/roles/notebook/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | pyenv_root: /pyenv/ 4 | deploy_user: ansible 5 | application_name: notebook 6 | application_home: /notebook 7 | python_version: 2.7.13 8 | virtualenv_path: "{{ pyenv_root }}/versions/{{ application_name }}/" 9 | -------------------------------------------------------------------------------- /ansible/roles/notebook/files/install-python.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export PYENV_ROOT="/pyenv" 4 | export PATH="$PYENV_ROOT/bin:$PATH" 5 | 6 | if which pyenv > /dev/null; then eval "$(pyenv init -)"; fi 7 | 8 | (pyenv versions | grep "$1") || pyenv install "$1" 9 | -------------------------------------------------------------------------------- /cpdb/config/logging_filters.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | from django.conf import settings 4 | 5 | 6 | class ContextFilter(logging.Filter): 7 | def filter(self, record): 8 | record.environment = settings.ENVIRONMENT 9 | return True 10 | -------------------------------------------------------------------------------- /docker/cpdpbot/requirements.txt: -------------------------------------------------------------------------------- 1 | gizeh==0.1.10 2 | moviepy==1.0.0 3 | requests==2.20.0 4 | azure==4.0.0 5 | tweepy==3.6.0 6 | azure-storage-queue==1.4.0 7 | mock==2.0.0 8 | robber==1.1.3 9 | tls-syslog==0.1.3 10 | imageio-ffmpeg==0.2.0 11 | imageio==2.5.0 12 | -------------------------------------------------------------------------------- /cpdb/sitemap/sitemaps/unit_sitemap.py: -------------------------------------------------------------------------------- 1 | from data.models import PoliceUnit 2 | from sitemap.sitemaps.base_sitemap import BaseSitemap 3 | 4 | 5 | class UnitSitemap(BaseSitemap): 6 | def items(self): 7 | return PoliceUnit.objects.all().order_by('unit_name') 8 | -------------------------------------------------------------------------------- /cpdb/xlsx/constants.py: -------------------------------------------------------------------------------- 1 | ACCUSED_XLSX = 'accused.xlsx' 2 | USE_OF_FORCE_XLSX = 'use_of_force.xlsx' 3 | INVESTIGATOR_XLSX = 'investigator.xlsx' 4 | DOCUMENTS_XLSX = 'documents.xlsx' 5 | XLSX_FILE_NAMES = [ACCUSED_XLSX, USE_OF_FORCE_XLSX, INVESTIGATOR_XLSX, DOCUMENTS_XLSX] 6 | -------------------------------------------------------------------------------- /apiary/app_config.md: -------------------------------------------------------------------------------- 1 | ## App config [/app-config/] 2 | 3 | ### List config [GET] 4 | 5 | + Response 200 (application/json) 6 | { 7 | "CONFIG_1": "VALUE 1", 8 | "CONFIG_2": "VALUE 2", 9 | "CONFIG_3": "VALUE 3" 10 | } 11 | -------------------------------------------------------------------------------- /cpdb/cms/tests/files/reporting.csv: -------------------------------------------------------------------------------- 1 | Link,Headline,Byline(s),Name of the publication,Date of publication,Excerpt (two paragraphs),Tags,Date Found,Officers mentioned ,Featured/starred 2 | url,title,author,publication,10/27/2015,"paragraph 1 3 | 4 | paragraph 2","tag 1, tag 2",,, 5 | -------------------------------------------------------------------------------- /cpdb/cms/utils.py: -------------------------------------------------------------------------------- 1 | import uuid 2 | 3 | seen_keys = {} 4 | 5 | 6 | def generate_draft_block_key(): 7 | key = None 8 | 9 | while key is None or key in seen_keys: 10 | key = str(uuid.uuid4())[:5] 11 | 12 | seen_keys[key] = True 13 | return key 14 | -------------------------------------------------------------------------------- /cpdb/sitemap/sitemaps/officer_sitemap.py: -------------------------------------------------------------------------------- 1 | from data.models import Officer 2 | from sitemap.sitemaps.base_sitemap import BaseSitemap 3 | 4 | 5 | class OfficerSitemap(BaseSitemap): 6 | def items(self): 7 | return Officer.objects.all().order_by('-allegation_count') 8 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/writers/test_accused_xlsx_writer/csv/empty/Allegation.csv: -------------------------------------------------------------------------------- 1 | crid,officer_name,address,old_complaint_address,incident_date,is_officer_complaint,beat,coaccused_count,category,subcategory,start_date,end_date,recc_finding,recc_outcome,final_finding,final_outcome,disciplined 2 | -------------------------------------------------------------------------------- /cpdb/activity_log/constants.py: -------------------------------------------------------------------------------- 1 | ADD_TAG_TO_DOCUMENT = 'ADD_TAG_TO_DOCUMENT' 2 | REMOVE_TAG_FROM_DOCUMENT = 'REMOVE_TAG_FROM_DOCUMENT' 3 | 4 | ACTION_TYPE_CHOICES = ( 5 | (ADD_TAG_TO_DOCUMENT, 'Add tag to document'), 6 | (REMOVE_TAG_FROM_DOCUMENT, 'Remove tag from document'), 7 | ) 8 | -------------------------------------------------------------------------------- /cpdb/sitemap/sitemaps/allegation_sitemap.py: -------------------------------------------------------------------------------- 1 | from data.models import Allegation 2 | from sitemap.sitemaps.base_sitemap import BaseSitemap 3 | 4 | 5 | class AllegationSitemap(BaseSitemap): 6 | def items(self): 7 | return Allegation.objects.all().order_by('-coaccused_count') 8 | -------------------------------------------------------------------------------- /cpdb/social_graph/queries/__init__.py: -------------------------------------------------------------------------------- 1 | from .geographic_data_query import GeographyCrsDataQuery, GeographyTrrsDataQuery 2 | from .social_graph_data_query import SocialGraphDataQuery 3 | 4 | __all__ = [ 5 | 'GeographyCrsDataQuery', 'GeographyTrrsDataQuery', 'SocialGraphDataQuery' 6 | ] 7 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/writers/test_investigator_xlsx_writer/csv/empty/Allegation.csv: -------------------------------------------------------------------------------- 1 | crid,officer_name,address,old_complaint_address,incident_date,is_officer_complaint,beat,coaccused_count,category,subcategory,start_date,end_date,recc_finding,recc_outcome,final_finding,final_outcome,disciplined 2 | -------------------------------------------------------------------------------- /apiary/officer_create_zip_file.md: -------------------------------------------------------------------------------- 1 | ## Officer create zip file [/officers/{officer_id}/create-zip-file/] 2 | 3 | ### Create zip file from excel and pdf files then save it on S3[GET] 4 | 5 | + Parameters 6 | + officer_id (number) - number ID of the officer 7 | 8 | + Response 200 (application/json) 9 | -------------------------------------------------------------------------------- /cpdb/alias/utils.py: -------------------------------------------------------------------------------- 1 | def set_aliases(doc_type_class, model_class, pk, aliases): 2 | # set db record 3 | record = model_class.objects.get(pk=pk) 4 | record.tags.set(*aliases) 5 | 6 | # update record's index 7 | document = doc_type_class.get(pk) 8 | document.update(tags=aliases) 9 | -------------------------------------------------------------------------------- /cpdb/analytics/models/event.py: -------------------------------------------------------------------------------- 1 | from django.contrib.postgres.fields import JSONField 2 | from django.db import models 3 | 4 | from data.models.common import TimeStampsModel 5 | 6 | 7 | class Event(TimeStampsModel): 8 | name = models.CharField(max_length=255) 9 | data = JSONField() 10 | -------------------------------------------------------------------------------- /cpdb/app_config/constants.py: -------------------------------------------------------------------------------- 1 | APP_CONFIG = [ 2 | { 3 | 'name': 'PINBOARD_INTRODUCTION_DELAY', 4 | 'value': '2000', 5 | 'description': 'Delay before displaying pinboard introduction in millisecond' 6 | } 7 | ] 8 | 9 | VISUAL_TOKEN_COLORS_KEY = 'VISUAL_TOKEN_COLORS' 10 | -------------------------------------------------------------------------------- /cpdb/popup/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.contrib.admin import ModelAdmin 3 | 4 | from popup.models import Popup 5 | 6 | 7 | class PopupAdmin(ModelAdmin): 8 | list_display = ('name', 'page', 'title', 'text') 9 | 10 | 11 | admin.site.register(Popup, PopupAdmin) 12 | -------------------------------------------------------------------------------- /cpdb/search/__init__.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings 2 | 3 | from elasticsearch_dsl.connections import connections 4 | from elasticsearch import Elasticsearch 5 | 6 | 7 | es_client = Elasticsearch(hosts=settings.ELASTICSEARCH_HOSTS) 8 | 9 | connections.add_connection('default', es_client) 10 | -------------------------------------------------------------------------------- /cpdb/social_graph/serializers/officer_serializer.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | from shared.serializer import OfficerPercentileSerializer 4 | 5 | 6 | class OfficerSerializer(OfficerPercentileSerializer): 7 | id = serializers.IntegerField() 8 | full_name = serializers.CharField() 9 | -------------------------------------------------------------------------------- /cpdb/config/settings/test_without_migrations.py: -------------------------------------------------------------------------------- 1 | from .test import * # NOQA 2 | 3 | 4 | class DisableMigrations(object): 5 | def __contains__(self, item): 6 | return True 7 | 8 | def __getitem__(self, item): 9 | return None 10 | 11 | 12 | MIGRATION_MODULES = DisableMigrations() 13 | -------------------------------------------------------------------------------- /cpdb/pinboard/serializers/desktop/pinned/officer_serializer.py: -------------------------------------------------------------------------------- 1 | from officers.serializers.response_serializers import PoliceUnitSerializer 2 | from ..common import OfficerSerializer as BaseOfficerSerializer 3 | 4 | 5 | class OfficerSerializer(BaseOfficerSerializer): 6 | unit = PoliceUnitSerializer(source='last_unit') 7 | -------------------------------------------------------------------------------- /cpdb/popup/tests/test_models.py: -------------------------------------------------------------------------------- 1 | from django.test.testcases import TestCase 2 | from robber.expect import expect 3 | 4 | from popup.factories import PopupFactory 5 | 6 | 7 | class PopupTestCase(TestCase): 8 | def test_str_method(self): 9 | expect(str(PopupFactory(name='some name'))).to.eq('some name') 10 | -------------------------------------------------------------------------------- /cpdb/toast/tests/test_models.py: -------------------------------------------------------------------------------- 1 | from django.test.testcases import TestCase 2 | from robber.expect import expect 3 | 4 | from toast.factories import ToastFactory 5 | 6 | 7 | class ToastTestCase(TestCase): 8 | def test_str_method(self): 9 | expect(str(ToastFactory(name='toast name'))).to.eq('toast name') 10 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | # ignore everything except cpdb, requirements and gunicorn.conf 2 | * 3 | !cpdb 4 | !requirements 5 | !lambda 6 | !gunicorn.conf 7 | 8 | # further stuffs to ignore 9 | cpdb/static 10 | cpdb/staticfiles 11 | cpdb/media 12 | cpdb/data_importer/cleaned_data 13 | cpdb/data_importer/original_data 14 | **/*.pyc 15 | -------------------------------------------------------------------------------- /ansible/roles/notebook/files/create-env.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export PYENV_ROOT="/pyenv" 4 | export PATH="$PYENV_ROOT/bin:$PATH" 5 | 6 | if which pyenv > /dev/null; then 7 | eval "$(pyenv init -)"; 8 | eval "$(pyenv virtualenv-init -)"; 9 | fi 10 | 11 | (pyenv versions | grep "$2") || pyenv virtualenv $1 $2 12 | -------------------------------------------------------------------------------- /cpdb/popup/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework.fields import CharField 2 | from rest_framework.serializers import Serializer 3 | 4 | 5 | class PopupSerializer(Serializer): 6 | name = CharField(max_length=64) 7 | page = CharField(max_length=255) 8 | title = CharField(max_length=255) 9 | text = CharField() 10 | -------------------------------------------------------------------------------- /cpdb/pinboard/serializers/mobile/pinned/officer_serializer.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | from ..common import OfficerMobileSerializer as BaseOfficerMobileSerializer 4 | 5 | 6 | class OfficerMobileSerializer(BaseOfficerMobileSerializer): 7 | complaint_count = serializers.IntegerField(source='allegation_count') 8 | -------------------------------------------------------------------------------- /cpdb/cms/tests/test_factories.py: -------------------------------------------------------------------------------- 1 | from django.test import SimpleTestCase 2 | 3 | from cms.factories import LinkEntityFactory 4 | 5 | 6 | class LinkEntityFactoryTestCase(SimpleTestCase): 7 | def test_factory(self): 8 | link_entity = LinkEntityFactory(url='url') 9 | self.assertEqual(link_entity.data['url'], 'url') 10 | -------------------------------------------------------------------------------- /cpdb/twitterbot/models/twitter_bot_visit_log.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | from data.models.common import TimeStampsModel 4 | 5 | 6 | class TwitterBotVisitLog(TimeStampsModel): 7 | response_log = models.ForeignKey('twitterbot.TwitterBotResponseLog', on_delete=models.CASCADE) 8 | request_path = models.CharField(max_length=255) 9 | -------------------------------------------------------------------------------- /cpdb/data/models/race_population.py: -------------------------------------------------------------------------------- 1 | from django.contrib.gis.db import models 2 | 3 | from .common import TimeStampsModel 4 | 5 | 6 | class RacePopulation(TimeStampsModel): 7 | race = models.CharField(max_length=255) 8 | count = models.PositiveIntegerField() 9 | area = models.ForeignKey('data.Area', on_delete=models.CASCADE) 10 | -------------------------------------------------------------------------------- /cpdb/search_mobile/serializers/lawsuit_recent_serializer.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | from .lawsuit_serializer import LawsuitSerializer 4 | 5 | 6 | class LawsuitRecentSerializer(LawsuitSerializer): 7 | type = serializers.SerializerMethodField() 8 | 9 | def get_type(self, obj): 10 | return 'LAWSUIT' 11 | -------------------------------------------------------------------------------- /cpdb/alias/constants.py: -------------------------------------------------------------------------------- 1 | from data.models import Officer, Area, PoliceUnit 2 | from officers.doc_types import OfficerInfoDocType 3 | from search.doc_types import AreaDocType, UnitDocType 4 | 5 | ALIAS_MAPPINGS = { 6 | 'officer': (OfficerInfoDocType, Officer), 7 | 'area': (AreaDocType, Area), 8 | 'unit': (UnitDocType, PoliceUnit) 9 | } 10 | -------------------------------------------------------------------------------- /cpdb/es_index/management/commands/rebuild_index_daily.py: -------------------------------------------------------------------------------- 1 | from django.core.management.base import BaseCommand 2 | from django.core.management import call_command 3 | 4 | 5 | class Command(BaseCommand): 6 | def handle(self, *args, **kwargs): 7 | call_command('rebuild_index', '--daily') 8 | call_command('rebuild_search_index', '--daily') 9 | -------------------------------------------------------------------------------- /cpdb/pinboard/serializers/mobile/common/__init__.py: -------------------------------------------------------------------------------- 1 | from .officer_serializers import OfficerMobileSerializer, OfficerRowMobileSerializer 2 | from .allegation_serializer import AllegationMobileSerializer 3 | 4 | 5 | __all__ = [ 6 | 'OfficerMobileSerializer', 7 | 'OfficerRowMobileSerializer', 8 | 'AllegationMobileSerializer', 9 | ] 10 | -------------------------------------------------------------------------------- /cpdb/sitemap/sitemaps/base_sitemap.py: -------------------------------------------------------------------------------- 1 | from django.contrib.sitemaps import Sitemap 2 | 3 | 4 | class BaseSitemap(Sitemap): 5 | changefreq = 'daily' 6 | priority = 0.5 7 | protocol = 'https' 8 | 9 | def items(self): 10 | raise NotImplementedError 11 | 12 | def lastmod(self, obj): 13 | return obj.updated_at 14 | -------------------------------------------------------------------------------- /cpdb/social_graph/serializers/victim_serializer.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | from shared.serializer import NoNullSerializer 4 | 5 | 6 | class VictimSerializer(NoNullSerializer): 7 | gender = serializers.CharField(source='gender_display') 8 | race = serializers.CharField() 9 | age = serializers.IntegerField() 10 | -------------------------------------------------------------------------------- /cpdb/trr/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from .models import TRRAttachmentRequest 3 | 4 | 5 | class TRRAttachmentRequestAdmin(admin.ModelAdmin): 6 | list_display = ['__str__'] 7 | fields = readonly_fields = ('email', 'trr_id', 'created_at') 8 | 9 | 10 | admin.site.register(TRRAttachmentRequest, TRRAttachmentRequestAdmin) 11 | -------------------------------------------------------------------------------- /cpdb/twitterbot/management/commands/list_webhooks.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | from twitterbot.twitter_base_command import TwitterBaseCommand 4 | 5 | 6 | class Command(TwitterBaseCommand): 7 | def handle(self, *args, **options): 8 | webhooks = self.twitter_client.webhook.all() 9 | self.stdout.write(json.dumps(webhooks, indent=2)) 10 | -------------------------------------------------------------------------------- /cpdb/pinboard/serializers/desktop/common/__init__.py: -------------------------------------------------------------------------------- 1 | from .officer_serializers import OfficerSerializer, OfficerRowSerializer 2 | from .allegation_serializer import AllegationSerializer 3 | from .victim_serializer import VictimSerializer 4 | 5 | __all__ = [ 6 | 'OfficerSerializer', 'OfficerRowSerializer', 'AllegationSerializer', 'VictimSerializer' 7 | ] 8 | -------------------------------------------------------------------------------- /apiary/city_summary.md: -------------------------------------------------------------------------------- 1 | ## City Summary [/v2/city-summary/] 2 | 3 | ### Get city summary [GET] 4 | 5 | + Response 200 (application/json) 6 | 7 | { 8 | "allegation_count": 125735, 9 | "discipline_count": 6404, 10 | 'lawsuits_count': 1460, 11 | 'total_lawsuit_settlements': '470485665.34' 12 | } 13 | -------------------------------------------------------------------------------- /cpdb/pinboard/serializers/desktop/common/victim_serializer.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | from shared.serializer import NoNullSerializer 4 | 5 | 6 | class VictimSerializer(NoNullSerializer): 7 | gender = serializers.CharField(source='gender_display') 8 | race = serializers.CharField() 9 | age = serializers.IntegerField() 10 | -------------------------------------------------------------------------------- /cpdb/app_config/serializers/visual_token_color_serializer.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | from app_config.models import VisualTokenColor 4 | 5 | 6 | class VisualTokenColorSerializer(serializers.ModelSerializer): 7 | class Meta: 8 | model = VisualTokenColor 9 | fields = ('color', 'text_color', 'lower_range', 'upper_range') 10 | -------------------------------------------------------------------------------- /cpdb/sitemap/sitemaps/attachment_sitemap.py: -------------------------------------------------------------------------------- 1 | from data.constants import MEDIA_TYPE_DOCUMENT 2 | from data.models import AttachmentFile 3 | from sitemap.sitemaps.base_sitemap import BaseSitemap 4 | 5 | 6 | class AttachmentSitemap(BaseSitemap): 7 | def items(self): 8 | return AttachmentFile.objects.showing().filter(file_type=MEDIA_TYPE_DOCUMENT).order_by('id') 9 | -------------------------------------------------------------------------------- /cpdb/twitterbot/models/respone_template.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | from twitterbot.constants import RESPONSE_TYPE_CHOICES 4 | from data.models.common import TimeStampsModel 5 | 6 | 7 | class ResponseTemplate(TimeStampsModel): 8 | response_type = models.CharField(max_length=20, choices=RESPONSE_TYPE_CHOICES) 9 | syntax = models.TextField() 10 | -------------------------------------------------------------------------------- /requirements/test.txt: -------------------------------------------------------------------------------- 1 | -r base.txt 2 | -r ../lambda/create_officer_zip/requirements.txt 3 | -r ../lambda/upload_pdf/requirements.txt 4 | 5 | flake8==3.7.9 6 | coverage==5.0.4 7 | coveralls==2.0.0 8 | factory-boy==2.11.1 9 | freezegun==0.3.13 10 | mock==2.0.0 11 | robber==1.1.5 12 | responses==0.10.5 13 | xlsx2csv==0.7.4 14 | moto==1.3.2 15 | botocore==1.13.42 16 | -------------------------------------------------------------------------------- /cpdb/search_mobile/serializers/trr_recent_serializer.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | from shared.serializer import NoNullSerializer 4 | 5 | 6 | class TRRRecentSerializer(NoNullSerializer): 7 | id = serializers.IntegerField() 8 | type = serializers.SerializerMethodField() 9 | 10 | def get_type(self, obj): 11 | return 'TRR' 12 | -------------------------------------------------------------------------------- /cpdb/xlsx/serializers/victim_xlsx_serializer.py: -------------------------------------------------------------------------------- 1 | from rest_framework.serializers import Serializer, CharField, IntegerField 2 | 3 | 4 | class VictimXlsxSerializer(Serializer): 5 | crid = CharField(source='allegation.crid') 6 | gender = CharField(source='gender_display', allow_blank=True) 7 | race = CharField() 8 | birth_year = IntegerField(allow_null=True) 9 | -------------------------------------------------------------------------------- /cpdb/cms/models/slug_page.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.contrib.postgres.fields import JSONField 3 | 4 | from data.models.common import TimeStampsModel 5 | 6 | 7 | class SlugPage(TimeStampsModel): 8 | slug = models.CharField(max_length=255, primary_key=True) 9 | serializer_class = models.CharField(max_length=255) 10 | fields = JSONField() 11 | -------------------------------------------------------------------------------- /cpdb/pinboard/serializers/mobile/relevant/officer_serializer.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | from ..common import OfficerMobileSerializer as BaseOfficerMobileSerializer 4 | 5 | 6 | class OfficerMobileSerializer(BaseOfficerMobileSerializer): 7 | allegation_count = serializers.IntegerField() 8 | coaccusal_count = serializers.IntegerField(allow_null=True) 9 | -------------------------------------------------------------------------------- /cpdb/sitemap/sitemaps/static_page_sitemap.py: -------------------------------------------------------------------------------- 1 | from sitemap.sitemaps.base_sitemap import BaseSitemap 2 | 3 | 4 | class StaticPageSiteMap(BaseSitemap): 5 | def items(self): 6 | return ['', 'collaborate', 'terms'] 7 | 8 | def location(self, item): 9 | return f'/{item}/' if item else '' 10 | 11 | def lastmod(self, obj): 12 | return None 13 | -------------------------------------------------------------------------------- /cpdb/twitterbot/models/__init__.py: -------------------------------------------------------------------------------- 1 | from .respone_template import ResponseTemplate 2 | from .tweet_response_round_robin import TweetResponseRoundRobin 3 | from .twitter_bot_response_log import TwitterBotResponseLog 4 | from .twitter_bot_visit_log import TwitterBotVisitLog 5 | 6 | __all__ = ['ResponseTemplate', 'TweetResponseRoundRobin', 'TwitterBotResponseLog', 'TwitterBotVisitLog'] 7 | -------------------------------------------------------------------------------- /docker/postgres/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mdillon/postgis:9.6-alpine 2 | 3 | USER $POSTGRES_USER 4 | 5 | ENV POSTGRES_APP_DB cpdb 6 | ENV POSTGRES_APP_USER cpdb 7 | ENV POSTGRES_APP_PASSWORD password 8 | ENV POSTGRES_NUMERACY_PASSWORD numeracy 9 | ENV POSTGRES_NOTEBOOK_PASSWORD notebook 10 | ENV POSTGRES_CIVIS_PASSWORD civis 11 | 12 | COPY init-scripts/* /docker-entrypoint-initdb.d/ 13 | -------------------------------------------------------------------------------- /cpdb/data/models/attachment_ocr.py: -------------------------------------------------------------------------------- 1 | from django.contrib.gis.db import models 2 | 3 | from .common import TimeStampsModel 4 | 5 | 6 | class AttachmentOCR(TimeStampsModel): 7 | attachment = models.ForeignKey('data.AttachmentFile', on_delete=models.CASCADE, related_name='attachment_ocrs') 8 | page_num = models.IntegerField() 9 | ocr_text = models.TextField(blank=True) 10 | -------------------------------------------------------------------------------- /cpdb/data/templates/attachment_changelist.html: -------------------------------------------------------------------------------- 1 | {% extends 'admin/change_list.html' %} 2 | 3 | {% block object-tools %} 4 |
5 |
6 | {% csrf_token %} 7 | 8 |
9 |
10 |
11 | {{ block.super }} 12 | {% endblock %} 13 | -------------------------------------------------------------------------------- /cpdb/data/utils/attachment_file.py: -------------------------------------------------------------------------------- 1 | from data.constants import MEDIA_IPRA_COPA_HIDING_TAGS, MEDIA_HIDING_TITLES 2 | 3 | 4 | def filter_attachments(attachment_queryset): 5 | query = attachment_queryset.filter(show=True).exclude(tag__in=MEDIA_IPRA_COPA_HIDING_TAGS) 6 | for keyword in MEDIA_HIDING_TITLES: 7 | query = query.exclude(title__icontains=keyword) 8 | return query 9 | -------------------------------------------------------------------------------- /cpdb/app_config/models/app_config.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | from data.models.common import TimeStampsModel 4 | 5 | 6 | class AppConfig(TimeStampsModel): 7 | name = models.CharField(max_length=32) 8 | value = models.CharField(max_length=64) 9 | description = models.TextField() 10 | 11 | def __str__(self): 12 | return f'{self.name}: {self.value}' 13 | -------------------------------------------------------------------------------- /cpdb/app_config/validators/visual_token_color_validators.py: -------------------------------------------------------------------------------- 1 | import string 2 | 3 | from django.core.exceptions import ValidationError 4 | 5 | 6 | def is_valid_hex_color(value): 7 | if value[0] == '#' and len(value) == 7 and all([c in string.hexdigits for c in value[1:]]): 8 | return True 9 | else: 10 | raise ValidationError('Value must be a valid hex color') 11 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0110_merge_20190108_0253.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.3 on 2019-01-08 08:53 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('data', '0099_attachmentrequest_noti_email_sent'), 10 | ('data', '0109_populate_areas_lineareas'), 11 | ] 12 | 13 | operations = [ 14 | ] 15 | -------------------------------------------------------------------------------- /cpdb/data/models/officer_alias.py: -------------------------------------------------------------------------------- 1 | from django.contrib.gis.db import models 2 | 3 | from .common import TimeStampsModel 4 | 5 | 6 | class OfficerAlias(TimeStampsModel): 7 | old_officer_id = models.IntegerField() 8 | new_officer = models.ForeignKey('data.Officer', on_delete=models.CASCADE) 9 | 10 | class Meta: 11 | unique_together = ('old_officer_id', 'new_officer') 12 | -------------------------------------------------------------------------------- /cpdb/data/validators.py: -------------------------------------------------------------------------------- 1 | from django.core.exceptions import ValidationError 2 | 3 | from data.constants import RACE_UNKNOWN_STRINGS 4 | 5 | 6 | def validate_race(value): 7 | # The only way to indicate an unknown race should be by saving it as 'Unknown' string in database 8 | if value.lower() in RACE_UNKNOWN_STRINGS: 9 | raise ValidationError(f'Value cannot be "{value}"') 10 | -------------------------------------------------------------------------------- /cpdb/pinboard/serializers/desktop/pinned/__init__.py: -------------------------------------------------------------------------------- 1 | from .officer_serializer import OfficerSerializer as PinnedOfficerSerializer 2 | from .allegation_serializer import AllegationSerializer as PinnedAllegationSerializer 3 | from .trr_serializer import TRRSerializer as PinnedTRRSerializer 4 | 5 | __all__ = [ 6 | 'PinnedOfficerSerializer', 'PinnedAllegationSerializer', 'PinnedTRRSerializer' 7 | ] 8 | -------------------------------------------------------------------------------- /cpdb/cms/tests/test_utils.py: -------------------------------------------------------------------------------- 1 | from django.test import SimpleTestCase 2 | 3 | from mock import patch 4 | 5 | from cms.utils import generate_draft_block_key 6 | 7 | 8 | class UtilsTestCase(SimpleTestCase): 9 | def test_generate_draft_block_key(self): 10 | with patch('cms.utils.uuid.uuid4', return_value='a1234'): 11 | self.assertEqual(generate_draft_block_key(), 'a1234') 12 | -------------------------------------------------------------------------------- /cpdb/data/management/commands/cache_data.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | from django.core.management import BaseCommand 4 | from data import cache_managers 5 | 6 | 7 | class Command(BaseCommand): 8 | def handle(self, *args, **kwargs): 9 | start_time = time.time() 10 | cache_managers.cache_all() 11 | self.stdout.write(f'Finished on --- {time.time() - start_time} seconds ---') 12 | -------------------------------------------------------------------------------- /cpdb/popup/models/popup.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | from data.models.common import TimeStampsModel 4 | 5 | 6 | class Popup(TimeStampsModel): 7 | name = models.CharField(max_length=64) 8 | page = models.CharField(max_length=32) 9 | title = models.CharField(max_length=255) 10 | text = models.TextField() 11 | 12 | def __str__(self): 13 | return self.name 14 | -------------------------------------------------------------------------------- /kubernetes/namespaces.yml: -------------------------------------------------------------------------------- 1 | kind: "Namespace" 2 | apiVersion: "v1" 3 | metadata: 4 | name: "production" 5 | labels: 6 | name: "production" 7 | --- 8 | kind: "Namespace" 9 | apiVersion: "v1" 10 | metadata: 11 | name: "beta" 12 | labels: 13 | name: "beta" 14 | --- 15 | kind: "Namespace" 16 | apiVersion: "v1" 17 | metadata: 18 | name: "staging" 19 | labels: 20 | name: "staging" 21 | -------------------------------------------------------------------------------- /ansible/roles/notebook/templates/start_jupyter.sh.j2: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export PYENV_ROOT="/pyenv" 4 | export PATH="$PYENV_ROOT/bin:$PATH" 5 | 6 | if which pyenv > /dev/null; then eval "$(pyenv init -)"; fi 7 | 8 | pyenv activate {{ application_name }} 9 | jupyter-notebook --no-browser --notebook-dir='{{ application_home }}' --config='/home/{{ deploy_user }}/.jupyter/jupyter_notebook_config.py' 10 | -------------------------------------------------------------------------------- /cpdb/activity_grid/models/activity_card.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | from data.models.common import TimeStampsModel 4 | 5 | 6 | class ActivityCard(TimeStampsModel): 7 | officer = models.OneToOneField('data.Officer', on_delete=models.CASCADE, related_name='activity_card') 8 | important = models.BooleanField(default=False) 9 | last_activity = models.DateTimeField(null=True) 10 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0090_merge_20181129_2015.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.3 on 2018-11-30 02:15 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('data', '0087_add_on_delete_to_several_models'), 10 | ('data', '0089_attachmentfile_change_unique_together'), 11 | ] 12 | 13 | operations = [ 14 | ] 15 | -------------------------------------------------------------------------------- /cpdb/email_service/backend.py: -------------------------------------------------------------------------------- 1 | from anymail.backends.mailgun import EmailBackend 2 | from bandit.backends.base import HijackBackendMixin 3 | 4 | 5 | # pragma: no cover 6 | class MailGunHijackBackend(HijackBackendMixin, EmailBackend): 7 | """ 8 | This backend intercepts outgoing messages drops them to a single email 9 | address, using the Anymail EmailBackend. 10 | """ 11 | pass 12 | -------------------------------------------------------------------------------- /cpdb/pinboard/serializers/desktop/admin/officer_serializer.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | from shared.serializer import OfficerPercentileSerializer 4 | 5 | 6 | class OfficerSerializer(OfficerPercentileSerializer): 7 | id = serializers.IntegerField() 8 | name = serializers.CharField(source='full_name') 9 | count = serializers.IntegerField(source='allegation_count') 10 | -------------------------------------------------------------------------------- /cpdb/data/models/line_area.py: -------------------------------------------------------------------------------- 1 | from django.contrib.gis.db import models 2 | 3 | from data.constants import LINE_AREA_CHOICES 4 | from .common import TimeStampsModel 5 | 6 | 7 | class LineArea(TimeStampsModel): 8 | name = models.CharField(max_length=100) 9 | linearea_type = models.CharField(max_length=30, choices=LINE_AREA_CHOICES) 10 | geom = models.MultiLineStringField(srid=4326, blank=True) 11 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0097_merge_20190101_2250.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.3 on 2019-01-02 04:50 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('data', '0096_add_created_at_and_updated_at_columns'), 10 | ('data', '0095_attachmenrequest_bulk_objects_manager'), 11 | ] 12 | 13 | operations = [ 14 | ] 15 | -------------------------------------------------------------------------------- /cpdb/search_terms/views.py: -------------------------------------------------------------------------------- 1 | from rest_framework import viewsets, mixins 2 | 3 | from .models import SearchTermCategory 4 | from .serializers import SearchTermCategorySerializer 5 | 6 | 7 | class SearchTermCategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): 8 | queryset = SearchTermCategory.objects.all() 9 | serializer_class = SearchTermCategorySerializer 10 | pagination_class = None 11 | -------------------------------------------------------------------------------- /cpdb/data/management/commands/fix_community_area_type.py: -------------------------------------------------------------------------------- 1 | from django.core.management import BaseCommand 2 | 3 | from data.models import Area 4 | 5 | 6 | class Command(BaseCommand): 7 | def handle(self, *args, **kwargs): 8 | for area in Area.objects.filter(area_type='Community'): 9 | area.area_type = 'community' 10 | area.name = area.name.title() 11 | area.save() 12 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0004_merge.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.9.5 on 2016-09-06 07:09 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('data', '0003_remove_unit_from_officer'), 12 | ('data', '0003_merge'), 13 | ] 14 | 15 | operations = [ 16 | ] 17 | -------------------------------------------------------------------------------- /cpdb/pinboard/serializers/desktop/relevant/__init__.py: -------------------------------------------------------------------------------- 1 | from .officer_serializer import OfficerSerializer as RelevantOfficerSerializer 2 | from .allegation_serializer import AllegationSerializer as RelevantAllegationSerializer 3 | from .document_serializer import DocumentSerializer as RelevantDocumentSerializer 4 | 5 | __all__ = [ 6 | 'RelevantOfficerSerializer', 'RelevantAllegationSerializer', 'RelevantDocumentSerializer' 7 | ] 8 | -------------------------------------------------------------------------------- /cpdb/twitterbot/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | from shared.serializer import OfficerYearlyPercentileSerializer 4 | 5 | 6 | class OfficerSerializer(serializers.Serializer): 7 | id = serializers.IntegerField() 8 | allegation_count = serializers.IntegerField() 9 | full_name = serializers.CharField() 10 | percentiles = OfficerYearlyPercentileSerializer(many=True, read_only=True) 11 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0008_merge.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.9.5 on 2017-02-27 07:39 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('data', '0007_policeunit_description'), 12 | ('data', '0007_officer_tags'), 13 | ] 14 | 15 | operations = [ 16 | ] 17 | -------------------------------------------------------------------------------- /cpdb/data/tests/models/test_officer_history.py: -------------------------------------------------------------------------------- 1 | from django.test.testcases import TestCase 2 | 3 | from robber.expect import expect 4 | 5 | from data.factories import OfficerHistoryFactory, PoliceUnitFactory 6 | 7 | 8 | class OfficerHistoryTestCase(TestCase): 9 | def test_unit_name(self): 10 | history = OfficerHistoryFactory(unit=PoliceUnitFactory(unit_name='abc')) 11 | expect(history.unit_name).to.eq('abc') 12 | -------------------------------------------------------------------------------- /cpdb/toast/models/toast.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | from data.models.common import TimeStampsModel 4 | 5 | 6 | class Toast(TimeStampsModel): 7 | name = models.CharField(max_length=25) 8 | template = models.TextField( 9 | help_text='Markdown supported' 10 | ) 11 | tags = models.CharField( 12 | max_length=255, 13 | ) 14 | 15 | def __str__(self): 16 | return self.name 17 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0003_merge.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.9.5 on 2016-09-06 04:16 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('data', '0002_add_full_name_to_officer'), 12 | ('data', '0002_alter_choice_fields'), 13 | ] 14 | 15 | operations = [ 16 | ] 17 | -------------------------------------------------------------------------------- /cpdb/search/constants.py: -------------------------------------------------------------------------------- 1 | from search.search_indexers import ( 2 | UnitIndexer, AreaIndexer, CrIndexer, TRRIndexer, 3 | RankIndexer, ZipCodeIndexer, SearchTermItemIndexer, LawsuitIndexer 4 | ) 5 | 6 | DEFAULT_INDEXERS = [ 7 | UnitIndexer, AreaIndexer, CrIndexer, TRRIndexer, 8 | RankIndexer, ZipCodeIndexer, SearchTermItemIndexer, LawsuitIndexer 9 | ] 10 | 11 | DAILY_INDEXERS = [ 12 | CrIndexer, LawsuitIndexer 13 | ] 14 | -------------------------------------------------------------------------------- /ansible/roles/notebook/templates/jupyter.conf.j2: -------------------------------------------------------------------------------- 1 | start on filesystem or runlevel [2345] 2 | stop on shutdown 3 | respawn 4 | 5 | description "Jupyter / IPython Notebook Upstart script" 6 | 7 | script 8 | echo $$ > /var/run/jupyter.pid 9 | exec su -s /bin/bash -c 'exec "$0" "$@"' {{ deploy_user }} -- /home/{{ deploy_user }}/start_jupyter.sh 10 | end script 11 | 12 | pre-stop script 13 | rm /var/run/jupyter.pid 14 | end script 15 | -------------------------------------------------------------------------------- /cpdb/analytics/filters.py: -------------------------------------------------------------------------------- 1 | from django_filters import BaseInFilter, CharFilter, FilterSet 2 | 3 | from .models import SearchTracking 4 | 5 | 6 | class CharInFilter(BaseInFilter, CharFilter): 7 | pass 8 | 9 | 10 | class SearchTrackingFilterSet(FilterSet): 11 | query_types = CharInFilter(field_name='query_type', lookup_expr='in') 12 | 13 | class Meta: 14 | model = SearchTracking 15 | fields = ('query_types', ) 16 | -------------------------------------------------------------------------------- /cpdb/document_cloud/migrations/0006_merge_20181129_2015.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.3 on 2018-11-30 02:15 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('document_cloud', '0005_documentcrawler_source_type_no_defaut_value'), 10 | ('document_cloud', '0003_alter_documentcloudsearchquery_type'), 11 | ] 12 | 13 | operations = [ 14 | ] 15 | -------------------------------------------------------------------------------- /cpdb/es_index/analyzers.py: -------------------------------------------------------------------------------- 1 | from elasticsearch_dsl import analyzer, tokenizer 2 | 3 | 4 | autocomplete_analyzer = analyzer( 5 | 'autocomplete', 6 | filter=['lowercase'], 7 | tokenizer=tokenizer( 8 | 'autocomplete', 'edge_ngram', 9 | min_gram=2, max_gram=10, token_chars=['letter', 'digit'])) 10 | 11 | autocomplete_search_analyzer = analyzer('autocomplete_search', filter=['lowercase'], tokenizer='whitespace') 12 | -------------------------------------------------------------------------------- /cpdb/pinboard/serializers/example_pinboard.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | from shared.serializer import NoNullSerializer 4 | 5 | 6 | class ExamplePinboardSerializer(NoNullSerializer): 7 | id = serializers.CharField(min_length=8, max_length=8, read_only=True, source='pinboard.id') 8 | title = serializers.CharField(source='pinboard.title') 9 | description = serializers.CharField(source='pinboard.description') 10 | -------------------------------------------------------------------------------- /cpdb/toast/factories.py: -------------------------------------------------------------------------------- 1 | import factory 2 | from faker import Faker 3 | 4 | from toast.models import Toast 5 | 6 | fake = Faker() 7 | 8 | 9 | class ToastFactory(factory.django.DjangoModelFactory): 10 | class Meta: 11 | model = Toast 12 | 13 | name = factory.LazyFunction(lambda: fake.word()) 14 | template = factory.LazyFunction(lambda: fake.text(512)) 15 | tags = factory.LazyFunction(lambda: fake.pylist(2, False, str)) 16 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0029_merge_20180207_2137.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.4 on 2018-02-08 03:37 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('data', '0028_merge_20180131_1334'), 12 | ('data', '0028_add_attachment_meta_info'), 13 | ] 14 | 15 | operations = [ 16 | ] 17 | -------------------------------------------------------------------------------- /cpdb/data/tests/management/commands/test_cache_data.py: -------------------------------------------------------------------------------- 1 | from django.test.testcases import TestCase 2 | from django.core.management import call_command 3 | 4 | from mock import patch 5 | from robber import expect 6 | 7 | 8 | class CacheDataTestCase(TestCase): 9 | @patch('data.cache_managers.cache_all') 10 | def test_cache(self, cache_all_mock): 11 | call_command('cache_data') 12 | expect(cache_all_mock).to.be.called_once() 13 | -------------------------------------------------------------------------------- /cpdb/search_mobile/serializers/lawsuit_serializer.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | import pytz 4 | 5 | from shared.serializer import NoNullSerializer 6 | 7 | 8 | class LawsuitSerializer(NoNullSerializer): 9 | id = serializers.IntegerField() 10 | case_no = serializers.CharField() 11 | primary_cause = serializers.CharField() 12 | incident_date = serializers.DateTimeField(format='%Y-%m-%d', default_timezone=pytz.utc) 13 | -------------------------------------------------------------------------------- /cpdb/trr/models/__init__.py: -------------------------------------------------------------------------------- 1 | from .action_response import ActionResponse 2 | from .charge import Charge 3 | from .subject_weapon import SubjectWeapon 4 | from .trr import TRR 5 | from .trr_attachment_request import TRRAttachmentRequest 6 | from .trr_status import TRRStatus 7 | from .weapon_discharge import WeaponDischarge 8 | 9 | __all__ = ['ActionResponse', 'Charge', 'SubjectWeapon', 'TRR', 'TRRAttachmentRequest', 'TRRStatus', 'WeaponDischarge'] 10 | -------------------------------------------------------------------------------- /cpdb/twitterbot/utils/cryptography.py: -------------------------------------------------------------------------------- 1 | import base64 2 | import hashlib 3 | import hmac 4 | 5 | 6 | def get_hash_token(key, msg): 7 | try: 8 | msg = msg.encode('utf-8') 9 | except AttributeError: 10 | pass 11 | hash_digest = hmac.new( 12 | key.encode('utf-8'), 13 | msg=msg, 14 | digestmod=hashlib.sha256 15 | ).digest() 16 | 17 | return f'sha256={base64.b64encode(hash_digest).decode()}' 18 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0028_merge_20180131_1334.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.4 on 2018-01-31 19:34 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('data', '0027_add_race_population'), 12 | ('data', '0027_officer_complaint_percentile'), 13 | ] 14 | 15 | operations = [ 16 | ] 17 | -------------------------------------------------------------------------------- /cpdb/pinboard/serializers/mobile/pinned/__init__.py: -------------------------------------------------------------------------------- 1 | from ..common import AllegationMobileSerializer as PinnedAllegationMobileSerializer 2 | from .officer_serializer import OfficerMobileSerializer as PinnedOfficerMobileSerializer 3 | from .trr_serializer import TRRMobileSerializer as PinnedTRRMobileSerializer 4 | 5 | __all__ = [ 6 | 'PinnedAllegationMobileSerializer', 7 | 'PinnedOfficerMobileSerializer', 8 | 'PinnedTRRMobileSerializer', 9 | ] 10 | -------------------------------------------------------------------------------- /cpdb/trr/models/subject_weapon.py: -------------------------------------------------------------------------------- 1 | from django.contrib.gis.db import models 2 | 3 | from data.models.common import TimeStampsModel 4 | 5 | 6 | class SubjectWeapon(TimeStampsModel): 7 | trr = models.ForeignKey('trr.TRR', on_delete=models.CASCADE) 8 | weapon_type = models.CharField(max_length=64, null=True) 9 | firearm_caliber = models.CharField(max_length=16, null=True) 10 | weapon_description = models.CharField(max_length=150, null=True) 11 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/writers/test_accused_xlsx_writer/csv/empty/Police Witness.csv: -------------------------------------------------------------------------------- 1 | crid,name,gender,race,appointed_date,resignation_date,rank,birth_year,active,complaint_percentile,civilian_allegation_percentile,internal_allegation_percentile,trr_percentile,honorable_mention_percentile,allegation_count,sustained_count,honorable_mention_count,unsustained_count,discipline_count,civilian_compliment_count,trr_count,major_award_count,current_badge,last_unit,current_salary 2 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/writers/test_documents_xlsx_writer/csv/documents_1/Complaint Documents.csv: -------------------------------------------------------------------------------- 1 | title,url,date_discovered,text_content 2 | CRID 1045950 CR Original Case Incident Report 1 of 5,https://assets.documentcloud.org/documents/5679592/CRID.pdf,2019-01-09,CHICAGO POLICE DEPARTMENT RD I HT334604 3 | CRID 1045950 CR Original Case Incident Report 2 of 5,https://assets.documentcloud.org/documents/5678901/CRID.pdf,2019-01-09,CHICAGO POLICE DEPARTMENT RD I HT334604 4 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/writers/test_documents_xlsx_writer/csv/documents_1/Investigation Documents.csv: -------------------------------------------------------------------------------- 1 | title,url,date_discovered,text_content 2 | CRID 1041253 CR Original Case Incident Report 1 of 5,https://assets.documentcloud.org/documents/1041253/CRID.pdf,2019-01-08,CHICAGO POLICE DEPARTMENT RD I HT334111 3 | CRID 1041253 CR Original Case Incident Report 2 of 5,https://assets.documentcloud.org/documents/1041253/CRID.pdf,2019-01-08,CHICAGO POLICE DEPARTMENT RD I HT334111 4 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0058_merge_20180617_2214.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.4 on 2018-06-18 03:14 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('data', '0057_victim_allegation_related_name'), 12 | ('data', '0057_remove-pre-1988-data'), 13 | ] 14 | 15 | operations = [ 16 | ] 17 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0060_merge_058_and_059.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.4 on 2018-07-11 04:12 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('data', '0059_import_old_complaint_address_latlng'), 12 | ('data', '0058_merge_20180617_2214'), 13 | ] 14 | 15 | operations = [ 16 | ] 17 | -------------------------------------------------------------------------------- /cpdb/data/models/police_witness.py: -------------------------------------------------------------------------------- 1 | from django.contrib.gis.db import models 2 | from django_bulk_update.manager import BulkUpdateManager 3 | 4 | from .common import TimeStampsModel 5 | 6 | 7 | class PoliceWitness(TimeStampsModel): 8 | allegation = models.ForeignKey('data.Allegation', on_delete=models.CASCADE, null=True) 9 | officer = models.ForeignKey('data.Officer', on_delete=models.CASCADE, null=True) 10 | 11 | objects = BulkUpdateManager() 12 | -------------------------------------------------------------------------------- /cpdb/search/indices.py: -------------------------------------------------------------------------------- 1 | from es_index.index_aliases import IndexAlias 2 | from .analyzers import autocomplete, autocomplete_search, text_analyzer, text_search_analyzer 3 | 4 | 5 | autocompletes_alias = IndexAlias('autocompletes') 6 | autocompletes = autocompletes_alias.write_index 7 | autocompletes.analyzer(autocomplete) 8 | autocompletes.analyzer(autocomplete_search) 9 | autocompletes.analyzer(text_analyzer) 10 | autocompletes.analyzer(text_search_analyzer) 11 | -------------------------------------------------------------------------------- /cpdb/xlsx/serializers/area_xlsx_serializer.py: -------------------------------------------------------------------------------- 1 | from rest_framework.serializers import Serializer, CharField 2 | 3 | 4 | class AreaXlsxSerializer(Serializer): 5 | name = CharField() 6 | area_type = CharField() 7 | median_income = CharField(allow_null=True) 8 | commander = CharField(source='commander.full_name', allow_null=True) 9 | alderman = CharField(allow_null=True) 10 | police_hq = CharField(source='police_hq.name', allow_null=True) 11 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/writers/test_investigator_xlsx_writer/csv/empty/Accused Officer.csv: -------------------------------------------------------------------------------- 1 | crid,name,gender,race,appointed_date,resignation_date,rank,birth_year,active,complaint_percentile,civilian_allegation_percentile,internal_allegation_percentile,trr_percentile,honorable_mention_percentile,allegation_count,sustained_count,honorable_mention_count,unsustained_count,discipline_count,civilian_compliment_count,trr_count,major_award_count,current_badge,last_unit,current_salary 2 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/writers/test_investigator_xlsx_writer/csv/empty/Police Witness.csv: -------------------------------------------------------------------------------- 1 | crid,name,gender,race,appointed_date,resignation_date,rank,birth_year,active,complaint_percentile,civilian_allegation_percentile,internal_allegation_percentile,trr_percentile,honorable_mention_percentile,allegation_count,sustained_count,honorable_mention_count,unsustained_count,discipline_count,civilian_compliment_count,trr_count,major_award_count,current_badge,last_unit,current_salary 2 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | indent_style = space 11 | trim_trailing_whitespace = true 12 | 13 | [*.{js,json,html,sass}] 14 | charset = utf-8 15 | indent_style = space 16 | indent_size = 2 17 | 18 | [*.py] 19 | charset = utf-8 20 | indent_size = 4 21 | -------------------------------------------------------------------------------- /cpdb/config/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for cpdb project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.9/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "cpdb.settings") 15 | application = get_wsgi_application() 16 | -------------------------------------------------------------------------------- /cpdb/data/utils/interpolate.py: -------------------------------------------------------------------------------- 1 | class ScaleThreshold: 2 | def __init__(self, domain, target_range): 3 | self.domain = domain 4 | self.target_range = target_range 5 | 6 | def interpolate(self, value): 7 | target_ind = 0 8 | for ind, domain_value in enumerate(self.domain): 9 | if domain_value > value: 10 | break 11 | target_ind = ind + 1 12 | return self.target_range[target_ind] 13 | -------------------------------------------------------------------------------- /cpdb/document_cloud/models/document_cloud_search_query.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | from document_cloud.constants import DOCUMENT_TYPES 4 | from data.models.common import TimeStampsModel 5 | from utils.models.choice_array_field import ChoiceArrayField 6 | 7 | 8 | class DocumentCloudSearchQuery(TimeStampsModel): 9 | types = ChoiceArrayField(models.CharField(max_length=20, choices=DOCUMENT_TYPES), default=list) 10 | query = models.TextField() 11 | -------------------------------------------------------------------------------- /apiary/analytic_events.md: -------------------------------------------------------------------------------- 1 | ## Analytic events [/events/] 2 | 3 | ### Create Event [POST] 4 | 5 | + Request (application/json) 6 | 7 | + Body 8 | 9 | { 10 | "name": "some-click", 11 | "data": { 12 | "id": 12, 13 | "title": "How accurate is the data?", 14 | "timestamp": "2017-01-23T03:11:53Z" 15 | } 16 | } 17 | 18 | + Response 201 19 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/writers/test_accused_xlsx_writer/csv/empty/Coaccused Officer.csv: -------------------------------------------------------------------------------- 1 | name,gender,race,appointed_date,resignation_date,rank,birth_year,active,complaint_percentile,civilian_allegation_percentile,internal_allegation_percentile,trr_percentile,honorable_mention_percentile,allegation_count,sustained_count,honorable_mention_count,unsustained_count,discipline_count,civilian_compliment_count,trr_count,major_award_count,current_badge,last_unit,current_salary,coaccusal_count 2 | -------------------------------------------------------------------------------- /apiary/pinboard_latest_retrieved.md: -------------------------------------------------------------------------------- 1 | ## Lastest retrieved pinboard [/pinboards/latest-retrieved-pinboard/] 2 | 3 | ### Get the lastest retrieved pinboard of the current session 4 | 5 | + Response 200 (application/json) 6 | 7 | { 8 | "id": "5cd06f2b", 9 | "title": "My Pinboard", 10 | "officer_ids": [1, 2], 11 | "crids": ["123abc"], 12 | "trr_ids": [1], 13 | "description": "abc" 14 | } 15 | -------------------------------------------------------------------------------- /cpdb/cms/migrations/0012_delete_faqpage.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.4 on 2018-05-14 09:21 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('cms', '0011_auto_20170301_0227'), 12 | ] 13 | 14 | operations = [ 15 | migrations.DeleteModel( 16 | name='FAQPage', 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /cpdb/social_graph/serializers/accused_serializer.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | import pytz 4 | 5 | from shared.serializer import NoNullSerializer 6 | 7 | 8 | class AccusedSerializer(NoNullSerializer): 9 | officer_id_1 = serializers.IntegerField() 10 | officer_id_2 = serializers.IntegerField() 11 | incident_date = serializers.DateTimeField(format='%Y-%m-%d', default_timezone=pytz.utc) 12 | accussed_count = serializers.IntegerField() 13 | -------------------------------------------------------------------------------- /cpdb/trr/models/charge.py: -------------------------------------------------------------------------------- 1 | from django.contrib.gis.db import models 2 | 3 | from data.models.common import TimeStampsModel 4 | 5 | 6 | class Charge(TimeStampsModel): 7 | trr = models.ForeignKey('trr.TRR', on_delete=models.CASCADE) 8 | sr_no = models.PositiveIntegerField(null=True) 9 | statute = models.CharField(max_length=64, null=True) 10 | description = models.CharField(max_length=64, null=True) 11 | subject_no = models.PositiveIntegerField(null=True) 12 | -------------------------------------------------------------------------------- /cpdb/data/models/common.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | from taggit.managers import TaggableManager 4 | 5 | 6 | class TaggableModel(models.Model): 7 | tags = TaggableManager(blank=True) 8 | 9 | class Meta: 10 | abstract = True 11 | 12 | 13 | class TimeStampsModel(models.Model): 14 | created_at = models.DateTimeField(auto_now_add=True) 15 | updated_at = models.DateTimeField(auto_now=True) 16 | 17 | class Meta: 18 | abstract = True 19 | -------------------------------------------------------------------------------- /cpdb/shared/browsable_api_renderder_without_form.py: -------------------------------------------------------------------------------- 1 | from rest_framework.renderers import BrowsableAPIRenderer 2 | 3 | 4 | class BrowsableAPIRendererWithoutForms(BrowsableAPIRenderer): 5 | """Renders the browsable api, but excludes the forms.""" 6 | def get_rendered_html_form(self, *args, **kwargs): 7 | """ 8 | We don't want the HTML forms to be rendered because it can be 9 | really slow with large datasets 10 | """ 11 | return "" 12 | -------------------------------------------------------------------------------- /cpdb/status/tests/test_views.py: -------------------------------------------------------------------------------- 1 | from django.urls import reverse 2 | 3 | from rest_framework.test import APITestCase 4 | from rest_framework import status 5 | from robber import expect 6 | 7 | 8 | class StatusViewsTestCase(APITestCase): 9 | def test_list(self): 10 | url = reverse('api-v2:status-list') 11 | response = self.client.get(url) 12 | expect(response.status_code).to.eq(status.HTTP_200_OK) 13 | expect(response.data).to.eq({'ok': True}) 14 | -------------------------------------------------------------------------------- /cpdb/email_service/constants.py: -------------------------------------------------------------------------------- 1 | CR_ATTACHMENT_AVAILABLE = 'cr_available' 2 | CR_ATTACHMENT_REQUEST = 'cr_request' 3 | TRR_ATTACHMENT_AVAILABLE = 'trr_available' 4 | TRR_ATTACHMENT_REQUEST = 'trr_request' 5 | ATTACHMENT_TYPE_CHOICES = [ 6 | [CR_ATTACHMENT_AVAILABLE, 'CR attachment available'], 7 | [CR_ATTACHMENT_REQUEST, 'CR attachment request'], 8 | [TRR_ATTACHMENT_AVAILABLE, 'TRR attachment available'], 9 | [TRR_ATTACHMENT_REQUEST, 'TRR attachment request'], 10 | ] 11 | -------------------------------------------------------------------------------- /cpdb/popup/factories.py: -------------------------------------------------------------------------------- 1 | import factory 2 | from faker import Faker 3 | 4 | from popup.models import Popup 5 | 6 | fake = Faker() 7 | 8 | 9 | class PopupFactory(factory.django.DjangoModelFactory): 10 | class Meta: 11 | model = Popup 12 | 13 | name = factory.LazyFunction(lambda: fake.word()) 14 | page = factory.LazyFunction(lambda: fake.word()) 15 | title = factory.LazyFunction(lambda: fake.word()) 16 | text = factory.LazyFunction(lambda: fake.text(512)) 17 | -------------------------------------------------------------------------------- /cpdb/analytics/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | from .models import Event, SearchTracking 4 | 5 | 6 | class EventSerializer(serializers.ModelSerializer): 7 | class Meta: 8 | model = Event 9 | fields = ('id', 'name', 'data') 10 | 11 | 12 | class SearchTrackingSerializer(serializers.ModelSerializer): 13 | class Meta: 14 | model = SearchTracking 15 | fields = ('id', 'query', 'usages', 'results', 'query_type', 'last_entered') 16 | -------------------------------------------------------------------------------- /cpdb/cms/permissions.py: -------------------------------------------------------------------------------- 1 | from rest_framework.permissions import SAFE_METHODS, BasePermission 2 | 3 | 4 | class IsAuthenticatedOrReadOnlyOrCreate(BasePermission): 5 | """ 6 | The request is authenticated as a user, or is a read-only request. 7 | """ 8 | 9 | def has_permission(self, request, view): 10 | return ( 11 | request.method in SAFE_METHODS + ('POST',) or 12 | request.user and 13 | request.user.is_authenticated 14 | ) 15 | -------------------------------------------------------------------------------- /cpdb/lawsuit/serializers/top_lawsuit_serializer.py: -------------------------------------------------------------------------------- 1 | import pytz 2 | 3 | from rest_framework import serializers 4 | 5 | from shared.serializer import NoNullSerializer 6 | 7 | 8 | class TopLawsuitSerializer(NoNullSerializer): 9 | id = serializers.IntegerField() 10 | case_no = serializers.CharField() 11 | summary = serializers.CharField() 12 | primary_cause = serializers.CharField() 13 | incident_date = serializers.DateTimeField(format='%Y-%m-%d', default_timezone=pytz.utc) 14 | -------------------------------------------------------------------------------- /cpdb/search_mobile/queries.py: -------------------------------------------------------------------------------- 1 | from data.models import Allegation 2 | 3 | from search.queries import OfficerQuery, CrQuery, TrrQuery, LawsuitQuery 4 | 5 | 6 | class OfficerMobileQuery(OfficerQuery): 7 | pass 8 | 9 | 10 | class CrMobileQuery(CrQuery): 11 | def queryset(self): 12 | return Allegation.objects.select_related('most_common_category') 13 | 14 | 15 | class TrrMobileQuery(TrrQuery): 16 | pass 17 | 18 | 19 | class LawsuitMobileQuery(LawsuitQuery): 20 | pass 21 | -------------------------------------------------------------------------------- /cpdb/search_mobile/serializers/officer_recent_serializer.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | from shared.serializer import NoNullSerializer 4 | 5 | 6 | class OfficerRecentSerializer(NoNullSerializer): 7 | id = serializers.IntegerField() 8 | name = serializers.CharField(source='full_name') 9 | badge = serializers.CharField(source='current_badge') 10 | type = serializers.SerializerMethodField() 11 | 12 | def get_type(self, obj): 13 | return 'OFFICER' 14 | -------------------------------------------------------------------------------- /cpdb/email_service/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from .models import EmailTemplate 3 | 4 | 5 | class EmailTemplateAdmin(admin.ModelAdmin): 6 | list_display = ('type', 'subject', 'body', 'from_email') 7 | 8 | def has_add_permission(self, request): 9 | return False # pragma: no cover 10 | 11 | def has_delete_permission(self, request, obj=None): 12 | return False # pragma: no cover 13 | 14 | 15 | admin.site.register(EmailTemplate, EmailTemplateAdmin) 16 | -------------------------------------------------------------------------------- /cpdb/es_index/utils.py: -------------------------------------------------------------------------------- 1 | import uuid 2 | from time import time 3 | 4 | 5 | per_run_uuid = str(uuid.uuid4()) 6 | 7 | 8 | def timing_validate(message): 9 | def real_decorator(func): 10 | def wrapper(*args, **kwargs): 11 | print(message) 12 | start_time = time() 13 | return_value = func(*args, **kwargs) 14 | print(f'Done in {time() - start_time}') 15 | return return_value 16 | return wrapper 17 | return real_decorator 18 | -------------------------------------------------------------------------------- /cpdb/pinboard/serializers/mobile/relevant/__init__.py: -------------------------------------------------------------------------------- 1 | from .officer_serializer import OfficerMobileSerializer as RelevantOfficerMobileSerializer 2 | from .allegation_serializer import AllegationMobileSerializer as RelevantAllegationMobileSerializer 3 | from .document_serializer import DocumentSerializer as RelevantDocumentMobileSerializer 4 | 5 | __all__ = [ 6 | 'RelevantOfficerMobileSerializer', 7 | 'RelevantAllegationMobileSerializer', 8 | 'RelevantDocumentMobileSerializer', 9 | ] 10 | -------------------------------------------------------------------------------- /cpdb/units/tests/mixins.py: -------------------------------------------------------------------------------- 1 | from units.index_aliases import units_index_alias 2 | from units.indexers import UnitIndexer 3 | 4 | 5 | class UnitSummaryTestCaseMixin(object): 6 | def setUp(self): 7 | units_index_alias.write_index.delete(ignore=404) 8 | units_index_alias.read_index.create(ignore=400) 9 | 10 | def refresh_index(self): 11 | with units_index_alias.indexing(): 12 | UnitIndexer().reindex() 13 | units_index_alias.write_index.refresh() 14 | -------------------------------------------------------------------------------- /lambda/upload_pdf/lambda_function.py: -------------------------------------------------------------------------------- 1 | from urllib.request import urlopen, Request 2 | 3 | import boto3 4 | 5 | 6 | def lambda_handler(event, context): 7 | s3 = boto3.client('s3') 8 | url = event['url'] 9 | key = event['key'] 10 | bucket = event['bucket'] 11 | req = Request(url, data=None, headers={'User-Agent': ''}) 12 | data = urlopen(req).read() 13 | 14 | s3.put_object(Body=data, Bucket=bucket, Key=key) 15 | return { 16 | 'statusCode': 200, 17 | } 18 | -------------------------------------------------------------------------------- /cpdb/data/tests/models/test_officer_badge_number.py: -------------------------------------------------------------------------------- 1 | from django.test.testcases import SimpleTestCase 2 | 3 | from robber.expect import expect 4 | 5 | from data.models import Officer, OfficerBadgeNumber 6 | 7 | 8 | class OfficerBadgeNumberTestCase(SimpleTestCase): 9 | def test_str(self): 10 | officer = Officer(first_name='Jeffery', last_name='Aaron') 11 | expect( 12 | str(OfficerBadgeNumber(officer=officer, star='123456')) 13 | ).to.eq('Jeffery Aaron - 123456') 14 | -------------------------------------------------------------------------------- /cpdb/twitterbot/constants.py: -------------------------------------------------------------------------------- 1 | IDS_OF_OTHER_BOTS = [30582622, 4880788160, 4923697764] 2 | TWITTER_ACTIVITY_API = 'https://api.twitter.com/1.1/account_activity/all/' 3 | 4 | RESPONSE_TYPE_SINGLE_OFFICER = 'single_officer' 5 | RESPONSE_TYPE_COACCUSED_PAIR = 'coaccused_pair' 6 | RESPONSE_TYPE_NOT_FOUND = 'not_found' 7 | RESPONSE_TYPE_CHOICES = [ 8 | [RESPONSE_TYPE_SINGLE_OFFICER, 'Single Officer'], 9 | [RESPONSE_TYPE_COACCUSED_PAIR, 'Coaccused Pair'], 10 | [RESPONSE_TYPE_NOT_FOUND, 'Not Found'] 11 | ] 12 | -------------------------------------------------------------------------------- /cpdb/search_mobile/tests/serializers/test_trr_recent_serializer.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | from robber import expect 4 | 5 | from search_mobile.serializers import TRRRecentSerializer 6 | from trr.factories import TRRFactory 7 | 8 | 9 | class TRRRecentSerializerTestCase(TestCase): 10 | def test_serialization(self): 11 | trr = TRRFactory(id=1) 12 | 13 | expect(TRRRecentSerializer(trr).data).to.eq({ 14 | 'id': 1, 15 | 'type': 'TRR', 16 | }) 17 | -------------------------------------------------------------------------------- /cpdb/twitterbot/tests/mixins.py: -------------------------------------------------------------------------------- 1 | from officers.index_aliases import officers_index_alias 2 | from officers.indexers import OfficersIndexer 3 | 4 | 5 | class RebuildIndexMixin: 6 | def setUp(self): 7 | officers_index_alias.write_index.delete(ignore=404) 8 | officers_index_alias.read_index.create(ignore=400) 9 | 10 | def refresh_index(self): 11 | with officers_index_alias.indexing(): 12 | OfficersIndexer().reindex() 13 | officers_index_alias.write_index.refresh() 14 | -------------------------------------------------------------------------------- /cpdb/xlsx/serializers/attachment_xlsx_serializer.py: -------------------------------------------------------------------------------- 1 | from rest_framework.serializers import Serializer, CharField, DateTimeField 2 | 3 | import pytz 4 | 5 | 6 | class AttachmentXlsxSerializer(Serializer): 7 | title = CharField(allow_blank=True, allow_null=True) 8 | url = CharField(allow_blank=True) 9 | date_discovered = DateTimeField( 10 | source='external_created_at', allow_null=True, format='%Y-%m-%d', default_timezone=pytz.utc 11 | ) 12 | text_content = CharField(allow_blank=True) 13 | -------------------------------------------------------------------------------- /apiary/officer_request_download.md: -------------------------------------------------------------------------------- 1 | ## Officer request download [/officers/{officer_id}/request-download/{?with-docs}] 2 | 3 | ### Get the url to the officer zip file[GET] 4 | 5 | + Parameters 6 | + officer_id (number) - number ID of the officer 7 | + with-docs (string, optional) - should the zip file contain docs or not 8 | + Default: `false` 9 | 10 | + Response 200 (application/text) 11 | 12 | "https://officer-content-staging.s3.amazonaws.com/zip_with_docs/Jerome_Finnigan_with_docs.zip" 13 | -------------------------------------------------------------------------------- /bin/shows_pr_since_last_deploy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | git checkout master 4 | CUR_ID="$(git rev-parse HEAD)" 5 | git checkout -b "master$CUR_ID" 6 | git merge develop -m "Merge changes from develop" 7 | echo "----------------- PULL REQUESTS SINCE LAST DEPLOY -----------------" 8 | git --no-pager log $CUR_ID..HEAD --pretty=oneline --abbrev-commit --grep "Merge pull request" 9 | echo "-------------------------------------------------------------------" 10 | git checkout master 11 | git branch -D "master$CUR_ID" 12 | -------------------------------------------------------------------------------- /apiary/officer_timeline_mini_map.md: -------------------------------------------------------------------------------- 1 | ## Officer timeline minimap [/officers/{officer_id}/timeline-minimap] 2 | 3 | ### Get Officer timeline minimap [GET] 4 | 5 | + Parameters 6 | + officer_id (number) - number ID of the officer 7 | 8 | + Response 200 (application/json) 9 | 10 | [ 11 | { 12 | "kind": "cr", 13 | "year": 2016 14 | }, 15 | { 16 | "kind": "trr", 17 | "year": 2015 18 | } 19 | ] 20 | -------------------------------------------------------------------------------- /cpdb/app_config/management/commands/create_initial_app_config.py: -------------------------------------------------------------------------------- 1 | from django.core.management.base import BaseCommand 2 | from app_config.models import AppConfig 3 | from app_config.constants import APP_CONFIG 4 | 5 | 6 | class Command(BaseCommand): 7 | def handle(self, *args, **options): 8 | for config_data in APP_CONFIG: 9 | config_object = AppConfig.objects.filter(name=config_data['name']).first() 10 | if not config_object: 11 | AppConfig.objects.create(**config_data) 12 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0098_attachmentfile_text_content.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.3 on 2018-12-28 09:08 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('data', '0097_merge_20190101_2250'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='attachmentfile', 15 | name='text_content', 16 | field=models.TextField(blank=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /cpdb/es_index/indices.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings 2 | 3 | from elasticsearch_dsl import Index as BaseIndex 4 | 5 | 6 | class Index(BaseIndex): 7 | def __init__(self, index_name, *args, **kwargs): 8 | if getattr(settings, 'TEST', False): 9 | super(Index, self).__init__(f'test_{index_name}', *args, **kwargs) 10 | self.settings(number_of_shards=1, number_of_replicas=0) 11 | else: 12 | super(Index, self).__init__(index_name, *args, **kwargs) # pragma: no cover 13 | -------------------------------------------------------------------------------- /cpdb/analytics/models/search_tracking.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | from analytics.constants import QUERY_TYPES 4 | 5 | 6 | class SearchTracking(models.Model): 7 | query = models.CharField(max_length=255) 8 | usages = models.PositiveIntegerField(default=0) 9 | results = models.PositiveIntegerField(default=0) 10 | query_type = models.CharField(choices=QUERY_TYPES, max_length=20) 11 | created_at = models.DateTimeField(auto_now_add=True) 12 | last_entered = models.DateTimeField(auto_now=True) 13 | -------------------------------------------------------------------------------- /cpdb/document_cloud/migrations/0007_rename_timestamp_to_created_at.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.3 on 2018-12-14 03:58 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('document_cloud', '0006_merge_20181129_2015'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RenameField( 14 | model_name='documentcrawler', 15 | old_name='timestamp', 16 | new_name='created_at', 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /cpdb/toast/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.contrib.admin import ModelAdmin 3 | from django.db.models import CharField 4 | from django.forms import TextInput 5 | 6 | from toast.models import Toast 7 | 8 | 9 | class ToastAdmin(ModelAdmin): 10 | list_display = ['name', 'template', 'tags'] 11 | readonly_fields = ['tags'] 12 | 13 | formfield_overrides = { 14 | CharField: {'widget': TextInput(attrs={'size': '101'})}, 15 | } 16 | 17 | 18 | admin.site.register(Toast, ToastAdmin) 19 | -------------------------------------------------------------------------------- /cpdb/tracker/tests/mixins.py: -------------------------------------------------------------------------------- 1 | from tracker.index_aliases import tracker_index_alias 2 | from tracker.indexers import AttachmentFileIndexer 3 | 4 | 5 | class TrackerTestCaseMixin(object): 6 | def setUp(self): 7 | tracker_index_alias.write_index.delete(ignore=404) 8 | tracker_index_alias.read_index.create(ignore=400) 9 | 10 | def refresh_index(self): 11 | with tracker_index_alias.indexing(): 12 | AttachmentFileIndexer().reindex() 13 | tracker_index_alias.write_index.refresh() 14 | -------------------------------------------------------------------------------- /cpdb/trr/migrations/0021_auto_20240610_2200.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.10 on 2024-06-11 03:00 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('trr', '0020_auto_20240610_2151'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='weapondischarge', 15 | name='weapon_type', 16 | field=models.CharField(max_length=50, null=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0112_attachmentfile_show.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.3 on 2019-02-14 04:48 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('data', '0111_add_views_count_and_downloads_count_fields'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='attachmentfile', 15 | name='show', 16 | field=models.BooleanField(default=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0133_auto_20240716_1545.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.10 on 2024-07-16 20:45 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('data', '0132_auto_20240609_1919'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='officerallegation', 15 | name='final_outcome', 16 | field=models.CharField(blank=True, max_length=100), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0134_auto_20240716_1556.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.10 on 2024-07-16 20:56 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('data', '0133_auto_20240716_1545'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='officerallegation', 15 | name='recc_outcome', 16 | field=models.CharField(blank=True, max_length=100), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /cpdb/trr/migrations/0018_auto_20240527_1741.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.10 on 2024-05-27 22:41 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('trr', '0017_add_created_at_and_updated_at_columns'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='trr', 15 | name='officer_rank', 16 | field=models.CharField(max_length=50, null=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /cpdb/trr/migrations/0019_auto_20240610_2108.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.10 on 2024-06-11 02:08 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('trr', '0018_auto_20240527_1741'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='subjectweapon', 15 | name='weapon_description', 16 | field=models.CharField(max_length=150, null=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0095_rename_timestamp_to_created_at.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.3 on 2018-12-14 03:58 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('data', '0094_change_attachmentfile_external_columns'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RenameField( 14 | model_name='attachmentrequest', 15 | old_name='timestamp', 16 | new_name='created_at', 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0122_attachmentfile_is_external_ocr.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.10 on 2020-05-26 04:53 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('data', '0121_allow_tags_to_be_blanked'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='attachmentfile', 15 | name='is_external_ocr', 16 | field=models.BooleanField(default=False), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /cpdb/data/models/attachment_narrative.py: -------------------------------------------------------------------------------- 1 | from django.contrib.gis.db import models 2 | 3 | from .common import TimeStampsModel 4 | 5 | 6 | class AttachmentNarrative(TimeStampsModel): 7 | attachment = models.ForeignKey( 8 | 'data.AttachmentFile', on_delete=models.CASCADE, related_name='attachment_narratives' 9 | ) 10 | page_num = models.IntegerField() 11 | section_name = models.CharField(max_length=255) 12 | column_name = models.CharField(max_length=255) 13 | text_content = models.TextField(blank=True) 14 | -------------------------------------------------------------------------------- /cpdb/lawsuit/migrations/0003_lawsuit_primary_cause.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.10 on 2020-08-11 04:58 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('lawsuit', '0002_lawsuit_point'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='lawsuit', 15 | name='primary_cause', 16 | field=models.CharField(blank=True, max_length=255, null=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /cpdb/shared/aws.py: -------------------------------------------------------------------------------- 1 | import boto3 2 | 3 | 4 | class AWS(object): 5 | def __init__(self): 6 | self._s3 = None 7 | self._lambda_client = None 8 | 9 | @property 10 | def s3(self): 11 | if not self._s3: 12 | self._s3 = boto3.client('s3') 13 | return self._s3 14 | 15 | @property 16 | def lambda_client(self): 17 | if not self._lambda_client: 18 | self._lambda_client = boto3.client('lambda') 19 | return self._lambda_client 20 | 21 | 22 | aws = AWS() 23 | -------------------------------------------------------------------------------- /cpdb/trr/migrations/0020_auto_20240610_2151.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.10 on 2024-06-11 02:51 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('trr', '0019_auto_20240610_2108'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='weapondischarge', 15 | name='weapon_type_description', 16 | field=models.CharField(max_length=70, null=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0118_attachmentfile_reprocess_text_count.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.11 on 2019-11-13 07:26 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('data', '0117_attachmentfile_tags'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='attachmentfile', 15 | name='reprocess_text_count', 16 | field=models.IntegerField(default=0), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /cpdb/toast/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework.fields import CharField, SerializerMethodField 2 | from rest_framework.serializers import Serializer 3 | 4 | 5 | class ToastBaseSerializer(Serializer): 6 | template = CharField(max_length=255) 7 | 8 | 9 | class ToastDesktopSerializer(ToastBaseSerializer): 10 | name = CharField(max_length=25) 11 | 12 | 13 | class ToastMobileSerializer(ToastBaseSerializer): 14 | name = SerializerMethodField() 15 | 16 | def get_name(self, obj): 17 | return obj.name.replace('MOBILE ', '') 18 | -------------------------------------------------------------------------------- /cpdb/trr/migrations/0016_rename_timestamp_to_created_at.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.3 on 2018-12-14 03:58 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('trr', '0015_attachment_request_add_airtable_record_id'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RenameField( 14 | model_name='trrattachmentrequest', 15 | old_name='timestamp', 16 | new_name='created_at', 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /cpdb/search/serializers/__init__.py: -------------------------------------------------------------------------------- 1 | from .lawsuit_serializer import LawsuitSerializer 2 | from .officer_recent_serializer import OfficerRecentSerializer 3 | from .allegation_recent_serializer import AllegationRecentSerializer 4 | from .trr_recent_serializer import TRRRecentSerializer 5 | from .lawsuit_recent_serializer import LawsuitRecentSerializer 6 | 7 | __all__ = [ 8 | 'LawsuitSerializer', 9 | 'OfficerRecentSerializer', 10 | 'AllegationRecentSerializer', 11 | 'TRRRecentSerializer', 12 | 'LawsuitRecentSerializer', 13 | ] 14 | -------------------------------------------------------------------------------- /cpdb/document_cloud/migrations/0011_documentcrawler_log_key.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.3 on 2019-02-28 02:13 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('document_cloud', '0010_documentcrawler_status'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='documentcrawler', 15 | name='log_key', 16 | field=models.CharField(max_length=255, null=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /cpdb/pinboard/serializers/desktop/relevant/document_serializer.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | from data.models import AttachmentFile 4 | from .allegation_serializer import AllegationSerializer 5 | 6 | 7 | class DocumentSerializer(serializers.ModelSerializer): 8 | allegation = AllegationSerializer(source='owner') 9 | 10 | class Meta: 11 | model = AttachmentFile 12 | fields = ( 13 | 'id', 14 | 'preview_image_url', 15 | 'url', 16 | 'allegation', 17 | ) 18 | -------------------------------------------------------------------------------- /cpdb/search_mobile/serializers/__init__.py: -------------------------------------------------------------------------------- 1 | from .lawsuit_serializer import LawsuitSerializer 2 | from .officer_recent_serializer import OfficerRecentSerializer 3 | from .allegation_recent_serializer import AllegationRecentSerializer 4 | from .trr_recent_serializer import TRRRecentSerializer 5 | from .lawsuit_recent_serializer import LawsuitRecentSerializer 6 | 7 | __all__ = [ 8 | 'LawsuitSerializer', 9 | 'OfficerRecentSerializer', 10 | 'AllegationRecentSerializer', 11 | 'TRRRecentSerializer', 12 | 'LawsuitRecentSerializer', 13 | ] 14 | -------------------------------------------------------------------------------- /cpdb/twitterbot/management/commands/list_subscriptions.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | from twitterbot.twitter_base_command import TwitterBaseCommand 4 | 5 | 6 | class Command(TwitterBaseCommand): 7 | def handle(self, *args, **options): 8 | token = self.twitter_client.get_bearer_token() 9 | 10 | if token: 11 | subscriptions = self.twitter_client.subscription.all(token) 12 | self.stdout.write(json.dumps(subscriptions, indent=2)) 13 | else: 14 | self.stderr.write('Cannot get authentication token') 15 | -------------------------------------------------------------------------------- /cpdb/data/cache_managers/__init__.py: -------------------------------------------------------------------------------- 1 | from activity_grid.cache_managers import activity_pair_card_cache_manager 2 | from . import allegation_cache_manager, officer_cache_manager, salary_cache_manager 3 | from lawsuit.cache_managers import lawsuit_cache_manager 4 | 5 | 6 | managers = [ 7 | allegation_cache_manager, 8 | officer_cache_manager, 9 | salary_cache_manager, 10 | activity_pair_card_cache_manager, 11 | lawsuit_cache_manager 12 | ] 13 | 14 | 15 | def cache_all(): 16 | for manager in managers: 17 | manager.cache_data() 18 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0135_add_investigating_agency_column.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.10 on 2024-08-09 21:01 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('data', '0134_auto_20240716_1556'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='investigatorallegation', 15 | name='investigating_agency', 16 | field=models.CharField(max_length=32, null=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /cpdb/lawsuit/migrations/0009_change_lawsuit_location_max_length.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.10 on 2020-08-14 09:25 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('lawsuit', '0008_add_default_value_to_payment_fields'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='lawsuit', 15 | name='location', 16 | field=models.CharField(blank=True, max_length=255), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /cpdb/lawsuit/migrations/0010_remove_lawsuit_plaintiff_unique_constraint.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.10 on 2020-08-14 11:25 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('lawsuit', '0009_change_lawsuit_location_max_length'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='lawsuitplaintiff', 15 | name='name', 16 | field=models.CharField(max_length=255), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /cpdb/search/serializers/trr_recent_serializer.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | import pytz 4 | 5 | from shared.serializer import NoNullSerializer 6 | 7 | 8 | class TRRRecentSerializer(NoNullSerializer): 9 | id = serializers.IntegerField() 10 | force_type = serializers.CharField(max_length=255, source='top_force_type') 11 | trr_datetime = serializers.DateTimeField(format='%Y-%m-%d', default_timezone=pytz.utc) 12 | type = serializers.SerializerMethodField() 13 | 14 | def get_type(self, obj): 15 | return 'TRR' 16 | -------------------------------------------------------------------------------- /cpdb/vftg/views.py: -------------------------------------------------------------------------------- 1 | from rest_framework import viewsets, status 2 | from rest_framework.response import Response 3 | 4 | from vftg.mailchimp_service import MailchimpService, MailchimpAPIError 5 | 6 | 7 | class VFTGViewSet(viewsets.ViewSet): 8 | def create(self, request): 9 | try: 10 | MailchimpService.subscribe(request.data['email']) 11 | except MailchimpAPIError as e: 12 | return Response({'success': False, 'detail': e.value}, status=status.HTTP_400_BAD_REQUEST) 13 | return Response({'success': True}) 14 | -------------------------------------------------------------------------------- /cpdb/cms/migrations/0006_faqpage_order.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.9.5 on 2017-01-10 03:31 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('cms', '0005_faqpage'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='faqpage', 17 | name='order', 18 | field=models.PositiveIntegerField(default=0), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0129_add_db_index_to_allegation_category.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.10 on 2020-09-11 07:15 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('data', '0128_officer_allegations'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='allegationcategory', 15 | name='category', 16 | field=models.CharField(blank=True, db_index=True, max_length=255), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /cpdb/data/tests/models/test_victim.py: -------------------------------------------------------------------------------- 1 | from django.test.testcases import TestCase 2 | 3 | from robber.expect import expect 4 | 5 | from data.factories import VictimFactory 6 | 7 | 8 | class VictimTestCase(TestCase): 9 | def test_gender_display(self): 10 | expect(VictimFactory(gender='M').gender_display).to.equal('Male') 11 | expect(VictimFactory(gender='F').gender_display).to.equal('Female') 12 | expect(VictimFactory(gender='X').gender_display).to.equal('X') 13 | expect(VictimFactory(gender='?').gender_display).to.equal('?') 14 | -------------------------------------------------------------------------------- /cpdb/lawsuit/migrations/0006_lawsuit_total_payments.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.10 on 2020-08-28 07:43 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('lawsuit', '0005_add_cache_columns_to_lawsuits'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='lawsuit', 15 | name='total_payments', 16 | field=models.DecimalField(decimal_places=2, max_digits=16, null=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /cpdb/pinboard/serializers/mobile/relevant/document_serializer.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | from data.models import AttachmentFile 4 | from .allegation_serializer import AllegationMobileSerializer 5 | 6 | 7 | class DocumentSerializer(serializers.ModelSerializer): 8 | allegation = AllegationMobileSerializer(source='owner') 9 | 10 | class Meta: 11 | model = AttachmentFile 12 | fields = ( 13 | 'id', 14 | 'preview_image_url', 15 | 'url', 16 | 'allegation', 17 | ) 18 | -------------------------------------------------------------------------------- /cpdb/pinboard/utils.py: -------------------------------------------------------------------------------- 1 | import uuid 2 | 3 | 4 | def generate_hex_from_uuid(length): 5 | if length % 2 != 0: 6 | raise ValueError(f'length must be an even number, got {length}') 7 | return uuid.uuid4().bytes[0:(length // 2)].hex().lstrip("0x").zfill(length) 8 | 9 | 10 | def int_to_zero_padded_hex(x, length): 11 | if x < 0 or x >= 16**length: 12 | raise ValueError(f'x must be within [0, 16**{length}], got {x}') 13 | return hex(x).lstrip("0x").zfill(length) 14 | 15 | 16 | def zero_padded_hex_to_int(x): 17 | return int(x, 16) 18 | -------------------------------------------------------------------------------- /cpdb/activity_grid/migrations/0007_activitypaircard_coaccusal_count.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.3 on 2019-02-13 02:27 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('activity_grid', '0006_add_created_at_and_updated_at_columns'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='activitypaircard', 15 | name='coaccusal_count', 16 | field=models.IntegerField(default=0), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0020_rename_field_type_to_award_type.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.4 on 2017-10-20 02:59 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('data', '0019_auto_20171019_0153'), 12 | ] 13 | 14 | operations = [ 15 | migrations.RenameField( 16 | model_name='award', 17 | old_name='type', 18 | new_name='award_type', 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0036_policeunit_active.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.4 on 2018-05-22 08:43 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('data', '0035_area_police_hq'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='policeunit', 17 | name='active', 18 | field=models.NullBooleanField(), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0106_add_field_police_witnesses.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.3 on 2019-01-08 03:53 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('data', '0105_change_allegation_to_fk'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='allegation', 15 | name='police_witnesses', 16 | field=models.ManyToManyField(through='data.PoliceWitness', to='data.Officer'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0119_add_is_extracted_summary_field_to_allegation.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.11 on 2019-12-19 08:22 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('data', '0118_attachmentfile_reprocess_text_count'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='allegation', 15 | name='is_extracted_summary', 16 | field=models.BooleanField(default=False), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /cpdb/lawsuit/migrations/0002_lawsuit_point.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.10 on 2020-08-10 08:25 2 | 3 | import django.contrib.gis.db.models.fields 4 | from django.db import migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('lawsuit', '0001_initial'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='lawsuit', 16 | name='point', 17 | field=django.contrib.gis.db.models.fields.PointField(null=True, srid=4326), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /cpdb/lawsuit/migrations/0007_alter_officers_fields_in_lawsuits.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.10 on 2020-08-28 08:42 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('lawsuit', '0006_lawsuit_total_payments'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='lawsuit', 15 | name='officers', 16 | field=models.ManyToManyField(related_name='lawsuits', to='data.Officer'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /cpdb/activity_grid/cache_managers/activity_pair_card_cache_manager.py: -------------------------------------------------------------------------------- 1 | from django.db.models import OuterRef 2 | 3 | from activity_grid.models import ActivityPairCard 4 | from data.models import Allegation 5 | from data.utils.subqueries import SQCount 6 | 7 | 8 | def cache_data(): 9 | allegations = Allegation.objects.filter( 10 | officerallegation__officer=OuterRef('officer1') 11 | ).filter( 12 | officerallegation__officer=OuterRef('officer2') 13 | ) 14 | ActivityPairCard.objects.update(coaccusal_count=SQCount(allegations.values('crid'))) 15 | -------------------------------------------------------------------------------- /cpdb/cms/migrations/0008_faqpage_starred.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.9.5 on 2017-01-19 03:29 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('cms', '0007_faqpage_order_data'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='faqpage', 17 | name='starred', 18 | field=models.BooleanField(default=False), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /cpdb/pinboard/migrations/0002_add_trrs_to_pinboard.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.3 on 2019-04-02 02:12 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('trr', '0017_add_created_at_and_updated_at_columns'), 10 | ('pinboard', '0001_initial'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='pinboard', 16 | name='trrs', 17 | field=models.ManyToManyField(to='trr.TRR'), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0128_officer_allegations.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.10 on 2020-07-31 10:05 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('data', '0127_model_attachmentfile_allow_null_allegation'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='officer', 15 | name='allegations', 16 | field=models.ManyToManyField(through='data.OfficerAllegation', to='data.Allegation'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /cpdb/pinboard/serializers/desktop/relevant/allegation_serializer.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | from ..common import ( 4 | AllegationSerializer as BaseAllegationSerializer, 5 | OfficerRowSerializer 6 | ) 7 | 8 | 9 | class AllegationSerializer(BaseAllegationSerializer): 10 | coaccused = serializers.SerializerMethodField() 11 | 12 | def get_coaccused(self, obj): 13 | coaccused = [officer_allegation.officer for officer_allegation in obj.prefetched_officer_allegations] 14 | return OfficerRowSerializer(coaccused, many=True).data 15 | -------------------------------------------------------------------------------- /cpdb/trr/migrations/0002_alter_trr_subject_id_type.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.4 on 2018-03-06 04:00 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('trr', '0001_initial'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='trr', 17 | name='subject_id', 18 | field=models.PositiveIntegerField(null=True), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0019_auto_20171019_0153.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.4 on 2017-10-19 06:53 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('data', '0018_victim'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='award', 17 | name='tracking_no', 18 | field=models.CharField(max_length=255, null=True), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0009_officer_rank_increase_length.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.9.5 on 2017-02-24 04:25 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('data', '0008_merge'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='officer', 17 | name='rank', 18 | field=models.CharField(blank=True, max_length=100), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0099_attachmentrequest_noti_email_sent.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.3 on 2019-01-04 04:42 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('data', '0098_attachmentfile_text_content'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='attachmentrequest', 15 | name='noti_email_sent', 16 | field=models.BooleanField(default=False, verbose_name='Notification email sent'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /cpdb/social_graph/tests/serializers/test_victim_serializer.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | from robber import expect 3 | 4 | from data.factories import VictimFactory 5 | 6 | from social_graph.serializers.victim_serializer import VictimSerializer 7 | 8 | 9 | class VictimSerializerTestCase(TestCase): 10 | def test_serialization(self): 11 | victim = VictimFactory(race='Black', gender='M', age=53) 12 | expect(VictimSerializer(victim).data).to.eq({ 13 | 'race': 'Black', 14 | 'gender': 'Male', 15 | 'age': 53, 16 | }) 17 | -------------------------------------------------------------------------------- /cpdb/app_config/admin/app_config_admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from app_config.models import AppConfig 3 | 4 | 5 | class AppConfigAdmin(admin.ModelAdmin): 6 | list_display = ('name', 'value', 'description') 7 | fields = ( 8 | 'name', 'value', 'description' 9 | ) 10 | readonly_fields = ['name', 'description'] 11 | 12 | def has_delete_permission(self, request, obj=None): 13 | return False 14 | 15 | def has_add_permission(self, request, obj=None): 16 | return False 17 | 18 | 19 | admin.site.register(AppConfig, AppConfigAdmin) 20 | -------------------------------------------------------------------------------- /cpdb/config/tests/test_urls.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | from django.urls import reverse 3 | 4 | from robber import expect 5 | 6 | 7 | class UrlsTestCase(TestCase): 8 | def test_index_redirect(self): 9 | response = self.client.get(reverse('index_redirect')) 10 | expect(response.status_code).to.eq(301) 11 | expect(response.url).to.eq('/') 12 | 13 | def test_admin_redirect(self): 14 | response = self.client.get(reverse('admin_redirect')) 15 | expect(response.status_code).to.eq(301) 16 | expect(response.url).to.eq('/admin/') 17 | -------------------------------------------------------------------------------- /cpdb/data/tests/management/commands/test_import_cr_summary.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | from django.core.management import call_command 3 | 4 | from robber import expect 5 | 6 | from data.factories import AllegationFactory 7 | 8 | 9 | class CommandTestCase(TestCase): 10 | def test_handle(self): 11 | allegation = AllegationFactory(crid='001') 12 | 13 | call_command('import_cr_summary', file_path='data/tests/data_sample/cr_summary.csv') 14 | 15 | allegation.refresh_from_db() 16 | expect(allegation.summary).be.eq('Summary Text 01 is here') 17 | -------------------------------------------------------------------------------- /cpdb/pinboard/tests/serializers/desktop/common/test_victim_serializer.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | from robber import expect 3 | 4 | from data.factories import VictimFactory 5 | 6 | from pinboard.serializers.desktop.common import VictimSerializer 7 | 8 | 9 | class VictimSerializerTestCase(TestCase): 10 | def test_serialization(self): 11 | victim = VictimFactory(race='Black', gender='M', age=53) 12 | expect(VictimSerializer(victim).data).to.eq({ 13 | 'race': 'Black', 14 | 'gender': 'Male', 15 | 'age': 53, 16 | }) 17 | -------------------------------------------------------------------------------- /cpdb/activity_grid/migrations/0002_activitycard_important.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.4 on 2017-09-20 04:34 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('activity_grid', '0001_initial'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='activitycard', 17 | name='important', 18 | field=models.BooleanField(default=False), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0006_officer_rank_freeform.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.9.5 on 2016-10-31 04:34 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('data', '0005_alter_officer_add_fields'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='officer', 17 | name='rank', 18 | field=models.CharField(blank=True, max_length=50), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /cpdb/data/tests/models/test_complainant.py: -------------------------------------------------------------------------------- 1 | from django.test.testcases import TestCase 2 | 3 | from robber.expect import expect 4 | 5 | from data.factories import ComplainantFactory 6 | 7 | 8 | class ComplainantTestCase(TestCase): 9 | def test_gender_display(self): 10 | expect(ComplainantFactory(gender='M').gender_display).to.equal('Male') 11 | expect(ComplainantFactory(gender='F').gender_display).to.equal('Female') 12 | expect(ComplainantFactory(gender='X').gender_display).to.equal('X') 13 | expect(ComplainantFactory(gender='?').gender_display).to.equal('?') 14 | -------------------------------------------------------------------------------- /cpdb/data/tests/models/test_involvement.py: -------------------------------------------------------------------------------- 1 | from django.test.testcases import TestCase 2 | 3 | from robber.expect import expect 4 | 5 | from data.factories import InvolvementFactory 6 | 7 | 8 | class InvolvementTestCase(TestCase): 9 | def test_gender_display(self): 10 | expect(InvolvementFactory(gender='M').gender_display).to.equal('Male') 11 | expect(InvolvementFactory(gender='F').gender_display).to.equal('Female') 12 | expect(InvolvementFactory(gender='X').gender_display).to.equal('X') 13 | expect(InvolvementFactory(gender='?').gender_display).to.equal('?') 14 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0007_policeunit_description.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.9.5 on 2017-02-14 07:10 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('data', '0006_officer_rank_freeform'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='policeunit', 17 | name='description', 18 | field=models.CharField(default=b'', max_length=255), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0021_officer_resignation_date.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.4 on 2017-10-24 07:26 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('data', '0020_rename_field_type_to_award_type'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='officer', 17 | name='resignation_date', 18 | field=models.DateField(null=True), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0107_remove_area_line_area_from_allegation.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.3 on 2019-01-08 04:17 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('data', '0106_add_field_police_witnesses'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RemoveField( 14 | model_name='allegation', 15 | name='areas', 16 | ), 17 | migrations.RemoveField( 18 | model_name='allegation', 19 | name='line_areas', 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /cpdb/es_index/__init__.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings 2 | 3 | from elasticsearch_dsl.connections import connections 4 | from elasticsearch import Elasticsearch 5 | 6 | 7 | es_client = Elasticsearch(hosts=settings.ELASTICSEARCH_HOSTS, timeout=300) 8 | 9 | connections.add_connection('default', es_client) 10 | 11 | indexer_klasses = [] 12 | indexer_klasses_map = dict() 13 | 14 | 15 | def register_indexer(app): 16 | def func(klass): 17 | indexer_klasses.append(klass) 18 | indexer_klasses_map.setdefault(app, []).append(klass) 19 | return klass 20 | return func 21 | -------------------------------------------------------------------------------- /apiary/toast_mobile.md: -------------------------------------------------------------------------------- 1 | ## Mobile Toast [/v2/mobile/toast/] 2 | 3 | ### Get toast [GET] 4 | 5 | + Response 200 (application/json) 6 | 7 | [ 8 | { 9 | "name": "OFFICER", 10 | "template": "{full_name} {action_type} pinboard", 11 | 12 | }, 13 | { 14 | "name": "CR", 15 | "template": "CR #{crid} {action_type} pinboard", 16 | 17 | }, 18 | { 19 | "name": "TRR", 20 | "template": "TRR #{id} {action_type} pinboard", 21 | } 22 | ] 23 | -------------------------------------------------------------------------------- /cpdb/analytics/migrations/0004_alter_searchtracking_query_type.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.3 on 2018-11-23 08:18 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('analytics', '0003_searchtracking'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='searchtracking', 15 | name='query_type', 16 | field=models.CharField(choices=[['free_text', 'Free Text'], ['no_interaction', 'No Interaction']], max_length=20), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /cpdb/cms/migrations/0013_remove_report_page_model.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.4 on 2018-05-15 05:26 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('cms', '0012_delete_faqpage'), 12 | ] 13 | 14 | operations = [ 15 | migrations.RemoveField( 16 | model_name='reportpage', 17 | name='officers', 18 | ), 19 | migrations.DeleteModel( 20 | name='ReportPage', 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0024_allegation_is_officer_complaint.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.4 on 2018-01-04 07:57 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('data', '0023_auto_20171219_0204'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='allegation', 17 | name='is_officer_complaint', 18 | field=models.BooleanField(default=False), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0032_officer_middle_initial2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.4 on 2018-02-28 09:43 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('data', '0031_remove_policewitness_fields'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='officer', 17 | name='middle_initial2', 18 | field=models.CharField(max_length=5, null=True), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0083_salary_rank_changed.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.4 on 2018-10-02 04:12 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('data', '0082_add_officer_and_allegation_cached_columns'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='salary', 17 | name='rank_changed', 18 | field=models.BooleanField(default=False), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /cpdb/data/tests/models/test_salary.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | from robber import expect 3 | 4 | from data.factories import OfficerFactory, SalaryFactory 5 | from data.models import Salary 6 | 7 | 8 | class SalaryManagerTestCase(TestCase): 9 | def test_ranks(self): 10 | SalaryFactory(rank='Detective', officer__rank='Officer') 11 | SalaryFactory(rank='Officer', officer__rank='Officer') 12 | OfficerFactory(rank='Senior Police Officer') 13 | 14 | ranks = Salary.objects.ranks 15 | expect(ranks).to.eq(['Detective', 'Officer', 'Senior Police Officer']) 16 | -------------------------------------------------------------------------------- /cpdb/pinboard/serializers/desktop/admin/trr_serializer.py: -------------------------------------------------------------------------------- 1 | import pytz 2 | from rest_framework import serializers 3 | 4 | from shared.serializer import NoNullSerializer 5 | 6 | 7 | class TRRSerializer(NoNullSerializer): 8 | id = serializers.IntegerField() 9 | trr_datetime = serializers.DateTimeField(format='%Y-%m-%d', default_timezone=pytz.utc) 10 | category = serializers.SerializerMethodField() 11 | 12 | def get_category(self, obj): 13 | force_types = [res.force_type for res in obj.actionresponse_set.all()] 14 | return force_types[0] if len(force_types) > 0 else 'Unknown' 15 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/writers/test_accused_xlsx_writer/csv/accused_8562/Police Witness.csv: -------------------------------------------------------------------------------- 1 | crid,name,gender,race,appointed_date,resignation_date,rank,birth_year,active,complaint_percentile,civilian_allegation_percentile,internal_allegation_percentile,trr_percentile,honorable_mention_percentile,allegation_count,sustained_count,honorable_mention_count,unsustained_count,discipline_count,civilian_compliment_count,trr_count,major_award_count,current_badge,last_unit,current_salary 2 | 1009678,Jeffery Aaron,Male,White,2005-09-26,,Sergeant of Police,1971,Yes,61.2357,61.2069,76.9384,79.8763,94.8669,6,0,61,0,0,4,7,0,1424,003,101442 3 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0095_attachmenrequest_bulk_objects_manager.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.3 on 2018-12-26 09:37 2 | 3 | from django.db import migrations 4 | import django.db.models.manager 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('data', '0094_attachmentfile_copa_external_id'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterModelManagers( 15 | name='attachmentrequest', 16 | managers=[ 17 | ('bulk_objects', django.db.models.manager.Manager()), 18 | ], 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /cpdb/pinboard/serializers/desktop/admin/allegation_serializer.py: -------------------------------------------------------------------------------- 1 | import pytz 2 | from rest_framework import serializers 3 | 4 | from shared.serializer import NoNullSerializer 5 | 6 | 7 | class AllegationSerializer(NoNullSerializer): 8 | crid = serializers.CharField() 9 | category = serializers.SerializerMethodField() 10 | incident_date = serializers.DateTimeField(format='%Y-%m-%d', default_timezone=pytz.utc) 11 | 12 | def get_category(self, obj): 13 | try: 14 | return obj.most_common_category.category 15 | except AttributeError: 16 | return 'Unknown' 17 | -------------------------------------------------------------------------------- /cpdb/pinboard/serializers/mobile/relevant/allegation_serializer.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | from ..common import ( 4 | AllegationMobileSerializer as BaseAllegationMobileSerializer, 5 | OfficerRowMobileSerializer, 6 | ) 7 | 8 | 9 | class AllegationMobileSerializer(BaseAllegationMobileSerializer): 10 | officers = serializers.SerializerMethodField() 11 | 12 | def get_officers(self, obj): 13 | officers = [officer_allegation.officer for officer_allegation in obj.prefetched_officer_allegations] 14 | return OfficerRowMobileSerializer(officers, many=True).data 15 | -------------------------------------------------------------------------------- /cpdb/popup/views.py: -------------------------------------------------------------------------------- 1 | from rest_framework.response import Response 2 | from rest_framework.viewsets import ViewSet 3 | 4 | from popup.models import Popup 5 | from popup.serializers import PopupSerializer 6 | 7 | 8 | class PopupViewSet(ViewSet): 9 | def list(self, request): 10 | page = self.request.query_params.get('page', None) 11 | if page is not None: 12 | queryset = Popup.objects.filter(page=page) 13 | else: 14 | queryset = Popup.objects.all() 15 | 16 | serializer = PopupSerializer(queryset, many=True) 17 | return Response(serializer.data) 18 | -------------------------------------------------------------------------------- /cpdb/search_terms/migrations/0009_make_slug_unique.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.4 on 2018-10-04 08:27 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('search_terms', '0008_change_primary_key'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='searchtermitem', 17 | name='slug', 18 | field=models.CharField(max_length=30, unique=True), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /cpdb/app_config/admin/visual_token_color_admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from app_config.models import VisualTokenColor 3 | 4 | 5 | class VisualTokenColorAdmin(admin.ModelAdmin): 6 | list_display = ('lower_range', 'upper_range', 'color', 'text_color') 7 | fields = ( 8 | 'lower_range', 'upper_range', 'color', 'text_color' 9 | ) 10 | 11 | def get_queryset(self, request): 12 | queryset = super(VisualTokenColorAdmin, self).get_queryset(request) 13 | return queryset.order_by('lower_range') 14 | 15 | 16 | admin.site.register(VisualTokenColor, VisualTokenColorAdmin) 17 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0085_officer_has_unique_name.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.4 on 2018-10-26 09:23 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('data', '0084_attachmentrequest_added_to_foia_airtable'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='officer', 17 | name='has_unique_name', 18 | field=models.BooleanField(default=False), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /cpdb/es_index/tests/test_register_indexer.py: -------------------------------------------------------------------------------- 1 | from django.test import SimpleTestCase 2 | 3 | from robber import expect 4 | 5 | from es_index import register_indexer, indexer_klasses, indexer_klasses_map 6 | 7 | 8 | class RegisterIndexerTestCase(SimpleTestCase): 9 | def setUp(self): 10 | del indexer_klasses[:] 11 | 12 | def test_register_indexer(self): 13 | klass = '1' 14 | app_name = 'app' 15 | 16 | expect(register_indexer(app_name)(klass)).to.eq(klass) 17 | expect(indexer_klasses).to.eq([klass]) 18 | expect(indexer_klasses_map[app_name]).to.eq([klass]) 19 | -------------------------------------------------------------------------------- /cpdb/search_terms/factories.py: -------------------------------------------------------------------------------- 1 | import factory 2 | 3 | from .models import SearchTermCategory, SearchTermItem 4 | 5 | 6 | class SearchTermCategoryFactory(factory.django.DjangoModelFactory): 7 | name = factory.Faker('word') 8 | 9 | class Meta: 10 | model = SearchTermCategory 11 | 12 | 13 | class SearchTermItemFactory(factory.django.DjangoModelFactory): 14 | category = factory.SubFactory(SearchTermCategoryFactory) 15 | slug = factory.Faker('slug') 16 | name = factory.Faker('word') 17 | description = factory.Faker('text') 18 | 19 | class Meta: 20 | model = SearchTermItem 21 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/management/utils/test_export_officer_xlsx/csv/accused_8562/Police Witness.csv: -------------------------------------------------------------------------------- 1 | crid,name,gender,race,appointed_date,resignation_date,rank,birth_year,active,complaint_percentile,civilian_allegation_percentile,internal_allegation_percentile,trr_percentile,honorable_mention_percentile,allegation_count,sustained_count,honorable_mention_count,unsustained_count,discipline_count,civilian_compliment_count,trr_count,major_award_count,current_badge,last_unit,current_salary 2 | 1009678,Jeffery Aaron,Male,White,2005-09-26,,Sergeant of Police,1971,Yes,61.2357,61.2069,76.9384,79.8763,94.8669,6,0,61,0,0,4,7,0,1424,003,101442 3 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/writers/test_investigator_xlsx_writer/csv/investigator_1234/Police Witness.csv: -------------------------------------------------------------------------------- 1 | crid,name,gender,race,appointed_date,resignation_date,rank,birth_year,active,complaint_percentile,civilian_allegation_percentile,internal_allegation_percentile,trr_percentile,honorable_mention_percentile,allegation_count,sustained_count,honorable_mention_count,unsustained_count,discipline_count,civilian_compliment_count,trr_count,major_award_count,current_badge,last_unit,current_salary 2 | 1009678,Jeffery Aaron,Male,White,2005-09-26,,Sergeant of Police,1971,Yes,61.2357,61.2069,76.9384,79.8763,94.8669,6,0,61,0,0,4,7,0,1424,003,101442 3 | -------------------------------------------------------------------------------- /cpdb/analytics/utils/clicky_tracking.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from django.conf import settings 3 | 4 | from analytics.constants import CLICKY_API_END_POINT 5 | 6 | 7 | def clicky_tracking(data): 8 | clicky_data = { 9 | 'site_id': settings.CLICKY_TRACKING_ID, 10 | 'sitekey_admin': settings.CLICKY_SITEKEY_ADMIN, 11 | 'type': data.get('type', 'click'), 12 | 'href': data.get('href'), 13 | 'title': data.get('title'), 14 | 'ip_address': data.get('ip_address'), 15 | 'ua': data.get('user_agent'), 16 | } 17 | requests.get(CLICKY_API_END_POINT, params=clicky_data) 18 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0058_allegation_old_complaint_address.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.4 on 2018-06-22 01:37 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('data', '0057_remove-pre-1988-data'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='allegation', 17 | name='old_complaint_address', 18 | field=models.CharField(max_length=255, null=True), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /cpdb/document_cloud/constants.py: -------------------------------------------------------------------------------- 1 | DOCUMENT_TYPES = [ 2 | ('CR', 'CR'), 3 | ('CPB', 'CPB'), 4 | ('TRR', 'TRR'), 5 | ('DOCUMENT', 'DOCUMENT'), 6 | ('OCIR', 'OCIR'), 7 | ('OBR', 'OBR'), 8 | ('AR', 'AR'), 9 | ('CHI-R', 'CHI-R'), 10 | ('incident/offense', 'Incident/Offense Report') 11 | ] 12 | 13 | DOCUMENT_CRAWLER_SUCCESS = 'Success' 14 | DOCUMENT_CRAWLER_FAILED = 'Failed' 15 | 16 | DOCUMENT_CRAWLER_STATUS_CHOICES = ( 17 | (DOCUMENT_CRAWLER_SUCCESS, DOCUMENT_CRAWLER_SUCCESS), 18 | (DOCUMENT_CRAWLER_FAILED, DOCUMENT_CRAWLER_FAILED) 19 | ) 20 | 21 | REPROCESS_TEXT_MAX_RETRIES = 3 22 | -------------------------------------------------------------------------------- /cpdb/search/serializers/lawsuit_recent_serializer.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | import pytz 4 | 5 | from shared.serializer import NoNullSerializer 6 | 7 | 8 | class LawsuitRecentSerializer(NoNullSerializer): 9 | id = serializers.IntegerField() 10 | case_no = serializers.CharField() 11 | primary_cause = serializers.CharField() 12 | summary = serializers.CharField() 13 | incident_date = serializers.DateTimeField(format='%Y-%m-%d', default_timezone=pytz.utc) 14 | type = serializers.SerializerMethodField() 15 | 16 | def get_type(self, obj): 17 | return 'LAWSUIT' 18 | -------------------------------------------------------------------------------- /cpdb/search_terms/migrations/0003_alter_nullable_description.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.4 on 2017-11-20 09:09 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('search_terms', '0002_add_order_number'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='searchtermitem', 17 | name='description', 18 | field=models.TextField(blank=True, null=True), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /cpdb/search_terms/migrations/0007_alter_uuid.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.4 on 2018-10-03 04:11 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | import uuid 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('search_terms', '0006_populate_uuid'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AlterField( 17 | model_name='searchtermitem', 18 | name='uuid', 19 | field=models.UUIDField(default=uuid.uuid4, editable=False), 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /cpdb/search_terms/migrations/0010_change_link_to_char.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.4 on 2018-10-04 09:19 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('search_terms', '0009_make_slug_unique'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='searchtermitem', 17 | name='link', 18 | field=models.CharField(blank=True, max_length=200, null=True), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /cpdb/twitterbot/migrations/0003_auto_20171019_2145.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.4 on 2017-10-20 02:45 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('twitterbot', '0002_tweetresponseroundrobin'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='tweetresponseroundrobin', 17 | name='last_index', 18 | field=models.PositiveIntegerField(default=0), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/management/utils/test_export_officer_xlsx/csv/investigator_1234/Police Witness.csv: -------------------------------------------------------------------------------- 1 | crid,name,gender,race,appointed_date,resignation_date,rank,birth_year,active,complaint_percentile,civilian_allegation_percentile,internal_allegation_percentile,trr_percentile,honorable_mention_percentile,allegation_count,sustained_count,honorable_mention_count,unsustained_count,discipline_count,civilian_compliment_count,trr_count,major_award_count,current_badge,last_unit,current_salary 2 | 1009678,Jeffery Aaron,Male,White,2005-09-26,,Sergeant of Police,1971,Yes,61.2357,61.2069,76.9384,79.8763,94.8669,6,0,61,0,0,4,7,0,1424,003,101442 3 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0084_attachmentrequest_added_to_foia_airtable.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.4 on 2018-10-01 04:38 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('data', '0083_salary_rank_changed'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='attachmentrequest', 17 | name='added_to_foia_airtable', 18 | field=models.BooleanField(default=False), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/writers/test_use_of_force_xlsx_writer/csv/empty/Use Of Force.csv: -------------------------------------------------------------------------------- 1 | id,beat,block,direction,street,location,trr_datetime,indoor_or_outdoor,lighting_condition,weather_condition,notify_OEMC,notify_district_sergeant,notify_OP_command,notify_DET_division,number_of_weapons_discharged,party_fired_first,location_recode,taser,total_number_of_shots,firearm_used,number_of_officers_using_firearm,officer_assigned_beat,officer_unit,officer_unit_detail,officer_on_duty,officer_in_uniform,officer_injured,officer_rank,subject_id,subject_armed,subject_injured,subject_alleged_injury,subject_age,subject_birth_year,subject_gender,subject_race 2 | -------------------------------------------------------------------------------- /cpdb/analytics/constants.py: -------------------------------------------------------------------------------- 1 | FREE_TEXT = 'free_text' 2 | NO_INTERACTION = 'no_interaction' 3 | 4 | QUERY_TYPES = [ 5 | [FREE_TEXT, 'Free Text'], 6 | [NO_INTERACTION, 'No Interaction'] 7 | ] 8 | 9 | DOWNLOAD_EVENT_TYPE = 'DOWNLOAD_EVENT_TYPE' 10 | VIEW_EVENT_TYPE = 'VIEW_EVENT_TYPE' 11 | 12 | ATTACHMENT_FILE_TRACKING_EVENT_TYPE = ( 13 | (DOWNLOAD_EVENT_TYPE, 'Download Event Type'), 14 | (VIEW_EVENT_TYPE, 'View Event Type') 15 | ) 16 | 17 | GA_API_END_POINT = 'https://www.google-analytics.com/collect' 18 | GA_API_VERSION = '1' 19 | GA_ANONYMOUS_ID = '555' 20 | CLICKY_API_END_POINT = 'http://in.getclicky.com/in.php' 21 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0068_attachmentfile_external_id.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.4 on 2018-09-21 10:17 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('data', '0067_attachmentrequest_timestamp'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='attachmentfile', 17 | name='external_id', 18 | field=models.CharField(db_index=True, max_length=50, null=True), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /cpdb/search/utils.py: -------------------------------------------------------------------------------- 1 | import zipcodes 2 | from django.conf import settings 3 | 4 | 5 | class ZipCode(object): 6 | def __init__(self, pk, zip_code, url): 7 | self.pk = pk 8 | self.zip_code = zip_code 9 | self.url = url 10 | 11 | 12 | def chicago_zip_codes(): 13 | results = [] 14 | for index, zip_code in enumerate(zipcodes.filter_by(zipcodes.list_all(), active=True, city='CHICAGO')): 15 | url = f"{settings.V1_URL}/url-mediator/session-builder?zip_code={zip_code['zip_code']}" 16 | results.append(ZipCode(pk=index, zip_code=zip_code['zip_code'], url=url)) 17 | return results 18 | -------------------------------------------------------------------------------- /cpdb/units/views.py: -------------------------------------------------------------------------------- 1 | from rest_framework import viewsets, status 2 | from rest_framework.decorators import action 3 | from rest_framework.response import Response 4 | 5 | from .doc_types import UnitDocType 6 | 7 | 8 | class UnitsViewSet(viewsets.ViewSet): 9 | 10 | @action(detail=True, methods=['get']) 11 | def summary(self, request, pk): 12 | query = UnitDocType().search().query('term', unit_name=pk) 13 | search_result = query.execute() 14 | 15 | if len(search_result): 16 | return Response(search_result[0].to_dict()) 17 | 18 | return Response(status=status.HTTP_404_NOT_FOUND) 19 | -------------------------------------------------------------------------------- /cpdb/xlsx/tests/writers/test_accused_xlsx_writer/csv/accused_8562/Allegation.csv: -------------------------------------------------------------------------------- 1 | crid,officer_name,address,old_complaint_address,incident_date,is_officer_complaint,beat,coaccused_count,category,subcategory,start_date,end_date,recc_finding,recc_outcome,final_finding,final_outcome,disciplined 2 | 1009678,Jerome Finnigan,"37XX W 63RD ST, CHICAGO IL",,2007-09-28,TRUE,0823,19,Illegal Search,Improper Search Of Person,2007-09-28,,Unknown,Unknown,Unknown,Unknown, 3 | 1012803,Jerome Finnigan,"31XX N NEWCASTLE AVE, CHICAGO IL",,2005-11-01,FALSE,2511,9,False Arrest,Illegal Arrest / False Arrest,2007-12-21,2008-05-29,Unknown,Unknown,Unknown,Unknown, 4 | -------------------------------------------------------------------------------- /.gitsecret/paths/mapping.cfg: -------------------------------------------------------------------------------- 1 | prod.env:a1f9510ee57dd193b62e2ac1bb23e76f573a2d4a286e2f0e1eacfa0dff600488 2 | staging.env:d566745266010ff7ab8f2e2b142d119550b65c12cc9e78220e3db9c45606312e 3 | kubernetes/secrets-production.yml:e355966fb84d6abd0889961d94fe48ce617eea9b34afd1602c845e25addd56eb 4 | kubernetes/secrets-staging.yml:92db9113c2c22e884c55452f606c2071f8eb4a7e8909309bbb2ce592b8b8011d 5 | pg-credentials.json:a496143e02ed8b4eacf3b484df8888c84d9a4e23ff365c30cd63a6d98ec3b589 6 | beta.env:baaa9ab174f0b95bd6746e2da3cf9d8f45d3b07fa3db84b99c1b8ca5b5c387ac 7 | kubernetes/secrets-beta.yml:886e4c8e50ad960aa582e09ca13f4134ba5319be4dc406c743246824629cfc18 8 | -------------------------------------------------------------------------------- /cpdb/cms/migrations/0009_reportpage_officers.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.9.5 on 2017-02-09 08:29 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('data', '0006_officer_rank_freeform'), 12 | ('cms', '0008_faqpage_starred'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AddField( 17 | model_name='reportpage', 18 | name='officers', 19 | field=models.ManyToManyField(to='data.Officer'), 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0027_officer_complaint_percentile.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.4 on 2018-01-29 06:32 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('data', '0026_add_investigatorallegation'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='officer', 17 | name='complaint_percentile', 18 | field=models.DecimalField(decimal_places=3, max_digits=6, null=True), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /cpdb/data/migrations/0103_remove_attachment_allegation_old_fk.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.3 on 2019-01-08 03:42 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('data', '0102_change_attachment_unique_together'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RemoveField( 14 | model_name='attachmentfile', 15 | name='allegation_old_fk', 16 | ), 17 | migrations.RemoveField( 18 | model_name='attachmentrequest', 19 | name='allegation_old_fk', 20 | ), 21 | ] 22 | --------------------------------------------------------------------------------