Esempio n. 1
0
def login(request):
    '''
    Handles login requests
    '''
    # Check if bypass mode is enabled
    if settings.AUTH_BYPASS:
        request.session['userid'] = settings.AUTH_BYPASS_USER
        request.session['is_admin'] = get_is_admin(request.session['userid'])
        logging.debug(
            f"Auth bypass mode is enabled. Logging in as {request.session['userid']}"
        )
        return redirect('/search')

    # If they are already logged in, send users to search page
    if request.session.get('userid', False):
        request.session['is_admin'] = get_is_admin(request.session['userid'])
        logging.debug(f"User already logged in: {request.session['userid']}")
        return redirect('/search')

    # Check if the logon was successful already
    if request.META.get('REMOTE_USER', False):
        logging.debug("Found signed-in Cosign user")
        remote_user = request.META['REMOTE_USER']
        if '@' in remote_user:
            return redirect('/unauthorized')
        request.session['userid'] = remote_user
        request.session['is_admin'] = get_is_admin(request.session['userid'])
        return redirect('/search')
    else:
        logging.debug("Authenticating the user")
        return redirect("/login")

    # Send users to the search page on sucessful login
    return redirect('/search')
def admin_searches(request):
    '''
    Render the admin page
    '''
    # Verify that the user is logged in and an admin
    if not request.session.get('userid', False) or not get_is_admin(
            request.session['userid']):
        return redirect('/login')

    response = {}
    response["headings"] = ["Date Submitted", "Query", "Progress"]

    if "error_message" in request.session:
        response["error_message"] = request.session["error_message"]
        request.session[
            "error_message"] = ""  # clear it out so it won't show on refresh

    all_user_searches = searches.objects.all().filter(
        deleted=False).order_by('-date_submitted')
    all_user_searches_hist = historical_searches.objects.all().filter(
        deleted=False).order_by('-date_submitted')

    for search_obj in all_user_searches:
        search_obj = build_search_info(search_obj)

    for search_obj in all_user_searches_hist:
        search_obj = build_search_info(search_obj)
        search_obj.status = "Deleted"

    response["searches"] = chain(all_user_searches, all_user_searches_hist)
    response["num_months_keep_searches"] = settings.NUM_MONTHS_KEEP_SEARCHES

    return render(request, 'textassembler_web/allsearches.html', response)
Esempio n. 3
0
def delete_admin_user(request, userid):
    '''
    delete the given user from the administrators table
    '''
    # Verify that the user is logged in and an admin
    if not request.session.get('userid', False) or not get_is_admin(request.session['userid']):
        return redirect('/login')

    # Clear past error messages
    request.session["error_message"] = ""

    # Validate that the user is not the current user
    if userid == request.session['userid']:
        request.session["error_message"] = "Can not remove the currently logged in user as an administrator."

    # Check if the user is in the administrators table
    admin_record = administrative_users.objects.all().filter(userid=userid)
    if not admin_record:
        request.session["error_message"] = "The User ID provided was not found in the database! If this persists, please contact a system administrator."

    # If they are, delete the record
    if request.session["error_message"] == "":
        admin_record.delete()

    # Refresh the page
    return redirect(admin_users)
Esempio n. 4
0
def add_admin_user(request):
    '''
    Add the given users as an administrator
    '''
    # Verify that the user is logged in and an admin
    if not request.session.get('userid', False) or not get_is_admin(request.session['userid']):
        return redirect('/login')

    # Clear past error messages
    request.session["error_message"] = ""

    # Parse the userid to add
    if "userid" in request.POST:
        userid = request.POST["userid"]

    # Validate the userid meets minimum requirements
    if not userid:
        request.session["error_message"] = "the User ID must be at least 1 character long."

    # Make sure the user is not already marked as an administrator
    admin_record = administrative_users.objects.all().filter(userid=userid)
    if admin_record:
        request.session["error_message"] = "The User ID provided is already in the system as an administrator."

    # Add the user to the administrator table
    if request.session["error_message"] == "":
        administrative_users.objects.create(userid=userid)

    # Refresh the page
    return redirect(admin_users)
Esempio n. 5
0
def validate_save(response, set_formats, set_post_filters, cur_user):
    '''
    Perform validation before saving the search
    '''
    est_results = None

    if 'error_message' not in response:
        response['error_message'] = ""

    # Perform any validation before saving
    ## Verify download formats
    if not set_formats:
        response[
            "error_message"] += "At least one download format must be selected."
        # Set the result data with the previous results if an error occurs
        # only do this if there are not already results since we don't want to overwrite those
        if "result_data" in response and 'search_results' not in response:
            response['search_results'] = response['result_data']

    ## Calculate estimated results for current selection
    if set_post_filters and len(set_post_filters) > 1 and not get_is_admin(
            cur_user):
        # The UI should enforce this doesn't happen, but just in case a user manually modified the request sent to the server
        response['error_message'] += "Please preview your search results with your selected filters to obtain a more accurate " \
            "result count before queueing your search."
    elif set_post_filters:
        est_results = sum(int(x.split("||")[-1]) for x in set_post_filters)
    elif 'result_data' in response and '@odata.count' in response[
            'result_data']:
        est_results = int(response['result_data']['@odata.count'])
    else:
        response['error_message'] += "Please select the filters to apply to the search; either the existing filters or one " \
            + "of the additional filter suggestions."

    if est_results and not get_is_admin(
            cur_user) and est_results > settings.MAX_RESULTS_ALLOWED:
        response["error_message"] += f"Non-administrative users are not allowed to queue searches with more than "\
            f"{settings.MAX_RESULTS_ALLOWED} results. Either further refine your search or see who to contact on the About page."

    return (response, est_results)
Esempio n. 6
0
def admin_users(request):
    '''
    Render the users page
    '''

    # Verify that the user is logged in and an admin
    if not request.session.get('userid', False) or not get_is_admin(request.session['userid']):
        return redirect('/login')

    response = {}
    response["headings"] = ["User", "Action"]

    if "error_message" in request.session:
        response["error_message"] = request.session["error_message"]
        request.session["error_message"] = "" # clear it out so it won't show on refresh

    response["users"] = administrative_users.objects.all().order_by('userid')

    return render(request, 'textassembler_web/users.html', response)
def admin_statistics(request):
    '''
    Render the statistics page
    '''
    # Verify that the user is logged in and an admin
    if not request.session.get('userid', False) or not get_is_admin(
            request.session['userid']):
        return redirect('/login')

    # Default the date range to the current month
    from_date = timezone.now().replace(day=1)
    to_date = timezone.now()

    # Parse the provided range if available
    if 'FromDate' in request.POST and 'ToDate' in request.POST:
        from_date = make_aware(
            datetime.datetime.strptime(request.POST['FromDate'], '%Y-%m-%d'))
        to_date = make_aware(
            datetime.datetime.strptime(request.POST['ToDate'], '%Y-%m-%d'))

    # Remove time from datetimes
    from_date = from_date.replace(hour=0, minute=0, second=0, microsecond=0)
    to_date = to_date.replace(hour=0, minute=0, second=0, microsecond=0)

    # Get the statistics from the database
    searches_complete, num_results_downloaded = get_completed_search_stats(
        from_date, to_date)
    site_searches_run, download_cnt = get_api_log_stats(from_date, to_date)
    searches_processed = get_processed_search_stats(from_date, to_date)

    # Build the response
    response = {
        "searches_complete": searches_complete,
        "searches_processed": searches_processed,
        "num_results_downloaded": num_results_downloaded,
        "download_cnt": download_cnt,
        "site_searches_run": site_searches_run,
        "from_date": datetime.datetime.strftime(from_date, '%Y-%m-%d'),
        "to_date": datetime.datetime.strftime(to_date, '%Y-%m-%d')
    }

    return render(request, 'textassembler_web/statistics.html', response)
Esempio n. 8
0
def search(request):  # pylint:disable=too-many-locals, too-many-branches, too-many-statements
    '''
    Render the search page
    '''

    # Verify that the user is logged in
    if not request.session.get('userid', False):
        return redirect('/login')

    filter_data = get_available_filters()
    set_filters = {}
    set_formats = []
    set_post_filters = []

    logging.debug("==== POST DATA ====")
    logging.debug(request.POST)

    # Set the initial form data
    form = TextAssemblerWebForm(request.POST or None)
    form.set_fields(get_available_filters(False),
                    request.POST['search'] if 'search' in request.POST else '')

    response = {
        "form":
        form,
        "error_message":
        "",
        "available_formats":
        available_formats.objects.all(),
        "available_sort_orders":
        available_sort_orders.objects.filter(removed__isnull=True),
    }

    # Parse the POST data
    for opt in filter_data:
        filter_data = {
            k: v
            for k, v in dict(request.POST).items()
            if k.lower() == opt['id'].lower()
        }
        for fld, vals in filter_data.items():
            set_filters[fld] = vals
    if "selected-formats" in dict(request.POST):
        set_formats = dict(request.POST)['selected-formats']
    if "post_filters" in dict(request.POST):
        set_post_filters = dict(request.POST)['post_filters']
    if "selected-sort-order" in dict(request.POST):
        set_sort_order = int(dict(request.POST)['selected-sort-order'][0])

    # Add post filters to set_filters
    for post_filter in set_post_filters:
        name = post_filter.split("||")[0]
        value = post_filter.split("||")[1]
        fmt = get_format_type(name)
        # convert the value(s) from base64 if the filter expects it
        if fmt == 'base64':
            value = base64.b64decode(value + "=========").decode('utf-8')
        if string_is_int(value):
            value = int(value)
        if name in set_filters:
            set_filters[name].append(value)
        else:
            set_filters[name] = [value]

    # Parse the User For field if an admin
    search_user = request.session['userid']
    if get_is_admin(request.session['userid']):
        if 'user_for' in dict(request.POST):
            search_user = dict(request.POST)['user_for'][0]
            logging.debug(
                f"Overriding search save user from {request.session['userid']} to {search_user}"
            )

    logging.debug("==== SET FILTERS ====")
    logging.debug(set_filters)

    # Validate any data necessary from the post data
    for key, values in set_filters.items():
        ## Make sure Year is an integer
        if key == 'year(Date)':
            for value in values:
                if not string_is_int(value) and not isinstance(value, int):
                    response['error_message'] += \
                        f"The 'Year' field requires only numeric input, provided: {value}."
        else:
            for value in values:
                if not value:
                    response['error_message'] += \
                        f"The '{key}' field can not be blank, please provide a value or remove the filter."
                    break
    if 'Date' in set_filters and 'year(Date)' in set_filters:
        response['error_message'] += \
            "Please you either the year filter or the range filter for dates, but not a combination of both."
    if len(search_user) > 50:
        response['error_message'] += \
            "The provided 'For User ID' value is longer than the maximum of 50 characters."

    # Send the set filters back to the form to pre-populate the fields
    response["post_data"] = json.dumps(set_filters)

    # Set the last result data to be used in event of form failure to prevent another call to LN API
    if 'result_data' in request.POST and request.POST['result_data']:
        response["result_data"] = json.loads(request.POST['result_data'])

    if request.method == 'POST' and form.is_valid(
    ) and response['error_message'] == '':

        clean = form.cleaned_data

        if clean["search"] != "":
            try:
                if "preview-search" in dict(
                        request.POST) or "add-filters" in dict(request.POST):
                    # Preview Search button selected
                    response = handle_preview_search(clean['search'],
                                                     set_filters, response)

                elif "submit-search" in dict(request.POST):
                    # Submit Search button selected
                    response = handle_save_search(search_user, clean['search'],
                                                  set_filters, set_formats,
                                                  set_sort_order, response,
                                                  set_post_filters,
                                                  request.session['userid'])
                    if "error_message" not in response:
                        return response

            except Exception as exp:  # pylint: disable=broad-except
                error = create_error_message(exp, os.path.basename(__file__))
                log_error(
                    f"Error occurred while processing search request. {error}",
                    json.dumps(dict(request.POST)))

                if settings.DEBUG:
                    response["error_message"] = error
                else:
                    response[
                        "error_message"] = "An unexpected error has occurred."

                # Set the result data with the previous results if an error occurs
                # only do this if there are not already results since we don't want to overwrite those
                if "result_data" in response and 'search_results' not in response:
                    response['search_results'] = response['result_data']

    elif request.method == 'POST' and not form.is_valid():
        # If there are any form errors, add them to the fields to they highlight the issues
        for field in form.errors:
            form[field].field.widget.attrs['class'] += ' error-field'

    return render(request, "textassembler_web/search.html", response)