diff --git a/.junie/guidelines.md b/.junie/guidelines.md index a104883..94a8baf 100644 --- a/.junie/guidelines.md +++ b/.junie/guidelines.md @@ -12,7 +12,7 @@ This document captures project-specific knowledge to streamline setup, testing, - See .env.local.example for an example of what to put in .env.local. - See CONTRIBUTING.md for details on how to set up your local environment. - Ruby and Bundler - - Runtime supports Ruby >= 0 + - Runtime supports Ruby >= 2.0 - Development tooling targets Ruby >= 2.3 (minimum supported by setup-ruby GHA). - Use a recent Ruby (>= 3.4 recommended) for fastest setup and to exercise modern coverage behavior. - Install dependencies via Bundler in project root: diff --git a/.opencollective.yml b/.opencollective.yml deleted file mode 100644 index 1eaf11d..0000000 --- a/.opencollective.yml +++ /dev/null @@ -1,3 +0,0 @@ -collective: "omniauth" -readme-backers-commit-subject: "💸 Thanks 🙏 to our new backers 🎒 and subscribers 📜" -readme-osc-tag: "OPENCOLLECTIVE" diff --git a/README.md b/README.md index e0b4154..e5fc4fe 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ | 📍 NOTE | |-------------------------------------------------------------------------------------------------------------------------------------------------------------------| | RubyGems (the [GitHub org][rubygems-org], not the website) [suffered][draper-security] a [hostile takeover][ellen-takeover] in September 2025. | +| Ultimately [4 maintainers][simi-removed] were [hard removed][martin-removed] and a reason has been given for only 1 of those, while 2 others resigned in protest. | | It is a [complicated story][draper-takeover] which is difficult to [parse quickly][draper-lies]. | | I'm adding notes like this to gems because I [don't condone theft][draper-theft] of repositories or gems from their rightful owners. | | If a similar theft happened with my repos/gems, I'd hope some would stand up for me. | @@ -37,6 +38,7 @@ # 📁 OmniAuth LDAP +[![Version][👽versioni]][👽version] [![GitHub tag (latest SemVer)][⛳️tag-img]][⛳️tag] [![License: MIT][📄license-img]][📄license-ref] [![Downloads Rank][👽dl-ranki]][👽dl-rank] [![Open Source Helpers][👽oss-helpi]][👽oss-help] [![CodeCov Test Coverage][🏀codecovi]][🏀codecov] [![Coveralls Test Coverage][🏀coveralls-img]][🏀coveralls] [![QLTY Test Coverage][🏀qlty-covi]][🏀qlty-cov] [![QLTY Maintainability][🏀qlty-mnti]][🏀qlty-mnt] [![CI Heads][🚎3-hd-wfi]][🚎3-hd-wf] [![CI Runtime Dependencies @ HEAD][🚎12-crh-wfi]][🚎12-crh-wf] [![CI Current][🚎11-c-wfi]][🚎11-c-wf] [![CI Truffle Ruby][🚎9-t-wfi]][🚎9-t-wf] [![CI JRuby][🚎10-j-wfi]][🚎10-j-wf] [![Deps Locked][🚎13-🔒️-wfi]][🚎13-🔒️-wf] [![Deps Unlocked][🚎14-🔓️-wfi]][🚎14-🔓️-wf] [![CI Supported][🚎6-s-wfi]][🚎6-s-wf] [![CI Legacy][🚎4-lg-wfi]][🚎4-lg-wf] [![CI Unsupported][🚎7-us-wfi]][🚎7-us-wf] [![CI Ancient][🚎1-an-wfi]][🚎1-an-wf] [![CI Test Coverage][🚎2-cov-wfi]][🚎2-cov-wf] [![CI Style][🚎5-st-wfi]][🚎5-st-wf] [![CodeQL][🖐codeQL-img]][🖐codeQL] [![Apache SkyWalking Eyes License Compatibility Check][🚎15-🪪-wfi]][🚎15-🪪-wf] `if ci_badges.map(&:color).detect { it != "green"}` ☝️ [let me know][🖼️galtzo-discord], as I may have missed the [discord notification][🖼️galtzo-discord]. @@ -75,10 +77,9 @@ All of the listed options are required, with the exception of `:title`, `:name_p | Works with Truffle Ruby | ![Truffle Ruby 22.3 Compat][💎truby-22.3i] ![Truffle Ruby 23.0 Compat][💎truby-23.0i]
[![Truffle Ruby 23.1 Compat][💎truby-23.1i]][🚎9-t-wf] [![Truffle Ruby 24.1 Compat][💎truby-c-i]][🚎11-c-wf] | | Works with MRI Ruby 3 | [![Ruby 3.0 Compat][💎ruby-3.0i]][🚎4-lg-wf] [![Ruby 3.1 Compat][💎ruby-3.1i]][🚎6-s-wf] [![Ruby 3.2 Compat][💎ruby-3.2i]][🚎6-s-wf] [![Ruby 3.3 Compat][💎ruby-3.3i]][🚎6-s-wf] [![Ruby 3.4 Compat][💎ruby-c-i]][🚎11-c-wf] [![Ruby HEAD Compat][💎ruby-headi]][🚎3-hd-wf] | | Works with MRI Ruby 2 | ![Ruby 2.0 Compat][💎ruby-2.0i] ![Ruby 2.1 Compat][💎ruby-2.1i] ![Ruby 2.2 Compat][💎ruby-2.2i]
[![Ruby 2.3 Compat][💎ruby-2.3i]][🚎1-an-wf] [![Ruby 2.4 Compat][💎ruby-2.4i]][🚎1-an-wf] [![Ruby 2.5 Compat][💎ruby-2.5i]][🚎1-an-wf] [![Ruby 2.6 Compat][💎ruby-2.6i]][🚎7-us-wf] [![Ruby 2.7 Compat][💎ruby-2.7i]][🚎7-us-wf] | -| Works with MRI Ruby 1 | ![Ruby 1.8 Compat][💎ruby-1.8i] ![Ruby 1.9 Compat][💎ruby-1.9i] | | Support & Community | [![Join Me on Daily.dev's RubyFriends][✉️ruby-friends-img]][✉️ruby-friends] [![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite] [![Get help from me on Upwork][👨🏼‍🏫expsup-upwork-img]][👨🏼‍🏫expsup-upwork] [![Get help from me on Codementor][👨🏼‍🏫expsup-codementor-img]][👨🏼‍🏫expsup-codementor] | -| Source | [![Source on Github.com][📜src-gh-img]][📜src-gh] [![The best SHA: dQw4w9WgXcQ!][🧮kloc-img]][🧮kloc] | -| Documentation | [![Current release on RubyDoc.info][📜docs-cr-rd-img]][🚎yard-current] [![YARD on Galtzo.com][📜docs-head-rd-img]][🚎yard-head] [![Maintainer Blog][🚂maint-blog-img]][🚂maint-blog] [![GitHub Wiki][📜gh-wiki-img]][📜gh-wiki] | +| Source | [![Source on Github.com][📜src-gh-img]][📜src-gh] [![The best SHA: dQw4w9WgXcQ!][🧮kloc-img]][🧮kloc] | +| Documentation | [![Current release on RubyDoc.info][📜docs-cr-rd-img]][🚎yard-current] [![YARD on Galtzo.com][📜docs-head-rd-img]][🚎yard-head] [![Maintainer Blog][🚂maint-blog-img]][🚂maint-blog] [![GitHub Wiki][📜gh-wiki-img]][📜gh-wiki] | | Compliance | [![License: MIT][📄license-img]][📄license-ref] [![Compatible with Apache Software Projects: Verified by SkyWalking Eyes][📄license-compat-img]][📄license-compat] [![📄ilo-declaration-img]][📄ilo-declaration] [![Security Policy][🔐security-img]][🔐security] [![Contributor Covenant 2.1][🪇conduct-img]][🪇conduct] [![SemVer 2.0.0][📌semver-img]][📌semver] | | Style | [![Enforced Code Style Linter][💎rlts-img]][💎rlts] [![Keep-A-Changelog 1.0.0][📗keep-changelog-img]][📗keep-changelog] [![Gitmoji Commits][📌gitmoji-img]][📌gitmoji] [![Compatibility appraised by: appraisal2][💎appraisal2-img]][💎appraisal2] | | Maintainer 🎖️ | [![Follow Me on LinkedIn][💖🖇linkedin-img]][💖🖇linkedin] [![Follow Me on Ruby.Social][💖🐘ruby-mast-img]][💖🐘ruby-mast] [![Follow Me on Bluesky][💖🦋bluesky-img]][💖🦋bluesky] [![Contact Maintainer][🚂maint-contact-img]][🚂maint-contact] [![My technical writing][💖💁🏼‍♂️devto-img]][💖💁🏼‍♂️devto] | @@ -92,7 +93,7 @@ Compatible with MRI Ruby 2.0+, and concordant releases of JRuby, and TruffleRuby |------------------------------------------------|--------------------------------------------------------| | 👟 Check it out! | ✨ [github.com/appraisal-rb/appraisal2][💎appraisal2] ✨ | -### Ruby 3.4 +#### Ruby 3.4 nkf/kconv has been part of Ruby since long ago. Eventually it became a standard gem, but was changed to a bundled gem in Ruby 3.4. @@ -547,7 +548,6 @@ Thanks for RTFM. ☺️ [🏙️entsup-tidelift-sonar]: https://blog.tidelift.com/tidelift-joins-sonar [💁🏼‍♂️peterboling]: http://www.peterboling.com [🚂railsbling]: http://www.railsbling.com -[📜src-cb]: https://codeberg.org/omniauth/omniauth-ldap [📜src-gh-img]: https://img.shields.io/badge/GitHub-238636?style=for-the-badge&logo=Github&logoColor=green [📜src-gh]: https://github.com/omniauth/omniauth-ldap [📜docs-cr-rd-img]: https://img.shields.io/badge/RubyDoc-Current_Release-943CD2?style=for-the-badge&logo=readthedocs&logoColor=white @@ -600,8 +600,6 @@ Thanks for RTFM. ☺️ [🚎14-🔓️-wfi]: https://github.com/omniauth/omniauth-ldap/actions/workflows/unlocked_deps.yml/badge.svg [🚎15-🪪-wf]: https://github.com/omniauth/omniauth-ldap/actions/workflows/license-eye.yml [🚎15-🪪-wfi]: https://github.com/omniauth/omniauth-ldap/actions/workflows/license-eye.yml/badge.svg -[💎ruby-1.8i]: https://img.shields.io/badge/Ruby-1.8_(%F0%9F%9A%ABCI)-AABBCC?style=for-the-badge&logo=ruby&logoColor=white -[💎ruby-1.9i]: https://img.shields.io/badge/Ruby-1.9_(%F0%9F%9A%ABCI)-AABBCC?style=for-the-badge&logo=ruby&logoColor=white [💎ruby-2.0i]: https://img.shields.io/badge/Ruby-2.0_(%F0%9F%9A%ABCI)-AABBCC?style=for-the-badge&logo=ruby&logoColor=white [💎ruby-2.1i]: https://img.shields.io/badge/Ruby-2.1_(%F0%9F%9A%ABCI)-AABBCC?style=for-the-badge&logo=ruby&logoColor=white [💎ruby-2.2i]: https://img.shields.io/badge/Ruby-2.2_(%F0%9F%9A%ABCI)-AABBCC?style=for-the-badge&logo=ruby&logoColor=white @@ -645,7 +643,7 @@ Thanks for RTFM. ☺️ [📗keep-changelog]: https://keepachangelog.com/en/1.0.0/ [📗keep-changelog-img]: https://img.shields.io/badge/keep--a--changelog-1.0.0-34495e.svg?style=flat [📌gitmoji]:https://gitmoji.dev -[📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square +[📌gitmoji-img]:https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ [🧮kloc-img]: https://img.shields.io/badge/KLOC-4.076-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue [🔐security]: SECURITY.md diff --git a/omniauth-ldap.gemspec b/omniauth-ldap.gemspec index 6ffba59..583fb1e 100644 --- a/omniauth-ldap.gemspec +++ b/omniauth-ldap.gemspec @@ -115,7 +115,7 @@ Gem::Specification.new do |spec| # visibility and discoverability. # However, development dependencies in gemspec will install on # all versions of Ruby that will run in CI. - # This gem, and its gemspec runtime dependencies, will install on Ruby down to 0. + # This gem, and its gemspec runtime dependencies, will install on Ruby down to 2.0. # This gem, and its gemspec development dependencies, will install on Ruby down to 2.3. # Thus, dev dependencies in gemspec must have # diff --git a/sig/omniauth-ldap.rbs b/sig/omniauth-ldap.rbs new file mode 100644 index 0000000..399b294 --- /dev/null +++ b/sig/omniauth-ldap.rbs @@ -0,0 +1,5 @@ +# Top-level signature file for the gem. Detailed signatures live in the files below: +# - sig/omniauth/ldap/version.rbs +# - sig/omniauth/ldap/adaptor.rbs +# - sig/omniauth/strategies/ldap.rbs +# This file is intentionally minimal to avoid duplicating declarations. diff --git a/sig/omniauth/ldap/adaptor.rbs b/sig/omniauth/ldap/adaptor.rbs new file mode 100644 index 0000000..accee0e --- /dev/null +++ b/sig/omniauth/ldap/adaptor.rbs @@ -0,0 +1,54 @@ +module OmniAuth + module LDAP + class Adaptor + class LdapError < ::StandardError + end + + class ConfigurationError < ::StandardError + end + + class AuthenticationError < ::StandardError + end + + class ConnectionError < ::StandardError + end + + VALID_ADAPTER_CONFIGURATION_KEYS: Array[Symbol] + MUST_HAVE_KEYS: Array[untyped] + METHOD: Hash[Symbol, Symbol?] + + attr_accessor bind_dn: String? + attr_accessor password: String? + + # Net::LDAP is provided by the net-ldap gem; we reference it here for clarity. + attr_reader connection: Net::LDAP + attr_reader uid: String? + attr_reader base: String? + # auth is the hash passed to Net::LDAP#auth or similar + attr_reader auth: Hash[Symbol, untyped] + # filter is an LDAP filter string when configured + attr_reader filter: String? + + # Validate that required keys exist in the configuration + def self.validate: (?Hash[Symbol, untyped]) -> void + def initialize: (?Hash[Symbol, untyped]) -> void + + # Perform a search and optionally bind; returns the matched entry or false + def bind_as: (?Hash[Symbol, untyped]) -> (Net::LDAP::Entry? | false) + + private + + # Returns a Net::LDAP encryption symbol (e.g. :simple_tls, :start_tls) or nil + def ensure_method: (untyped) -> Symbol? + + # Returns an array of SASL auth hashes + def sasl_auths: (?Hash[Symbol, untyped]) -> Array[Hash[Symbol, untyped]] + + # Returns initial credential (string) and a proc that accepts a challenge and returns the response + # Use Array[untyped] here to avoid tuple syntax issues in some linters; the runtime value + # is commonly a two-element array [initial_credential, proc]. + def sasl_bind_setup_digest_md5: (?Hash[Symbol, untyped]) -> Array[untyped] + def sasl_bind_setup_gss_spnego: (?Hash[Symbol, untyped]) -> Array[untyped] + end + end +end diff --git a/sig/omniauth/ldap/version.rbs b/sig/omniauth/ldap/version.rbs new file mode 100644 index 0000000..69199f2 --- /dev/null +++ b/sig/omniauth/ldap/version.rbs @@ -0,0 +1,11 @@ +module OmniAuth + module LDAP + module Version + VERSION: String + end + + # Traditional constant alias + VERSION: String + end +end + diff --git a/sig/omniauth/strategies/ldap.rbs b/sig/omniauth/strategies/ldap.rbs new file mode 100644 index 0000000..04a629c --- /dev/null +++ b/sig/omniauth/strategies/ldap.rbs @@ -0,0 +1,24 @@ +module OmniAuth + module Strategies + class LDAP + OMNIAUTH_GTE_V2: bool + + # CONFIG is a read-only mapping of string keys to mapping definitions + CONFIG: Hash[String, untyped] + + # The request_phase either returns a Rack-compatible response or the form response. + def request_phase: () -> (Rack::Response | Array[untyped] | String) + + # The callback_phase may call super (untyped) or return a failure symbol + def callback_phase: () -> untyped + + # Accepts an adaptor and returns a Net::LDAP::Filter or similar + def filter: (OmniAuth::LDAP::Adaptor) -> Net::LDAP::Filter + + # Map a user object (Net::LDAP::Entry-like) into a Hash for the auth info + def self.map_user: (Hash[String, untyped], untyped) -> Hash[String, untyped] + + def missing_credentials?: () -> bool + end + end +end diff --git a/sig/rbs/net-ldap.rbs b/sig/rbs/net-ldap.rbs new file mode 100644 index 0000000..edc8f02 --- /dev/null +++ b/sig/rbs/net-ldap.rbs @@ -0,0 +1,19 @@ +# Minimal stubs for net-ldap types used by the gem +module Net + class LDAP + def initialize: (Hash[Symbol, untyped]) -> void + def open: () { (self) -> untyped } -> untyped + def search: (?Hash[Symbol, untyped]) -> Array[Net::LDAP::Entry] + def bind: (?Hash[Symbol, untyped]) -> bool + end + + class LDAP::Entry + def dn: () -> String + end + + class LDAP::Filter + def self.construct: (String) -> Net::LDAP::Filter + def self.eq: (String, String) -> Net::LDAP::Filter + end +end + diff --git a/sig/rbs/net-ntlm.rbs b/sig/rbs/net-ntlm.rbs new file mode 100644 index 0000000..a6e898f --- /dev/null +++ b/sig/rbs/net-ntlm.rbs @@ -0,0 +1,16 @@ +# Minimal stubs for net-ntlm types used by the gem +module Net + module NTLM + class Message + def self.parse: (untyped) -> Net::NTLM::Message + def response: (?Hash[Symbol, untyped], ?Hash[Symbol, untyped]) -> Net::NTLM::Message + end + + class Message::Type1 + def serialize: () -> String + end + + def self.encode_utf16le: (String) -> String + end +end + diff --git a/sig/rbs/sasl.rbs b/sig/rbs/sasl.rbs new file mode 100644 index 0000000..7894116 --- /dev/null +++ b/sig/rbs/sasl.rbs @@ -0,0 +1,12 @@ +# Minimal stubs for SASL bindings used in tests +module SASL + class Preferences + def initialize: (?Hash[Symbol, untyped]) -> void + end + + class SASL + def initialize: (String, SASL::Preferences) -> void + def receive: (String, untyped) -> [untyped, untyped] + end +end +