prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Fix sign-in
  We seem to have a problem with old cookies from a different account preventing log in.
  
  Goal page is not accessible once connected
  "405 Method Not Allowed"
  on this page 
  https://liberapay.com/unisson/goal.html when i want to change my goal
  I'm connected on my account.
  
  Fix sign-in
  We seem to have a problem with old cookies from a different account preventing log in.
  
  
  </issue>
  <code>
  [start of liberapay/security/authentication.py]
  1 """Defines website authentication helpers.
  2 """
  3 import binascii
  4 
  5 from aspen import Response
  6 from liberapay.constants import SESSION
  7 from liberapay.models.participant import Participant
  8 
  9 
  10 class _ANON(object):
  11     ANON = True
  12     is_admin = False
  13     id = None
  14     __bool__ = __nonzero__ = lambda *a: False
  15     get_tip_to = lambda self, tippee: Participant._zero_tip_dict(tippee)
  16     __repr__ = lambda self: '<ANON>'
  17 
  18 
  19 ANON = _ANON()
  20 
  21 
  22 def sign_in(request, state):
  23     try:
  24         body = request.body
  25     except Response:
  26         return
  27 
  28     p = None
  29 
  30     if body.get('log-in.username'):
  31         p = Participant.authenticate(
  32             'username', 'password',
  33             body.pop('log-in.username'), body.pop('log-in.password')
  34         )
  35         if p and p.status == 'closed':
  36             p.update_status('active')
  37 
  38     elif body.get('sign-in.username'):
  39         if body.pop('sign-in.terms') != 'agree':
  40             raise Response(400, 'you have to agree to the terms')
  41         kind = body.pop('sign-in.kind')
  42         if kind not in ('individual', 'organization'):
  43             raise Response(400, 'bad kind')
  44         with state['website'].db.get_cursor() as c:
  45             p = Participant.make_active(
  46                 body.pop('sign-in.username'), kind, body.pop('sign-in.password'),
  47                 cursor=c
  48             )
  49             p.add_email(body.pop('sign-in.email'), cursor=c)
  50         p.authenticated = True
  51 
  52     if p:
  53         response = state.setdefault('response', Response())
  54         p.sign_in(response.headers.cookie)
  55         if body.pop('form.repost', None) != 'true':
  56             response.redirect(request.line.uri)
  57         state['user'] = p
  58 
  59 
  60 def start_user_as_anon():
  61     """Make sure we always have a user object, regardless of exceptions during authentication.
  62     """
  63     return {'user': ANON}
  64 
  65 
  66 def authenticate_user_if_possible(request, state, user):
  67     """This signs the user in.
  68     """
  69     if request.line.uri.startswith('/assets/'):
  70         return
  71     if 'Authorization' in request.headers:
  72         header = request.headers['authorization']
  73         if not header.startswith('Basic '):
  74             raise Response(401, 'Unsupported authentication method')
  75         try:
  76             creds = binascii.a2b_base64(header[len('Basic '):]).split(':', 1)
  77         except binascii.Error:
  78             raise Response(400, 'Malformed "Authorization" header')
  79         participant = Participant.authenticate('id', 'password', *creds)
  80         if not participant:
  81             raise Response(401)
  82         return {'user': participant}
  83     elif SESSION in request.headers.cookie:
  84         creds = request.headers.cookie[SESSION].value.split(':', 1)
  85         p = Participant.authenticate('id', 'session', *creds)
  86         if p:
  87             return {'user': p}
  88     elif request.method == 'POST':
  89         sign_in(request, state)
  90 
  91 
  92 def add_auth_to_response(response, request=None, user=ANON):
  93     if request is None:
  94         return  # early parsing must've failed
  95     if request.line.uri.startswith('/assets/'):
  96         return  # assets never get auth headers
  97 
  98     if SESSION in request.headers.cookie:
  99         if not user.ANON:
  100             user.keep_signed_in(response.headers.cookie)
  101
  [end of liberapay/security/authentication.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/liberapay/security/authentication.py b/liberapay/security/authentication.py
  --- a/liberapay/security/authentication.py
  +++ b/liberapay/security/authentication.py
  @@ -19,12 +19,15 @@
   ANON = _ANON()
   
   
  -def sign_in(request, state):
  +def sign_in_with_form_data(request, state):
       try:
           body = request.body
       except Response:
           return
   
  +    if not isinstance(body, dict):
  +        return
  +
       p = None
   
       if body.get('log-in.username'):
  @@ -49,12 +52,7 @@
               p.add_email(body.pop('sign-in.email'), cursor=c)
           p.authenticated = True
   
  -    if p:
  -        response = state.setdefault('response', Response())
  -        p.sign_in(response.headers.cookie)
  -        if body.pop('form.repost', None) != 'true':
  -            response.redirect(request.line.uri)
  -        state['user'] = p
  +    return p
   
   
   def start_user_as_anon():
  @@ -68,6 +66,8 @@
       """
       if request.line.uri.startswith('/assets/'):
           return
  +
  +    # HTTP auth
       if 'Authorization' in request.headers:
           header = request.headers['authorization']
           if not header.startswith('Basic '):
  @@ -80,13 +80,26 @@
           if not participant:
               raise Response(401)
           return {'user': participant}
  -    elif SESSION in request.headers.cookie:
  +
  +    # Cookie and form auth
  +    # We want to try cookie auth first, but we want form auth to supersede it
  +    p = None
  +    response = state.setdefault('response', Response())
  +    if SESSION in request.headers.cookie:
           creds = request.headers.cookie[SESSION].value.split(':', 1)
           p = Participant.authenticate('id', 'session', *creds)
           if p:
  -            return {'user': p}
  -    elif request.method == 'POST':
  -        sign_in(request, state)
  +            state['user'] = p
  +    if request.method == 'POST':
  +        old_p = p
  +        p = sign_in_with_form_data(request, state)
  +        if p:
  +            if old_p:
  +                old_p.sign_out(response.headers.cookie)
  +            p.sign_in(response.headers.cookie)
  +            state['user'] = p
  +            if request.body.pop('form.repost', None) != 'true':
  +                response.redirect(request.line.uri)
   
   
   def add_auth_to_response(response, request=None, user=ANON):
  
verification_info: {"golden_diff": "diff --git a/liberapay/security/authentication.py b/liberapay/security/authentication.py\n--- a/liberapay/security/authentication.py\n+++ b/liberapay/security/authentication.py\n@@ -19,12 +19,15 @@\n ANON = _ANON()\n \n \n-def sign_in(request, state):\n+def sign_in_with_form_data(request, state):\n     try:\n         body = request.body\n     except Response:\n         return\n \n+    if not isinstance(body, dict):\n+        return\n+\n     p = None\n \n     if body.get('log-in.username'):\n@@ -49,12 +52,7 @@\n             p.add_email(body.pop('sign-in.email'), cursor=c)\n         p.authenticated = True\n \n-    if p:\n-        response = state.setdefault('response', Response())\n-        p.sign_in(response.headers.cookie)\n-        if body.pop('form.repost', None) != 'true':\n-            response.redirect(request.line.uri)\n-        state['user'] = p\n+    return p\n \n \n def start_user_as_anon():\n@@ -68,6 +66,8 @@\n     \"\"\"\n     if request.line.uri.startswith('/assets/'):\n         return\n+\n+    # HTTP auth\n     if 'Authorization' in request.headers:\n         header = request.headers['authorization']\n         if not header.startswith('Basic '):\n@@ -80,13 +80,26 @@\n         if not participant:\n             raise Response(401)\n         return {'user': participant}\n-    elif SESSION in request.headers.cookie:\n+\n+    # Cookie and form auth\n+    # We want to try cookie auth first, but we want form auth to supersede it\n+    p = None\n+    response = state.setdefault('response', Response())\n+    if SESSION in request.headers.cookie:\n         creds = request.headers.cookie[SESSION].value.split(':', 1)\n         p = Participant.authenticate('id', 'session', *creds)\n         if p:\n-            return {'user': p}\n-    elif request.method == 'POST':\n-        sign_in(request, state)\n+            state['user'] = p\n+    if request.method == 'POST':\n+        old_p = p\n+        p = sign_in_with_form_data(request, state)\n+        if p:\n+            if old_p:\n+                old_p.sign_out(response.headers.cookie)\n+            p.sign_in(response.headers.cookie)\n+            state['user'] = p\n+            if request.body.pop('form.repost', None) != 'true':\n+                response.redirect(request.line.uri)\n \n \n def add_auth_to_response(response, request=None, user=ANON):\n", "issue": "Fix sign-in\nWe seem to have a problem with old cookies from a different account preventing log in.\n\nGoal page is not accessible once connected\n\"405 Method Not Allowed\"\non this page \nhttps://liberapay.com/unisson/goal.html when i want to change my goal\nI'm connected on my account.\n\nFix sign-in\nWe seem to have a problem with old cookies from a different account preventing log in.\n\n", "before_files": [{"content": "\"\"\"Defines website authentication helpers.\n\"\"\"\nimport binascii\n\nfrom aspen import Response\nfrom liberapay.constants import SESSION\nfrom liberapay.models.participant import Participant\n\n\nclass _ANON(object):\n    ANON = True\n    is_admin = False\n    id = None\n    __bool__ = __nonzero__ = lambda *a: False\n    get_tip_to = lambda self, tippee: Participant._zero_tip_dict(tippee)\n    __repr__ = lambda self: '<ANON>'\n\n\nANON = _ANON()\n\n\ndef sign_in(request, state):\n    try:\n        body = request.body\n    except Response:\n        return\n\n    p = None\n\n    if body.get('log-in.username'):\n        p = Participant.authenticate(\n            'username', 'password',\n            body.pop('log-in.username'), body.pop('log-in.password')\n        )\n        if p and p.status == 'closed':\n            p.update_status('active')\n\n    elif body.get('sign-in.username'):\n        if body.pop('sign-in.terms') != 'agree':\n            raise Response(400, 'you have to agree to the terms')\n        kind = body.pop('sign-in.kind')\n        if kind not in ('individual', 'organization'):\n            raise Response(400, 'bad kind')\n        with state['website'].db.get_cursor() as c:\n            p = Participant.make_active(\n                body.pop('sign-in.username'), kind, body.pop('sign-in.password'),\n                cursor=c\n            )\n            p.add_email(body.pop('sign-in.email'), cursor=c)\n        p.authenticated = True\n\n    if p:\n        response = state.setdefault('response', Response())\n        p.sign_in(response.headers.cookie)\n        if body.pop('form.repost', None) != 'true':\n            response.redirect(request.line.uri)\n        state['user'] = p\n\n\ndef start_user_as_anon():\n    \"\"\"Make sure we always have a user object, regardless of exceptions during authentication.\n    \"\"\"\n    return {'user': ANON}\n\n\ndef authenticate_user_if_possible(request, state, user):\n    \"\"\"This signs the user in.\n    \"\"\"\n    if request.line.uri.startswith('/assets/'):\n        return\n    if 'Authorization' in request.headers:\n        header = request.headers['authorization']\n        if not header.startswith('Basic '):\n            raise Response(401, 'Unsupported authentication method')\n        try:\n            creds = binascii.a2b_base64(header[len('Basic '):]).split(':', 1)\n        except binascii.Error:\n            raise Response(400, 'Malformed \"Authorization\" header')\n        participant = Participant.authenticate('id', 'password', *creds)\n        if not participant:\n            raise Response(401)\n        return {'user': participant}\n    elif SESSION in request.headers.cookie:\n        creds = request.headers.cookie[SESSION].value.split(':', 1)\n        p = Participant.authenticate('id', 'session', *creds)\n        if p:\n            return {'user': p}\n    elif request.method == 'POST':\n        sign_in(request, state)\n\n\ndef add_auth_to_response(response, request=None, user=ANON):\n    if request is None:\n        return  # early parsing must've failed\n    if request.line.uri.startswith('/assets/'):\n        return  # assets never get auth headers\n\n    if SESSION in request.headers.cookie:\n        if not user.ANON:\n            user.keep_signed_in(response.headers.cookie)\n", "path": "liberapay/security/authentication.py"}]}