コード例 #1
0
def ldap_list(request):
    c = LDAPConnection()
    usrid = request.GET.get("id", None)
    if usrid:
        data = c.search(settings.USER_DN, "iodineUid={}".format(usrid), ["*"])
        if len(data) == 0:
            return JsonResponse({"account": None})
        account = {
            k: (v[0] if isinstance(v, list) else v)
            for k, v in data[0]["attributes"].items()
        }
        account["dn"] = data[0]["dn"]
        account["userPassword"] = "******"
        return JsonResponse({"account": account})
    else:
        is_student = request.GET.get("type", "teacher") == "student"
        is_attendance = request.GET.get("type", "teacher") == "attendance"
        object_class = "objectClass=tjhsstStudent" if is_student else "objectClass=tjhsstUser" if is_attendance else "objectClass=tjhsstTeacher"
        data = c.search(settings.USER_DN, object_class, ["iodineUid", "cn"])
        accounts = [{
            "id": x["attributes"]["iodineUid"],
            "name": x["attributes"]["cn"]
        } for x in data]
        accounts = sorted(accounts, key=lambda acc: acc["name"])
        return JsonResponse({"accounts": accounts})
コード例 #2
0
ファイル: views.py プロジェクト: czhao39/ion
def all_classes_view(request):
    c = LDAPConnection()

    classes = c.search("ou=schedule,dc=tjhsst,dc=edu",
                       "objectClass=tjhsstClass",
                       ["tjhsstSectionId", "dn"]
                       )

    logger.debug("{} classes found.".format(len(classes)))

    if len(classes) > 0:
        schedule = []
        for row in classes:
            class_dn = row["dn"]
            class_object = Class(dn=class_dn)
            sortvalue = class_object.sortvalue
            schedule.append((sortvalue, class_object))

        ordered_schedule = sorted(schedule, key=lambda e: e[0])
        classes_objs = list(zip(*ordered_schedule))[1]  # The class objects
    else:
        classes_objs = []
        raise Http404

    context = {
        "classes": classes_objs
    }

    return render(request, "users/all_classes.html", context)
コード例 #3
0
ファイル: views.py プロジェクト: naitian/ion
def class_room_view(request, room_id):
    if settings.USE_IONLDAP and (request.user.is_eighthoffice
                                 or not request.user.is_eighth_admin):
        return redirect("ionldap_class_room", room_id=room_id)

    c = LDAPConnection()
    room_id = LDAPFilter.escape(room_id)

    classes = c.search(
        "ou=schedule,dc=tjhsst,dc=edu",
        "(&(objectClass=tjhsstClass)(roomNumber={}))".format(room_id),
        ["tjhsstSectionId"])

    if len(classes) > 0:
        schedule = []
        for row in classes:
            class_dn = row["dn"]
            class_object = Class(dn=class_dn)
            sortvalue = class_object.sortvalue
            schedule.append((sortvalue, class_object))

        ordered_schedule = sorted(schedule, key=lambda e: e[0])
        classes_objs = list(zip(*ordered_schedule))[1]  # The class objects
    else:
        classes_objs = []
        raise Http404

    context = {"room": room_id, "classes": classes_objs}

    return render(request, "users/class_room.html", context)
コード例 #4
0
ファイル: views.py プロジェクト: naitian/ion
def all_classes_view(request):
    if settings.USE_IONLDAP and (request.user.is_eighthoffice
                                 or not request.user.is_eighth_admin):
        return redirect("ionldap_all_classes")

    c = LDAPConnection()

    classes = c.search("ou=schedule,dc=tjhsst,dc=edu",
                       "objectClass=tjhsstClass", ["tjhsstSectionId"])

    logger.debug("{} classes found.".format(len(classes)))

    if len(classes) > 0:
        schedule = []
        for row in classes:
            class_dn = row["dn"]
            class_object = Class(dn=class_dn)
            sortvalue = class_object.sortvalue
            schedule.append((sortvalue, class_object))

        ordered_schedule = sorted(schedule, key=lambda e: e[0])
        classes_objs = list(zip(*ordered_schedule))[1]  # The class objects
    else:
        classes_objs = []
        raise Http404

    context = {"classes": classes_objs}

    return render(request, "users/all_classes.html", context)
コード例 #5
0
ファイル: views.py プロジェクト: czhao39/ion
def class_room_view(request, room_id):
    c = LDAPConnection()
    room_id = LDAPFilter.escape(room_id)

    classes = c.search("ou=schedule,dc=tjhsst,dc=edu",
                       "(&(objectClass=tjhsstClass)(roomNumber={}))".format(room_id),
                       ["tjhsstSectionId", "dn"]
                       )

    if len(classes) > 0:
        schedule = []
        for row in classes:
            class_dn = row["dn"]
            class_object = Class(dn=class_dn)
            sortvalue = class_object.sortvalue
            schedule.append((sortvalue, class_object))

        ordered_schedule = sorted(schedule, key=lambda e: e[0])
        classes_objs = list(zip(*ordered_schedule))[1]  # The class objects
    else:
        classes_objs = []
        raise Http404

    context = {
        "room": room_id,
        "classes": classes_objs
    }

    return render(request, "users/class_room.html", context)
コード例 #6
0
ファイル: views.py プロジェクト: willzhang05/ion
def ldap_test(request):
    from intranet.db.ldap_db import LDAPConnection
    from intranet import settings

    c = LDAPConnection()

    results = ""

    search_dn = request.POST.get("search_dn")
    search_q = request.POST.get("search_q")
    search_attrs = request.POST.getlist("search_attrs")

    user_attribute_dn = request.POST.get("user_attribute_dn")
    user_attribute_attrs = request.POST.getlist("user_attribute_attrs")
    if request.method == "POST":
        if "search_q" in request.POST:
            try:
                req = c.search(search_dn, search_q, search_attrs)
            except Exception as e:
                results += "EXCEPTION: {}\n".format(e)
            else:
                logger.debug(req)
                if not isinstance(req, list):
                    req = [req]
                for row in req:
                    results += "{}: \n".format(row[0])
                    for perm, value in row[1].iteritems():
                        results += "\t{}: {}\n".format(perm, value)

        if "user_attribute_dn" in request.POST:
            if "dc=edu" not in user_attribute_dn:
                user_attribute_dn = User.objects.get(id=user_attribute_dn).dn
            try:
                req = c.user_attributes(user_attribute_dn, user_attribute_attrs)
            except Exception as e:
                results += "EXCEPTION: {}\n".format(e)
            else:
                logger.debug(req)
                result = req.first_result()
                logger.debug(result)
                if isinstance(result, dict):
                    for perm, value in result.iteritems():
                        logger.debug("{} {}".format(perm, value))
                        results += "{}: {}\n".format(perm, value)
                else:
                    results += "Empty result"

    logger.debug(results)

    context = {
        "search_dn": search_dn or settings.USER_DN or "",
        "search_q": search_q or "",
        "search_attrs": search_attrs or "",
        "user_attribute_dn": user_attribute_dn or "",
        "user_attribute_attrs": user_attribute_attrs or "",
        "results": results
    }

    return render(request, "preferences/ldap.html", context)
コード例 #7
0
def do_classes_search(q):
    c = LDAPConnection()
    result_dns = []
    q = escape_filter_chars(q)
    q = q.replace(escape_filter_chars('*'), '*')
    parts = q.split(" ")
    # split on each word
    i = 0
    for p in parts:
        exact = False
        logger.debug(p)
        if p.startswith('"') and p.endswith('"'):
            exact = True
            p = p[1:-1]

        if exact:
            logger.debug("Simple exact: {}".format(p))
            # No implied wildcard
            query = (("(&(|(tjhsstClassId={0})"
                      "(cn={0})"
                      ")(|(objectClass=tjhsstClass)))")).format(p)
        else:
            logger.debug("Simple wildcard: {}".format(p))
            if p.endswith("*"):
                p = p[:-1]
            if p.startswith("*"):
                p = p[1:]
            # Search for first, last, middle, nickname uid, with implied
            # wildcard at beginning and end
            query = (("(&(|(tjhsstClassId=*{0})"
                      "(tjhsstClassId={0}*)"
                      "(cn=*{0})"
                      "(cn={0}*)"
                      ")(|(objectClass=tjhsstClass)))")).format(p)

        logger.debug("Running LDAP query: {}".format(query))

        res = c.search(settings.CLASS_DN, query, None)
        new_dns = []
        # if multiple words, delete those that weren't in previous searches
        for row in res:
            dn = row["dn"]
            if i == 0:
                new_dns.append(dn)
            elif dn in result_dns:
                new_dns.append(dn)

        result_dns = new_dns
        i += 1

    # loop through the DNs saved and get actual user objects
    classes = []
    for dn in result_dns:
        result_class = Class(dn=dn)
        if result_class not in classes:
            classes.append(result_class)
    classes = sorted(classes, key=lambda c: str(c))
    return classes
コード例 #8
0
ファイル: views.py プロジェクト: evanyeyeye/e-ion
def do_classes_search(q):
    c = LDAPConnection()
    result_dns = []
    q = escape_filter_chars(q)
    q = q.replace(escape_filter_chars('*'), '*')
    parts = q.split(" ")
    # split on each word
    i = 0
    for p in parts:
        exact = False
        logger.debug(p)
        if p.startswith('"') and p.endswith('"'):
            exact = True
            p = p[1:-1]

        if exact:
            logger.debug("Simple exact: {}".format(p))
            # No implied wildcard
            query = (("(&(|(tjhsstClassId={0})" "(cn={0})" ")(|(objectClass=tjhsstClass)))")).format(p)
        else:
            logger.debug("Simple wildcard: {}".format(p))
            if p.endswith("*"):
                p = p[:-1]
            if p.startswith("*"):
                p = p[1:]
            # Search for first, last, middle, nickname uid, with implied
            # wildcard at beginning and end
            query = (("(&(|(tjhsstClassId=*{0})" "(tjhsstClassId={0}*)" "(cn=*{0})" "(cn={0}*)" ")(|(objectClass=tjhsstClass)))")).format(p)

        logger.debug("Running LDAP query: {}".format(query))

        res = c.search(settings.CLASS_DN, query, None)
        new_dns = []
        # if multiple words, delete those that weren't in previous searches
        for row in res:
            dn = row["dn"]
            if i == 0:
                new_dns.append(dn)
            elif dn in result_dns:
                new_dns.append(dn)

        result_dns = new_dns
        i += 1

    # loop through the DNs saved and get actual user objects
    classes = []
    for dn in result_dns:
        result_class = Class(dn=dn)
        if result_class not in classes:
            classes.append(result_class)
    classes = sorted(classes, key=lambda c: str(c))
    return classes
コード例 #9
0
ファイル: maintenance.py プロジェクト: evanyeyeye/e-ion
def ldap_list(request):
    c = LDAPConnection()
    usrid = request.GET.get("id", None)
    if usrid:
        data = c.search(settings.USER_DN, "iodineUid={}".format(usrid), ["*"])
        if len(data) == 0:
            return JsonResponse({"account": None})
        account = {k: (v[0] if isinstance(v, list) else v) for k, v in data[0]["attributes"].items()}
        account["dn"] = data[0]["dn"]
        return JsonResponse({"account": account})
    else:
        is_student = request.GET.get("type", "teacher") == "student"
        data = c.search(settings.USER_DN, "objectClass=tjhsstStudent" if is_student else "objectClass=tjhsstTeacher", ["iodineUid", "cn"])
        accounts = [{"id": x["attributes"]["iodineUid"], "name": x["attributes"]["cn"]} for x in data]
        accounts = sorted(accounts, key=lambda acc: acc["name"])
        return JsonResponse({"accounts": accounts})
コード例 #10
0
ファイル: maintenance.py プロジェクト: evanyeyeye/e-ion
def clear_comments_view(request):
    context = {"admin_page_title": "Clear Admin Comments", "completed": False}
    if request.method == "POST" and request.POST.get("confirm"):
        deleted_comments = ""
        count = 0

        c = LDAPConnection()
        comments = c.search(settings.USER_DN, "objectClass=tjhsstStudent", ["eighthoffice-comments"])
        for row in comments:
            if "eighthoffice-comments" in row:
                c.del_attribute(row["dn"], "eighthoffice-comments")
                u = User.objects.get(dn=row["dn"])
                invalidate_obj(u)
                u.clear_cache()
                deleted_comments += "=== {} ({})\n{}\n".format(u.full_name, u.username, row["eighthoffice-comments"])
                count += 1

        context["deleted_comments"] = deleted_comments or "No comments were deleted."
        context["deleted_comments_count"] = count
        context["completed"] = True
    return render(request, "eighth/admin/clear_comments.html", context)
コード例 #11
0
def ldap_next_id(request):
    is_student = request.GET.get("type", "teacher") == "student"
    is_attendance = request.GET.get("type", "teacher") == "attendance"
    usrid = 0
    c = LDAPConnection()
    if is_student:
        res = c.search(settings.USER_DN, "(objectClass=tjhsstStudent)",
                       ["iodineUidNumber"])
    elif is_attendance:
        res = c.search(settings.USER_DN, "(objectClass=tjhsstUser)",
                       ["iodineUidNumber"])
    else:
        res = c.search(settings.USER_DN, "(objectClass=tjhsstTeacher)",
                       ["iodineUidNumber"])
    if len(res) > 0:
        res = [int(x["attributes"]["iodineUidNumber"][0]) for x in res]
        if is_student:
            usrid = max(res) + 1
        elif is_attendance:
            res = set([x for x in res if x < 7000])
            usrid = max(res) + 1
            if usrid == 7000:
                for x in range(6000, 7000):
                    if x not in res:
                        usrid = x
                        break
            else:
                logger.error("Out of attendance user LDAP IDs!")
        else:
            res = set([x for x in res if x < 1400])
            usrid = max(res) + 1
            if usrid == 1400:
                for x in range(1400):
                    if x not in res:
                        usrid = x
                        break
            else:
                logger.error("Out of teacher LDAP IDs!")
    return JsonResponse({"id": usrid})
コード例 #12
0
ファイル: maintenance.py プロジェクト: evanyeyeye/e-ion
def ldap_next_id(request):
    is_student = request.GET.get("type", "teacher") == "student"
    usrid = 0
    c = LDAPConnection()
    if is_student:
        res = c.search(settings.USER_DN, "(objectClass=tjhsstStudent)", ["iodineUidNumber"])
    else:
        res = c.search(settings.USER_DN, "(objectClass=tjhsstTeacher)", ["iodineUidNumber"])
    if len(res) > 0:
        res = [int(x["attributes"]["iodineUidNumber"][0]) for x in res]
        if is_student:
            usrid = max(res) + 1
        else:
            res = set([x for x in res if x < 1200])
            usrid = max(res) + 1
            if usrid == 1200:
                for x in range(1200):
                    if x not in res:
                        usrid = x
                        break
            else:
                logger.error("Out of teacher LDAP IDs!")
    return JsonResponse({"id": usrid})
コード例 #13
0
def clear_comments_view(request):
    context = {"admin_page_title": "Clear Admin Comments", "completed": False}
    if request.method == "POST" and request.POST.get("confirm"):
        deleted_comments = ""
        count = 0

        c = LDAPConnection()
        comments = c.search(settings.USER_DN, "objectClass=tjhsstStudent",
                            ["eighthoffice-comments"])
        for row in comments:
            if "eighthoffice-comments" in row:
                c.del_attribute(row["dn"], "eighthoffice-comments")
                u = User.objects.get(dn=row["dn"])
                invalidate_obj(u)
                u.clear_cache()
                deleted_comments += "=== {} ({})\n{}\n".format(
                    u.full_name, u.username, row["eighthoffice-comments"])
                count += 1

        context[
            "deleted_comments"] = deleted_comments or "No comments were deleted."
        context["deleted_comments_count"] = count
        context["completed"] = True
    return render(request, "eighth/admin/clear_comments.html", context)
コード例 #14
0
def ldap_delete(request):
    dn = request.POST.get("dn", None)
    if request.method == "POST" and dn:
        if not dn.endswith(settings.USER_DN):
            return JsonResponse({
                "success": False,
                "error": "Invalid DN!",
                "details": dn
            })
        c = LDAPConnection()
        success = c.conn.delete(dn)
        return JsonResponse({
            "success": success,
            "error": "LDAP query failed!" if not success else None,
            "details": c.conn.last_error
        })
    return JsonResponse({"success": False})
コード例 #15
0
ファイル: views.py プロジェクト: evanyeyeye/e-ion
def do_ldap_query(q, admin=False):
    c = LDAPConnection()
    result_dns = []

    q = escape_filter_chars(q)
    # Allow wildcards
    q = q.replace(escape_filter_chars('*'), '*')

    # If only a digit, search for student ID and user ID
    if q.isdigit():
        logger.debug("Digit search: {}".format(q))
        if USE_SID_LDAP:
            query = ("(&(|(tjhsstStudentId={0})" "(iodineUidNumber={0})" ")(|(objectClass=tjhsstStudent)(objectClass=tjhsstTeacher)))").format(q)

            logger.debug("Running LDAP query: {}".format(query))

            res = c.search(settings.USER_DN, query, None)
            for row in res:
                dn = row["dn"]
                result_dns.append(dn)
        else:
            sid_users = User.objects.filter(_student_id=q)
            uid_users = User.objects.filter(id=q)
            for u in sid_users:
                result_dns.append(u.dn)

            for u in uid_users:
                result_dns.append(u.dn)
            logger.debug("Running local DB query for UID and SID")
    elif ":" in q:
        logger.debug("Advanced search")
        # A mapping between search keys and LDAP entires
        map_attrs = {
            "firstname": (
                "givenname",
                "nickname",),
            "first": (
                "givenname",
                "nickname",),
            "lastname": ("sn",),
            "last": ("sn",),
            "nick": ("nickname",),
            "nickname": ("nickname",),
            "name": (
                "sn",
                "mname",
                "givenname",
                "nickname",),
            "city": ("l",),
            "town": ("l",),
            "middlename": ("mname",),
            "middle": ("mname",),
            "phone": (
                "homephone",
                "mobile",),
            "homephone": ("homephone",),
            "cell": ("mobile",),
            "address": ("street",),
            "zip": ("postalcode",),
            "grade": ("graduationYear",),
            "gradyear": ("graduationYear",),
            "email": ("mail",),
            "studentid": ("tjhsstStudentId",),
            "sex": ("sex",),
            "gender": ("sex",),
            "id": ("iodineUidNumber",),
            "username": ("iodineUid",),
            "counselor": ("counselor",),
            "type": ("objectClass",)
        }

        inner = ""
        parts = q.split(" ")
        # split each word
        for p in parts:
            # Check for less than/greater than, and replace =
            sep = "="
            if ":" in p:
                cat, val = p.split(":")
            elif "=" in p:
                cat, val = p.split("=")
            elif "<" in p:
                cat, val = p.split("<")
                sep = "<="
            elif ">" in p:
                cat, val = p.split(">")
                sep = ">="
            else:
                logger.debug("Advanced fallback: {}".format(p))
                # Fall back on regular searching (there's no key)

                # Wildcards are already implied at the start and end
                if p.endswith("*"):
                    p = p[:-1]
                if p.startswith("*"):
                    p = p[1:]

                exact = False
                if p.startswith('"') and p.endswith('"'):
                    exact = True
                    p = p[1:-1]

                if len(p) == 0:
                    continue

                if exact:
                    # No implied wildcard
                    inner += (("(|(givenName={0})"
                               "(sn={0})"
                               "(iodineUid={0})") + ("(mname={0})" if admin else "") + ("(nickname={0})"
                                                                                        ")")).format(p)
                else:
                    # Search firstname, lastname, uid, nickname (+ middlename if admin) with
                    # implied wildcard at beginning and end of the search
                    # string
                    inner += (("(|(givenName=*{0})"
                               "(givenName={0}*)"
                               "(sn=*{0})"
                               "(sn={0}*)"
                               "(iodineUid=*{0})"
                               "(iodineUid={0}*)") + ("(mname=*{0})"
                                                      "(mname={0}*)" if admin else "") + ("(nickname=*{0})"
                                                                                          "(nickname={0}*)"
                                                                                          ")")).format(p)

                continue  # skip rest of processing
            logger.debug("Advanced exact: {}".format(p))
            if val.startswith('"') and val.endswith('"'):
                # Already exact
                val = val[1:-1]

            cat = cat.lower()
            val = val.lower()

            # fix grade, because LDAP only stores graduation year
            if cat == "grade" and val.isdigit():
                val = "{}".format(Grade.year_from_grade(int(val)))
            elif cat == "grade" and val == "staff":
                cat = "type"
                val = "teacher"
            elif cat == "grade" and val == "student":
                cat = "type"
                val = "student"

            if cat == "type" and val == "teacher":
                val = "tjhsstTeacher"
            elif cat == "type" and val == "student":
                val = "tjhsstStudent"

            # replace sex:male with sex:m and sex:female with sex:f
            if cat == "sex" or cat == "gender":
                val = val[:1]

            # if an invalid key, ignore
            if cat not in map_attrs:
                continue

            attrs = map_attrs[cat]

            inner += "(|"
            # for each of the possible LDAP fields, add to the search query
            for attr in attrs:
                inner += "({}{}{})".format(attr, sep, val)
            inner += ")"

        query = "(&{}(|(objectClass=tjhsstStudent)(objectClass=tjhsstTeacher)))".format(inner)

        logger.debug("Running LDAP query: {}".format(query))

        res = c.search(settings.USER_DN, query, None)
        for row in res:
            dn = row["dn"]
            result_dns.append(dn)

    else:
        logger.debug("Simple search")
        # Non-advanced search; no ":"
        parts = q.split(" ")
        # split on each word
        i = 0
        for p in parts:
            exact = False
            logger.debug(p)
            if p.startswith('"') and p.endswith('"'):
                exact = True
                p = p[1:-1]

            if exact:
                logger.debug("Simple exact: {}".format(p))
                # No implied wildcard
                query = (("(&(|(givenName={0})"
                          "(sn={0})"
                          "(iodineUid={0})") + ("(mname={0})"
                                                if admin else "") + ("(nickname={0})"
                                                                     ")(|(objectClass=tjhsstStudent)(objectClass=tjhsstTeacher)))")).format(p)
            else:
                logger.debug("Simple wildcard: {}".format(p))
                if p.endswith("*"):
                    p = p[:-1]
                if p.startswith("*"):
                    p = p[1:]
                # Search for first, last, middle, nickname uid, with implied
                # wildcard at beginning and end
                query = (("(&(|(givenName=*{0})"
                          "(givenName={0}*)"
                          "(sn=*{0})"
                          "(sn={0}*)"
                          "(iodineUid=*{0})"
                          "(iodineUid={0}*)") + ("(mname=*{0})"
                                                 "(mname={0}*)"
                                                 if admin else "") + ("(nickname=*{0})"
                                                                      "(nickname={0}*)"
                                                                      ")(|(objectClass=tjhsstStudent)(objectClass=tjhsstTeacher)))")).format(p)

            logger.debug("Running LDAP query: {}".format(query))

            res = c.search(settings.USER_DN, query, None)
            new_dns = []
            # if multiple words, delete those that weren't in previous searches
            for row in res:
                dn = row["dn"]
                if i == 0:
                    new_dns.append(dn)
                elif dn in result_dns:
                    new_dns.append(dn)

            result_dns = new_dns
            i += 1

    # loop through the DNs saved and get actual user objects
    users = []
    for dn in result_dns:
        user = User.get_user(dn=dn)
        if user.is_active:
            users.append(user)

    return users
コード例 #16
0
def do_ldap_query(q, admin=False):
    c = LDAPConnection()
    result_dns = []

    q = escape_filter_chars(q)
    # Allow wildcards
    q = q.replace(escape_filter_chars('*'), '*')

    # If only a digit, search for student ID and user ID
    if q.isdigit():
        logger.debug("Digit search: {}".format(q))
        if USE_SID_LDAP:
            query = ("(&(|(tjhsstStudentId={0})" "(iodineUidNumber={0})" ")(|(objectClass=tjhsstStudent)(objectClass=tjhsstTeacher)))").format(q)

            logger.debug("Running LDAP query: {}".format(query))

            res = c.search(settings.USER_DN, query, ["dn"])
            for row in res:
                dn = row["dn"]
                result_dns.append(dn)
        else:
            sid_users = User.objects.filter(_student_id=q)
            uid_users = User.objects.filter(id=q)
            for u in sid_users:
                result_dns.append(u.dn)

            for u in uid_users:
                result_dns.append(u.dn)
            logger.debug("Running local DB query for UID and SID")
    elif ":" in q:
        logger.debug("Advanced search")
        # A mapping between search keys and LDAP entires
        map_attrs = {
            "firstname": ("givenname",
                          "nickname",),
            "first": ("givenname",
                      "nickname",),
            "lastname": ("sn",),
            "last": ("sn",),
            "nick": ("nickname",),
            "nickname": ("nickname",),
            "name": ("sn",
                     "mname",
                     "givenname",
                     "nickname",),
            "city": ("l",),
            "town": ("l",),
            "middlename": ("mname",),
            "middle": ("mname",),
            "phone": ("homephone",
                      "mobile",),
            "homephone": ("homephone",),
            "cell": ("mobile",),
            "address": ("street",),
            "zip": ("postalcode",),
            "grade": ("graduationYear",),
            "gradyear": ("graduationYear",),
            "email": ("mail",),
            "studentid": ("tjhsstStudentId",),
            "sex": ("sex",),
            "gender": ("sex",),
            "id": ("iodineUidNumber",),
            "username": ("iodineUid",),
            "counselor": ("counselor",),
            "type": ("objectClass",)
        }

        inner = ""
        parts = q.split(" ")
        # split each word
        for p in parts:
            # Check for less than/greater than, and replace =
            sep = "="
            if ":" in p:
                cat, val = p.split(":")
            elif "=" in p:
                cat, val = p.split("=")
            elif "<" in p:
                cat, val = p.split("<")
                sep = "<="
            elif ">" in p:
                cat, val = p.split(">")
                sep = ">="
            else:
                logger.debug("Advanced fallback: {}".format(p))
                # Fall back on regular searching (there's no key)

                # Wildcards are already implied at the start and end
                if p.endswith("*"):
                    p = p[:-1]
                if p.startswith("*"):
                    p = p[1:]

                exact = False
                if p.startswith('"') and p.endswith('"'):
                    exact = True
                    p = p[1:-1]

                if len(p) == 0:
                    continue

                if exact:
                    # No implied wildcard
                    inner += (("(|(givenName={0})"
                               "(sn={0})"
                               "(iodineUid={0})") + ("(mname={0})" if admin else "") + ("(nickname={0})"
                                                                                        ")")).format(p)
                else:
                    # Search firstname, lastname, uid, nickname (+ middlename if admin) with
                    # implied wildcard at beginning and end of the search string
                    inner += (("(|(givenName=*{0})"
                               "(givenName={0}*)"
                               "(sn=*{0})"
                               "(sn={0}*)"
                               "(iodineUid=*{0})"
                               "(iodineUid={0}*)") + ("(mname=*{0})"
                                                      "(mname={0}*)" if admin else "") + ("(nickname=*{0})"
                                                                                          "(nickname={0}*)"
                                                                                          ")")).format(p)

                continue  # skip rest of processing
            logger.debug("Advanced exact: {}".format(p))
            if val.startswith('"') and val.endswith('"'):
                # Already exact
                val = val[1:-1]

            cat = cat.lower()
            val = val.lower()

            # fix grade, because LDAP only stores graduation year
            if cat == "grade" and val.isdigit():
                val = "{}".format(Grade.year_from_grade(int(val)))
            elif cat == "grade" and val == "staff":
                cat = "type"
                val = "teacher"
            elif cat == "grade" and val == "student":
                cat = "type"
                val = "student"

            if cat == "type" and val == "teacher":
                val = "tjhsstTeacher"
            elif cat == "type" and val == "student":
                val = "tjhsstStudent"

            # replace sex:male with sex:m and sex:female with sex:f
            if cat == "sex" or cat == "gender":
                val = val[:1]

            # if an invalid key, ignore
            if cat not in map_attrs:
                continue

            attrs = map_attrs[cat]

            inner += "(|"
            # for each of the possible LDAP fields, add to the search query
            for attr in attrs:
                inner += "({}{}{})".format(attr, sep, val)
            inner += ")"

        query = "(&{}(|(objectClass=tjhsstStudent)(objectClass=tjhsstTeacher)))".format(inner)

        logger.debug("Running LDAP query: {}".format(query))

        res = c.search(settings.USER_DN, query, ["dn"])
        for row in res:
            dn = row["dn"]
            result_dns.append(dn)

    else:
        logger.debug("Simple search")
        # Non-advanced search; no ":"
        parts = q.split(" ")
        # split on each word
        i = 0
        for p in parts:
            exact = False
            logger.debug(p)
            if p.startswith('"') and p.endswith('"'):
                exact = True
                p = p[1:-1]

            if exact:
                logger.debug("Simple exact: {}".format(p))
                # No implied wildcard
                query = (("(&(|(givenName={0})"
                          "(sn={0})"
                          "(iodineUid={0})") + ("(mname={0})"
                                                if admin else "") + ("(nickname={0})"
                                                                     ")(|(objectClass=tjhsstStudent)(objectClass=tjhsstTeacher)))")).format(p)
            else:
                logger.debug("Simple wildcard: {}".format(p))
                if p.endswith("*"):
                    p = p[:-1]
                if p.startswith("*"):
                    p = p[1:]
                # Search for first, last, middle, nickname uid, with implied
                # wildcard at beginning and end
                query = (("(&(|(givenName=*{0})"
                          "(givenName={0}*)"
                          "(sn=*{0})"
                          "(sn={0}*)"
                          "(iodineUid=*{0})"
                          "(iodineUid={0}*)") + ("(mname=*{0})"
                                                 "(mname={0}*)" if admin else "") +
                         ("(nickname=*{0})"
                          "(nickname={0}*)"
                          ")(|(objectClass=tjhsstStudent)(objectClass=tjhsstTeacher)))")).format(p)

            logger.debug("Running LDAP query: {}".format(query))

            res = c.search(settings.USER_DN, query, ["dn"])
            new_dns = []
            # if multiple words, delete those that weren't in previous searches
            for row in res:
                dn = row["dn"]
                if i == 0:
                    new_dns.append(dn)
                elif dn in result_dns:
                    new_dns.append(dn)

            result_dns = new_dns
            i += 1

    # loop through the DNs saved and get actual user objects
    users = []
    for dn in result_dns:
        user = User.get_user(dn=dn)
        if user.is_active:
            users.append(user)

    return users
コード例 #17
0
def ldap_modify(request):
    dn = request.POST.get("dn", None)
    if request.method == "POST":
        c = LDAPConnection()

        object_class = request.POST.get("objectClass", None)
        if object_class != "tjhsstStudent" and object_class != "tjhsstTeacher" and object_class != "tjhsstUser":
            return JsonResponse({
                "success":
                False,
                "error":
                "Invalid objectClass!",
                "details":
                "Valid objectClasses are tjhsstStudent, tjhsstTeacher, and tjhsstUser."
            })

        if dn:  # modify account
            attrs = {}
            for field, name in LDAP_BASIC_FIELDS:
                if field == "iodineUid":
                    continue  # this is handled by modify_dn
                value = request.POST.get(field, None)
                if value:
                    attrs[field] = [(ldap3.MODIFY_REPLACE, [value])]

            if object_class == "tjhsstStudent":
                for field, name in LDAP_STUDENT_FIELDS:
                    value = request.POST.get(field, None)
                    if value:
                        attrs[field] = [(ldap3.MODIFY_REPLACE, [value])]

            success = c.conn.modify(dn, attrs)
            clear_user_cache(dn)

            try:
                u = User.get_user(dn=dn)
            except User.DoesNotExist:
                client.captureException()
                logger.warning(
                    "User with dn {} not found in database!".format(dn))
                u = None

            new_uid = request.POST.get("iodineUid", None)

            if success and new_uid and not "iodineUid={},{}".format(
                    new_uid, settings.USER_DN) == dn:
                if User.objects.filter(username=new_uid).count():
                    return JsonResponse({
                        "success":
                        False,
                        "id":
                        None,
                        "error":
                        "The username '{}' already exists!".format(new_uid)
                    })

                success = c.conn.modify_dn(dn, "iodineUid={}".format(new_uid))
                if success and u:
                    u.username = new_uid
                    u.save()

            return JsonResponse({
                "success":
                success,
                "id":
                new_uid if success else None,
                "error":
                "LDAP query failed!" if not success else None,
                "details":
                c.conn.last_error or str(c.conn.result)
            })
        else:  # create new account
            attrs = dict(LDAP_DEFAULT_FIELDS)
            for field, name in LDAP_BASIC_FIELDS:
                value = request.POST.get(field, None)
                if not value:
                    return JsonResponse({
                        "success":
                        False,
                        "error":
                        "{} is a required field!".format(field)
                    })
                attrs[field] = value
            if object_class == "tjhsstUser":
                attrs[
                    "userPassword"] = "******"
            if object_class == "tjhsstStudent":
                for field, name in LDAP_STUDENT_FIELDS:
                    value = request.POST.get(field, None)
                    if not value:
                        return JsonResponse({
                            "success":
                            False,
                            "error":
                            "{} is a required field for students!".format(
                                field)
                        })
                    attrs[field] = value

            try:
                iodine_uid_num = int(attrs["iodineUidNumber"])
            except ValueError:
                return JsonResponse({
                    "success":
                    False,
                    "error":
                    "iodineUidNumber must be an integer!"
                })

            if object_class == "tjhsstTeacher":
                if iodine_uid_num < 0 or iodine_uid_num > 10000:
                    return JsonResponse({
                        "success":
                        False,
                        "error":
                        "iodineUidNumber must be between 0 and 10,000!"
                    })
            elif object_class == "tjhsstUser":
                if iodine_uid_num < 6000 or iodine_uid_num > 7000:
                    return JsonResponse({
                        "success":
                        False,
                        "error":
                        "iodineUidNumber must be between 6,000 and 7,000!"
                    })
            else:
                if iodine_uid_num < 30000:
                    return JsonResponse({
                        "success":
                        False,
                        "error":
                        "iodineUidNumber must be above 30,000!"
                    })

            success = c.conn.add("iodineUid={},{}".format(
                attrs["iodineUid"], settings.USER_DN),
                                 object_class=object_class,
                                 attributes=attrs)
            print(c.conn.result)
            return JsonResponse({
                "success":
                success,
                "id":
                request.POST.get("iodineUid", None) if success else None,
                "error":
                "LDAP query failed!" if not success else None,
                "details":
                c.conn.result["message"]
            })