Beispiel #1
0
def verify_settings():
    ensure_settings()

    session.forget(response)  # Don't need the session so don't block on it
    auto_create = False
    ret = ""
    auto = request.vars.get('auto', '')
    if auto == "true":
        auto_create = True

    ret += "<h4>Active Directory Settings</h4><div style='font-size: 10px;'>"
    r = AD.VerifyADSettings(auto_create)
    ret += AD.GetErrorString()
    if r is not True:
        ret += "<div style='font-weight: bold; color: red;'>Active Directory Error</div>"
    else:
        ret += "<div style='font-weight: bold; color: green;'>Tests Passed</div>"
    ret += "</div><hr />"

    ret += "<h4>Canvas Settings</h4><div style='font-size: 10px;'>"
    r = Canvas.VerifyCanvasSettings()
    ret += Canvas.GetErrorString()
    if r is not True:
        ret += "<div style='font-weight: bold; color: red;'>Canvas Error</div>"
    else:
        ret += "<div style='font-weight: bold; color: green;'>Tests Passed</div>"
    ret += "</div><hr />"

    return ret
Beispiel #2
0
    def SetPassword(student_id, new_password, update_db=True):
        db = current.db
        ret = ""

        if student_id == "" or new_password == "":
            return "Can't set empty password!"

        if len(new_password) < 6:
            return "Can't set password - Too short!"

        # Set AD password
        user_name = Student.GetUsername(student_id)
        if AD.Connect() is True:
            user_dn = Student.GetAD_DN(user_name,
                                       Student.GetProgram(student_id))
            if AD.SetPassword(user_dn, new_password) is not True:
                return "Error setting AD password: "******"Error setting Canvas password: "******"Error setting system password"

        return ret
Beispiel #3
0
 def SetPassword(faculty_id, new_password, update_db=True):
     db = current.db
     ret = ""
     
     if faculty_id == "" or new_password == "":
         return "Can't set empty password!"
     
     if len(new_password) < 6:
         return "Can't set password - Too short!"
     
     # Set AD password
     user_name = Faculty.GetUsername(faculty_id)
     if AD.Connect() is True:
         user_dn = Faculty.GetAD_DN(user_name, Faculty.GetProgram(faculty_id))
         if AD.SetPassword(user_dn, new_password) is not True:
             return "Error setting AD password: "******"skipping ad set")
         pass
     
     # Set Canvas password
     if Canvas.SetPassword(user_name, new_password) is not True:
         return "Error setting Canvas password: "******"Error setting SMC password"
     
     return ret
Beispiel #4
0
def next_test():
    
    
    # Get the users to import
    sheet_name = "STUDENT USERS"
    #rows = db(db.student_import_queue.sheet_name == sheet_name).select()
    #rows = db(db.student_info).select()
    #for row in rows:
    
    #_ad_encoding = "iso-8859-1" 
    
    #_ldap = Connection(AD._ldap_session, "huskers",
    #                                  "testing",
    #                                  authentication=ldap3.NTLM,
    #                                  auto_bind=True,
    #                                  raise_exceptions=True,
    #                                  auto_referrals=False,
    #                                  client_strategy=ldap3.RESTARTABLE,
    #                                  #receive_timeout=60,
    #                                  
    #                                  )
    
    AD.ConnectAD()
    
    return locals()
Beispiel #5
0
def winrm_test():
    ret = ""

    r = AD.ConnectWinRM()
    errors = AD._errors

    return locals()
Beispiel #6
0
def ad_test():
    # ad_pw = AppSettings.GetValue("ad_service_password", "NOT FOUND")
    # file_pw = AppSettings.GetValue("file_server_login_pass", "NOT FOUND")
    c = AD.Connect()
        
    # Keep this off - exposes too much
    # ld = AD._ldap

    # whoami = AD._ldap.extend.standard.who_am_i()

    cn_name = "s777777"
    dn = "cn=s777777,ou=cse,ou=students,dc=pencol,dc=local"
    container_dn = "ou=cse,ou=students,dc=pencol,dc=local"

    #current_enrollment = Canvas.GetCurrentClasses(cn_name)
    #courses = {}
    #for e in current_enrollment:
    #    courses[e['id']] = e['updated_at']

    # create_user = AD.CreateUser(cn_name, container_dn)
    # Student.SetPassword("777777", "Sid777777!")

    # update_user = AD.UpdateUserInfo(dn, email_address="test@test", first_name="test", last_name="smith",
    #                                 display_name="testing", description="this is a test", id_number="10",
    #                                 home_drive_letter="W", home_directory="c:\home",
    #                                 login_script="login_script", profile_path="pfpath",
    #                                 ts_allow_login='******')


    # Test - Enable user
    # disable = AD.DisableUser(dn)
    # enable = AD.EnableUser(dn)
    # Student.EnableAccount("777777")

    # r = AD._ldap.search(dn.encode(AD._ad_encoding),
    #                    "(name=" + str(cn_name).encode(AD._ad_encoding) + ")",
    #                    search_scope=ldap3.SUBTREE,
    #                   attributes=['distinguishedName'],
    #                    )
    # s = AD._ldap.response
    # ret_arr)  # ['distinguishedName'])

    #ret = AD.VerifyADSettings(False)



    #last_login_time = AD.GetLastLoginTime(dn)

    #grp_dn = "cn=test_group,OU=StudentGroups,DC=pencol,DC=local"
    #cg = AD.CreateGroup(grp_dn)

    #add_to_group = AD.AddUserToGroup(dn, grp_dn)

    #t_ou_dn = "OU=test_OU,DC=pencol,DC=local"
    #test_ou = AD.CreateOU(t_ou_dn)


    err = AD._errors

    return locals()
Beispiel #7
0
def refresh_all_ad_logins(run_from="UI"):
    # Go to the AD server and refresh all student and staff AD login times
    ret = ""

    # Might be longer running - make sure to commit so we don't leave databases locked
    db.commit()

    # Update the last login value for all users (students and faculty)
    if AD._ldap_enabled is not True:
        ret = "[AD Disabled]"
        return ret
    if AD.ConnectAD() is not True:
        ret = "[AD Connection Error]" + AD.GetErrorString()
        return ret

    # Grab list of students
    rows = db(db.student_info).select(db.student_info.user_id)
    for row in rows:
        # ret += "UID: " + row.user_id
        ll = Student.GetLastADLoginTime(row.user_id)
        # if (ll == None):
        #    ret += "None"
        # else:
        #    ret += str(ll)
        db(db.student_info.user_id == row.user_id).update(ad_last_login=ll)
        db.commit()

    # Grab a list of faculty
    rows = db(db.faculty_info).select(db.faculty_info.user_id)
    for row in rows:
        # ret += "UID: " + row.user_id
        ll = Faculty.GetLastADLoginTime(row.user_id)
        # if (ll == None):
        #    ret += "None"
        # else:
        #    ret += str(ll)
        db(db.faculty_info.user_id == row.user_id).update(ad_last_login=ll)
        db.commit()

    rows = None
    ad_errors = AD.GetErrorString()
    ret = "Done."

    # Have to call commit in tasks if changes made to the db
    db.commit()
    return ret
Beispiel #8
0
def ensure_settings():
    # Check the settings table, there should be one row
    if db(db.my_app_settings).count() < 1:
        # Add a row
        db.my_app_settings.insert()

    # Make sure LDAP is reset after reloading settings
    AD.Close()
    return True
Beispiel #9
0
    def DisableAccount(student_id):
        ret = ""
        db = current.db  # Grab the current db object
        auth = current.auth  # Grab the current auth object

        user_name = Student.GetUsername(student_id)

        pw = "J#jsa3#31" + str(time.time())

        Student.SetPassword(student_id, pw, False)

        user_dn = Student.GetAD_DN(user_name, Student.GetProgram(student_id))
        r = AD.DisableUser(user_dn)

        # Update the database to reflect the change
        db(db.student_info.user_id == student_id).update(account_enabled=False)
        if r is False:
            ret = "ERROR disabling account - " + AD.GetErrorString()
        return ret
Beispiel #10
0
    def GetLastADLoginTime(student_id):
        ret = ""
        db = current.db  # Grab the current db object
        auth = current.auth  # Grab the current auth object

        user_name = Student.GetUsername(student_id)

        # AD - Disable
        user_dn = Student.GetAD_DN(user_name, Student.GetProgram(student_id))

        ret = AD.GetLastLoginTime(user_dn)
        return ret
Beispiel #11
0
def create_home_directory(user_name, home_directory):
    print("Creating home directory for: " + user_name + " [" +
          str(time.time()) + "]")
    ret = AD.CreateHomeDirectory(user_name, home_directory)
    print("Done Creating home directory for: " + user_name + " [" +
          str(time.time()) + "]")
    print("Result: " + ret)

    # Have to call commit in tasks if changes made to the db
    db.commit()

    return ret
Beispiel #12
0
def switchquota():
    ensure_settings()

    disabled = SQLFORM.factory(submit_button="Set Quota Disabled",
                               _name="disabled").process(formname="disabled")

    tracking = SQLFORM.factory(submit_button="Set Quota Tracking",
                               _name="tracking").process(formname="tracking")

    enforcing = SQLFORM.factory(
        submit_button="Set Quota Enforcing",
        _name="enforcing").process(formname="enforcing")

    if disabled.accepted:
        if AD.SetQuotaEnabled(False, False) is not True:
            response.flash = "Error setting quota mode to disabled: " + AD.GetErrorString(
            )
        else:
            response.flash = "Quota set to disabled"  # + str(ret)
    if tracking.accepted:
        if AD.SetQuotaEnabled(True, False) is not True:
            response.flash = "Error setting quota mode to tracking: " + AD.GetErrorString(
            )
        else:
            response.flash = "Quota set to tracking"  # + str(ret)
    if enforcing.accepted:
        if AD.SetQuotaEnabled(True, True) is not True:
            response.flash = "Error setting quota mode to enforcing: " + AD.GetErrorString(
            )
        else:
            response.flash = "Quota set to enforcing"  # + str(ret)

    return dict(switch_disabled=disabled,
                switch_tracking=tracking,
                switch_enforcing=enforcing)
Beispiel #13
0
 def EnableAccount(faculty_id):
     ret = ""
     db = current.db # Grab the current db object
     auth = current.auth # Grab the current auth object
     
     user_name = Faculty.GetUsername(faculty_id)
     
     pw = Faculty.GetPassword(faculty_id)
     
     Faculty.SetPassword(faculty_id, pw)
     
     # AD - Disable
     user_dn = Faculty.GetAD_DN(user_name, Faculty.GetProgram(faculty_id))
     AD.EnableUser(user_dn)
     
     # Update the database to reflect the change
     db(db.faculty_info.user_id == faculty_id).update(account_enabled=True)
     
     return ret
Beispiel #14
0
def config_ad_settings():
    ensure_settings()

    rows = db().select(db.my_app_settings.ALL)
    form = SQLFORM(db.my_app_settings,
                   rows[0],
                   showid=False,
                   fields=[
                       "ad_import_enabled", "ad_service_user",
                       "ad_service_password", "ad_server_protocol",
                       "ad_server_address"
                   ]).process()

    if form.accepted:
        # Saved
        response.flash = "Settings Saved!"
        AD.Close()
        pass
    elif form.errors:
        response.flash = "Error! " + str(form.errors)
    return dict(form=form)
Beispiel #15
0
def faculty_do_import():
    AD.Close()
    sheet_name = request.vars.sheet_name
    erase_current_password = False
    if request.vars.erase_current_password == "True":
        erase_current_password = True
    erase_current_quota = False
    if request.vars.erase_current_quota == "True":
        erase_current_quota = True

    # Add faculty account to faculty_info table
    count = Faculty.CreateW2PyAccounts(sheet_name, erase_current_password,
                                       erase_current_quota)

    # Setup queue for canvas and for ad imports
    count2 = Faculty.QueueActiveDirectoryImports(sheet_name)
    count3 = Faculty.QueueCanvasImports(sheet_name)
    if count2 > count:
        count = count2
    if count3 > count:
        count = count3
    return dict(sheet_name=sheet_name, count=count)
Beispiel #16
0
def config_zfs_settings():
    ensure_settings()
    msg = ""

    rows = db().select(db.my_app_settings.ALL)
    form = SQLFORM(db.my_app_settings,
                   rows[0],
                   showid=False,
                   fields=[
                       "zpool_enabled", "zpool_server_address",
                       "zpool_login_user", "zpool_login_password",
                       "zpool_source_dataset", "zpool_dest_dataset",
                       "zpool_sync_setting"
                   ]).process()

    if form.accepted:
        # Saved
        response.flash = "Settings Saved!"
        AD.Close()
        pass
    elif form.errors:
        response.flash = "Error! " + str(form.errors)
    return dict(form=form, message=msg)
Beispiel #17
0
def config_student_settings():
    ensure_settings()

    rows = db().select(db.my_app_settings.ALL)
    form = SQLFORM(db.my_app_settings,
                   rows[0],
                   showid=False,
                   fields=[
                       "student_id_pattern", "student_password_pattern",
                       "student_email_pattern", "ad_student_cn",
                       "ad_student_group_cn", "ad_student_home_directory",
                       "ad_student_home_drive", "ad_student_profile_directory",
                       "ad_student_login_script_path",
                       "ad_student_home_directory_quota"
                   ]).process()

    if form.accepted:
        # Saved
        response.flash = "Settings Saved!"
        AD.Close()
        pass
    elif form.errors:
        response.flash = "Error! " + str(form.errors)
    return dict(form=form)
Beispiel #18
0
 def GetAD_DN(user_name, program):
     ret = Faculty.GetAD_CN(program)
     ret = AD.GetDN(user_name, ret)
     
     return ret
Beispiel #19
0
        update_document_database_from_json_files=
        update_document_database_from_json_files,
        flush_redis_keys=flush_redis_keys,
        pull_youtube_caption=pull_youtube_caption,
    ))
current.scheduler = scheduler

# Make sure to run the ad login refresh every hour or so
refresh_ad_login = current.cache.ram('refresh_ad_login',
                                     lambda: True,
                                     time_expire=60 * 60)
if refresh_ad_login is True and request.is_scheduler is not True:
    # Set the current value to false so we don't need to refresh for a while
    current.cache.ram('refresh_ad_login', lambda: False, time_expire=-1)
    # Update the last login value for all users (students and faculty)
    AD.Init()  # Make sur AD settings are loaded
    print("Queueing up refresh_all_ad_logins...")
    # print(str(request.is_scheduler))
    # print(str(request))
    if AD._ldap_enabled is not True:
        # Not enabled, skip
        print("AD Not enabled, skipping refresh_all_ad_logins...")
    else:
        # Schedule the process
        result = scheduler.queue_task('refresh_all_ad_logins',
                                      timeout=1200,
                                      sync_output=5,
                                      group_name="misc",
                                      repeats=1,
                                      period=0,
                                      pvars=dict(run_from='x_scheduler.py'))
Beispiel #20
0
    def ProcessADStudent():
        db = current.db  # Grab the current db object
        scheduler = current.scheduler
        ret = ""
        # AD.Close()

        ldap_enabled = AppSettings.GetValue('ad_import_enabled', False)
        if ldap_enabled is not True:
            return "Done! - LDAP Import Disabled"

        if AD.Connect() is not True:
            ret += "<b>Error connecting to Active Directory server</b><br/><font size=-4>"
            ret += AD.GetErrorString()
            ret += "</font><br/>Done!"
            return ret

        if AD.VerifyADSettings() is not True:
            ret += "<b>Error verifying AD settings</b><br/><font size=-4>"
            ret += AD.GetErrorString()
            ret += "</font><br/>Done!"
            return ret
        else:
            # If everything is good clear errors
            AD._errors = []

        # ad_student_cn = AppSettings.GetValue('ad_student_cn', 'OU=Students,DC=ad,DC=correctionsed,DC=com')
        ad_student_group_cn = AppSettings.GetValue(
            'ad_student_group_cn',
            'OU=StudentGroups,DC=ad,DC=correctionsed,DC=com')
        ad_student_group_dn = 'CN=Students,' + ad_student_group_cn

        # Ensure the student group exists
        if AD.CreateGroup(ad_student_group_dn) is not True:
            ret += "<b>Error creating students group:</b> " + str(
                ad_student_group_dn) + "<br />"
            ret += str(AD._errors)

        # Grab the first student off the queue
        rows = db(db.student_import_queue.id == db.student_ad_import_queue.student_import_queue)\
            .select(orderby=db.student_import_queue.account_enabled|db.student_import_queue.student_name,
                    limitby=(0, 1))

        for row in rows:
            # Pop the student off the queue
            db(db.student_ad_import_queue.id ==
               row.student_ad_import_queue.id).delete()
            db.commit()
            # Get the student info
            # Get info for current student
            student_user_name = Student.GetUsername(
                row.student_import_queue.user_id)
            student_password = Student.GetPassword(
                row.student_import_queue.user_id,
                row.student_import_queue.student_password)
            (student_first_name, student_last_name) = Util.ParseName(
                row.student_import_queue.student_name)
            student_email = Student.GetEmail(row.student_import_queue.user_id)
            student_display_name = row.student_import_queue.student_name + " (" + student_user_name + ")"
            student_user_id = row.student_import_queue.user_id
            student_home_directory = Student.GetHomeDirectory(
                row.student_import_queue.user_id)
            student_home_drive = Student.GetHomeDrive(
                row.student_import_queue.user_id)
            student_login_script_path = Student.GetLoginScriptPath(
                row.student_import_queue.user_id)
            student_profile_path = Student.GetProfilePath(
                row.student_import_queue.user_id)
            student_enabled = row.student_import_queue.account_enabled
            student_quota = Student.GetADQuota(
                row.student_import_queue.user_id)
            student_dn = Student.GetAD_DN(student_user_name,
                                          row.student_import_queue.program)
            student_cn = Student.GetAD_CN(row.student_import_queue.program)

            first_run = False
            fr = db(db.student_ad_import_status.user_id ==
                    row.student_import_queue.user_id).select().first()
            if fr is None:
                first_run = True
            db.student_ad_import_status.insert(
                user_id=row.student_import_queue.user_id)
            db.commit()

            # print("Student Info: ")
            # print(" -> User Name: " + str(student_user_name))
            # print(" -> Password: "******" -> First Name: " + str(student_first_name))
            # print(" -> Last Name: " + str(student_last_name))
            # print(" -> Email: " + str(student_email))
            # print(" -> Display Name: " + str(student_display_name))
            # print(" -> ID: " + str(student_user_id))
            # print(" -> Home Dir: " + str(student_home_directory))
            # print(" -> Home Drive: " + str(student_home_drive))
            # print(" -> Login Script: " + str(student_login_script_path))
            # print(" -> Profile Path: " + str(student_profile_path))
            # print(" -> Enabled: " + str(student_enabled))
            # print(" -> Quota: " + str(student_quota))
            # print(" -> AD DN: " + str(student_dn))
            # print(" -> AD CN: " + str(student_cn))

            # Create the student
            if AD.CreateUser(student_user_name, student_cn) is not True:
                ret += "<b>Error creating students account:</b> " + str(student_user_name) +\
                       " - " + str(student_cn) + "<br />Done!"
                return ret
            db.commit()
            # Update user with current info
            if AD.UpdateUserInfo(student_dn,
                                 email_address=student_email,
                                 first_name=student_first_name,
                                 last_name=student_last_name,
                                 display_name=student_display_name,
                                 description="Student Account",
                                 id_number=student_user_name,
                                 home_drive_letter=student_home_drive,
                                 home_directory=student_home_directory,
                                 login_script=student_login_script_path,
                                 profile_path=student_profile_path,
                                 ts_allow_login='******') is not True:
                ret += "<b>Error creating setting student information:</b> " + str(
                    student_user_name) + "<br />"
            db.commit()
            # Set password
            if AD.SetPassword(student_dn, student_password) is not True:
                ret += "<b>Error setting password for user:</b> " + str(
                    student_user_name) + "<br />"
            db.commit()
            # Add to the students group
            if AD.AddUserToGroup(student_dn, ad_student_group_dn) is not True:
                ret += "<b>Error adding user to students group:</b> " + str(
                    student_user_name) + "<br />"
            db.commit()
            if student_enabled is True:
                AD.EnableUser(student_dn)
            else:
                AD.DisableUser(student_dn)
            db.commit()

            # Get the list of classes for this student
            if student_enabled is True:
                enroll_classes = row.student_import_queue.import_classes.split(
                    ',')
                for enroll_class in enroll_classes:
                    # Trim spaces
                    enroll_class = enroll_class.strip()

                    if enroll_class == '':
                        continue  # Skip empty class names

                    Student.AddClass(row.student_import_queue.user_id,
                                     enroll_class)

                    class_dn = AD.GetDN(enroll_class, ad_student_group_cn)
                    if AD.GetLDAPObject(class_dn) is None:
                        # Class group doesn't exist, add it
                        if AD.CreateGroup(class_dn) is not True:
                            ret += "<b>Error creating class group:</b> " + str(
                                enroll_class) + "<br />"

                    # Add student to the class group
                    if AD.AddUserToGroup(student_dn, class_dn) is not True:
                        ret += "<b>Error adding student to group:</b> " + str(student_user_name) + "/" +\
                               str(enroll_class) + "<br />"
            db.commit()
            # Setup physical home directory
            if student_enabled is True:
                # if (AD.CreateHomeDirectory(student_user_name, student_home_directory) != True):
                #    ret += "<b>Error creating home folder:</b> " + str(student_user_name) + "<br />"
                if first_run:
                    result = scheduler.queue_task(
                        'create_home_directory',
                        pvars=dict(user_name=student_user_name,
                                   home_directory=student_home_directory),
                        timeout=1200,
                        immediate=True,
                        sync_output=5,
                        group_name="create_home_directory")
                if AD.SetDriveQuota(student_user_name,
                                    student_quota) is not True:
                    ret += "<b>Error setting quota for student:</b> " + str(
                        student_user_name) + "<br />"
            db.commit()
            # Show errors
            if len(AD._errors) > 0:
                ret += AD.GetErrorString()

            ret += student_display_name  # + " (" + student_user_name + ")"
            if row.student_import_queue.account_enabled is True:
                ret += " - <span style='color: green; font-weight: bolder;'>Imported</span>"
            else:
                ret += " - <span style='color: red; font-weight: bolder;'>Disabled</span>"

        if ret == "":
            ret = "Done!"
        return ret
Beispiel #21
0
    def GetAD_DN(user_name, program):
        ret = Student.GetAD_CN(program)
        ret = AD.GetDN(user_name, ret)

        return ret
Beispiel #22
0
    def ProcessADFaculty():
        db = current.db # Grab the current db object
        scheduler = current.scheduler
        ret = ""

        ldap_enabled = AppSettings.GetValue('ad_import_enabled', False)
        if ldap_enabled is not True:
            return "Done! - LDAP Import Disabled"
        
        if AD.Connect() is not True:
            ret += "<b>Error connecting to Active Directory server</b><br/><font size=-4>"
            ret += AD.GetErrorString()
            ret += "</font><br/>Done!"
            return ret
        
        if AD.VerifyADSettings() is not True:
            ret += "<b>Error verifying AD settings</b><br/><font size=-4>"
            ret += AD.GetErrorString()
            ret += "</font><br/>Done!"
            return ret
        else:
            # If everything is good clear errors
            AD._errors = []

        ad_faculty_group_cn = AppSettings.GetValue('ad_faculty_group_cn',
                                                   'OU=FacultyGroups,DC=ad,DC=correctionsed,DC=com')
        ad_faculty_group_dn = 'CN=Faculty,' + ad_faculty_group_cn
        
        # Ensure the faculty group exists
        if AD.CreateGroup(ad_faculty_group_dn) is not True:
            ret += "<b>Error creating faculty group:</b> " + str(ad_faculty_group_dn) + "<br />"
            ret += str(AD._errors)
        
        # Grab the first faculty off the queue
        rows = db(db.faculty_import_queue.id == db.faculty_ad_import_queue.faculty_import_queue)\
            .select(orderby=db.faculty_import_queue.account_enabled|db.faculty_import_queue.faculty_name,
                    limitby=(0, 1))
        
        for row in rows:
            # Pop the faculty off the queue
            db(db.faculty_ad_import_queue.id == row.faculty_ad_import_queue.id).delete()
            db.commit()
            # Get the faculty info
            faculty_user_name = Faculty.GetUsername(row.faculty_import_queue.user_id)
            faculty_password = Faculty.GetPassword(row.faculty_import_queue.user_id, row.faculty_import_queue.faculty_password)
            (faculty_first_name, faculty_last_name) = Util.ParseName(row.faculty_import_queue.faculty_name)
            faculty_email = Faculty.GetEmail(row.faculty_import_queue.user_id)
            faculty_display_name = row.faculty_import_queue.faculty_name + " (" + faculty_user_name + ")"
            faculty_user_id = row.faculty_import_queue.user_id
            faculty_home_directory = Faculty.GetHomeDirectory(row.faculty_import_queue.user_id)
            faculty_home_drive = Faculty.GetHomeDrive(row.faculty_import_queue.user_id)
            faculty_login_script_path = Faculty.GetLoginScriptPath(row.faculty_import_queue.user_id)
            faculty_profile_path = Faculty.GetProfilePath(row.faculty_import_queue.user_id)
            faculty_enabled = row.faculty_import_queue.account_enabled
            faculty_quota = Faculty.GetADQuota(row.faculty_import_queue.user_id)
            faculty_dn = Faculty.GetAD_DN(faculty_user_name, row.faculty_import_queue.program)
            faculty_cn = Faculty.GetAD_CN(row.faculty_import_queue.program)
            
            first_run = False
            fr = db(db.faculty_ad_import_status.user_id==row.faculty_import_queue.user_id).select().first()
            if fr is None:
                first_run = True
            db.faculty_ad_import_status.insert(user_id=row.faculty_import_queue.user_id)
            db.commit()
            
            # Create the faculty
            if AD.CreateUser(faculty_user_name, faculty_cn) is not True:
                ret += "<b>Error creating faculty account:</b> " + str(faculty_user_name) + " - " + str(faculty_cn) +\
                       "<br />Done!"  # + AD.GetErrorString()
                return ret
            db.commit()
            # Update user with current info
            if AD.UpdateUserInfo(faculty_dn, email_address=faculty_email, first_name=faculty_first_name,
                                 last_name=faculty_last_name, display_name=faculty_display_name,
                                 description="Faculty Account", id_number=faculty_user_name,
                                 home_drive_letter=faculty_home_drive, home_directory=faculty_home_directory,
                                 login_script=faculty_login_script_path, profile_path=faculty_profile_path,
                                 ts_allow_login='******') is not True:
                ret += "<b>Error creating setting faculty information:</b> " + str(faculty_user_name) + "<br />"
            db.commit()
            # Set password
            if AD.SetPassword(faculty_dn, faculty_password) is not True:
                ret += "<b>Error setting password for user:</b> " + str(faculty_user_name) + "<br />"
            db.commit()
            # Add to the faculty group
            if AD.AddUserToGroup(faculty_dn, ad_faculty_group_dn) is not True:
                ret += "<b>Error adding user to faculty group:</b> " + str(faculty_user_name) + "<br />"
            db.commit()
            if faculty_enabled is True:
                AD.EnableUser(faculty_dn)
            else:
                AD.DisableUser(faculty_dn)
            db.commit()

            # NOTE - We do NOT want to remove faculty from anything automatically
            
            # Get the list of classes for this faculty
            if faculty_enabled is True:
                enroll_classes = row.faculty_import_queue.import_classes.split(',')
                for enroll_class in enroll_classes:
                    # Trim spaces
                    enroll_class = enroll_class.strip()

                    if enroll_class == '':
                        continue  # Skip empty class names
                    # ret += "Enrolling into: " + enroll_class
                    Faculty.AddClass(row.faculty_import_queue.user_id, enroll_class)
                    
                    class_dn = AD.GetDN(enroll_class + "-F", ad_faculty_group_cn)
                    if AD.GetLDAPObject(class_dn) is None:
                        # Class group doesn't exist, add it
                        if AD.CreateGroup(class_dn) is not True:
                            ret += "<b>Error creating class group:</b> " + str(enroll_class) + "<br />"

                    # Add faculty to the class group
                    if AD.AddUserToGroup(faculty_dn, class_dn) is not True:
                        ret += "<b>Error adding faculty to group:</b> " + str(faculty_user_name) +\
                               "/" + str(enroll_class) + "<br />"
            db.commit()
            # Setup physical home directory
            if faculty_enabled is True:
                # if (AD.CreateHomeDirectory(faculty_user_name, faculty_home_directory) != True):
                #    ret += "<b>Error creating home folder:</b> " + str(faculty_user_name) + "<br />"
                if first_run:
                    result = scheduler.queue_task('create_home_directory',
                                                  pvars=dict(user_name=faculty_user_name,
                                                             home_directory=faculty_home_directory),
                                                  timeout=1200, immediate=True, sync_output=5,
                                                  group_name="create_home_directory")
                if AD.SetDriveQuota(faculty_user_name, faculty_quota) is not True:
                    ret += "<b>Error setting quota for faculty:</b> " + str(faculty_user_name) + "<br />"
            db.commit()
            # Show errors
            if len(AD._errors) > 0:
                ret += AD.GetErrorString()
            
            ret += faculty_display_name  # + " (" + faculty_user_name + ")"
            if row.faculty_import_queue.account_enabled is True:
                ret += " - <span style='color: green; font-weight: bolder;'>Imported</span>"
            else:
                ret += " - <span style='color: red; font-weight: bolder;'>Disabled</span>"

        # Finished importing, clean up after AD
        AD.Close()
        
        if ret == "":
            ret = "Done!"
        return ret