Return the local network CIDR derived from `ip` output, or None. Used as a runtime fallback when an API caller doesn't pass an explicit network=. Replaces the old hardcoded '192.168.1.0/24' default that silently scanned the wrong subnet on any non-192.168.1.x network.
()
| 8572 | return jsonify({'success': False, 'error': 'Not authenticated'}), 401 |
| 8573 | |
| 8574 | data = request.get_json() |
| 8575 | if not data: |
| 8576 | return jsonify({'success': False, 'error': 'No data provided'}), 400 |
| 8577 | |
| 8578 | result = auth_mgr.change_password( |
| 8579 | data.get('current_password', ''), |
| 8580 | data.get('new_password', '') |
| 8581 | ) |
| 8582 | return jsonify(result) if result['success'] else (jsonify(result), 400) |
| 8583 | |
| 8584 | |
| 8585 | @app.route('/api/auth/recover', methods=['POST']) |
| 8586 | def auth_recover(): |
| 8587 | """Use a recovery code to reset password and login.""" |
| 8588 | ip = _auth_client_ip() |
| 8589 | limited, retry_after = _auth_rate_limited(ip) |
| 8590 | if limited: |
| 8591 | response = jsonify({'success': False, 'error': 'Too many failed attempts. Try again later.', |
| 8592 | 'retry_after': retry_after}) |
| 8593 | response.headers['Retry-After'] = str(retry_after) |
| 8594 | return response, 429 |
| 8595 | |
| 8596 | data = request.get_json() |
| 8597 | if not data: |
| 8598 | return jsonify({'success': False, 'error': 'No data provided'}), 400 |
| 8599 | |
| 8600 | result = auth_mgr.recover( |
| 8601 | data.get('username', '').strip(), |
| 8602 | data.get('recovery_code', '').strip(), |
| 8603 | data.get('new_password', '') |
| 8604 | ) |
| 8605 | if result['success']: |
| 8606 | _auth_clear_failures(ip) |
| 8607 | session['authenticated'] = True |
| 8608 | session['username'] = data.get('username', '').strip() |
| 8609 | session['login_time'] = time.time() |
| 8610 | session.permanent = True |
| 8611 | return jsonify(result) |
| 8612 | _auth_record_failure(ip) |
| 8613 | return jsonify(result), 400 |
no test coverage detected