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})
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)
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)
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)
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)
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)
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
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})
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)
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})
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})
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)
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})
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
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
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"] })