• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pulibrary / tigerdata-app / 904be010-4760-47b0-943f-db65c886cd13

28 Oct 2025 02:06PM UTC coverage: 72.228% (-19.1%) from 91.294%
904be010-4760-47b0-943f-db65c886cd13

Pull #2057

circleci

hectorcorrea
Force a change
Pull Request #2057: Dashboard displays projects straights from Mediaflux

65 of 69 new or added lines in 4 files covered. (94.2%)

257 existing lines in 31 files now uncovered.

2221 of 3075 relevant lines covered (72.23%)

190.52 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

43.86
/app/services/princeton_users.rb
1
# frozen_string_literal: true
2
class PrincetonUsers
1✔
3
  CHARS_AND_NUMS =  ('a'..'z').to_a + (0..9).to_a + ['-']
1✔
4
  RDSS_DEVELOPERS = %w[bs3097 jrg5 cac9 hc8719 rl3667 kl37 pp9425 jh6441].freeze
1✔
5

6
  class << self
1✔
7

8

9
    # Returns a list of Users that match the given query
10
    def user_list_query(query)
1✔
11
      tokens = query.downcase.strip.split(/[^a-zA-Z\d]/).compact_blank
15✔
12
      return [] if tokens.count == 0
15✔
13
      if (tokens.count == 1)
15✔
14
        # if I have a single token I might be trying a uid search, so put all the uid matches at the top
15
        uid_query(tokens[0]) | name_query(tokens)
9✔
16
      else
17
        name_query(tokens)
6✔
18
      end.map{|user| { uid: user.uid, name: user.display_name, display_name: user.display_name_safe } }
15✔
19
    end
20

21
    def uid_query(token)
1✔
22
      order_sql = User.sanitize_sql_for_order("LENGTH(uid)-LENGTH('#{token}')")
9✔
23
      search_token = User.sanitize_sql_like(token)+'%'
9✔
24
      User.where("(uid like ?)",search_token).order(Arel.sql(order_sql)).order(:uid)
9✔
25
    end
26

27
    def name_query(tokens)
1✔
28
      tokens.inject(User.all) do |partial_query, token|
15✔
29
        search_token = '%'+User.sanitize_sql_like(token)+'%'
27✔
30
        partial_query.where("(LOWER(display_name) like ?) OR (LOWER(uid) like ?)", search_token, search_token)
27✔
31
      end.order(:given_name).order(:family_name)
32
    end
33

34
    def load_rdss_developers
1✔
UNCOV
35
      RDSS_DEVELOPERS.each do |netid|
×
UNCOV
36
        create_user_from_ldap_by_uid(netid)
×
37
        rescue TigerData::LdapError
UNCOV
38
        raise TigerData::LdapError, "Unable to create user from LDAP. Are you connected to VPN?"
×
39
      end
40
    end
41

42
    # Creates users from LDAP data, starting with the given uid prefix.
43
    def create_users_from_ldap(current_uid_start: "", ldap_connection: default_ldap_connection)
1✔
UNCOV
44
      CHARS_AND_NUMS.each do |char|
×
UNCOV
45
        filter =(~ Net::LDAP::Filter.eq( "pustatus", "guest" )) & Net::LDAP::Filter.eq("uid", "#{current_uid_start}#{char}*")
×
UNCOV
46
        people = ldap_connection.search(filter:, attributes: [:pudisplayname, :givenname, :sn, :uid, :edupersonprincipalname]);
×
UNCOV
47
        if ldap_connection.get_operation_result.message == "Success"
×
UNCOV
48
          people.each{|person| user_from_ldap(person)}
×
49
        else
UNCOV
50
          create_users_from_ldap(current_uid_start: "#{current_uid_start}#{char}", ldap_connection:)
×
51
        end
52
      end
53
    end
54

55
    def create_user_from_ldap_by_uid(uid, ldap_connection: default_ldap_connection)
1✔
UNCOV
56
      filter = Net::LDAP::Filter.eq('uid', uid)
×
UNCOV
57
      person = ldap_connection.search(filter:, attributes: [:pudisplayname, :givenname, :sn, :uid, :edupersonprincipalname]);
×
UNCOV
58
      raise TigerData::LdapError, "More than one user matches supplied uid: #{uid}" if person.length > 1
×
UNCOV
59
      raise TigerData::LdapError, "No user with uid #{uid} found" if person.empty?
×
UNCOV
60
      user_from_ldap(person.first)
×
61
    end
62

63
  # Creates or updates a User from an LDAP entry.
64
  # @param ldap_person [Net::LDAP::Entry] an LDAP entry representing a person
65
  # @return [User, nil] the created or updated User, or nil if the LDAP entry is missing a edupersonprincipalname
66
    def user_from_ldap(ldap_person)
1✔
UNCOV
67
      return if check_for_malformed_ldap_entries(ldap_person)
×
UNCOV
68
      uid = ldap_person[:uid].first.downcase
×
UNCOV
69
      current_entries = User.where(uid:)
×
UNCOV
70
      if current_entries.empty?
×
UNCOV
71
        User.create(uid: , display_name: ldap_person[:pudisplayname].first,
×
72
                    family_name: ldap_person[:sn].first, given_name: ldap_person[:givenname].first,
73
                    email: ldap_person[:edupersonprincipalname].first, provider: "cas")
74
      else
UNCOV
75
        user = current_entries.first
×
UNCOV
76
        if user.display_name.blank?
×
UNCOV
77
          user.display_name = ldap_person[:pudisplayname].first
×
UNCOV
78
          user.family_name = ldap_person[:sn].first
×
UNCOV
79
          user.given_name = ldap_person[:givenname].first
×
UNCOV
80
          user.provider = "cas"
×
UNCOV
81
          user.save
×
82
        end
UNCOV
83
        user
×
84
      end
85
    end
86

87
    # If any required LDAP fields are missing, return true
88
    # @param ldap_person [Net::LDAP::Entry] an LDAP entry representing a person
89
    # @return [Boolean] true if the LDAP entry is missing required fields, false otherwise
90
    def check_for_malformed_ldap_entries(ldap_person)
1✔
UNCOV
91
      uid_blank = ldap_person[:uid].blank?
×
UNCOV
92
      edupersonprincipalname_blank = ldap_person[:edupersonprincipalname].blank?
×
UNCOV
93
      malformed = uid_blank || edupersonprincipalname_blank
×
UNCOV
94
      malformed
×
95
    end
96

97
    def default_ldap_connection
1✔
UNCOV
98
      @default_ldap_connection ||= Net::LDAP.new host: "ldap.princeton.edu", base: "o=Princeton University,c=US", port: 636,
×
99
                                                  encryption: {
100
                                                    method: :simple_tls,
101
                                                    tls_options: OpenSSL::SSL::SSLContext::DEFAULT_PARAMS
102
                                                  }
103
    end
104
  end
105
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc