コード例 #1
0
def create_app(request):
    if request.method != "POST":
        response = PrettyJsonResponse({
            "success": False,
            "error": "Request is not of method POST"
        })
        response.status_code = 400
        return response

    try:
        name = request.POST["name"]
        user_id = request.session["user_id"]
    except (KeyError, AttributeError):
        response = PrettyJsonResponse({
            "success":
            False,
            "message":
            "Request does not have name or user."
        })
        response.status_code = 400
        return response

    user = get_user_by_id(user_id)

    new_app = App(name=name, user=user)
    new_app.save()

    keen_add_event.delay("App created", {
        "appid": new_app.id,
        "name": new_app.name,
        "userid": user.id
    })

    s = Scopes()

    return PrettyJsonResponse({
        "success": True,
        "message": "App sucessfully created",
        "app": {
            "name": new_app.name,
            "id": new_app.id,
            "token": new_app.api_token,
            "created": new_app.created,
            "updated": new_app.last_updated,
            "oauth": {
                "client_id": new_app.client_id,
                "client_secret": new_app.client_secret,
                "callback_url": new_app.callback_url,
                "scopes": s.get_all_scopes()
            },
            "webhook": {
                "verification_secret": new_app.webhook.verification_secret,
            }
        }
    })
コード例 #2
0
def regenerate_app_token(request):
    if request.method != "POST":
        response = PrettyJsonResponse({
            "success": False,
            "error": "Request is not of method POST"
        })
        response.status_code = 400
        return response

    try:
        app_id = request.POST["app_id"]
        user_id = request.session["user_id"]
    except (KeyError, AttributeError):
        response = PrettyJsonResponse({
            "success":
            False,
            "message":
            "Request does not have an app_id."
        })
        response.status_code = 400
        return response

    user = get_user_by_id(user_id)

    apps = App.objects.filter(id=app_id, user=user)
    if len(apps) == 0:
        response = PrettyJsonResponse({
            "success": False,
            "message": "App does not exist."
        })
        response.status_code = 400
        return response
    else:
        app = apps[0]
        app.regenerate_token()
        new_api_token = app.api_token

        keen_add_event.delay("App token regenerated", {
            "appid": app.id,
            "userid": user.id
        })

        return PrettyJsonResponse({
            "success": True,
            "message": "App token sucessfully regenerated.",
            "app": {
                "id": app.id,
                "token": new_api_token,
                "date": app.last_updated
            }
        })
コード例 #3
0
def rename_app(request):
    if request.method != "POST":
        response = PrettyJsonResponse({
            "success": False,
            "error": "Request is not of method POST"
        })
        response.status_code = 400
        return response

    try:
        app_id = request.POST["app_id"]
        new_name = request.POST["new_name"]
        user_id = request.session["user_id"]
    except (KeyError, AttributeError):
        response = PrettyJsonResponse({
            "success":
            False,
            "message":
            "Request does not have app_id/new_name"
        })
        response.status_code = 400
        return response

    user = get_user_by_id(user_id)

    apps = App.objects.filter(id=app_id, user=user, deleted=False)
    if len(apps) == 0:
        response = PrettyJsonResponse({
            "success": False,
            "message": "App does not exist."
        })
        response.status_code = 400
        return response
    else:
        app = apps[0]
        app.name = new_name
        app.save()

        keen_add_event.delay("App renamed", {
            "appid": app.id,
            "new_name": app.name,
            "userid": user.id
        })

        return PrettyJsonResponse({
            "success": True,
            "message": "App sucessfully renamed.",
            "date": app.last_updated
        })
コード例 #4
0
def myapps_shibboleth_callback(request):
    # should auth user login or signup
    # then redirect to my apps homepage
    eppn = request.META['HTTP_EPPN']
    groups = request.META['HTTP_UCLINTRANETGROUPS']
    cn = request.META['HTTP_CN']
    department = request.META['HTTP_DEPARTMENT']
    given_name = request.META['HTTP_GIVENNAME']
    display_name = request.META['HTTP_DISPLAYNAME']
    employee_id = request.META['HTTP_EMPLOYEEID']

    try:
        user = User.objects.get(email=eppn)
    except ObjectDoesNotExist:
        # create a new user
        new_user = User(email=eppn,
                        full_name=display_name,
                        given_name=given_name,
                        department=department,
                        cn=cn,
                        raw_intranet_groups=groups,
                        employee_id=employee_id)

        new_user.save()
        add_user_to_mailing_list_task.delay(new_user.email, new_user.full_name)

        request.session["user_id"] = new_user.id
        keen_add_event.delay("signup", {
            "id": new_user.id,
            "email": eppn,
            "name": display_name
        })
    else:
        # user exists already, update values
        request.session["user_id"] = user.id
        user.full_name = display_name
        user.given_name = given_name
        user.department = department
        user.raw_intranet_groups = groups
        user.employee_id = employee_id
        user.save()

        keen_add_event.delay("User data updated", {
            "id": user.id,
            "email": eppn,
            "name": display_name
        })

    return redirect("/oauth/myapps")
コード例 #5
0
ファイル: api_applications.py プロジェクト: hiMaisie/uclapi
def delete_app(request):
    if request.method != "POST":
        response = PrettyJsonResponse({
            "success": False,
            "error": "Request is not of method POST"
        })
        response.status_code = 400
        return response

    try:
        app_id = request.POST["app_id"]
        user_id = request.session["user_id"]
    except KeyError:
        response = PrettyJsonResponse({
            "success":
            False,
            "message":
            "Request does not have app_id."
        })
        response.status_code = 400
        return response

    user = get_user_by_id(user_id)

    apps = App.objects.filter(id=app_id, user=user)
    if len(apps) == 0:
        response = PrettyJsonResponse({
            "success": False,
            "message": "App does not exist."
        })
        response.status_code = 400
        return response
    else:
        app = apps[0]
        app.deleted = True
        app.save()

        keen_add_event.delay("App deleted", {
            "appid": app_id,
            "userid": user.id
        })

        return PrettyJsonResponse({
            "success": True,
            "message": "App sucessfully deleted.",
        })
コード例 #6
0
def log_api_call(request, token, token_type):
    service = request.path.split("/")[1]
    method = request.path.split("/")[2]

    headers = request.META
    version_headers = {}
    regex = re.compile("^HTTP_UCLAPI_.*_VERSION$")
    for header in headers:
        if regex.match(header):
            version_headers[header] = headers[header]

    queryparams = dict(request.GET)

    if token_type in {"general", "oauth"}:
        parameters = {
            "userid": token.user.id,
            "email": token.user.email,
            "name": token.user.given_name,
            "service": service,
            "method": method,
            "version-headers": version_headers,
            "queryparams": queryparams,
            "temp_token": False,
            "token_type": token_type
        }
    elif token_type == "general-temp":
        parameters = {
            "service": service,
            "method": method,
            "version-headers": version_headers,
            "queryparams": queryparams,
            "temp_token": True,
            "token_type": token_type
        }

    keen_add_event.delay("apicall", parameters)
コード例 #7
0
def update_scopes(request):
    if request.method != "POST":
        response = PrettyJsonResponse({
            "success": False,
            "error": "Request is not of method POST"
        })
        response.status_code = 400
        return response

    try:
        app_id = request.POST["app_id"]
    except KeyError:
        response = PrettyJsonResponse({
            "success":
            False,
            "message":
            "Request does not have an app_id."
        })
        response.status_code = 400
        return response

    try:
        user_id = request.session["user_id"]
    except (KeyError, AttributeError):
        response = PrettyJsonResponse({
            "success":
            False,
            "message":
            "User ID not set in session. Please log in again."
        })
        response.status_code = 400
        return response

    try:
        scopes_json = request.POST["scopes"]
    except KeyError:
        response = PrettyJsonResponse({
            "success": False,
            "message": "No scopes data attached."
        })
        response.status_code = 400
        return response

    try:
        scopes = json.loads(scopes_json)
    except ValueError:
        response = PrettyJsonResponse({
            "success":
            False,
            "message":
            "Invalid scope data that could not be parsed."
        })
        response.status_code = 400
        return response

    user = get_user_by_id(user_id)

    apps = App.objects.filter(id=app_id, user=user)
    if len(apps) == 0:
        response = PrettyJsonResponse({
            "success": False,
            "message": "App does not exist."
        })
        response.status_code = 400
        return response
    else:
        app = apps[0]
        current = app.scope.scope_number
        s = Scopes()
        try:
            for scope in scopes:
                if "checked" in scope and scope["checked"]:
                    current = s.add_scope(current, scope["name"])
                else:
                    current = s.remove_scope(current, scope["name"])

            app.scope.scope_number = current
            app.scope.save()
            app.save()
        except (KeyError, ValueError, TypeError):
            response = PrettyJsonResponse({
                "success":
                False,
                "message":
                "Invalid scope data that could not be iterated."
            })
            response.status_code = 400
            return response

        keen_add_event.delay("App scopes changed", {
            "appid": app_id,
            "userid": user.id,
            "scopes": scopes
        })

        return PrettyJsonResponse({
            "success": True,
            "message": "Scope successfully changed.",
        })
コード例 #8
0
def set_callback_url(request):
    if request.method != "POST":
        response = PrettyJsonResponse({
            "success": False,
            "error": "Request is not of method POST"
        })
        response.status_code = 400
        return response
    try:
        app_id = request.POST["app_id"]
    except KeyError:
        response = PrettyJsonResponse({
            "success":
            False,
            "message":
            "Request does not have an app_id."
        })
        response.status_code = 400
        return response

    try:
        user_id = request.session["user_id"]
    except (KeyError, AttributeError):
        response = PrettyJsonResponse({
            "success":
            False,
            "message":
            "User ID not set in session. Please log in again."
        })
        response.status_code = 400
        return response

    try:
        new_callback_url = request.POST["callback_url"]
    except KeyError:
        response = PrettyJsonResponse({
            "success":
            False,
            "message":
            "Request does not have a Callback URL."
        })
        response.status_code = 400
        return response
    url_not_safe_saved = is_url_unsafe(new_callback_url)
    if url_not_safe_saved:
        if url_not_safe_saved == NOT_HTTPS:
            message = "The requested callback URL does not "\
                      "start with 'https://'."
        elif url_not_safe_saved == NOT_VALID:
            message = "The requested callback URL is not valid."
        elif url_not_safe_saved == URL_BLACKLISTED:
            message = "The requested callback URL is forbidden."
        elif url_not_safe_saved == NOT_PUBLIC:
            message = "The requested callback URL is not publicly available."
        response = PrettyJsonResponse({"success": False, "message": message})
        response.status_code = 400
        return response

    user = get_user_by_id(user_id)

    apps = App.objects.filter(id=app_id, user=user)
    if len(apps) == 0:
        response = PrettyJsonResponse({
            "success": False,
            "message": "App does not exist."
        })
        response.status_code = 400
        return response

    app = apps[0]
    app.callback_url = new_callback_url
    app.save()

    keen_add_event.delay("App callback URL changed", {
        "appid": app_id,
        "userid": user.id,
        "newcallbackurl": new_callback_url
    })

    return PrettyJsonResponse({
        "success": True,
        "message": "Callback URL successfully changed.",
    })
コード例 #9
0
def shibcallback(request):
    # Callback from Shib login. Get ALL the meta!
    appdata_signed = request.GET.get("appdata", None)
    if not appdata_signed:
        response = PrettyJsonResponse({
            "ok":
            False,
            "error": ("No signed app data returned from Shibboleth."
                      " Please use the authorise endpoint.")
        })
        response.status_code = 400
        return response

    signer = TimestampSigner()
    try:
        # Expire our signed tokens after five minutes for added security
        appdata = signer.unsign(appdata_signed, max_age=300)
    except signing.SignatureExpired:
        response = PrettyJsonResponse({
            "ok":
            False,
            "error": ("Login data has expired. Please attempt to log in "
                      "again. If the issues persist please contact the "
                      "UCL API Team to rectify this.")
        })
        response.status_code = 400
        return response
    except signing.BadSignature:
        response = PrettyJsonResponse({
            "ok":
            False,
            "error": ("Bad signature. Please attempt to log in again. "
                      "If the issues persist please contact the UCL API "
                      "Team to rectify this.")
        })
        response.status_code = 400
        return response

    client_id = appdata[:33]
    state = appdata[33:]

    # We can trust this value because it was extracted from the signed data
    # string sent via Shibboleth
    app = App.objects.get(client_id=client_id)

    eppn = request.META['HTTP_EPPN']
    groups = request.META['HTTP_UCLINTRANETGROUPS']
    cn = request.META['HTTP_CN']
    department = request.META['HTTP_DEPARTMENT']
    given_name = request.META['HTTP_GIVENNAME']
    display_name = request.META['HTTP_DISPLAYNAME']
    employee_id = request.META['HTTP_EMPLOYEEID']

    # If a user has never used the API before then we need to sign them up
    try:
        user = User.objects.get(email=eppn)
    except User.DoesNotExist:
        # create a new user
        user = User(email=eppn,
                    full_name=display_name,
                    given_name=given_name,
                    department=department,
                    cn=cn,
                    raw_intranet_groups=groups,
                    employee_id=employee_id)

        user.save()
        keen_add_event.delay("signup", {
            "id": user.id,
            "email": eppn,
            "name": display_name
        })
    else:
        # User exists already, so update the values
        user = User.objects.get(email=eppn)
        user.full_name = display_name
        user.given_name = given_name
        user.department = department
        user.raw_intranet_groups = groups
        user.employee_id = employee_id
        user.save()

        keen_add_event.delay("User data updated", {
            "id": user.id,
            "email": eppn,
            "name": display_name
        })

    # Log the user into the system using their User ID
    request.session["user_id"] = user.id

    signer = TimestampSigner()
    response_data = {
        "client_id": app.client_id,
        "state": state,
        "user_upi": user.employee_id
    }

    response_data_str = json.dumps(response_data, cls=DjangoJSONEncoder)
    response_data_signed = signer.sign(response_data_str)

    s = Scopes()

    page_data = {
        "app_name": app.name,
        "creator": app.user.full_name,
        "client_id": app.client_id,
        "state": state,
        "scopes": s.scope_dict(app.scope.scope_number),
        "user": {
            "full_name": user.full_name,
            "cn": user.cn,
            "email": user.email,
            "department": user.department,
            "upi": user.employee_id
        },
        "signed_data": response_data_signed
    }

    initial_data = json.dumps(page_data, cls=DjangoJSONEncoder)
    return render(request, 'permissions.html', {'initial_data': initial_data})
コード例 #10
0
def edit_webhook(request):
    if request.method != "POST":
        response = PrettyJsonResponse({
            "ok":
            False,
            "message": ("Request is not of method POST")
        })
        response.status_code = 400
        return response

    try:
        app_id = request.POST["app_id"]
        url = request.POST["url"]
        siteid = request.POST["siteid"]
        roomid = request.POST["roomid"]
        contact = request.POST["contact"]
        user_id = request.session["user_id"]
    except KeyError:
        response = PrettyJsonResponse({
            "ok":
            False,
            "message": ("Request is missing parameters. Should have app_id"
                        ", url, siteid, roomid, contact"
                        " as well as a sessionid cookie")
        })
        response.status_code = 400
        return response

    if not user_owns_app(user_id, app_id):
        response = PrettyJsonResponse({
            "ok":
            False,
            "message": ("App does not exist or user is lacking permission.")
        })
        response.status_code = 400
        return response

    app = App.objects.get(id=app_id)
    webhook = app.webhook

    if url != webhook.url:
        if is_url_unsafe(url):
            response = PrettyJsonResponse({
                "ok": False,
                "message": ("Invalid URL")
            })
            response.status_code = 400
            return response

        if not verify_ownership(url, generate_secret(),
                                webhook.verification_secret):
            response = PrettyJsonResponse({
                "ok":
                False,
                "message": ("Ownership of webhook can't be verified."
                            "Make sure to follow the documentation: "
                            "https://uclapi.com/docs#webhook/challenge-event")
            })
            response.status_code = 400
            return response

        webhook.url = url
        webhook.save()

    webhook.siteid = siteid
    webhook.roomid = roomid
    webhook.contact = contact
    webhook.enabled = True
    webhook.save()

    keen_add_event.delay(
        "Webhook edited", {
            "appid": app.id,
            "userid": user_id,
            "url": url,
            "siteid": siteid,
            "roomid": roomid,
            "contact": contact,
        })

    return PrettyJsonResponse({
        "ok": True,
        "message": "Webhook sucessfully changed.",
        "url": webhook.url,
        "roomid": webhook.roomid,
        "siteid": webhook.siteid,
        "contact": webhook.contact
    })
コード例 #11
0
def set_callback_url(request):
    if request.method != "POST":
        response = PrettyJsonResponse({
            "success": False,
            "error": "Request is not of method POST"
        })
        response.status_code = 400
        return response
    try:
        app_id = request.POST["app_id"]
    except KeyError:
        response = PrettyJsonResponse({
            "success":
            False,
            "message":
            "Request does not have an app_id."
        })
        response.status_code = 400
        return response

    try:
        user_id = request.session["user_id"]
    except (KeyError, AttributeError):
        response = PrettyJsonResponse({
            "success":
            False,
            "message":
            "User ID not set in session. Please log in again."
        })
        response.status_code = 400
        return response

    try:
        new_callback_url = request.POST["callback_url"]
    except KeyError:
        response = PrettyJsonResponse({
            "success":
            False,
            "message":
            "Request does not have a Callback URL."
        })
        response.status_code = 400
        return response

    if not is_url_safe(new_callback_url):
        response = PrettyJsonResponse({
            "success":
            False,
            "message": ("The requested callback URL"
                        " is not valid.")
        })
        response.status_code = 400
        return response

    user = get_user_by_id(user_id)

    apps = App.objects.filter(id=app_id, user=user)
    if len(apps) == 0:
        response = PrettyJsonResponse({
            "success": False,
            "message": "App does not exist."
        })
        response.status_code = 400
        return response

    app = apps[0]
    app.callback_url = new_callback_url
    app.save()

    keen_add_event.delay("App callback URL changed", {
        "appid": app_id,
        "userid": user.id,
        "newcallbackurl": new_callback_url
    })

    return PrettyJsonResponse({
        "success": True,
        "message": "Callback URL successfully changed.",
    })