Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lazy loading ldap user #1104

Merged
merged 14 commits into from
Oct 4, 2017
4 changes: 2 additions & 2 deletions app/controllers/associated_users_controller.rb
Expand Up @@ -40,7 +40,7 @@ def new
@dashboard = false

if params[:identity_id] # if user selected
@identity = Identity.find(params[:identity_id])
@identity = Identity.find_or_create(params[:identity_id])
@project_role = @protocol.project_roles.new(identity_id: @identity.id)
@current_pi = @protocol.primary_principal_investigator

Expand Down Expand Up @@ -117,7 +117,7 @@ def destroy
def search_identities
# Like SearchController#identities, but without ssr/sr authorization
term = params[:term].strip
results = Identity.search(term).map { |i| { label: i.display_name, value: i.id, email: i.email } }
results = Identity.search(term).map { |i| { label: i.display_name, value: i.suggestion_value, email: i.email } }
results = [{ label: 'No Results' }] if results.empty?

render json: results.to_json
Expand Down
6 changes: 3 additions & 3 deletions app/controllers/dashboard/associated_users_controller.rb
Expand Up @@ -49,9 +49,9 @@ def edit
def new
@header_text = t(:authorized_users)[:add][:header]
@dashboard = true

if params[:identity_id] # if user selected
@identity = Identity.find(params[:identity_id])
@identity = Identity.find_or_create(params[:identity_id])
@project_role = @protocol.project_roles.new(identity_id: @identity.id)
@current_pi = @protocol.primary_principal_investigator

Expand Down Expand Up @@ -149,7 +149,7 @@ def destroy
def search_identities
# Like SearchController#identities, but without ssr/sr authorization
term = params[:term].strip
results = Identity.search(term).map { |i| { label: i.display_name, value: i.id, email: i.email } }
results = Identity.search(term).map { |i| { label: i.display_name, value: i.suggestion_value, email: i.email } }
results = [{ label: 'No Results' }] if results.empty?

render json: results.to_json
Expand Down
39 changes: 29 additions & 10 deletions app/lib/directory.rb
Expand Up @@ -50,20 +50,29 @@ class Directory
def self.search(term)
# Search ldap (if enabled) and the database
if USE_LDAP && !SUPPRESS_LDAP_FOR_USER_SEARCH
ldap_results = search_ldap(term)
db_results = search_database(term)
# If there are any entries returned from ldap that were not in the
# database, then create them
create_or_update_database_from_ldap(ldap_results, db_results)
# Finally, search the database a second time and return the results.
# If there were no new identities created, then this should return
# the same as the original call to search_database().
return search_database(term)
if LAZY_LOAD
return self.search_and_merge_ldap_and_database_results(term)
else
return self.search_and_merge_and_update_ldap_and_database_results(term)
end

else # only search database once
return search_database(term)
end
end

def self.search_and_merge_and_update_ldap_and_database_results(term)
ldap_results = self.search_ldap(term)
db_results = self.search_database(term)
self.create_or_update_database_from_ldap(ldap_results, db_results)
# Finally, search the database a second time and return the results.
# If there were no new identities created, then this should return
# the same as the original call to search_database().
return self.search_database(term)
end

# Searches the database only for a given search string. Returns an
# array of Identities.
def self.search_database(term)
Expand All @@ -72,6 +81,16 @@ def self.search_database(term)
return identities
end

def self.find_or_create(ldap_uid)
identity = Identity.find_by_ldap_uid(ldap_uid)
return identity if identity
# search the ldap using unid, create the record in database, and then return it
m = /(.*)@#{DOMAIN}/.match(ldap_uid)
ldap_results = self.search_ldap(m[1])
self.create_or_update_database_from_ldap(ldap_results, [])
Identity.find_by_ldap_uid(ldap_uid)
end

# Searches LDAP only for the given search string. Returns an array of
# Net::LDAP::Entry.
def self.search_ldap(term)
Expand Down Expand Up @@ -186,7 +205,7 @@ def self.create_or_update_database_from_ldap(ldap_results, db_results)
end
end
end

# search and merge results but don't change the database
# this assumes USE_LDAP = true, otherwise you wouldn't use this function
def self.search_and_merge_ldap_and_database_results(term)
Expand All @@ -202,11 +221,11 @@ def self.search_and_merge_ldap_and_database_results(term)
uid = "#{ldap_result[LDAP_UID].try(:first).try(:downcase)}@#{DOMAIN}"
if identities[uid]
results << identities[uid]
else
else
email = ldap_result[LDAP_EMAIL].try(:first)
if email && email.strip.length > 0 # all SPARC users must have an email, this filters out some of the inactive LDAP users.
results << Identity.new(ldap_uid: uid, first_name: ldap_result[LDAP_FIRST_NAME].try(:first), last_name: ldap_result[LDAP_LAST_NAME].try(:first), email: email)
end
end
end
end
results
Expand Down
18 changes: 17 additions & 1 deletion app/models/identity.rb
Expand Up @@ -90,6 +90,14 @@ def email_required?
false
end

def suggestion_value
if LAZY_LOAD && USE_LDAP
ldap_uid
else
id
end
end

###############################################################################
############################## HELPER METHODS #################################
###############################################################################
Expand Down Expand Up @@ -161,6 +169,14 @@ def self.search(term)
return Directory.search(term)
end

def self.find_or_create(id)
if LAZY_LOAD && USE_LDAP
return Directory.find_or_create(id)
else
return self.find(id)
end
end

###############################################################################
########################### PERMISSION METHODS ################################
###############################################################################
Expand Down Expand Up @@ -233,7 +249,7 @@ def can_view_protocol?(protocol)
def can_edit_protocol?(protocol)
protocol.project_roles.where(identity_id: self.id, project_rights: ['approve', 'request']).any?
end

# Determines whether this identity can edit a given organization's information in CatalogManager.
# Returns true if this identity's catalog_manager_organizations includes the given organization.
def can_edit_entity? organization, deep_search=false
Expand Down
1 change: 1 addition & 0 deletions config/application.yml.example
Expand Up @@ -19,6 +19,7 @@
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

development:
lazy_load: true
default_mail_to: catesa@musc.edu
admin_mail_to: catesa@musc.edu
feedback_mail_to: "hutsonk@musc.edu"
Expand Down
1 change: 1 addition & 0 deletions config/initializers/01_obis_setup.rb
Expand Up @@ -28,6 +28,7 @@
# Otherwise all emails will be routed to DEFAULT_MAIL_TO
SEND_EMAILS_TO_REAL_USERS = application_config['send_emails_to_real_users'] || false

LAZY_LOAD = application_config['lazy_load']
ADMIN_MAIL_TO = application_config['admin_mail_to']
EPIC_RIGHTS_MAIL_TO = application_config['approve_epic_rights_mail_to']
FEEDBACK_MAIL_TO = application_config['feedback_mail_to']
Expand Down
Expand Up @@ -30,10 +30,12 @@
before(:each) do
matching_record1 = instance_double(Identity,
display_name: "My Good Name",
suggestion_value: 1,
id: 1,
email: "user1@email.com")
matching_record2 = instance_double(Identity,
display_name: "Person",
suggestion_value: 2,
id: 2,
email: "user2@email.com")
allow(Identity).to receive(:search).with("ABC").and_return([matching_record1, matching_record2])
Expand Down