internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: uclapi/uclapi

Issue:
Webhooks
They haven't been delivered for a _long_ time now, so we finally need to dig deep and see what is going wrong. The room data is definitely up to date, however.


Discussion:
This is *still*, shamefully, broken. Fixes to this will likely come with DevOps improvements as we review our caching operations.

Resolving patch:
diff --git a/backend/uclapi/roombookings/management/commands/trigger_webhooks.py b/backend/uclapi/roombookings/management/commands/trigger_webhooks.py
--- a/backend/uclapi/roombookings/management/commands/trigger_webhooks.py
+++ b/backend/uclapi/roombookings/management/commands/trigger_webhooks.py
@@ -4,16 +4,25 @@
 from dashboard.models import Webhook, WebhookTriggerHistory
 from datetime import datetime
 from deepdiff import DeepDiff
-import grequests
 from django.utils import timezone
+from requests_futures.sessions import FuturesSession
 
 
 class Command(BaseCommand):
 
     help = 'Diff roombooking result sets and notify relevant webhooks'
 
+    def add_arguments(self, parser):
+        parser.add_argument(
+            '--debug',
+            action='store_true',
+            dest='debug',
+            help='Print webhook responses',
+        )
+
     def handle(self, *args, **options):
         self.stdout.write("Triggering webhooks")
+        session = FuturesSession()
 
         # currently locked table is the old one, more recent one is not locked
         lock = Lock.objects.all()[0]  # there is only ever one lock
@@ -121,10 +130,11 @@ def webhook_filter(booking):
 
             webhooks_to_enact[idx]["payload"] = payload
 
-            if payload["content"] != {}:
+            if payload["content"] != {} and webhook["url"] != "":
                 unsent_requests.append(
-                    grequests.post(
-                        webhook["url"], json=payload, headers={
+                    session.post(
+                        webhook["url"], json=payload,
+                        headers={
                             "User-Agent": "uclapi-bot/1"
                         }
                     )
@@ -132,7 +142,11 @@ def webhook_filter(booking):
         self.stdout.write(
             "Triggering {} webhooks.".format(len(unsent_requests))
         )
-        grequests.map(unsent_requests)
+        if("debug" in options):
+            for i in unsent_requests:
+                self.stdout.write(
+                    'response status {0}'.format(i.result().status_code)
+                )
 
         for webhook in webhooks_to_enact:
             if webhook["payload"]["content"] != {}:


Test patch:
Repository: uclapi/uclapi

Issue:
OAuth Standards Compliance
So it turns out that my OAuth 2.0 implementation violates section 4.2.2 of RFC 6749 by calling the UCL API User Token just a `token` and not an `access_token`.

This breaks apps (such as Discourse) that rely on OAuth implementations actually being standards compliant. Whoopsidaisies!


Discussion:
This is issue #999 because fixing this is an EMERGENCY since we don't follow standards!

Resolving patch:
diff --git a/backend/uclapi/oauth/views.py b/backend/uclapi/oauth/views.py
--- a/backend/uclapi/oauth/views.py
+++ b/backend/uclapi/oauth/views.py
@@ -461,6 +461,7 @@ def token(request):
         "state": state,
         "client_id": app.client_id,
         "token": token.token,
+        "access_token": token.token,
         "scope": json.dumps(s.scope_dict(token.scope.scope_number))
     }
 


Test patch:
Repository: uclapi/uclapi

Issue:
Workspaces Summary Endpoint Data Out of Date
We have had reports that the Workspaces Summary endpoint is not supplying up to date data. This is a high priority bug if confirmed. Thanks to @henryzhang00 for the report!


Discussion:
If the header is correct we haven't updated the cache in 2 days??
If that's the case then I need to sort this ASAP because the only thing worse than an API that's down is an API that's supplying faulty data
Are there logs for the cronbox that runs cache.py. It should update the header at the bottom so that indicates we aren't reaching that line, or the commands just isn't running at all.
Yeah I checked the cron box logs, and found that some code was tripping over itself so I updated the crontab to give the full cache more breathing room the 2am cache time.

Resolving patch:
diff --git a/backend/uclapi/workspaces/occupeye/cache.py b/backend/uclapi/workspaces/occupeye/cache.py
--- a/backend/uclapi/workspaces/occupeye/cache.py
+++ b/backend/uclapi/workspaces/occupeye/cache.py
@@ -253,12 +253,13 @@ def cache_all_survey_sensor_states(self, survey_id):
                 # This is a rare case, so just set it to False.
                 # Easier than expecting our clients to deal with null
                 occupied_state = False
-            pipeline.hmset(sensor_status_key, {
+            sensor_status = {
                 "occupied": str(occupied_state),
-                "hardware_id": sensor_data["HardwareID"],
-                "last_trigger_type": sensor_data["LastTriggerType"],
-                "last_trigger_timestamp": sensor_data["LastTriggerTime"]
-            })
+                "hardware_id": str(sensor_data["HardwareID"]),
+                "last_trigger_type": str(sensor_data["LastTriggerType"]),
+                "last_trigger_timestamp": str(sensor_data["LastTriggerTime"])
+            }
+            pipeline.hmset(sensor_status_key, sensor_status)
 
         pipeline.execute()
 


Test patch:
Repository: uclapi/uclapi

Issue:
Medium Articles Bug
Bug in getting medium articles on the homepage


Discussion:

Resolving patch:
diff --git a/backend/uclapi/dashboard/app_helpers.py b/backend/uclapi/dashboard/app_helpers.py
--- a/backend/uclapi/dashboard/app_helpers.py
+++ b/backend/uclapi/dashboard/app_helpers.py
@@ -4,9 +4,10 @@
 from common.helpers import generate_api_token
 from uclapi.settings import (
     MEDIUM_ARTICLE_QUANTITY,
-    REDIS_UCLAPI_HOST
+    REDIS_UCLAPI_HOST,
+    DEBUG
 )
-
+from django.core.management import call_command
 import os
 import redis
 import textwrap
@@ -15,6 +16,11 @@
 
 def get_articles():
     r = redis.Redis(host=REDIS_UCLAPI_HOST)
+    if not r.exists("Blog:item:1:url"):
+        if DEBUG:
+            call_command('update_medium')
+        else:
+            return []
     pipe = r.pipeline()
     articles = []
     for i in range(0, MEDIUM_ARTICLE_QUANTITY):


Test patch:
Repository: uclapi/uclapi

Issue:
AMP/Instance Data not returned by the personal timetable endpoints
`timetable/app_helpers.py`, line 288 should have the following:
```
"instance": instance_data
```


Discussion:

Resolving patch:
diff --git a/backend/uclapi/timetable/app_helpers.py b/backend/uclapi/timetable/app_helpers.py
--- a/backend/uclapi/timetable/app_helpers.py
+++ b/backend/uclapi/timetable/app_helpers.py
@@ -284,7 +284,8 @@ def _get_timetable_events(full_modules, stumodules):
                         "session_type_str": _get_session_type_str(
                             event.moduletype
                         ),
-                        "contact": booking.condisplayname
+                        "contact": booking.condisplayname,
+                        "instance": instance_data
                     }
 
                     # If this is student module data, add in the group code


Test patch:
Repository: uclapi/uclapi

Issue:
Webhooks are not deleted upon App deleting
Create an app, link webhook. delete app. The webhook will still fire.


Discussion:

Resolving patch:
diff --git a/backend/uclapi/dashboard/api_applications.py b/backend/uclapi/dashboard/api_applications.py
--- a/backend/uclapi/dashboard/api_applications.py
+++ b/backend/uclapi/dashboard/api_applications.py
@@ -202,6 +202,13 @@ def delete_app(request):
     else:
         app = apps[0]
         app.deleted = True
+        webhook = app.webhook
+        webhook.url = ""
+        webhook.siteid = ""
+        webhook.roomid = ""
+        webhook.contact = ""
+        webhook.enabled = False
+        webhook.save()
         app.save()
 
         keen_add_event.delay("App deleted", {
diff --git a/backend/uclapi/roombookings/management/commands/trigger_webhooks.py b/backend/uclapi/roombookings/management/commands/trigger_webhooks.py
--- a/backend/uclapi/roombookings/management/commands/trigger_webhooks.py
+++ b/backend/uclapi/roombookings/management/commands/trigger_webhooks.py
@@ -50,7 +50,7 @@ def handle(self, *args, **options):
 
         ddiff = DeepDiff(old_bookings, new_bookings, ignore_order=True)
 
-        webhooks = Webhook.objects.all()
+        webhooks = Webhook.objects.filter(app__deleted=False)
         #  assumption: list of webhooks will be longer than ddiff
 
         num_bookings_added = 0


Test patch:
Repository: uclapi/uclapi

Issue:
Data exposed by webhooks, not shown by /bookings
An example is Gordon St (22) 4.01 . which is provided by webhooks when bookings change but we do not return it for bookings usually.


Discussion:

Resolving patch:
diff --git a/backend/uclapi/roombookings/management/commands/trigger_webhooks.py b/backend/uclapi/roombookings/management/commands/trigger_webhooks.py
--- a/backend/uclapi/roombookings/management/commands/trigger_webhooks.py
+++ b/backend/uclapi/roombookings/management/commands/trigger_webhooks.py
@@ -7,6 +7,7 @@
 from deepdiff import DeepDiff
 from django.utils import timezone
 from requests_futures.sessions import FuturesSession
+from django.db.models import Q
 
 
 class Command(BaseCommand):
@@ -39,11 +40,13 @@ def handle(self, *args, **options):
 
         old_bookings = _serialize_bookings(
             old_booking_table.objects.filter(
+                Q(bookabletype='CB') | Q(siteid='238') | Q(siteid='240'),
                 startdatetime__gt=now
             )
         )
         new_bookings = _serialize_bookings(
             new_booking_table.objects.filter(
+                Q(bookabletype='CB') | Q(siteid='238') | Q(siteid='240'),
                 startdatetime__gt=now
             )
         )


Test patch:
Repository: uclapi/uclapi

Issue:
[BUG] Dates on the dashboard are incorrect
**Describe the bug**
The created at and last modified dates for apps on the dashboard are incorrect.

![image](https://user-images.githubusercontent.com/6523121/67673142-48d43c00-f971-11e9-89fa-711589d1cca4.png)

(this app was not created on 28th October; it was created several months before)


Discussion:

Resolving patch:
diff --git a/backend/uclapi/oauth/urls.py b/backend/uclapi/oauth/urls.py
--- a/backend/uclapi/oauth/urls.py
+++ b/backend/uclapi/oauth/urls.py
@@ -15,4 +15,5 @@
     url(r'user/data$', views.userdata),
     url(r'user/studentnumber$', views.get_student_number),
     url(r'deauthorise$', views.deauthorise_app),
+    url(r'logout$', views.logout),
 ]
diff --git a/backend/uclapi/oauth/views.py b/backend/uclapi/oauth/views.py
--- a/backend/uclapi/oauth/views.py
+++ b/backend/uclapi/oauth/views.py
@@ -665,7 +665,7 @@ def my_apps(request):
         url = os.environ["SHIBBOLETH_ROOT"] + "/Login?target="
         param = urllib.parse.urljoin(
             request.build_absolute_uri(request.path),
-            "/shibcallback"
+            "/oauth/myapps/shibcallback"
         )
         param = quote(param)
         url = url + param
@@ -759,3 +759,10 @@ def deauthorise_app(request):
     })
     response.status_code = 200
     return response
+
+
+@ensure_csrf_cookie
+def logout(request):
+    response = redirect('/')
+    response.delete_cookie('user_id')
+    return response
\ No newline at end of file


Test patch:
Repository: uclapi/uclapi

Issue:
Broken logging in flow for the settings page
**Describe the bug**
Logging in when accessing settings page leads to 404

**To Reproduce**
Clear your cache 
Go to uclapi.com
Click on settings 
Log into your account
Observe 404 uclapi.com/shibcallback does not exist:

**Expected behavior**
Should redirect to the callback for the settings page

OR 

Could redesign so the log in button redirects to the home page and then once logged in those pages are accessible

**Screenshots**
If applicable, add screenshots to help explain your problem.
![image](https://user-images.githubusercontent.com/3999881/75058538-17a8ea00-54d3-11ea-997f-63b4cb72b4bb.png)





Discussion:

Resolving patch:
diff --git a/backend/uclapi/oauth/urls.py b/backend/uclapi/oauth/urls.py
--- a/backend/uclapi/oauth/urls.py
+++ b/backend/uclapi/oauth/urls.py
@@ -4,7 +4,6 @@
 
 urlpatterns = [
     url(r'myapps/shibcallback$', views.myapps_shibboleth_callback),
-	url(r'myapps', views.my_apps),
     url(r'authorise/$', views.authorise),
     url(r'shibcallback', views.shibcallback),
     url(r'token$', views.token),
@@ -15,5 +14,4 @@
     url(r'user/data$', views.userdata),
     url(r'user/studentnumber$', views.get_student_number),
     url(r'deauthorise$', views.deauthorise_app),
-    url(r'logout$', views.logout),
 ]
diff --git a/backend/uclapi/oauth/views.py b/backend/uclapi/oauth/views.py
--- a/backend/uclapi/oauth/views.py
+++ b/backend/uclapi/oauth/views.py
@@ -652,11 +652,11 @@ def myapps_shibboleth_callback(request):
             user.raw_intranet_groups = groups
         user.save()
 
-    return redirect("/oauth/myapps")
+    return redirect(settings)
 
 
 @ensure_csrf_cookie
-def my_apps(request):
+def settings(request):
     # Check whether the user is logged in
     try:
         user_id = request.session["user_id"]
@@ -763,6 +763,10 @@ def deauthorise_app(request):
 
 @ensure_csrf_cookie
 def logout(request):
-    response = redirect('/')
-    response.delete_cookie('user_id')
+    try:
+        del request.session['user_id']
+    except KeyError:
+        pass
+        
+    response = redirect('/', )
     return response
\ No newline at end of file
diff --git a/backend/uclapi/uclapi/urls.py b/backend/uclapi/uclapi/urls.py
--- a/backend/uclapi/uclapi/urls.py
+++ b/backend/uclapi/uclapi/urls.py
@@ -15,10 +15,11 @@
 """
 from django.conf.urls import url, include
 from django.contrib import admin
+from django.urls import path
 from dashboard.views import documentation, home, about
+from oauth.views import settings, logout
 from marketplace.views import marketplace
 
-
 app_name = "uclapi"
 
 urlpatterns = [
@@ -26,6 +27,8 @@
     url(r'^dashboard/', include('dashboard.urls')),
     url(r'^docs', documentation),
     url(r'^about', about),
+    path('settings/', settings),
+    path('logout/', logout),
     url(r'^marketplace', marketplace),
     url(r'^roombookings/', include('roombookings.urls')),
     url(r'^oauth/', include('oauth.urls')),


Test patch:
Repository: uclapi/uclapi

Issue:
Document date_filter parameter for timetable endpoint
**Is your feature request related to a problem? Please describe.**

The /timetable/personal endpoint accepts an undocumented `date_filter` query parameter in ISO 8601 format, i.e. YYYY-MM-DD

**Describe the solution you'd like**

Document this in uclapi.com/docs


Discussion:
Depends on #1934 

Basically, if people start to split their requests into smaller dates than 1 year, then it will actually affect our performance worse. Once the above issue is resolved then we can actually publicise this. I'll add this onto my ever-growing TODO.
Since #1934 has been indicated as less important due to caching, this can now be done.

Resolving patch:
diff --git a/backend/uclapi/timetable/views.py b/backend/uclapi/timetable/views.py
--- a/backend/uclapi/timetable/views.py
+++ b/backend/uclapi/timetable/views.py
@@ -34,11 +34,8 @@ def get_personal_timetable_endpoint(request, *args, **kwargs):
     """
     token = kwargs['token']
     user = token.user
-    try:
-        date_filter = request.GET["date_filter"]
-        timetable = get_student_timetable(user.employee_id, date_filter)
-    except KeyError:
-        timetable = get_student_timetable(user.employee_id)
+    date_filter = request.GET.get("date")
+    timetable = get_student_timetable(user.employee_id, date_filter)
 
     response = {
         "ok": True,
@@ -66,7 +63,7 @@ def get_modules_timetable_endpoint(request, *args, **kwargs):
 
     modules = module_ids.split(',')
 
-    date_filter = request.GET.get("date_filter")
+    date_filter = request.GET.get("date")
     custom_timetable = get_custom_timetable(modules, date_filter)
 
     if custom_timetable:


Test patch:
Repository: uclapi/uclapi

Issue:
[BUG] cachet URL error
Currently when sending requests to the status page we are getting the error 

```Unexpected: Failed to create fixed cachet incident. Reason: ValueError("Cannot determine api version based on endpoint 'https://cachet.apps.uclapi.com/api/v1/'. If the api version is not present in the url, please supply it on client creation.")```



Discussion:

Resolving patch:
diff --git a/backend/uclapi/common/cachet.py b/backend/uclapi/common/cachet.py
--- a/backend/uclapi/common/cachet.py
+++ b/backend/uclapi/common/cachet.py
@@ -77,7 +77,8 @@ def create_incident(error_message: str, component_name: str,
     """
 
     cachet_client = cachetclient.Client(endpoint=settings.CACHET_URL,
-                                        api_token=settings.CACHET_TOKEN)
+                                        api_token=settings.CACHET_TOKEN,
+                                        version="1")
 
     target_comp = _get_component(cachet_client, component_name)
 
@@ -112,7 +113,8 @@ def update_incident(update_message: str, component_name: str,
     """
 
     cachet_client = cachetclient.Client(endpoint=settings.CACHET_URL,
-                                        api_token=settings.CACHET_TOKEN)
+                                        api_token=settings.CACHET_TOKEN,
+                                        version="1")
 
     target_comp = _get_component(cachet_client, component_name)
 


Test patch:
Repository: uclapi/uclapi

Issue:
[BUG] Requests of Undefined when Creating a New App
**Describe the bug**
When creating a new app on the staging.ninja dashboard the redirect page fails to render.

**To Reproduce**
Steps to reproduce the behavior:
1. Create a new app on https://staging.ninja/dashboard/

**Expected behavior**
Return to app list page.

**Screenshots**
```js
vendors-66dfc54de2ab880932e8.js:2 TypeError: Cannot read property 'requests' of undefined
    at dashboard-edcd2f4fb681f0126f93.js:1
    at Array.map (<anonymous>)
    at A.value (dashboard-edcd2f4fb681f0126f93.js:1)
    at jo (vendors-66dfc54de2ab880932e8.js:2)
    at Yo (vendors-66dfc54de2ab880932e8.js:2)
    at ys (vendors-66dfc54de2ab880932e8.js:2)
    at El (vendors-66dfc54de2ab880932e8.js:2)
    at fl (vendors-66dfc54de2ab880932e8.js:2)
    at sl (vendors-66dfc54de2ab880932e8.js:2)
    at vendors-66dfc54de2ab880932e8.js:2

dashboard-edcd2f4fb681f0126f93.js:1 Uncaught (in promise) TypeError: Cannot read property 'requests' of undefined
    at dashboard-edcd2f4fb681f0126f93.js:1
    at Array.map (<anonymous>)
    at A.value (dashboard-edcd2f4fb681f0126f93.js:1)
    at jo (vendors-66dfc54de2ab880932e8.js:2)
    at Yo (vendors-66dfc54de2ab880932e8.js:2)
    at ys (vendors-66dfc54de2ab880932e8.js:2)
    at El (vendors-66dfc54de2ab880932e8.js:2)
    at fl (vendors-66dfc54de2ab880932e8.js:2)
    at sl (vendors-66dfc54de2ab880932e8.js:2)
    at vendors-66dfc54de2ab880932e8.js:2
```


**Additional context**
Does not occur in production.



Discussion:

Resolving patch:
diff --git a/backend/uclapi/dashboard/api_applications.py b/backend/uclapi/dashboard/api_applications.py
--- a/backend/uclapi/dashboard/api_applications.py
+++ b/backend/uclapi/dashboard/api_applications.py
@@ -65,6 +65,12 @@ def create_app(request):
             },
             "webhook": {
                 "verification_secret": new_app.webhook.verification_secret,
+            },
+            "analytics": {
+                "requests": 0,
+                "remaining_quota": User._meta.get_field('oauth_quota').get_default(),
+                "users": 0,
+                "users_per_dept": []
             }
         }
     })


Test patch:
Repository: uclapi/uclapi

Issue:
[BUG] AttributeError /dashboard/api/analytics/quota
**Describe the bug**
`AttributeError` `/dashboard/api/analytics/quota`
`NoneType` object has no attribute 'user'

**To Reproduce**
Steps to reproduce the behavior:
1.  `https://uclapi.com/dashboard/api/analytics/quota`
2.  HTTP 500

**Expected behavior**
Not crash

**Additional context**
`dashboard/api_applications.py:479`


Discussion:
note to self: it's when a token is in the valid format but does not exist (but this error doesn't happen on other endpoints with the same situation)

Resolving patch:
diff --git a/backend/uclapi/dashboard/api_applications.py b/backend/uclapi/dashboard/api_applications.py
--- a/backend/uclapi/dashboard/api_applications.py
+++ b/backend/uclapi/dashboard/api_applications.py
@@ -481,12 +481,17 @@ def get_quota_remaining(token):
 
     if token.startswith('uclapi-user-'):
         Otoken = OAuthToken.objects.filter(token__exact=token).first()
+        if Otoken is None:
+            return None
 
         cache_key = "oauth:" + Otoken.user.email
         limit = Otoken.user.oauth_quota
 
     elif token.startswith('uclapi-'):
         app = App.objects.filter(api_token__exact=token).first()
+        if app is None:
+            return None
+
         cache_key = app.user.email
         limit = app.user.dev_quota
 


Test patch:
diff --git a/backend/uclapi/dashboard/tests.py b/backend/uclapi/dashboard/tests.py
--- a/backend/uclapi/dashboard/tests.py
+++ b/backend/uclapi/dashboard/tests.py
@@ -1142,6 +1142,18 @@ def test_analytics_bad_token_provided(self):
             self.assertEqual(response.status_code, 400)
             self.assertEqual(content["message"], "Token is invalid")
 
+    def test_analytics_quota_non_existent_token_provided(self):
+        request = self.factory.get(
+            '/api/analytics/quota',
+            {
+                "token": "uclapi-user-nonexistenttoken"
+            }
+        )
+        response = quota_remaining(request)
+        content = json.loads(response.content.decode())
+        self.assertEqual(response.status_code, 400)
+        self.assertEqual(content["message"], "Token is invalid")
+
     def test_analytics_num_requests_good_app_token_flow(self):
         # Set up token
         user_ = User.objects.create(
Repository: uclapi/uclapi

Issue:
[Feature Request] Add /authorize Oauth route
**Is your feature request related to a problem? Please describe.**
I  have been attempting to use 'auth0-react' to implement Oauth with UCL API, however, this requires a fair bit of tinkering as
the defaults of this and many other auth libraries are to redirect to a "/authorize?client_id..." endpoint which the UCL API does not support. 

While this can be avoided through customisation,  would it be possible to add a "/authorize" route, as I believe this could make it easier to use some of the "plug and play" Americanized auth libraries available?

**Describe the solution you'd like**

 Edit uclapi/backend/uclapi/oauth/urls.py as below 
```
urlpatterns = [
    url(r'authorise/$', views.authorise),
    url(r'authorize/$', views.authorise),    <===== Including views.authorise for the  'authorize/$' route.
    url(r'shibcallback', views.shibcallback),
    url(r'token$', views.token),
    url(r'tokens/scopes$', views.scope_map),
    url(r'tokens/test$', views.token_test),
    url(r'user/allow$', views.userallow),
    url(r'user/deny$', views.userdeny),
    url(r'user/data$', views.userdata),
    url(r'user/studentnumber$', views.get_student_number),
    url(r'deauthorise$', views.deauthorise_app),
    url(r'user/settings$', views.get_settings)
]
```

![image](https://user-images.githubusercontent.com/57833957/219857932-86c371d5-c0f0-444b-a179-6c312b48c9c2.png)

![image](https://user-images.githubusercontent.com/57833957/219857962-7da7e11e-475b-4d6c-bb71-1c6eefcf0354.png)





Discussion:

Resolving patch:
diff --git a/backend/uclapi/oauth/urls.py b/backend/uclapi/oauth/urls.py
--- a/backend/uclapi/oauth/urls.py
+++ b/backend/uclapi/oauth/urls.py
@@ -4,6 +4,7 @@
 
 urlpatterns = [
     url(r'authorise/$', views.authorise),
+    url(r'authorize/$', views.authorise),
     url(r'adcallback', views.adcallback),
     url(r'token$', views.token),
     url(r'tokens/scopes$', views.scope_map),


Test patch: