[{"data":1,"prerenderedAt":10529},["ShallowReactive",2],{"navigation":3,"/authentication-and-authorization/password-management":1016,"/authentication-and-authorization/password-management-surround":10524},[4,54,89,123,165,211,253,331,389,439,462,488,514,540,578,624,650,672,702,736,774,800,850,856,862,868,874,928],{"title":5,"path":6,"stem":7,"children":8},"Introduction and Foundations","/introduction-and-foundations","01.introduction-and-foundations/01.index",[9,10,14,18,22,26,30,34,38,42,46,50],{"title":5,"path":6,"stem":7},{"title":11,"path":12,"stem":13},"What is Django","/introduction-and-foundations/what-is-django","01.introduction-and-foundations/02.what-is-django",{"title":15,"path":16,"stem":17},"Key Concepts and Philosophy","/introduction-and-foundations/key-concepts-and-philosophy","01.introduction-and-foundations/03.key-concepts-and-philosophy",{"title":19,"path":20,"stem":21},"MVC vs MVT: Understanding Django's Architecture","/introduction-and-foundations/mvc-vs-mvt","01.introduction-and-foundations/04.mvc-vs-mvt",{"title":23,"path":24,"stem":25},"Project Structure Overview","/introduction-and-foundations/project-structure-overview","01.introduction-and-foundations/05.project-structure-overview",{"title":27,"path":28,"stem":29},"Installing Django","/introduction-and-foundations/installing-django","01.introduction-and-foundations/06.installing-django",{"title":31,"path":32,"stem":33},"Creating Your First Django Project","/introduction-and-foundations/creating-first-project","01.introduction-and-foundations/07.creating-first-project",{"title":35,"path":36,"stem":37},"Creating Your First Django App","/introduction-and-foundations/creating-first-app","01.introduction-and-foundations/08.creating-first-app",{"title":39,"path":40,"stem":41},"Your First Django \"Hello World\"","/introduction-and-foundations/hello-world","01.introduction-and-foundations/09.hello-world",{"title":43,"path":44,"stem":45},"Django Quick Start Guide","/introduction-and-foundations/quick-start-guide","01.introduction-and-foundations/10.quick-start-guide",{"title":47,"path":48,"stem":49},"How Django Handles Requests","/introduction-and-foundations/how-django-handles-requests","01.introduction-and-foundations/11.how-django-handles-requests",{"title":51,"path":52,"stem":53},"Django Settings","/introduction-and-foundations/django-settings","01.introduction-and-foundations/12.django-settings",{"title":55,"path":56,"stem":57,"children":58},"The Development Environment","/development-environment","02.development-environment/1.index",[59,61,65,69,73,77,81,85],{"title":60,"path":56,"stem":57},"Development Environment",{"title":62,"path":63,"stem":64},"Recommended Tooling for Django Development","/development-environment/recommended-tooling","02.development-environment/2.recommended-tooling",{"title":66,"path":67,"stem":68},"Virtual Environments","/development-environment/virtual-environments","02.development-environment/3.virtual-environments",{"title":70,"path":71,"stem":72},"Django Admin and Management Commands","/development-environment/admin-and-management-commands","02.development-environment/4.admin-and-management-commands",{"title":74,"path":75,"stem":76},"Django Project Settings","/development-environment/project-settings","02.development-environment/5.project-settings",{"title":78,"path":79,"stem":80},"Managing Django Environments: Local, Staging, and Production","/development-environment/environments-local-staging-production","02.development-environment/6.environments-local-staging-production",{"title":82,"path":83,"stem":84},"Running Django Development Server","/development-environment/running-development-server","02.development-environment/7.running-development-server",{"title":86,"path":87,"stem":88},"Working with Django Shell","/development-environment/working-with-shell","02.development-environment/8.working-with-shell",{"title":90,"path":91,"stem":92,"children":93},"Templates and Presentation Layer","/templates-and-presentation","03.templates-and-presentation/1.index",[94,95,99,103,107,111,115,119],{"title":90,"path":91,"stem":92},{"title":96,"path":97,"stem":98},"Introduction to Django Templates","/templates-and-presentation/introduction-to-templates","03.templates-and-presentation/2.introduction-to-templates",{"title":100,"path":101,"stem":102},"The Django Template Language","/templates-and-presentation/django-template-language","03.templates-and-presentation/3.django-template-language",{"title":104,"path":105,"stem":106},"Template Inheritance","/templates-and-presentation/template-inheritance","03.templates-and-presentation/4.template-inheritance",{"title":108,"path":109,"stem":110},"Built-in Template Tags and Filters","/templates-and-presentation/built-in-template-tags-and-filters","03.templates-and-presentation/5.built-in-template-tags-and-filters",{"title":112,"path":113,"stem":114},"Including Static Files","/templates-and-presentation/including-static-files","03.templates-and-presentation/6.including-static-files",{"title":116,"path":117,"stem":118},"Working with Media Files","/templates-and-presentation/working-with-media-files","03.templates-and-presentation/7.working-with-media-files",{"title":120,"path":121,"stem":122},"Using Alternative Template Engines","/templates-and-presentation/using-alternative-template-engines","03.templates-and-presentation/8.using-alternative-template-engines",{"title":124,"path":125,"stem":126,"children":127},"URLs and Views","/urls-and-views","04.urls-and-views/01.index",[128,129,133,137,141,145,149,153,157,161],{"title":124,"path":125,"stem":126},{"title":130,"path":131,"stem":132},"The URL Dispatcher","/urls-and-views/the-url-dispatcher","04.urls-and-views/02.the-url-dispatcher",{"title":134,"path":135,"stem":136},"Writing Function-Based Views","/urls-and-views/writing-function-based-views","04.urls-and-views/03.writing-function-based-views",{"title":138,"path":139,"stem":140},"View Decorators","/urls-and-views/view-decorators","04.urls-and-views/04.view-decorators",{"title":142,"path":143,"stem":144},"Rendering Responses","/urls-and-views/rendering-responses","04.urls-and-views/05.rendering-responses",{"title":146,"path":147,"stem":148},"Redirects","/urls-and-views/redirects","04.urls-and-views/06.redirects",{"title":150,"path":151,"stem":152},"Handling HTTP Methods","/urls-and-views/handling-http-methods","04.urls-and-views/07.handling-http-methods",{"title":154,"path":155,"stem":156},"Conditional View Processing","/urls-and-views/conditional-view-processing","04.urls-and-views/08.conditional-view-processing",{"title":158,"path":159,"stem":160},"File Uploads","/urls-and-views/file-uploads","04.urls-and-views/09.file-uploads",{"title":162,"path":163,"stem":164},"Using Django Shortcut Functions","/urls-and-views/using-django-shortcut-functions","04.urls-and-views/10.using-django-shortcut-functions",{"title":166,"path":167,"stem":168,"children":169},"Class Based Views","/class-based-views","05.class-based-views/01.index",[170,171,175,179,183,187,191,195,199,203,207],{"title":166,"path":167,"stem":168},{"title":172,"path":173,"stem":174},"Introduction to Class-Based Views","/class-based-views/introduction-to-class-based-views","05.class-based-views/02.introduction-to-class-based-views",{"title":176,"path":177,"stem":178},"Common Base Classes","/class-based-views/common-base-classes","05.class-based-views/03.common-base-classes",{"title":180,"path":181,"stem":182},"Built-in Generic Views","/class-based-views/built-in-generic-views","05.class-based-views/04.built-in-generic-views",{"title":184,"path":185,"stem":186},"Views for CRUD Operations","/class-based-views/views-for-crud-operations","05.class-based-views/05.views-for-crud-operations",{"title":188,"path":189,"stem":190},"Handling Forms with Class-Based Views","/class-based-views/handling-forms-with-class-based-views","05.class-based-views/06.handling-forms-with-class-based-views",{"title":192,"path":193,"stem":194},"Using Mixins","/class-based-views/using-mixins","05.class-based-views/07.using-mixins",{"title":196,"path":197,"stem":198},"URL Configuration with Class-Based Views","/class-based-views/url-configuration-with-class-based-views","05.class-based-views/08.url-configuration-with-class-based-views",{"title":200,"path":201,"stem":202},"Subclassing Generic Views","/class-based-views/subclassing-generic-views","05.class-based-views/09.subclassing-generic-views",{"title":204,"path":205,"stem":206},"Asynchronous Class-Based Views","/class-based-views/asynchronous-class-based-views","05.class-based-views/10.asynchronous-class-based-views",{"title":208,"path":209,"stem":210},"Pagination","/class-based-views/pagination","05.class-based-views/11.pagination",{"title":212,"path":213,"stem":214,"children":215},"Forms and User Input","/forms-and-user-input","06.forms-and-user-input/01.index",[216,217,221,225,229,233,237,241,245,249],{"title":212,"path":213,"stem":214},{"title":218,"path":219,"stem":220},"Understanding HTML Forms","/forms-and-user-input/understanding-html-forms","06.forms-and-user-input/02.understanding-html-forms",{"title":222,"path":223,"stem":224},"Django's Role in Form Handling","/forms-and-user-input/djangos-role-in-form-handling","06.forms-and-user-input/03.djangos-role-in-form-handling",{"title":226,"path":227,"stem":228},"Creating Forms with Forms API","/forms-and-user-input/creating-forms-with-forms-api","06.forms-and-user-input/04.creating-forms-with-forms-api",{"title":230,"path":231,"stem":232},"Form Validation","/forms-and-user-input/form-validation","06.forms-and-user-input/05.form-validation",{"title":234,"path":235,"stem":236},"Built-in Fields and Widgets","/forms-and-user-input/built-in-fields-and-widgets","06.forms-and-user-input/06.built-in-fields-and-widgets",{"title":238,"path":239,"stem":240},"Form Rendering in Templates","/forms-and-user-input/form-rendering-in-templates","06.forms-and-user-input/07.form-rendering-in-templates",{"title":242,"path":243,"stem":244},"Model Forms","/forms-and-user-input/model-forms","06.forms-and-user-input/08.model-forms",{"title":246,"path":247,"stem":248},"Advanced Form Techniques","/forms-and-user-input/advanced-form-techniques","06.forms-and-user-input/09.advanced-form-techniques",{"title":250,"path":251,"stem":252},"Security Considerations for Forms","/forms-and-user-input/security-considerations-for-forms","06.forms-and-user-input/10.security-considerations-for-forms",{"title":254,"path":255,"stem":256,"children":257},"Models and Databases","/models-and-databases","07.models-and-databases/01.index",[258,259,263,267,271,275,279,283,287,291,295,299,303,307,311,315,319,323,327],{"title":254,"path":255,"stem":256},{"title":260,"path":261,"stem":262},"Understanding Django Models","/models-and-databases/understanding-django-models","07.models-and-databases/02.understanding-django-models",{"title":264,"path":265,"stem":266},"Defining Fields","/models-and-databases/defining-fields","07.models-and-databases/03.defining-fields",{"title":268,"path":269,"stem":270},"Relationships and Foreign Keys","/models-and-databases/relationships-and-foreign-keys","07.models-and-databases/04.relationships-and-foreign-keys",{"title":272,"path":273,"stem":274},"Examples of Relationship Patterns","/models-and-databases/examples-of-relationship-patterns","07.models-and-databases/05.examples-of-relationship-patterns",{"title":276,"path":277,"stem":278},"Making Queries","/models-and-databases/making-queries","07.models-and-databases/06.making-queries",{"title":280,"path":281,"stem":282},"Filtering, Ordering, and Slicing","/models-and-databases/filtering-ordering-slicing","07.models-and-databases/07.filtering-ordering-slicing",{"title":284,"path":285,"stem":286},"Managers and QuerySets","/models-and-databases/managers-and-querysets","07.models-and-databases/08.managers-and-querysets",{"title":288,"path":289,"stem":290},"Aggregation","/models-and-databases/aggregation","07.models-and-databases/09.aggregation",{"title":292,"path":293,"stem":294},"Search","/models-and-databases/search","07.models-and-databases/10.search",{"title":296,"path":297,"stem":298},"Raw SQL Queries","/models-and-databases/raw-sql-queries","07.models-and-databases/11.raw-sql-queries",{"title":300,"path":301,"stem":302},"Transactions","/models-and-databases/transactions","07.models-and-databases/12.transactions",{"title":304,"path":305,"stem":306},"Multiple Databases","/models-and-databases/multiple-databases","07.models-and-databases/13.multiple-databases",{"title":308,"path":309,"stem":310},"Tablespaces","/models-and-databases/tablespaces","07.models-and-databases/14.tablespaces",{"title":312,"path":313,"stem":314},"Composite Primary Keys","/models-and-databases/composite-primary-keys","07.models-and-databases/15.composite-primary-keys",{"title":316,"path":317,"stem":318},"Database Instrumentation","/models-and-databases/database-instrumentation","07.models-and-databases/16.database-instrumentation",{"title":320,"path":321,"stem":322},"Database Optimization","/models-and-databases/database-optimization","07.models-and-databases/17.database-optimization",{"title":324,"path":325,"stem":326},"Fixtures","/models-and-databases/fixtures","07.models-and-databases/18.fixtures",{"title":328,"path":329,"stem":330},"Signals","/models-and-databases/signals","07.models-and-databases/19.signals",{"title":332,"path":333,"stem":334,"children":335},"Migrations","/migrations","08.migrations/01.index",[336,337,341,345,349,353,357,361,365,369,373,377,381,385],{"title":332,"path":333,"stem":334},{"title":338,"path":339,"stem":340},"How Migrations Work","/migrations/how-migrations-work","08.migrations/02.how-migrations-work",{"title":342,"path":343,"stem":344},"Management Commands","/migrations/management-commands","08.migrations/03.management-commands",{"title":346,"path":347,"stem":348},"Dependencies and Workflow","/migrations/dependencies-and-workflow","08.migrations/04.dependencies-and-workflow",{"title":350,"path":351,"stem":352},"Transaction Handling","/migrations/transaction-handling","08.migrations/05.transaction-handling",{"title":354,"path":355,"stem":356},"Adding Migrations to Apps","/migrations/adding-migrations-to-apps","08.migrations/06.adding-migrations-to-apps",{"title":358,"path":359,"stem":360},"Reversing Migrations","/migrations/reversing-migrations","08.migrations/07.reversing-migrations",{"title":362,"path":363,"stem":364},"Historical Models","/migrations/historical-models","08.migrations/08.historical-models",{"title":366,"path":367,"stem":368},"Considerations When Removing Fields","/migrations/considerations-when-removing-fields","08.migrations/09.considerations-when-removing-fields",{"title":370,"path":371,"stem":372},"Data Migrations","/migrations/data-migrations","08.migrations/10.data-migrations",{"title":374,"path":375,"stem":376},"Squashing Migrations","/migrations/squashing-migrations","08.migrations/11.squashing-migrations",{"title":378,"path":379,"stem":380},"Serializing Values","/migrations/serializing-values","08.migrations/12.serializing-values",{"title":382,"path":383,"stem":384},"Supporting Multiple Django Versions","/migrations/supporting-multiple-django-versions","08.migrations/13.supporting-multiple-django-versions",{"title":386,"path":387,"stem":388},"Django Serialization Framework","/migrations/django-serialization-framework","08.migrations/14.django-serialization-framework",{"title":390,"path":391,"stem":392,"children":393},"Authentication and Authorization","/authentication-and-authorization","09.authentication-and-authorization/01.index",[394,395,399,403,407,411,415,419,423,427,431,435],{"title":390,"path":391,"stem":392},{"title":396,"path":397,"stem":398},"Overview of Django's Authentication System","/authentication-and-authorization/overview-of-django-authentication-system","09.authentication-and-authorization/02.overview-of-django-authentication-system",{"title":400,"path":401,"stem":402},"Users and Groups","/authentication-and-authorization/users-and-groups","09.authentication-and-authorization/03.users-and-groups",{"title":404,"path":405,"stem":406},"Permissions","/authentication-and-authorization/permissions","09.authentication-and-authorization/04.permissions",{"title":408,"path":409,"stem":410},"Password Management","/authentication-and-authorization/password-management","09.authentication-and-authorization/05.password-management",{"title":412,"path":413,"stem":414},"Authentication Views","/authentication-and-authorization/authentication-views","09.authentication-and-authorization/06.authentication-views",{"title":416,"path":417,"stem":418},"Login and Logout","/authentication-and-authorization/login-and-logout","09.authentication-and-authorization/07.login-and-logout",{"title":420,"path":421,"stem":422},"Custom User Models","/authentication-and-authorization/custom-user-models","09.authentication-and-authorization/08.custom-user-models",{"title":424,"path":425,"stem":426},"Middleware for Authentication","/authentication-and-authorization/middleware-for-authentication","09.authentication-and-authorization/09.middleware-for-authentication",{"title":428,"path":429,"stem":430},"Authorization in Views and Templates","/authentication-and-authorization/authorization-in-views-and-templates","09.authentication-and-authorization/10.authorization-in-views-and-templates",{"title":432,"path":433,"stem":434},"Integrating Social Authentication","/authentication-and-authorization/integrating-social-authentication","09.authentication-and-authorization/11.integrating-social-authentication",{"title":436,"path":437,"stem":438},"Security Best Practices","/authentication-and-authorization/security-best-practices","09.authentication-and-authorization/12.security-best-practices",{"title":440,"path":441,"stem":442,"children":443},"Sessions, Cookies, and State","/sessions-cookies-state","10.sessions-cookies-state/01.index",[444,446,450,454,458],{"title":445,"path":441,"stem":442},"Sessions, Cookies, and State Management",{"title":447,"path":448,"stem":449},"Introduction to Sessions","/sessions-cookies-state/introduction-to-sessions","10.sessions-cookies-state/02.introduction-to-sessions",{"title":451,"path":452,"stem":453},"Working with Cookies","/sessions-cookies-state/working-with-cookies","10.sessions-cookies-state/03.working-with-cookies",{"title":455,"path":456,"stem":457},"Server-Side Session Storage Options","/sessions-cookies-state/server-side-session-storage-options","10.sessions-cookies-state/04.server-side-session-storage-options",{"title":459,"path":460,"stem":461},"Session Security","/sessions-cookies-state/session-security","10.sessions-cookies-state/05.session-security",{"title":463,"path":464,"stem":465,"children":466},"Working with Files","/working-with-files","11.working-with-files/01.index",[467,468,472,476,480,484],{"title":463,"path":464,"stem":465},{"title":469,"path":470,"stem":471},"Files in Models","/working-with-files/files-in-models","11.working-with-files/02.files-in-models",{"title":473,"path":474,"stem":475},"The File Object","/working-with-files/the-file-object","11.working-with-files/03.the-file-object",{"title":477,"path":478,"stem":479},"Storage Backends","/working-with-files/storage-backends","11.working-with-files/04.storage-backends",{"title":481,"path":482,"stem":483},"Using Cloud Storage Providers","/working-with-files/using-cloud-storage-providers","11.working-with-files/05.using-cloud-storage-providers",{"title":485,"path":486,"stem":487},"Managing Media in Production","/working-with-files/managing-media-in-production","11.working-with-files/06.managing-media-in-production",{"title":489,"path":490,"stem":491,"children":492},"Admin Site","/admin-site","12.admin-site/01.index",[493,494,498,502,506,510],{"title":489,"path":490,"stem":491},{"title":495,"path":496,"stem":497},"Enabling the Admin","/admin-site/enabling-the-admin","12.admin-site/02.enabling-the-admin",{"title":499,"path":500,"stem":501},"Registering Models","/admin-site/registering-models","12.admin-site/03.registering-models",{"title":503,"path":504,"stem":505},"Customizing Admin Display","/admin-site/customizing-admin-display","12.admin-site/04.customizing-admin-display",{"title":507,"path":508,"stem":509},"Admin Actions","/admin-site/admin-actions","12.admin-site/05.admin-actions",{"title":511,"path":512,"stem":513},"Admin Security Best Practices","/admin-site/admin-security-best-practices","12.admin-site/06.admin-security-best-practices",{"title":515,"path":516,"stem":517,"children":518},"Middleware","/middleware","13.middleware/01.index",[519,520,524,528,532,536],{"title":515,"path":516,"stem":517},{"title":521,"path":522,"stem":523},"Middleware Overview","/middleware/middleware-overview","13.middleware/02.middleware-overview",{"title":525,"path":526,"stem":527},"Built-in Middleware","/middleware/built-in-middleware","13.middleware/03.built-in-middleware",{"title":529,"path":530,"stem":531},"Creating Custom Middleware","/middleware/creating-custom-middleware","13.middleware/04.creating-custom-middleware",{"title":533,"path":534,"stem":535},"Middleware Ordering","/middleware/middleware-ordering","13.middleware/05.middleware-ordering",{"title":537,"path":538,"stem":539},"Performance and Debugging","/middleware/performance-and-debugging","13.middleware/06.performance-and-debugging",{"title":541,"path":542,"stem":543,"children":544},"Security","/security","14.security/01.index",[545,546,550,554,558,562,566,570,574],{"title":541,"path":542,"stem":543},{"title":547,"path":548,"stem":549},"Django Security Philosophy","/security/django-security-philosophy","14.security/02.django-security-philosophy",{"title":551,"path":552,"stem":553},"Cross Site Request Forgery","/security/cross-site-request-forgery","14.security/03.cross-site-request-forgery",{"title":555,"path":556,"stem":557},"Cross Site Scripting","/security/cross-site-scripting","14.security/04.cross-site-scripting",{"title":559,"path":560,"stem":561},"SQL Injection Protection","/security/sql-injection-protection","14.security/05.sql-injection-protection",{"title":563,"path":564,"stem":565},"Clickjacking Protection","/security/clickjacking-protection","14.security/06.clickjacking-protection",{"title":567,"path":568,"stem":569},"HTTPS Setup and HSTS","/security/https-setup-and-hsts","14.security/07.https-setup-and-hsts",{"title":571,"path":572,"stem":573},"Password Storage and Cryptography","/security/password-storage-and-cryptography","14.security/08.password-storage-and-cryptography",{"title":575,"path":576,"stem":577},"Secure Deployment Checklist","/security/secure-deployment-checklist","14.security/09.secure-deployment-checklist",{"title":579,"path":580,"stem":581,"children":582},"Testing","/testing","15.testing/01.index",[583,584,588,592,596,600,604,608,612,616,620],{"title":579,"path":580,"stem":581},{"title":585,"path":586,"stem":587},"Introduction to Django Testing","/testing/introduction-to-django-testing","15.testing/02.introduction-to-django-testing",{"title":589,"path":590,"stem":591},"Writing and Running Tests","/testing/writing-and-running-tests","15.testing/03.writing-and-running-tests",{"title":593,"path":594,"stem":595},"Test Tools","/testing/test-tools","15.testing/04.test-tools",{"title":597,"path":598,"stem":599},"Testing Models","/testing/testing-models","15.testing/05.testing-models",{"title":601,"path":602,"stem":603},"Testing Views","/testing/testing-views","15.testing/06.testing-views",{"title":605,"path":606,"stem":607},"Testing Forms","/testing/testing-forms","15.testing/07.testing-forms",{"title":609,"path":610,"stem":611},"Testing Templates","/testing/testing-templates","15.testing/08.testing-templates",{"title":613,"path":614,"stem":615},"Testing Authentication","/testing/testing-authentication","15.testing/09.testing-authentication",{"title":617,"path":618,"stem":619},"Advanced Testing Topics","/testing/advanced-testing-topics","15.testing/10.advanced-testing-topics",{"title":621,"path":622,"stem":623},"Performance Testing","/testing/performance-testing","15.testing/11.performance-testing",{"title":625,"path":626,"stem":627,"children":628},"Static Assets and Frontend Integration","/static-assets-and-frontend-integration","16.static-assets-and-frontend-integration/01.index",[629,630,634,638,642,646],{"title":625,"path":626,"stem":627},{"title":631,"path":632,"stem":633},"Working with Static Files","/static-assets-and-frontend-integration/working-with-static-files","16.static-assets-and-frontend-integration/02.working-with-static-files",{"title":635,"path":636,"stem":637},"Integrating CSS and JavaScript","/static-assets-and-frontend-integration/integrating-css-and-javascript","16.static-assets-and-frontend-integration/03.integrating-css-and-javascript",{"title":639,"path":640,"stem":641},"Using Build Tools like Vite or Webpack","/static-assets-and-frontend-integration/using-build-tools-like-vite-or-webpack","16.static-assets-and-frontend-integration/04.using-build-tools-like-vite-or-webpack",{"title":643,"path":644,"stem":645},"Using React or Vue with Django","/static-assets-and-frontend-integration/using-react-or-vue-with-django","16.static-assets-and-frontend-integration/05.using-react-or-vue-with-django",{"title":647,"path":648,"stem":649},"Managing CORS","/static-assets-and-frontend-integration/managing-cors","16.static-assets-and-frontend-integration/06.managing-cors",{"title":651,"path":652,"stem":653,"children":654},"Internationalization and Localization","/internationalization-and-localization","17.internationalization-and-localization/01.index",[655,656,660,664,668],{"title":651,"path":652,"stem":653},{"title":657,"path":658,"stem":659},"Enabling Translation","/internationalization-and-localization/enabling-translation","17.internationalization-and-localization/02.enabling-translation",{"title":661,"path":662,"stem":663},"Translating Text in Code and Templates","/internationalization-and-localization/translating-text-in-code-and-templates","17.internationalization-and-localization/03.translating-text-in-code-and-templates",{"title":665,"path":666,"stem":667},"Timezone Support","/internationalization-and-localization/timezone-support","17.internationalization-and-localization/04.timezone-support",{"title":669,"path":670,"stem":671},"Locale Middleware","/internationalization-and-localization/locale-middleware","17.internationalization-and-localization/05.locale-middleware",{"title":673,"path":674,"stem":675,"children":676},"Caching","/caching","18.caching/01.index",[677,678,682,686,690,694,698],{"title":673,"path":674,"stem":675},{"title":679,"path":680,"stem":681},"Introduction to Caching","/caching/introduction-to-caching","18.caching/02.introduction-to-caching",{"title":683,"path":684,"stem":685},"Cache Backends","/caching/cache-backends","18.caching/03.cache-backends",{"title":687,"path":688,"stem":689},"Per View Caching","/caching/per-view-caching","18.caching/04.per-view-caching",{"title":691,"path":692,"stem":693},"Low Level Cache API","/caching/low-level-cache-api","18.caching/05.low-level-cache-api",{"title":695,"path":696,"stem":697},"Template Fragment Caching","/caching/template-fragment-caching","18.caching/06.template-fragment-caching",{"title":699,"path":700,"stem":701},"Deployment Level Caching Patterns","/caching/deployment-level-caching-patterns","18.caching/07.deployment-level-caching-patterns",{"title":703,"path":704,"stem":705,"children":706},"Asynchronous Django","/asynchronous-django","19.asynchronous-django/01.index",[707,708,712,716,720,724,728,732],{"title":703,"path":704,"stem":705},{"title":709,"path":710,"stem":711},"Introduction to ASGI","/asynchronous-django/introduction-to-asgi","19.asynchronous-django/02.introduction-to-asgi",{"title":713,"path":714,"stem":715},"Async Views","/asynchronous-django/async-views","19.asynchronous-django/03.async-views",{"title":717,"path":718,"stem":719},"Async ORM Status","/asynchronous-django/async-orm-status","19.asynchronous-django/04.async-orm-status",{"title":721,"path":722,"stem":723},"WebSockets with Channels","/asynchronous-django/websockets-with-channels","19.asynchronous-django/05.websockets-with-channels",{"title":725,"path":726,"stem":727},"Background Tasks with Celery or RQ","/asynchronous-django/background-tasks-with-celery-or-rq","19.asynchronous-django/06.background-tasks-with-celery-or-rq",{"title":729,"path":730,"stem":731},"Asynchronous Support","/asynchronous-django/asynchronous-support","19.asynchronous-django/07.asynchronous-support",{"title":733,"path":734,"stem":735},"Django's Tasks Framework","/asynchronous-django/django-tasks-framework","19.asynchronous-django/08.django-tasks-framework",{"title":737,"path":738,"stem":739,"children":740},"Deployment","/deployment","20.deployment/01.index",[741,742,746,750,754,758,762,766,770],{"title":737,"path":738,"stem":739},{"title":743,"path":744,"stem":745},"Preparing for Production","/deployment/preparing-for-production","20.deployment/02.preparing-for-production",{"title":747,"path":748,"stem":749},"Using WSGI and ASGI Servers","/deployment/using-wsgi-and-asgi-servers","20.deployment/03.using-wsgi-and-asgi-servers",{"title":751,"path":752,"stem":753},"Deploying on Linux Servers","/deployment/deploying-on-linux-servers","20.deployment/04.deploying-on-linux-servers",{"title":755,"path":756,"stem":757},"Using Docker","/deployment/using-docker","20.deployment/05.using-docker",{"title":759,"path":760,"stem":761},"Cloud Deployment Guides","/deployment/cloud-deployment-guides","20.deployment/06.cloud-deployment-guides",{"title":763,"path":764,"stem":765},"Scaling and Load Balancing","/deployment/scaling-and-load-balancing","20.deployment/07.scaling-and-load-balancing",{"title":767,"path":768,"stem":769},"Monitoring and Logging","/deployment/monitoring-and-logging","20.deployment/08.monitoring-and-logging",{"title":771,"path":772,"stem":773},"Backup Strategies","/deployment/backup-strategies","20.deployment/09.backup-strategies",{"title":775,"path":776,"stem":777,"children":778},"Performance and Optimization","/performance-and-optimization","21.performance-and-optimization/01.index",[779,780,784,788,792,796],{"title":775,"path":776,"stem":777},{"title":781,"path":782,"stem":783},"Query Optimization","/performance-and-optimization/query-optimization","21.performance-and-optimization/02.query-optimization",{"title":785,"path":786,"stem":787},"Template Rendering Optimization","/performance-and-optimization/template-rendering-optimization","21.performance-and-optimization/03.template-rendering-optimization",{"title":789,"path":790,"stem":791},"Using Select Related and Prefetch Related","/performance-and-optimization/using-select-related-and-prefetch-related","21.performance-and-optimization/04.using-select-related-and-prefetch-related",{"title":793,"path":794,"stem":795},"Caching Strategies","/performance-and-optimization/caching-strategies","21.performance-and-optimization/05.caching-strategies",{"title":797,"path":798,"stem":799},"Profiling Django Apps","/performance-and-optimization/profiling-django-apps","21.performance-and-optimization/06.profiling-django-apps",{"title":801,"path":802,"stem":803,"children":804},"Advanced and Expert Topics","/advanced-and-expert-topics","22.advanced-and-expert-topics/01.index",[805,806,810,814,818,822,826,830,834,838,842,846],{"title":801,"path":802,"stem":803},{"title":807,"path":808,"stem":809},"System Architecture Patterns","/advanced-and-expert-topics/system-architecture-patterns","22.advanced-and-expert-topics/02.system-architecture-patterns",{"title":811,"path":812,"stem":813},"Domain Driven Design with Django","/advanced-and-expert-topics/domain-driven-design-with-django","22.advanced-and-expert-topics/03.domain-driven-design-with-django",{"title":815,"path":816,"stem":817},"Building Large Scale Django Projects","/advanced-and-expert-topics/building-large-scale-django-projects","22.advanced-and-expert-topics/04.building-large-scale-django-projects",{"title":819,"path":820,"stem":821},"Plugin Architectures for Django Apps","/advanced-and-expert-topics/plugin-architectures-for-django-apps","22.advanced-and-expert-topics/05.plugin-architectures-for-django-apps",{"title":823,"path":824,"stem":825},"Extending Django's Core","/advanced-and-expert-topics/extending-djangos-core","22.advanced-and-expert-topics/06.extending-djangos-core",{"title":827,"path":828,"stem":829},"Custom ORM Expressions","/advanced-and-expert-topics/custom-orm-expressions","22.advanced-and-expert-topics/07.custom-orm-expressions",{"title":831,"path":832,"stem":833},"Custom Management Commands","/advanced-and-expert-topics/custom-management-commands","22.advanced-and-expert-topics/08.custom-management-commands",{"title":835,"path":836,"stem":837},"Working with Signals","/advanced-and-expert-topics/working-with-signals","22.advanced-and-expert-topics/09.working-with-signals",{"title":839,"path":840,"stem":841},"Building Reusable Django Packages","/advanced-and-expert-topics/building-reusable-django-packages","22.advanced-and-expert-topics/10.building-reusable-django-packages",{"title":843,"path":844,"stem":845},"Integrating Microservices","/advanced-and-expert-topics/integrating-microservices","22.advanced-and-expert-topics/11.integrating-microservices",{"title":847,"path":848,"stem":849},"Advanced Security Hardening","/advanced-and-expert-topics/advanced-security-hardening","22.advanced-and-expert-topics/12.advanced-security-hardening",{"title":851,"path":852,"stem":853,"children":854},"Logging in Django","/logging-in-django","23.logging-in-django/01.index",[855],{"title":851,"path":852,"stem":853},{"title":857,"path":858,"stem":859,"children":860},"FAQ and Troubleshooting","/faq-and-troubleshooting","24.faq-and-troubleshooting/01.index",[861],{"title":857,"path":858,"stem":859},{"title":863,"path":864,"stem":865,"children":866},"External Packages and Ecosystem","/external-packages-and-ecosystem","25.external-packages-and-ecosystem/01.index",[867],{"title":863,"path":864,"stem":865},{"title":869,"path":870,"stem":871,"children":872},"Django Internals and Contributing","/django-internals-and-contributing","26.django-internals-and-contributing/01.index",[873],{"title":869,"path":870,"stem":871},{"title":875,"path":876,"stem":877,"children":878},"Microservices with Django","/microservices-with-django","27.microservices-with-django/01.index",[879,880,884,888,892,896,900,904,908,912,916,920,924],{"title":875,"path":876,"stem":877},{"title":881,"path":882,"stem":883},"What Is a Microservice?","/microservices-with-django/what-is-a-microservice","27.microservices-with-django/02.what-is-a-microservice",{"title":885,"path":886,"stem":887},"Introducing the Django Microservices Architecture","/microservices-with-django/django-microservices-architecture","27.microservices-with-django/03.django-microservices-architecture",{"title":889,"path":890,"stem":891},"Setting Up the Development and Runtime Environment","/microservices-with-django/development-environment","27.microservices-with-django/04.development-environment",{"title":893,"path":894,"stem":895},"Cloud-native Data Processing with MongoDB","/microservices-with-django/cloud-native-data-processing","27.microservices-with-django/05.cloud-native-data-processing",{"title":897,"path":898,"stem":899},"Creating RESTful APIs for Microservices","/microservices-with-django/restful-apis","27.microservices-with-django/06.restful-apis",{"title":901,"path":902,"stem":903},"Orchestrating Microservices with Celery and RabbitMQ","/microservices-with-django/orchestrating-celery-rabbitmq","27.microservices-with-django/07.orchestrating-celery-rabbitmq",{"title":905,"path":906,"stem":907},"Testing Microservices","/microservices-with-django/testing-microservices","27.microservices-with-django/08.testing-microservices",{"title":909,"path":910,"stem":911},"Deploying Microservices","/microservices-with-django/deploying-microservices","27.microservices-with-django/09.deploying-microservices",{"title":913,"path":914,"stem":915},"Securing Microservices","/microservices-with-django/securing-microservices","27.microservices-with-django/10.securing-microservices",{"title":917,"path":918,"stem":919},"Improving Microservices Performance with Caching","/microservices-with-django/performance-caching","27.microservices-with-django/11.performance-caching",{"title":921,"path":922,"stem":923},"Best Practices","/microservices-with-django/best-practices","27.microservices-with-django/12.best-practices",{"title":925,"path":926,"stem":927},"Transforming a Monolithic Web App into a Microservice version","/microservices-with-django/monolith-to-microservices","27.microservices-with-django/13.monolith-to-microservices",{"title":929,"path":930,"stem":931,"children":932},"Releases","/releases","releases",[933,936,940,944,948,952,956,960,964,968,972,976,980,984,988,992,996,1000,1004,1008,1012],{"title":934,"path":930,"stem":935},"Django Releases","releases/index",{"title":937,"path":938,"stem":939},"Django 5.1.10 release notes","/releases/5.1.10","releases/5.1.10",{"title":941,"path":942,"stem":943},"Django 5.1.11 release notes","/releases/5.1.11","releases/5.1.11",{"title":945,"path":946,"stem":947},"Django 5.1.12 release notes","/releases/5.1.12","releases/5.1.12",{"title":949,"path":950,"stem":951},"Django 5.1.13 release notes","/releases/5.1.13","releases/5.1.13",{"title":953,"path":954,"stem":955},"Django 5.1.14 release notes","/releases/5.1.14","releases/5.1.14",{"title":957,"path":958,"stem":959},"Django 5.1.15 release notes","/releases/5.1.15","releases/5.1.15",{"title":961,"path":962,"stem":963},"Django 5.2 release notes","/releases/5.2","releases/5.2",{"title":965,"path":966,"stem":967},"Django 5.2.1 release notes","/releases/5.2.1","releases/5.2.1",{"title":969,"path":970,"stem":971},"Django 5.2.10 release notes","/releases/5.2.10","releases/5.2.10",{"title":973,"path":974,"stem":975},"Django 5.2.2 release notes","/releases/5.2.2","releases/5.2.2",{"title":977,"path":978,"stem":979},"Django 5.2.3 release notes","/releases/5.2.3","releases/5.2.3",{"title":981,"path":982,"stem":983},"Django 5.2.4 release notes","/releases/5.2.4","releases/5.2.4",{"title":985,"path":986,"stem":987},"Django 5.2.5 release notes","/releases/5.2.5","releases/5.2.5",{"title":989,"path":990,"stem":991},"Django 5.2.6 release notes","/releases/5.2.6","releases/5.2.6",{"title":993,"path":994,"stem":995},"Django 5.2.7 release notes","/releases/5.2.7","releases/5.2.7",{"title":997,"path":998,"stem":999},"Django 5.2.8 release notes","/releases/5.2.8","releases/5.2.8",{"title":1001,"path":1002,"stem":1003},"Django 5.2.9 release notes","/releases/5.2.9","releases/5.2.9",{"title":1005,"path":1006,"stem":1007},"Django 6.0 release notes","/releases/6.0","releases/6.0",{"title":1009,"path":1010,"stem":1011},"Django 6.0.1 release notes","/releases/6.0.1","releases/6.0.1",{"title":1013,"path":1014,"stem":1015},"Django 6.1 release notes - UNDER DEVELOPMENT","/releases/6.1","releases/6.1",{"id":1017,"title":408,"body":1018,"description":1028,"extension":10519,"links":10520,"meta":10521,"navigation":1172,"path":409,"seo":10522,"stem":410,"__hash__":10523},"docs/09.authentication-and-authorization/05.password-management.md",{"type":1019,"value":1020,"toc":10514},"minimark",[1021,1025,1029,1034,1039,10507,10510],[1022,1023,408],"h1",{"id":1024},"password-management",[1026,1027,1028],"p",{},"Secure password management is critical for protecting user accounts and maintaining application security. Django provides robust password handling capabilities including hashing, validation, and secure storage. Understanding these features enables you to implement strong password policies and protect user credentials.",[1030,1031,1033],"h2",{"id":1032},"password-hashing-and-storage","Password Hashing and Storage",[1035,1036,1038],"h3",{"id":1037},"djangos-password-hashing-system","Django's Password Hashing System",[1040,1041,1046],"pre",{"className":1042,"code":1043,"language":1044,"meta":1045,"style":1045},"language-python shiki shiki-themes material-theme-lighter vitesse-light vitesse-dark","# Django's password hashing system\nfrom django.contrib.auth.hashers import (\n    make_password, check_password, is_password_usable,\n    get_hasher, identify_hasher\n)\nfrom django.contrib.auth import get_user_model\nfrom django.conf import settings\n\nUser = get_user_model()\n\nclass PasswordHashingSystem:\n    \"\"\"Understanding Django's password hashing system\"\"\"\n    \n    @staticmethod\n    def password_hasher_configuration():\n        \"\"\"Configure password hashers in settings\"\"\"\n        \n        # Django's default password hashers (in order of preference)\n        password_hashers = [\n            'django.contrib.auth.hashers.Argon2PasswordHasher',      # Most secure (default)\n            'django.contrib.auth.hashers.PBKDF2PasswordHasher',      # Fallback\n            'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',  # Legacy\n            'django.contrib.auth.hashers.BCryptSHA256PasswordHasher', # Alternative\n            'django.contrib.auth.hashers.ScryptPasswordHasher',      # Alternative\n        ]\n        \n        # Custom hasher configuration\n        custom_settings = {\n            'PASSWORD_HASHERS': password_hashers,\n            \n            # Argon2 configuration\n            'ARGON2_TIME_COST': 2,      # Number of iterations\n            'ARGON2_MEMORY_COST': 512,  # Memory usage in KB\n            'ARGON2_PARALLELISM': 2,    # Number of parallel threads\n            \n            # PBKDF2 configuration\n            'PBKDF2_ITERATIONS': 320000,  # Number of iterations (Django 4.0+)\n        }\n        \n        return custom_settings\n    \n    @staticmethod\n    def password_hashing_examples():\n        \"\"\"Examples of password hashing operations\"\"\"\n        \n        # Hash a password\n        plain_password = \"secure_password123\"\n        hashed_password = make_password(plain_password)\n        \n        print(f\"Plain password: {plain_password}\")\n        print(f\"Hashed password: {hashed_password}\")\n        \n        # Check password\n        is_correct = check_password(plain_password, hashed_password)\n        print(f\"Password check: {is_correct}\")\n        \n        # Check if password is usable\n        is_usable = is_password_usable(hashed_password)\n        print(f\"Password is usable: {is_usable}\")\n        \n        # Get hasher information\n        hasher = identify_hasher(hashed_password)\n        print(f\"Hasher algorithm: {hasher.algorithm}\")\n        \n        return {\n            'hashed_password': hashed_password,\n            'is_correct': is_correct,\n            'is_usable': is_usable,\n            'algorithm': hasher.algorithm\n        }\n    \n    @staticmethod\n    def custom_password_hasher():\n        \"\"\"Create a custom password hasher\"\"\"\n        \n        from django.contrib.auth.hashers import BasePasswordHasher\n        import hashlib\n        import secrets\n        \n        class CustomSHA256Hasher(BasePasswordHasher):\n            \"\"\"\n            Custom SHA256-based password hasher\n            Note: This is for demonstration - use Django's built-in hashers in production\n            \"\"\"\n            \n            algorithm = \"custom_sha256\"\n            library = \"hashlib\"\n            \n            def encode(self, password, salt):\n                \"\"\"Encode password with salt\"\"\"\n                \n                if not salt:\n                    salt = self.salt()\n                \n                # Combine password and salt\n                combined = f\"{salt}${password}\"\n                \n                # Hash multiple times for security\n                hash_value = combined.encode('utf-8')\n                for _ in range(10000):  # 10,000 iterations\n                    hash_value = hashlib.sha256(hash_value).digest()\n                \n                # Convert to hex\n                hash_hex = hash_value.hex()\n                \n                return f\"{self.algorithm}${salt}${hash_hex}\"\n            \n            def verify(self, password, encoded):\n                \"\"\"Verify password against encoded hash\"\"\"\n                \n                algorithm, salt, hash_value = encoded.split('$', 2)\n                \n                # Encode the provided password\n                encoded_2 = self.encode(password, salt)\n                \n                # Compare hashes\n                return encoded == encoded_2\n            \n            def safe_summary(self, encoded):\n                \"\"\"Return safe summary of encoded password\"\"\"\n                \n                algorithm, salt, hash_value = encoded.split('$', 2)\n                \n                return {\n                    'algorithm': algorithm,\n                    'salt': salt[:6] + '...',\n                    'hash': hash_value[:6] + '...',\n                }\n            \n            def harden_runtime(self, password, encoded):\n                \"\"\"Harden against timing attacks\"\"\"\n                pass\n            \n            def must_update(self, encoded):\n                \"\"\"Check if password needs to be updated\"\"\"\n                return False\n        \n        return CustomSHA256Hasher\n    \n    @staticmethod\n    def password_upgrade_mechanism():\n        \"\"\"Implement password upgrade mechanism\"\"\"\n        \n        def upgrade_user_password(user, raw_password):\n            \"\"\"Upgrade user's password hash if needed\"\"\"\n            \n            # Check if password needs upgrading\n            if user.password:\n                hasher = identify_hasher(user.password)\n                \n                # Check if we're using the preferred hasher\n                preferred_hasher = get_hasher()\n                \n                if hasher.algorithm != preferred_hasher.algorithm:\n                    # Upgrade to preferred hasher\n                    user.set_password(raw_password)\n                    user.save(update_fields=['password'])\n                    \n                    return True, f\"Upgraded from {hasher.algorithm} to {preferred_hasher.algorithm}\"\n                \n                # Check if hasher parameters need updating\n                elif hasher.must_update(user.password):\n                    user.set_password(raw_password)\n                    user.save(update_fields=['password'])\n                    \n                    return True, f\"Updated {hasher.algorithm} parameters\"\n            \n            return False, \"No upgrade needed\"\n        \n        def bulk_password_upgrade():\n            \"\"\"Upgrade passwords for all users (run during maintenance)\"\"\"\n            \n            upgraded_count = 0\n            \n            # This would typically be done when users log in\n            # Here's how you might do a bulk upgrade if you have access to plain passwords\n            \n            for user in User.objects.all():\n                if user.password:\n                    hasher = identify_hasher(user.password)\n                    preferred_hasher = get_hasher()\n                    \n                    if hasher.algorithm != preferred_hasher.algorithm:\n                        # In practice, you can't upgrade without the plain password\n                        # This would be done during login when you have access to it\n                        print(f\"User {user.username} needs password upgrade\")\n                        upgraded_count += 1\n            \n            return upgraded_count\n        \n        return upgrade_user_password, bulk_password_upgrade\n\n# Password validation\nclass PasswordValidation:\n    \"\"\"Implement comprehensive password validation\"\"\"\n    \n    @staticmethod\n    def django_password_validators():\n        \"\"\"Configure Django's built-in password validators\"\"\"\n        \n        password_validators = [\n            {\n                'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',\n                'OPTIONS': {\n                    'user_attributes': ('username', 'first_name', 'last_name', 'email'),\n                    'max_similarity': 0.7,\n                }\n            },\n            {\n                'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',\n                'OPTIONS': {\n                    'min_length': 12,\n                }\n            },\n            {\n                'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',\n            },\n            {\n                'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',\n            },\n        ]\n        \n        return password_validators\n    \n    @staticmethod\n    def custom_password_validators():\n        \"\"\"Create custom password validators\"\"\"\n        \n        from django.contrib.auth.password_validation import CommonPasswordValidator\n        from django.core.exceptions import ValidationError\n        import re\n        \n        class ComplexityValidator:\n            \"\"\"Validate password complexity requirements\"\"\"\n            \n            def __init__(self, min_uppercase=1, min_lowercase=1, min_digits=1, min_special=1):\n                self.min_uppercase = min_uppercase\n                self.min_lowercase = min_lowercase\n                self.min_digits = min_digits\n                self.min_special = min_special\n            \n            def validate(self, password, user=None):\n                \"\"\"Validate password complexity\"\"\"\n                \n                errors = []\n                \n                # Check uppercase letters\n                uppercase_count = len(re.findall(r'[A-Z]', password))\n                if uppercase_count \u003C self.min_uppercase:\n                    errors.append(\n                        f\"Password must contain at least {self.min_uppercase} uppercase letter(s).\"\n                    )\n                \n                # Check lowercase letters\n                lowercase_count = len(re.findall(r'[a-z]', password))\n                if lowercase_count \u003C self.min_lowercase:\n                    errors.append(\n                        f\"Password must contain at least {self.min_lowercase} lowercase letter(s).\"\n                    )\n                \n                # Check digits\n                digit_count = len(re.findall(r'\\d', password))\n                if digit_count \u003C self.min_digits:\n                    errors.append(\n                        f\"Password must contain at least {self.min_digits} digit(s).\"\n                    )\n                \n                # Check special characters\n                special_count = len(re.findall(r'[!@#$%^&*(),.?\":{}|\u003C>]', password))\n                if special_count \u003C self.min_special:\n                    errors.append(\n                        f\"Password must contain at least {self.min_special} special character(s).\"\n                    )\n                \n                if errors:\n                    raise ValidationError(errors)\n            \n            def get_help_text(self):\n                \"\"\"Return help text for password requirements\"\"\"\n                \n                return (\n                    f\"Your password must contain at least {self.min_uppercase} uppercase letter, \"\n                    f\"{self.min_lowercase} lowercase letter, {self.min_digits} digit, \"\n                    f\"and {self.min_special} special character.\"\n                )\n        \n        class PasswordHistoryValidator:\n            \"\"\"Prevent reuse of recent passwords\"\"\"\n            \n            def __init__(self, history_count=5):\n                self.history_count = history_count\n            \n            def validate(self, password, user=None):\n                \"\"\"Check against password history\"\"\"\n                \n                if user and hasattr(user, 'password_history'):\n                    # Get recent password hashes\n                    recent_passwords = user.password_history.order_by('-created_at')[:self.history_count]\n                    \n                    for old_password in recent_passwords:\n                        if check_password(password, old_password.password_hash):\n                            raise ValidationError(\n                                f\"Password cannot be one of your last {self.history_count} passwords.\"\n                            )\n            \n            def get_help_text(self):\n                return f\"Password cannot be one of your last {self.history_count} passwords.\"\n        \n        class PasswordExpiryValidator:\n            \"\"\"Validate password age\"\"\"\n            \n            def __init__(self, max_age_days=90):\n                self.max_age_days = max_age_days\n            \n            def validate(self, password, user=None):\n                \"\"\"Check if password needs to be changed due to age\"\"\"\n                \n                if user and user.password:\n                    # Check when password was last changed\n                    if hasattr(user, 'password_changed_at'):\n                        password_age = timezone.now() - user.password_changed_at\n                        \n                        if password_age.days > self.max_age_days:\n                            raise ValidationError(\n                                f\"Password is {password_age.days} days old. \"\n                                f\"Passwords must be changed every {self.max_age_days} days.\"\n                            )\n            \n            def get_help_text(self):\n                return f\"Passwords must be changed every {self.max_age_days} days.\"\n        \n        return ComplexityValidator, PasswordHistoryValidator, PasswordExpiryValidator\n    \n    @staticmethod\n    def validate_password_strength():\n        \"\"\"Comprehensive password strength validation\"\"\"\n        \n        from django.contrib.auth.password_validation import validate_password\n        from django.core.exceptions import ValidationError\n        \n        def check_password_strength(password, user=None):\n            \"\"\"Check password strength and return detailed feedback\"\"\"\n            \n            strength_score = 0\n            feedback = []\n            \n            # Length check\n            if len(password) >= 12:\n                strength_score += 2\n                feedback.append(\"✓ Good length (12+ characters)\")\n            elif len(password) >= 8:\n                strength_score += 1\n                feedback.append(\"⚠ Minimum length met (8+ characters)\")\n            else:\n                feedback.append(\"✗ Too short (minimum 8 characters)\")\n            \n            # Character variety\n            has_upper = bool(re.search(r'[A-Z]', password))\n            has_lower = bool(re.search(r'[a-z]', password))\n            has_digit = bool(re.search(r'\\d', password))\n            has_special = bool(re.search(r'[!@#$%^&*(),.?\":{}|\u003C>]', password))\n            \n            variety_count = sum([has_upper, has_lower, has_digit, has_special])\n            \n            if variety_count >= 4:\n                strength_score += 3\n                feedback.append(\"✓ Excellent character variety\")\n            elif variety_count >= 3:\n                strength_score += 2\n                feedback.append(\"✓ Good character variety\")\n            elif variety_count >= 2:\n                strength_score += 1\n                feedback.append(\"⚠ Basic character variety\")\n            else:\n                feedback.append(\"✗ Poor character variety\")\n            \n            # Common patterns check\n            common_patterns = [\n                r'123', r'abc', r'qwerty', r'password', r'admin'\n            ]\n            \n            has_common_pattern = any(\n                re.search(pattern, password.lower()) for pattern in common_patterns\n            )\n            \n            if not has_common_pattern:\n                strength_score += 1\n                feedback.append(\"✓ No common patterns detected\")\n            else:\n                feedback.append(\"✗ Contains common patterns\")\n            \n            # Django validation\n            try:\n                validate_password(password, user)\n                strength_score += 1\n                feedback.append(\"✓ Passes Django validation\")\n            except ValidationError as e:\n                feedback.extend([f\"✗ {error}\" for error in e.messages])\n            \n            # Calculate strength level\n            if strength_score >= 6:\n                strength_level = \"Very Strong\"\n            elif strength_score >= 4:\n                strength_level = \"Strong\"\n            elif strength_score >= 2:\n                strength_level = \"Moderate\"\n            else:\n                strength_level = \"Weak\"\n            \n            return {\n                'score': strength_score,\n                'max_score': 7,\n                'level': strength_level,\n                'feedback': feedback\n            }\n        \n        return check_password_strength\n\n# Password reset and recovery\nclass PasswordResetSystem:\n    \"\"\"Implement secure password reset functionality\"\"\"\n    \n    @staticmethod\n    def secure_password_reset_tokens():\n        \"\"\"Generate secure password reset tokens\"\"\"\n        \n        from django.contrib.auth.tokens import PasswordResetTokenGenerator\n        from django.utils.crypto import constant_time_compare\n        import hashlib\n        \n        class SecurePasswordResetTokenGenerator(PasswordResetTokenGenerator):\n            \"\"\"Enhanced password reset token generator\"\"\"\n            \n            def _make_hash_value(self, user, timestamp):\n                \"\"\"Create hash value for token generation\"\"\"\n                \n                # Include additional user data for security\n                login_timestamp = '' if user.last_login is None else user.last_login.replace(microsecond=0, tzinfo=None)\n                \n                return (\n                    str(user.pk) + user.password + str(login_timestamp) + \n                    str(timestamp) + str(user.email)\n                )\n            \n            def check_token(self, user, token):\n                \"\"\"Check if token is valid with additional security checks\"\"\"\n                \n                # Check if user is active\n                if not user.is_active:\n                    return False\n                \n                # Check token age (24 hours max)\n                if not super().check_token(user, token):\n                    return False\n                \n                # Additional security: check if password was changed after token generation\n                # This would require storing token generation time\n                \n                return True\n        \n        # Custom token generator with shorter expiry\n        class ShortLivedTokenGenerator(PasswordResetTokenGenerator):\n            \"\"\"Token generator with shorter expiry time\"\"\"\n            \n            def _num_seconds(self, dt):\n                \"\"\"Return number of seconds since epoch\"\"\"\n                return int((dt - datetime(2001, 1, 1)).total_seconds())\n            \n            def _make_token_with_timestamp(self, user, timestamp, legacy=False):\n                \"\"\"Generate token with custom timestamp handling\"\"\"\n                \n                # Reduce token lifetime to 1 hour (3600 seconds)\n                ts_b36 = base36.dumps(timestamp)\n                hash_string = salted_hmac(\n                    self.key_salt,\n                    self._make_hash_value(user, timestamp),\n                    secret=self.secret,\n                    algorithm=self.algorithm,\n                ).hexdigest()[::2]\n                \n                return f\"{ts_b36}-{hash_string}\"\n        \n        return SecurePasswordResetTokenGenerator, ShortLivedTokenGenerator\n    \n    @staticmethod\n    def password_reset_rate_limiting():\n        \"\"\"Implement rate limiting for password reset requests\"\"\"\n        \n        from django.core.cache import cache\n        from django.http import HttpResponseTooManyRequests\n        \n        def rate_limit_password_reset(email, max_attempts=3, window=3600):\n            \"\"\"Rate limit password reset attempts\"\"\"\n            \n            cache_key = f\"password_reset_{email}\"\n            attempts = cache.get(cache_key, 0)\n            \n            if attempts >= max_attempts:\n                return False, f\"Too many password reset attempts. Try again in {window//60} minutes.\"\n            \n            # Increment attempts\n            cache.set(cache_key, attempts + 1, window)\n            \n            return True, f\"Password reset email sent. {max_attempts - attempts - 1} attempts remaining.\"\n        \n        def password_reset_view_with_rate_limiting(request):\n            \"\"\"Password reset view with rate limiting\"\"\"\n            \n            if request.method == 'POST':\n                email = request.POST.get('email')\n                \n                # Check rate limit\n                allowed, message = rate_limit_password_reset(email)\n                \n                if not allowed:\n                    return HttpResponseTooManyRequests(message)\n                \n                # Proceed with password reset\n                try:\n                    user = User.objects.get(email=email)\n                    # Send password reset email\n                    messages.success(request, \"Password reset email sent.\")\n                except User.DoesNotExist:\n                    # Don't reveal if email exists\n                    messages.success(request, \"If the email exists, a reset link has been sent.\")\n            \n            return render(request, 'password_reset.html')\n        \n        return rate_limit_password_reset, password_reset_view_with_rate_limiting\n    \n    @staticmethod\n    def secure_password_reset_workflow():\n        \"\"\"Implement complete secure password reset workflow\"\"\"\n        \n        from django.core.mail import send_mail\n        from django.urls import reverse\n        from django.contrib.sites.shortcuts import get_current_site\n        \n        def initiate_password_reset(request, email):\n            \"\"\"Initiate password reset process\"\"\"\n            \n            try:\n                user = User.objects.get(email=email, is_active=True)\n            except User.DoesNotExist:\n                # Don't reveal if user exists\n                return True, \"If the email exists, a reset link has been sent.\"\n            \n            # Generate token\n            token_generator = SecurePasswordResetTokenGenerator()\n            token = token_generator.make_token(user)\n            \n            # Create reset URL\n            current_site = get_current_site(request)\n            reset_url = request.build_absolute_uri(\n                reverse('password_reset_confirm', kwargs={\n                    'uidb64': urlsafe_base64_encode(force_bytes(user.pk)),\n                    'token': token,\n                })\n            )\n            \n            # Send email\n            subject = f\"Password Reset - {current_site.name}\"\n            message = f\"\"\"\n            Hello {user.get_full_name() or user.username},\n            \n            You requested a password reset for your account at {current_site.name}.\n            \n            Please click the link below to reset your password:\n            {reset_url}\n            \n            This link will expire in 24 hours.\n            \n            If you didn't request this reset, please ignore this email.\n            \n            Best regards,\n            The {current_site.name} Team\n            \"\"\"\n            \n            send_mail(\n                subject,\n                message,\n                settings.DEFAULT_FROM_EMAIL,\n                [user.email],\n                fail_silently=False,\n            )\n            \n            # Log password reset request\n            import logging\n            logger = logging.getLogger(__name__)\n            logger.info(f\"Password reset requested for user: {user.username}\")\n            \n            return True, \"Password reset email sent.\"\n        \n        def confirm_password_reset(uidb64, token, new_password):\n            \"\"\"Confirm password reset and set new password\"\"\"\n            \n            try:\n                # Decode user ID\n                uid = force_str(urlsafe_base64_decode(uidb64))\n                user = User.objects.get(pk=uid)\n            except (TypeError, ValueError, OverflowError, User.DoesNotExist):\n                return False, \"Invalid reset link.\"\n            \n            # Check token\n            token_generator = SecurePasswordResetTokenGenerator()\n            if not token_generator.check_token(user, token):\n                return False, \"Invalid or expired reset link.\"\n            \n            # Validate new password\n            try:\n                validate_password(new_password, user)\n            except ValidationError as e:\n                return False, e.messages\n            \n            # Set new password\n            user.set_password(new_password)\n            user.save()\n            \n            # Log successful password reset\n            import logging\n            logger = logging.getLogger(__name__)\n            logger.info(f\"Password reset completed for user: {user.username}\")\n            \n            return True, \"Password reset successfully.\"\n        \n        return initiate_password_reset, confirm_password_reset\n\n# Password security monitoring\nclass PasswordSecurityMonitoring:\n    \"\"\"Monitor and analyze password security\"\"\"\n    \n    @staticmethod\n    def password_breach_checking():\n        \"\"\"Check passwords against known breaches\"\"\"\n        \n        import hashlib\n        import requests\n        \n        def check_password_breach(password):\n            \"\"\"Check if password appears in known breaches using HaveIBeenPwned API\"\"\"\n            \n            # Hash password with SHA-1\n            sha1_hash = hashlib.sha1(password.encode('utf-8')).hexdigest().upper()\n            \n            # Use k-anonymity: send only first 5 characters\n            prefix = sha1_hash[:5]\n            suffix = sha1_hash[5:]\n            \n            try:\n                # Query HaveIBeenPwned API\n                response = requests.get(\n                    f\"https://api.pwnedpasswords.com/range/{prefix}\",\n                    timeout=5\n                )\n                \n                if response.status_code == 200:\n                    # Check if our suffix appears in results\n                    for line in response.text.splitlines():\n                        hash_suffix, count = line.split(':')\n                        if hash_suffix == suffix:\n                            return True, int(count)\n                    \n                    return False, 0\n                \n            except requests.RequestException:\n                # If API is unavailable, don't block password change\n                return None, 0\n            \n            return False, 0\n        \n        def validate_password_not_breached(password):\n            \"\"\"Validator to check password against breaches\"\"\"\n            \n            is_breached, count = check_password_breach(password)\n            \n            if is_breached:\n                if count > 100:\n                    raise ValidationError(\n                        f\"This password has been found in {count} data breaches. \"\n                        \"Please choose a different password.\"\n                    )\n                else:\n                    # Just warn for passwords with low breach counts\n                    pass\n        \n        return check_password_breach, validate_password_not_breached\n    \n    @staticmethod\n    def password_analytics():\n        \"\"\"Analyze password patterns and security\"\"\"\n        \n        def analyze_user_passwords():\n            \"\"\"Analyze password patterns across all users\"\"\"\n            \n            from collections import defaultdict\n            \n            analytics = {\n                'total_users': User.objects.count(),\n                'users_with_passwords': User.objects.exclude(password='').count(),\n                'password_algorithms': defaultdict(int),\n                'weak_passwords': 0,\n                'expired_passwords': 0,\n            }\n            \n            for user in User.objects.exclude(password=''):\n                # Analyze password hash algorithm\n                if user.password:\n                    try:\n                        hasher = identify_hasher(user.password)\n                        analytics['password_algorithms'][hasher.algorithm] += 1\n                    except ValueError:\n                        analytics['password_algorithms']['unknown'] += 1\n                \n                # Check for weak passwords (would need additional data)\n                # This is a simplified example\n                if len(user.password) \u003C 100:  # Rough estimate for weak hash\n                    analytics['weak_passwords'] += 1\n            \n            return analytics\n        \n        def generate_password_security_report():\n            \"\"\"Generate comprehensive password security report\"\"\"\n            \n            analytics = analyze_user_passwords()\n            \n            report = {\n                'summary': analytics,\n                'recommendations': [],\n                'action_items': []\n            }\n            \n            # Generate recommendations\n            if analytics['password_algorithms'].get('md5', 0) > 0:\n                report['recommendations'].append(\n                    \"Upgrade users from MD5 password hashing\"\n                )\n                report['action_items'].append(\n                    \"Force password reset for users with MD5 hashes\"\n                )\n            \n            if analytics['weak_passwords'] > analytics['total_users'] * 0.1:\n                report['recommendations'].append(\n                    \"Implement stronger password requirements\"\n                )\n            \n            return report\n        \n        return analyze_user_passwords, generate_password_security_report\n","python","",[1047,1048,1049,1058,1092,1112,1123,1129,1150,1167,1174,1190,1195,1209,1223,1229,1239,1252,1263,1269,1275,1286,1305,1320,1335,1350,1365,1371,1376,1382,1393,1411,1417,1423,1444,1464,1483,1488,1494,1514,1520,1525,1534,1539,1546,1556,1566,1571,1577,1594,1613,1618,1647,1670,1675,1681,1702,1725,1730,1736,1752,1775,1780,1786,1803,1832,1837,1844,1859,1875,1891,1910,1915,1920,1927,1937,1947,1952,1977,1986,1994,1999,2017,2023,2029,2035,2040,2045,2060,2075,2080,2108,2119,2125,2139,2158,2163,2169,2200,2205,2211,2238,2264,2293,2298,2304,2322,2327,2366,2371,2394,2404,2409,2447,2452,2458,2482,2487,2493,2507,2512,2530,2540,2545,2580,2585,2592,2609,2644,2674,2680,2685,2707,2717,2723,2728,2746,2756,2765,2770,2778,2783,2790,2800,2810,2815,2836,2847,2852,2858,2873,2893,2898,2904,2917,2922,2945,2951,2969,2997,3003,3045,3050,3056,3079,3094,3117,3122,3149,3154,3172,3177,3187,3197,3202,3213,3218,3224,3230,3235,3261,3274,3294,3306,3311,3333,3339,3345,3374,3386,3391,3399,3404,3416,3421,3427,3437,3447,3452,3459,3469,3479,3484,3494,3500,3522,3536,3587,3604,3609,3615,3620,3640,3653,3670,3675,3680,3685,3705,3710,3715,3735,3740,3745,3750,3758,3763,3770,3780,3790,3795,3820,3842,3850,3855,3865,3875,3880,3931,3948,3963,3978,3993,3998,4025,4035,4040,4051,4056,4062,4109,4128,4142,4164,4170,4175,4181,4220,4238,4249,4269,4274,4279,4285,4321,4339,4350,4370,4375,4380,4386,4425,4443,4454,4474,4479,4484,4494,4510,4515,4529,4539,4544,4551,4573,4606,4627,4633,4638,4648,4658,4663,4686,4701,4706,4731,4741,4746,4774,4780,4820,4825,4841,4865,4875,4897,4903,4908,4921,4942,4947,4957,4967,4972,4995,5010,5015,5040,5050,5055,5072,5078,5100,5129,5135,5159,5168,5190,5211,5216,5221,5234,5255,5260,5276,5281,5288,5298,5308,5313,5337,5356,5361,5383,5393,5398,5408,5418,5423,5429,5450,5461,5482,5503,5512,5532,5540,5560,5565,5571,5611,5649,5683,5721,5726,5760,5765,5781,5791,5811,5825,5834,5854,5867,5876,5896,5903,5923,5928,5934,5944,6003,6009,6014,6027,6065,6071,6076,6088,6097,6117,6124,6144,6149,6155,6163,6179,6188,6208,6225,6267,6272,6278,6293,6308,6321,6335,6348,6362,6369,6383,6388,6395,6412,6429,6446,6461,6467,6472,6480,6485,6491,6501,6511,6516,6523,6533,6543,6548,6573,6595,6602,6607,6622,6632,6637,6660,6670,6675,6681,6743,6748,6755,6797,6823,6828,6833,6856,6866,6871,6877,6893,6900,6905,6911,6937,6944,6949,6955,6961,6966,6974,6979,6985,6999,7009,7014,7033,7043,7086,7091,7123,7133,7138,7144,7166,7179,7192,7212,7229,7245,7262,7267,7294,7299,7311,7316,7323,7333,7343,7348,7369,7386,7391,7425,7435,7440,7461,7489,7494,7508,7538,7543,7549,7579,7584,7616,7621,7636,7646,7651,7676,7705,7710,7716,7737,7742,7754,7769,7774,7780,7788,7816,7822,7848,7863,7869,7893,7898,7921,7926,7938,7943,7950,7960,7970,7975,7996,8013,8039,8044,8063,8073,8078,8085,8123,8136,8142,8157,8162,8168,8180,8202,8207,8213,8230,8247,8270,8301,8317,8323,8328,8333,8339,8366,8378,8408,8413,8432,8437,8443,8455,8460,8466,8471,8477,8482,8488,8507,8512,8517,8525,8533,8541,8554,8569,8581,8586,8591,8597,8606,8630,8662,8667,8682,8687,8710,8720,8725,8732,8738,8760,8788,8818,8834,8839,8845,8856,8879,8895,8900,8906,8913,8929,8942,8958,8963,8969,8985,8996,9001,9007,9014,9033,9063,9068,9084,9089,9101,9106,9112,9122,9132,9137,9144,9154,9164,9169,9176,9184,9189,9203,9213,9218,9224,9266,9271,9277,9294,9311,9316,9323,9329,9346,9365,9376,9381,9386,9406,9412,9436,9466,9481,9500,9505,9516,9521,9535,9541,9552,9557,9568,9573,9587,9597,9602,9622,9627,9637,9652,9661,9678,9689,9694,9702,9708,9714,9719,9731,9736,9743,9753,9763,9768,9778,9788,9793,9807,9812,9822,9847,9885,9907,9923,9939,9944,9949,9978,9984,9997,10005,10025,10055,10065,10093,10098,10104,10110,10137,10157,10162,10170,10175,10185,10195,10200,10211,10216,10226,10243,10258,10272,10277,10282,10288,10329,10349,10360,10365,10384,10394,10399,10404,10443,10462,10472,10477,10482,10490,10495],"code",{"__ignoreMap":1045},[1050,1051,1054],"span",{"class":1052,"line":1053},"line",1,[1050,1055,1057],{"class":1056},"s9Tkl","# Django's password hashing system\n",[1050,1059,1061,1065,1069,1073,1076,1078,1081,1083,1086,1089],{"class":1052,"line":1060},2,[1050,1062,1064],{"class":1063},"siDh9","from",[1050,1066,1068],{"class":1067},"sftqT"," django",[1050,1070,1072],{"class":1071},"soVBu",".",[1050,1074,1075],{"class":1067},"contrib",[1050,1077,1072],{"class":1071},[1050,1079,1080],{"class":1067},"auth",[1050,1082,1072],{"class":1071},[1050,1084,1085],{"class":1067},"hashers ",[1050,1087,1088],{"class":1063},"import",[1050,1090,1091],{"class":1071}," (\n",[1050,1093,1095,1098,1101,1104,1106,1109],{"class":1052,"line":1094},3,[1050,1096,1097],{"class":1067},"    make_password",[1050,1099,1100],{"class":1071},",",[1050,1102,1103],{"class":1067}," check_password",[1050,1105,1100],{"class":1071},[1050,1107,1108],{"class":1067}," is_password_usable",[1050,1110,1111],{"class":1071},",\n",[1050,1113,1115,1118,1120],{"class":1052,"line":1114},4,[1050,1116,1117],{"class":1067},"    get_hasher",[1050,1119,1100],{"class":1071},[1050,1121,1122],{"class":1067}," identify_hasher\n",[1050,1124,1126],{"class":1052,"line":1125},5,[1050,1127,1128],{"class":1071},")\n",[1050,1130,1132,1134,1136,1138,1140,1142,1145,1147],{"class":1052,"line":1131},6,[1050,1133,1064],{"class":1063},[1050,1135,1068],{"class":1067},[1050,1137,1072],{"class":1071},[1050,1139,1075],{"class":1067},[1050,1141,1072],{"class":1071},[1050,1143,1144],{"class":1067},"auth ",[1050,1146,1088],{"class":1063},[1050,1148,1149],{"class":1067}," get_user_model\n",[1050,1151,1153,1155,1157,1159,1162,1164],{"class":1052,"line":1152},7,[1050,1154,1064],{"class":1063},[1050,1156,1068],{"class":1067},[1050,1158,1072],{"class":1071},[1050,1160,1161],{"class":1067},"conf ",[1050,1163,1088],{"class":1063},[1050,1165,1166],{"class":1067}," settings\n",[1050,1168,1170],{"class":1052,"line":1169},8,[1050,1171,1173],{"emptyLinePlaceholder":1172},true,"\n",[1050,1175,1177,1180,1183,1187],{"class":1052,"line":1176},9,[1050,1178,1179],{"class":1067},"User ",[1050,1181,1182],{"class":1071},"=",[1050,1184,1186],{"class":1185},"siWMO"," get_user_model",[1050,1188,1189],{"class":1071},"()\n",[1050,1191,1193],{"class":1052,"line":1192},10,[1050,1194,1173],{"emptyLinePlaceholder":1172},[1050,1196,1198,1202,1206],{"class":1052,"line":1197},11,[1050,1199,1201],{"class":1200},"s5Kfy","class",[1050,1203,1205],{"class":1204},"sD-vU"," PasswordHashingSystem",[1050,1207,1208],{"class":1071},":\n",[1050,1210,1212,1216,1220],{"class":1052,"line":1211},12,[1050,1213,1215],{"class":1214},"sm7ve","    \"\"\"",[1050,1217,1219],{"class":1218},"sVyVU","Understanding Django's password hashing system",[1050,1221,1222],{"class":1214},"\"\"\"\n",[1050,1224,1226],{"class":1052,"line":1225},13,[1050,1227,1228],{"class":1067},"    \n",[1050,1230,1232,1235],{"class":1052,"line":1231},14,[1050,1233,1234],{"class":1071},"    @",[1050,1236,1238],{"class":1237},"sa2tF","staticmethod\n",[1050,1240,1242,1245,1249],{"class":1052,"line":1241},15,[1050,1243,1244],{"class":1200},"    def",[1050,1246,1248],{"class":1247},"sljsM"," password_hasher_configuration",[1050,1250,1251],{"class":1071},"():\n",[1050,1253,1255,1258,1261],{"class":1052,"line":1254},16,[1050,1256,1257],{"class":1214},"        \"\"\"",[1050,1259,1260],{"class":1218},"Configure password hashers in settings",[1050,1262,1222],{"class":1214},[1050,1264,1266],{"class":1052,"line":1265},17,[1050,1267,1268],{"class":1067},"        \n",[1050,1270,1272],{"class":1052,"line":1271},18,[1050,1273,1274],{"class":1056},"        # Django's default password hashers (in order of preference)\n",[1050,1276,1278,1281,1283],{"class":1052,"line":1277},19,[1050,1279,1280],{"class":1067},"        password_hashers ",[1050,1282,1182],{"class":1071},[1050,1284,1285],{"class":1071}," [\n",[1050,1287,1289,1293,1297,1300,1302],{"class":1052,"line":1288},20,[1050,1290,1292],{"class":1291},"sbYkP","            '",[1050,1294,1296],{"class":1295},"sTbE_","django.contrib.auth.hashers.Argon2PasswordHasher",[1050,1298,1299],{"class":1291},"'",[1050,1301,1100],{"class":1071},[1050,1303,1304],{"class":1056},"      # Most secure (default)\n",[1050,1306,1308,1310,1313,1315,1317],{"class":1052,"line":1307},21,[1050,1309,1292],{"class":1291},[1050,1311,1312],{"class":1295},"django.contrib.auth.hashers.PBKDF2PasswordHasher",[1050,1314,1299],{"class":1291},[1050,1316,1100],{"class":1071},[1050,1318,1319],{"class":1056},"      # Fallback\n",[1050,1321,1323,1325,1328,1330,1332],{"class":1052,"line":1322},22,[1050,1324,1292],{"class":1291},[1050,1326,1327],{"class":1295},"django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher",[1050,1329,1299],{"class":1291},[1050,1331,1100],{"class":1071},[1050,1333,1334],{"class":1056},"  # Legacy\n",[1050,1336,1338,1340,1343,1345,1347],{"class":1052,"line":1337},23,[1050,1339,1292],{"class":1291},[1050,1341,1342],{"class":1295},"django.contrib.auth.hashers.BCryptSHA256PasswordHasher",[1050,1344,1299],{"class":1291},[1050,1346,1100],{"class":1071},[1050,1348,1349],{"class":1056}," # Alternative\n",[1050,1351,1353,1355,1358,1360,1362],{"class":1052,"line":1352},24,[1050,1354,1292],{"class":1291},[1050,1356,1357],{"class":1295},"django.contrib.auth.hashers.ScryptPasswordHasher",[1050,1359,1299],{"class":1291},[1050,1361,1100],{"class":1071},[1050,1363,1364],{"class":1056},"      # Alternative\n",[1050,1366,1368],{"class":1052,"line":1367},25,[1050,1369,1370],{"class":1071},"        ]\n",[1050,1372,1374],{"class":1052,"line":1373},26,[1050,1375,1268],{"class":1067},[1050,1377,1379],{"class":1052,"line":1378},27,[1050,1380,1381],{"class":1056},"        # Custom hasher configuration\n",[1050,1383,1385,1388,1390],{"class":1052,"line":1384},28,[1050,1386,1387],{"class":1067},"        custom_settings ",[1050,1389,1182],{"class":1071},[1050,1391,1392],{"class":1071}," {\n",[1050,1394,1396,1398,1401,1403,1406,1409],{"class":1052,"line":1395},29,[1050,1397,1292],{"class":1291},[1050,1399,1400],{"class":1295},"PASSWORD_HASHERS",[1050,1402,1299],{"class":1291},[1050,1404,1405],{"class":1071},":",[1050,1407,1408],{"class":1067}," password_hashers",[1050,1410,1111],{"class":1071},[1050,1412,1414],{"class":1052,"line":1413},30,[1050,1415,1416],{"class":1067},"            \n",[1050,1418,1420],{"class":1052,"line":1419},31,[1050,1421,1422],{"class":1056},"            # Argon2 configuration\n",[1050,1424,1426,1428,1431,1433,1435,1439,1441],{"class":1052,"line":1425},32,[1050,1427,1292],{"class":1291},[1050,1429,1430],{"class":1295},"ARGON2_TIME_COST",[1050,1432,1299],{"class":1291},[1050,1434,1405],{"class":1071},[1050,1436,1438],{"class":1437},"s7CZa"," 2",[1050,1440,1100],{"class":1071},[1050,1442,1443],{"class":1056},"      # Number of iterations\n",[1050,1445,1447,1449,1452,1454,1456,1459,1461],{"class":1052,"line":1446},33,[1050,1448,1292],{"class":1291},[1050,1450,1451],{"class":1295},"ARGON2_MEMORY_COST",[1050,1453,1299],{"class":1291},[1050,1455,1405],{"class":1071},[1050,1457,1458],{"class":1437}," 512",[1050,1460,1100],{"class":1071},[1050,1462,1463],{"class":1056},"  # Memory usage in KB\n",[1050,1465,1467,1469,1472,1474,1476,1478,1480],{"class":1052,"line":1466},34,[1050,1468,1292],{"class":1291},[1050,1470,1471],{"class":1295},"ARGON2_PARALLELISM",[1050,1473,1299],{"class":1291},[1050,1475,1405],{"class":1071},[1050,1477,1438],{"class":1437},[1050,1479,1100],{"class":1071},[1050,1481,1482],{"class":1056},"    # Number of parallel threads\n",[1050,1484,1486],{"class":1052,"line":1485},35,[1050,1487,1416],{"class":1067},[1050,1489,1491],{"class":1052,"line":1490},36,[1050,1492,1493],{"class":1056},"            # PBKDF2 configuration\n",[1050,1495,1497,1499,1502,1504,1506,1509,1511],{"class":1052,"line":1496},37,[1050,1498,1292],{"class":1291},[1050,1500,1501],{"class":1295},"PBKDF2_ITERATIONS",[1050,1503,1299],{"class":1291},[1050,1505,1405],{"class":1071},[1050,1507,1508],{"class":1437}," 320000",[1050,1510,1100],{"class":1071},[1050,1512,1513],{"class":1056},"  # Number of iterations (Django 4.0+)\n",[1050,1515,1517],{"class":1052,"line":1516},38,[1050,1518,1519],{"class":1071},"        }\n",[1050,1521,1523],{"class":1052,"line":1522},39,[1050,1524,1268],{"class":1067},[1050,1526,1528,1531],{"class":1052,"line":1527},40,[1050,1529,1530],{"class":1063},"        return",[1050,1532,1533],{"class":1067}," custom_settings\n",[1050,1535,1537],{"class":1052,"line":1536},41,[1050,1538,1228],{"class":1067},[1050,1540,1542,1544],{"class":1052,"line":1541},42,[1050,1543,1234],{"class":1071},[1050,1545,1238],{"class":1237},[1050,1547,1549,1551,1554],{"class":1052,"line":1548},43,[1050,1550,1244],{"class":1200},[1050,1552,1553],{"class":1247}," password_hashing_examples",[1050,1555,1251],{"class":1071},[1050,1557,1559,1561,1564],{"class":1052,"line":1558},44,[1050,1560,1257],{"class":1214},[1050,1562,1563],{"class":1218},"Examples of password hashing operations",[1050,1565,1222],{"class":1214},[1050,1567,1569],{"class":1052,"line":1568},45,[1050,1570,1268],{"class":1067},[1050,1572,1574],{"class":1052,"line":1573},46,[1050,1575,1576],{"class":1056},"        # Hash a password\n",[1050,1578,1580,1583,1585,1588,1591],{"class":1052,"line":1579},47,[1050,1581,1582],{"class":1067},"        plain_password ",[1050,1584,1182],{"class":1071},[1050,1586,1587],{"class":1291}," \"",[1050,1589,1590],{"class":1295},"secure_password123",[1050,1592,1593],{"class":1291},"\"\n",[1050,1595,1597,1600,1602,1605,1608,1611],{"class":1052,"line":1596},48,[1050,1598,1599],{"class":1067},"        hashed_password ",[1050,1601,1182],{"class":1071},[1050,1603,1604],{"class":1185}," make_password",[1050,1606,1607],{"class":1071},"(",[1050,1609,1610],{"class":1185},"plain_password",[1050,1612,1128],{"class":1071},[1050,1614,1616],{"class":1052,"line":1615},49,[1050,1617,1268],{"class":1067},[1050,1619,1621,1625,1627,1630,1633,1637,1639,1642,1645],{"class":1052,"line":1620},50,[1050,1622,1624],{"class":1623},"sJdAF","        print",[1050,1626,1607],{"class":1071},[1050,1628,1629],{"class":1200},"f",[1050,1631,1632],{"class":1295},"\"Plain password: ",[1050,1634,1636],{"class":1635},"s3h35","{",[1050,1638,1610],{"class":1185},[1050,1640,1641],{"class":1635},"}",[1050,1643,1644],{"class":1295},"\"",[1050,1646,1128],{"class":1071},[1050,1648,1650,1652,1654,1656,1659,1661,1664,1666,1668],{"class":1052,"line":1649},51,[1050,1651,1624],{"class":1623},[1050,1653,1607],{"class":1071},[1050,1655,1629],{"class":1200},[1050,1657,1658],{"class":1295},"\"Hashed password: ",[1050,1660,1636],{"class":1635},[1050,1662,1663],{"class":1185},"hashed_password",[1050,1665,1641],{"class":1635},[1050,1667,1644],{"class":1295},[1050,1669,1128],{"class":1071},[1050,1671,1673],{"class":1052,"line":1672},52,[1050,1674,1268],{"class":1067},[1050,1676,1678],{"class":1052,"line":1677},53,[1050,1679,1680],{"class":1056},"        # Check password\n",[1050,1682,1684,1687,1689,1691,1693,1695,1697,1700],{"class":1052,"line":1683},54,[1050,1685,1686],{"class":1067},"        is_correct ",[1050,1688,1182],{"class":1071},[1050,1690,1103],{"class":1185},[1050,1692,1607],{"class":1071},[1050,1694,1610],{"class":1185},[1050,1696,1100],{"class":1071},[1050,1698,1699],{"class":1185}," hashed_password",[1050,1701,1128],{"class":1071},[1050,1703,1705,1707,1709,1711,1714,1716,1719,1721,1723],{"class":1052,"line":1704},55,[1050,1706,1624],{"class":1623},[1050,1708,1607],{"class":1071},[1050,1710,1629],{"class":1200},[1050,1712,1713],{"class":1295},"\"Password check: ",[1050,1715,1636],{"class":1635},[1050,1717,1718],{"class":1185},"is_correct",[1050,1720,1641],{"class":1635},[1050,1722,1644],{"class":1295},[1050,1724,1128],{"class":1071},[1050,1726,1728],{"class":1052,"line":1727},56,[1050,1729,1268],{"class":1067},[1050,1731,1733],{"class":1052,"line":1732},57,[1050,1734,1735],{"class":1056},"        # Check if password is usable\n",[1050,1737,1739,1742,1744,1746,1748,1750],{"class":1052,"line":1738},58,[1050,1740,1741],{"class":1067},"        is_usable ",[1050,1743,1182],{"class":1071},[1050,1745,1108],{"class":1185},[1050,1747,1607],{"class":1071},[1050,1749,1663],{"class":1185},[1050,1751,1128],{"class":1071},[1050,1753,1755,1757,1759,1761,1764,1766,1769,1771,1773],{"class":1052,"line":1754},59,[1050,1756,1624],{"class":1623},[1050,1758,1607],{"class":1071},[1050,1760,1629],{"class":1200},[1050,1762,1763],{"class":1295},"\"Password is usable: ",[1050,1765,1636],{"class":1635},[1050,1767,1768],{"class":1185},"is_usable",[1050,1770,1641],{"class":1635},[1050,1772,1644],{"class":1295},[1050,1774,1128],{"class":1071},[1050,1776,1778],{"class":1052,"line":1777},60,[1050,1779,1268],{"class":1067},[1050,1781,1783],{"class":1052,"line":1782},61,[1050,1784,1785],{"class":1056},"        # Get hasher information\n",[1050,1787,1789,1792,1794,1797,1799,1801],{"class":1052,"line":1788},62,[1050,1790,1791],{"class":1067},"        hasher ",[1050,1793,1182],{"class":1071},[1050,1795,1796],{"class":1185}," identify_hasher",[1050,1798,1607],{"class":1071},[1050,1800,1663],{"class":1185},[1050,1802,1128],{"class":1071},[1050,1804,1806,1808,1810,1812,1815,1817,1820,1822,1826,1828,1830],{"class":1052,"line":1805},63,[1050,1807,1624],{"class":1623},[1050,1809,1607],{"class":1071},[1050,1811,1629],{"class":1200},[1050,1813,1814],{"class":1295},"\"Hasher algorithm: ",[1050,1816,1636],{"class":1635},[1050,1818,1819],{"class":1185},"hasher",[1050,1821,1072],{"class":1071},[1050,1823,1825],{"class":1824},"sBPpx","algorithm",[1050,1827,1641],{"class":1635},[1050,1829,1644],{"class":1295},[1050,1831,1128],{"class":1071},[1050,1833,1835],{"class":1052,"line":1834},64,[1050,1836,1268],{"class":1067},[1050,1838,1840,1842],{"class":1052,"line":1839},65,[1050,1841,1530],{"class":1063},[1050,1843,1392],{"class":1071},[1050,1845,1847,1849,1851,1853,1855,1857],{"class":1052,"line":1846},66,[1050,1848,1292],{"class":1291},[1050,1850,1663],{"class":1295},[1050,1852,1299],{"class":1291},[1050,1854,1405],{"class":1071},[1050,1856,1699],{"class":1067},[1050,1858,1111],{"class":1071},[1050,1860,1862,1864,1866,1868,1870,1873],{"class":1052,"line":1861},67,[1050,1863,1292],{"class":1291},[1050,1865,1718],{"class":1295},[1050,1867,1299],{"class":1291},[1050,1869,1405],{"class":1071},[1050,1871,1872],{"class":1067}," is_correct",[1050,1874,1111],{"class":1071},[1050,1876,1878,1880,1882,1884,1886,1889],{"class":1052,"line":1877},68,[1050,1879,1292],{"class":1291},[1050,1881,1768],{"class":1295},[1050,1883,1299],{"class":1291},[1050,1885,1405],{"class":1071},[1050,1887,1888],{"class":1067}," is_usable",[1050,1890,1111],{"class":1071},[1050,1892,1894,1896,1898,1900,1902,1905,1907],{"class":1052,"line":1893},69,[1050,1895,1292],{"class":1291},[1050,1897,1825],{"class":1295},[1050,1899,1299],{"class":1291},[1050,1901,1405],{"class":1071},[1050,1903,1904],{"class":1067}," hasher",[1050,1906,1072],{"class":1071},[1050,1908,1909],{"class":1824},"algorithm\n",[1050,1911,1913],{"class":1052,"line":1912},70,[1050,1914,1519],{"class":1071},[1050,1916,1918],{"class":1052,"line":1917},71,[1050,1919,1228],{"class":1067},[1050,1921,1923,1925],{"class":1052,"line":1922},72,[1050,1924,1234],{"class":1071},[1050,1926,1238],{"class":1237},[1050,1928,1930,1932,1935],{"class":1052,"line":1929},73,[1050,1931,1244],{"class":1200},[1050,1933,1934],{"class":1247}," custom_password_hasher",[1050,1936,1251],{"class":1071},[1050,1938,1940,1942,1945],{"class":1052,"line":1939},74,[1050,1941,1257],{"class":1214},[1050,1943,1944],{"class":1218},"Create a custom password hasher",[1050,1946,1222],{"class":1214},[1050,1948,1950],{"class":1052,"line":1949},75,[1050,1951,1268],{"class":1067},[1050,1953,1955,1958,1960,1962,1964,1966,1968,1970,1972,1974],{"class":1052,"line":1954},76,[1050,1956,1957],{"class":1063},"        from",[1050,1959,1068],{"class":1067},[1050,1961,1072],{"class":1071},[1050,1963,1075],{"class":1067},[1050,1965,1072],{"class":1071},[1050,1967,1080],{"class":1067},[1050,1969,1072],{"class":1071},[1050,1971,1085],{"class":1067},[1050,1973,1088],{"class":1063},[1050,1975,1976],{"class":1067}," BasePasswordHasher\n",[1050,1978,1980,1983],{"class":1052,"line":1979},77,[1050,1981,1982],{"class":1063},"        import",[1050,1984,1985],{"class":1067}," hashlib\n",[1050,1987,1989,1991],{"class":1052,"line":1988},78,[1050,1990,1982],{"class":1063},[1050,1992,1993],{"class":1067}," secrets\n",[1050,1995,1997],{"class":1052,"line":1996},79,[1050,1998,1268],{"class":1067},[1050,2000,2002,2005,2008,2010,2014],{"class":1052,"line":2001},80,[1050,2003,2004],{"class":1200},"        class",[1050,2006,2007],{"class":1204}," CustomSHA256Hasher",[1050,2009,1607],{"class":1071},[1050,2011,2013],{"class":2012},"sYn-s","BasePasswordHasher",[1050,2015,2016],{"class":1071},"):\n",[1050,2018,2020],{"class":1052,"line":2019},81,[1050,2021,2022],{"class":1214},"            \"\"\"\n",[1050,2024,2026],{"class":1052,"line":2025},82,[1050,2027,2028],{"class":1218},"            Custom SHA256-based password hasher\n",[1050,2030,2032],{"class":1052,"line":2031},83,[1050,2033,2034],{"class":1218},"            Note: This is for demonstration - use Django's built-in hashers in production\n",[1050,2036,2038],{"class":1052,"line":2037},84,[1050,2039,2022],{"class":1214},[1050,2041,2043],{"class":1052,"line":2042},85,[1050,2044,1416],{"class":1067},[1050,2046,2048,2051,2053,2055,2058],{"class":1052,"line":2047},86,[1050,2049,2050],{"class":1067},"            algorithm ",[1050,2052,1182],{"class":1071},[1050,2054,1587],{"class":1291},[1050,2056,2057],{"class":1295},"custom_sha256",[1050,2059,1593],{"class":1291},[1050,2061,2063,2066,2068,2070,2073],{"class":1052,"line":2062},87,[1050,2064,2065],{"class":1067},"            library ",[1050,2067,1182],{"class":1071},[1050,2069,1587],{"class":1291},[1050,2071,2072],{"class":1295},"hashlib",[1050,2074,1593],{"class":1291},[1050,2076,2078],{"class":1052,"line":2077},88,[1050,2079,1416],{"class":1067},[1050,2081,2083,2086,2089,2091,2095,2097,2101,2103,2106],{"class":1052,"line":2082},89,[1050,2084,2085],{"class":1200},"            def",[1050,2087,2088],{"class":1247}," encode",[1050,2090,1607],{"class":1071},[1050,2092,2094],{"class":2093},"sRjD_","self",[1050,2096,1100],{"class":1071},[1050,2098,2100],{"class":2099},"sCyAa"," password",[1050,2102,1100],{"class":1071},[1050,2104,2105],{"class":2099}," salt",[1050,2107,2016],{"class":1071},[1050,2109,2111,2114,2117],{"class":1052,"line":2110},90,[1050,2112,2113],{"class":1214},"                \"\"\"",[1050,2115,2116],{"class":1218},"Encode password with salt",[1050,2118,1222],{"class":1214},[1050,2120,2122],{"class":1052,"line":2121},91,[1050,2123,2124],{"class":1067},"                \n",[1050,2126,2128,2131,2135,2137],{"class":1052,"line":2127},92,[1050,2129,2130],{"class":1063},"                if",[1050,2132,2134],{"class":2133},"sVsLi"," not",[1050,2136,2105],{"class":1067},[1050,2138,1208],{"class":1071},[1050,2140,2142,2145,2147,2151,2153,2156],{"class":1052,"line":2141},93,[1050,2143,2144],{"class":1067},"                    salt ",[1050,2146,1182],{"class":1071},[1050,2148,2150],{"class":2149},"se3Ec"," self",[1050,2152,1072],{"class":1071},[1050,2154,2155],{"class":1185},"salt",[1050,2157,1189],{"class":1071},[1050,2159,2161],{"class":1052,"line":2160},94,[1050,2162,2124],{"class":1067},[1050,2164,2166],{"class":1052,"line":2165},95,[1050,2167,2168],{"class":1056},"                # Combine password and salt\n",[1050,2170,2172,2175,2177,2180,2182,2184,2186,2188,2191,2193,2196,2198],{"class":1052,"line":2171},96,[1050,2173,2174],{"class":1067},"                combined ",[1050,2176,1182],{"class":1071},[1050,2178,2179],{"class":1200}," f",[1050,2181,1644],{"class":1295},[1050,2183,1636],{"class":1635},[1050,2185,2155],{"class":1067},[1050,2187,1641],{"class":1635},[1050,2189,2190],{"class":1295},"$",[1050,2192,1636],{"class":1635},[1050,2194,2195],{"class":1067},"password",[1050,2197,1641],{"class":1635},[1050,2199,1593],{"class":1295},[1050,2201,2203],{"class":1052,"line":2202},97,[1050,2204,2124],{"class":1067},[1050,2206,2208],{"class":1052,"line":2207},98,[1050,2209,2210],{"class":1056},"                # Hash multiple times for security\n",[1050,2212,2214,2217,2219,2222,2224,2227,2229,2231,2234,2236],{"class":1052,"line":2213},99,[1050,2215,2216],{"class":1067},"                hash_value ",[1050,2218,1182],{"class":1071},[1050,2220,2221],{"class":1067}," combined",[1050,2223,1072],{"class":1071},[1050,2225,2226],{"class":1185},"encode",[1050,2228,1607],{"class":1071},[1050,2230,1299],{"class":1291},[1050,2232,2233],{"class":1295},"utf-8",[1050,2235,1299],{"class":1291},[1050,2237,1128],{"class":1071},[1050,2239,2241,2244,2247,2250,2253,2255,2258,2261],{"class":1052,"line":2240},100,[1050,2242,2243],{"class":1063},"                for",[1050,2245,2246],{"class":1067}," _ ",[1050,2248,2249],{"class":1063},"in",[1050,2251,2252],{"class":1623}," range",[1050,2254,1607],{"class":1071},[1050,2256,2257],{"class":1437},"10000",[1050,2259,2260],{"class":1071},"):",[1050,2262,2263],{"class":1056},"  # 10,000 iterations\n",[1050,2265,2267,2270,2272,2275,2277,2280,2282,2285,2288,2291],{"class":1052,"line":2266},101,[1050,2268,2269],{"class":1067},"                    hash_value ",[1050,2271,1182],{"class":1071},[1050,2273,2274],{"class":1067}," hashlib",[1050,2276,1072],{"class":1071},[1050,2278,2279],{"class":1185},"sha256",[1050,2281,1607],{"class":1071},[1050,2283,2284],{"class":1185},"hash_value",[1050,2286,2287],{"class":1071},").",[1050,2289,2290],{"class":1185},"digest",[1050,2292,1189],{"class":1071},[1050,2294,2296],{"class":1052,"line":2295},102,[1050,2297,2124],{"class":1067},[1050,2299,2301],{"class":1052,"line":2300},103,[1050,2302,2303],{"class":1056},"                # Convert to hex\n",[1050,2305,2307,2310,2312,2315,2317,2320],{"class":1052,"line":2306},104,[1050,2308,2309],{"class":1067},"                hash_hex ",[1050,2311,1182],{"class":1071},[1050,2313,2314],{"class":1067}," hash_value",[1050,2316,1072],{"class":1071},[1050,2318,2319],{"class":1185},"hex",[1050,2321,1189],{"class":1071},[1050,2323,2325],{"class":1052,"line":2324},105,[1050,2326,2124],{"class":1067},[1050,2328,2330,2333,2335,2337,2339,2341,2343,2345,2347,2349,2351,2353,2355,2357,2359,2362,2364],{"class":1052,"line":2329},106,[1050,2331,2332],{"class":1063},"                return",[1050,2334,2179],{"class":1200},[1050,2336,1644],{"class":1295},[1050,2338,1636],{"class":1635},[1050,2340,2094],{"class":2149},[1050,2342,1072],{"class":1071},[1050,2344,1825],{"class":1824},[1050,2346,1641],{"class":1635},[1050,2348,2190],{"class":1295},[1050,2350,1636],{"class":1635},[1050,2352,2155],{"class":1067},[1050,2354,1641],{"class":1635},[1050,2356,2190],{"class":1295},[1050,2358,1636],{"class":1635},[1050,2360,2361],{"class":1067},"hash_hex",[1050,2363,1641],{"class":1635},[1050,2365,1593],{"class":1295},[1050,2367,2369],{"class":1052,"line":2368},107,[1050,2370,1416],{"class":1067},[1050,2372,2374,2376,2379,2381,2383,2385,2387,2389,2392],{"class":1052,"line":2373},108,[1050,2375,2085],{"class":1200},[1050,2377,2378],{"class":1247}," verify",[1050,2380,1607],{"class":1071},[1050,2382,2094],{"class":2093},[1050,2384,1100],{"class":1071},[1050,2386,2100],{"class":2099},[1050,2388,1100],{"class":1071},[1050,2390,2391],{"class":2099}," encoded",[1050,2393,2016],{"class":1071},[1050,2395,2397,2399,2402],{"class":1052,"line":2396},109,[1050,2398,2113],{"class":1214},[1050,2400,2401],{"class":1218},"Verify password against encoded hash",[1050,2403,1222],{"class":1214},[1050,2405,2407],{"class":1052,"line":2406},110,[1050,2408,2124],{"class":1067},[1050,2410,2412,2415,2417,2419,2421,2424,2426,2428,2430,2433,2435,2437,2439,2441,2443,2445],{"class":1052,"line":2411},111,[1050,2413,2414],{"class":1067},"                algorithm",[1050,2416,1100],{"class":1071},[1050,2418,2105],{"class":1067},[1050,2420,1100],{"class":1071},[1050,2422,2423],{"class":1067}," hash_value ",[1050,2425,1182],{"class":1071},[1050,2427,2391],{"class":1067},[1050,2429,1072],{"class":1071},[1050,2431,2432],{"class":1185},"split",[1050,2434,1607],{"class":1071},[1050,2436,1299],{"class":1291},[1050,2438,2190],{"class":1295},[1050,2440,1299],{"class":1291},[1050,2442,1100],{"class":1071},[1050,2444,1438],{"class":1437},[1050,2446,1128],{"class":1071},[1050,2448,2450],{"class":1052,"line":2449},112,[1050,2451,2124],{"class":1067},[1050,2453,2455],{"class":1052,"line":2454},113,[1050,2456,2457],{"class":1056},"                # Encode the provided password\n",[1050,2459,2461,2464,2466,2468,2470,2472,2474,2476,2478,2480],{"class":1052,"line":2460},114,[1050,2462,2463],{"class":1067},"                encoded_2 ",[1050,2465,1182],{"class":1071},[1050,2467,2150],{"class":2149},[1050,2469,1072],{"class":1071},[1050,2471,2226],{"class":1185},[1050,2473,1607],{"class":1071},[1050,2475,2195],{"class":1185},[1050,2477,1100],{"class":1071},[1050,2479,2105],{"class":1185},[1050,2481,1128],{"class":1071},[1050,2483,2485],{"class":1052,"line":2484},115,[1050,2486,2124],{"class":1067},[1050,2488,2490],{"class":1052,"line":2489},116,[1050,2491,2492],{"class":1056},"                # Compare hashes\n",[1050,2494,2496,2498,2501,2504],{"class":1052,"line":2495},117,[1050,2497,2332],{"class":1063},[1050,2499,2500],{"class":1067}," encoded ",[1050,2502,2503],{"class":2133},"==",[1050,2505,2506],{"class":1067}," encoded_2\n",[1050,2508,2510],{"class":1052,"line":2509},118,[1050,2511,1416],{"class":1067},[1050,2513,2515,2517,2520,2522,2524,2526,2528],{"class":1052,"line":2514},119,[1050,2516,2085],{"class":1200},[1050,2518,2519],{"class":1247}," safe_summary",[1050,2521,1607],{"class":1071},[1050,2523,2094],{"class":2093},[1050,2525,1100],{"class":1071},[1050,2527,2391],{"class":2099},[1050,2529,2016],{"class":1071},[1050,2531,2533,2535,2538],{"class":1052,"line":2532},120,[1050,2534,2113],{"class":1214},[1050,2536,2537],{"class":1218},"Return safe summary of encoded password",[1050,2539,1222],{"class":1214},[1050,2541,2543],{"class":1052,"line":2542},121,[1050,2544,2124],{"class":1067},[1050,2546,2548,2550,2552,2554,2556,2558,2560,2562,2564,2566,2568,2570,2572,2574,2576,2578],{"class":1052,"line":2547},122,[1050,2549,2414],{"class":1067},[1050,2551,1100],{"class":1071},[1050,2553,2105],{"class":1067},[1050,2555,1100],{"class":1071},[1050,2557,2423],{"class":1067},[1050,2559,1182],{"class":1071},[1050,2561,2391],{"class":1067},[1050,2563,1072],{"class":1071},[1050,2565,2432],{"class":1185},[1050,2567,1607],{"class":1071},[1050,2569,1299],{"class":1291},[1050,2571,2190],{"class":1295},[1050,2573,1299],{"class":1291},[1050,2575,1100],{"class":1071},[1050,2577,1438],{"class":1437},[1050,2579,1128],{"class":1071},[1050,2581,2583],{"class":1052,"line":2582},123,[1050,2584,2124],{"class":1067},[1050,2586,2588,2590],{"class":1052,"line":2587},124,[1050,2589,2332],{"class":1063},[1050,2591,1392],{"class":1071},[1050,2593,2595,2598,2600,2602,2604,2607],{"class":1052,"line":2594},125,[1050,2596,2597],{"class":1291},"                    '",[1050,2599,1825],{"class":1295},[1050,2601,1299],{"class":1291},[1050,2603,1405],{"class":1071},[1050,2605,2606],{"class":1067}," algorithm",[1050,2608,1111],{"class":1071},[1050,2610,2612,2614,2616,2618,2620,2622,2625,2628,2631,2634,2637,2640,2642],{"class":1052,"line":2611},126,[1050,2613,2597],{"class":1291},[1050,2615,2155],{"class":1295},[1050,2617,1299],{"class":1291},[1050,2619,1405],{"class":1071},[1050,2621,2105],{"class":1067},[1050,2623,2624],{"class":1071},"[:",[1050,2626,2627],{"class":1437},"6",[1050,2629,2630],{"class":1071},"]",[1050,2632,2633],{"class":2133}," +",[1050,2635,2636],{"class":1291}," '",[1050,2638,2639],{"class":1295},"...",[1050,2641,1299],{"class":1291},[1050,2643,1111],{"class":1071},[1050,2645,2647,2649,2652,2654,2656,2658,2660,2662,2664,2666,2668,2670,2672],{"class":1052,"line":2646},127,[1050,2648,2597],{"class":1291},[1050,2650,2651],{"class":1295},"hash",[1050,2653,1299],{"class":1291},[1050,2655,1405],{"class":1071},[1050,2657,2314],{"class":1067},[1050,2659,2624],{"class":1071},[1050,2661,2627],{"class":1437},[1050,2663,2630],{"class":1071},[1050,2665,2633],{"class":2133},[1050,2667,2636],{"class":1291},[1050,2669,2639],{"class":1295},[1050,2671,1299],{"class":1291},[1050,2673,1111],{"class":1071},[1050,2675,2677],{"class":1052,"line":2676},128,[1050,2678,2679],{"class":1071},"                }\n",[1050,2681,2683],{"class":1052,"line":2682},129,[1050,2684,1416],{"class":1067},[1050,2686,2688,2690,2693,2695,2697,2699,2701,2703,2705],{"class":1052,"line":2687},130,[1050,2689,2085],{"class":1200},[1050,2691,2692],{"class":1247}," harden_runtime",[1050,2694,1607],{"class":1071},[1050,2696,2094],{"class":2093},[1050,2698,1100],{"class":1071},[1050,2700,2100],{"class":2099},[1050,2702,1100],{"class":1071},[1050,2704,2391],{"class":2099},[1050,2706,2016],{"class":1071},[1050,2708,2710,2712,2715],{"class":1052,"line":2709},131,[1050,2711,2113],{"class":1214},[1050,2713,2714],{"class":1218},"Harden against timing attacks",[1050,2716,1222],{"class":1214},[1050,2718,2720],{"class":1052,"line":2719},132,[1050,2721,2722],{"class":1063},"                pass\n",[1050,2724,2726],{"class":1052,"line":2725},133,[1050,2727,1416],{"class":1067},[1050,2729,2731,2733,2736,2738,2740,2742,2744],{"class":1052,"line":2730},134,[1050,2732,2085],{"class":1200},[1050,2734,2735],{"class":1247}," must_update",[1050,2737,1607],{"class":1071},[1050,2739,2094],{"class":2093},[1050,2741,1100],{"class":1071},[1050,2743,2391],{"class":2099},[1050,2745,2016],{"class":1071},[1050,2747,2749,2751,2754],{"class":1052,"line":2748},135,[1050,2750,2113],{"class":1214},[1050,2752,2753],{"class":1218},"Check if password needs to be updated",[1050,2755,1222],{"class":1214},[1050,2757,2759,2761],{"class":1052,"line":2758},136,[1050,2760,2332],{"class":1063},[1050,2762,2764],{"class":2763},"s8XtY"," False\n",[1050,2766,2768],{"class":1052,"line":2767},137,[1050,2769,1268],{"class":1067},[1050,2771,2773,2775],{"class":1052,"line":2772},138,[1050,2774,1530],{"class":1063},[1050,2776,2777],{"class":1067}," CustomSHA256Hasher\n",[1050,2779,2781],{"class":1052,"line":2780},139,[1050,2782,1228],{"class":1067},[1050,2784,2786,2788],{"class":1052,"line":2785},140,[1050,2787,1234],{"class":1071},[1050,2789,1238],{"class":1237},[1050,2791,2793,2795,2798],{"class":1052,"line":2792},141,[1050,2794,1244],{"class":1200},[1050,2796,2797],{"class":1247}," password_upgrade_mechanism",[1050,2799,1251],{"class":1071},[1050,2801,2803,2805,2808],{"class":1052,"line":2802},142,[1050,2804,1257],{"class":1214},[1050,2806,2807],{"class":1218},"Implement password upgrade mechanism",[1050,2809,1222],{"class":1214},[1050,2811,2813],{"class":1052,"line":2812},143,[1050,2814,1268],{"class":1067},[1050,2816,2818,2821,2824,2826,2829,2831,2834],{"class":1052,"line":2817},144,[1050,2819,2820],{"class":1200},"        def",[1050,2822,2823],{"class":1247}," upgrade_user_password",[1050,2825,1607],{"class":1071},[1050,2827,2828],{"class":2099},"user",[1050,2830,1100],{"class":1071},[1050,2832,2833],{"class":2099}," raw_password",[1050,2835,2016],{"class":1071},[1050,2837,2839,2842,2845],{"class":1052,"line":2838},145,[1050,2840,2841],{"class":1214},"            \"\"\"",[1050,2843,2844],{"class":1218},"Upgrade user's password hash if needed",[1050,2846,1222],{"class":1214},[1050,2848,2850],{"class":1052,"line":2849},146,[1050,2851,1416],{"class":1067},[1050,2853,2855],{"class":1052,"line":2854},147,[1050,2856,2857],{"class":1056},"            # Check if password needs upgrading\n",[1050,2859,2861,2864,2867,2869,2871],{"class":1052,"line":2860},148,[1050,2862,2863],{"class":1063},"            if",[1050,2865,2866],{"class":1067}," user",[1050,2868,1072],{"class":1071},[1050,2870,2195],{"class":1824},[1050,2872,1208],{"class":1071},[1050,2874,2876,2879,2881,2883,2885,2887,2889,2891],{"class":1052,"line":2875},149,[1050,2877,2878],{"class":1067},"                hasher ",[1050,2880,1182],{"class":1071},[1050,2882,1796],{"class":1185},[1050,2884,1607],{"class":1071},[1050,2886,2828],{"class":1185},[1050,2888,1072],{"class":1071},[1050,2890,2195],{"class":1824},[1050,2892,1128],{"class":1071},[1050,2894,2896],{"class":1052,"line":2895},150,[1050,2897,2124],{"class":1067},[1050,2899,2901],{"class":1052,"line":2900},151,[1050,2902,2903],{"class":1056},"                # Check if we're using the preferred hasher\n",[1050,2905,2907,2910,2912,2915],{"class":1052,"line":2906},152,[1050,2908,2909],{"class":1067},"                preferred_hasher ",[1050,2911,1182],{"class":1071},[1050,2913,2914],{"class":1185}," get_hasher",[1050,2916,1189],{"class":1071},[1050,2918,2920],{"class":1052,"line":2919},153,[1050,2921,2124],{"class":1067},[1050,2923,2925,2927,2929,2931,2933,2936,2939,2941,2943],{"class":1052,"line":2924},154,[1050,2926,2130],{"class":1063},[1050,2928,1904],{"class":1067},[1050,2930,1072],{"class":1071},[1050,2932,1825],{"class":1824},[1050,2934,2935],{"class":2133}," !=",[1050,2937,2938],{"class":1067}," preferred_hasher",[1050,2940,1072],{"class":1071},[1050,2942,1825],{"class":1824},[1050,2944,1208],{"class":1071},[1050,2946,2948],{"class":1052,"line":2947},155,[1050,2949,2950],{"class":1056},"                    # Upgrade to preferred hasher\n",[1050,2952,2954,2957,2959,2962,2964,2967],{"class":1052,"line":2953},156,[1050,2955,2956],{"class":1067},"                    user",[1050,2958,1072],{"class":1071},[1050,2960,2961],{"class":1185},"set_password",[1050,2963,1607],{"class":1071},[1050,2965,2966],{"class":1185},"raw_password",[1050,2968,1128],{"class":1071},[1050,2970,2972,2974,2976,2979,2981,2985,2988,2990,2992,2994],{"class":1052,"line":2971},157,[1050,2973,2956],{"class":1067},[1050,2975,1072],{"class":1071},[1050,2977,2978],{"class":1185},"save",[1050,2980,1607],{"class":1071},[1050,2982,2984],{"class":2983},"sqOPj","update_fields",[1050,2986,2987],{"class":1071},"=[",[1050,2989,1299],{"class":1291},[1050,2991,2195],{"class":1295},[1050,2993,1299],{"class":1291},[1050,2995,2996],{"class":1071},"])\n",[1050,2998,3000],{"class":1052,"line":2999},158,[1050,3001,3002],{"class":1067},"                    \n",[1050,3004,3006,3009,3012,3014,3016,3019,3021,3023,3025,3027,3029,3032,3034,3037,3039,3041,3043],{"class":1052,"line":3005},159,[1050,3007,3008],{"class":1063},"                    return",[1050,3010,3011],{"class":2763}," True",[1050,3013,1100],{"class":1071},[1050,3015,2179],{"class":1200},[1050,3017,3018],{"class":1295},"\"Upgraded from ",[1050,3020,1636],{"class":1635},[1050,3022,1819],{"class":1067},[1050,3024,1072],{"class":1071},[1050,3026,1825],{"class":1824},[1050,3028,1641],{"class":1635},[1050,3030,3031],{"class":1295}," to ",[1050,3033,1636],{"class":1635},[1050,3035,3036],{"class":1067},"preferred_hasher",[1050,3038,1072],{"class":1071},[1050,3040,1825],{"class":1824},[1050,3042,1641],{"class":1635},[1050,3044,1593],{"class":1295},[1050,3046,3048],{"class":1052,"line":3047},160,[1050,3049,2124],{"class":1067},[1050,3051,3053],{"class":1052,"line":3052},161,[1050,3054,3055],{"class":1056},"                # Check if hasher parameters need updating\n",[1050,3057,3059,3062,3064,3066,3069,3071,3073,3075,3077],{"class":1052,"line":3058},162,[1050,3060,3061],{"class":1063},"                elif",[1050,3063,1904],{"class":1067},[1050,3065,1072],{"class":1071},[1050,3067,3068],{"class":1185},"must_update",[1050,3070,1607],{"class":1071},[1050,3072,2828],{"class":1185},[1050,3074,1072],{"class":1071},[1050,3076,2195],{"class":1824},[1050,3078,2016],{"class":1071},[1050,3080,3082,3084,3086,3088,3090,3092],{"class":1052,"line":3081},163,[1050,3083,2956],{"class":1067},[1050,3085,1072],{"class":1071},[1050,3087,2961],{"class":1185},[1050,3089,1607],{"class":1071},[1050,3091,2966],{"class":1185},[1050,3093,1128],{"class":1071},[1050,3095,3097,3099,3101,3103,3105,3107,3109,3111,3113,3115],{"class":1052,"line":3096},164,[1050,3098,2956],{"class":1067},[1050,3100,1072],{"class":1071},[1050,3102,2978],{"class":1185},[1050,3104,1607],{"class":1071},[1050,3106,2984],{"class":2983},[1050,3108,2987],{"class":1071},[1050,3110,1299],{"class":1291},[1050,3112,2195],{"class":1295},[1050,3114,1299],{"class":1291},[1050,3116,2996],{"class":1071},[1050,3118,3120],{"class":1052,"line":3119},165,[1050,3121,3002],{"class":1067},[1050,3123,3125,3127,3129,3131,3133,3136,3138,3140,3142,3144,3146],{"class":1052,"line":3124},166,[1050,3126,3008],{"class":1063},[1050,3128,3011],{"class":2763},[1050,3130,1100],{"class":1071},[1050,3132,2179],{"class":1200},[1050,3134,3135],{"class":1295},"\"Updated ",[1050,3137,1636],{"class":1635},[1050,3139,1819],{"class":1067},[1050,3141,1072],{"class":1071},[1050,3143,1825],{"class":1824},[1050,3145,1641],{"class":1635},[1050,3147,3148],{"class":1295}," parameters\"\n",[1050,3150,3152],{"class":1052,"line":3151},167,[1050,3153,1416],{"class":1067},[1050,3155,3157,3160,3163,3165,3167,3170],{"class":1052,"line":3156},168,[1050,3158,3159],{"class":1063},"            return",[1050,3161,3162],{"class":2763}," False",[1050,3164,1100],{"class":1071},[1050,3166,1587],{"class":1291},[1050,3168,3169],{"class":1295},"No upgrade needed",[1050,3171,1593],{"class":1291},[1050,3173,3175],{"class":1052,"line":3174},169,[1050,3176,1268],{"class":1067},[1050,3178,3180,3182,3185],{"class":1052,"line":3179},170,[1050,3181,2820],{"class":1200},[1050,3183,3184],{"class":1247}," bulk_password_upgrade",[1050,3186,1251],{"class":1071},[1050,3188,3190,3192,3195],{"class":1052,"line":3189},171,[1050,3191,2841],{"class":1214},[1050,3193,3194],{"class":1218},"Upgrade passwords for all users (run during maintenance)",[1050,3196,1222],{"class":1214},[1050,3198,3200],{"class":1052,"line":3199},172,[1050,3201,1416],{"class":1067},[1050,3203,3205,3208,3210],{"class":1052,"line":3204},173,[1050,3206,3207],{"class":1067},"            upgraded_count ",[1050,3209,1182],{"class":1071},[1050,3211,3212],{"class":1437}," 0\n",[1050,3214,3216],{"class":1052,"line":3215},174,[1050,3217,1416],{"class":1067},[1050,3219,3221],{"class":1052,"line":3220},175,[1050,3222,3223],{"class":1056},"            # This would typically be done when users log in\n",[1050,3225,3227],{"class":1052,"line":3226},176,[1050,3228,3229],{"class":1056},"            # Here's how you might do a bulk upgrade if you have access to plain passwords\n",[1050,3231,3233],{"class":1052,"line":3232},177,[1050,3234,1416],{"class":1067},[1050,3236,3238,3241,3244,3246,3249,3251,3254,3256,3259],{"class":1052,"line":3237},178,[1050,3239,3240],{"class":1063},"            for",[1050,3242,3243],{"class":1067}," user ",[1050,3245,2249],{"class":1063},[1050,3247,3248],{"class":1067}," User",[1050,3250,1072],{"class":1071},[1050,3252,3253],{"class":1824},"objects",[1050,3255,1072],{"class":1071},[1050,3257,3258],{"class":1185},"all",[1050,3260,1251],{"class":1071},[1050,3262,3264,3266,3268,3270,3272],{"class":1052,"line":3263},179,[1050,3265,2130],{"class":1063},[1050,3267,2866],{"class":1067},[1050,3269,1072],{"class":1071},[1050,3271,2195],{"class":1824},[1050,3273,1208],{"class":1071},[1050,3275,3277,3280,3282,3284,3286,3288,3290,3292],{"class":1052,"line":3276},180,[1050,3278,3279],{"class":1067},"                    hasher ",[1050,3281,1182],{"class":1071},[1050,3283,1796],{"class":1185},[1050,3285,1607],{"class":1071},[1050,3287,2828],{"class":1185},[1050,3289,1072],{"class":1071},[1050,3291,2195],{"class":1824},[1050,3293,1128],{"class":1071},[1050,3295,3297,3300,3302,3304],{"class":1052,"line":3296},181,[1050,3298,3299],{"class":1067},"                    preferred_hasher ",[1050,3301,1182],{"class":1071},[1050,3303,2914],{"class":1185},[1050,3305,1189],{"class":1071},[1050,3307,3309],{"class":1052,"line":3308},182,[1050,3310,3002],{"class":1067},[1050,3312,3314,3317,3319,3321,3323,3325,3327,3329,3331],{"class":1052,"line":3313},183,[1050,3315,3316],{"class":1063},"                    if",[1050,3318,1904],{"class":1067},[1050,3320,1072],{"class":1071},[1050,3322,1825],{"class":1824},[1050,3324,2935],{"class":2133},[1050,3326,2938],{"class":1067},[1050,3328,1072],{"class":1071},[1050,3330,1825],{"class":1824},[1050,3332,1208],{"class":1071},[1050,3334,3336],{"class":1052,"line":3335},184,[1050,3337,3338],{"class":1056},"                        # In practice, you can't upgrade without the plain password\n",[1050,3340,3342],{"class":1052,"line":3341},185,[1050,3343,3344],{"class":1056},"                        # This would be done during login when you have access to it\n",[1050,3346,3348,3351,3353,3355,3358,3360,3362,3364,3367,3369,3372],{"class":1052,"line":3347},186,[1050,3349,3350],{"class":1623},"                        print",[1050,3352,1607],{"class":1071},[1050,3354,1629],{"class":1200},[1050,3356,3357],{"class":1295},"\"User ",[1050,3359,1636],{"class":1635},[1050,3361,2828],{"class":1185},[1050,3363,1072],{"class":1071},[1050,3365,3366],{"class":1824},"username",[1050,3368,1641],{"class":1635},[1050,3370,3371],{"class":1295}," needs password upgrade\"",[1050,3373,1128],{"class":1071},[1050,3375,3377,3380,3383],{"class":1052,"line":3376},187,[1050,3378,3379],{"class":1067},"                        upgraded_count ",[1050,3381,3382],{"class":1071},"+=",[1050,3384,3385],{"class":1437}," 1\n",[1050,3387,3389],{"class":1052,"line":3388},188,[1050,3390,1416],{"class":1067},[1050,3392,3394,3396],{"class":1052,"line":3393},189,[1050,3395,3159],{"class":1063},[1050,3397,3398],{"class":1067}," upgraded_count\n",[1050,3400,3402],{"class":1052,"line":3401},190,[1050,3403,1268],{"class":1067},[1050,3405,3407,3409,3411,3413],{"class":1052,"line":3406},191,[1050,3408,1530],{"class":1063},[1050,3410,2823],{"class":1067},[1050,3412,1100],{"class":1071},[1050,3414,3415],{"class":1067}," bulk_password_upgrade\n",[1050,3417,3419],{"class":1052,"line":3418},192,[1050,3420,1173],{"emptyLinePlaceholder":1172},[1050,3422,3424],{"class":1052,"line":3423},193,[1050,3425,3426],{"class":1056},"# Password validation\n",[1050,3428,3430,3432,3435],{"class":1052,"line":3429},194,[1050,3431,1201],{"class":1200},[1050,3433,3434],{"class":1204}," PasswordValidation",[1050,3436,1208],{"class":1071},[1050,3438,3440,3442,3445],{"class":1052,"line":3439},195,[1050,3441,1215],{"class":1214},[1050,3443,3444],{"class":1218},"Implement comprehensive password validation",[1050,3446,1222],{"class":1214},[1050,3448,3450],{"class":1052,"line":3449},196,[1050,3451,1228],{"class":1067},[1050,3453,3455,3457],{"class":1052,"line":3454},197,[1050,3456,1234],{"class":1071},[1050,3458,1238],{"class":1237},[1050,3460,3462,3464,3467],{"class":1052,"line":3461},198,[1050,3463,1244],{"class":1200},[1050,3465,3466],{"class":1247}," django_password_validators",[1050,3468,1251],{"class":1071},[1050,3470,3472,3474,3477],{"class":1052,"line":3471},199,[1050,3473,1257],{"class":1214},[1050,3475,3476],{"class":1218},"Configure Django's built-in password validators",[1050,3478,1222],{"class":1214},[1050,3480,3482],{"class":1052,"line":3481},200,[1050,3483,1268],{"class":1067},[1050,3485,3487,3490,3492],{"class":1052,"line":3486},201,[1050,3488,3489],{"class":1067},"        password_validators ",[1050,3491,1182],{"class":1071},[1050,3493,1285],{"class":1071},[1050,3495,3497],{"class":1052,"line":3496},202,[1050,3498,3499],{"class":1071},"            {\n",[1050,3501,3503,3506,3509,3511,3513,3515,3518,3520],{"class":1052,"line":3502},203,[1050,3504,3505],{"class":1291},"                '",[1050,3507,3508],{"class":1295},"NAME",[1050,3510,1299],{"class":1291},[1050,3512,1405],{"class":1071},[1050,3514,2636],{"class":1291},[1050,3516,3517],{"class":1295},"django.contrib.auth.password_validation.UserAttributeSimilarityValidator",[1050,3519,1299],{"class":1291},[1050,3521,1111],{"class":1071},[1050,3523,3525,3527,3530,3532,3534],{"class":1052,"line":3524},204,[1050,3526,3505],{"class":1291},[1050,3528,3529],{"class":1295},"OPTIONS",[1050,3531,1299],{"class":1291},[1050,3533,1405],{"class":1071},[1050,3535,1392],{"class":1071},[1050,3537,3539,3541,3544,3546,3548,3551,3553,3555,3557,3559,3561,3564,3566,3568,3570,3573,3575,3577,3579,3582,3584],{"class":1052,"line":3538},205,[1050,3540,2597],{"class":1291},[1050,3542,3543],{"class":1295},"user_attributes",[1050,3545,1299],{"class":1291},[1050,3547,1405],{"class":1071},[1050,3549,3550],{"class":1071}," (",[1050,3552,1299],{"class":1291},[1050,3554,3366],{"class":1295},[1050,3556,1299],{"class":1291},[1050,3558,1100],{"class":1071},[1050,3560,2636],{"class":1291},[1050,3562,3563],{"class":1295},"first_name",[1050,3565,1299],{"class":1291},[1050,3567,1100],{"class":1071},[1050,3569,2636],{"class":1291},[1050,3571,3572],{"class":1295},"last_name",[1050,3574,1299],{"class":1291},[1050,3576,1100],{"class":1071},[1050,3578,2636],{"class":1291},[1050,3580,3581],{"class":1295},"email",[1050,3583,1299],{"class":1291},[1050,3585,3586],{"class":1071},"),\n",[1050,3588,3590,3592,3595,3597,3599,3602],{"class":1052,"line":3589},206,[1050,3591,2597],{"class":1291},[1050,3593,3594],{"class":1295},"max_similarity",[1050,3596,1299],{"class":1291},[1050,3598,1405],{"class":1071},[1050,3600,3601],{"class":1437}," 0.7",[1050,3603,1111],{"class":1071},[1050,3605,3607],{"class":1052,"line":3606},207,[1050,3608,2679],{"class":1071},[1050,3610,3612],{"class":1052,"line":3611},208,[1050,3613,3614],{"class":1071},"            },\n",[1050,3616,3618],{"class":1052,"line":3617},209,[1050,3619,3499],{"class":1071},[1050,3621,3623,3625,3627,3629,3631,3633,3636,3638],{"class":1052,"line":3622},210,[1050,3624,3505],{"class":1291},[1050,3626,3508],{"class":1295},[1050,3628,1299],{"class":1291},[1050,3630,1405],{"class":1071},[1050,3632,2636],{"class":1291},[1050,3634,3635],{"class":1295},"django.contrib.auth.password_validation.MinimumLengthValidator",[1050,3637,1299],{"class":1291},[1050,3639,1111],{"class":1071},[1050,3641,3643,3645,3647,3649,3651],{"class":1052,"line":3642},211,[1050,3644,3505],{"class":1291},[1050,3646,3529],{"class":1295},[1050,3648,1299],{"class":1291},[1050,3650,1405],{"class":1071},[1050,3652,1392],{"class":1071},[1050,3654,3656,3658,3661,3663,3665,3668],{"class":1052,"line":3655},212,[1050,3657,2597],{"class":1291},[1050,3659,3660],{"class":1295},"min_length",[1050,3662,1299],{"class":1291},[1050,3664,1405],{"class":1071},[1050,3666,3667],{"class":1437}," 12",[1050,3669,1111],{"class":1071},[1050,3671,3673],{"class":1052,"line":3672},213,[1050,3674,2679],{"class":1071},[1050,3676,3678],{"class":1052,"line":3677},214,[1050,3679,3614],{"class":1071},[1050,3681,3683],{"class":1052,"line":3682},215,[1050,3684,3499],{"class":1071},[1050,3686,3688,3690,3692,3694,3696,3698,3701,3703],{"class":1052,"line":3687},216,[1050,3689,3505],{"class":1291},[1050,3691,3508],{"class":1295},[1050,3693,1299],{"class":1291},[1050,3695,1405],{"class":1071},[1050,3697,2636],{"class":1291},[1050,3699,3700],{"class":1295},"django.contrib.auth.password_validation.CommonPasswordValidator",[1050,3702,1299],{"class":1291},[1050,3704,1111],{"class":1071},[1050,3706,3708],{"class":1052,"line":3707},217,[1050,3709,3614],{"class":1071},[1050,3711,3713],{"class":1052,"line":3712},218,[1050,3714,3499],{"class":1071},[1050,3716,3718,3720,3722,3724,3726,3728,3731,3733],{"class":1052,"line":3717},219,[1050,3719,3505],{"class":1291},[1050,3721,3508],{"class":1295},[1050,3723,1299],{"class":1291},[1050,3725,1405],{"class":1071},[1050,3727,2636],{"class":1291},[1050,3729,3730],{"class":1295},"django.contrib.auth.password_validation.NumericPasswordValidator",[1050,3732,1299],{"class":1291},[1050,3734,1111],{"class":1071},[1050,3736,3738],{"class":1052,"line":3737},220,[1050,3739,3614],{"class":1071},[1050,3741,3743],{"class":1052,"line":3742},221,[1050,3744,1370],{"class":1071},[1050,3746,3748],{"class":1052,"line":3747},222,[1050,3749,1268],{"class":1067},[1050,3751,3753,3755],{"class":1052,"line":3752},223,[1050,3754,1530],{"class":1063},[1050,3756,3757],{"class":1067}," password_validators\n",[1050,3759,3761],{"class":1052,"line":3760},224,[1050,3762,1228],{"class":1067},[1050,3764,3766,3768],{"class":1052,"line":3765},225,[1050,3767,1234],{"class":1071},[1050,3769,1238],{"class":1237},[1050,3771,3773,3775,3778],{"class":1052,"line":3772},226,[1050,3774,1244],{"class":1200},[1050,3776,3777],{"class":1247}," custom_password_validators",[1050,3779,1251],{"class":1071},[1050,3781,3783,3785,3788],{"class":1052,"line":3782},227,[1050,3784,1257],{"class":1214},[1050,3786,3787],{"class":1218},"Create custom password validators",[1050,3789,1222],{"class":1214},[1050,3791,3793],{"class":1052,"line":3792},228,[1050,3794,1268],{"class":1067},[1050,3796,3798,3800,3802,3804,3806,3808,3810,3812,3815,3817],{"class":1052,"line":3797},229,[1050,3799,1957],{"class":1063},[1050,3801,1068],{"class":1067},[1050,3803,1072],{"class":1071},[1050,3805,1075],{"class":1067},[1050,3807,1072],{"class":1071},[1050,3809,1080],{"class":1067},[1050,3811,1072],{"class":1071},[1050,3813,3814],{"class":1067},"password_validation ",[1050,3816,1088],{"class":1063},[1050,3818,3819],{"class":1067}," CommonPasswordValidator\n",[1050,3821,3823,3825,3827,3829,3832,3834,3837,3839],{"class":1052,"line":3822},230,[1050,3824,1957],{"class":1063},[1050,3826,1068],{"class":1067},[1050,3828,1072],{"class":1071},[1050,3830,3831],{"class":1067},"core",[1050,3833,1072],{"class":1071},[1050,3835,3836],{"class":1067},"exceptions ",[1050,3838,1088],{"class":1063},[1050,3840,3841],{"class":1067}," ValidationError\n",[1050,3843,3845,3847],{"class":1052,"line":3844},231,[1050,3846,1982],{"class":1063},[1050,3848,3849],{"class":1067}," re\n",[1050,3851,3853],{"class":1052,"line":3852},232,[1050,3854,1268],{"class":1067},[1050,3856,3858,3860,3863],{"class":1052,"line":3857},233,[1050,3859,2004],{"class":1200},[1050,3861,3862],{"class":1204}," ComplexityValidator",[1050,3864,1208],{"class":1071},[1050,3866,3868,3870,3873],{"class":1052,"line":3867},234,[1050,3869,2841],{"class":1214},[1050,3871,3872],{"class":1218},"Validate password complexity requirements",[1050,3874,1222],{"class":1214},[1050,3876,3878],{"class":1052,"line":3877},235,[1050,3879,1416],{"class":1067},[1050,3881,3883,3885,3888,3890,3892,3894,3897,3899,3902,3904,3907,3909,3911,3913,3916,3918,3920,3922,3925,3927,3929],{"class":1052,"line":3882},236,[1050,3884,2085],{"class":1200},[1050,3886,3887],{"class":1623}," __init__",[1050,3889,1607],{"class":1071},[1050,3891,2094],{"class":2093},[1050,3893,1100],{"class":1071},[1050,3895,3896],{"class":2099}," min_uppercase",[1050,3898,1182],{"class":2133},[1050,3900,3901],{"class":1437},"1",[1050,3903,1100],{"class":1071},[1050,3905,3906],{"class":2099}," min_lowercase",[1050,3908,1182],{"class":2133},[1050,3910,3901],{"class":1437},[1050,3912,1100],{"class":1071},[1050,3914,3915],{"class":2099}," min_digits",[1050,3917,1182],{"class":2133},[1050,3919,3901],{"class":1437},[1050,3921,1100],{"class":1071},[1050,3923,3924],{"class":2099}," min_special",[1050,3926,1182],{"class":2133},[1050,3928,3901],{"class":1437},[1050,3930,2016],{"class":1071},[1050,3932,3934,3937,3939,3942,3945],{"class":1052,"line":3933},237,[1050,3935,3936],{"class":2149},"                self",[1050,3938,1072],{"class":1071},[1050,3940,3941],{"class":1824},"min_uppercase",[1050,3943,3944],{"class":1071}," =",[1050,3946,3947],{"class":1067}," min_uppercase\n",[1050,3949,3951,3953,3955,3958,3960],{"class":1052,"line":3950},238,[1050,3952,3936],{"class":2149},[1050,3954,1072],{"class":1071},[1050,3956,3957],{"class":1824},"min_lowercase",[1050,3959,3944],{"class":1071},[1050,3961,3962],{"class":1067}," min_lowercase\n",[1050,3964,3966,3968,3970,3973,3975],{"class":1052,"line":3965},239,[1050,3967,3936],{"class":2149},[1050,3969,1072],{"class":1071},[1050,3971,3972],{"class":1824},"min_digits",[1050,3974,3944],{"class":1071},[1050,3976,3977],{"class":1067}," min_digits\n",[1050,3979,3981,3983,3985,3988,3990],{"class":1052,"line":3980},240,[1050,3982,3936],{"class":2149},[1050,3984,1072],{"class":1071},[1050,3986,3987],{"class":1824},"min_special",[1050,3989,3944],{"class":1071},[1050,3991,3992],{"class":1067}," min_special\n",[1050,3994,3996],{"class":1052,"line":3995},241,[1050,3997,1416],{"class":1067},[1050,3999,4001,4003,4006,4008,4010,4012,4014,4016,4018,4020,4023],{"class":1052,"line":4000},242,[1050,4002,2085],{"class":1200},[1050,4004,4005],{"class":1247}," validate",[1050,4007,1607],{"class":1071},[1050,4009,2094],{"class":2093},[1050,4011,1100],{"class":1071},[1050,4013,2100],{"class":2099},[1050,4015,1100],{"class":1071},[1050,4017,2866],{"class":2099},[1050,4019,1182],{"class":2133},[1050,4021,4022],{"class":2763},"None",[1050,4024,2016],{"class":1071},[1050,4026,4028,4030,4033],{"class":1052,"line":4027},243,[1050,4029,2113],{"class":1214},[1050,4031,4032],{"class":1218},"Validate password complexity",[1050,4034,1222],{"class":1214},[1050,4036,4038],{"class":1052,"line":4037},244,[1050,4039,2124],{"class":1067},[1050,4041,4043,4046,4048],{"class":1052,"line":4042},245,[1050,4044,4045],{"class":1067},"                errors ",[1050,4047,1182],{"class":1071},[1050,4049,4050],{"class":1071}," []\n",[1050,4052,4054],{"class":1052,"line":4053},246,[1050,4055,2124],{"class":1067},[1050,4057,4059],{"class":1052,"line":4058},247,[1050,4060,4061],{"class":1056},"                # Check uppercase letters\n",[1050,4063,4065,4068,4070,4073,4075,4078,4080,4083,4085,4088,4090,4094,4098,4100,4102,4104,4106],{"class":1052,"line":4064},248,[1050,4066,4067],{"class":1067},"                uppercase_count ",[1050,4069,1182],{"class":1071},[1050,4071,4072],{"class":1623}," len",[1050,4074,1607],{"class":1071},[1050,4076,4077],{"class":1185},"re",[1050,4079,1072],{"class":1071},[1050,4081,4082],{"class":1185},"findall",[1050,4084,1607],{"class":1071},[1050,4086,4087],{"class":1200},"r",[1050,4089,1299],{"class":1291},[1050,4091,4093],{"class":4092},"sETVe","[",[1050,4095,4097],{"class":4096},"sz9Cv","A-Z",[1050,4099,2630],{"class":4092},[1050,4101,1299],{"class":1291},[1050,4103,1100],{"class":1071},[1050,4105,2100],{"class":1185},[1050,4107,4108],{"class":1071},"))\n",[1050,4110,4112,4114,4117,4120,4122,4124,4126],{"class":1052,"line":4111},249,[1050,4113,2130],{"class":1063},[1050,4115,4116],{"class":1067}," uppercase_count ",[1050,4118,4119],{"class":2133},"\u003C",[1050,4121,2150],{"class":2149},[1050,4123,1072],{"class":1071},[1050,4125,3941],{"class":1824},[1050,4127,1208],{"class":1071},[1050,4129,4131,4134,4136,4139],{"class":1052,"line":4130},250,[1050,4132,4133],{"class":1067},"                    errors",[1050,4135,1072],{"class":1071},[1050,4137,4138],{"class":1185},"append",[1050,4140,4141],{"class":1071},"(\n",[1050,4143,4145,4148,4151,4153,4155,4157,4159,4161],{"class":1052,"line":4144},251,[1050,4146,4147],{"class":1200},"                        f",[1050,4149,4150],{"class":1295},"\"Password must contain at least ",[1050,4152,1636],{"class":1635},[1050,4154,2094],{"class":2149},[1050,4156,1072],{"class":1071},[1050,4158,3941],{"class":1824},[1050,4160,1641],{"class":1635},[1050,4162,4163],{"class":1295}," uppercase letter(s).\"\n",[1050,4165,4167],{"class":1052,"line":4166},252,[1050,4168,4169],{"class":1071},"                    )\n",[1050,4171,4173],{"class":1052,"line":4172},253,[1050,4174,2124],{"class":1067},[1050,4176,4178],{"class":1052,"line":4177},254,[1050,4179,4180],{"class":1056},"                # Check lowercase letters\n",[1050,4182,4184,4187,4189,4191,4193,4195,4197,4199,4201,4203,4205,4207,4210,4212,4214,4216,4218],{"class":1052,"line":4183},255,[1050,4185,4186],{"class":1067},"                lowercase_count ",[1050,4188,1182],{"class":1071},[1050,4190,4072],{"class":1623},[1050,4192,1607],{"class":1071},[1050,4194,4077],{"class":1185},[1050,4196,1072],{"class":1071},[1050,4198,4082],{"class":1185},[1050,4200,1607],{"class":1071},[1050,4202,4087],{"class":1200},[1050,4204,1299],{"class":1291},[1050,4206,4093],{"class":4092},[1050,4208,4209],{"class":4096},"a-z",[1050,4211,2630],{"class":4092},[1050,4213,1299],{"class":1291},[1050,4215,1100],{"class":1071},[1050,4217,2100],{"class":1185},[1050,4219,4108],{"class":1071},[1050,4221,4223,4225,4228,4230,4232,4234,4236],{"class":1052,"line":4222},256,[1050,4224,2130],{"class":1063},[1050,4226,4227],{"class":1067}," lowercase_count ",[1050,4229,4119],{"class":2133},[1050,4231,2150],{"class":2149},[1050,4233,1072],{"class":1071},[1050,4235,3957],{"class":1824},[1050,4237,1208],{"class":1071},[1050,4239,4241,4243,4245,4247],{"class":1052,"line":4240},257,[1050,4242,4133],{"class":1067},[1050,4244,1072],{"class":1071},[1050,4246,4138],{"class":1185},[1050,4248,4141],{"class":1071},[1050,4250,4252,4254,4256,4258,4260,4262,4264,4266],{"class":1052,"line":4251},258,[1050,4253,4147],{"class":1200},[1050,4255,4150],{"class":1295},[1050,4257,1636],{"class":1635},[1050,4259,2094],{"class":2149},[1050,4261,1072],{"class":1071},[1050,4263,3957],{"class":1824},[1050,4265,1641],{"class":1635},[1050,4267,4268],{"class":1295}," lowercase letter(s).\"\n",[1050,4270,4272],{"class":1052,"line":4271},259,[1050,4273,4169],{"class":1071},[1050,4275,4277],{"class":1052,"line":4276},260,[1050,4278,2124],{"class":1067},[1050,4280,4282],{"class":1052,"line":4281},261,[1050,4283,4284],{"class":1056},"                # Check digits\n",[1050,4286,4288,4291,4293,4295,4297,4299,4301,4303,4305,4307,4309,4313,4315,4317,4319],{"class":1052,"line":4287},262,[1050,4289,4290],{"class":1067},"                digit_count ",[1050,4292,1182],{"class":1071},[1050,4294,4072],{"class":1623},[1050,4296,1607],{"class":1071},[1050,4298,4077],{"class":1185},[1050,4300,1072],{"class":1071},[1050,4302,4082],{"class":1185},[1050,4304,1607],{"class":1071},[1050,4306,4087],{"class":1200},[1050,4308,1299],{"class":1291},[1050,4310,4312],{"class":4311},"sRJPX","\\d",[1050,4314,1299],{"class":1291},[1050,4316,1100],{"class":1071},[1050,4318,2100],{"class":1185},[1050,4320,4108],{"class":1071},[1050,4322,4324,4326,4329,4331,4333,4335,4337],{"class":1052,"line":4323},263,[1050,4325,2130],{"class":1063},[1050,4327,4328],{"class":1067}," digit_count ",[1050,4330,4119],{"class":2133},[1050,4332,2150],{"class":2149},[1050,4334,1072],{"class":1071},[1050,4336,3972],{"class":1824},[1050,4338,1208],{"class":1071},[1050,4340,4342,4344,4346,4348],{"class":1052,"line":4341},264,[1050,4343,4133],{"class":1067},[1050,4345,1072],{"class":1071},[1050,4347,4138],{"class":1185},[1050,4349,4141],{"class":1071},[1050,4351,4353,4355,4357,4359,4361,4363,4365,4367],{"class":1052,"line":4352},265,[1050,4354,4147],{"class":1200},[1050,4356,4150],{"class":1295},[1050,4358,1636],{"class":1635},[1050,4360,2094],{"class":2149},[1050,4362,1072],{"class":1071},[1050,4364,3972],{"class":1824},[1050,4366,1641],{"class":1635},[1050,4368,4369],{"class":1295}," digit(s).\"\n",[1050,4371,4373],{"class":1052,"line":4372},266,[1050,4374,4169],{"class":1071},[1050,4376,4378],{"class":1052,"line":4377},267,[1050,4379,2124],{"class":1067},[1050,4381,4383],{"class":1052,"line":4382},268,[1050,4384,4385],{"class":1056},"                # Check special characters\n",[1050,4387,4389,4392,4394,4396,4398,4400,4402,4404,4406,4408,4410,4412,4415,4417,4419,4421,4423],{"class":1052,"line":4388},269,[1050,4390,4391],{"class":1067},"                special_count ",[1050,4393,1182],{"class":1071},[1050,4395,4072],{"class":1623},[1050,4397,1607],{"class":1071},[1050,4399,4077],{"class":1185},[1050,4401,1072],{"class":1071},[1050,4403,4082],{"class":1185},[1050,4405,1607],{"class":1071},[1050,4407,4087],{"class":1200},[1050,4409,1299],{"class":1291},[1050,4411,4093],{"class":4092},[1050,4413,4414],{"class":4096},"!@#$%^&*(),.?\":{}|\u003C>",[1050,4416,2630],{"class":4092},[1050,4418,1299],{"class":1291},[1050,4420,1100],{"class":1071},[1050,4422,2100],{"class":1185},[1050,4424,4108],{"class":1071},[1050,4426,4428,4430,4433,4435,4437,4439,4441],{"class":1052,"line":4427},270,[1050,4429,2130],{"class":1063},[1050,4431,4432],{"class":1067}," special_count ",[1050,4434,4119],{"class":2133},[1050,4436,2150],{"class":2149},[1050,4438,1072],{"class":1071},[1050,4440,3987],{"class":1824},[1050,4442,1208],{"class":1071},[1050,4444,4446,4448,4450,4452],{"class":1052,"line":4445},271,[1050,4447,4133],{"class":1067},[1050,4449,1072],{"class":1071},[1050,4451,4138],{"class":1185},[1050,4453,4141],{"class":1071},[1050,4455,4457,4459,4461,4463,4465,4467,4469,4471],{"class":1052,"line":4456},272,[1050,4458,4147],{"class":1200},[1050,4460,4150],{"class":1295},[1050,4462,1636],{"class":1635},[1050,4464,2094],{"class":2149},[1050,4466,1072],{"class":1071},[1050,4468,3987],{"class":1824},[1050,4470,1641],{"class":1635},[1050,4472,4473],{"class":1295}," special character(s).\"\n",[1050,4475,4477],{"class":1052,"line":4476},273,[1050,4478,4169],{"class":1071},[1050,4480,4482],{"class":1052,"line":4481},274,[1050,4483,2124],{"class":1067},[1050,4485,4487,4489,4492],{"class":1052,"line":4486},275,[1050,4488,2130],{"class":1063},[1050,4490,4491],{"class":1067}," errors",[1050,4493,1208],{"class":1071},[1050,4495,4497,4500,4503,4505,4508],{"class":1052,"line":4496},276,[1050,4498,4499],{"class":1063},"                    raise",[1050,4501,4502],{"class":1185}," ValidationError",[1050,4504,1607],{"class":1071},[1050,4506,4507],{"class":1185},"errors",[1050,4509,1128],{"class":1071},[1050,4511,4513],{"class":1052,"line":4512},277,[1050,4514,1416],{"class":1067},[1050,4516,4518,4520,4523,4525,4527],{"class":1052,"line":4517},278,[1050,4519,2085],{"class":1200},[1050,4521,4522],{"class":1247}," get_help_text",[1050,4524,1607],{"class":1071},[1050,4526,2094],{"class":2093},[1050,4528,2016],{"class":1071},[1050,4530,4532,4534,4537],{"class":1052,"line":4531},279,[1050,4533,2113],{"class":1214},[1050,4535,4536],{"class":1218},"Return help text for password requirements",[1050,4538,1222],{"class":1214},[1050,4540,4542],{"class":1052,"line":4541},280,[1050,4543,2124],{"class":1067},[1050,4545,4547,4549],{"class":1052,"line":4546},281,[1050,4548,2332],{"class":1063},[1050,4550,1091],{"class":1071},[1050,4552,4554,4557,4560,4562,4564,4566,4568,4570],{"class":1052,"line":4553},282,[1050,4555,4556],{"class":1200},"                    f",[1050,4558,4559],{"class":1295},"\"Your password must contain at least ",[1050,4561,1636],{"class":1635},[1050,4563,2094],{"class":2149},[1050,4565,1072],{"class":1071},[1050,4567,3941],{"class":1824},[1050,4569,1641],{"class":1635},[1050,4571,4572],{"class":1295}," uppercase letter, \"\n",[1050,4574,4576,4578,4580,4582,4584,4586,4588,4590,4593,4595,4597,4599,4601,4603],{"class":1052,"line":4575},283,[1050,4577,4556],{"class":1200},[1050,4579,1644],{"class":1295},[1050,4581,1636],{"class":1635},[1050,4583,2094],{"class":2149},[1050,4585,1072],{"class":1071},[1050,4587,3957],{"class":1824},[1050,4589,1641],{"class":1635},[1050,4591,4592],{"class":1295}," lowercase letter, ",[1050,4594,1636],{"class":1635},[1050,4596,2094],{"class":2149},[1050,4598,1072],{"class":1071},[1050,4600,3972],{"class":1824},[1050,4602,1641],{"class":1635},[1050,4604,4605],{"class":1295}," digit, \"\n",[1050,4607,4609,4611,4614,4616,4618,4620,4622,4624],{"class":1052,"line":4608},284,[1050,4610,4556],{"class":1200},[1050,4612,4613],{"class":1295},"\"and ",[1050,4615,1636],{"class":1635},[1050,4617,2094],{"class":2149},[1050,4619,1072],{"class":1071},[1050,4621,3987],{"class":1824},[1050,4623,1641],{"class":1635},[1050,4625,4626],{"class":1295}," special character.\"\n",[1050,4628,4630],{"class":1052,"line":4629},285,[1050,4631,4632],{"class":1071},"                )\n",[1050,4634,4636],{"class":1052,"line":4635},286,[1050,4637,1268],{"class":1067},[1050,4639,4641,4643,4646],{"class":1052,"line":4640},287,[1050,4642,2004],{"class":1200},[1050,4644,4645],{"class":1204}," PasswordHistoryValidator",[1050,4647,1208],{"class":1071},[1050,4649,4651,4653,4656],{"class":1052,"line":4650},288,[1050,4652,2841],{"class":1214},[1050,4654,4655],{"class":1218},"Prevent reuse of recent passwords",[1050,4657,1222],{"class":1214},[1050,4659,4661],{"class":1052,"line":4660},289,[1050,4662,1416],{"class":1067},[1050,4664,4666,4668,4670,4672,4674,4676,4679,4681,4684],{"class":1052,"line":4665},290,[1050,4667,2085],{"class":1200},[1050,4669,3887],{"class":1623},[1050,4671,1607],{"class":1071},[1050,4673,2094],{"class":2093},[1050,4675,1100],{"class":1071},[1050,4677,4678],{"class":2099}," history_count",[1050,4680,1182],{"class":2133},[1050,4682,4683],{"class":1437},"5",[1050,4685,2016],{"class":1071},[1050,4687,4689,4691,4693,4696,4698],{"class":1052,"line":4688},291,[1050,4690,3936],{"class":2149},[1050,4692,1072],{"class":1071},[1050,4694,4695],{"class":1824},"history_count",[1050,4697,3944],{"class":1071},[1050,4699,4700],{"class":1067}," history_count\n",[1050,4702,4704],{"class":1052,"line":4703},292,[1050,4705,1416],{"class":1067},[1050,4707,4709,4711,4713,4715,4717,4719,4721,4723,4725,4727,4729],{"class":1052,"line":4708},293,[1050,4710,2085],{"class":1200},[1050,4712,4005],{"class":1247},[1050,4714,1607],{"class":1071},[1050,4716,2094],{"class":2093},[1050,4718,1100],{"class":1071},[1050,4720,2100],{"class":2099},[1050,4722,1100],{"class":1071},[1050,4724,2866],{"class":2099},[1050,4726,1182],{"class":2133},[1050,4728,4022],{"class":2763},[1050,4730,2016],{"class":1071},[1050,4732,4734,4736,4739],{"class":1052,"line":4733},294,[1050,4735,2113],{"class":1214},[1050,4737,4738],{"class":1218},"Check against password history",[1050,4740,1222],{"class":1214},[1050,4742,4744],{"class":1052,"line":4743},295,[1050,4745,2124],{"class":1067},[1050,4747,4749,4751,4753,4756,4759,4761,4763,4765,4767,4770,4772],{"class":1052,"line":4748},296,[1050,4750,2130],{"class":1063},[1050,4752,3243],{"class":1067},[1050,4754,4755],{"class":2133},"and",[1050,4757,4758],{"class":1623}," hasattr",[1050,4760,1607],{"class":1071},[1050,4762,2828],{"class":1185},[1050,4764,1100],{"class":1071},[1050,4766,2636],{"class":1291},[1050,4768,4769],{"class":1295},"password_history",[1050,4771,1299],{"class":1291},[1050,4773,2016],{"class":1071},[1050,4775,4777],{"class":1052,"line":4776},297,[1050,4778,4779],{"class":1056},"                    # Get recent password hashes\n",[1050,4781,4783,4786,4788,4790,4792,4794,4796,4799,4801,4803,4806,4808,4811,4813,4815,4817],{"class":1052,"line":4782},298,[1050,4784,4785],{"class":1067},"                    recent_passwords ",[1050,4787,1182],{"class":1071},[1050,4789,2866],{"class":1067},[1050,4791,1072],{"class":1071},[1050,4793,4769],{"class":1824},[1050,4795,1072],{"class":1071},[1050,4797,4798],{"class":1185},"order_by",[1050,4800,1607],{"class":1071},[1050,4802,1299],{"class":1291},[1050,4804,4805],{"class":1295},"-created_at",[1050,4807,1299],{"class":1291},[1050,4809,4810],{"class":1071},")[:",[1050,4812,2094],{"class":2149},[1050,4814,1072],{"class":1071},[1050,4816,4695],{"class":1824},[1050,4818,4819],{"class":1071},"]\n",[1050,4821,4823],{"class":1052,"line":4822},299,[1050,4824,3002],{"class":1067},[1050,4826,4828,4831,4834,4836,4839],{"class":1052,"line":4827},300,[1050,4829,4830],{"class":1063},"                    for",[1050,4832,4833],{"class":1067}," old_password ",[1050,4835,2249],{"class":1063},[1050,4837,4838],{"class":1067}," recent_passwords",[1050,4840,1208],{"class":1071},[1050,4842,4844,4847,4849,4851,4853,4855,4858,4860,4863],{"class":1052,"line":4843},301,[1050,4845,4846],{"class":1063},"                        if",[1050,4848,1103],{"class":1185},[1050,4850,1607],{"class":1071},[1050,4852,2195],{"class":1185},[1050,4854,1100],{"class":1071},[1050,4856,4857],{"class":1185}," old_password",[1050,4859,1072],{"class":1071},[1050,4861,4862],{"class":1824},"password_hash",[1050,4864,2016],{"class":1071},[1050,4866,4868,4871,4873],{"class":1052,"line":4867},302,[1050,4869,4870],{"class":1063},"                            raise",[1050,4872,4502],{"class":1185},[1050,4874,4141],{"class":1071},[1050,4876,4878,4881,4884,4886,4888,4890,4892,4894],{"class":1052,"line":4877},303,[1050,4879,4880],{"class":1200},"                                f",[1050,4882,4883],{"class":1295},"\"Password cannot be one of your last ",[1050,4885,1636],{"class":1635},[1050,4887,2094],{"class":2149},[1050,4889,1072],{"class":1071},[1050,4891,4695],{"class":1824},[1050,4893,1641],{"class":1635},[1050,4895,4896],{"class":1295}," passwords.\"\n",[1050,4898,4900],{"class":1052,"line":4899},304,[1050,4901,4902],{"class":1071},"                            )\n",[1050,4904,4906],{"class":1052,"line":4905},305,[1050,4907,1416],{"class":1067},[1050,4909,4911,4913,4915,4917,4919],{"class":1052,"line":4910},306,[1050,4912,2085],{"class":1200},[1050,4914,4522],{"class":1247},[1050,4916,1607],{"class":1071},[1050,4918,2094],{"class":2093},[1050,4920,2016],{"class":1071},[1050,4922,4924,4926,4928,4930,4932,4934,4936,4938,4940],{"class":1052,"line":4923},307,[1050,4925,2332],{"class":1063},[1050,4927,2179],{"class":1200},[1050,4929,4883],{"class":1295},[1050,4931,1636],{"class":1635},[1050,4933,2094],{"class":2149},[1050,4935,1072],{"class":1071},[1050,4937,4695],{"class":1824},[1050,4939,1641],{"class":1635},[1050,4941,4896],{"class":1295},[1050,4943,4945],{"class":1052,"line":4944},308,[1050,4946,1268],{"class":1067},[1050,4948,4950,4952,4955],{"class":1052,"line":4949},309,[1050,4951,2004],{"class":1200},[1050,4953,4954],{"class":1204}," PasswordExpiryValidator",[1050,4956,1208],{"class":1071},[1050,4958,4960,4962,4965],{"class":1052,"line":4959},310,[1050,4961,2841],{"class":1214},[1050,4963,4964],{"class":1218},"Validate password age",[1050,4966,1222],{"class":1214},[1050,4968,4970],{"class":1052,"line":4969},311,[1050,4971,1416],{"class":1067},[1050,4973,4975,4977,4979,4981,4983,4985,4988,4990,4993],{"class":1052,"line":4974},312,[1050,4976,2085],{"class":1200},[1050,4978,3887],{"class":1623},[1050,4980,1607],{"class":1071},[1050,4982,2094],{"class":2093},[1050,4984,1100],{"class":1071},[1050,4986,4987],{"class":2099}," max_age_days",[1050,4989,1182],{"class":2133},[1050,4991,4992],{"class":1437},"90",[1050,4994,2016],{"class":1071},[1050,4996,4998,5000,5002,5005,5007],{"class":1052,"line":4997},313,[1050,4999,3936],{"class":2149},[1050,5001,1072],{"class":1071},[1050,5003,5004],{"class":1824},"max_age_days",[1050,5006,3944],{"class":1071},[1050,5008,5009],{"class":1067}," max_age_days\n",[1050,5011,5013],{"class":1052,"line":5012},314,[1050,5014,1416],{"class":1067},[1050,5016,5018,5020,5022,5024,5026,5028,5030,5032,5034,5036,5038],{"class":1052,"line":5017},315,[1050,5019,2085],{"class":1200},[1050,5021,4005],{"class":1247},[1050,5023,1607],{"class":1071},[1050,5025,2094],{"class":2093},[1050,5027,1100],{"class":1071},[1050,5029,2100],{"class":2099},[1050,5031,1100],{"class":1071},[1050,5033,2866],{"class":2099},[1050,5035,1182],{"class":2133},[1050,5037,4022],{"class":2763},[1050,5039,2016],{"class":1071},[1050,5041,5043,5045,5048],{"class":1052,"line":5042},316,[1050,5044,2113],{"class":1214},[1050,5046,5047],{"class":1218},"Check if password needs to be changed due to age",[1050,5049,1222],{"class":1214},[1050,5051,5053],{"class":1052,"line":5052},317,[1050,5054,2124],{"class":1067},[1050,5056,5058,5060,5062,5064,5066,5068,5070],{"class":1052,"line":5057},318,[1050,5059,2130],{"class":1063},[1050,5061,3243],{"class":1067},[1050,5063,4755],{"class":2133},[1050,5065,2866],{"class":1067},[1050,5067,1072],{"class":1071},[1050,5069,2195],{"class":1824},[1050,5071,1208],{"class":1071},[1050,5073,5075],{"class":1052,"line":5074},319,[1050,5076,5077],{"class":1056},"                    # Check when password was last changed\n",[1050,5079,5081,5083,5085,5087,5089,5091,5093,5096,5098],{"class":1052,"line":5080},320,[1050,5082,3316],{"class":1063},[1050,5084,4758],{"class":1623},[1050,5086,1607],{"class":1071},[1050,5088,2828],{"class":1185},[1050,5090,1100],{"class":1071},[1050,5092,2636],{"class":1291},[1050,5094,5095],{"class":1295},"password_changed_at",[1050,5097,1299],{"class":1291},[1050,5099,2016],{"class":1071},[1050,5101,5103,5106,5108,5111,5113,5116,5119,5122,5124,5126],{"class":1052,"line":5102},321,[1050,5104,5105],{"class":1067},"                        password_age ",[1050,5107,1182],{"class":1071},[1050,5109,5110],{"class":1067}," timezone",[1050,5112,1072],{"class":1071},[1050,5114,5115],{"class":1185},"now",[1050,5117,5118],{"class":1071},"()",[1050,5120,5121],{"class":2133}," -",[1050,5123,2866],{"class":1067},[1050,5125,1072],{"class":1071},[1050,5127,5128],{"class":1824},"password_changed_at\n",[1050,5130,5132],{"class":1052,"line":5131},322,[1050,5133,5134],{"class":1067},"                        \n",[1050,5136,5138,5140,5143,5145,5148,5151,5153,5155,5157],{"class":1052,"line":5137},323,[1050,5139,4846],{"class":1063},[1050,5141,5142],{"class":1067}," password_age",[1050,5144,1072],{"class":1071},[1050,5146,5147],{"class":1824},"days",[1050,5149,5150],{"class":2133}," >",[1050,5152,2150],{"class":2149},[1050,5154,1072],{"class":1071},[1050,5156,5004],{"class":1824},[1050,5158,1208],{"class":1071},[1050,5160,5162,5164,5166],{"class":1052,"line":5161},324,[1050,5163,4870],{"class":1063},[1050,5165,4502],{"class":1185},[1050,5167,4141],{"class":1071},[1050,5169,5171,5173,5176,5178,5181,5183,5185,5187],{"class":1052,"line":5170},325,[1050,5172,4880],{"class":1200},[1050,5174,5175],{"class":1295},"\"Password is ",[1050,5177,1636],{"class":1635},[1050,5179,5180],{"class":1185},"password_age",[1050,5182,1072],{"class":1071},[1050,5184,5147],{"class":1824},[1050,5186,1641],{"class":1635},[1050,5188,5189],{"class":1295}," days old. \"\n",[1050,5191,5193,5195,5198,5200,5202,5204,5206,5208],{"class":1052,"line":5192},326,[1050,5194,4880],{"class":1200},[1050,5196,5197],{"class":1295},"\"Passwords must be changed every ",[1050,5199,1636],{"class":1635},[1050,5201,2094],{"class":2149},[1050,5203,1072],{"class":1071},[1050,5205,5004],{"class":1824},[1050,5207,1641],{"class":1635},[1050,5209,5210],{"class":1295}," days.\"\n",[1050,5212,5214],{"class":1052,"line":5213},327,[1050,5215,4902],{"class":1071},[1050,5217,5219],{"class":1052,"line":5218},328,[1050,5220,1416],{"class":1067},[1050,5222,5224,5226,5228,5230,5232],{"class":1052,"line":5223},329,[1050,5225,2085],{"class":1200},[1050,5227,4522],{"class":1247},[1050,5229,1607],{"class":1071},[1050,5231,2094],{"class":2093},[1050,5233,2016],{"class":1071},[1050,5235,5237,5239,5241,5243,5245,5247,5249,5251,5253],{"class":1052,"line":5236},330,[1050,5238,2332],{"class":1063},[1050,5240,2179],{"class":1200},[1050,5242,5197],{"class":1295},[1050,5244,1636],{"class":1635},[1050,5246,2094],{"class":2149},[1050,5248,1072],{"class":1071},[1050,5250,5004],{"class":1824},[1050,5252,1641],{"class":1635},[1050,5254,5210],{"class":1295},[1050,5256,5258],{"class":1052,"line":5257},331,[1050,5259,1268],{"class":1067},[1050,5261,5263,5265,5267,5269,5271,5273],{"class":1052,"line":5262},332,[1050,5264,1530],{"class":1063},[1050,5266,3862],{"class":1067},[1050,5268,1100],{"class":1071},[1050,5270,4645],{"class":1067},[1050,5272,1100],{"class":1071},[1050,5274,5275],{"class":1067}," PasswordExpiryValidator\n",[1050,5277,5279],{"class":1052,"line":5278},333,[1050,5280,1228],{"class":1067},[1050,5282,5284,5286],{"class":1052,"line":5283},334,[1050,5285,1234],{"class":1071},[1050,5287,1238],{"class":1237},[1050,5289,5291,5293,5296],{"class":1052,"line":5290},335,[1050,5292,1244],{"class":1200},[1050,5294,5295],{"class":1247}," validate_password_strength",[1050,5297,1251],{"class":1071},[1050,5299,5301,5303,5306],{"class":1052,"line":5300},336,[1050,5302,1257],{"class":1214},[1050,5304,5305],{"class":1218},"Comprehensive password strength validation",[1050,5307,1222],{"class":1214},[1050,5309,5311],{"class":1052,"line":5310},337,[1050,5312,1268],{"class":1067},[1050,5314,5316,5318,5320,5322,5324,5326,5328,5330,5332,5334],{"class":1052,"line":5315},338,[1050,5317,1957],{"class":1063},[1050,5319,1068],{"class":1067},[1050,5321,1072],{"class":1071},[1050,5323,1075],{"class":1067},[1050,5325,1072],{"class":1071},[1050,5327,1080],{"class":1067},[1050,5329,1072],{"class":1071},[1050,5331,3814],{"class":1067},[1050,5333,1088],{"class":1063},[1050,5335,5336],{"class":1067}," validate_password\n",[1050,5338,5340,5342,5344,5346,5348,5350,5352,5354],{"class":1052,"line":5339},339,[1050,5341,1957],{"class":1063},[1050,5343,1068],{"class":1067},[1050,5345,1072],{"class":1071},[1050,5347,3831],{"class":1067},[1050,5349,1072],{"class":1071},[1050,5351,3836],{"class":1067},[1050,5353,1088],{"class":1063},[1050,5355,3841],{"class":1067},[1050,5357,5359],{"class":1052,"line":5358},340,[1050,5360,1268],{"class":1067},[1050,5362,5364,5366,5369,5371,5373,5375,5377,5379,5381],{"class":1052,"line":5363},341,[1050,5365,2820],{"class":1200},[1050,5367,5368],{"class":1247}," check_password_strength",[1050,5370,1607],{"class":1071},[1050,5372,2195],{"class":2099},[1050,5374,1100],{"class":1071},[1050,5376,2866],{"class":2099},[1050,5378,1182],{"class":2133},[1050,5380,4022],{"class":2763},[1050,5382,2016],{"class":1071},[1050,5384,5386,5388,5391],{"class":1052,"line":5385},342,[1050,5387,2841],{"class":1214},[1050,5389,5390],{"class":1218},"Check password strength and return detailed feedback",[1050,5392,1222],{"class":1214},[1050,5394,5396],{"class":1052,"line":5395},343,[1050,5397,1416],{"class":1067},[1050,5399,5401,5404,5406],{"class":1052,"line":5400},344,[1050,5402,5403],{"class":1067},"            strength_score ",[1050,5405,1182],{"class":1071},[1050,5407,3212],{"class":1437},[1050,5409,5411,5414,5416],{"class":1052,"line":5410},345,[1050,5412,5413],{"class":1067},"            feedback ",[1050,5415,1182],{"class":1071},[1050,5417,4050],{"class":1071},[1050,5419,5421],{"class":1052,"line":5420},346,[1050,5422,1416],{"class":1067},[1050,5424,5426],{"class":1052,"line":5425},347,[1050,5427,5428],{"class":1056},"            # Length check\n",[1050,5430,5432,5434,5436,5438,5440,5443,5446,5448],{"class":1052,"line":5431},348,[1050,5433,2863],{"class":1063},[1050,5435,4072],{"class":1623},[1050,5437,1607],{"class":1071},[1050,5439,2195],{"class":1185},[1050,5441,5442],{"class":1071},")",[1050,5444,5445],{"class":2133}," >=",[1050,5447,3667],{"class":1437},[1050,5449,1208],{"class":1071},[1050,5451,5453,5456,5458],{"class":1052,"line":5452},349,[1050,5454,5455],{"class":1067},"                strength_score ",[1050,5457,3382],{"class":1071},[1050,5459,5460],{"class":1437}," 2\n",[1050,5462,5464,5467,5469,5471,5473,5475,5478,5480],{"class":1052,"line":5463},350,[1050,5465,5466],{"class":1067},"                feedback",[1050,5468,1072],{"class":1071},[1050,5470,4138],{"class":1185},[1050,5472,1607],{"class":1071},[1050,5474,1644],{"class":1291},[1050,5476,5477],{"class":1295},"✓ Good length (12+ characters)",[1050,5479,1644],{"class":1291},[1050,5481,1128],{"class":1071},[1050,5483,5485,5488,5490,5492,5494,5496,5498,5501],{"class":1052,"line":5484},351,[1050,5486,5487],{"class":1063},"            elif",[1050,5489,4072],{"class":1623},[1050,5491,1607],{"class":1071},[1050,5493,2195],{"class":1185},[1050,5495,5442],{"class":1071},[1050,5497,5445],{"class":2133},[1050,5499,5500],{"class":1437}," 8",[1050,5502,1208],{"class":1071},[1050,5504,5506,5508,5510],{"class":1052,"line":5505},352,[1050,5507,5455],{"class":1067},[1050,5509,3382],{"class":1071},[1050,5511,3385],{"class":1437},[1050,5513,5515,5517,5519,5521,5523,5525,5528,5530],{"class":1052,"line":5514},353,[1050,5516,5466],{"class":1067},[1050,5518,1072],{"class":1071},[1050,5520,4138],{"class":1185},[1050,5522,1607],{"class":1071},[1050,5524,1644],{"class":1291},[1050,5526,5527],{"class":1295},"⚠ Minimum length met (8+ characters)",[1050,5529,1644],{"class":1291},[1050,5531,1128],{"class":1071},[1050,5533,5535,5538],{"class":1052,"line":5534},354,[1050,5536,5537],{"class":1063},"            else",[1050,5539,1208],{"class":1071},[1050,5541,5543,5545,5547,5549,5551,5553,5556,5558],{"class":1052,"line":5542},355,[1050,5544,5466],{"class":1067},[1050,5546,1072],{"class":1071},[1050,5548,4138],{"class":1185},[1050,5550,1607],{"class":1071},[1050,5552,1644],{"class":1291},[1050,5554,5555],{"class":1295},"✗ Too short (minimum 8 characters)",[1050,5557,1644],{"class":1291},[1050,5559,1128],{"class":1071},[1050,5561,5563],{"class":1052,"line":5562},356,[1050,5564,1416],{"class":1067},[1050,5566,5568],{"class":1052,"line":5567},357,[1050,5569,5570],{"class":1056},"            # Character variety\n",[1050,5572,5574,5577,5579,5582,5584,5586,5588,5591,5593,5595,5597,5599,5601,5603,5605,5607,5609],{"class":1052,"line":5573},358,[1050,5575,5576],{"class":1067},"            has_upper ",[1050,5578,1182],{"class":1071},[1050,5580,5581],{"class":1237}," bool",[1050,5583,1607],{"class":1071},[1050,5585,4077],{"class":1185},[1050,5587,1072],{"class":1071},[1050,5589,5590],{"class":1185},"search",[1050,5592,1607],{"class":1071},[1050,5594,4087],{"class":1200},[1050,5596,1299],{"class":1291},[1050,5598,4093],{"class":4092},[1050,5600,4097],{"class":4096},[1050,5602,2630],{"class":4092},[1050,5604,1299],{"class":1291},[1050,5606,1100],{"class":1071},[1050,5608,2100],{"class":1185},[1050,5610,4108],{"class":1071},[1050,5612,5614,5617,5619,5621,5623,5625,5627,5629,5631,5633,5635,5637,5639,5641,5643,5645,5647],{"class":1052,"line":5613},359,[1050,5615,5616],{"class":1067},"            has_lower ",[1050,5618,1182],{"class":1071},[1050,5620,5581],{"class":1237},[1050,5622,1607],{"class":1071},[1050,5624,4077],{"class":1185},[1050,5626,1072],{"class":1071},[1050,5628,5590],{"class":1185},[1050,5630,1607],{"class":1071},[1050,5632,4087],{"class":1200},[1050,5634,1299],{"class":1291},[1050,5636,4093],{"class":4092},[1050,5638,4209],{"class":4096},[1050,5640,2630],{"class":4092},[1050,5642,1299],{"class":1291},[1050,5644,1100],{"class":1071},[1050,5646,2100],{"class":1185},[1050,5648,4108],{"class":1071},[1050,5650,5652,5655,5657,5659,5661,5663,5665,5667,5669,5671,5673,5675,5677,5679,5681],{"class":1052,"line":5651},360,[1050,5653,5654],{"class":1067},"            has_digit ",[1050,5656,1182],{"class":1071},[1050,5658,5581],{"class":1237},[1050,5660,1607],{"class":1071},[1050,5662,4077],{"class":1185},[1050,5664,1072],{"class":1071},[1050,5666,5590],{"class":1185},[1050,5668,1607],{"class":1071},[1050,5670,4087],{"class":1200},[1050,5672,1299],{"class":1291},[1050,5674,4312],{"class":4311},[1050,5676,1299],{"class":1291},[1050,5678,1100],{"class":1071},[1050,5680,2100],{"class":1185},[1050,5682,4108],{"class":1071},[1050,5684,5686,5689,5691,5693,5695,5697,5699,5701,5703,5705,5707,5709,5711,5713,5715,5717,5719],{"class":1052,"line":5685},361,[1050,5687,5688],{"class":1067},"            has_special ",[1050,5690,1182],{"class":1071},[1050,5692,5581],{"class":1237},[1050,5694,1607],{"class":1071},[1050,5696,4077],{"class":1185},[1050,5698,1072],{"class":1071},[1050,5700,5590],{"class":1185},[1050,5702,1607],{"class":1071},[1050,5704,4087],{"class":1200},[1050,5706,1299],{"class":1291},[1050,5708,4093],{"class":4092},[1050,5710,4414],{"class":4096},[1050,5712,2630],{"class":4092},[1050,5714,1299],{"class":1291},[1050,5716,1100],{"class":1071},[1050,5718,2100],{"class":1185},[1050,5720,4108],{"class":1071},[1050,5722,5724],{"class":1052,"line":5723},362,[1050,5725,1416],{"class":1067},[1050,5727,5729,5732,5734,5737,5740,5743,5745,5748,5750,5753,5755,5758],{"class":1052,"line":5728},363,[1050,5730,5731],{"class":1067},"            variety_count ",[1050,5733,1182],{"class":1071},[1050,5735,5736],{"class":1623}," sum",[1050,5738,5739],{"class":1071},"([",[1050,5741,5742],{"class":1185},"has_upper",[1050,5744,1100],{"class":1071},[1050,5746,5747],{"class":1185}," has_lower",[1050,5749,1100],{"class":1071},[1050,5751,5752],{"class":1185}," has_digit",[1050,5754,1100],{"class":1071},[1050,5756,5757],{"class":1185}," has_special",[1050,5759,2996],{"class":1071},[1050,5761,5763],{"class":1052,"line":5762},364,[1050,5764,1416],{"class":1067},[1050,5766,5768,5770,5773,5776,5779],{"class":1052,"line":5767},365,[1050,5769,2863],{"class":1063},[1050,5771,5772],{"class":1067}," variety_count ",[1050,5774,5775],{"class":2133},">=",[1050,5777,5778],{"class":1437}," 4",[1050,5780,1208],{"class":1071},[1050,5782,5784,5786,5788],{"class":1052,"line":5783},366,[1050,5785,5455],{"class":1067},[1050,5787,3382],{"class":1071},[1050,5789,5790],{"class":1437}," 3\n",[1050,5792,5794,5796,5798,5800,5802,5804,5807,5809],{"class":1052,"line":5793},367,[1050,5795,5466],{"class":1067},[1050,5797,1072],{"class":1071},[1050,5799,4138],{"class":1185},[1050,5801,1607],{"class":1071},[1050,5803,1644],{"class":1291},[1050,5805,5806],{"class":1295},"✓ Excellent character variety",[1050,5808,1644],{"class":1291},[1050,5810,1128],{"class":1071},[1050,5812,5814,5816,5818,5820,5823],{"class":1052,"line":5813},368,[1050,5815,5487],{"class":1063},[1050,5817,5772],{"class":1067},[1050,5819,5775],{"class":2133},[1050,5821,5822],{"class":1437}," 3",[1050,5824,1208],{"class":1071},[1050,5826,5828,5830,5832],{"class":1052,"line":5827},369,[1050,5829,5455],{"class":1067},[1050,5831,3382],{"class":1071},[1050,5833,5460],{"class":1437},[1050,5835,5837,5839,5841,5843,5845,5847,5850,5852],{"class":1052,"line":5836},370,[1050,5838,5466],{"class":1067},[1050,5840,1072],{"class":1071},[1050,5842,4138],{"class":1185},[1050,5844,1607],{"class":1071},[1050,5846,1644],{"class":1291},[1050,5848,5849],{"class":1295},"✓ Good character variety",[1050,5851,1644],{"class":1291},[1050,5853,1128],{"class":1071},[1050,5855,5857,5859,5861,5863,5865],{"class":1052,"line":5856},371,[1050,5858,5487],{"class":1063},[1050,5860,5772],{"class":1067},[1050,5862,5775],{"class":2133},[1050,5864,1438],{"class":1437},[1050,5866,1208],{"class":1071},[1050,5868,5870,5872,5874],{"class":1052,"line":5869},372,[1050,5871,5455],{"class":1067},[1050,5873,3382],{"class":1071},[1050,5875,3385],{"class":1437},[1050,5877,5879,5881,5883,5885,5887,5889,5892,5894],{"class":1052,"line":5878},373,[1050,5880,5466],{"class":1067},[1050,5882,1072],{"class":1071},[1050,5884,4138],{"class":1185},[1050,5886,1607],{"class":1071},[1050,5888,1644],{"class":1291},[1050,5890,5891],{"class":1295},"⚠ Basic character variety",[1050,5893,1644],{"class":1291},[1050,5895,1128],{"class":1071},[1050,5897,5899,5901],{"class":1052,"line":5898},374,[1050,5900,5537],{"class":1063},[1050,5902,1208],{"class":1071},[1050,5904,5906,5908,5910,5912,5914,5916,5919,5921],{"class":1052,"line":5905},375,[1050,5907,5466],{"class":1067},[1050,5909,1072],{"class":1071},[1050,5911,4138],{"class":1185},[1050,5913,1607],{"class":1071},[1050,5915,1644],{"class":1291},[1050,5917,5918],{"class":1295},"✗ Poor character variety",[1050,5920,1644],{"class":1291},[1050,5922,1128],{"class":1071},[1050,5924,5926],{"class":1052,"line":5925},376,[1050,5927,1416],{"class":1067},[1050,5929,5931],{"class":1052,"line":5930},377,[1050,5932,5933],{"class":1056},"            # Common patterns check\n",[1050,5935,5937,5940,5942],{"class":1052,"line":5936},378,[1050,5938,5939],{"class":1067},"            common_patterns ",[1050,5941,1182],{"class":1071},[1050,5943,1285],{"class":1071},[1050,5945,5947,5950,5952,5956,5958,5960,5963,5965,5968,5970,5972,5974,5976,5979,5981,5983,5985,5987,5989,5991,5993,5995,5997,6000],{"class":1052,"line":5946},379,[1050,5948,5949],{"class":1200},"                r",[1050,5951,1299],{"class":1291},[1050,5953,5955],{"class":5954},"s27EL","123",[1050,5957,1299],{"class":1291},[1050,5959,1100],{"class":1071},[1050,5961,5962],{"class":1200}," r",[1050,5964,1299],{"class":1291},[1050,5966,5967],{"class":5954},"abc",[1050,5969,1299],{"class":1291},[1050,5971,1100],{"class":1071},[1050,5973,5962],{"class":1200},[1050,5975,1299],{"class":1291},[1050,5977,5978],{"class":5954},"qwerty",[1050,5980,1299],{"class":1291},[1050,5982,1100],{"class":1071},[1050,5984,5962],{"class":1200},[1050,5986,1299],{"class":1291},[1050,5988,2195],{"class":5954},[1050,5990,1299],{"class":1291},[1050,5992,1100],{"class":1071},[1050,5994,5962],{"class":1200},[1050,5996,1299],{"class":1291},[1050,5998,5999],{"class":5954},"admin",[1050,6001,6002],{"class":1291},"'\n",[1050,6004,6006],{"class":1052,"line":6005},380,[1050,6007,6008],{"class":1071},"            ]\n",[1050,6010,6012],{"class":1052,"line":6011},381,[1050,6013,1416],{"class":1067},[1050,6015,6017,6020,6022,6025],{"class":1052,"line":6016},382,[1050,6018,6019],{"class":1067},"            has_common_pattern ",[1050,6021,1182],{"class":1071},[1050,6023,6024],{"class":1623}," any",[1050,6026,4141],{"class":1071},[1050,6028,6030,6033,6035,6037,6039,6042,6044,6046,6048,6051,6054,6057,6060,6062],{"class":1052,"line":6029},383,[1050,6031,6032],{"class":1185},"                re",[1050,6034,1072],{"class":1071},[1050,6036,5590],{"class":1185},[1050,6038,1607],{"class":1071},[1050,6040,6041],{"class":1185},"pattern",[1050,6043,1100],{"class":1071},[1050,6045,2100],{"class":1185},[1050,6047,1072],{"class":1071},[1050,6049,6050],{"class":1185},"lower",[1050,6052,6053],{"class":1071},"())",[1050,6055,6056],{"class":1063}," for",[1050,6058,6059],{"class":1185}," pattern ",[1050,6061,2249],{"class":1063},[1050,6063,6064],{"class":1185}," common_patterns\n",[1050,6066,6068],{"class":1052,"line":6067},384,[1050,6069,6070],{"class":1071},"            )\n",[1050,6072,6074],{"class":1052,"line":6073},385,[1050,6075,1416],{"class":1067},[1050,6077,6079,6081,6083,6086],{"class":1052,"line":6078},386,[1050,6080,2863],{"class":1063},[1050,6082,2134],{"class":2133},[1050,6084,6085],{"class":1067}," has_common_pattern",[1050,6087,1208],{"class":1071},[1050,6089,6091,6093,6095],{"class":1052,"line":6090},387,[1050,6092,5455],{"class":1067},[1050,6094,3382],{"class":1071},[1050,6096,3385],{"class":1437},[1050,6098,6100,6102,6104,6106,6108,6110,6113,6115],{"class":1052,"line":6099},388,[1050,6101,5466],{"class":1067},[1050,6103,1072],{"class":1071},[1050,6105,4138],{"class":1185},[1050,6107,1607],{"class":1071},[1050,6109,1644],{"class":1291},[1050,6111,6112],{"class":1295},"✓ No common patterns detected",[1050,6114,1644],{"class":1291},[1050,6116,1128],{"class":1071},[1050,6118,6120,6122],{"class":1052,"line":6119},389,[1050,6121,5537],{"class":1063},[1050,6123,1208],{"class":1071},[1050,6125,6127,6129,6131,6133,6135,6137,6140,6142],{"class":1052,"line":6126},390,[1050,6128,5466],{"class":1067},[1050,6130,1072],{"class":1071},[1050,6132,4138],{"class":1185},[1050,6134,1607],{"class":1071},[1050,6136,1644],{"class":1291},[1050,6138,6139],{"class":1295},"✗ Contains common patterns",[1050,6141,1644],{"class":1291},[1050,6143,1128],{"class":1071},[1050,6145,6147],{"class":1052,"line":6146},391,[1050,6148,1416],{"class":1067},[1050,6150,6152],{"class":1052,"line":6151},392,[1050,6153,6154],{"class":1056},"            # Django validation\n",[1050,6156,6158,6161],{"class":1052,"line":6157},393,[1050,6159,6160],{"class":1063},"            try",[1050,6162,1208],{"class":1071},[1050,6164,6166,6169,6171,6173,6175,6177],{"class":1052,"line":6165},394,[1050,6167,6168],{"class":1185},"                validate_password",[1050,6170,1607],{"class":1071},[1050,6172,2195],{"class":1185},[1050,6174,1100],{"class":1071},[1050,6176,2866],{"class":1185},[1050,6178,1128],{"class":1071},[1050,6180,6182,6184,6186],{"class":1052,"line":6181},395,[1050,6183,5455],{"class":1067},[1050,6185,3382],{"class":1071},[1050,6187,3385],{"class":1437},[1050,6189,6191,6193,6195,6197,6199,6201,6204,6206],{"class":1052,"line":6190},396,[1050,6192,5466],{"class":1067},[1050,6194,1072],{"class":1071},[1050,6196,4138],{"class":1185},[1050,6198,1607],{"class":1071},[1050,6200,1644],{"class":1291},[1050,6202,6203],{"class":1295},"✓ Passes Django validation",[1050,6205,1644],{"class":1291},[1050,6207,1128],{"class":1071},[1050,6209,6211,6214,6217,6220,6223],{"class":1052,"line":6210},397,[1050,6212,6213],{"class":1063},"            except",[1050,6215,6216],{"class":1067}," ValidationError ",[1050,6218,6219],{"class":1063},"as",[1050,6221,6222],{"class":1067}," e",[1050,6224,1208],{"class":1071},[1050,6226,6228,6230,6232,6235,6237,6239,6242,6244,6247,6249,6251,6253,6256,6258,6260,6262,6265],{"class":1052,"line":6227},398,[1050,6229,5466],{"class":1067},[1050,6231,1072],{"class":1071},[1050,6233,6234],{"class":1185},"extend",[1050,6236,5739],{"class":1071},[1050,6238,1629],{"class":1200},[1050,6240,6241],{"class":1295},"\"✗ ",[1050,6243,1636],{"class":1635},[1050,6245,6246],{"class":1185},"error",[1050,6248,1641],{"class":1635},[1050,6250,1644],{"class":1295},[1050,6252,6056],{"class":1063},[1050,6254,6255],{"class":1185}," error ",[1050,6257,2249],{"class":1063},[1050,6259,6222],{"class":1185},[1050,6261,1072],{"class":1071},[1050,6263,6264],{"class":1824},"messages",[1050,6266,2996],{"class":1071},[1050,6268,6270],{"class":1052,"line":6269},399,[1050,6271,1416],{"class":1067},[1050,6273,6275],{"class":1052,"line":6274},400,[1050,6276,6277],{"class":1056},"            # Calculate strength level\n",[1050,6279,6281,6283,6286,6288,6291],{"class":1052,"line":6280},401,[1050,6282,2863],{"class":1063},[1050,6284,6285],{"class":1067}," strength_score ",[1050,6287,5775],{"class":2133},[1050,6289,6290],{"class":1437}," 6",[1050,6292,1208],{"class":1071},[1050,6294,6296,6299,6301,6303,6306],{"class":1052,"line":6295},402,[1050,6297,6298],{"class":1067},"                strength_level ",[1050,6300,1182],{"class":1071},[1050,6302,1587],{"class":1291},[1050,6304,6305],{"class":1295},"Very Strong",[1050,6307,1593],{"class":1291},[1050,6309,6311,6313,6315,6317,6319],{"class":1052,"line":6310},403,[1050,6312,5487],{"class":1063},[1050,6314,6285],{"class":1067},[1050,6316,5775],{"class":2133},[1050,6318,5778],{"class":1437},[1050,6320,1208],{"class":1071},[1050,6322,6324,6326,6328,6330,6333],{"class":1052,"line":6323},404,[1050,6325,6298],{"class":1067},[1050,6327,1182],{"class":1071},[1050,6329,1587],{"class":1291},[1050,6331,6332],{"class":1295},"Strong",[1050,6334,1593],{"class":1291},[1050,6336,6338,6340,6342,6344,6346],{"class":1052,"line":6337},405,[1050,6339,5487],{"class":1063},[1050,6341,6285],{"class":1067},[1050,6343,5775],{"class":2133},[1050,6345,1438],{"class":1437},[1050,6347,1208],{"class":1071},[1050,6349,6351,6353,6355,6357,6360],{"class":1052,"line":6350},406,[1050,6352,6298],{"class":1067},[1050,6354,1182],{"class":1071},[1050,6356,1587],{"class":1291},[1050,6358,6359],{"class":1295},"Moderate",[1050,6361,1593],{"class":1291},[1050,6363,6365,6367],{"class":1052,"line":6364},407,[1050,6366,5537],{"class":1063},[1050,6368,1208],{"class":1071},[1050,6370,6372,6374,6376,6378,6381],{"class":1052,"line":6371},408,[1050,6373,6298],{"class":1067},[1050,6375,1182],{"class":1071},[1050,6377,1587],{"class":1291},[1050,6379,6380],{"class":1295},"Weak",[1050,6382,1593],{"class":1291},[1050,6384,6386],{"class":1052,"line":6385},409,[1050,6387,1416],{"class":1067},[1050,6389,6391,6393],{"class":1052,"line":6390},410,[1050,6392,3159],{"class":1063},[1050,6394,1392],{"class":1071},[1050,6396,6398,6400,6403,6405,6407,6410],{"class":1052,"line":6397},411,[1050,6399,3505],{"class":1291},[1050,6401,6402],{"class":1295},"score",[1050,6404,1299],{"class":1291},[1050,6406,1405],{"class":1071},[1050,6408,6409],{"class":1067}," strength_score",[1050,6411,1111],{"class":1071},[1050,6413,6415,6417,6420,6422,6424,6427],{"class":1052,"line":6414},412,[1050,6416,3505],{"class":1291},[1050,6418,6419],{"class":1295},"max_score",[1050,6421,1299],{"class":1291},[1050,6423,1405],{"class":1071},[1050,6425,6426],{"class":1437}," 7",[1050,6428,1111],{"class":1071},[1050,6430,6432,6434,6437,6439,6441,6444],{"class":1052,"line":6431},413,[1050,6433,3505],{"class":1291},[1050,6435,6436],{"class":1295},"level",[1050,6438,1299],{"class":1291},[1050,6440,1405],{"class":1071},[1050,6442,6443],{"class":1067}," strength_level",[1050,6445,1111],{"class":1071},[1050,6447,6449,6451,6454,6456,6458],{"class":1052,"line":6448},414,[1050,6450,3505],{"class":1291},[1050,6452,6453],{"class":1295},"feedback",[1050,6455,1299],{"class":1291},[1050,6457,1405],{"class":1071},[1050,6459,6460],{"class":1067}," feedback\n",[1050,6462,6464],{"class":1052,"line":6463},415,[1050,6465,6466],{"class":1071},"            }\n",[1050,6468,6470],{"class":1052,"line":6469},416,[1050,6471,1268],{"class":1067},[1050,6473,6475,6477],{"class":1052,"line":6474},417,[1050,6476,1530],{"class":1063},[1050,6478,6479],{"class":1067}," check_password_strength\n",[1050,6481,6483],{"class":1052,"line":6482},418,[1050,6484,1173],{"emptyLinePlaceholder":1172},[1050,6486,6488],{"class":1052,"line":6487},419,[1050,6489,6490],{"class":1056},"# Password reset and recovery\n",[1050,6492,6494,6496,6499],{"class":1052,"line":6493},420,[1050,6495,1201],{"class":1200},[1050,6497,6498],{"class":1204}," PasswordResetSystem",[1050,6500,1208],{"class":1071},[1050,6502,6504,6506,6509],{"class":1052,"line":6503},421,[1050,6505,1215],{"class":1214},[1050,6507,6508],{"class":1218},"Implement secure password reset functionality",[1050,6510,1222],{"class":1214},[1050,6512,6514],{"class":1052,"line":6513},422,[1050,6515,1228],{"class":1067},[1050,6517,6519,6521],{"class":1052,"line":6518},423,[1050,6520,1234],{"class":1071},[1050,6522,1238],{"class":1237},[1050,6524,6526,6528,6531],{"class":1052,"line":6525},424,[1050,6527,1244],{"class":1200},[1050,6529,6530],{"class":1247}," secure_password_reset_tokens",[1050,6532,1251],{"class":1071},[1050,6534,6536,6538,6541],{"class":1052,"line":6535},425,[1050,6537,1257],{"class":1214},[1050,6539,6540],{"class":1218},"Generate secure password reset tokens",[1050,6542,1222],{"class":1214},[1050,6544,6546],{"class":1052,"line":6545},426,[1050,6547,1268],{"class":1067},[1050,6549,6551,6553,6555,6557,6559,6561,6563,6565,6568,6570],{"class":1052,"line":6550},427,[1050,6552,1957],{"class":1063},[1050,6554,1068],{"class":1067},[1050,6556,1072],{"class":1071},[1050,6558,1075],{"class":1067},[1050,6560,1072],{"class":1071},[1050,6562,1080],{"class":1067},[1050,6564,1072],{"class":1071},[1050,6566,6567],{"class":1067},"tokens ",[1050,6569,1088],{"class":1063},[1050,6571,6572],{"class":1067}," PasswordResetTokenGenerator\n",[1050,6574,6576,6578,6580,6582,6585,6587,6590,6592],{"class":1052,"line":6575},428,[1050,6577,1957],{"class":1063},[1050,6579,1068],{"class":1067},[1050,6581,1072],{"class":1071},[1050,6583,6584],{"class":1067},"utils",[1050,6586,1072],{"class":1071},[1050,6588,6589],{"class":1067},"crypto ",[1050,6591,1088],{"class":1063},[1050,6593,6594],{"class":1067}," constant_time_compare\n",[1050,6596,6598,6600],{"class":1052,"line":6597},429,[1050,6599,1982],{"class":1063},[1050,6601,1985],{"class":1067},[1050,6603,6605],{"class":1052,"line":6604},430,[1050,6606,1268],{"class":1067},[1050,6608,6610,6612,6615,6617,6620],{"class":1052,"line":6609},431,[1050,6611,2004],{"class":1200},[1050,6613,6614],{"class":1204}," SecurePasswordResetTokenGenerator",[1050,6616,1607],{"class":1071},[1050,6618,6619],{"class":2012},"PasswordResetTokenGenerator",[1050,6621,2016],{"class":1071},[1050,6623,6625,6627,6630],{"class":1052,"line":6624},432,[1050,6626,2841],{"class":1214},[1050,6628,6629],{"class":1218},"Enhanced password reset token generator",[1050,6631,1222],{"class":1214},[1050,6633,6635],{"class":1052,"line":6634},433,[1050,6636,1416],{"class":1067},[1050,6638,6640,6642,6645,6647,6649,6651,6653,6655,6658],{"class":1052,"line":6639},434,[1050,6641,2085],{"class":1200},[1050,6643,6644],{"class":1247}," _make_hash_value",[1050,6646,1607],{"class":1071},[1050,6648,2094],{"class":2093},[1050,6650,1100],{"class":1071},[1050,6652,2866],{"class":2099},[1050,6654,1100],{"class":1071},[1050,6656,6657],{"class":2099}," timestamp",[1050,6659,2016],{"class":1071},[1050,6661,6663,6665,6668],{"class":1052,"line":6662},435,[1050,6664,2113],{"class":1214},[1050,6666,6667],{"class":1218},"Create hash value for token generation",[1050,6669,1222],{"class":1214},[1050,6671,6673],{"class":1052,"line":6672},436,[1050,6674,2124],{"class":1067},[1050,6676,6678],{"class":1052,"line":6677},437,[1050,6679,6680],{"class":1056},"                # Include additional user data for security\n",[1050,6682,6684,6687,6689,6692,6695,6697,6699,6702,6705,6708,6711,6713,6715,6717,6719,6722,6724,6727,6729,6732,6734,6737,6739,6741],{"class":1052,"line":6683},438,[1050,6685,6686],{"class":1067},"                login_timestamp ",[1050,6688,1182],{"class":1071},[1050,6690,6691],{"class":1291}," ''",[1050,6693,6694],{"class":1063}," if",[1050,6696,2866],{"class":1067},[1050,6698,1072],{"class":1071},[1050,6700,6701],{"class":1824},"last_login",[1050,6703,6704],{"class":2133}," is",[1050,6706,6707],{"class":2763}," None",[1050,6709,6710],{"class":1063}," else",[1050,6712,2866],{"class":1067},[1050,6714,1072],{"class":1071},[1050,6716,6701],{"class":1824},[1050,6718,1072],{"class":1071},[1050,6720,6721],{"class":1185},"replace",[1050,6723,1607],{"class":1071},[1050,6725,6726],{"class":2983},"microsecond",[1050,6728,1182],{"class":1071},[1050,6730,6731],{"class":1437},"0",[1050,6733,1100],{"class":1071},[1050,6735,6736],{"class":2983}," tzinfo",[1050,6738,1182],{"class":1071},[1050,6740,4022],{"class":2763},[1050,6742,1128],{"class":1071},[1050,6744,6746],{"class":1052,"line":6745},439,[1050,6747,2124],{"class":1067},[1050,6749,6751,6753],{"class":1052,"line":6750},440,[1050,6752,2332],{"class":1063},[1050,6754,1091],{"class":1071},[1050,6756,6758,6761,6763,6765,6767,6770,6772,6774,6776,6778,6780,6782,6785,6787,6790,6792,6794],{"class":1052,"line":6757},441,[1050,6759,6760],{"class":1237},"                    str",[1050,6762,1607],{"class":1071},[1050,6764,2828],{"class":1185},[1050,6766,1072],{"class":1071},[1050,6768,6769],{"class":1824},"pk",[1050,6771,5442],{"class":1071},[1050,6773,2633],{"class":2133},[1050,6775,2866],{"class":1067},[1050,6777,1072],{"class":1071},[1050,6779,2195],{"class":1824},[1050,6781,2633],{"class":2133},[1050,6783,6784],{"class":1237}," str",[1050,6786,1607],{"class":1071},[1050,6788,6789],{"class":1185},"login_timestamp",[1050,6791,5442],{"class":1071},[1050,6793,2633],{"class":2133},[1050,6795,6796],{"class":1067}," \n",[1050,6798,6800,6802,6804,6807,6809,6811,6813,6815,6817,6819,6821],{"class":1052,"line":6799},442,[1050,6801,6760],{"class":1237},[1050,6803,1607],{"class":1071},[1050,6805,6806],{"class":1185},"timestamp",[1050,6808,5442],{"class":1071},[1050,6810,2633],{"class":2133},[1050,6812,6784],{"class":1237},[1050,6814,1607],{"class":1071},[1050,6816,2828],{"class":1185},[1050,6818,1072],{"class":1071},[1050,6820,3581],{"class":1824},[1050,6822,1128],{"class":1071},[1050,6824,6826],{"class":1052,"line":6825},443,[1050,6827,4632],{"class":1071},[1050,6829,6831],{"class":1052,"line":6830},444,[1050,6832,1416],{"class":1067},[1050,6834,6836,6838,6841,6843,6845,6847,6849,6851,6854],{"class":1052,"line":6835},445,[1050,6837,2085],{"class":1200},[1050,6839,6840],{"class":1247}," check_token",[1050,6842,1607],{"class":1071},[1050,6844,2094],{"class":2093},[1050,6846,1100],{"class":1071},[1050,6848,2866],{"class":2099},[1050,6850,1100],{"class":1071},[1050,6852,6853],{"class":2099}," token",[1050,6855,2016],{"class":1071},[1050,6857,6859,6861,6864],{"class":1052,"line":6858},446,[1050,6860,2113],{"class":1214},[1050,6862,6863],{"class":1218},"Check if token is valid with additional security checks",[1050,6865,1222],{"class":1214},[1050,6867,6869],{"class":1052,"line":6868},447,[1050,6870,2124],{"class":1067},[1050,6872,6874],{"class":1052,"line":6873},448,[1050,6875,6876],{"class":1056},"                # Check if user is active\n",[1050,6878,6880,6882,6884,6886,6888,6891],{"class":1052,"line":6879},449,[1050,6881,2130],{"class":1063},[1050,6883,2134],{"class":2133},[1050,6885,2866],{"class":1067},[1050,6887,1072],{"class":1071},[1050,6889,6890],{"class":1824},"is_active",[1050,6892,1208],{"class":1071},[1050,6894,6896,6898],{"class":1052,"line":6895},450,[1050,6897,3008],{"class":1063},[1050,6899,2764],{"class":2763},[1050,6901,6903],{"class":1052,"line":6902},451,[1050,6904,2124],{"class":1067},[1050,6906,6908],{"class":1052,"line":6907},452,[1050,6909,6910],{"class":1056},"                # Check token age (24 hours max)\n",[1050,6912,6914,6916,6918,6921,6924,6927,6929,6931,6933,6935],{"class":1052,"line":6913},453,[1050,6915,2130],{"class":1063},[1050,6917,2134],{"class":2133},[1050,6919,6920],{"class":1237}," super",[1050,6922,6923],{"class":1071},"().",[1050,6925,6926],{"class":1185},"check_token",[1050,6928,1607],{"class":1071},[1050,6930,2828],{"class":1185},[1050,6932,1100],{"class":1071},[1050,6934,6853],{"class":1185},[1050,6936,2016],{"class":1071},[1050,6938,6940,6942],{"class":1052,"line":6939},454,[1050,6941,3008],{"class":1063},[1050,6943,2764],{"class":2763},[1050,6945,6947],{"class":1052,"line":6946},455,[1050,6948,2124],{"class":1067},[1050,6950,6952],{"class":1052,"line":6951},456,[1050,6953,6954],{"class":1056},"                # Additional security: check if password was changed after token generation\n",[1050,6956,6958],{"class":1052,"line":6957},457,[1050,6959,6960],{"class":1056},"                # This would require storing token generation time\n",[1050,6962,6964],{"class":1052,"line":6963},458,[1050,6965,2124],{"class":1067},[1050,6967,6969,6971],{"class":1052,"line":6968},459,[1050,6970,2332],{"class":1063},[1050,6972,6973],{"class":2763}," True\n",[1050,6975,6977],{"class":1052,"line":6976},460,[1050,6978,1268],{"class":1067},[1050,6980,6982],{"class":1052,"line":6981},461,[1050,6983,6984],{"class":1056},"        # Custom token generator with shorter expiry\n",[1050,6986,6988,6990,6993,6995,6997],{"class":1052,"line":6987},462,[1050,6989,2004],{"class":1200},[1050,6991,6992],{"class":1204}," ShortLivedTokenGenerator",[1050,6994,1607],{"class":1071},[1050,6996,6619],{"class":2012},[1050,6998,2016],{"class":1071},[1050,7000,7002,7004,7007],{"class":1052,"line":7001},463,[1050,7003,2841],{"class":1214},[1050,7005,7006],{"class":1218},"Token generator with shorter expiry time",[1050,7008,1222],{"class":1214},[1050,7010,7012],{"class":1052,"line":7011},464,[1050,7013,1416],{"class":1067},[1050,7015,7017,7019,7022,7024,7026,7028,7031],{"class":1052,"line":7016},465,[1050,7018,2085],{"class":1200},[1050,7020,7021],{"class":1247}," _num_seconds",[1050,7023,1607],{"class":1071},[1050,7025,2094],{"class":2093},[1050,7027,1100],{"class":1071},[1050,7029,7030],{"class":2099}," dt",[1050,7032,2016],{"class":1071},[1050,7034,7036,7038,7041],{"class":1052,"line":7035},466,[1050,7037,2113],{"class":1214},[1050,7039,7040],{"class":1218},"Return number of seconds since epoch",[1050,7042,1222],{"class":1214},[1050,7044,7046,7048,7051,7054,7057,7060,7063,7065,7068,7070,7073,7075,7077,7080,7083],{"class":1052,"line":7045},467,[1050,7047,2332],{"class":1063},[1050,7049,7050],{"class":1237}," int",[1050,7052,7053],{"class":1071},"((",[1050,7055,7056],{"class":1185},"dt ",[1050,7058,7059],{"class":2133},"-",[1050,7061,7062],{"class":1185}," datetime",[1050,7064,1607],{"class":1071},[1050,7066,7067],{"class":1437},"2001",[1050,7069,1100],{"class":1071},[1050,7071,7072],{"class":1437}," 1",[1050,7074,1100],{"class":1071},[1050,7076,7072],{"class":1437},[1050,7078,7079],{"class":1071},")).",[1050,7081,7082],{"class":1185},"total_seconds",[1050,7084,7085],{"class":1071},"())\n",[1050,7087,7089],{"class":1052,"line":7088},468,[1050,7090,1416],{"class":1067},[1050,7092,7094,7096,7099,7101,7103,7105,7107,7109,7111,7113,7116,7118,7121],{"class":1052,"line":7093},469,[1050,7095,2085],{"class":1200},[1050,7097,7098],{"class":1247}," _make_token_with_timestamp",[1050,7100,1607],{"class":1071},[1050,7102,2094],{"class":2093},[1050,7104,1100],{"class":1071},[1050,7106,2866],{"class":2099},[1050,7108,1100],{"class":1071},[1050,7110,6657],{"class":2099},[1050,7112,1100],{"class":1071},[1050,7114,7115],{"class":2099}," legacy",[1050,7117,1182],{"class":2133},[1050,7119,7120],{"class":2763},"False",[1050,7122,2016],{"class":1071},[1050,7124,7126,7128,7131],{"class":1052,"line":7125},470,[1050,7127,2113],{"class":1214},[1050,7129,7130],{"class":1218},"Generate token with custom timestamp handling",[1050,7132,1222],{"class":1214},[1050,7134,7136],{"class":1052,"line":7135},471,[1050,7137,2124],{"class":1067},[1050,7139,7141],{"class":1052,"line":7140},472,[1050,7142,7143],{"class":1056},"                # Reduce token lifetime to 1 hour (3600 seconds)\n",[1050,7145,7147,7150,7152,7155,7157,7160,7162,7164],{"class":1052,"line":7146},473,[1050,7148,7149],{"class":1067},"                ts_b36 ",[1050,7151,1182],{"class":1071},[1050,7153,7154],{"class":1067}," base36",[1050,7156,1072],{"class":1071},[1050,7158,7159],{"class":1185},"dumps",[1050,7161,1607],{"class":1071},[1050,7163,6806],{"class":1185},[1050,7165,1128],{"class":1071},[1050,7167,7169,7172,7174,7177],{"class":1052,"line":7168},474,[1050,7170,7171],{"class":1067},"                hash_string ",[1050,7173,1182],{"class":1071},[1050,7175,7176],{"class":1185}," salted_hmac",[1050,7178,4141],{"class":1071},[1050,7180,7182,7185,7187,7190],{"class":1052,"line":7181},475,[1050,7183,7184],{"class":2149},"                    self",[1050,7186,1072],{"class":1071},[1050,7188,7189],{"class":1824},"key_salt",[1050,7191,1111],{"class":1071},[1050,7193,7195,7197,7199,7202,7204,7206,7208,7210],{"class":1052,"line":7194},476,[1050,7196,7184],{"class":2149},[1050,7198,1072],{"class":1071},[1050,7200,7201],{"class":1185},"_make_hash_value",[1050,7203,1607],{"class":1071},[1050,7205,2828],{"class":1185},[1050,7207,1100],{"class":1071},[1050,7209,6657],{"class":1185},[1050,7211,3586],{"class":1071},[1050,7213,7215,7218,7220,7222,7224,7227],{"class":1052,"line":7214},477,[1050,7216,7217],{"class":2983},"                    secret",[1050,7219,1182],{"class":1071},[1050,7221,2094],{"class":2149},[1050,7223,1072],{"class":1071},[1050,7225,7226],{"class":1824},"secret",[1050,7228,1111],{"class":1071},[1050,7230,7232,7235,7237,7239,7241,7243],{"class":1052,"line":7231},478,[1050,7233,7234],{"class":2983},"                    algorithm",[1050,7236,1182],{"class":1071},[1050,7238,2094],{"class":2149},[1050,7240,1072],{"class":1071},[1050,7242,1825],{"class":1824},[1050,7244,1111],{"class":1071},[1050,7246,7248,7251,7254,7257,7260],{"class":1052,"line":7247},479,[1050,7249,7250],{"class":1071},"                ).",[1050,7252,7253],{"class":1185},"hexdigest",[1050,7255,7256],{"class":1071},"()[::",[1050,7258,7259],{"class":1437},"2",[1050,7261,4819],{"class":1071},[1050,7263,7265],{"class":1052,"line":7264},480,[1050,7266,2124],{"class":1067},[1050,7268,7270,7272,7274,7276,7278,7281,7283,7285,7287,7290,7292],{"class":1052,"line":7269},481,[1050,7271,2332],{"class":1063},[1050,7273,2179],{"class":1200},[1050,7275,1644],{"class":1295},[1050,7277,1636],{"class":1635},[1050,7279,7280],{"class":1067},"ts_b36",[1050,7282,1641],{"class":1635},[1050,7284,7059],{"class":1295},[1050,7286,1636],{"class":1635},[1050,7288,7289],{"class":1067},"hash_string",[1050,7291,1641],{"class":1635},[1050,7293,1593],{"class":1295},[1050,7295,7297],{"class":1052,"line":7296},482,[1050,7298,1268],{"class":1067},[1050,7300,7302,7304,7306,7308],{"class":1052,"line":7301},483,[1050,7303,1530],{"class":1063},[1050,7305,6614],{"class":1067},[1050,7307,1100],{"class":1071},[1050,7309,7310],{"class":1067}," ShortLivedTokenGenerator\n",[1050,7312,7314],{"class":1052,"line":7313},484,[1050,7315,1228],{"class":1067},[1050,7317,7319,7321],{"class":1052,"line":7318},485,[1050,7320,1234],{"class":1071},[1050,7322,1238],{"class":1237},[1050,7324,7326,7328,7331],{"class":1052,"line":7325},486,[1050,7327,1244],{"class":1200},[1050,7329,7330],{"class":1247}," password_reset_rate_limiting",[1050,7332,1251],{"class":1071},[1050,7334,7336,7338,7341],{"class":1052,"line":7335},487,[1050,7337,1257],{"class":1214},[1050,7339,7340],{"class":1218},"Implement rate limiting for password reset requests",[1050,7342,1222],{"class":1214},[1050,7344,7346],{"class":1052,"line":7345},488,[1050,7347,1268],{"class":1067},[1050,7349,7351,7353,7355,7357,7359,7361,7364,7366],{"class":1052,"line":7350},489,[1050,7352,1957],{"class":1063},[1050,7354,1068],{"class":1067},[1050,7356,1072],{"class":1071},[1050,7358,3831],{"class":1067},[1050,7360,1072],{"class":1071},[1050,7362,7363],{"class":1067},"cache ",[1050,7365,1088],{"class":1063},[1050,7367,7368],{"class":1067}," cache\n",[1050,7370,7372,7374,7376,7378,7381,7383],{"class":1052,"line":7371},490,[1050,7373,1957],{"class":1063},[1050,7375,1068],{"class":1067},[1050,7377,1072],{"class":1071},[1050,7379,7380],{"class":1067},"http ",[1050,7382,1088],{"class":1063},[1050,7384,7385],{"class":1067}," HttpResponseTooManyRequests\n",[1050,7387,7389],{"class":1052,"line":7388},491,[1050,7390,1268],{"class":1067},[1050,7392,7394,7396,7399,7401,7403,7405,7408,7410,7413,7415,7418,7420,7423],{"class":1052,"line":7393},492,[1050,7395,2820],{"class":1200},[1050,7397,7398],{"class":1247}," rate_limit_password_reset",[1050,7400,1607],{"class":1071},[1050,7402,3581],{"class":2099},[1050,7404,1100],{"class":1071},[1050,7406,7407],{"class":2099}," max_attempts",[1050,7409,1182],{"class":2133},[1050,7411,7412],{"class":1437},"3",[1050,7414,1100],{"class":1071},[1050,7416,7417],{"class":2099}," window",[1050,7419,1182],{"class":2133},[1050,7421,7422],{"class":1437},"3600",[1050,7424,2016],{"class":1071},[1050,7426,7428,7430,7433],{"class":1052,"line":7427},493,[1050,7429,2841],{"class":1214},[1050,7431,7432],{"class":1218},"Rate limit password reset attempts",[1050,7434,1222],{"class":1214},[1050,7436,7438],{"class":1052,"line":7437},494,[1050,7439,1416],{"class":1067},[1050,7441,7443,7446,7448,7450,7453,7455,7457,7459],{"class":1052,"line":7442},495,[1050,7444,7445],{"class":1067},"            cache_key ",[1050,7447,1182],{"class":1071},[1050,7449,2179],{"class":1200},[1050,7451,7452],{"class":1295},"\"password_reset_",[1050,7454,1636],{"class":1635},[1050,7456,3581],{"class":1067},[1050,7458,1641],{"class":1635},[1050,7460,1593],{"class":1295},[1050,7462,7464,7467,7469,7472,7474,7477,7479,7482,7484,7487],{"class":1052,"line":7463},496,[1050,7465,7466],{"class":1067},"            attempts ",[1050,7468,1182],{"class":1071},[1050,7470,7471],{"class":1067}," cache",[1050,7473,1072],{"class":1071},[1050,7475,7476],{"class":1185},"get",[1050,7478,1607],{"class":1071},[1050,7480,7481],{"class":1185},"cache_key",[1050,7483,1100],{"class":1071},[1050,7485,7486],{"class":1437}," 0",[1050,7488,1128],{"class":1071},[1050,7490,7492],{"class":1052,"line":7491},497,[1050,7493,1416],{"class":1067},[1050,7495,7497,7499,7502,7504,7506],{"class":1052,"line":7496},498,[1050,7498,2863],{"class":1063},[1050,7500,7501],{"class":1067}," attempts ",[1050,7503,5775],{"class":2133},[1050,7505,7407],{"class":1067},[1050,7507,1208],{"class":1071},[1050,7509,7511,7513,7515,7517,7519,7522,7524,7527,7530,7533,7535],{"class":1052,"line":7510},499,[1050,7512,2332],{"class":1063},[1050,7514,3162],{"class":2763},[1050,7516,1100],{"class":1071},[1050,7518,2179],{"class":1200},[1050,7520,7521],{"class":1295},"\"Too many password reset attempts. Try again in ",[1050,7523,1636],{"class":1635},[1050,7525,7526],{"class":1067},"window",[1050,7528,7529],{"class":2133},"//",[1050,7531,7532],{"class":1437},"60",[1050,7534,1641],{"class":1635},[1050,7536,7537],{"class":1295}," minutes.\"\n",[1050,7539,7541],{"class":1052,"line":7540},500,[1050,7542,1416],{"class":1067},[1050,7544,7546],{"class":1052,"line":7545},501,[1050,7547,7548],{"class":1056},"            # Increment attempts\n",[1050,7550,7552,7555,7557,7560,7562,7564,7566,7568,7571,7573,7575,7577],{"class":1052,"line":7551},502,[1050,7553,7554],{"class":1067},"            cache",[1050,7556,1072],{"class":1071},[1050,7558,7559],{"class":1185},"set",[1050,7561,1607],{"class":1071},[1050,7563,7481],{"class":1185},[1050,7565,1100],{"class":1071},[1050,7567,7501],{"class":1185},[1050,7569,7570],{"class":2133},"+",[1050,7572,7072],{"class":1437},[1050,7574,1100],{"class":1071},[1050,7576,7417],{"class":1185},[1050,7578,1128],{"class":1071},[1050,7580,7582],{"class":1052,"line":7581},503,[1050,7583,1416],{"class":1067},[1050,7585,7587,7589,7591,7593,7595,7598,7600,7603,7605,7607,7609,7611,7613],{"class":1052,"line":7586},504,[1050,7588,3159],{"class":1063},[1050,7590,3011],{"class":2763},[1050,7592,1100],{"class":1071},[1050,7594,2179],{"class":1200},[1050,7596,7597],{"class":1295},"\"Password reset email sent. ",[1050,7599,1636],{"class":1635},[1050,7601,7602],{"class":1067},"max_attempts ",[1050,7604,7059],{"class":2133},[1050,7606,7501],{"class":1067},[1050,7608,7059],{"class":2133},[1050,7610,7072],{"class":1437},[1050,7612,1641],{"class":1635},[1050,7614,7615],{"class":1295}," attempts remaining.\"\n",[1050,7617,7619],{"class":1052,"line":7618},505,[1050,7620,1268],{"class":1067},[1050,7622,7624,7626,7629,7631,7634],{"class":1052,"line":7623},506,[1050,7625,2820],{"class":1200},[1050,7627,7628],{"class":1247}," password_reset_view_with_rate_limiting",[1050,7630,1607],{"class":1071},[1050,7632,7633],{"class":2099},"request",[1050,7635,2016],{"class":1071},[1050,7637,7639,7641,7644],{"class":1052,"line":7638},507,[1050,7640,2841],{"class":1214},[1050,7642,7643],{"class":1218},"Password reset view with rate limiting",[1050,7645,1222],{"class":1214},[1050,7647,7649],{"class":1052,"line":7648},508,[1050,7650,1416],{"class":1067},[1050,7652,7654,7656,7659,7661,7664,7667,7669,7672,7674],{"class":1052,"line":7653},509,[1050,7655,2863],{"class":1063},[1050,7657,7658],{"class":1067}," request",[1050,7660,1072],{"class":1071},[1050,7662,7663],{"class":1824},"method",[1050,7665,7666],{"class":2133}," ==",[1050,7668,2636],{"class":1291},[1050,7670,7671],{"class":1295},"POST",[1050,7673,1299],{"class":1291},[1050,7675,1208],{"class":1071},[1050,7677,7679,7682,7684,7686,7688,7691,7693,7695,7697,7699,7701,7703],{"class":1052,"line":7678},510,[1050,7680,7681],{"class":1067},"                email ",[1050,7683,1182],{"class":1071},[1050,7685,7658],{"class":1067},[1050,7687,1072],{"class":1071},[1050,7689,7671],{"class":7690},"sFGJz",[1050,7692,1072],{"class":1071},[1050,7694,7476],{"class":1185},[1050,7696,1607],{"class":1071},[1050,7698,1299],{"class":1291},[1050,7700,3581],{"class":1295},[1050,7702,1299],{"class":1291},[1050,7704,1128],{"class":1071},[1050,7706,7708],{"class":1052,"line":7707},511,[1050,7709,2124],{"class":1067},[1050,7711,7713],{"class":1052,"line":7712},512,[1050,7714,7715],{"class":1056},"                # Check rate limit\n",[1050,7717,7719,7722,7724,7727,7729,7731,7733,7735],{"class":1052,"line":7718},513,[1050,7720,7721],{"class":1067},"                allowed",[1050,7723,1100],{"class":1071},[1050,7725,7726],{"class":1067}," message ",[1050,7728,1182],{"class":1071},[1050,7730,7398],{"class":1185},[1050,7732,1607],{"class":1071},[1050,7734,3581],{"class":1185},[1050,7736,1128],{"class":1071},[1050,7738,7740],{"class":1052,"line":7739},514,[1050,7741,2124],{"class":1067},[1050,7743,7745,7747,7749,7752],{"class":1052,"line":7744},515,[1050,7746,2130],{"class":1063},[1050,7748,2134],{"class":2133},[1050,7750,7751],{"class":1067}," allowed",[1050,7753,1208],{"class":1071},[1050,7755,7757,7759,7762,7764,7767],{"class":1052,"line":7756},516,[1050,7758,3008],{"class":1063},[1050,7760,7761],{"class":1185}," HttpResponseTooManyRequests",[1050,7763,1607],{"class":1071},[1050,7765,7766],{"class":1185},"message",[1050,7768,1128],{"class":1071},[1050,7770,7772],{"class":1052,"line":7771},517,[1050,7773,2124],{"class":1067},[1050,7775,7777],{"class":1052,"line":7776},518,[1050,7778,7779],{"class":1056},"                # Proceed with password reset\n",[1050,7781,7783,7786],{"class":1052,"line":7782},519,[1050,7784,7785],{"class":1063},"                try",[1050,7787,1208],{"class":1071},[1050,7789,7791,7794,7796,7798,7800,7802,7804,7806,7808,7810,7812,7814],{"class":1052,"line":7790},520,[1050,7792,7793],{"class":1067},"                    user ",[1050,7795,1182],{"class":1071},[1050,7797,3248],{"class":1067},[1050,7799,1072],{"class":1071},[1050,7801,3253],{"class":1824},[1050,7803,1072],{"class":1071},[1050,7805,7476],{"class":1185},[1050,7807,1607],{"class":1071},[1050,7809,3581],{"class":2983},[1050,7811,1182],{"class":1071},[1050,7813,3581],{"class":1185},[1050,7815,1128],{"class":1071},[1050,7817,7819],{"class":1052,"line":7818},521,[1050,7820,7821],{"class":1056},"                    # Send password reset email\n",[1050,7823,7825,7828,7830,7833,7835,7837,7839,7841,7844,7846],{"class":1052,"line":7824},522,[1050,7826,7827],{"class":1067},"                    messages",[1050,7829,1072],{"class":1071},[1050,7831,7832],{"class":1185},"success",[1050,7834,1607],{"class":1071},[1050,7836,7633],{"class":1185},[1050,7838,1100],{"class":1071},[1050,7840,1587],{"class":1291},[1050,7842,7843],{"class":1295},"Password reset email sent.",[1050,7845,1644],{"class":1291},[1050,7847,1128],{"class":1071},[1050,7849,7851,7854,7856,7858,7861],{"class":1052,"line":7850},523,[1050,7852,7853],{"class":1063},"                except",[1050,7855,3248],{"class":1067},[1050,7857,1072],{"class":1071},[1050,7859,7860],{"class":1824},"DoesNotExist",[1050,7862,1208],{"class":1071},[1050,7864,7866],{"class":1052,"line":7865},524,[1050,7867,7868],{"class":1056},"                    # Don't reveal if email exists\n",[1050,7870,7872,7874,7876,7878,7880,7882,7884,7886,7889,7891],{"class":1052,"line":7871},525,[1050,7873,7827],{"class":1067},[1050,7875,1072],{"class":1071},[1050,7877,7832],{"class":1185},[1050,7879,1607],{"class":1071},[1050,7881,7633],{"class":1185},[1050,7883,1100],{"class":1071},[1050,7885,1587],{"class":1291},[1050,7887,7888],{"class":1295},"If the email exists, a reset link has been sent.",[1050,7890,1644],{"class":1291},[1050,7892,1128],{"class":1071},[1050,7894,7896],{"class":1052,"line":7895},526,[1050,7897,1416],{"class":1067},[1050,7899,7901,7903,7906,7908,7910,7912,7914,7917,7919],{"class":1052,"line":7900},527,[1050,7902,3159],{"class":1063},[1050,7904,7905],{"class":1185}," render",[1050,7907,1607],{"class":1071},[1050,7909,7633],{"class":1185},[1050,7911,1100],{"class":1071},[1050,7913,2636],{"class":1291},[1050,7915,7916],{"class":1295},"password_reset.html",[1050,7918,1299],{"class":1291},[1050,7920,1128],{"class":1071},[1050,7922,7924],{"class":1052,"line":7923},528,[1050,7925,1268],{"class":1067},[1050,7927,7929,7931,7933,7935],{"class":1052,"line":7928},529,[1050,7930,1530],{"class":1063},[1050,7932,7398],{"class":1067},[1050,7934,1100],{"class":1071},[1050,7936,7937],{"class":1067}," password_reset_view_with_rate_limiting\n",[1050,7939,7941],{"class":1052,"line":7940},530,[1050,7942,1228],{"class":1067},[1050,7944,7946,7948],{"class":1052,"line":7945},531,[1050,7947,1234],{"class":1071},[1050,7949,1238],{"class":1237},[1050,7951,7953,7955,7958],{"class":1052,"line":7952},532,[1050,7954,1244],{"class":1200},[1050,7956,7957],{"class":1247}," secure_password_reset_workflow",[1050,7959,1251],{"class":1071},[1050,7961,7963,7965,7968],{"class":1052,"line":7962},533,[1050,7964,1257],{"class":1214},[1050,7966,7967],{"class":1218},"Implement complete secure password reset workflow",[1050,7969,1222],{"class":1214},[1050,7971,7973],{"class":1052,"line":7972},534,[1050,7974,1268],{"class":1067},[1050,7976,7978,7980,7982,7984,7986,7988,7991,7993],{"class":1052,"line":7977},535,[1050,7979,1957],{"class":1063},[1050,7981,1068],{"class":1067},[1050,7983,1072],{"class":1071},[1050,7985,3831],{"class":1067},[1050,7987,1072],{"class":1071},[1050,7989,7990],{"class":1067},"mail ",[1050,7992,1088],{"class":1063},[1050,7994,7995],{"class":1067}," send_mail\n",[1050,7997,7999,8001,8003,8005,8008,8010],{"class":1052,"line":7998},536,[1050,8000,1957],{"class":1063},[1050,8002,1068],{"class":1067},[1050,8004,1072],{"class":1071},[1050,8006,8007],{"class":1067},"urls ",[1050,8009,1088],{"class":1063},[1050,8011,8012],{"class":1067}," reverse\n",[1050,8014,8016,8018,8020,8022,8024,8026,8029,8031,8034,8036],{"class":1052,"line":8015},537,[1050,8017,1957],{"class":1063},[1050,8019,1068],{"class":1067},[1050,8021,1072],{"class":1071},[1050,8023,1075],{"class":1067},[1050,8025,1072],{"class":1071},[1050,8027,8028],{"class":1067},"sites",[1050,8030,1072],{"class":1071},[1050,8032,8033],{"class":1067},"shortcuts ",[1050,8035,1088],{"class":1063},[1050,8037,8038],{"class":1067}," get_current_site\n",[1050,8040,8042],{"class":1052,"line":8041},538,[1050,8043,1268],{"class":1067},[1050,8045,8047,8049,8052,8054,8056,8058,8061],{"class":1052,"line":8046},539,[1050,8048,2820],{"class":1200},[1050,8050,8051],{"class":1247}," initiate_password_reset",[1050,8053,1607],{"class":1071},[1050,8055,7633],{"class":2099},[1050,8057,1100],{"class":1071},[1050,8059,8060],{"class":2099}," email",[1050,8062,2016],{"class":1071},[1050,8064,8066,8068,8071],{"class":1052,"line":8065},540,[1050,8067,2841],{"class":1214},[1050,8069,8070],{"class":1218},"Initiate password reset process",[1050,8072,1222],{"class":1214},[1050,8074,8076],{"class":1052,"line":8075},541,[1050,8077,1416],{"class":1067},[1050,8079,8081,8083],{"class":1052,"line":8080},542,[1050,8082,6160],{"class":1063},[1050,8084,1208],{"class":1071},[1050,8086,8088,8091,8093,8095,8097,8099,8101,8103,8105,8107,8109,8111,8113,8116,8118,8121],{"class":1052,"line":8087},543,[1050,8089,8090],{"class":1067},"                user ",[1050,8092,1182],{"class":1071},[1050,8094,3248],{"class":1067},[1050,8096,1072],{"class":1071},[1050,8098,3253],{"class":1824},[1050,8100,1072],{"class":1071},[1050,8102,7476],{"class":1185},[1050,8104,1607],{"class":1071},[1050,8106,3581],{"class":2983},[1050,8108,1182],{"class":1071},[1050,8110,3581],{"class":1185},[1050,8112,1100],{"class":1071},[1050,8114,8115],{"class":2983}," is_active",[1050,8117,1182],{"class":1071},[1050,8119,8120],{"class":2763},"True",[1050,8122,1128],{"class":1071},[1050,8124,8126,8128,8130,8132,8134],{"class":1052,"line":8125},544,[1050,8127,6213],{"class":1063},[1050,8129,3248],{"class":1067},[1050,8131,1072],{"class":1071},[1050,8133,7860],{"class":1824},[1050,8135,1208],{"class":1071},[1050,8137,8139],{"class":1052,"line":8138},545,[1050,8140,8141],{"class":1056},"                # Don't reveal if user exists\n",[1050,8143,8145,8147,8149,8151,8153,8155],{"class":1052,"line":8144},546,[1050,8146,2332],{"class":1063},[1050,8148,3011],{"class":2763},[1050,8150,1100],{"class":1071},[1050,8152,1587],{"class":1291},[1050,8154,7888],{"class":1295},[1050,8156,1593],{"class":1291},[1050,8158,8160],{"class":1052,"line":8159},547,[1050,8161,1416],{"class":1067},[1050,8163,8165],{"class":1052,"line":8164},548,[1050,8166,8167],{"class":1056},"            # Generate token\n",[1050,8169,8171,8174,8176,8178],{"class":1052,"line":8170},549,[1050,8172,8173],{"class":1067},"            token_generator ",[1050,8175,1182],{"class":1071},[1050,8177,6614],{"class":1185},[1050,8179,1189],{"class":1071},[1050,8181,8183,8186,8188,8191,8193,8196,8198,8200],{"class":1052,"line":8182},550,[1050,8184,8185],{"class":1067},"            token ",[1050,8187,1182],{"class":1071},[1050,8189,8190],{"class":1067}," token_generator",[1050,8192,1072],{"class":1071},[1050,8194,8195],{"class":1185},"make_token",[1050,8197,1607],{"class":1071},[1050,8199,2828],{"class":1185},[1050,8201,1128],{"class":1071},[1050,8203,8205],{"class":1052,"line":8204},551,[1050,8206,1416],{"class":1067},[1050,8208,8210],{"class":1052,"line":8209},552,[1050,8211,8212],{"class":1056},"            # Create reset URL\n",[1050,8214,8216,8219,8221,8224,8226,8228],{"class":1052,"line":8215},553,[1050,8217,8218],{"class":1067},"            current_site ",[1050,8220,1182],{"class":1071},[1050,8222,8223],{"class":1185}," get_current_site",[1050,8225,1607],{"class":1071},[1050,8227,7633],{"class":1185},[1050,8229,1128],{"class":1071},[1050,8231,8233,8236,8238,8240,8242,8245],{"class":1052,"line":8232},554,[1050,8234,8235],{"class":1067},"            reset_url ",[1050,8237,1182],{"class":1071},[1050,8239,7658],{"class":1067},[1050,8241,1072],{"class":1071},[1050,8243,8244],{"class":1185},"build_absolute_uri",[1050,8246,4141],{"class":1071},[1050,8248,8250,8253,8255,8257,8260,8262,8264,8267],{"class":1052,"line":8249},555,[1050,8251,8252],{"class":1185},"                reverse",[1050,8254,1607],{"class":1071},[1050,8256,1299],{"class":1291},[1050,8258,8259],{"class":1295},"password_reset_confirm",[1050,8261,1299],{"class":1291},[1050,8263,1100],{"class":1071},[1050,8265,8266],{"class":2983}," kwargs",[1050,8268,8269],{"class":1071},"={\n",[1050,8271,8273,8275,8278,8280,8282,8285,8287,8290,8292,8294,8296,8298],{"class":1052,"line":8272},556,[1050,8274,2597],{"class":1291},[1050,8276,8277],{"class":1295},"uidb64",[1050,8279,1299],{"class":1291},[1050,8281,1405],{"class":1071},[1050,8283,8284],{"class":1185}," urlsafe_base64_encode",[1050,8286,1607],{"class":1071},[1050,8288,8289],{"class":1185},"force_bytes",[1050,8291,1607],{"class":1071},[1050,8293,2828],{"class":1185},[1050,8295,1072],{"class":1071},[1050,8297,6769],{"class":1824},[1050,8299,8300],{"class":1071},")),\n",[1050,8302,8304,8306,8309,8311,8313,8315],{"class":1052,"line":8303},557,[1050,8305,2597],{"class":1291},[1050,8307,8308],{"class":1295},"token",[1050,8310,1299],{"class":1291},[1050,8312,1405],{"class":1071},[1050,8314,6853],{"class":1185},[1050,8316,1111],{"class":1071},[1050,8318,8320],{"class":1052,"line":8319},558,[1050,8321,8322],{"class":1071},"                })\n",[1050,8324,8326],{"class":1052,"line":8325},559,[1050,8327,6070],{"class":1071},[1050,8329,8331],{"class":1052,"line":8330},560,[1050,8332,1416],{"class":1067},[1050,8334,8336],{"class":1052,"line":8335},561,[1050,8337,8338],{"class":1056},"            # Send email\n",[1050,8340,8342,8345,8347,8349,8352,8354,8357,8359,8362,8364],{"class":1052,"line":8341},562,[1050,8343,8344],{"class":1067},"            subject ",[1050,8346,1182],{"class":1071},[1050,8348,2179],{"class":1200},[1050,8350,8351],{"class":1295},"\"Password Reset - ",[1050,8353,1636],{"class":1635},[1050,8355,8356],{"class":1067},"current_site",[1050,8358,1072],{"class":1071},[1050,8360,8361],{"class":1824},"name",[1050,8363,1641],{"class":1635},[1050,8365,1593],{"class":1295},[1050,8367,8369,8372,8374,8376],{"class":1052,"line":8368},563,[1050,8370,8371],{"class":1067},"            message ",[1050,8373,1182],{"class":1071},[1050,8375,2179],{"class":1200},[1050,8377,1222],{"class":1295},[1050,8379,8381,8384,8386,8388,8390,8393,8395,8398,8400,8402,8404,8406],{"class":1052,"line":8380},564,[1050,8382,8383],{"class":1295},"            Hello ",[1050,8385,1636],{"class":1635},[1050,8387,2828],{"class":1067},[1050,8389,1072],{"class":1071},[1050,8391,8392],{"class":1185},"get_full_name",[1050,8394,5118],{"class":1071},[1050,8396,8397],{"class":2133}," or",[1050,8399,2866],{"class":1067},[1050,8401,1072],{"class":1071},[1050,8403,3366],{"class":1824},[1050,8405,1641],{"class":1635},[1050,8407,1111],{"class":1295},[1050,8409,8411],{"class":1052,"line":8410},565,[1050,8412,1416],{"class":1295},[1050,8414,8416,8419,8421,8423,8425,8427,8429],{"class":1052,"line":8415},566,[1050,8417,8418],{"class":1295},"            You requested a password reset for your account at ",[1050,8420,1636],{"class":1635},[1050,8422,8356],{"class":1067},[1050,8424,1072],{"class":1071},[1050,8426,8361],{"class":1824},[1050,8428,1641],{"class":1635},[1050,8430,8431],{"class":1295},".\n",[1050,8433,8435],{"class":1052,"line":8434},567,[1050,8436,1416],{"class":1295},[1050,8438,8440],{"class":1052,"line":8439},568,[1050,8441,8442],{"class":1295},"            Please click the link below to reset your password:\n",[1050,8444,8446,8449,8452],{"class":1052,"line":8445},569,[1050,8447,8448],{"class":1635},"            {",[1050,8450,8451],{"class":1067},"reset_url",[1050,8453,8454],{"class":1635},"}\n",[1050,8456,8458],{"class":1052,"line":8457},570,[1050,8459,1416],{"class":1295},[1050,8461,8463],{"class":1052,"line":8462},571,[1050,8464,8465],{"class":1295},"            This link will expire in 24 hours.\n",[1050,8467,8469],{"class":1052,"line":8468},572,[1050,8470,1416],{"class":1295},[1050,8472,8474],{"class":1052,"line":8473},573,[1050,8475,8476],{"class":1295},"            If you didn't request this reset, please ignore this email.\n",[1050,8478,8480],{"class":1052,"line":8479},574,[1050,8481,1416],{"class":1295},[1050,8483,8485],{"class":1052,"line":8484},575,[1050,8486,8487],{"class":1295},"            Best regards,\n",[1050,8489,8491,8494,8496,8498,8500,8502,8504],{"class":1052,"line":8490},576,[1050,8492,8493],{"class":1295},"            The ",[1050,8495,1636],{"class":1635},[1050,8497,8356],{"class":1067},[1050,8499,1072],{"class":1071},[1050,8501,8361],{"class":1824},[1050,8503,1641],{"class":1635},[1050,8505,8506],{"class":1295}," Team\n",[1050,8508,8510],{"class":1052,"line":8509},577,[1050,8511,2022],{"class":1295},[1050,8513,8515],{"class":1052,"line":8514},578,[1050,8516,1416],{"class":1067},[1050,8518,8520,8523],{"class":1052,"line":8519},579,[1050,8521,8522],{"class":1185},"            send_mail",[1050,8524,4141],{"class":1071},[1050,8526,8528,8531],{"class":1052,"line":8527},580,[1050,8529,8530],{"class":1185},"                subject",[1050,8532,1111],{"class":1071},[1050,8534,8536,8539],{"class":1052,"line":8535},581,[1050,8537,8538],{"class":1185},"                message",[1050,8540,1111],{"class":1071},[1050,8542,8544,8547,8549,8552],{"class":1052,"line":8543},582,[1050,8545,8546],{"class":1185},"                settings",[1050,8548,1072],{"class":1071},[1050,8550,8551],{"class":7690},"DEFAULT_FROM_EMAIL",[1050,8553,1111],{"class":1071},[1050,8555,8557,8560,8562,8564,8566],{"class":1052,"line":8556},583,[1050,8558,8559],{"class":1071},"                [",[1050,8561,2828],{"class":1185},[1050,8563,1072],{"class":1071},[1050,8565,3581],{"class":1824},[1050,8567,8568],{"class":1071},"],\n",[1050,8570,8572,8575,8577,8579],{"class":1052,"line":8571},584,[1050,8573,8574],{"class":2983},"                fail_silently",[1050,8576,1182],{"class":1071},[1050,8578,7120],{"class":2763},[1050,8580,1111],{"class":1071},[1050,8582,8584],{"class":1052,"line":8583},585,[1050,8585,6070],{"class":1071},[1050,8587,8589],{"class":1052,"line":8588},586,[1050,8590,1416],{"class":1067},[1050,8592,8594],{"class":1052,"line":8593},587,[1050,8595,8596],{"class":1056},"            # Log password reset request\n",[1050,8598,8600,8603],{"class":1052,"line":8599},588,[1050,8601,8602],{"class":1063},"            import",[1050,8604,8605],{"class":1067}," logging\n",[1050,8607,8609,8612,8614,8617,8619,8622,8624,8628],{"class":1052,"line":8608},589,[1050,8610,8611],{"class":1067},"            logger ",[1050,8613,1182],{"class":1071},[1050,8615,8616],{"class":1067}," logging",[1050,8618,1072],{"class":1071},[1050,8620,8621],{"class":1185},"getLogger",[1050,8623,1607],{"class":1071},[1050,8625,8627],{"class":8626},"s131V","__name__",[1050,8629,1128],{"class":1071},[1050,8631,8633,8636,8638,8641,8643,8645,8648,8650,8652,8654,8656,8658,8660],{"class":1052,"line":8632},590,[1050,8634,8635],{"class":1067},"            logger",[1050,8637,1072],{"class":1071},[1050,8639,8640],{"class":1185},"info",[1050,8642,1607],{"class":1071},[1050,8644,1629],{"class":1200},[1050,8646,8647],{"class":1295},"\"Password reset requested for user: ",[1050,8649,1636],{"class":1635},[1050,8651,2828],{"class":1185},[1050,8653,1072],{"class":1071},[1050,8655,3366],{"class":1824},[1050,8657,1641],{"class":1635},[1050,8659,1644],{"class":1295},[1050,8661,1128],{"class":1071},[1050,8663,8665],{"class":1052,"line":8664},591,[1050,8666,1416],{"class":1067},[1050,8668,8670,8672,8674,8676,8678,8680],{"class":1052,"line":8669},592,[1050,8671,3159],{"class":1063},[1050,8673,3011],{"class":2763},[1050,8675,1100],{"class":1071},[1050,8677,1587],{"class":1291},[1050,8679,7843],{"class":1295},[1050,8681,1593],{"class":1291},[1050,8683,8685],{"class":1052,"line":8684},593,[1050,8686,1268],{"class":1067},[1050,8688,8690,8692,8695,8697,8699,8701,8703,8705,8708],{"class":1052,"line":8689},594,[1050,8691,2820],{"class":1200},[1050,8693,8694],{"class":1247}," confirm_password_reset",[1050,8696,1607],{"class":1071},[1050,8698,8277],{"class":2099},[1050,8700,1100],{"class":1071},[1050,8702,6853],{"class":2099},[1050,8704,1100],{"class":1071},[1050,8706,8707],{"class":2099}," new_password",[1050,8709,2016],{"class":1071},[1050,8711,8713,8715,8718],{"class":1052,"line":8712},595,[1050,8714,2841],{"class":1214},[1050,8716,8717],{"class":1218},"Confirm password reset and set new password",[1050,8719,1222],{"class":1214},[1050,8721,8723],{"class":1052,"line":8722},596,[1050,8724,1416],{"class":1067},[1050,8726,8728,8730],{"class":1052,"line":8727},597,[1050,8729,6160],{"class":1063},[1050,8731,1208],{"class":1071},[1050,8733,8735],{"class":1052,"line":8734},598,[1050,8736,8737],{"class":1056},"                # Decode user ID\n",[1050,8739,8741,8744,8746,8749,8751,8754,8756,8758],{"class":1052,"line":8740},599,[1050,8742,8743],{"class":1067},"                uid ",[1050,8745,1182],{"class":1071},[1050,8747,8748],{"class":1185}," force_str",[1050,8750,1607],{"class":1071},[1050,8752,8753],{"class":1185},"urlsafe_base64_decode",[1050,8755,1607],{"class":1071},[1050,8757,8277],{"class":1185},[1050,8759,4108],{"class":1071},[1050,8761,8763,8765,8767,8769,8771,8773,8775,8777,8779,8781,8783,8786],{"class":1052,"line":8762},600,[1050,8764,8090],{"class":1067},[1050,8766,1182],{"class":1071},[1050,8768,3248],{"class":1067},[1050,8770,1072],{"class":1071},[1050,8772,3253],{"class":1824},[1050,8774,1072],{"class":1071},[1050,8776,7476],{"class":1185},[1050,8778,1607],{"class":1071},[1050,8780,6769],{"class":2983},[1050,8782,1182],{"class":1071},[1050,8784,8785],{"class":1185},"uid",[1050,8787,1128],{"class":1071},[1050,8789,8791,8793,8795,8798,8800,8803,8805,8808,8810,8812,8814,8816],{"class":1052,"line":8790},601,[1050,8792,6213],{"class":1063},[1050,8794,3550],{"class":1071},[1050,8796,8797],{"class":1237},"TypeError",[1050,8799,1100],{"class":1071},[1050,8801,8802],{"class":1237}," ValueError",[1050,8804,1100],{"class":1071},[1050,8806,8807],{"class":1237}," OverflowError",[1050,8809,1100],{"class":1071},[1050,8811,3248],{"class":1067},[1050,8813,1072],{"class":1071},[1050,8815,7860],{"class":1824},[1050,8817,2016],{"class":1071},[1050,8819,8821,8823,8825,8827,8829,8832],{"class":1052,"line":8820},602,[1050,8822,2332],{"class":1063},[1050,8824,3162],{"class":2763},[1050,8826,1100],{"class":1071},[1050,8828,1587],{"class":1291},[1050,8830,8831],{"class":1295},"Invalid reset link.",[1050,8833,1593],{"class":1291},[1050,8835,8837],{"class":1052,"line":8836},603,[1050,8838,1416],{"class":1067},[1050,8840,8842],{"class":1052,"line":8841},604,[1050,8843,8844],{"class":1056},"            # Check token\n",[1050,8846,8848,8850,8852,8854],{"class":1052,"line":8847},605,[1050,8849,8173],{"class":1067},[1050,8851,1182],{"class":1071},[1050,8853,6614],{"class":1185},[1050,8855,1189],{"class":1071},[1050,8857,8859,8861,8863,8865,8867,8869,8871,8873,8875,8877],{"class":1052,"line":8858},606,[1050,8860,2863],{"class":1063},[1050,8862,2134],{"class":2133},[1050,8864,8190],{"class":1067},[1050,8866,1072],{"class":1071},[1050,8868,6926],{"class":1185},[1050,8870,1607],{"class":1071},[1050,8872,2828],{"class":1185},[1050,8874,1100],{"class":1071},[1050,8876,6853],{"class":1185},[1050,8878,2016],{"class":1071},[1050,8880,8882,8884,8886,8888,8890,8893],{"class":1052,"line":8881},607,[1050,8883,2332],{"class":1063},[1050,8885,3162],{"class":2763},[1050,8887,1100],{"class":1071},[1050,8889,1587],{"class":1291},[1050,8891,8892],{"class":1295},"Invalid or expired reset link.",[1050,8894,1593],{"class":1291},[1050,8896,8898],{"class":1052,"line":8897},608,[1050,8899,1416],{"class":1067},[1050,8901,8903],{"class":1052,"line":8902},609,[1050,8904,8905],{"class":1056},"            # Validate new password\n",[1050,8907,8909,8911],{"class":1052,"line":8908},610,[1050,8910,6160],{"class":1063},[1050,8912,1208],{"class":1071},[1050,8914,8916,8918,8920,8923,8925,8927],{"class":1052,"line":8915},611,[1050,8917,6168],{"class":1185},[1050,8919,1607],{"class":1071},[1050,8921,8922],{"class":1185},"new_password",[1050,8924,1100],{"class":1071},[1050,8926,2866],{"class":1185},[1050,8928,1128],{"class":1071},[1050,8930,8932,8934,8936,8938,8940],{"class":1052,"line":8931},612,[1050,8933,6213],{"class":1063},[1050,8935,6216],{"class":1067},[1050,8937,6219],{"class":1063},[1050,8939,6222],{"class":1067},[1050,8941,1208],{"class":1071},[1050,8943,8945,8947,8949,8951,8953,8955],{"class":1052,"line":8944},613,[1050,8946,2332],{"class":1063},[1050,8948,3162],{"class":2763},[1050,8950,1100],{"class":1071},[1050,8952,6222],{"class":1067},[1050,8954,1072],{"class":1071},[1050,8956,8957],{"class":1824},"messages\n",[1050,8959,8961],{"class":1052,"line":8960},614,[1050,8962,1416],{"class":1067},[1050,8964,8966],{"class":1052,"line":8965},615,[1050,8967,8968],{"class":1056},"            # Set new password\n",[1050,8970,8972,8975,8977,8979,8981,8983],{"class":1052,"line":8971},616,[1050,8973,8974],{"class":1067},"            user",[1050,8976,1072],{"class":1071},[1050,8978,2961],{"class":1185},[1050,8980,1607],{"class":1071},[1050,8982,8922],{"class":1185},[1050,8984,1128],{"class":1071},[1050,8986,8988,8990,8992,8994],{"class":1052,"line":8987},617,[1050,8989,8974],{"class":1067},[1050,8991,1072],{"class":1071},[1050,8993,2978],{"class":1185},[1050,8995,1189],{"class":1071},[1050,8997,8999],{"class":1052,"line":8998},618,[1050,9000,1416],{"class":1067},[1050,9002,9004],{"class":1052,"line":9003},619,[1050,9005,9006],{"class":1056},"            # Log successful password reset\n",[1050,9008,9010,9012],{"class":1052,"line":9009},620,[1050,9011,8602],{"class":1063},[1050,9013,8605],{"class":1067},[1050,9015,9017,9019,9021,9023,9025,9027,9029,9031],{"class":1052,"line":9016},621,[1050,9018,8611],{"class":1067},[1050,9020,1182],{"class":1071},[1050,9022,8616],{"class":1067},[1050,9024,1072],{"class":1071},[1050,9026,8621],{"class":1185},[1050,9028,1607],{"class":1071},[1050,9030,8627],{"class":8626},[1050,9032,1128],{"class":1071},[1050,9034,9036,9038,9040,9042,9044,9046,9049,9051,9053,9055,9057,9059,9061],{"class":1052,"line":9035},622,[1050,9037,8635],{"class":1067},[1050,9039,1072],{"class":1071},[1050,9041,8640],{"class":1185},[1050,9043,1607],{"class":1071},[1050,9045,1629],{"class":1200},[1050,9047,9048],{"class":1295},"\"Password reset completed for user: ",[1050,9050,1636],{"class":1635},[1050,9052,2828],{"class":1185},[1050,9054,1072],{"class":1071},[1050,9056,3366],{"class":1824},[1050,9058,1641],{"class":1635},[1050,9060,1644],{"class":1295},[1050,9062,1128],{"class":1071},[1050,9064,9066],{"class":1052,"line":9065},623,[1050,9067,1416],{"class":1067},[1050,9069,9071,9073,9075,9077,9079,9082],{"class":1052,"line":9070},624,[1050,9072,3159],{"class":1063},[1050,9074,3011],{"class":2763},[1050,9076,1100],{"class":1071},[1050,9078,1587],{"class":1291},[1050,9080,9081],{"class":1295},"Password reset successfully.",[1050,9083,1593],{"class":1291},[1050,9085,9087],{"class":1052,"line":9086},625,[1050,9088,1268],{"class":1067},[1050,9090,9092,9094,9096,9098],{"class":1052,"line":9091},626,[1050,9093,1530],{"class":1063},[1050,9095,8051],{"class":1067},[1050,9097,1100],{"class":1071},[1050,9099,9100],{"class":1067}," confirm_password_reset\n",[1050,9102,9104],{"class":1052,"line":9103},627,[1050,9105,1173],{"emptyLinePlaceholder":1172},[1050,9107,9109],{"class":1052,"line":9108},628,[1050,9110,9111],{"class":1056},"# Password security monitoring\n",[1050,9113,9115,9117,9120],{"class":1052,"line":9114},629,[1050,9116,1201],{"class":1200},[1050,9118,9119],{"class":1204}," PasswordSecurityMonitoring",[1050,9121,1208],{"class":1071},[1050,9123,9125,9127,9130],{"class":1052,"line":9124},630,[1050,9126,1215],{"class":1214},[1050,9128,9129],{"class":1218},"Monitor and analyze password security",[1050,9131,1222],{"class":1214},[1050,9133,9135],{"class":1052,"line":9134},631,[1050,9136,1228],{"class":1067},[1050,9138,9140,9142],{"class":1052,"line":9139},632,[1050,9141,1234],{"class":1071},[1050,9143,1238],{"class":1237},[1050,9145,9147,9149,9152],{"class":1052,"line":9146},633,[1050,9148,1244],{"class":1200},[1050,9150,9151],{"class":1247}," password_breach_checking",[1050,9153,1251],{"class":1071},[1050,9155,9157,9159,9162],{"class":1052,"line":9156},634,[1050,9158,1257],{"class":1214},[1050,9160,9161],{"class":1218},"Check passwords against known breaches",[1050,9163,1222],{"class":1214},[1050,9165,9167],{"class":1052,"line":9166},635,[1050,9168,1268],{"class":1067},[1050,9170,9172,9174],{"class":1052,"line":9171},636,[1050,9173,1982],{"class":1063},[1050,9175,1985],{"class":1067},[1050,9177,9179,9181],{"class":1052,"line":9178},637,[1050,9180,1982],{"class":1063},[1050,9182,9183],{"class":1067}," requests\n",[1050,9185,9187],{"class":1052,"line":9186},638,[1050,9188,1268],{"class":1067},[1050,9190,9192,9194,9197,9199,9201],{"class":1052,"line":9191},639,[1050,9193,2820],{"class":1200},[1050,9195,9196],{"class":1247}," check_password_breach",[1050,9198,1607],{"class":1071},[1050,9200,2195],{"class":2099},[1050,9202,2016],{"class":1071},[1050,9204,9206,9208,9211],{"class":1052,"line":9205},640,[1050,9207,2841],{"class":1214},[1050,9209,9210],{"class":1218},"Check if password appears in known breaches using HaveIBeenPwned API",[1050,9212,1222],{"class":1214},[1050,9214,9216],{"class":1052,"line":9215},641,[1050,9217,1416],{"class":1067},[1050,9219,9221],{"class":1052,"line":9220},642,[1050,9222,9223],{"class":1056},"            # Hash password with SHA-1\n",[1050,9225,9227,9230,9232,9234,9236,9239,9241,9243,9245,9247,9249,9251,9253,9255,9257,9259,9261,9264],{"class":1052,"line":9226},643,[1050,9228,9229],{"class":1067},"            sha1_hash ",[1050,9231,1182],{"class":1071},[1050,9233,2274],{"class":1067},[1050,9235,1072],{"class":1071},[1050,9237,9238],{"class":1185},"sha1",[1050,9240,1607],{"class":1071},[1050,9242,2195],{"class":1185},[1050,9244,1072],{"class":1071},[1050,9246,2226],{"class":1185},[1050,9248,1607],{"class":1071},[1050,9250,1299],{"class":1291},[1050,9252,2233],{"class":1295},[1050,9254,1299],{"class":1291},[1050,9256,7079],{"class":1071},[1050,9258,7253],{"class":1185},[1050,9260,6923],{"class":1071},[1050,9262,9263],{"class":1185},"upper",[1050,9265,1189],{"class":1071},[1050,9267,9269],{"class":1052,"line":9268},644,[1050,9270,1416],{"class":1067},[1050,9272,9274],{"class":1052,"line":9273},645,[1050,9275,9276],{"class":1056},"            # Use k-anonymity: send only first 5 characters\n",[1050,9278,9280,9283,9285,9288,9290,9292],{"class":1052,"line":9279},646,[1050,9281,9282],{"class":1067},"            prefix ",[1050,9284,1182],{"class":1071},[1050,9286,9287],{"class":1067}," sha1_hash",[1050,9289,2624],{"class":1071},[1050,9291,4683],{"class":1437},[1050,9293,4819],{"class":1071},[1050,9295,9297,9300,9302,9304,9306,9308],{"class":1052,"line":9296},647,[1050,9298,9299],{"class":1067},"            suffix ",[1050,9301,1182],{"class":1071},[1050,9303,9287],{"class":1067},[1050,9305,4093],{"class":1071},[1050,9307,4683],{"class":1437},[1050,9309,9310],{"class":1071},":]\n",[1050,9312,9314],{"class":1052,"line":9313},648,[1050,9315,1416],{"class":1067},[1050,9317,9319,9321],{"class":1052,"line":9318},649,[1050,9320,6160],{"class":1063},[1050,9322,1208],{"class":1071},[1050,9324,9326],{"class":1052,"line":9325},650,[1050,9327,9328],{"class":1056},"                # Query HaveIBeenPwned API\n",[1050,9330,9332,9335,9337,9340,9342,9344],{"class":1052,"line":9331},651,[1050,9333,9334],{"class":1067},"                response ",[1050,9336,1182],{"class":1071},[1050,9338,9339],{"class":1067}," requests",[1050,9341,1072],{"class":1071},[1050,9343,7476],{"class":1185},[1050,9345,4141],{"class":1071},[1050,9347,9349,9351,9354,9356,9359,9361,9363],{"class":1052,"line":9348},652,[1050,9350,4556],{"class":1200},[1050,9352,9353],{"class":1295},"\"https://api.pwnedpasswords.com/range/",[1050,9355,1636],{"class":1635},[1050,9357,9358],{"class":1185},"prefix",[1050,9360,1641],{"class":1635},[1050,9362,1644],{"class":1295},[1050,9364,1111],{"class":1071},[1050,9366,9368,9371,9373],{"class":1052,"line":9367},653,[1050,9369,9370],{"class":2983},"                    timeout",[1050,9372,1182],{"class":1071},[1050,9374,9375],{"class":1437},"5\n",[1050,9377,9379],{"class":1052,"line":9378},654,[1050,9380,4632],{"class":1071},[1050,9382,9384],{"class":1052,"line":9383},655,[1050,9385,2124],{"class":1067},[1050,9387,9389,9391,9394,9396,9399,9401,9404],{"class":1052,"line":9388},656,[1050,9390,2130],{"class":1063},[1050,9392,9393],{"class":1067}," response",[1050,9395,1072],{"class":1071},[1050,9397,9398],{"class":1824},"status_code",[1050,9400,7666],{"class":2133},[1050,9402,9403],{"class":1437}," 200",[1050,9405,1208],{"class":1071},[1050,9407,9409],{"class":1052,"line":9408},657,[1050,9410,9411],{"class":1056},"                    # Check if our suffix appears in results\n",[1050,9413,9415,9417,9420,9422,9424,9426,9429,9431,9434],{"class":1052,"line":9414},658,[1050,9416,4830],{"class":1063},[1050,9418,9419],{"class":1067}," line ",[1050,9421,2249],{"class":1063},[1050,9423,9393],{"class":1067},[1050,9425,1072],{"class":1071},[1050,9427,9428],{"class":1824},"text",[1050,9430,1072],{"class":1071},[1050,9432,9433],{"class":1185},"splitlines",[1050,9435,1251],{"class":1071},[1050,9437,9439,9442,9444,9447,9449,9452,9454,9456,9458,9460,9462,9464],{"class":1052,"line":9438},659,[1050,9440,9441],{"class":1067},"                        hash_suffix",[1050,9443,1100],{"class":1071},[1050,9445,9446],{"class":1067}," count ",[1050,9448,1182],{"class":1071},[1050,9450,9451],{"class":1067}," line",[1050,9453,1072],{"class":1071},[1050,9455,2432],{"class":1185},[1050,9457,1607],{"class":1071},[1050,9459,1299],{"class":1291},[1050,9461,1405],{"class":1295},[1050,9463,1299],{"class":1291},[1050,9465,1128],{"class":1071},[1050,9467,9469,9471,9474,9476,9479],{"class":1052,"line":9468},660,[1050,9470,4846],{"class":1063},[1050,9472,9473],{"class":1067}," hash_suffix ",[1050,9475,2503],{"class":2133},[1050,9477,9478],{"class":1067}," suffix",[1050,9480,1208],{"class":1071},[1050,9482,9484,9487,9489,9491,9493,9495,9498],{"class":1052,"line":9483},661,[1050,9485,9486],{"class":1063},"                            return",[1050,9488,3011],{"class":2763},[1050,9490,1100],{"class":1071},[1050,9492,7050],{"class":1237},[1050,9494,1607],{"class":1071},[1050,9496,9497],{"class":1185},"count",[1050,9499,1128],{"class":1071},[1050,9501,9503],{"class":1052,"line":9502},662,[1050,9504,3002],{"class":1067},[1050,9506,9508,9510,9512,9514],{"class":1052,"line":9507},663,[1050,9509,3008],{"class":1063},[1050,9511,3162],{"class":2763},[1050,9513,1100],{"class":1071},[1050,9515,3212],{"class":1437},[1050,9517,9519],{"class":1052,"line":9518},664,[1050,9520,2124],{"class":1067},[1050,9522,9524,9526,9528,9530,9533],{"class":1052,"line":9523},665,[1050,9525,6213],{"class":1063},[1050,9527,9339],{"class":1067},[1050,9529,1072],{"class":1071},[1050,9531,9532],{"class":1824},"RequestException",[1050,9534,1208],{"class":1071},[1050,9536,9538],{"class":1052,"line":9537},666,[1050,9539,9540],{"class":1056},"                # If API is unavailable, don't block password change\n",[1050,9542,9544,9546,9548,9550],{"class":1052,"line":9543},667,[1050,9545,2332],{"class":1063},[1050,9547,6707],{"class":2763},[1050,9549,1100],{"class":1071},[1050,9551,3212],{"class":1437},[1050,9553,9555],{"class":1052,"line":9554},668,[1050,9556,1416],{"class":1067},[1050,9558,9560,9562,9564,9566],{"class":1052,"line":9559},669,[1050,9561,3159],{"class":1063},[1050,9563,3162],{"class":2763},[1050,9565,1100],{"class":1071},[1050,9567,3212],{"class":1437},[1050,9569,9571],{"class":1052,"line":9570},670,[1050,9572,1268],{"class":1067},[1050,9574,9576,9578,9581,9583,9585],{"class":1052,"line":9575},671,[1050,9577,2820],{"class":1200},[1050,9579,9580],{"class":1247}," validate_password_not_breached",[1050,9582,1607],{"class":1071},[1050,9584,2195],{"class":2099},[1050,9586,2016],{"class":1071},[1050,9588,9590,9592,9595],{"class":1052,"line":9589},672,[1050,9591,2841],{"class":1214},[1050,9593,9594],{"class":1218},"Validator to check password against breaches",[1050,9596,1222],{"class":1214},[1050,9598,9600],{"class":1052,"line":9599},673,[1050,9601,1416],{"class":1067},[1050,9603,9605,9608,9610,9612,9614,9616,9618,9620],{"class":1052,"line":9604},674,[1050,9606,9607],{"class":1067},"            is_breached",[1050,9609,1100],{"class":1071},[1050,9611,9446],{"class":1067},[1050,9613,1182],{"class":1071},[1050,9615,9196],{"class":1185},[1050,9617,1607],{"class":1071},[1050,9619,2195],{"class":1185},[1050,9621,1128],{"class":1071},[1050,9623,9625],{"class":1052,"line":9624},675,[1050,9626,1416],{"class":1067},[1050,9628,9630,9632,9635],{"class":1052,"line":9629},676,[1050,9631,2863],{"class":1063},[1050,9633,9634],{"class":1067}," is_breached",[1050,9636,1208],{"class":1071},[1050,9638,9640,9642,9644,9647,9650],{"class":1052,"line":9639},677,[1050,9641,2130],{"class":1063},[1050,9643,9446],{"class":1067},[1050,9645,9646],{"class":2133},">",[1050,9648,9649],{"class":1437}," 100",[1050,9651,1208],{"class":1071},[1050,9653,9655,9657,9659],{"class":1052,"line":9654},678,[1050,9656,4499],{"class":1063},[1050,9658,4502],{"class":1185},[1050,9660,4141],{"class":1071},[1050,9662,9664,9666,9669,9671,9673,9675],{"class":1052,"line":9663},679,[1050,9665,4147],{"class":1200},[1050,9667,9668],{"class":1295},"\"This password has been found in ",[1050,9670,1636],{"class":1635},[1050,9672,9497],{"class":1185},[1050,9674,1641],{"class":1635},[1050,9676,9677],{"class":1295}," data breaches. \"\n",[1050,9679,9681,9684,9687],{"class":1052,"line":9680},680,[1050,9682,9683],{"class":1291},"                        \"",[1050,9685,9686],{"class":1295},"Please choose a different password.",[1050,9688,1593],{"class":1291},[1050,9690,9692],{"class":1052,"line":9691},681,[1050,9693,4169],{"class":1071},[1050,9695,9697,9700],{"class":1052,"line":9696},682,[1050,9698,9699],{"class":1063},"                else",[1050,9701,1208],{"class":1071},[1050,9703,9705],{"class":1052,"line":9704},683,[1050,9706,9707],{"class":1056},"                    # Just warn for passwords with low breach counts\n",[1050,9709,9711],{"class":1052,"line":9710},684,[1050,9712,9713],{"class":1063},"                    pass\n",[1050,9715,9717],{"class":1052,"line":9716},685,[1050,9718,1268],{"class":1067},[1050,9720,9722,9724,9726,9728],{"class":1052,"line":9721},686,[1050,9723,1530],{"class":1063},[1050,9725,9196],{"class":1067},[1050,9727,1100],{"class":1071},[1050,9729,9730],{"class":1067}," validate_password_not_breached\n",[1050,9732,9734],{"class":1052,"line":9733},687,[1050,9735,1228],{"class":1067},[1050,9737,9739,9741],{"class":1052,"line":9738},688,[1050,9740,1234],{"class":1071},[1050,9742,1238],{"class":1237},[1050,9744,9746,9748,9751],{"class":1052,"line":9745},689,[1050,9747,1244],{"class":1200},[1050,9749,9750],{"class":1247}," password_analytics",[1050,9752,1251],{"class":1071},[1050,9754,9756,9758,9761],{"class":1052,"line":9755},690,[1050,9757,1257],{"class":1214},[1050,9759,9760],{"class":1218},"Analyze password patterns and security",[1050,9762,1222],{"class":1214},[1050,9764,9766],{"class":1052,"line":9765},691,[1050,9767,1268],{"class":1067},[1050,9769,9771,9773,9776],{"class":1052,"line":9770},692,[1050,9772,2820],{"class":1200},[1050,9774,9775],{"class":1247}," analyze_user_passwords",[1050,9777,1251],{"class":1071},[1050,9779,9781,9783,9786],{"class":1052,"line":9780},693,[1050,9782,2841],{"class":1214},[1050,9784,9785],{"class":1218},"Analyze password patterns across all users",[1050,9787,1222],{"class":1214},[1050,9789,9791],{"class":1052,"line":9790},694,[1050,9792,1416],{"class":1067},[1050,9794,9796,9799,9802,9804],{"class":1052,"line":9795},695,[1050,9797,9798],{"class":1063},"            from",[1050,9800,9801],{"class":1067}," collections ",[1050,9803,1088],{"class":1063},[1050,9805,9806],{"class":1067}," defaultdict\n",[1050,9808,9810],{"class":1052,"line":9809},696,[1050,9811,1416],{"class":1067},[1050,9813,9815,9818,9820],{"class":1052,"line":9814},697,[1050,9816,9817],{"class":1067},"            analytics ",[1050,9819,1182],{"class":1071},[1050,9821,1392],{"class":1071},[1050,9823,9825,9827,9830,9832,9834,9836,9838,9840,9842,9844],{"class":1052,"line":9824},698,[1050,9826,3505],{"class":1291},[1050,9828,9829],{"class":1295},"total_users",[1050,9831,1299],{"class":1291},[1050,9833,1405],{"class":1071},[1050,9835,3248],{"class":1067},[1050,9837,1072],{"class":1071},[1050,9839,3253],{"class":1824},[1050,9841,1072],{"class":1071},[1050,9843,9497],{"class":1185},[1050,9845,9846],{"class":1071},"(),\n",[1050,9848,9850,9852,9855,9857,9859,9861,9863,9865,9867,9870,9872,9874,9876,9879,9881,9883],{"class":1052,"line":9849},699,[1050,9851,3505],{"class":1291},[1050,9853,9854],{"class":1295},"users_with_passwords",[1050,9856,1299],{"class":1291},[1050,9858,1405],{"class":1071},[1050,9860,3248],{"class":1067},[1050,9862,1072],{"class":1071},[1050,9864,3253],{"class":1824},[1050,9866,1072],{"class":1071},[1050,9868,9869],{"class":1185},"exclude",[1050,9871,1607],{"class":1071},[1050,9873,2195],{"class":2983},[1050,9875,1182],{"class":1071},[1050,9877,9878],{"class":1291},"''",[1050,9880,2287],{"class":1071},[1050,9882,9497],{"class":1185},[1050,9884,9846],{"class":1071},[1050,9886,9888,9890,9893,9895,9897,9900,9902,9905],{"class":1052,"line":9887},700,[1050,9889,3505],{"class":1291},[1050,9891,9892],{"class":1295},"password_algorithms",[1050,9894,1299],{"class":1291},[1050,9896,1405],{"class":1071},[1050,9898,9899],{"class":1185}," defaultdict",[1050,9901,1607],{"class":1071},[1050,9903,9904],{"class":1237},"int",[1050,9906,3586],{"class":1071},[1050,9908,9910,9912,9915,9917,9919,9921],{"class":1052,"line":9909},701,[1050,9911,3505],{"class":1291},[1050,9913,9914],{"class":1295},"weak_passwords",[1050,9916,1299],{"class":1291},[1050,9918,1405],{"class":1071},[1050,9920,7486],{"class":1437},[1050,9922,1111],{"class":1071},[1050,9924,9926,9928,9931,9933,9935,9937],{"class":1052,"line":9925},702,[1050,9927,3505],{"class":1291},[1050,9929,9930],{"class":1295},"expired_passwords",[1050,9932,1299],{"class":1291},[1050,9934,1405],{"class":1071},[1050,9936,7486],{"class":1437},[1050,9938,1111],{"class":1071},[1050,9940,9942],{"class":1052,"line":9941},703,[1050,9943,6466],{"class":1071},[1050,9945,9947],{"class":1052,"line":9946},704,[1050,9948,1416],{"class":1067},[1050,9950,9952,9954,9956,9958,9960,9962,9964,9966,9968,9970,9972,9974,9976],{"class":1052,"line":9951},705,[1050,9953,3240],{"class":1063},[1050,9955,3243],{"class":1067},[1050,9957,2249],{"class":1063},[1050,9959,3248],{"class":1067},[1050,9961,1072],{"class":1071},[1050,9963,3253],{"class":1824},[1050,9965,1072],{"class":1071},[1050,9967,9869],{"class":1185},[1050,9969,1607],{"class":1071},[1050,9971,2195],{"class":2983},[1050,9973,1182],{"class":1071},[1050,9975,9878],{"class":1291},[1050,9977,2016],{"class":1071},[1050,9979,9981],{"class":1052,"line":9980},706,[1050,9982,9983],{"class":1056},"                # Analyze password hash algorithm\n",[1050,9985,9987,9989,9991,9993,9995],{"class":1052,"line":9986},707,[1050,9988,2130],{"class":1063},[1050,9990,2866],{"class":1067},[1050,9992,1072],{"class":1071},[1050,9994,2195],{"class":1824},[1050,9996,1208],{"class":1071},[1050,9998,10000,10003],{"class":1052,"line":9999},708,[1050,10001,10002],{"class":1063},"                    try",[1050,10004,1208],{"class":1071},[1050,10006,10008,10011,10013,10015,10017,10019,10021,10023],{"class":1052,"line":10007},709,[1050,10009,10010],{"class":1067},"                        hasher ",[1050,10012,1182],{"class":1071},[1050,10014,1796],{"class":1185},[1050,10016,1607],{"class":1071},[1050,10018,2828],{"class":1185},[1050,10020,1072],{"class":1071},[1050,10022,2195],{"class":1824},[1050,10024,1128],{"class":1071},[1050,10026,10028,10031,10033,10035,10037,10039,10042,10044,10046,10048,10050,10053],{"class":1052,"line":10027},710,[1050,10029,10030],{"class":1067},"                        analytics",[1050,10032,4093],{"class":1071},[1050,10034,1299],{"class":1291},[1050,10036,9892],{"class":1295},[1050,10038,1299],{"class":1291},[1050,10040,10041],{"class":1071},"][",[1050,10043,1819],{"class":1067},[1050,10045,1072],{"class":1071},[1050,10047,1825],{"class":1824},[1050,10049,2630],{"class":1071},[1050,10051,10052],{"class":1071}," +=",[1050,10054,3385],{"class":1437},[1050,10056,10058,10061,10063],{"class":1052,"line":10057},711,[1050,10059,10060],{"class":1063},"                    except",[1050,10062,8802],{"class":1237},[1050,10064,1208],{"class":1071},[1050,10066,10068,10070,10072,10074,10076,10078,10080,10082,10085,10087,10089,10091],{"class":1052,"line":10067},712,[1050,10069,10030],{"class":1067},[1050,10071,4093],{"class":1071},[1050,10073,1299],{"class":1291},[1050,10075,9892],{"class":1295},[1050,10077,1299],{"class":1291},[1050,10079,10041],{"class":1071},[1050,10081,1299],{"class":1291},[1050,10083,10084],{"class":1295},"unknown",[1050,10086,1299],{"class":1291},[1050,10088,2630],{"class":1071},[1050,10090,10052],{"class":1071},[1050,10092,3385],{"class":1437},[1050,10094,10096],{"class":1052,"line":10095},713,[1050,10097,2124],{"class":1067},[1050,10099,10101],{"class":1052,"line":10100},714,[1050,10102,10103],{"class":1056},"                # Check for weak passwords (would need additional data)\n",[1050,10105,10107],{"class":1052,"line":10106},715,[1050,10108,10109],{"class":1056},"                # This is a simplified example\n",[1050,10111,10113,10115,10117,10119,10121,10123,10125,10127,10130,10132,10134],{"class":1052,"line":10112},716,[1050,10114,2130],{"class":1063},[1050,10116,4072],{"class":1623},[1050,10118,1607],{"class":1071},[1050,10120,2828],{"class":1185},[1050,10122,1072],{"class":1071},[1050,10124,2195],{"class":1824},[1050,10126,5442],{"class":1071},[1050,10128,10129],{"class":2133}," \u003C",[1050,10131,9649],{"class":1437},[1050,10133,1405],{"class":1071},[1050,10135,10136],{"class":1056},"  # Rough estimate for weak hash\n",[1050,10138,10140,10143,10145,10147,10149,10151,10153,10155],{"class":1052,"line":10139},717,[1050,10141,10142],{"class":1067},"                    analytics",[1050,10144,4093],{"class":1071},[1050,10146,1299],{"class":1291},[1050,10148,9914],{"class":1295},[1050,10150,1299],{"class":1291},[1050,10152,2630],{"class":1071},[1050,10154,10052],{"class":1071},[1050,10156,3385],{"class":1437},[1050,10158,10160],{"class":1052,"line":10159},718,[1050,10161,1416],{"class":1067},[1050,10163,10165,10167],{"class":1052,"line":10164},719,[1050,10166,3159],{"class":1063},[1050,10168,10169],{"class":1067}," analytics\n",[1050,10171,10173],{"class":1052,"line":10172},720,[1050,10174,1268],{"class":1067},[1050,10176,10178,10180,10183],{"class":1052,"line":10177},721,[1050,10179,2820],{"class":1200},[1050,10181,10182],{"class":1247}," generate_password_security_report",[1050,10184,1251],{"class":1071},[1050,10186,10188,10190,10193],{"class":1052,"line":10187},722,[1050,10189,2841],{"class":1214},[1050,10191,10192],{"class":1218},"Generate comprehensive password security report",[1050,10194,1222],{"class":1214},[1050,10196,10198],{"class":1052,"line":10197},723,[1050,10199,1416],{"class":1067},[1050,10201,10203,10205,10207,10209],{"class":1052,"line":10202},724,[1050,10204,9817],{"class":1067},[1050,10206,1182],{"class":1071},[1050,10208,9775],{"class":1185},[1050,10210,1189],{"class":1071},[1050,10212,10214],{"class":1052,"line":10213},725,[1050,10215,1416],{"class":1067},[1050,10217,10219,10222,10224],{"class":1052,"line":10218},726,[1050,10220,10221],{"class":1067},"            report ",[1050,10223,1182],{"class":1071},[1050,10225,1392],{"class":1071},[1050,10227,10229,10231,10234,10236,10238,10241],{"class":1052,"line":10228},727,[1050,10230,3505],{"class":1291},[1050,10232,10233],{"class":1295},"summary",[1050,10235,1299],{"class":1291},[1050,10237,1405],{"class":1071},[1050,10239,10240],{"class":1067}," analytics",[1050,10242,1111],{"class":1071},[1050,10244,10246,10248,10251,10253,10255],{"class":1052,"line":10245},728,[1050,10247,3505],{"class":1291},[1050,10249,10250],{"class":1295},"recommendations",[1050,10252,1299],{"class":1291},[1050,10254,1405],{"class":1071},[1050,10256,10257],{"class":1071}," [],\n",[1050,10259,10261,10263,10266,10268,10270],{"class":1052,"line":10260},729,[1050,10262,3505],{"class":1291},[1050,10264,10265],{"class":1295},"action_items",[1050,10267,1299],{"class":1291},[1050,10269,1405],{"class":1071},[1050,10271,4050],{"class":1071},[1050,10273,10275],{"class":1052,"line":10274},730,[1050,10276,6466],{"class":1071},[1050,10278,10280],{"class":1052,"line":10279},731,[1050,10281,1416],{"class":1067},[1050,10283,10285],{"class":1052,"line":10284},732,[1050,10286,10287],{"class":1056},"            # Generate recommendations\n",[1050,10289,10291,10293,10295,10297,10299,10301,10303,10306,10308,10310,10312,10315,10317,10319,10321,10323,10325,10327],{"class":1052,"line":10290},733,[1050,10292,2863],{"class":1063},[1050,10294,10240],{"class":1067},[1050,10296,4093],{"class":1071},[1050,10298,1299],{"class":1291},[1050,10300,9892],{"class":1295},[1050,10302,1299],{"class":1291},[1050,10304,10305],{"class":1071},"].",[1050,10307,7476],{"class":1185},[1050,10309,1607],{"class":1071},[1050,10311,1299],{"class":1291},[1050,10313,10314],{"class":1295},"md5",[1050,10316,1299],{"class":1291},[1050,10318,1100],{"class":1071},[1050,10320,7486],{"class":1437},[1050,10322,5442],{"class":1071},[1050,10324,5150],{"class":2133},[1050,10326,7486],{"class":1437},[1050,10328,1208],{"class":1071},[1050,10330,10332,10335,10337,10339,10341,10343,10345,10347],{"class":1052,"line":10331},734,[1050,10333,10334],{"class":1067},"                report",[1050,10336,4093],{"class":1071},[1050,10338,1299],{"class":1291},[1050,10340,10250],{"class":1295},[1050,10342,1299],{"class":1291},[1050,10344,10305],{"class":1071},[1050,10346,4138],{"class":1185},[1050,10348,4141],{"class":1071},[1050,10350,10352,10355,10358],{"class":1052,"line":10351},735,[1050,10353,10354],{"class":1291},"                    \"",[1050,10356,10357],{"class":1295},"Upgrade users from MD5 password hashing",[1050,10359,1593],{"class":1291},[1050,10361,10363],{"class":1052,"line":10362},736,[1050,10364,4632],{"class":1071},[1050,10366,10368,10370,10372,10374,10376,10378,10380,10382],{"class":1052,"line":10367},737,[1050,10369,10334],{"class":1067},[1050,10371,4093],{"class":1071},[1050,10373,1299],{"class":1291},[1050,10375,10265],{"class":1295},[1050,10377,1299],{"class":1291},[1050,10379,10305],{"class":1071},[1050,10381,4138],{"class":1185},[1050,10383,4141],{"class":1071},[1050,10385,10387,10389,10392],{"class":1052,"line":10386},738,[1050,10388,10354],{"class":1291},[1050,10390,10391],{"class":1295},"Force password reset for users with MD5 hashes",[1050,10393,1593],{"class":1291},[1050,10395,10397],{"class":1052,"line":10396},739,[1050,10398,4632],{"class":1071},[1050,10400,10402],{"class":1052,"line":10401},740,[1050,10403,1416],{"class":1067},[1050,10405,10407,10409,10411,10413,10415,10417,10419,10421,10423,10425,10427,10429,10431,10433,10435,10438,10441],{"class":1052,"line":10406},741,[1050,10408,2863],{"class":1063},[1050,10410,10240],{"class":1067},[1050,10412,4093],{"class":1071},[1050,10414,1299],{"class":1291},[1050,10416,9914],{"class":1295},[1050,10418,1299],{"class":1291},[1050,10420,2630],{"class":1071},[1050,10422,5150],{"class":2133},[1050,10424,10240],{"class":1067},[1050,10426,4093],{"class":1071},[1050,10428,1299],{"class":1291},[1050,10430,9829],{"class":1295},[1050,10432,1299],{"class":1291},[1050,10434,2630],{"class":1071},[1050,10436,10437],{"class":2133}," *",[1050,10439,10440],{"class":1437}," 0.1",[1050,10442,1208],{"class":1071},[1050,10444,10446,10448,10450,10452,10454,10456,10458,10460],{"class":1052,"line":10445},742,[1050,10447,10334],{"class":1067},[1050,10449,4093],{"class":1071},[1050,10451,1299],{"class":1291},[1050,10453,10250],{"class":1295},[1050,10455,1299],{"class":1291},[1050,10457,10305],{"class":1071},[1050,10459,4138],{"class":1185},[1050,10461,4141],{"class":1071},[1050,10463,10465,10467,10470],{"class":1052,"line":10464},743,[1050,10466,10354],{"class":1291},[1050,10468,10469],{"class":1295},"Implement stronger password requirements",[1050,10471,1593],{"class":1291},[1050,10473,10475],{"class":1052,"line":10474},744,[1050,10476,4632],{"class":1071},[1050,10478,10480],{"class":1052,"line":10479},745,[1050,10481,1416],{"class":1067},[1050,10483,10485,10487],{"class":1052,"line":10484},746,[1050,10486,3159],{"class":1063},[1050,10488,10489],{"class":1067}," report\n",[1050,10491,10493],{"class":1052,"line":10492},747,[1050,10494,1268],{"class":1067},[1050,10496,10498,10500,10502,10504],{"class":1052,"line":10497},748,[1050,10499,1530],{"class":1063},[1050,10501,9775],{"class":1067},[1050,10503,1100],{"class":1071},[1050,10505,10506],{"class":1067}," generate_password_security_report\n",[1026,10508,10509],{},"Effective password management is essential for application security. By implementing strong hashing, comprehensive validation, secure reset mechanisms, and continuous monitoring, you can protect user accounts and maintain the integrity of your authentication system.",[10511,10512,10513],"style",{},"html pre.shiki code .s9Tkl, html code.shiki .s9Tkl{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#A0ADA0;--shiki-default-font-style:inherit;--shiki-dark:#758575DD;--shiki-dark-font-style:inherit}html pre.shiki code .siDh9, html code.shiki .siDh9{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#1E754F;--shiki-default-font-style:inherit;--shiki-dark:#4D9375;--shiki-dark-font-style:inherit}html pre.shiki code .sftqT, html code.shiki .sftqT{--shiki-light:#90A4AE;--shiki-default:#393A34;--shiki-dark:#DBD7CAEE}html pre.shiki code .soVBu, html code.shiki .soVBu{--shiki-light:#39ADB5;--shiki-default:#999999;--shiki-dark:#666666}html pre.shiki code .siWMO, html code.shiki .siWMO{--shiki-light:#6182B8;--shiki-default:#393A34;--shiki-dark:#DBD7CAEE}html pre.shiki code .s5Kfy, html code.shiki .s5Kfy{--shiki-light:#9C3EDA;--shiki-default:#AB5959;--shiki-dark:#CB7676}html pre.shiki code .sD-vU, html code.shiki .sD-vU{--shiki-light:#E2931D;--shiki-default:#2E8F82;--shiki-dark:#5DA994}html pre.shiki code .sm7ve, html code.shiki .sm7ve{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#B5695977;--shiki-default-font-style:inherit;--shiki-dark:#C98A7D77;--shiki-dark-font-style:inherit}html pre.shiki code .sVyVU, html code.shiki .sVyVU{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#B56959;--shiki-default-font-style:inherit;--shiki-dark:#C98A7D;--shiki-dark-font-style:inherit}html pre.shiki code .sa2tF, html code.shiki .sa2tF{--shiki-light:#E2931D;--shiki-default:#998418;--shiki-dark:#B8A965}html pre.shiki code .sljsM, html code.shiki .sljsM{--shiki-light:#6182B8;--shiki-default:#59873A;--shiki-dark:#80A665}html pre.shiki code .sbYkP, html code.shiki .sbYkP{--shiki-light:#39ADB5;--shiki-default:#B5695977;--shiki-dark:#C98A7D77}html pre.shiki code .sTbE_, html code.shiki .sTbE_{--shiki-light:#91B859;--shiki-default:#B56959;--shiki-dark:#C98A7D}html pre.shiki code .s7CZa, html code.shiki .s7CZa{--shiki-light:#F76D47;--shiki-default:#2F798A;--shiki-dark:#4C9A91}html pre.shiki code .sJdAF, html code.shiki .sJdAF{--shiki-light:#6182B8;--shiki-default:#998418;--shiki-dark:#B8A965}html pre.shiki code .s3h35, html code.shiki .s3h35{--shiki-light:#F76D47;--shiki-default:#A65E2B;--shiki-dark:#C99076}html pre.shiki code .sBPpx, html code.shiki .sBPpx{--shiki-light:#E53935;--shiki-default:#393A34;--shiki-dark:#DBD7CAEE}html pre.shiki code .sYn-s, html code.shiki .sYn-s{--shiki-light:#E2931D;--shiki-default:#59873A;--shiki-dark:#80A665}html pre.shiki code .sRjD_, html code.shiki .sRjD_{--shiki-light:#E53935;--shiki-light-font-style:italic;--shiki-default:#393A34;--shiki-default-font-style:inherit;--shiki-dark:#DBD7CAEE;--shiki-dark-font-style:inherit}html pre.shiki code .sCyAa, html code.shiki .sCyAa{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#393A34;--shiki-default-font-style:inherit;--shiki-dark:#DBD7CAEE;--shiki-dark-font-style:inherit}html pre.shiki code .sVsLi, html code.shiki .sVsLi{--shiki-light:#39ADB5;--shiki-default:#AB5959;--shiki-dark:#CB7676}html pre.shiki code .se3Ec, html code.shiki .se3Ec{--shiki-light:#90A4AE;--shiki-default:#A65E2B;--shiki-dark:#C99076}html pre.shiki code .s8XtY, html code.shiki .s8XtY{--shiki-light:#39ADB5;--shiki-default:#1E754F;--shiki-dark:#4D9375}html pre.shiki code .sqOPj, html code.shiki .sqOPj{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#B07D48;--shiki-default-font-style:inherit;--shiki-dark:#BD976A;--shiki-dark-font-style:inherit}html pre.shiki code .sETVe, html code.shiki .sETVe{--shiki-light:#39ADB5;--shiki-default:#A65E2B;--shiki-dark:#C99076}html pre.shiki code .sz9Cv, html code.shiki .sz9Cv{--shiki-light:#91B859;--shiki-default:#A65E2B;--shiki-dark:#C99076}html pre.shiki code .sRJPX, html code.shiki .sRJPX{--shiki-light:#91B859;--shiki-default:#998418;--shiki-dark:#B8A965}html pre.shiki code .s27EL, html code.shiki .s27EL{--shiki-light:#91B859;--shiki-default:#AB5E3F;--shiki-dark:#C4704F}html pre.shiki code .sFGJz, html code.shiki .sFGJz{--shiki-light:#E53935;--shiki-default:#A65E2B;--shiki-dark:#C99076}html pre.shiki code .s131V, html code.shiki .s131V{--shiki-light:#90A4AE;--shiki-default:#998418;--shiki-dark:#B8A965}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":1045,"searchDepth":1053,"depth":1060,"links":10515},[10516],{"id":1032,"depth":1060,"text":1033,"children":10517},[10518],{"id":1037,"depth":1094,"text":1038},"md",null,{},{"title":408,"description":1028},"9b1yjTBYp4WYMyKDGXQQPfZh8Ybb53_ACdl5P0cSjKU",[10525,10527],{"title":404,"path":405,"stem":406,"description":10526,"children":-1},"Django's permission system provides fine-grained access control for your application's resources. Understanding how to create, assign, and check permissions enables you to build secure applications with precise authorization controls.",{"title":412,"path":413,"stem":414,"description":10528,"children":-1},"Django provides built-in authentication views for common authentication workflows like login, logout, password change, and password reset. Understanding how to use and customize these views enables you to implement secure authentication flows that meet your application's specific requirements.",1772474927601]