From 83a5527037aad202600ff539f5404bb235c09515 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Sun, 8 Jun 2025 06:24:29 +0700 Subject: [PATCH 1/5] =?UTF-8?q?=F0=9F=8E=A8=20Modernize=20Codebase?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apt-install/devcontainer-feature.json | 9 + .devcontainer/apt-install/install.sh | 5 + .devcontainer/devcontainer.json | 28 + .envrc | 37 + .github/dependabot.yml | 13 + .github/workflows/ancient.yml | 144 +++ .github/workflows/codeql-analysis.yml | 70 ++ .github/workflows/coverage.yml | 140 +++ .github/workflows/current-runtime-heads.yml | 88 ++ .github/workflows/current.yml | 83 ++ .github/workflows/dependency-review.yml | 20 + .github/workflows/heads.yml | 98 ++ .github/workflows/jruby-ancient.yml | 100 ++ .github/workflows/jruby.yml | 80 ++ .github/workflows/legacy.yml | 67 ++ .github/workflows/style.yml | 64 ++ .github/workflows/supported.yml | 82 ++ .github/workflows/unsupported.yml | 171 ++++ .gitignore | 58 +- .idea/.gitignore | 10 + .idea/GitLink.xml | 6 + .idea/dbnavigator.xml | 427 ++++++++ .idea/dictionaries/project.xml | 8 + .idea/git_toolbox_prj.xml | 15 + .idea/misc.xml | 4 + .idea/modules.xml | 8 + .idea/omniauth-openid.iml | 112 +++ .idea/vcs.xml | 7 + .qlty/qlty.toml | 78 ++ .rspec | 5 +- .rubocop.yml | 2 + .rubocop_gradual.lock | 22 + .simplecov | 5 + .tool-versions | 1 + .travis.yml | 23 - .yard_gfm_support.rb | 22 + .yardopts | 11 +- Appraisal.root.gemfile | 12 + Appraisals | 171 ++++ CHANGELOG.md | 54 + CODE_OF_CONDUCT.md | 7 +- CONTRIBUTING.md | 132 +++ Gemfile | 56 +- Gemfile.lock | 317 ++++-- Guardfile | 7 +- LICENSE | 19 - LICENSE.txt | 23 + README.md | 367 ++++++- REEK | 36 + Rakefile | 132 ++- SECURITY.md | 30 + bin/bundle | 109 ++ bin/gem_checksums | 27 + bin/htmldiff | 27 + bin/ldiff | 27 + bin/rackup | 27 + bin/rake | 27 + bin/rspec | 27 + certs/pboling.pem | 27 + .gemtest => docs/.nojekyll | 0 docs/OmniAuth.html | 117 +++ docs/OmniAuth/OpenID.html | 132 +++ docs/OmniAuth/OpenID/Version.html | 126 +++ docs/OmniAuth/Strategies.html | 115 +++ docs/OmniAuth/Strategies/OpenID.html | 772 ++++++++++++++ docs/_index.html | 169 ++++ docs/class_list.html | 54 + docs/css/common.css | 1 + docs/css/full_list.css | 58 ++ docs/css/style.css | 503 ++++++++++ docs/file.CHANGELOG.html | 138 +++ docs/file.CITATION.html | 92 ++ docs/file.CODE_OF_CONDUCT.html | 202 ++++ docs/file.CONTRIBUTING.html | 202 ++++ docs/file.LICENSE.html | 70 ++ docs/file.README.html | 377 +++++++ docs/file.SECURITY.html | 111 ++ docs/file_list.html | 89 ++ docs/frames.html | 22 + docs/images/logo/README.txt | 38 + .../logo/galtzo-floss-logos-original.svg | 1 + .../logo/galtzo-floss-logos-wordless.svg | 1 + docs/images/logo/omniauth-logo-182px.png | Bin 0 -> 22567 bytes docs/images/logo/openid_rgb-300dpi.png | Bin 0 -> 17026 bytes docs/images/logo/ruby-logo-124px.jpeg | Bin 0 -> 3935 bytes docs/images/logo/ruby-logo-198px.svg | 948 ++++++++++++++++++ docs/index.html | 377 +++++++ docs/js/app.js | 344 +++++++ docs/js/full_list.js | 242 +++++ docs/js/jquery.js | 4 + docs/method_list.html | 126 +++ docs/top-level-namespace.html | 110 ++ examples/sinatra.rb | 22 +- gemfiles/audit.gemfile | 11 + gemfiles/coverage.gemfile | 13 + gemfiles/dep_heads.gemfile | 7 + gemfiles/modular/audit.gemfile | 5 + gemfiles/modular/coverage.gemfile | 6 + gemfiles/modular/documentation.gemfile | 11 + gemfiles/modular/logger/r2.4/v1.5.3.gemfile | 3 + gemfiles/modular/logger/r2/v1.5.gemfile | 3 + gemfiles/modular/logger/r3/v1.7.gemfile | 2 + gemfiles/modular/logger/vHEAD.gemfile | 2 + gemfiles/modular/mutex_m/r2.4/v0.1.gemfile | 3 + gemfiles/modular/mutex_m/r2/v0.3.gemfile | 2 + gemfiles/modular/mutex_m/r3/v0.3.gemfile | 2 + gemfiles/modular/mutex_m/vHEAD.gemfile | 2 + gemfiles/modular/omniauth/r2/v1.0.gemfile | 5 + gemfiles/modular/omniauth/r2/v1.1.gemfile | 5 + gemfiles/modular/omniauth/r2/v1.2.gemfile | 5 + gemfiles/modular/omniauth/r2/v1.3.gemfile | 5 + gemfiles/modular/omniauth/r2/v1.4.gemfile | 5 + gemfiles/modular/omniauth/r2/v1.5.gemfile | 5 + gemfiles/modular/omniauth/r2/v1.6.gemfile | 5 + gemfiles/modular/omniauth/r2/v1.7.gemfile | 5 + gemfiles/modular/omniauth/r2/v1.8.gemfile | 5 + gemfiles/modular/omniauth/r2/v1.9.gemfile | 5 + gemfiles/modular/omniauth/r2/v2.0.gemfile | 5 + gemfiles/modular/omniauth/r2/v2.1.gemfile | 5 + gemfiles/modular/omniauth/r3/v2.1.gemfile | 5 + gemfiles/modular/omniauth/vHEAD.gemfile | 4 + gemfiles/modular/rack-openid/vHEAD.gemfile | 4 + gemfiles/modular/runtime_heads.gemfile | 12 + gemfiles/modular/stringio/r2.4/v0.0.2.gemfile | 4 + gemfiles/modular/stringio/r2/v3.0.gemfile | 5 + gemfiles/modular/stringio/r3/v3.0.gemfile | 5 + gemfiles/modular/stringio/vHEAD.gemfile | 2 + gemfiles/modular/style.gemfile | 13 + gemfiles/modular/x_std_libs/r2.4/libs.gemfile | 3 + gemfiles/modular/x_std_libs/r2/libs.gemfile | 3 + gemfiles/modular/x_std_libs/r3/libs.gemfile | 3 + gemfiles/modular/x_std_libs/vHEAD.gemfile | 3 + gemfiles/omniauth_v1.1_r2.4.gemfile | 9 + gemfiles/omniauth_v1.2_r2.gemfile | 9 + gemfiles/omniauth_v1.3_r2.gemfile | 9 + gemfiles/omniauth_v1.4_r2.gemfile | 9 + gemfiles/omniauth_v1.5_r2.gemfile | 9 + gemfiles/omniauth_v1.6_r2.gemfile | 9 + gemfiles/omniauth_v1.7_r2.gemfile | 9 + gemfiles/omniauth_v1.8_r2.gemfile | 9 + gemfiles/omniauth_v1.9_r2.gemfile | 9 + gemfiles/omniauth_v2.0_r2.gemfile | 9 + gemfiles/omniauth_v2.1_r3.0.gemfile | 9 + gemfiles/omniauth_v2.1_r3.gemfile | 9 + gemfiles/style.gemfile | 11 + lib/omniauth-openid.rb | 15 +- lib/omniauth-openid/version.rb | 19 +- lib/omniauth/openid/version.rb | 8 + lib/omniauth/strategies/open_id.rb | 111 +- omniauth-openid.gemspec | 116 ++- spec/config/omniauth.rb | 7 + spec/config/rspec/rack_test.rb | 5 + spec/config/rspec/rspec_block_is_expected.rb | 2 + spec/config/rspec/rspec_core.rb | 11 + spec/config/rspec/version_gem.rb | 1 + spec/omniauth/openid/version_spec.rb | 19 + spec/omniauth/strategies/open_id_spec.rb | 38 +- spec/spec_helper.rb | 50 +- 158 files changed, 9779 insertions(+), 287 deletions(-) create mode 100644 .devcontainer/apt-install/devcontainer-feature.json create mode 100644 .devcontainer/apt-install/install.sh create mode 100644 .devcontainer/devcontainer.json create mode 100644 .envrc create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/ancient.yml create mode 100644 .github/workflows/codeql-analysis.yml create mode 100644 .github/workflows/coverage.yml create mode 100644 .github/workflows/current-runtime-heads.yml create mode 100644 .github/workflows/current.yml create mode 100644 .github/workflows/dependency-review.yml create mode 100644 .github/workflows/heads.yml create mode 100644 .github/workflows/jruby-ancient.yml create mode 100644 .github/workflows/jruby.yml create mode 100644 .github/workflows/legacy.yml create mode 100644 .github/workflows/style.yml create mode 100644 .github/workflows/supported.yml create mode 100644 .github/workflows/unsupported.yml create mode 100644 .idea/.gitignore create mode 100644 .idea/GitLink.xml create mode 100644 .idea/dbnavigator.xml create mode 100644 .idea/dictionaries/project.xml create mode 100644 .idea/git_toolbox_prj.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/omniauth-openid.iml create mode 100644 .idea/vcs.xml create mode 100644 .qlty/qlty.toml create mode 100644 .rubocop.yml create mode 100644 .rubocop_gradual.lock create mode 100644 .simplecov create mode 100644 .tool-versions delete mode 100644 .travis.yml create mode 100644 .yard_gfm_support.rb create mode 100644 Appraisal.root.gemfile create mode 100644 Appraisals create mode 100644 CHANGELOG.md create mode 100755 CONTRIBUTING.md delete mode 100644 LICENSE create mode 100644 LICENSE.txt create mode 100644 REEK create mode 100644 SECURITY.md create mode 100755 bin/bundle create mode 100755 bin/gem_checksums create mode 100755 bin/htmldiff create mode 100755 bin/ldiff create mode 100755 bin/rackup create mode 100755 bin/rake create mode 100755 bin/rspec create mode 100644 certs/pboling.pem rename .gemtest => docs/.nojekyll (100%) create mode 100644 docs/OmniAuth.html create mode 100644 docs/OmniAuth/OpenID.html create mode 100644 docs/OmniAuth/OpenID/Version.html create mode 100644 docs/OmniAuth/Strategies.html create mode 100644 docs/OmniAuth/Strategies/OpenID.html create mode 100644 docs/_index.html create mode 100644 docs/class_list.html create mode 100644 docs/css/common.css create mode 100644 docs/css/full_list.css create mode 100644 docs/css/style.css create mode 100644 docs/file.CHANGELOG.html create mode 100644 docs/file.CITATION.html create mode 100644 docs/file.CODE_OF_CONDUCT.html create mode 100644 docs/file.CONTRIBUTING.html create mode 100644 docs/file.LICENSE.html create mode 100644 docs/file.README.html create mode 100644 docs/file.SECURITY.html create mode 100644 docs/file_list.html create mode 100644 docs/frames.html create mode 100644 docs/images/logo/README.txt create mode 100644 docs/images/logo/galtzo-floss-logos-original.svg create mode 100644 docs/images/logo/galtzo-floss-logos-wordless.svg create mode 100644 docs/images/logo/omniauth-logo-182px.png create mode 100644 docs/images/logo/openid_rgb-300dpi.png create mode 100644 docs/images/logo/ruby-logo-124px.jpeg create mode 100644 docs/images/logo/ruby-logo-198px.svg create mode 100644 docs/index.html create mode 100644 docs/js/app.js create mode 100644 docs/js/full_list.js create mode 100644 docs/js/jquery.js create mode 100644 docs/method_list.html create mode 100644 docs/top-level-namespace.html create mode 100644 gemfiles/audit.gemfile create mode 100644 gemfiles/coverage.gemfile create mode 100644 gemfiles/dep_heads.gemfile create mode 100755 gemfiles/modular/audit.gemfile create mode 100755 gemfiles/modular/coverage.gemfile create mode 100755 gemfiles/modular/documentation.gemfile create mode 100644 gemfiles/modular/logger/r2.4/v1.5.3.gemfile create mode 100644 gemfiles/modular/logger/r2/v1.5.gemfile create mode 100644 gemfiles/modular/logger/r3/v1.7.gemfile create mode 100644 gemfiles/modular/logger/vHEAD.gemfile create mode 100644 gemfiles/modular/mutex_m/r2.4/v0.1.gemfile create mode 100644 gemfiles/modular/mutex_m/r2/v0.3.gemfile create mode 100644 gemfiles/modular/mutex_m/r3/v0.3.gemfile create mode 100644 gemfiles/modular/mutex_m/vHEAD.gemfile create mode 100644 gemfiles/modular/omniauth/r2/v1.0.gemfile create mode 100644 gemfiles/modular/omniauth/r2/v1.1.gemfile create mode 100644 gemfiles/modular/omniauth/r2/v1.2.gemfile create mode 100644 gemfiles/modular/omniauth/r2/v1.3.gemfile create mode 100644 gemfiles/modular/omniauth/r2/v1.4.gemfile create mode 100644 gemfiles/modular/omniauth/r2/v1.5.gemfile create mode 100644 gemfiles/modular/omniauth/r2/v1.6.gemfile create mode 100644 gemfiles/modular/omniauth/r2/v1.7.gemfile create mode 100644 gemfiles/modular/omniauth/r2/v1.8.gemfile create mode 100644 gemfiles/modular/omniauth/r2/v1.9.gemfile create mode 100644 gemfiles/modular/omniauth/r2/v2.0.gemfile create mode 100644 gemfiles/modular/omniauth/r2/v2.1.gemfile create mode 100644 gemfiles/modular/omniauth/r3/v2.1.gemfile create mode 100644 gemfiles/modular/omniauth/vHEAD.gemfile create mode 100644 gemfiles/modular/rack-openid/vHEAD.gemfile create mode 100644 gemfiles/modular/runtime_heads.gemfile create mode 100644 gemfiles/modular/stringio/r2.4/v0.0.2.gemfile create mode 100644 gemfiles/modular/stringio/r2/v3.0.gemfile create mode 100644 gemfiles/modular/stringio/r3/v3.0.gemfile create mode 100644 gemfiles/modular/stringio/vHEAD.gemfile create mode 100755 gemfiles/modular/style.gemfile create mode 100644 gemfiles/modular/x_std_libs/r2.4/libs.gemfile create mode 100644 gemfiles/modular/x_std_libs/r2/libs.gemfile create mode 100644 gemfiles/modular/x_std_libs/r3/libs.gemfile create mode 100644 gemfiles/modular/x_std_libs/vHEAD.gemfile create mode 100644 gemfiles/omniauth_v1.1_r2.4.gemfile create mode 100644 gemfiles/omniauth_v1.2_r2.gemfile create mode 100644 gemfiles/omniauth_v1.3_r2.gemfile create mode 100644 gemfiles/omniauth_v1.4_r2.gemfile create mode 100644 gemfiles/omniauth_v1.5_r2.gemfile create mode 100644 gemfiles/omniauth_v1.6_r2.gemfile create mode 100644 gemfiles/omniauth_v1.7_r2.gemfile create mode 100644 gemfiles/omniauth_v1.8_r2.gemfile create mode 100644 gemfiles/omniauth_v1.9_r2.gemfile create mode 100644 gemfiles/omniauth_v2.0_r2.gemfile create mode 100644 gemfiles/omniauth_v2.1_r3.0.gemfile create mode 100644 gemfiles/omniauth_v2.1_r3.gemfile create mode 100644 gemfiles/style.gemfile create mode 100644 lib/omniauth/openid/version.rb create mode 100644 spec/config/omniauth.rb create mode 100644 spec/config/rspec/rack_test.rb create mode 100644 spec/config/rspec/rspec_block_is_expected.rb create mode 100644 spec/config/rspec/rspec_core.rb create mode 100644 spec/config/rspec/version_gem.rb create mode 100644 spec/omniauth/openid/version_spec.rb diff --git a/.devcontainer/apt-install/devcontainer-feature.json b/.devcontainer/apt-install/devcontainer-feature.json new file mode 100644 index 0000000..bf4d0e4 --- /dev/null +++ b/.devcontainer/apt-install/devcontainer-feature.json @@ -0,0 +1,9 @@ +{ + "name": "Apt Install Packages", + "id": "apt-install", + "version": "1.0.0", + "description": "More packages are needed", + "install": { + "script": "install.sh" + } +} \ No newline at end of file diff --git a/.devcontainer/apt-install/install.sh b/.devcontainer/apt-install/install.sh new file mode 100644 index 0000000..061ca0f --- /dev/null +++ b/.devcontainer/apt-install/install.sh @@ -0,0 +1,5 @@ +#!/bin/sh +apt-get update -y +apt-get install -y direnv default-jdk postgresql libpq-dev git zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev software-properties-common libffi-dev +# Adds the direnv setup script to ~/.bashrc file (at the end) +echo 'eval "$(direnv hook bash)"' >> ~/.bashrc \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..d3daa43 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,28 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/ruby +{ + "name": "Ruby", + // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile + "image": "mcr.microsoft.com/devcontainers/ruby:1-3-bookworm", + + // Features to add to the dev container. More info: https://containers.dev/features. + "features": { + "./apt-install": {} + }, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + + // Use 'postCreateCommand' to run commands after the container is created. + "postCreateCommand": "bundle update --bundler", + + // Configure tool-specific properties. + "customizations" : { + "jetbrains" : { + "backend" : "RubyMine" + } + }, + + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" +} diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..87cfd95 --- /dev/null +++ b/.envrc @@ -0,0 +1,37 @@ +# Run any command in this library's bin/ without the bin/ prefix! +PATH_add bin + +# Only add things to this file that should be shared with the team. + +# **dotenv** (See end of file for .env.local integration) +# .env would override anything in this file, if enabled. +# .env is a DOCKER standard, and if we use it, it would be in deployed, or DOCKER, environments. +# Override and customize anything below in your own .env.local +# If you are using dotenv and not direnv, +# copy the following `export` statements to your own .env file. + +### General Ruby ### +# Turn off Ruby Warnings about deprecated code +# export RUBYOPT="-W0" + +### External Testing Controls +export K_SOUP_COV_DO=true # Means you want code coverage +# Available formats are html, xml, rcov, lcov, json, tty +export K_SOUP_COV_COMMAND_NAME="RSpec Coverage" +export K_SOUP_COV_FORMATTERS="html,tty" +export K_SOUP_COV_MIN_BRANCH=11 # Means you want to enforce X% branch coverage +export K_SOUP_COV_MIN_LINE=61 # Means you want to enforce X% line coverage +export K_SOUP_COV_MIN_HARD=true # Means you want the build to fail if the coverage thresholds are not met +export K_SOUP_COV_MULTI_FORMATTERS=true +export MAX_ROWS=1 # Setting for simplecov-console gem for tty output, limits to the worst N rows of bad coverage + +# Internal Debugging Controls +export DEBUG=false # do not allow byebug statements (override in .env.local) + +# .env would override anything in this file, if `dotenv` is uncommented below. +# .env is a DOCKER standard, and if we use it, it would be in deployed, or DOCKER, environments, +# and that is why we generally want to leave it commented out. +# dotenv + +# .env.local will override anything in this file. +dotenv_if_exists .env.local diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..46f1c90 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,13 @@ +version: 2 +updates: + - package-ecosystem: bundler + directory: "/" + schedule: + interval: "daily" + open-pull-requests-limit: 10 + ignore: + - dependency-name: "rubocop-lts" + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" diff --git a/.github/workflows/ancient.yml b/.github/workflows/ancient.yml new file mode 100644 index 0000000..5ab5b99 --- /dev/null +++ b/.github/workflows/ancient.yml @@ -0,0 +1,144 @@ +name: MRI 2.4, 2.5 (Ancient) + +permissions: + contents: read + +env: + K_SOUP_COV_DO: false + +on: + push: + branches: + - 'main' + tags: + - '!*' # Do not execute on tags + pull_request: + branches: + - '*' + # Allow manually triggering the workflow. + workflow_dispatch: + +# Cancels all previous workflow runs for the same branch that have not yet completed. +concurrency: + # The concurrency group contains the workflow name and the branch name. + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + test: + name: Specs ${{ matrix.ruby }} ${{ matrix.appraisal_name }}${{ matrix.name_extra || '' }} + if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" + runs-on: ubuntu-22.04 + continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} + env: # $BUNDLE_GEMFILE must be set at job level, so it is set for all steps + BUNDLE_GEMFILE: ${{ github.workspace }}/${{ matrix.gemfile }}.gemfile + strategy: + fail-fast: false + matrix: + include: + # Ruby 2.4 + - ruby: "2.4" + appraisal_name: "omniauth-v1.1-r2.4" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: "3.3.27" + bundler: "2.3.27" + + # Ruby 2.5 + - ruby: "2.5" + appraisal_name: "omniauth-v1.2-r2" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: "3.3.27" + bundler: "2.3.27" + - ruby: "2.5" + appraisal_name: "omniauth-v1.3-r2" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: "3.3.27" + bundler: "2.3.27" + - ruby: "2.5" + appraisal_name: "omniauth-v1.4-r2" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: "3.3.27" + bundler: "2.3.27" + - ruby: "2.5" + appraisal_name: "omniauth-v1.5-r2" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: "3.3.27" + bundler: "2.3.27" + - ruby: "2.5" + appraisal_name: "omniauth-v1.6-r2" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: "3.3.27" + bundler: "2.3.27" + - ruby: "2.5" + appraisal_name: "omniauth-v1.7-r2" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: "3.3.27" + bundler: "2.3.27" + - ruby: "2.5" + appraisal_name: "omniauth-v1.8-r2" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: "3.3.27" + bundler: "2.3.27" + - ruby: "2.5" + appraisal_name: "omniauth-v1.9-r2" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: "3.3.27" + bundler: "2.3.27" + - ruby: "2.5" + appraisal_name: "omniauth-v2.0-r2" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: "3.3.27" + bundler: "2.3.27" + + steps: + ### COUCHDB + - name: Start CouchDB + uses: iamssen/couchdb-github-action@master + if: "endsWith(matrix.exec_cmd, 'couch_potato')" + with: + couchdb-version: "3.4.1" + + ### MONGODB + - name: Start MongoDB + uses: supercharge/mongodb-github-action@1.12.0 + if: "endsWith(matrix.exec_cmd, 'mongoid')" + with: + mongodb-version: "8.0" + + ### SMOKE-TEST + - name: Smoke CouchDB + if: "endsWith(matrix.exec_cmd, 'couch_potato')" + run: | + curl -f http://127.0.0.1:5984/ + curl -X POST -H "Content-Type: application/json; charset=utf-8" -d '{"name": "admin", "password": "password"}' http://127.0.0.1:5984/_session + + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Ruby & RubyGems + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + rubygems: ${{ matrix.rubygems }} + bundler: ${{ matrix.bundler }} + bundler-cache: false + + # Raw `bundle` will use the BUNDLE_GEMFILE set to matrix.gemfile (i.e. Appraisal.root) + # We need to do this first to get appraisal installed. + # NOTE: This does not use the main Gemfile at all. + - name: Install Root Appraisal + run: bundle + - name: Appraisal for ${{ matrix.ruby }}@${{ matrix.appraisal_name }} + run: bundle exec appraisal ${{ matrix.appraisal_name }} bundle + - name: Run ${{ matrix.exec_cmd }} on ${{ matrix.ruby }}@${{ matrix.appraisal_name }} + run: bundle exec appraisal ${{ matrix.appraisal_name }} bundle exec ${{ matrix.exec_cmd }} diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 0000000..502c2a0 --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,70 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: [ main, "*-stable" ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ main, "*-stable" ] + schedule: + - cron: '35 1 * * 5' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'ruby' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] + # Learn more about CodeQL language support at https://git.io/codeql-language-support + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v3 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml new file mode 100644 index 0000000..56595ef --- /dev/null +++ b/.github/workflows/coverage.yml @@ -0,0 +1,140 @@ +name: Test Coverage + +permissions: + contents: read + pull-requests: write + id-token: write + +env: + K_SOUP_COV_MIN_BRANCH: 11 + K_SOUP_COV_MIN_LINE: 61 + K_SOUP_COV_MIN_HARD: true + K_SOUP_COV_FORMATTERS: "html,xml,rcov,lcov,json,tty" + K_SOUP_COV_DO: true + K_SOUP_COV_MULTI_FORMATTERS: true + K_SOUP_COV_COMMAND_NAME: "RSpec Coverage" + +on: + push: + branches: + - 'main' + tags: + - '!*' # Do not execute on tags + pull_request: + branches: + - '*' + # Allow manually triggering the workflow. + workflow_dispatch: + +# Cancels all previous workflow runs for the same branch that have not yet completed. +concurrency: + # The concurrency group contains the workflow name and the branch name. + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + coverage: + name: Code Coverage on ${{ matrix.ruby }}@current + if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} + env: # $BUNDLE_GEMFILE must be set at job level, so it is set for all steps + BUNDLE_GEMFILE: ${{ github.workspace }}/${{ matrix.gemfile }}.gemfile + strategy: + fail-fast: false + matrix: + include: + # Coverage + - ruby: "ruby" + appraisal_name: "coverage" + exec_cmd: "rake spec:orm:all" + gemfile: "Appraisal.root" + rubygems: latest + bundler: latest + + steps: + ### COUCHDB + - name: Start CouchDB + uses: iamssen/couchdb-github-action@master + with: + couchdb-version: "3.4.1" + + ### MONGODB + - name: Start MongoDB + uses: supercharge/mongodb-github-action@1.12.0 + with: + mongodb-version: "8.0" + + ### SMOKE-TEST + - name: Smoke CouchDB + run: | + curl -f http://127.0.0.1:5984/ + curl -X POST -H "Content-Type: application/json; charset=utf-8" -d '{"name": "admin", "password": "password"}' http://127.0.0.1:5984/_session + + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Ruby & RubyGems + uses: ruby/setup-ruby@v1 + with: + ruby-version: "${{ matrix.ruby }}" + rubygems: "${{ matrix.rubygems }}" + bundler: "${{ matrix.bundler }}" + bundler-cache: false + + # Raw `bundle` will use the BUNDLE_GEMFILE set to matrix.gemfile (i.e. Appraisal.root) + # We need to do this first to get appraisal installed. + # NOTE: This does not use the primary Gemfile at all. + - name: Install Root Appraisal + run: bundle + - name: Appraisal for ${{ matrix.ruby }}@${{ matrix.appraisal_name }} + run: bundle exec appraisal ${{ matrix.appraisal_name }} bundle + - name: Run ${{ matrix.exec_cmd }} on ${{ matrix.ruby }}@${{ matrix.appraisal_name }} + run: bundle exec appraisal ${{ matrix.appraisal_name }} bundle exec ${{ matrix.exec_cmd }} + + # Do SaaS coverage uploads first + - name: Upload coverage to Coveralls + uses: coverallsapp/github-action@master + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + continue-on-error: ${{ matrix.experimental != 'false' }} + + - name: Upload coverage to QLTY + uses: qltysh/qlty-action/coverage@main + with: + token: ${{secrets.QLTY_COVERAGE_TOKEN}} + files: coverage/.resultset.json + continue-on-error: ${{ matrix.experimental != 'false' }} + + # Build will fail here if coverage upload fails + # which will hopefully be noticed for the lack of code coverage comments + - name: Upload coverage to CodeCov + uses: codecov/codecov-action@v5 + with: + use_oidc: true + fail_ci_if_error: true # optional (default = false) + verbose: true # optional (default = false) + + # Then PR comments + - name: Code Coverage Summary Report + uses: irongut/CodeCoverageSummary@v1.3.0 + if: ${{ github.event_name == 'pull_request' }} + with: + filename: ./coverage/coverage.xml + badge: true + fail_below_min: true + format: markdown + hide_branch_rate: false + hide_complexity: true + indicators: true + output: both + thresholds: '61 11' + continue-on-error: ${{ matrix.experimental != 'false' }} + + - name: Add Coverage PR Comment + uses: marocchino/sticky-pull-request-comment@v2 + if: ${{ github.event_name == 'pull_request' }} + with: + recreate: true + path: code-coverage-results.md + continue-on-error: ${{ matrix.experimental != 'false' }} diff --git a/.github/workflows/current-runtime-heads.yml b/.github/workflows/current-runtime-heads.yml new file mode 100644 index 0000000..dfb913c --- /dev/null +++ b/.github/workflows/current-runtime-heads.yml @@ -0,0 +1,88 @@ +# Targets the evergreen latest release of ruby, truffleruby, and jruby +# and tests against the HEAD of runtime dependencies +name: Runtime Deps @ HEAD + +permissions: + contents: read + +env: + K_SOUP_COV_DO: false + +on: + push: + branches: + - 'main' + - '*-stable' + tags: + - '!*' # Do not execute on tags + pull_request: + branches: + - '*' + # Allow manually triggering the workflow. + workflow_dispatch: + +# Cancels all previous workflow runs for the same branch that have not yet completed. +concurrency: + # The concurrency group contains the workflow name and the branch name. + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + test: + name: Specs ${{ matrix.ruby }}@${{ matrix.appraisal_name }} + if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} + env: # $BUNDLE_GEMFILE must be set at job level, so it is set for all steps + BUNDLE_GEMFILE: ${{ github.workspace }}/${{ matrix.gemfile }}.gemfile + strategy: + matrix: + include: + # Ruby 3.4 + - ruby: "ruby" + appraisal_name: "dep-heads" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: latest + bundler: latest + + # truffleruby-24.1 + # (according to documentation: targets Ruby 3.3 compatibility) + # (according to runtime: targets Ruby 3.2 compatibility) + - ruby: "truffleruby" + appraisal_name: "dep-heads" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: default + bundler: default + + # jruby-10.0 (targets Ruby 3.4 compatibility) + - ruby: "jruby" + appraisal_name: "dep-heads" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + experimental: true + rubygems: default + bundler: default + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Ruby & RubyGems + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + rubygems: ${{ matrix.rubygems }} + bundler: ${{ matrix.bundler }} + bundler-cache: false + + # Raw `bundle` will use the BUNDLE_GEMFILE set to matrix.gemfile (i.e. Appraisal.root) + # We need to do this first to get appraisal installed. + # NOTE: This does not use the primary Gemfile at all. + - name: Install Root Appraisal + run: bundle + - name: Appraisal for ${{ matrix.ruby }}@${{ matrix.appraisal_name }} + run: bundle exec appraisal ${{ matrix.appraisal_name }} bundle + - name: Run ${{ matrix.exec_cmd }} on ${{ matrix.ruby }}@${{ matrix.appraisal_name }} + run: bundle exec appraisal ${{ matrix.appraisal_name }} bundle exec ${{ matrix.exec_cmd }} diff --git a/.github/workflows/current.yml b/.github/workflows/current.yml new file mode 100644 index 0000000..afac894 --- /dev/null +++ b/.github/workflows/current.yml @@ -0,0 +1,83 @@ +# Targets the evergreen latest release of ruby, truffleruby, and jruby +name: Current + +permissions: + contents: read + +env: + K_SOUP_COV_DO: false + +on: + push: + branches: + - 'main' + tags: + - '!*' # Do not execute on tags + pull_request: + branches: + - '*' + # Allow manually triggering the workflow. + workflow_dispatch: + +# Cancels all previous workflow runs for the same branch that have not yet completed. +concurrency: + # The concurrency group contains the workflow name and the branch name. + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + test: + name: Specs ${{ matrix.ruby }}@${{ matrix.appraisal_name }} + if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} + env: # $BUNDLE_GEMFILE must be set at job level, so it is set for all steps + BUNDLE_GEMFILE: ${{ github.workspace }}/${{ matrix.gemfile }}.gemfile + strategy: + matrix: + include: + # Ruby 3.4 + - ruby: "3.4" + appraisal_name: "omniauth-v2.1-r3" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: latest + bundler: latest + + # truffleruby-24.1 + - ruby: "truffleruby" + appraisal_name: "omniauth-v2.1-r3" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: default + bundler: default + + # jruby-10.0 (targets Ruby 3.4 compatibility) + - ruby: "jruby" + appraisal_name: "omniauth-v2.1-r3" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: default + bundler: default + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Ruby & RubyGems + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + rubygems: ${{ matrix.rubygems }} + bundler: ${{ matrix.bundler }} + bundler-cache: false + + # Raw `bundle` will use the BUNDLE_GEMFILE set to matrix.gemfile (i.e. Appraisal.root) + # We need to do this first to get appraisal installed. + # NOTE: This does not use the main Gemfile at all. + - name: Install Root Appraisal + run: bundle + - name: Appraisal for ${{ matrix.ruby }}@${{ matrix.appraisal_name }} + run: bundle exec appraisal ${{ matrix.appraisal_name }} bundle + - name: Run ${{ matrix.exec_cmd }} on ${{ matrix.ruby }}@${{ matrix.appraisal_name }} + run: bundle exec appraisal ${{ matrix.appraisal_name }} bundle exec ${{ matrix.exec_cmd }} diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml new file mode 100644 index 0000000..0d4a013 --- /dev/null +++ b/.github/workflows/dependency-review.yml @@ -0,0 +1,20 @@ +# Dependency Review Action +# +# This Action will scan dependency manifest files that change as part of a Pull Request, surfacing known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable packages will be blocked from merging. +# +# Source repository: https://github.com/actions/dependency-review-action +# Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement +name: 'Dependency Review' +on: [pull_request] + +permissions: + contents: read + +jobs: + dependency-review: + runs-on: ubuntu-latest + steps: + - name: 'Checkout Repository' + uses: actions/checkout@v4 + - name: 'Dependency Review' + uses: actions/dependency-review-action@v4 diff --git a/.github/workflows/heads.yml b/.github/workflows/heads.yml new file mode 100644 index 0000000..ad171bd --- /dev/null +++ b/.github/workflows/heads.yml @@ -0,0 +1,98 @@ +name: Heads + +permissions: + contents: read + +env: + K_SOUP_COV_DO: false + +on: + push: + branches: + - 'main' + tags: + - '!*' # Do not execute on tags + pull_request: + branches: + - '*' + # Allow manually triggering the workflow. + workflow_dispatch: + +# Cancels all previous workflow runs for the same branch that have not yet completed. +concurrency: + # The concurrency group contains the workflow name and the branch name. + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + test: + name: Specs ${{ matrix.ruby }}@${{ matrix.appraisal_name }}${{ matrix.name_extra || '' }} + if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} + env: # $BUNDLE_GEMFILE must be set at job level, so it is set for all steps + BUNDLE_GEMFILE: ${{ github.workspace }}/${{ matrix.gemfile }}.gemfile + strategy: + fail-fast: true + matrix: + include: + # NOTE: Heads use default rubygems / bundler; their defaults are custom, unreleased, and from the future! + # ruby-head + - ruby: "ruby-head" + appraisal_name: "omniauth-v2.1-r3" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: default + bundler: default + +# # truffleruby-head + - ruby: "truffleruby-head" + appraisal_name: "omniauth-v2.1-r3" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: default + bundler: default + + # jruby-head + - ruby: "jruby-head" + appraisal_name: "omniauth-v2.1-r3" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: default + bundler: default + + steps: + ### COUCHDB + - name: Start CouchDB + uses: iamssen/couchdb-github-action@master + if: "endsWith(matrix.exec_cmd, 'couch_potato')" + with: + couchdb-version: "3.4.1" + + ### SMOKE-TEST + - name: Smoke CouchDB + if: "endsWith(matrix.exec_cmd, 'couch_potato')" + run: | + curl -f http://127.0.0.1:5984/ + curl -X POST -H "Content-Type: application/json; charset=utf-8" -d '{"name": "admin", "password": "password"}' http://127.0.0.1:5984/_session + + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Ruby & RubyGems + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + rubygems: ${{ matrix.rubygems }} + bundler: ${{ matrix.bundler }} + bundler-cache: false + + # Raw `bundle` will use the BUNDLE_GEMFILE set to matrix.gemfile (i.e. Appraisal.root) + # We need to do this first to get appraisal installed. + # NOTE: This does not use the main Gemfile at all. + - name: Install Root Appraisal + run: bundle + - name: Appraisal for ${{ matrix.ruby }}@${{ matrix.appraisal_name }} + run: bundle exec appraisal ${{ matrix.appraisal_name }} bundle + - name: Run ${{ matrix.exec_cmd }} on ${{ matrix.ruby }}@${{ matrix.appraisal_name }} + run: bundle exec appraisal ${{ matrix.appraisal_name }} bundle exec ${{ matrix.exec_cmd }} diff --git a/.github/workflows/jruby-ancient.yml b/.github/workflows/jruby-ancient.yml new file mode 100644 index 0000000..02f961a --- /dev/null +++ b/.github/workflows/jruby-ancient.yml @@ -0,0 +1,100 @@ +name: JRuby 9.2, 9.3 + +permissions: + contents: read + +env: + K_SOUP_COV_DO: false + +on: + push: + branches: + - 'main' + tags: + - '!*' # Do not execute on tags + pull_request: + branches: + - '*' + # Allow manually triggering the workflow. + workflow_dispatch: + +# Cancels all previous workflow runs for the same branch that have not yet completed. +concurrency: + # The concurrency group contains the workflow name and the branch name. + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + test: + name: Specs ${{ matrix.ruby }} ${{ matrix.appraisal_name }}${{ matrix.name_extra || '' }} + if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" + runs-on: ubuntu-22.04 + continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} + env: # $BUNDLE_GEMFILE must be set at job level, so it is set for all steps + BUNDLE_GEMFILE: ${{ github.workspace }}/${{ matrix.gemfile }}.gemfile + strategy: + matrix: + include: + # jruby-9.2 (targets Ruby 2.5 compatibility) + - ruby: "jruby-9.2" + appraisal_name: "omniauth-v1.9-r2" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: default + bundler: default + - ruby: "jruby-9.2" + appraisal_name: "omniauth-v2.0-r2" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: default + bundler: default + + # jruby-9.3 (targets Ruby 2.6 compatibility) + - ruby: "jruby-9.3" + appraisal_name: "omniauth-v1.9-r2" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: default + bundler: default + - ruby: "jruby-9.3" + appraisal_name: "omniauth-v2.0-r2" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: default + bundler: default + + steps: + ### COUCHDB + - name: Start CouchDB + uses: iamssen/couchdb-github-action@master + if: "endsWith(matrix.exec_cmd, 'couch_potato')" + with: + couchdb-version: "3.4.1" + + ### SMOKE-TEST + - name: Smoke CouchDB + if: "endsWith(matrix.exec_cmd, 'couch_potato')" + run: | + curl -f http://127.0.0.1:5984/ + curl -X POST -H "Content-Type: application/json; charset=utf-8" -d '{"name": "admin", "password": "password"}' http://127.0.0.1:5984/_session + + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Ruby & RubyGems + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + rubygems: ${{ matrix.rubygems }} + bundler: ${{ matrix.bundler }} + bundler-cache: false + + # Raw `bundle` will use the BUNDLE_GEMFILE set to matrix.gemfile (i.e. Appraisal.root) + # We need to do this first to get appraisal installed. + # NOTE: This does not use the main Gemfile at all. + - name: Install Root Appraisal + run: bundle + - name: Appraisal for ${{ matrix.ruby }}@${{ matrix.appraisal_name }} + run: bundle exec appraisal ${{ matrix.appraisal_name }} bundle + - name: Run ${{ matrix.exec_cmd }} on ${{ matrix.ruby }}@${{ matrix.appraisal_name }} + run: bundle exec appraisal ${{ matrix.appraisal_name }} bundle exec ${{ matrix.exec_cmd }} diff --git a/.github/workflows/jruby.yml b/.github/workflows/jruby.yml new file mode 100644 index 0000000..02c2e6d --- /dev/null +++ b/.github/workflows/jruby.yml @@ -0,0 +1,80 @@ +name: JRuby + +permissions: + contents: read + +env: + K_SOUP_COV_DO: false + +on: + push: + branches: + - 'main' + tags: + - '!*' # Do not execute on tags + pull_request: + branches: + - '*' + # Allow manually triggering the workflow. + workflow_dispatch: + +# Cancels all previous workflow runs for the same branch that have not yet completed. +concurrency: + # The concurrency group contains the workflow name and the branch name. + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + test: + name: Specs ${{ matrix.ruby }} ${{ matrix.appraisal_name }}${{ matrix.name_extra || '' }} + if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" + runs-on: ubuntu-22.04 + continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} + env: # $BUNDLE_GEMFILE must be set at job level, so it is set for all steps + BUNDLE_GEMFILE: ${{ github.workspace }}/${{ matrix.gemfile }}.gemfile + strategy: + matrix: + include: + # jruby-9.4 (targets Ruby 3.1 compatibility) + - ruby: "jruby-9.4" + appraisal_name: "omniauth-v2.1-r3" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: default + bundler: default + + steps: + ### COUCHDB + - name: Start CouchDB + uses: iamssen/couchdb-github-action@master + if: "endsWith(matrix.exec_cmd, 'couch_potato')" + with: + couchdb-version: "3.4.1" + + ### SMOKE-TEST + - name: Smoke CouchDB + if: "endsWith(matrix.exec_cmd, 'couch_potato')" + run: | + curl -f http://127.0.0.1:5984/ + curl -X POST -H "Content-Type: application/json; charset=utf-8" -d '{"name": "admin", "password": "password"}' http://127.0.0.1:5984/_session + + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Ruby & RubyGems + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + rubygems: ${{ matrix.rubygems }} + bundler: ${{ matrix.bundler }} + bundler-cache: false + + # Raw `bundle` will use the BUNDLE_GEMFILE set to matrix.gemfile (i.e. Appraisal.root) + # We need to do this first to get appraisal installed. + # NOTE: This does not use the main Gemfile at all. + - name: Install Root Appraisal + run: bundle + - name: Appraisal for ${{ matrix.ruby }}@${{ matrix.appraisal_name }} + run: bundle exec appraisal ${{ matrix.appraisal_name }} bundle + - name: Run ${{ matrix.exec_cmd }} on ${{ matrix.ruby }}@${{ matrix.appraisal_name }} + run: bundle exec appraisal ${{ matrix.appraisal_name }} bundle exec ${{ matrix.exec_cmd }} diff --git a/.github/workflows/legacy.yml b/.github/workflows/legacy.yml new file mode 100644 index 0000000..b2b9be6 --- /dev/null +++ b/.github/workflows/legacy.yml @@ -0,0 +1,67 @@ +name: MRI 3.0 (Legacy) + +permissions: + contents: read + +env: + K_SOUP_COV_DO: false + +on: + push: + branches: + - 'main' + tags: + - '!*' # Do not execute on tags + pull_request: + branches: + - '*' + # Allow manually triggering the workflow. + workflow_dispatch: + +# Cancels all previous workflow runs for the same branch that have not yet completed. +concurrency: + # The concurrency group contains the workflow name and the branch name. + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + test: + name: Specs ${{ matrix.ruby }} ${{ matrix.appraisal_name }}${{ matrix.name_extra || '' }} + if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" + runs-on: ubuntu-22.04 + continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} + env: # $BUNDLE_GEMFILE must be set at job level, so it is set for all steps + BUNDLE_GEMFILE: ${{ github.workspace }}/${{ matrix.gemfile }}.gemfile + strategy: + fail-fast: false + matrix: + include: + # Ruby 3.0 + - ruby: "3.0" + appraisal_name: "omniauth-v2.1-r3.0" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: '3.5.23' + bundler: '2.5.23' + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Ruby & RubyGems + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + rubygems: ${{ matrix.rubygems }} + bundler: ${{ matrix.bundler }} + bundler-cache: false + + # Raw `bundle` will use the BUNDLE_GEMFILE set to matrix.gemfile (i.e. Appraisal.root) + # We need to do this first to get appraisal installed. + # NOTE: This does not use the main Gemfile at all. + - name: Install Root Appraisal + run: bundle + - name: Appraisal for ${{ matrix.ruby }}@${{ matrix.appraisal_name }} + run: bundle exec appraisal ${{ matrix.appraisal_name }} bundle + - name: Run ${{ matrix.exec_cmd }} on ${{ matrix.ruby }}@${{ matrix.appraisal_name }} + run: bundle exec appraisal ${{ matrix.appraisal_name }} bundle exec ${{ matrix.exec_cmd }} diff --git a/.github/workflows/style.yml b/.github/workflows/style.yml new file mode 100644 index 0000000..fda124e --- /dev/null +++ b/.github/workflows/style.yml @@ -0,0 +1,64 @@ +name: Style + +permissions: + contents: read + +on: + push: + branches: + - 'main' + tags: + - '!*' # Do not execute on tags + pull_request: + branches: + - '*' + # Allow manually triggering the workflow. + workflow_dispatch: + +# Cancels all previous workflow runs for the same branch that have not yet completed. +concurrency: + # The concurrency group contains the workflow name and the branch name. + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + rubocop: + name: Style on ${{ matrix.ruby }}@current + if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} + env: # $BUNDLE_GEMFILE must be set at job level, so it is set for all steps + BUNDLE_GEMFILE: ${{ github.workspace }}/${{ matrix.gemfile }}.gemfile + strategy: + fail-fast: false + matrix: + include: + # Style + - ruby: "ruby" + appraisal_name: "style" + exec_cmd: "rake rubocop_gradual:check" + gemfile: "Appraisal.root" + rubygems: latest + bundler: latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Ruby & RubyGems + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + rubygems: ${{ matrix.rubygems }} + bundler: ${{ matrix.bundler }} + bundler-cache: false + + # Raw `bundle` will use the BUNDLE_GEMFILE set to matrix.gemfile (i.e. Appraisal.root) + # We need to do this first to get appraisal installed. + # NOTE: This does not use the main Gemfile at all. + - name: Install Root Appraisal + run: bundle + - name: Appraisal for ${{ matrix.ruby }}@${{ matrix.appraisal_name }} + run: bundle exec appraisal ${{ matrix.appraisal_name }} bundle + - name: Run ${{ matrix.exec_cmd }} on ${{ matrix.ruby }}@${{ matrix.appraisal_name }} + run: bundle exec appraisal ${{ matrix.appraisal_name }} bundle exec ${{ matrix.exec_cmd }} diff --git a/.github/workflows/supported.yml b/.github/workflows/supported.yml new file mode 100644 index 0000000..7bef3c6 --- /dev/null +++ b/.github/workflows/supported.yml @@ -0,0 +1,82 @@ +name: MRI (Supported) + +permissions: + contents: read + +env: + K_SOUP_COV_DO: false + +on: + push: + branches: + - 'main' + tags: + - '!*' # Do not execute on tags + pull_request: + branches: + - '*' + # Allow manually triggering the workflow. + workflow_dispatch: + +# Cancels all previous workflow runs for the same branch that have not yet completed. +concurrency: + # The concurrency group contains the workflow name and the branch name. + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + test: + name: Specs ${{ matrix.ruby }} ${{ matrix.appraisal_name }}${{ matrix.name_extra || '' }} + if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} + env: # $BUNDLE_GEMFILE must be set at job level, so it is set for all steps + BUNDLE_GEMFILE: ${{ github.workspace }}/${{ matrix.gemfile }}.gemfile + strategy: + matrix: + include: + # Ruby 3.1 + - ruby: "3.1" + appraisal_name: "omniauth-v2.1-r3" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: latest + bundler: latest + + # Ruby 3.2 + - ruby: "3.2" + appraisal_name: "omniauth-v2.1-r3" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: latest + bundler: latest + + # Ruby 3.3 + - ruby: "3.3" + appraisal_name: "omniauth-v2.1-r3" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: latest + bundler: latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Ruby & RubyGems + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + rubygems: ${{ matrix.rubygems }} + bundler: ${{ matrix.bundler }} + bundler-cache: false + + # Raw `bundle` will use the BUNDLE_GEMFILE set to matrix.gemfile (i.e. Appraisal.root) + # We need to do this first to get appraisal installed. + # NOTE: This does not use the main Gemfile at all. + - name: Install Root Appraisal + run: bundle + - name: Appraisal for ${{ matrix.ruby }}@${{ matrix.appraisal_name }} + run: bundle exec appraisal ${{ matrix.appraisal_name }} bundle + - name: Run ${{ matrix.exec_cmd }} on ${{ matrix.ruby }}@${{ matrix.appraisal_name }} + run: bundle exec appraisal ${{ matrix.appraisal_name }} bundle exec ${{ matrix.exec_cmd }} diff --git a/.github/workflows/unsupported.yml b/.github/workflows/unsupported.yml new file mode 100644 index 0000000..c0242e2 --- /dev/null +++ b/.github/workflows/unsupported.yml @@ -0,0 +1,171 @@ +name: MRI 2.6 & 2.7 (Unsupported) + +permissions: + contents: read + +env: + K_SOUP_COV_DO: false + +on: + push: + branches: + - 'main' + tags: + - '!*' # Do not execute on tags + pull_request: + branches: + - '*' + # Allow manually triggering the workflow. + workflow_dispatch: + +# Cancels all previous workflow runs for the same branch that have not yet completed. +concurrency: + # The concurrency group contains the workflow name and the branch name. + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + test: + name: Specs ${{ matrix.ruby }} ${{ matrix.appraisal_name }}${{ matrix.name_extra || '' }} + if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" + runs-on: ubuntu-22.04 + continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} + env: # $BUNDLE_GEMFILE must be set at job level, so it is set for all steps + BUNDLE_GEMFILE: ${{ github.workspace }}/${{ matrix.gemfile }}.gemfile + strategy: + fail-fast: false + matrix: + include: + # Ruby 2.6 + - ruby: "2.6" + appraisal_name: "omniauth-v1.2-r2" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: '3.4.22' + bundler: '2.4.22' + - ruby: "2.6" + appraisal_name: "omniauth-v1.3-r2" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: '3.4.22' + bundler: '2.4.22' + - ruby: "2.6" + appraisal_name: "omniauth-v1.4-r2" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: '3.4.22' + bundler: '2.4.22' + - ruby: "2.6" + appraisal_name: "omniauth-v1.5-r2" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: '3.4.22' + bundler: '2.4.22' + - ruby: "2.6" + appraisal_name: "omniauth-v1.6-r2" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: '3.4.22' + bundler: '2.4.22' + - ruby: "2.6" + appraisal_name: "omniauth-v1.7-r2" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: '3.4.22' + bundler: '2.4.22' + - ruby: "2.6" + appraisal_name: "omniauth-v1.8-r2" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: '3.4.22' + bundler: '2.4.22' + - ruby: "2.6" + appraisal_name: "omniauth-v1.9-r2" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: '3.4.22' + bundler: '2.4.22' + - ruby: "2.6" + appraisal_name: "omniauth-v2.0-r2" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: '3.4.22' + bundler: '2.4.22' + + # Ruby 2.7 + - ruby: "2.7" + appraisal_name: "omniauth-v1.2-r2" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: '3.4.22' + bundler: '2.4.22' + - ruby: "2.7" + appraisal_name: "omniauth-v1.3-r2" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: '3.4.22' + bundler: '2.4.22' + - ruby: "2.7" + appraisal_name: "omniauth-v1.4-r2" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: '3.4.22' + bundler: '2.4.22' + - ruby: "2.7" + appraisal_name: "omniauth-v1.5-r2" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: '3.4.22' + bundler: '2.4.22' + - ruby: "2.7" + appraisal_name: "omniauth-v1.6-r2" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: '3.4.22' + bundler: '2.4.22' + - ruby: "2.7" + appraisal_name: "omniauth-v1.7-r2" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: '3.4.22' + bundler: '2.4.22' + - ruby: "2.7" + appraisal_name: "omniauth-v1.8-r2" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: '3.4.22' + bundler: '2.4.22' + - ruby: "2.7" + appraisal_name: "omniauth-v1.9-r2" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: '3.4.22' + bundler: '2.4.22' + - ruby: "2.7" + appraisal_name: "omniauth-v2.0-r2" + exec_cmd: "rake spec" + gemfile: "Appraisal.root" + rubygems: '3.4.22' + bundler: '2.4.22' + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Ruby & RubyGems + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + rubygems: ${{ matrix.rubygems }} + bundler: ${{ matrix.bundler }} + bundler-cache: false + + # Raw `bundle` will use the BUNDLE_GEMFILE set to matrix.gemfile (i.e. Appraisal.root) + # We need to do this first to get appraisal installed. + # NOTE: This does not use the main Gemfile at all. + - name: Install Root Appraisal + run: bundle + - name: Appraisal for ${{ matrix.ruby }}@${{ matrix.appraisal_name }} + run: bundle exec appraisal ${{ matrix.appraisal_name }} bundle + - name: Run ${{ matrix.exec_cmd }} on ${{ matrix.ruby }}@${{ matrix.appraisal_name }} + run: bundle exec appraisal ${{ matrix.appraisal_name }} bundle exec ${{ matrix.exec_cmd }} diff --git a/.gitignore b/.gitignore index f34d9a2..159a4bd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,18 +1,44 @@ +# Build Artifacts +/pkg/ +/tmp/ *.gem -*.rbc -.bundle -.config -.yardoc -Gemfile.lock -InstalledFiles -_yardoc -coverage -doc/ -lib/bundler/man -/pkg -rdoc -spec/reports -test/tmp -test/version_tmp -tmp +# Bundler +/.bundle/ +/gemfiles/*.lock +/gemfiles/.bundle/ +/gemfiles/.bundle/config +/gemfiles/vendor/ +Appraisal.*.gemfile.lock + +# Specs +.rspec_status +/coverage/ +/spec/reports/ + +# Documentation +/.yardoc/ +/_yardoc/ +/rdoc/ +/doc/ + +# Ruby Version Managers (RVM, rbenv, etc) +# Ignored because we currently use .tool-versions +.rvmrc +.ruby-version +.ruby-gemset + +# Benchmarking +/measurement/ + +# Debugger detritus +.byebug_history + +# direnv - brew install direnv +.env.local + +# OS Detritus +.DS_Store + +# Editors +*~ diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..a29d697 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,10 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# CodeStream ignored files +/codestream.xml diff --git a/.idea/GitLink.xml b/.idea/GitLink.xml new file mode 100644 index 0000000..009597c --- /dev/null +++ b/.idea/GitLink.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/dbnavigator.xml b/.idea/dbnavigator.xml new file mode 100644 index 0000000..b9e7cc8 --- /dev/null +++ b/.idea/dbnavigator.xml @@ -0,0 +1,427 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/dictionaries/project.xml b/.idea/dictionaries/project.xml new file mode 100644 index 0000000..4e1f2b8 --- /dev/null +++ b/.idea/dictionaries/project.xml @@ -0,0 +1,8 @@ + + + + securerandom + webmock + + + \ No newline at end of file diff --git a/.idea/git_toolbox_prj.xml b/.idea/git_toolbox_prj.xml new file mode 100644 index 0000000..02b915b --- /dev/null +++ b/.idea/git_toolbox_prj.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..39693f0 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..0cf8196 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/omniauth-openid.iml b/.idea/omniauth-openid.iml new file mode 100644 index 0000000..fcab90e --- /dev/null +++ b/.idea/omniauth-openid.iml @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..13b4e4e --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.qlty/qlty.toml b/.qlty/qlty.toml new file mode 100644 index 0000000..5f1b620 --- /dev/null +++ b/.qlty/qlty.toml @@ -0,0 +1,78 @@ +# For a guide to configuration, visit https://qlty.sh/d/config +# Or for a full reference, visit https://qlty.sh/d/qlty-toml +config_version = "0" + +exclude_patterns = [ + "*_min.*", + "*-min.*", + "*.min.*", + "**/.yarn/**", + "**/*.d.ts", + "**/assets/**", + "**/bin/**", + "**/bower_components/**", + "**/build/**", + "**/cache/**", + "**/config/**", + "**/.devcontainer", + "**/db/**", + "**/deps/**", + "**/dist/**", + "**/doc/**", + "**/extern/**", + "**/external/**", + "**/generated/**", + "**/Godeps/**", + "**/gradlew/**", + "**/mvnw/**", + "**/node_modules/**", + "**/protos/**", + "**/seed/**", + "**/target/**", + "**/templates/**", + "**/testdata/**", + "**/vendor/**", + ".github/workflows/codeql-analysis.yml" +] + +test_patterns = [ + "**/test/**", + "**/spec/**", + "**/*.test.*", + "**/*.spec.*", + "**/*_test.*", + "**/*_spec.*", + "**/test_*.*", + "**/spec_*.*", +] + +[smells] +mode = "comment" + +[smells.boolean_logic] +threshold = 4 +enabled = true + +[smells.file_complexity] +threshold = 55 +enabled = false + +[smells.return_statements] +threshold = 4 +enabled = true + +[smells.nested_control_flow] +threshold = 4 +enabled = true + +[smells.function_parameters] +threshold = 4 +enabled = true + +[smells.function_complexity] +threshold = 5 +enabled = true + +[smells.duplication] +enabled = true +threshold = 20 \ No newline at end of file diff --git a/.rspec b/.rspec index 5f16476..bdb15cb 100644 --- a/.rspec +++ b/.rspec @@ -1,2 +1,3 @@ ---color ---format progress +--require spec_helper +--format=documentation +--colour diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..6de99cd --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,2 @@ +inherit_gem: + rubocop-lts: config/rubygem_rspec.yml diff --git a/.rubocop_gradual.lock b/.rubocop_gradual.lock new file mode 100644 index 0000000..34f6804 --- /dev/null +++ b/.rubocop_gradual.lock @@ -0,0 +1,22 @@ +{ + "bin/bundle:247448467": [ + [64, 5, 20, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2485198147] + ], + "lib/omniauth/strategies/open_id.rb:3703196606": [ + [50, 17, 10, "Lint/DuplicateHashKey: Duplicated key in hash literal.", 3672542120] + ], + "omniauth-openid.gemspec:1451907988": [ + [4, 23, 12, "Gemspec/RubyVersionGlobalsUsage: Do not use `RUBY_VERSION` in gemspec file.", 31296028] + ], + "spec/omniauth/openid/version_spec.rb:4155563924": [ + [11, 58, 25, "RSpec/DescribedClass: Use `described_class` instead of `OmniAuth::OpenID::Version`.", 3486261707] + ], + "spec/omniauth/strategies/open_id_spec.rb:1187086664": [ + [1, 1, 60, "RSpec/SpecFilePathFormat: Spec path should end with `omni_auth/strategies/open_id*_spec.rb`.", 3122388919], + [55, 13, 12, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 1731001529], + [72, 13, 14, "RSpec/ContextWording: Context description should match /^when\\b/, /^with\\b/, or /^without\\b/.", 468958882], + [73, 7, 45, "RSpec/NestedGroups: Maximum example group nesting exceeded [4/3].", 3384971759], + [74, 9, 37, "RSpec/MultipleExpectations: Example has too many expectations [2/1].", 526327299], + [75, 11, 7, "RSpec/PendingWithoutReason: Give the reason for pending.", 2397655994] + ] +} diff --git a/.simplecov b/.simplecov new file mode 100644 index 0000000..cde49ad --- /dev/null +++ b/.simplecov @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +require "kettle/soup/cover/config" + +SimpleCov.start diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 0000000..ca745c6 --- /dev/null +++ b/.tool-versions @@ -0,0 +1 @@ +ruby 3.4.4 diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index ba4092c..0000000 --- a/.travis.yml +++ /dev/null @@ -1,23 +0,0 @@ -bundler_args: --without development -before_install: - - gem update --system - - gem update bundler -cache: bundler -env: - global: - - JRUBY_OPTS="$JRUBY_OPTS --debug" -language: ruby -rvm: - - jruby-9.2.14.0 - - 2.4.10 - - 2.5.8 - - 2.6.6 - - 2.7.2 - - jruby-head - - ruby-head -matrix: - allow_failures: - - rvm: jruby-head - - rvm: ruby-head - fast_finish: true -sudo: false diff --git a/.yard_gfm_support.rb b/.yard_gfm_support.rb new file mode 100644 index 0000000..4f2f140 --- /dev/null +++ b/.yard_gfm_support.rb @@ -0,0 +1,22 @@ +# Gratefully and liberally taken from the MIT-licensed https://github.com/bensheldon/good_job/pull/113/files +require "kramdown" +require "kramdown-parser-gfm" + +# Custom markup provider class that always renders Kramdown using GFM (Github Flavored Markdown). +# GFM is needed to render markdown tables and fenced code blocks in the README. +class KramdownGfmDocument < Kramdown::Document + def initialize(source, options = {}) + options[:input] = "GFM" unless options.key?(:input) + super(source, options) + end +end + +# Insert the new provider as the highest priority option for Markdown. +# See: +# - https://github.com/lsegal/yard/issues/1157 +# - https://github.com/lsegal/yard/issues/1017 +# - https://github.com/lsegal/yard/blob/main/lib/yard/templates/helpers/markup_helper.rb +YARD::Templates::Helpers::MarkupHelper::MARKUP_PROVIDERS[:markdown].insert( + 0, + {const: "KramdownGfmDocument"}, +) diff --git a/.yardopts b/.yardopts index 7a69ee4..479134d 100644 --- a/.yardopts +++ b/.yardopts @@ -1,4 +1,11 @@ +--plugin junk +--plugin relative_markdown_links +--readme README.md +--charset utf-8 --markup markdown ---markup-provider maruku +--output docs +--load .yard_gfm_support.rb +'lib/**/*.rb' - -LICENSE +'*.md' +'*.txt' \ No newline at end of file diff --git a/Appraisal.root.gemfile b/Appraisal.root.gemfile new file mode 100644 index 0000000..9d72016 --- /dev/null +++ b/Appraisal.root.gemfile @@ -0,0 +1,12 @@ +git_source(:github) { |repo_name| "https://github.com/#{repo_name}" } + +source "https://rubygems.org" + +# Appraisal Root Gemfile is for running appraisal to generate the Appraisal Gemfiles +# in gemfiles/*gemfile. +# On CI, we use it for the Appraisal-based builds. +# We do not load the standard Gemfile, as it is tailored for local development. + +gemspec + +gem "appraisal", github: "pboling/appraisal", branch: "galtzo" diff --git a/Appraisals b/Appraisals new file mode 100644 index 0000000..32b3cc5 --- /dev/null +++ b/Appraisals @@ -0,0 +1,171 @@ +# frozen_string_literal: true + +# HOW TO UPDATE APPRAISALS: +# BUNDLE_GEMFILE=Appraisal.root.gemfile bundle +# BUNDLE_GEMFILE=Appraisal.root.gemfile bundle exec appraisal update +# bundle exec rake rubocop_gradual:autocorrect + +# Used for HEAD (nightly) releases of ruby, truffleruby, and jruby. +# Split into discrete appraisals if one of them needs a dependency locked discretely. +appraise "dep-heads" do + eval_gemfile "modular/runtime_heads.gemfile" + remove_gem "appraisal" # only present because it must be in the gemfile because we target a git branch +end + +# Test Matrix: +# - Ruby 2.4 +appraise "omniauth-v1.1-r2.4" do + eval_gemfile "modular/omniauth/r2/v1.1.gemfile" + eval_gemfile "modular/x_std_libs/r2.4/libs.gemfile" + remove_gem "appraisal" # only present because it must be in the gemfile because we target a git branch +end + +# Test Matrix: +# - Ruby 2.5 +# - Ruby 2.6 +# - Ruby 2.7 +appraise "omniauth-v1.2-r2" do + eval_gemfile "modular/omniauth/r2/v1.2.gemfile" + eval_gemfile "modular/x_std_libs/r2/libs.gemfile" + remove_gem "appraisal" # only present because it must be in the gemfile because we target a git branch +end + +# Compat: Ruby >= 2.5 +# Test Matrix: +# - Ruby 2.5 +# - Ruby 2.6 +# - Ruby 2.7 +appraise "omniauth-v1.3-r2" do + eval_gemfile "modular/omniauth/r2/v1.3.gemfile" + eval_gemfile "modular/x_std_libs/r2/libs.gemfile" + remove_gem "appraisal" # only present because it must be in the gemfile because we target a git branch +end + +# Compat: Ruby >= 2.5 +# Test Matrix: +# - Ruby 2.5 +# - Ruby 2.6 +# - Ruby 2.7 +appraise "omniauth-v1.4-r2" do + eval_gemfile "modular/omniauth/r2/v1.4.gemfile" + eval_gemfile "modular/x_std_libs/r2/libs.gemfile" + remove_gem "appraisal" # only present because it must be in the gemfile because we target a git branch +end + +# Compat: Ruby >= 2.5 +# Test Matrix: +# - Ruby 2.5 +# - Ruby 2.6 +# - Ruby 2.7 +appraise "omniauth-v1.5-r2" do + eval_gemfile "modular/omniauth/r2/v1.5.gemfile" + eval_gemfile "modular/x_std_libs/r2/libs.gemfile" + remove_gem "appraisal" # only present because it must be in the gemfile because we target a git branch +end + +# Compat: Ruby >= 2.5 +# Test Matrix: +# - Ruby 2.5 +# - Ruby 2.6 +# - Ruby 2.7 +appraise "omniauth-v1.6-r2" do + eval_gemfile "modular/omniauth/r2/v1.6.gemfile" + eval_gemfile "modular/x_std_libs/r2/libs.gemfile" + remove_gem "appraisal" # only present because it must be in the gemfile because we target a git branch +end + +# Compat: Ruby >= 2.5 +# Test Matrix: +# - Ruby 2.5 +# - Ruby 2.6 +# - Ruby 2.7 +appraise "omniauth-v1.7-r2" do + eval_gemfile "modular/omniauth/r2/v1.7.gemfile" + eval_gemfile "modular/x_std_libs/r2/libs.gemfile" + remove_gem "appraisal" # only present because it must be in the gemfile because we target a git branch +end + +# Compat: Ruby >= 2.5 +# Test Matrix: +# - Ruby 2.5 +# - Ruby 2.6 +# - Ruby 2.7 +appraise "omniauth-v1.8-r2" do + eval_gemfile "modular/omniauth/r2/v1.8.gemfile" + eval_gemfile "modular/x_std_libs/r2/libs.gemfile" + remove_gem "appraisal" # only present because it must be in the gemfile because we target a git branch +end + +# Compat: Ruby >= 2.5 +# Test Matrix: +# - Ruby 2.5 +# - JRuby 9.2 +# - Ruby 2.6 +# - JRuby 9.3 +# - Ruby 2.7 +appraise "omniauth-v1.9-r2" do + eval_gemfile "modular/omniauth/r2/v1.9.gemfile" + eval_gemfile "modular/x_std_libs/r2/libs.gemfile" + remove_gem "appraisal" # only present because it must be in the gemfile because we target a git branch +end + +# Compat: Ruby >= 2.5 +# Test Matrix: +# - Ruby 2.5 +# - JRuby 9.2 +# - Ruby 2.6 +# - JRuby 9.3 +# - Ruby 2.7 +appraise "omniauth-v2.0-r2" do + eval_gemfile "modular/omniauth/r2/v2.0.gemfile" + eval_gemfile "modular/x_std_libs/r2/libs.gemfile" + remove_gem "appraisal" # only present because it must be in the gemfile because we target a git branch +end + +# Compat: Ruby >= 2.5 +# Test Matrix: +# - Ruby 3.0 +appraise "omniauth-v2.1-r3.0" do + eval_gemfile "modular/omniauth/r3/v2.1.gemfile" + eval_gemfile "modular/x_std_libs/r3/libs.gemfile" + remove_gem "appraisal" # only present because it must be in the gemfile because we target a git branch +end + +# Compat: Ruby >= 3.1 +# Test Matrix: +# - Ruby 3.1 +# - JRuby 9.4 +# - Ruby 3.2 +# - Ruby 3.3 +# - JRuby 10.0 +# - jruby-head +appraise "omniauth-v2.1-r3" do + eval_gemfile "modular/omniauth/r3/v2.1.gemfile" + eval_gemfile "modular/x_std_libs/r3/libs.gemfile" + remove_gem "appraisal" # only present because it must be in the gemfile because we target a git branch +end + +# Only run security audit on the latest version of Ruby +appraise "audit" do + eval_gemfile "modular/omniauth/r3/v2.1.gemfile" + eval_gemfile "modular/audit.gemfile" + eval_gemfile "modular/x_std_libs/r3/libs.gemfile" + remove_gem "appraisal" # only present because it must be in the gemfile because we target a git branch +end + +# Only run coverage on the latest version of Ruby +appraise "coverage" do + eval_gemfile "modular/omniauth/r3/v2.1.gemfile" + eval_gemfile "modular/coverage.gemfile" + gem "ostruct", "~> 0.6", ">= 0.6.1" # Ruby >= 2.5 + eval_gemfile "modular/x_std_libs/r3/libs.gemfile" + remove_gem "appraisal" # only present because it must be in the gemfile because we target a git branch +end + +# Only run linter on the latest version of Ruby (but, in support of the oldest supported Ruby version) +appraise "style" do + eval_gemfile "modular/style.gemfile" + eval_gemfile "modular/omniauth/r3/v2.1.gemfile" + eval_gemfile "modular/x_std_libs/r3/libs.gemfile" + remove_gem "appraisal" # only present because it must be in the gemfile because we target a git branch +end diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..c55955f --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,54 @@ +# Changelog + +This file documents all notable changes to this project since v2.0.2. + +The format is based on [Keep a Changelog v1](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning v2](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] +### Added +### Changed +### Deprecated +### Removed +### Fixed +### Security + +## [2.0.2] - 2025-06-08 +- TAG: [v2.0.2][2.0.2t] +- COVERAGE: 92.06% -- 348/378 lines in 15 files +- BRANCH COVERAGE: 79.49% -- 62/78 branches in 15 files +- 44.44% documented +### Added +- Github Actions for Continuous Integration by @pboling + - Test workflows with latest dependencies and more platform and dep HEADs + - Expanded test suite, covering many more points of the dependency matrix +- More documentation by @pboling +- 20 year signing cert expires 2045-04-29 by @pboling +- Added CITATION.cff by @pboling +- devcontainer for easier maintenance by @pboling +- Add SECURITY.md policy by @pboling +- CONTRIBUTING.md - Instructions for contributing by @pboling +- Modernized gem structure, and updated dependencies for development by @pboling +- Set `SKIP_GEM_SIGNING` in env to allow `gem build` without cryptographic signing requirement by @pboling + - Useful for linux distros whose package managers sign packages independently +### Changed +- Updated Code of Conduct to Contributor Covenant v2.1 by @pboling + +## [2.0.1] - 2021-01-19 +- TAG: [v2.0.0][2.0.0t] + +## [1.0.1] - 2011-11-04 +- TAG: [v1.0.1][1.0.1t] + +## [1.0.0] - 2011-11-02 +- TAG: [v1.0.][1.0.0t] + +[Unreleased]: https://github.com/omniauth/omniauth-openid/compare/v2.0.2...HEAD +[2.0.2]: https://github.com/omniauth/omniauth-openid/compare/v2.0.2...v2.0.1 +[2.0.2t]: https://github.com/omniauth/omniauth-openid/tags/v2.0.2 +[2.0.1]: https://github.com/omniauth/omniauth-openid/compare/v2.0.1...v1.0.1 +[2.0.1t]: https://github.com/omniauth/omniauth-openid/tags/v2.0.1 +[1.0.1]: https://github.com/omniauth/omniauth-openid/compare/v1.0.1...v1.0.0 +[1.0.1t]: https://github.com/omniauth/omniauth-openid/tags/v1.0.1 +[1.0.0]: https://github.com/omniauth/omniauth-openid/compare/6019f3abd7b707567e2217c91be64f7a6c4aa34b...v1.0.0 +[1.0.0t]: https://github.com/omniauth/omniauth-openid/tags/v1.0.0 diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index d33878e..6be4700 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -53,7 +53,7 @@ decisions when appropriate. This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. -Examples of representing our community include using an official e-mail address, +Examples of representing our community include using an official email address, posting via an official social media account, or acting as an appointed representative at an online or offline event. @@ -61,7 +61,7 @@ representative at an online or offline event. Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at -[INSERT CONTACT METHOD]. +[![Contact BDFL][🚂bdfl-contact-img]][🚂bdfl-contact]. All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the @@ -131,4 +131,5 @@ For answers to common questions about this code of conduct, see the FAQ at [Mozilla CoC]: https://github.com/mozilla/diversity [FAQ]: https://www.contributor-covenant.org/faq [translations]: https://www.contributor-covenant.org/translations - +[🚂bdfl-contact]: http://www.railsbling.com/contact +[🚂bdfl-contact-img]: https://img.shields.io/badge/Contact-BDFL-0093D0.svg?style=flat&logo=rubyonrails&logoColor=red diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100755 index 0000000..c0e650c --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,132 @@ +# Contributing + +Bug reports and pull requests are welcome on GitHub at [https://github.com/omniauth/omniauth-openid][🚎src-main]. +This project should be a safe, welcoming space for collaboration, so contributors agree to adhere to +the [code of conduct][🤝conduct]. + +To submit a patch, please fork the project, create a patch with tests, and send a pull request. + +Remember to [![Keep A Changelog][📗keep-changelog-img]][📗keep-changelog] if you make changes. + +## Help out! + +Take a look at the `reek` list which is the file called `REEK` and find something to improve. + +Follow these instructions: + +1. Fork the repository +2. Create a feature branch (`git checkout -b my-new-feature`) +3. Make some fixes. +4. Commit changes (`git commit -am 'Added some feature'`) +5. Push to the branch (`git push origin my-new-feature`) +6. Make sure to add tests for it. This is important, so it doesn't break in a future release. +7. Create new Pull Request. + +## Appraisals + +From time to time the appraisal gemfiles in `gemfiles/` will need to be updated. + +NOTE: The `eval_gemfile` feature comes from a [fork][🚎appraisal-fork] of Appraisal. + +Please upvote the PR for `eval_gemfile` [support][🚎appraisal-eval-gemfile-pr] + +Create or update them with the commands: + +```shell +BUNDLE_GEMFILE=Appraisal.root.gemfile bundle +BUNDLE_GEMFILE=Appraisal.root.gemfile bundle exec appraisal update +bundle exec rake rubocop_gradual:autocorrect +``` + +When adding an appraisal to CI, check the [runner tool cache][🏃‍♂️runner-tool-cache] to see which runner to use. + +## The Reek List + +Take a look at the `reek` list which is the file called `REEK` and find something to improve. + +To refresh the `reek` list: + +```bash +bundle exec reek > REEK +``` + +## Run Tests + +To run all tests: + +```bash +bundle exec rake test +``` + +## Lint It + +Run all the default tasks, which includes running the gradually autocorrecting linter, `rubocop-gradual`. + +```bash +bundle exec rake +``` + +Or just run the linter. + +```bash +bundle exec rake rubocop_gradual:autocorrect +``` + +## Contributors + +[![Contributors][🖐contributors-img]][🖐contributors] + +Made with [contributors-img][🖐contrib-rocks]. + +## For Maintainers + +### One-time, Per-maintainer, Setup + +**IMPORTANT**: To sign a build, +a public key for signing gems will need to be picked up by the line in the +`gemspec` defining the `spec.cert_chain` (check the relevant ENV variables there). +All releases to RubyGems.org are signed releases. +See: [RubyGems Security Guide][🔒️rubygems-security-guide] + +NOTE: To build without signing the gem set `SKIP_GEM_SIGNING` to any value in the environment. + +### To release a new version: + +1. Run `bin/setup && bin/rake` as a "test, coverage, & linting" sanity check +2. Update the version number in `version.rb`, and ensure `CHANGELOG.md` reflects changes +3. Run `bin/setup && bin/rake` again as a secondary check, and to update `Gemfile.lock` +4. Run `git commit -am "🔖 Prepare release v"` to commit the changes +5. Run `git push` to trigger the final CI pipeline before release, and merge PRs + - NOTE: Remember to [check the build][🧪build]. +6. Run `export GIT_TRUNK_BRANCH_NAME="$(git remote show origin | grep 'HEAD branch' | cut -d ' ' -f5)" && echo $GIT_TRUNK_BRANCH_NAME` +7. Run `git checkout $GIT_TRUNK_BRANCH_NAME` +8. Run `git pull origin $GIT_TRUNK_BRANCH_NAME` to ensure latest trunk code +9. Set `SOURCE_DATE_EPOCH` so `rake build` and `rake release` use same timestamp, and generate same checksums + - Run `export SOURCE_DATE_EPOCH=$EPOCHSECONDS && echo $SOURCE_DATE_EPOCH` + - If the echo above has no output, then it didn't work. + - Note: `zsh/datetime` module is needed, if running `zsh`. + - In older versions of `bash` you can use `date +%s` instead, i.e. `export SOURCE_DATE_EPOCH=$(date +%s) && echo $SOURCE_DATE_EPOCH` +10. Run `bundle exec rake build` +11. Run `bin/gem_checksums` (more context [1][🔒️rubygems-checksums-pr], [2][🔒️rubygems-guides-pr]) + to create SHA-256 and SHA-512 checksums. This functionality is provided by the `stone_checksums` + [gem][💎stone_checksums]. + - The script automatically commits but does not push the checksums +12. Run `bundle exec rake release` which will create a git tag for the version, + push git commits and tags, and push the `.gem` file to [rubygems.org][💎rubygems] + +13. [🚎src-main]: https://github.com/omniauth/omniauth-openid +[🧪build]: https://github.com/omniauth/omniauth-openid/actions +[🤝conduct]: https://github.com/omniauth/omniauth-openid/blob/main/CODE_OF_CONDUCT.md +[🖐contrib-rocks]: https://contrib.rocks +[🖐contributors]: https://github.com/omniauth/omniauth-openid/graphs/contributors +[🖐contributors-img]: https://contrib.rocks/image?repo=omniauth/omniauth-openid +[💎rubygems]: https://rubygems.org +[🔒️rubygems-security-guide]: https://guides.rubygems.org/security/#building-gems +[🔒️rubygems-checksums-pr]: https://github.com/rubygems/rubygems/pull/6022 +[🔒️rubygems-guides-pr]: https://github.com/rubygems/guides/pull/325 +[💎stone_checksums]: https://github.com/pboling/stone_checksums +[📗keep-changelog]: https://keepachangelog.com/en/1.0.0/ +[📗keep-changelog-img]: https://img.shields.io/badge/keep--a--changelog-1.0.0-FFDD67.svg?style=flat +[🚎appraisal-eval-gemfile-pr]: https://github.com/thoughtbot/appraisal/pull/248 +[🚎appraisal-fork]: https://github.com/pboling/appraisal/tree/galtzo +[🏃‍♂️runner-tool-cache]: https://github.com/ruby/ruby-builder/releases/tag/toolcache diff --git a/Gemfile b/Gemfile index 402aaf2..46be10c 100644 --- a/Gemfile +++ b/Gemfile @@ -1,23 +1,43 @@ -source 'http://rubygems.org' +#### IMPORTANT ####################################################### +# Gemfile is for local development ONLY; Gemfile is NOT loaded in CI # +####################################################### IMPORTANT #### -gem 'rake', '~> 12.0' +source "https://rubygems.org" -platforms :jruby do - gem 'jruby-openssl', '~> 0.9' -end - -gem 'ruby-openid', '2.1.8', :git => 'git://github.com/mbleigh/ruby-openid.git' +git_source(:github) { |repo_name| "https://github.com/#{repo_name}" } gemspec -group :development, :test do - gem 'rack-test' - gem 'rspec', '>= 3.0' - gem 'simplecov', '>= 0.9' - gem 'webmock', '~> 3.0' - gem 'yard', '>= 0.9.11' -end - -group :example do - gem 'sinatra' -end +### Std Lib Extracted Gems +eval_gemfile "gemfiles/modular/x_std_libs/r3/libs.gemfile" + +### Security Audit +eval_gemfile "gemfiles/modular/audit.gemfile" + +### Documentation +eval_gemfile "gemfiles/modular/documentation.gemfile" + +### Linting +eval_gemfile "gemfiles/modular/style.gemfile" + +# Code Coverage +eval_gemfile "gemfiles/modular/coverage.gemfile" + +### Testing +gem "appraisal", github: "pboling/appraisal", branch: "galtzo" + +# gem 'rake', '~> 12.0' + +# platforms :jruby do +# gem 'jruby-openssl', '~> 0.9' +# end +# group :development, :test do +# gem 'rack-test' +# gem 'rspec', '>= 3.0' +# gem 'simplecov', '>= 0.9' +# gem 'webmock'#, '~> 3.0' +# gem 'yard', '>= 0.9.11' +# end +# group :example do +# gem 'sinatra' +# end diff --git a/Gemfile.lock b/Gemfile.lock index 1cc6560..2aae65f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,41 +1,128 @@ GIT - remote: git://github.com/mbleigh/ruby-openid.git - revision: 4b6fdd152edbc9d1f617056879eb03bd82b78eb4 + remote: https://github.com/pboling/appraisal + revision: a3a3e4b7db67d9b085f96b2ffddd2b51bd8a1196 + branch: galtzo specs: - ruby-openid (2.1.8) + appraisal (3.0.0.rc1) + bundler (>= 1.17.3) + rake (>= 10) + thor (>= 0.14) + +GIT + remote: https://github.com/pboling/yard-junk + revision: 54ccebabbfa9a9cd44d0b991687ebbfd22c32b55 + branch: next + specs: + yard-junk (0.0.10) + backports (>= 3.18) + benchmark + ostruct + rainbow + yard PATH remote: . specs: - omniauth-openid (2.0.1) - omniauth (>= 1.0, < 3.0) - rack-openid (~> 1.4.0) + omniauth-openid (2.0.2) + omniauth (>= 1.1) + rack-openid (~> 1.4) + ruby-openid (~> 2.1, >= 2.1.8) + version_gem (~> 1.1, >= 1.1.8) GEM - remote: http://rubygems.org/ + remote: https://rubygems.org/ specs: - addressable (2.8.1) - public_suffix (>= 2.0.2, < 6.0) - base64 (0.2.0) - crack (0.4.5) + addressable (2.8.7) + public_suffix (>= 2.0.2, < 7.0) + ansi (1.5.0) + ast (2.4.3) + backports (3.25.1) + base64 (0.3.0) + benchmark (0.4.1) + bigdecimal (3.2.2) + bundler-audit (0.9.2) + bundler (>= 1.2.0, < 3) + thor (~> 1.0) + concurrent-ruby (1.3.5) + crack (1.0.0) + bigdecimal rexml - diff-lcs (1.4.4) - docile (1.3.5) - hashdiff (1.0.1) - hashie (4.1.0) + date (3.4.1) + diff-lcs (1.6.2) + diffy (3.4.3) + docile (1.4.1) + dry-configurable (1.3.0) + dry-core (~> 1.1) + zeitwerk (~> 2.6) + dry-core (1.1.0) + concurrent-ruby (~> 1.0) + logger + zeitwerk (~> 2.6) + dry-inflector (1.2.0) + dry-initializer (3.2.0) + dry-logic (1.6.0) + bigdecimal + concurrent-ruby (~> 1.0) + dry-core (~> 1.1) + zeitwerk (~> 2.6) + dry-schema (1.14.1) + concurrent-ruby (~> 1.0) + dry-configurable (~> 1.0, >= 1.0.1) + dry-core (~> 1.1) + dry-initializer (~> 3.2) + dry-logic (~> 1.5) + dry-types (~> 1.8) + zeitwerk (~> 2.6) + dry-types (1.8.2) + bigdecimal (~> 3.0) + concurrent-ruby (~> 1.0) + dry-core (~> 1.0) + dry-inflector (~> 1.0) + dry-logic (~> 1.4) + zeitwerk (~> 2.6) + erb (5.0.1) + hashdiff (1.2.0) + hashie (5.0.0) + json (2.12.2) + kettle-soup-cover (1.0.9) + simplecov (~> 0.22) + simplecov-cobertura (~> 2.1) + simplecov-console (~> 0.9, >= 0.9.1) + simplecov-html (~> 0.12) + simplecov-lcov (~> 0.8) + simplecov-rcov (~> 0.3, >= 0.3.3) + simplecov_json_formatter (~> 0.1, >= 0.1.4) + version_gem (~> 1.1, >= 1.1.7) + kramdown (2.5.1) + rexml (>= 3.3.9) + kramdown-parser-gfm (1.1.0) + kramdown (~> 2.0) + language_server-protocol (3.17.0.5) + lint_roller (1.1.0) logger (1.7.0) - mustermann (3.0.3) - ruby2_keywords (~> 0.0.1) + mutex_m (0.3.0) + nokogiri (1.18.8-x86_64-linux-gnu) + racc (~> 1.4) omniauth (2.1.3) hashie (>= 3.4.6) rack (>= 2.2.3) rack-protection - public_suffix (5.0.0) + ostruct (0.6.1) + parallel (1.27.0) + parser (3.3.8.0) + ast (~> 2.4.1) + racc + prism (1.4.0) + psych (5.2.6) + date + stringio + public_suffix (6.0.2) + racc (1.8.1) rack (3.1.16) rack-openid (1.4.2) rack (>= 1.1.0) ruby-openid (>= 2.1.8) - rack-protection (4.1.0) + rack-protection (4.1.1) base64 (>= 0.1.0) logger (>= 1.6.0) rack (>= 3.0.0, < 4) @@ -44,54 +131,170 @@ GEM rack (>= 3.0.0) rack-test (2.2.0) rack (>= 1.3) - rake (12.3.3) - rexml (3.3.9) - rspec (3.10.0) - rspec-core (~> 3.10.0) - rspec-expectations (~> 3.10.0) - rspec-mocks (~> 3.10.0) - rspec-core (3.10.1) - rspec-support (~> 3.10.0) - rspec-expectations (3.10.1) + rainbow (3.1.1) + rake (13.3.0) + rdoc (6.14.0) + erb + psych (>= 4.0.0) + reek (6.5.0) + dry-schema (~> 1.13) + logger (~> 1.6) + parser (~> 3.3.0) + rainbow (>= 2.0, < 4.0) + rexml (~> 3.1) + regexp_parser (2.10.0) + rexml (3.4.1) + rspec (3.13.1) + rspec-core (~> 3.13.0) + rspec-expectations (~> 3.13.0) + rspec-mocks (~> 3.13.0) + rspec-block_is_expected (1.0.6) + rspec-core (3.13.4) + rspec-support (~> 3.13.0) + rspec-expectations (3.13.5) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.13.0) + rspec-mocks (3.13.5) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.10.0) - rspec-mocks (3.10.1) + rspec-support (~> 3.13.0) + rspec-support (3.13.4) + rubocop (1.75.8) + json (~> 2.3) + language_server-protocol (~> 3.17.0.2) + lint_roller (~> 1.1.0) + parallel (~> 1.10) + parser (>= 3.3.0.2) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 2.9.3, < 3.0) + rubocop-ast (>= 1.44.0, < 2.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 2.4.0, < 4.0) + rubocop-ast (1.45.0) + parser (>= 3.3.7.2) + prism (~> 1.4) + rubocop-gradual (0.3.6) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.10.0) - rspec-support (3.10.1) - ruby2_keywords (0.0.5) - simplecov (0.18.5) + diffy (~> 3.0) + parallel (~> 1.10) + rainbow (>= 2.2.2, < 4.0) + rubocop (~> 1.0) + rubocop-lts (12.1.1) + rubocop-ruby2_4 (>= 2.0.3, < 3) + standard-rubocop-lts (>= 1.0.3, < 3) + version_gem (>= 1.1.2, < 3) + rubocop-md (1.2.4) + rubocop (>= 1.45) + rubocop-packaging (0.6.0) + lint_roller (~> 1.1.0) + rubocop (>= 1.72.1, < 2.0) + rubocop-performance (1.25.0) + lint_roller (~> 1.1) + rubocop (>= 1.75.0, < 2.0) + rubocop-ast (>= 1.38.0, < 2.0) + rubocop-rake (0.7.1) + lint_roller (~> 1.1) + rubocop (>= 1.72.1) + rubocop-rspec (3.6.0) + lint_roller (~> 1.1) + rubocop (~> 1.72, >= 1.72.1) + rubocop-ruby2_4 (2.0.5) + rubocop-gradual (~> 0.3, >= 0.3.1) + rubocop-md (~> 1.2) + rubocop-rake (~> 0.6) + rubocop-shopify (~> 2.14) + rubocop-thread_safety (~> 0.5, >= 0.5.1) + standard-rubocop-lts (~> 1.0, >= 1.0.7) + version_gem (>= 1.1.3, < 3) + rubocop-shopify (2.17.1) + rubocop (~> 1.62) + rubocop-thread_safety (0.7.2) + lint_roller (~> 1.1) + rubocop (~> 1.72, >= 1.72.1) + ruby-openid (2.9.2) + ruby-progressbar (1.13.0) + simplecov (0.22.0) docile (~> 1.1) simplecov-html (~> 0.11) - simplecov-html (0.12.3) - sinatra (4.1.0) - logger (>= 1.6.0) - mustermann (~> 3.0) - rack (>= 3.0.0, < 4) - rack-protection (= 4.1.0) - rack-session (>= 2.0.0, < 3) - tilt (~> 2.0) - tilt (2.6.0) - webmock (3.11.1) - addressable (>= 2.3.6) + simplecov_json_formatter (~> 0.1) + simplecov-cobertura (2.1.0) + rexml + simplecov (~> 0.19) + simplecov-console (0.9.3) + ansi + simplecov + terminal-table + simplecov-html (0.13.1) + simplecov-lcov (0.8.0) + simplecov-rcov (0.3.7) + simplecov (>= 0.4.1) + simplecov_json_formatter (0.1.4) + standard (1.50.0) + language_server-protocol (~> 3.17.0.2) + lint_roller (~> 1.0) + rubocop (~> 1.75.5) + standard-custom (~> 1.0.0) + standard-performance (~> 1.8) + standard-custom (1.0.2) + lint_roller (~> 1.0) + rubocop (~> 1.50) + standard-performance (1.8.0) + lint_roller (~> 1.1) + rubocop-performance (~> 1.25.0) + standard-rubocop-lts (1.0.10) + rspec-block_is_expected (~> 1.0, >= 1.0.5) + standard (>= 1.35.1, < 2) + standard-custom (>= 1.0.2, < 2) + standard-performance (>= 1.3.1, < 2) + version_gem (>= 1.1.4, < 3) + stone_checksums (1.0.0) + version_gem (>= 1.1.5, < 3) + stringio (3.1.7) + terminal-table (4.0.0) + unicode-display_width (>= 1.1.1, < 4) + thor (1.3.2) + unicode-display_width (3.1.4) + unicode-emoji (~> 4.0, >= 4.0.4) + unicode-emoji (4.0.4) + version_gem (1.1.8) + webmock (3.25.1) + addressable (>= 2.8.0) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) - yard (0.9.36) + yard (0.9.37) + yard-relative_markdown_links (0.5.0) + nokogiri (>= 1.14.3, < 2) + zeitwerk (2.7.3) PLATFORMS - ruby + x86_64-linux DEPENDENCIES - jruby-openssl (~> 0.9) + appraisal! + benchmark (~> 0.4, >= 0.4.1) + bundler-audit (~> 0.9.2) + kettle-soup-cover (~> 1.0, >= 1.0.6) + kramdown (~> 2.5, >= 2.5.1) + kramdown-parser-gfm (~> 1.1) + logger (~> 1.7) + mutex_m (~> 0.2) omniauth-openid! - rack-test - rake (~> 12.0) - rspec (>= 3.0) - ruby-openid (= 2.1.8)! - simplecov (>= 0.9) - sinatra - webmock (~> 3.0) - yard (>= 0.9.11) + rack-session (>= 1) + rack-test (~> 2.2) + rake (~> 13) + rdoc (~> 6.11) + reek (~> 6.5) + rspec (~> 3) + rspec-block_is_expected (~> 1.0, >= 1.0.6) + rubocop-lts (~> 12.1, >= 12.1.1) + rubocop-packaging (~> 0.6, >= 0.6.0) + rubocop-rspec (~> 3.6) + standard (>= 1.50) + stone_checksums (~> 1.0) + stringio (>= 3.0) + webmock (~> 3.18, >= 3.18.1) + yard (~> 0.9, >= 0.9.37) + yard-junk (~> 0.0, >= 0.0.10)! + yard-relative_markdown_links (~> 0.5.0) BUNDLED WITH - 2.2.5 + 2.6.9 diff --git a/Guardfile b/Guardfile index fbefba2..9ca65f8 100644 --- a/Guardfile +++ b/Guardfile @@ -1,9 +1,8 @@ # A sample Guardfile # More info at https://github.com/guard/guard#readme -guard 'rspec', :version => 2 do +guard "rspec", version: 2 do watch(%r{^spec/.+_spec\.rb$}) - watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" } - watch('spec/spec_helper.rb') { "spec" } + watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" } + watch("spec/spec_helper.rb") { "spec" } end - diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 811fa0e..0000000 --- a/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2010-2011 Michael Bleigh and Intridea, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..d88543b --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,23 @@ +MIT License + +Copyright (c) 2025 Peter H. Boling, and omniauth-openid contributors +Copyright (c) 2010-2011 Michael Bleigh, and Intridea, Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 164163d..97c980b 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,26 @@ -# OmniAuth::OpenID +

+ + Galtzo.com Logo by Aboling0, CC BY-SA 4.0 + + + OmniAuth Logo possibly by Ted O'Meara, license unknown + + + OmniAuth Logo possibly by Ted O'Meara, license unknown + + + Yukihiro Matsumoto, Ruby Visual Identity Team, CC BY-SA 2.5 + +

-[![Liberapay Goal Progress][⛳liberapay-img]][⛳liberapay] [![Sponsor Me on Github][🖇sponsor-img]][🖇sponsor] [![Buy me a coffee][🖇buyme-small-img]][🖇buyme] [![Donate on Polar][🖇polar-img]][🖇polar] [![Donate to my FLOSS or refugee efforts at ko-fi.com][🖇kofi-img]][🖇kofi] [![Donate to my FLOSS or refugee efforts using Patreon][🖇patreon-img]][🖇patreon] +# 🫵 OmniAuth::OpenID + +[![Version][👽versioni]][👽version] [![License: MIT][📄license-img]][📄license-ref] [![Downloads Rank][👽dl-ranki]][👽dl-rank] [![Open Source Helpers][👽oss-helpi]][👽oss-help] [![Depfu][🔑depfui♻️]][🔑depfu] [![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 JRuby][🚎10-j-wfi]][🚎10-j-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] --- + +[![Liberapay Goal Progress][⛳liberapay-img]][⛳liberapay] [![Sponsor Me on Github][🖇sponsor-img]][🖇sponsor] [![Buy me a coffee][🖇buyme-small-img]][🖇buyme] [![Donate on Polar][🖇polar-img]][🖇polar] [![Donate to my FLOSS or refugee efforts at ko-fi.com][🖇kofi-img]][🖇kofi] [![Donate to my FLOSS or refugee efforts using Patreon][🖇patreon-img]][🖇patreon] + [⛳liberapay-img]: https://img.shields.io/liberapay/goal/pboling.svg?logo=liberapay [⛳liberapay]: https://liberapay.com/pboling/donate [🖇sponsor-img]: https://img.shields.io/badge/Sponsor_Me!-pboling.svg?style=social&logo=github @@ -15,38 +33,96 @@ [🖇patreon]: https://patreon.com/galtzo [🖇buyme-small-img]: https://img.shields.io/badge/buy_me_a_coffee-✓-yellow.svg?style=flat -Provides strategies for authenticating to providers using the OpenID v2 standard, which is deprecated, and very old. It is *not* for the modern OpenID Connect standard. If you want OpenID Connect then you want: [omniauth/omniauth_openid_connect](https://github.com/omniauth/omniauth_openid_connect) +Provides strategies for authenticating to providers using the OpenID v2 standard, which is deprecated, and very old. It is *not* for the modern OpenID Connect (OIDC) standard. For OpenID Connect (OIDC) check out: [omniauth/omniauth_openid_connect](https://github.com/omniauth/omniauth_openid_connect) + +| Tokens to Remember | [![Gem name][⛳️name-img]][⛳️gem-name] [![Gem namespace][⛳️namespace-img]][⛳️gem-namespace] | +|-----------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Works with JRuby | [![JRuby 9.2 Compat][💎jruby-9.2i]][🚎10-j-wf] [![JRuby 9.3 Compat][💎jruby-9.3i]][🚎10-j-wf] [![JRuby 9.4 Compat][💎jruby-9.4i]][🚎10-j-wf] [![JRuby 10.0 Compat][💎jruby-c-i]][🚎11-c-wf] [![JRuby HEAD Compat][💎jruby-headi]][🚎3-hd-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.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] | +| Source | [![Source on GitLab.com][📜src-gl-img]][📜src-gl] [![Source on CodeBerg.org][📜src-cb-img]][📜src-cb] [![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] [![BDFL Blog][🚂bdfl-blog-img]][🚂bdfl-blog] [![Wiki][📜wiki-img]][📜wiki] | +| Compliance | [![License: MIT][📄license-img]][📄license-ref] [![📄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] | +| Support | [![Live Chat on Discord][✉️discord-invite-img]][✉️discord-invite] [![Get help from me on Upwork][👨🏼‍🏫expsup-upwork-img]][👨🏼‍🏫expsup-upwork] [![Get help from me on Codementor][👨🏼‍🏫expsup-codementor-img]][👨🏼‍🏫expsup-codementor] | +| Enterprise Support | [![Get help from me on Tidelift][🏙️entsup-tidelift-img]][🏙️entsup-tidelift]
💡Subscribe for support guarantees covering _all_ FLOSS dependencies!
💡Tidelift is part of [Sonar][🏙️entsup-tidelift-sonar]!
💡Tidelift pays maintainers to maintain the software you depend on!
📊`@`Pointy Haired Boss: An [enterprise support][🏙️entsup-tidelift] subscription is "[never gonna let you down][🧮kloc]", and *supports* open source maintainers! | +| Comrade BDFL 🎖️ | [![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 BDFL][🚂bdfl-contact-img]][🚂bdfl-contact] [![My technical writing][💖💁🏼‍♂️devto-img]][💖💁🏼‍♂️devto] | +| `...` 💖 | [![Find Me on WellFound:][💖✌️wellfound-img]][💖✌️wellfound] [![Find Me on CrunchBase][💖💲crunchbase-img]][💖💲crunchbase] [![My LinkTree][💖🌳linktree-img]][💖🌳linktree] [![More About Me][💖💁🏼‍♂️aboutme-img]][💖💁🏼‍♂️aboutme] [🧊][💖🧊berg] [🐙][💖🐙hub] [🛖][💖🛖hut] [🧪][💖🧪lab] | + +## ✨ Installation + +Install the gem and add to the application's Gemfile by executing: + + $ bundle add omniauth-openid + +If bundler is not being used to manage dependencies, install the gem by executing: + + $ gem install omniauth-openid + +### 🔒 Secure Installation + +`omniauth-openid` is cryptographically signed, and has verifiable [SHA-256 and SHA-512][💎SHA_checksums] checksums by +[stone_checksums][💎stone_checksums]. Be sure the gem you install hasn’t been tampered with +by following the instructions below. + +Add my public key (if you haven’t already, expires 2045-04-29) as a trusted certificate: -## Installation +```shell +gem cert --add <(curl -Ls https://raw.github.com/omniauth/omniauth-openid/main/certs/pboling.pem) +``` - gem install omniauth-openid +You only need to do that once. Then proceed to install with: -## Stand-Alone Example +```shell +gem install omniauth-openid -P MediumSecurity +``` + +The `MediumSecurity` trust profile will verify signed gems, but allow the installation of unsigned dependencies. + +This is necessary because not all of `omniauth-openid`’s dependencies are signed, so we cannot use `HighSecurity`. + +If you want to up your security game full-time: + +```shell +bundle config set --global trust-policy MediumSecurity +``` + +NOTE: Be prepared to track down certs for signed gems and add them the same way you added mine. + +## 🔧 Compatibility + +... + +## 🔧 Basic Usage Use the strategy as a middleware in your application: - require 'omniauth-openid' - require 'openid/store/filesystem' +```ruby +require "omniauth-openid" +require "openid/store/filesystem" - use Rack::Session::Cookie - use OmniAuth::Strategies::OpenID, :store => OpenID::Store::Filesystem.new('/tmp') +use Rack::Session::Cookie +use OmniAuth::Strategies::OpenID, store: OpenID::Store::Filesystem.new("/tmp") +``` Then simply direct users to `/auth/open_id` to prompt them for their OpenID identifier. You may also pre-set the identifier by passing an `identifier` parameter to the URL (Example: `/auth/open_id?openid_url=yahoo.com`). A list of all OpenID stores is available at http://github.com/openid/ruby-openid/tree/master/lib/openid/store/ -## OmniAuth Builder +### OmniAuth Builder If OpenID is one of several authentication strategies, use the OmniAuth Builder: - require 'omniauth-openid' - require 'openid/store/filesystem' +```ruby +require "omniauth-openid" +require "openid/store/filesystem" - use OmniAuth::Builder do - provider :open_id, :store => OpenID::Store::Filesystem.new('/tmp') - end +use OmniAuth::Builder do + provider :open_id, store: OpenID::Store::Filesystem.new("/tmp") +end +``` -## Configured Identifiers +### Configured Identifiers You may pre-configure an OpenID identifier. For example, to use Google's main OpenID endpoint: @@ -56,15 +132,112 @@ You may pre-configure an OpenID identifier. For example, to use Google's main O Note the use of nil, which will trigger ruby-openid's default Memory Store. -## License +Please contribute some documentation if you have the gumption! The maintainer's time is limited, and sometimes the authors of PRs with new options don't update the _this_ readme. 😭 + +## 🔐 Security + +See [SECURITY.md][🔐security]. + +## 🤝 Contributing + +If you need some ideas of where to help, you could work on adding more code coverage, +or if it is already 💯 (see [below](#code-coverage)) check [issues][🤝gh-issues], or [PRs][🤝gh-pulls], +or use the gem and think about how it could be better. -Copyright (c) 2011 Michael Bleigh and Intridea, Inc. +We [![Keep A Changelog][📗keep-changelog-img]][📗keep-changelog] so if you make changes, remember to update it. -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +See [CONTRIBUTING.md][🤝contributing] for more detailed instructions. -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +### 🚀 Release Instructions -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +See [CONTRIBUTING.md][🤝contributing]. + +### Code Coverage + +[![Coverage Graph][🔑codecov-g♻️]][🔑codecov] + +### 🪇 Code of Conduct + +Everyone interacting with this project's codebases, issue trackers, +chat rooms and mailing lists agrees to follow the [![Contributor Covenant 2.1][🪇conduct-img]][🪇conduct]. + +## 🌈 Contributors + +[![Contributors][🖐contributors-img]][🖐contributors] + +Made with [contributors-img][🖐contrib-rocks]. + +## ⭐️ Star History + + + + + + Star History Chart + + + +## 📌 Versioning + +This Library adheres to [![Semantic Versioning 2.0.0][📌semver-img]][📌semver]. +Violations of this scheme should be reported as bugs. +Specifically, if a minor or patch version is released that breaks backward compatibility, +a new version should be immediately released that restores compatibility. +Breaking changes to the public API will only be introduced with new major versions. + +### 📌 Is "Platform Support" part of the public API? + +Yes. But I'm obligated to include notes... + +SemVer should, but doesn't explicitly, say that dropping support for specific Platforms +is a *breaking change* to an API. +It is obvious to many, but not all, and since the spec is silent, the bike shedding is endless. + +> dropping support for a platform is both obviously and objectively a breaking change + +- Jordan Harband (@ljharb, maintainer of SemVer) [in SemVer issue 716][📌semver-breaking] + +To get a better understanding of how SemVer is intended to work over a project's lifetime, +read this article from the creator of SemVer: + +- ["Major Version Numbers are Not Sacred"][📌major-versions-not-sacred] + +As a result of this policy, and the interpretive lens used by the maintainer, +you can (and should) specify a dependency on these libraries using +the [Pessimistic Version Constraint][📌pvc] with two digits of precision. + +For example: + +```ruby +spec.add_dependency("omniauth-openid", "~> 3.1") +``` + +See [CHANGELOG.md][📌changelog] for a list of releases. + +## 📄 License + +The gem is available as open source under the terms of +the [MIT License][📄license] [![License: MIT][📄license-img]][📄license-ref]. +See [LICENSE.txt][📄license] for the official [Copyright Notice][📄copyright-notice-explainer]. + +### © Copyright + + ## 🤑 One more thing @@ -79,3 +252,153 @@ or one of the others at the head of this README. [🖇buyme-img]: https://img.buymeacoffee.com/button-api/?text=Buy%20me%20a%20latte&emoji=&slug=pboling&button_colour=FFDD00&font_colour=000000&font_family=Cookie&outline_colour=000000&coffee_colour=ffffff [🖇buyme]: https://www.buymeacoffee.com/pboling + +[✇bundle-group-pattern]: https://gist.github.com/pboling/4564780 +[⛳️gem-namespace]: https://github.com/omniauth/omniauth-openid +[⛳️namespace-img]: https://img.shields.io/badge/namespace-OmniAuth%3A%3AOpenID-brightgreen.svg?style=flat&logo=ruby&logoColor=white +[⛳️gem-name]: https://rubygems.org/gems/omniauth-openid +[⛳️name-img]: https://img.shields.io/badge/name-omniauth--openid-brightgreen.svg?style=flat&logo=rubygems&logoColor=red +[🚂bdfl-blog]: http://www.railsbling.com/tags/omniauth-openid +[🚂bdfl-blog-img]: https://img.shields.io/badge/blog-railsbling-0093D0.svg?style=for-the-badge&logo=rubyonrails&logoColor=orange +[🚂bdfl-contact]: http://www.railsbling.com/contact +[🚂bdfl-contact-img]: https://img.shields.io/badge/Contact-BDFL-0093D0.svg?style=flat&logo=rubyonrails&logoColor=red +[💖🖇linkedin]: http://www.linkedin.com/in/peterboling +[💖🖇linkedin-img]: https://img.shields.io/badge/PeterBoling-LinkedIn-0B66C2?style=flat&logo=newjapanprowrestling +[💖✌️wellfound]: https://angel.co/u/peter-boling +[💖✌️wellfound-img]: https://img.shields.io/badge/peter--boling-orange?style=flat&logo=wellfound +[💖💲crunchbase]: https://www.crunchbase.com/person/peter-boling +[💖💲crunchbase-img]: https://img.shields.io/badge/peter--boling-purple?style=flat&logo=crunchbase +[💖🐘ruby-mast]: https://ruby.social/@galtzo +[💖🐘ruby-mast-img]: https://img.shields.io/mastodon/follow/109447111526622197?domain=https%3A%2F%2Fruby.social&style=flat&logo=mastodon&label=Ruby%20%40galtzo +[💖🦋bluesky]: https://bsky.app/profile/galtzo.com +[💖🦋bluesky-img]: https://img.shields.io/badge/@galtzo.com-0285FF?style=flat&logo=bluesky&logoColor=white +[💖🌳linktree]: https://linktr.ee/galtzo +[💖🌳linktree-img]: https://img.shields.io/badge/galtzo-purple?style=flat&logo=linktree +[💖💁🏼‍♂️devto]: https://dev.to/galtzo +[💖💁🏼‍♂️devto-img]: https://img.shields.io/badge/dev.to-0A0A0A?style=flat&logo=devdotto&logoColor=white +[💖💁🏼‍♂️aboutme]: https://about.me/peter.boling +[💖💁🏼‍♂️aboutme-img]: https://img.shields.io/badge/about.me-0A0A0A?style=flat&logo=aboutme&logoColor=white +[💖🧊berg]: https://codeberg.org/pboling +[💖🐙hub]: https://github.org/pboling +[💖🛖hut]: https://sr.ht/~galtzo/ +[💖🧪lab]: https://gitlab.com/pboling +[👨🏼‍🏫expsup-upwork]: https://www.upwork.com/freelancers/~014942e9b056abdf86?mp_source=share +[👨🏼‍🏫expsup-upwork-img]: https://img.shields.io/badge/UpWork-13544E?style=for-the-badge&logo=Upwork&logoColor=white +[👨🏼‍🏫expsup-codementor]: https://www.codementor.io/peterboling?utm_source=github&utm_medium=button&utm_term=peterboling&utm_campaign=github +[👨🏼‍🏫expsup-codementor-img]: https://img.shields.io/badge/CodeMentor-Get_Help-1abc9c?style=for-the-badge&logo=CodeMentor&logoColor=white +[🏙️entsup-tidelift]: https://tidelift.com/subscription +[🏙️entsup-tidelift-img]: https://img.shields.io/badge/Tidelift_and_Sonar-Enterprise_Support-FD3456?style=for-the-badge&logo=sonar&logoColor=white +[🏙️entsup-tidelift-sonar]: https://blog.tidelift.com/tidelift-joins-sonar +[💁🏼‍♂️peterboling]: http://www.peterboling.com +[🚂railsbling]: http://www.railsbling.com +[📜src-gl-img]: https://img.shields.io/badge/GitLab-FBA326?style=for-the-badge&logo=Gitlab&logoColor=orange +[📜src-gl]: https://gitlab.com/omniauth/omniauth-openid/ +[📜src-cb-img]: https://img.shields.io/badge/CodeBerg-4893CC?style=for-the-badge&logo=CodeBerg&logoColor=blue +[📜src-cb]: https://codeberg.org/omniauth/omniauth-openid +[📜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-openid +[📜docs-cr-rd-img]: https://img.shields.io/badge/RubyDoc-Current_Release-943CD2?style=for-the-badge&logo=readthedocs&logoColor=white +[📜docs-head-rd-img]: https://img.shields.io/badge/YARD_on_Galtzo.com-HEAD-943CD2?style=for-the-badge&logo=readthedocs&logoColor=white +[📜wiki]: https://github.com/omniauth/omniauth-openid/wiki +[📜wiki-img]: https://img.shields.io/badge/wiki-examples-943CD2.svg?style=for-the-badge&logo=Wiki&logoColor=white +[👽dl-rank]: https://rubygems.org/gems/omniauth-openid +[👽dl-ranki]: https://img.shields.io/gem/rd/omniauth-openid.svg +[👽oss-help]: https://www.codetriage.com/omniauth/omniauth-openid +[👽oss-helpi]: https://www.codetriage.com/omniauth/omniauth-openid/badges/users.svg +[👽version]: https://rubygems.org/gems/omniauth-openid +[👽versioni]: https://img.shields.io/gem/v/omniauth-openid.svg +[🔑qlty-mnt]: https://qlty.sh/gh/omniauth/projects/omniauth-openid +[🔑qlty-mnti♻️]: https://qlty.sh/badges/c2eb0211-c105-4fc6-9b36-650307c67e06/maintainability.svg +[🔑qlty-cov]: https://qlty.sh/gh/omniauth/projects/omniauth-openid +[🔑qlty-covi♻️]: https://qlty.sh/badges/c2eb0211-c105-4fc6-9b36-650307c67e06/test_coverage.svg +[🔑codecov]: https://codecov.io/gh/omniauth/omniauth-openid +[🔑codecovi♻️]: https://codecov.io/gh/omniauth/omniauth-openid/branch/main/graph/badge.svg?token=cc6UdZCpAL +[🔑coveralls]: https://coveralls.io/github/omniauth/omniauth-openid?branch=main +[🔑coveralls-img]: https://coveralls.io/repos/github/omniauth/omniauth-openid/badge.svg?branch=main +[🔑depfu]: https://depfu.com/github/omniauth/omniauth-openid?project_id=22381 +[🔑depfui♻️]: https://badges.depfu.com/badges/6c9b45362951b872127f9e46d39bed76/count.svg +[🖐codeQL]: https://github.com/omniauth/omniauth-openid/security/code-scanning +[🖐codeQL-img]: https://github.com/omniauth/omniauth-openid/actions/workflows/codeql-analysis.yml/badge.svg +[🚎1-an-wf]: https://github.com/omniauth/omniauth-openid/actions/workflows/ancient.yml +[🚎1-an-wfi]: https://github.com/omniauth/omniauth-openid/actions/workflows/ancient.yml/badge.svg +[🚎2-cov-wf]: https://github.com/omniauth/omniauth-openid/actions/workflows/coverage.yml +[🚎2-cov-wfi]: https://github.com/omniauth/omniauth-openid/actions/workflows/coverage.yml/badge.svg +[🚎3-hd-wf]: https://github.com/omniauth/omniauth-openid/actions/workflows/heads.yml +[🚎3-hd-wfi]: https://github.com/omniauth/omniauth-openid/actions/workflows/heads.yml/badge.svg +[🚎4-lg-wf]: https://github.com/omniauth/omniauth-openid/actions/workflows/legacy.yml +[🚎4-lg-wfi]: https://github.com/omniauth/omniauth-openid/actions/workflows/legacy.yml/badge.svg +[🚎5-st-wf]: https://github.com/omniauth/omniauth-openid/actions/workflows/style.yml +[🚎5-st-wfi]: https://github.com/omniauth/omniauth-openid/actions/workflows/style.yml/badge.svg +[🚎6-s-wf]: https://github.com/omniauth/omniauth-openid/actions/workflows/supported.yml +[🚎6-s-wfi]: https://github.com/omniauth/omniauth-openid/actions/workflows/supported.yml/badge.svg +[🚎7-us-wf]: https://github.com/omniauth/omniauth-openid/actions/workflows/unsupported.yml +[🚎7-us-wfi]: https://github.com/omniauth/omniauth-openid/actions/workflows/unsupported.yml/badge.svg +[🚎8-ho-wf]: https://github.com/omniauth/omniauth-openid/actions/workflows/hoary.yml +[🚎8-ho-wfi]: https://github.com/omniauth/omniauth-openid/actions/workflows/hoary.yml/badge.svg +[🚎9-t-wf]: https://github.com/omniauth/omniauth-openid/actions/workflows/truffle.yml +[🚎9-t-wfi]: https://github.com/omniauth/omniauth-openid/actions/workflows/truffle.yml/badge.svg +[🚎10-j-wf]: https://github.com/omniauth/omniauth-openid/actions/workflows/jruby.yml +[🚎10-j-wfi]: https://github.com/omniauth/omniauth-openid/actions/workflows/jruby.yml/badge.svg +[🚎11-c-wf]: https://github.com/omniauth/omniauth-openid/actions/workflows/current.yml +[🚎11-c-wfi]: https://github.com/omniauth/omniauth-openid/actions/workflows/current.yml/badge.svg +[🚎12-crh-wf]: https://github.com/omniauth/omniauth-openid/actions/workflows/current-runtime-heads.yml +[🚎12-crh-wfi]: https://github.com/omniauth/omniauth-openid/actions/workflows/current-runtime-heads.yml/badge.svg +[💎ruby-2.3i]: https://img.shields.io/badge/Ruby-2.3-DF00CA?style=for-the-badge&logo=ruby&logoColor=white +[💎ruby-2.4i]: https://img.shields.io/badge/Ruby-2.4-DF00CA?style=for-the-badge&logo=ruby&logoColor=white +[💎ruby-2.5i]: https://img.shields.io/badge/Ruby-2.5-DF00CA?style=for-the-badge&logo=ruby&logoColor=white +[💎ruby-2.6i]: https://img.shields.io/badge/Ruby-2.6-DF00CA?style=for-the-badge&logo=ruby&logoColor=white +[💎ruby-2.7i]: https://img.shields.io/badge/Ruby-2.7-DF00CA?style=for-the-badge&logo=ruby&logoColor=white +[💎ruby-3.0i]: https://img.shields.io/badge/Ruby-3.0-CC342D?style=for-the-badge&logo=ruby&logoColor=white +[💎ruby-3.1i]: https://img.shields.io/badge/Ruby-3.1-CC342D?style=for-the-badge&logo=ruby&logoColor=white +[💎ruby-3.2i]: https://img.shields.io/badge/Ruby-3.2-CC342D?style=for-the-badge&logo=ruby&logoColor=white +[💎ruby-3.3i]: https://img.shields.io/badge/Ruby-3.3-CC342D?style=for-the-badge&logo=ruby&logoColor=white +[💎ruby-c-i]: https://img.shields.io/badge/Ruby-current-CC342D?style=for-the-badge&logo=ruby&logoColor=green +[💎ruby-headi]: https://img.shields.io/badge/Ruby-HEAD-CC342D?style=for-the-badge&logo=ruby&logoColor=blue +[💎truby-22.3i]: https://img.shields.io/badge/Truffle_Ruby-22.3-34BCB1?style=for-the-badge&logo=ruby&logoColor=pink +[💎truby-23.0i]: https://img.shields.io/badge/Truffle_Ruby-23.0-34BCB1?style=for-the-badge&logo=ruby&logoColor=pink +[💎truby-23.1i]: https://img.shields.io/badge/Truffle_Ruby-23.1-34BCB1?style=for-the-badge&logo=ruby&logoColor=pink +[💎truby-c-i]: https://img.shields.io/badge/Truffle_Ruby-current-34BCB1?style=for-the-badge&logo=ruby&logoColor=green +[💎truby-headi]: https://img.shields.io/badge/Truffle_Ruby-HEAD-34BCB1?style=for-the-badge&logo=ruby&logoColor=blue +[💎jruby-9.2i]: https://img.shields.io/badge/JRuby-9.2-FBE742?style=for-the-badge&logo=ruby&logoColor=red +[💎jruby-9.3i]: https://img.shields.io/badge/JRuby-9.3-FBE742?style=for-the-badge&logo=ruby&logoColor=red +[💎jruby-9.4i]: https://img.shields.io/badge/JRuby-9.4-FBE742?style=for-the-badge&logo=ruby&logoColor=red +[💎jruby-c-i]: https://img.shields.io/badge/JRuby-current-FBE742?style=for-the-badge&logo=ruby&logoColor=green +[💎jruby-headi]: https://img.shields.io/badge/JRuby-HEAD-FBE742?style=for-the-badge&logo=ruby&logoColor=blue +[🤝gh-issues]: https://github.com/omniauth/omniauth-openid/issues +[🤝gh-pulls]: https://github.com/omniauth/omniauth-openid/pulls +[🤝contributing]: CONTRIBUTING.md +[🔑codecov-g♻️]: https://codecov.io/gh/omniauth/omniauth-openid/graphs/tree.svg?token=cc6UdZCpAL +[🖐contrib-rocks]: https://contrib.rocks +[🖐contributors]: https://github.com/omniauth/omniauth-openid/graphs/contributors +[🖐contributors-img]: https://contrib.rocks/image?repo=omniauth/omniauth-openid +[🚎contributors-gl]: https://gitlab.com/omniauth/omniauth-openid/-/graphs/main +[🪇conduct]: CODE_OF_CONDUCT.md +[🪇conduct-img]: https://img.shields.io/badge/Contributor_Covenant-2.1-259D6C.svg +[📌pvc]: http://guides.rubygems.org/patterns/#pessimistic-version-constraint +[📌semver]: https://semver.org/spec/v2.0.0.html +[📌semver-img]: https://img.shields.io/badge/semver-2.0.0-259D6C.svg?style=flat +[📌semver-breaking]: https://github.com/semver/semver/issues/716#issuecomment-869336139 +[📌major-versions-not-sacred]: https://tom.preston-werner.com/2022/05/23/major-version-numbers-are-not-sacred.html +[📌changelog]: CHANGELOG.md +[📗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😜%20😍-34495e.svg?style=flat-square +[🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ +[🧮kloc-img]: https://img.shields.io/badge/KLOC-0.378-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue +[🔐security]: SECURITY.md +[🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat +[📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year +[📄license]: LICENSE.txt +[📄license-ref]: https://opensource.org/licenses/MIT +[📄license-img]: https://img.shields.io/badge/License-MIT-259D6C.svg +[📄ilo-declaration]: https://www.ilo.org/declaration/lang--en/index.htm +[📄ilo-declaration-img]: https://img.shields.io/badge/ILO_Fundamental_Principles-✓-259D6C.svg?style=flat +[🚎yard-current]: http://rubydoc.info/gems/omniauth-openid +[🚎yard-head]: https://omniauth-openid.galtzo.com +[💎stone_checksums]: https://github.com/pboling/stone_checksums +[💎SHA_checksums]: https://github.com/omniauth/omniauth-openid/tree/main/checksums +[💎rlts]: https://github.com/rubocop-lts/rubocop-lts +[💎rlts-img]: https://img.shields.io/badge/code_style_%26_linting-rubocop--lts-34495e.svg?plastic&logo=ruby&logoColor=white +[✉️discord-invite]: https://discord.gg/3qme4XHNKN +[✉️discord-invite-img]: https://img.shields.io/discord/1373797679469170758?style=for-the-badge diff --git a/REEK b/REEK new file mode 100644 index 0000000..36afd00 --- /dev/null +++ b/REEK @@ -0,0 +1,36 @@ +lib/omniauth/openid/version.rb -- 1 warning: + [2]:IrresponsibleModule: OmniAuth::OpenID has no descriptive comment [https://github.com/troessner/reek/blob/v6.5.0/docs/Irresponsible-Module.md] +lib/omniauth/strategies/open_id.rb -- 28 warnings: + [129, 129]:DuplicateMethodCall: OmniAuth::Strategies::OpenID#ax_user_info calls 'AX[:city]' 2 times [https://github.com/troessner/reek/blob/v6.5.0/docs/Duplicate-Method-Call.md] + [126, 128]:DuplicateMethodCall: OmniAuth::Strategies::OpenID#ax_user_info calls 'AX[:first_name]' 2 times [https://github.com/troessner/reek/blob/v6.5.0/docs/Duplicate-Method-Call.md] + [127, 128]:DuplicateMethodCall: OmniAuth::Strategies::OpenID#ax_user_info calls 'AX[:last_name]' 2 times [https://github.com/troessner/reek/blob/v6.5.0/docs/Duplicate-Method-Call.md] + [129, 129]:DuplicateMethodCall: OmniAuth::Strategies::OpenID#ax_user_info calls 'AX[:state]' 2 times [https://github.com/troessner/reek/blob/v6.5.0/docs/Duplicate-Method-Call.md] + [131, 131]:DuplicateMethodCall: OmniAuth::Strategies::OpenID#ax_user_info calls 'AX[:website]' 2 times [https://github.com/troessner/reek/blob/v6.5.0/docs/Duplicate-Method-Call.md] + [131, 131]:DuplicateMethodCall: OmniAuth::Strategies::OpenID#ax_user_info calls 'Array(ax.get_single(AX[:website]))' 2 times [https://github.com/troessner/reek/blob/v6.5.0/docs/Duplicate-Method-Call.md] + [129, 129]:DuplicateMethodCall: OmniAuth::Strategies::OpenID#ax_user_info calls 'ax.get_single(AX[:city])' 2 times [https://github.com/troessner/reek/blob/v6.5.0/docs/Duplicate-Method-Call.md] + [126, 128]:DuplicateMethodCall: OmniAuth::Strategies::OpenID#ax_user_info calls 'ax.get_single(AX[:first_name])' 2 times [https://github.com/troessner/reek/blob/v6.5.0/docs/Duplicate-Method-Call.md] + [127, 128]:DuplicateMethodCall: OmniAuth::Strategies::OpenID#ax_user_info calls 'ax.get_single(AX[:last_name])' 2 times [https://github.com/troessner/reek/blob/v6.5.0/docs/Duplicate-Method-Call.md] + [129, 129]:DuplicateMethodCall: OmniAuth::Strategies::OpenID#ax_user_info calls 'ax.get_single(AX[:state])' 2 times [https://github.com/troessner/reek/blob/v6.5.0/docs/Duplicate-Method-Call.md] + [131, 131]:DuplicateMethodCall: OmniAuth::Strategies::OpenID#ax_user_info calls 'ax.get_single(AX[:website])' 2 times [https://github.com/troessner/reek/blob/v6.5.0/docs/Duplicate-Method-Call.md] + [45, 50]:DuplicateMethodCall: OmniAuth::Strategies::OpenID#dummy_app calls 'options.trust_root' 2 times [https://github.com/troessner/reek/blob/v6.5.0/docs/Duplicate-Method-Call.md] + [81, 82]:DuplicateMethodCall: OmniAuth::Strategies::OpenID#get_identifier calls 'options.identifier_param' 2 times [https://github.com/troessner/reek/blob/v6.5.0/docs/Duplicate-Method-Call.md] + [125, 126, 127, 128, 128, 128, 129, 129, 129, 129, 130, 131, 131]:FeatureEnvy: OmniAuth::Strategies::OpenID#ax_user_info refers to 'ax' more than self (maybe move it to another class?) [https://github.com/troessner/reek/blob/v6.5.0/docs/Feature-Envy.md] + [81, 82, 83]:FeatureEnvy: OmniAuth::Strategies::OpenID#get_identifier refers to 'f' more than self (maybe move it to another class?) [https://github.com/troessner/reek/blob/v6.5.0/docs/Feature-Envy.md] + [114, 115, 116, 117]:FeatureEnvy: OmniAuth::Strategies::OpenID#sreg_user_info refers to 'sreg' more than self (maybe move it to another class?) [https://github.com/troessner/reek/blob/v6.5.0/docs/Feature-Envy.md] + [9]:InstanceVariableAssumption: OmniAuth::Strategies::OpenID assumes too much for instance variable '@openid_response' [https://github.com/troessner/reek/blob/v6.5.0/docs/Instance-Variable-Assumption.md] + [45]:NestedIterators: OmniAuth::Strategies::OpenID#dummy_app contains iterators nested 2 deep [https://github.com/troessner/reek/blob/v6.5.0/docs/Nested-Iterators.md] + [134]:NilCheck: OmniAuth::Strategies::OpenID#ax_user_info performs a nil-check [https://github.com/troessner/reek/blob/v6.5.0/docs/Nil-Check.md] + [118]:NilCheck: OmniAuth::Strategies::OpenID#sreg_user_info performs a nil-check [https://github.com/troessner/reek/blob/v6.5.0/docs/Nil-Check.md] + [132]:UncommunicativeVariableName: OmniAuth::Strategies::OpenID#ax_user_info has the variable name 'h' [https://github.com/troessner/reek/blob/v6.5.0/docs/Uncommunicative-Variable-Name.md] + [132, 134]:UncommunicativeVariableName: OmniAuth::Strategies::OpenID#ax_user_info has the variable name 'k' [https://github.com/troessner/reek/blob/v6.5.0/docs/Uncommunicative-Variable-Name.md] + [132, 134]:UncommunicativeVariableName: OmniAuth::Strategies::OpenID#ax_user_info has the variable name 'v' [https://github.com/troessner/reek/blob/v6.5.0/docs/Uncommunicative-Variable-Name.md] + [45]:UncommunicativeVariableName: OmniAuth::Strategies::OpenID#dummy_app has the variable name 'm' [https://github.com/troessner/reek/blob/v6.5.0/docs/Uncommunicative-Variable-Name.md] + [80]:UncommunicativeVariableName: OmniAuth::Strategies::OpenID#get_identifier has the variable name 'f' [https://github.com/troessner/reek/blob/v6.5.0/docs/Uncommunicative-Variable-Name.md] + [59, 60]:UncommunicativeVariableName: OmniAuth::Strategies::OpenID#identifier has the variable name 'i' [https://github.com/troessner/reek/blob/v6.5.0/docs/Uncommunicative-Variable-Name.md] + [118]:UncommunicativeVariableName: OmniAuth::Strategies::OpenID#sreg_user_info has the variable name 'k' [https://github.com/troessner/reek/blob/v6.5.0/docs/Uncommunicative-Variable-Name.md] + [118]:UncommunicativeVariableName: OmniAuth::Strategies::OpenID#sreg_user_info has the variable name 'v' [https://github.com/troessner/reek/blob/v6.5.0/docs/Uncommunicative-Variable-Name.md] +spec/omniauth/strategies/open_id_spec.rb -- 1 warning: + [2]:TooManyStatements: app has approx 6 statements [https://github.com/troessner/reek/blob/v6.5.0/docs/Too-Many-Statements.md] +.yard_gfm_support.rb -- 1 warning: + [9, 9]:FeatureEnvy: KramdownGfmDocument#initialize refers to 'options' more than self (maybe move it to another class?) [https://github.com/troessner/reek/blob/v6.5.0/docs/Feature-Envy.md] +31 total warnings diff --git a/Rakefile b/Rakefile index 69797fc..ef7c4a1 100644 --- a/Rakefile +++ b/Rakefile @@ -1,6 +1,126 @@ -require 'bundler' -Bundler::GemHelper.install_tasks -require 'rspec/core/rake_task' -RSpec::Core::RakeTask.new(:spec) -task :default => :spec -task :test => :spec +# frozen_string_literal: true + +require "bundler/gem_tasks" + +defaults = [] + +# See: https://docs.gitlab.com/ci/variables/predefined_variables/ +is_gitlab = ENV.fetch("GITLAB_CI", "false").casecmp("true") == 0 + +### DEVELOPMENT TASKS +# Setup Kettle Soup Cover +begin + require "kettle-soup-cover" + + Kettle::Soup::Cover.install_tasks + # NOTE: Coverage on CI is configured independent of this task. + # This task is for local development, as it opens results in browser + defaults << "coverage" unless Kettle::Soup::Cover::IS_CI +rescue LoadError + desc("(stub) coverage is unavailable") + task("coverage") do + warn("NOTE: kettle-soup-cover isn't installed, or is disabled for #{RUBY_VERSION} in the current environment") + end +end + +# Setup Bundle Audit +begin + require "bundler/audit/task" + + Bundler::Audit::Task.new + defaults.push("bundle:audit:update", "bundle:audit") +rescue LoadError + desc("(stub) bundle:audit is unavailable") + task("bundle:audit") do + warn("NOTE: bundler-audit isn't installed, or is disabled for #{RUBY_VERSION} in the current environment") + end + desc("(stub) bundle:audit:update is unavailable") + task("bundle:audit:update") do + warn("NOTE: bundler-audit isn't installed, or is disabled for #{RUBY_VERSION} in the current environment") + end +end + +# Setup RSpec +begin + require "rspec/core/rake_task" + + RSpec::Core::RakeTask.new(:spec) + defaults << "spec" +rescue LoadError + desc("spec task stub") + task(:spec) do + warn("NOTE: rspec isn't installed, or is disabled for #{RUBY_VERSION} in the current environment") + end +end + +desc "spec is a pre-requisite of test task" +task test: :spec + +# Setup RuboCop-LTS +begin + require "rubocop/lts" + + Rubocop::Lts.install_tasks + # Make autocorrect the default rubocop task + defaults << "rubocop_gradual:autocorrect" +rescue LoadError + desc("(stub) rubocop_gradual is unavailable") + task(:rubocop_gradual) do + warn("NOTE: rubocop-lts isn't installed, or is disabled for #{RUBY_VERSION} in the current environment") + end +end + +# Setup Yard +begin + require "yard" + + YARD::Rake::YardocTask.new(:yard) do |t| + t.files = [ + # Source Splats (alphabetical) + "lib/**/*.rb", + "-", # source and extra docs are separated by "-" + # Extra Files (alphabetical) + "*.cff", + "*.md", + "*.txt", + ] + end + defaults << "yard" +rescue LoadError + desc("(stub) yard is unavailable") + task(:yard) do + warn("NOTE: yard isn't installed, or is disabled for #{RUBY_VERSION} in the current environment") + end +end + +# Setup Reek +begin + require "reek/rake/task" + + Reek::Rake::Task.new do |t| + t.fail_on_error = true + t.verbose = false + t.source_files = "{lib,spec,spec_ignored,spec_orms}/**/*.rb" + end + defaults << "reek" unless is_gitlab +rescue LoadError + desc("(stub) reek is unavailable") + task(:reek) do + warn("NOTE: reek isn't installed, or is disabled for #{RUBY_VERSION} in the current environment") + end +end + +### RELEASE TASKS +# Setup stone_checksums +begin + require "stone_checksums" + + GemChecksums.install_tasks +rescue LoadError + desc("(stub) build:generate_checksums is unavailable") + task("build:generate_checksums") do + warn("NOTE: stone_checksums isn't installed, or is disabled for #{RUBY_VERSION} in the current environment") + end +end + +task default: defaults diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..c3d3cee --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,30 @@ +# Security Policy + +## Supported Versions + +| Version | Supported | +|---------|-----------| +| 2.x | ✅ | +| 1.x | ❌ | + +## Security contact information + +To report a security vulnerability, please use the +[Tidelift security contact](https://tidelift.com/security). +Tidelift will coordinate the fix and disclosure. + +## Additional Support + +If you are interested in support for versions older than the latest release, +please consider sponsoring the project / maintainer @ https://liberapay.com/pboling/donate, +or find other sponsorship links in the [README]. + +[README]: README.md + +## Enterprise Support + +Available as part of the Tidelift Subscription. + +The maintainers of this library and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source packages you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers for the exact packages you use. [Learn more.][tidelift-ref] + +[tidelift-ref]: https://tidelift.com/subscription/pkg/rubygems-omniauth-openid?utm_source=rubygems-omniauth-openid&utm_medium=referral&utm_campaign=enterprise&utm_term=repo \ No newline at end of file diff --git a/bin/bundle b/bin/bundle new file mode 100755 index 0000000..71881c3 --- /dev/null +++ b/bin/bundle @@ -0,0 +1,109 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'bundle' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "rubygems" + +m = Module.new do + module_function + + def invoked_as_script? + File.expand_path($0) == File.expand_path(__FILE__) + end + + def env_var_version + ENV["BUNDLER_VERSION"] + end + + def cli_arg_version + return unless invoked_as_script? # don't want to hijack other binstubs + return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update` + bundler_version = nil + update_index = nil + ARGV.each_with_index do |a, i| + if update_index && update_index.succ == i && a.match?(Gem::Version::ANCHORED_VERSION_PATTERN) + bundler_version = a + end + next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/o + bundler_version = $1 + update_index = i + end + bundler_version + end + + def gemfile + gemfile = ENV["BUNDLE_GEMFILE"] + return gemfile if gemfile && !gemfile.empty? + + File.expand_path("../Gemfile", __dir__) + end + + def lockfile + lockfile = + case File.basename(gemfile) + when "gems.rb" then gemfile.sub(/\.rb$/, ".locked") + else "#{gemfile}.lock" + end + File.expand_path(lockfile) + end + + def lockfile_version + return unless File.file?(lockfile) + lockfile_contents = File.read(lockfile) + return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/o + Regexp.last_match(1) + end + + def bundler_requirement + @bundler_requirement ||= + env_var_version || + cli_arg_version || + bundler_requirement_for(lockfile_version) + end + + def bundler_requirement_for(version) + return "#{Gem::Requirement.default}.a" unless version + + bundler_gem_version = Gem::Version.new(version) + + bundler_gem_version.approximate_recommendation + end + + def load_bundler! + ENV["BUNDLE_GEMFILE"] ||= gemfile + + activate_bundler + end + + def activate_bundler + gem_error = activation_error_handling do + gem("bundler", bundler_requirement) + end + return if gem_error.nil? + require_error = activation_error_handling do + require "bundler/version" + end + return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION)) + warn("Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`") + exit(42) + end + + def activation_error_handling + yield + nil + rescue StandardError, LoadError => e + e + end +end + +m.load_bundler! + +if m.invoked_as_script? + load Gem.bin_path("bundler", "bundle") +end diff --git a/bin/gem_checksums b/bin/gem_checksums new file mode 100755 index 0000000..45a1d2a --- /dev/null +++ b/bin/gem_checksums @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'gem_checksums' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("stone_checksums", "gem_checksums") diff --git a/bin/htmldiff b/bin/htmldiff new file mode 100755 index 0000000..0aeaec8 --- /dev/null +++ b/bin/htmldiff @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'htmldiff' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("diff-lcs", "htmldiff") diff --git a/bin/ldiff b/bin/ldiff new file mode 100755 index 0000000..8173ede --- /dev/null +++ b/bin/ldiff @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'ldiff' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("diff-lcs", "ldiff") diff --git a/bin/rackup b/bin/rackup new file mode 100755 index 0000000..0af6faf --- /dev/null +++ b/bin/rackup @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'rackup' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("rack", "rackup") diff --git a/bin/rake b/bin/rake new file mode 100755 index 0000000..4eb7d7b --- /dev/null +++ b/bin/rake @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'rake' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("rake", "rake") diff --git a/bin/rspec b/bin/rspec new file mode 100755 index 0000000..cb53ebe --- /dev/null +++ b/bin/rspec @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'rspec' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("rspec-core", "rspec") diff --git a/certs/pboling.pem b/certs/pboling.pem new file mode 100644 index 0000000..d5c7e8b --- /dev/null +++ b/certs/pboling.pem @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE----- +MIIEgDCCAuigAwIBAgIBATANBgkqhkiG9w0BAQsFADBDMRUwEwYDVQQDDAxwZXRl +ci5ib2xpbmcxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkW +A2NvbTAeFw0yNTA1MDQxNTMzMDlaFw00NTA0MjkxNTMzMDlaMEMxFTATBgNVBAMM +DHBldGVyLmJvbGluZzEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPy +LGQBGRYDY29tMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAruUoo0WA +uoNuq6puKWYeRYiZekz/nsDeK5x/0IEirzcCEvaHr3Bmz7rjo1I6On3gGKmiZs61 +LRmQ3oxy77ydmkGTXBjruJB+pQEn7UfLSgQ0xa1/X3kdBZt6RmabFlBxnHkoaGY5 +mZuZ5+Z7walmv6sFD9ajhzj+oIgwWfnEHkXYTR8I6VLN7MRRKGMPoZ/yvOmxb2DN +coEEHWKO9CvgYpW7asIihl/9GMpKiRkcYPm9dGQzZc6uTwom1COfW0+ZOFrDVBuV +FMQRPswZcY4Wlq0uEBLPU7hxnCL9nKK6Y9IhdDcz1mY6HZ91WImNslOSI0S8hRpj +yGOWxQIhBT3fqCBlRIqFQBudrnD9jSNpSGsFvbEijd5ns7Z9ZMehXkXDycpGAUj1 +to/5cuTWWw1JqUWrKJYoifnVhtE1o1DZ+LkPtWxHtz5kjDG/zR3MG0Ula0UOavlD +qbnbcXPBnwXtTFeZ3C+yrWpE4pGnl3yGkZj9SMTlo9qnTMiPmuWKQDatAgMBAAGj +fzB9MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBQE8uWvNbPVNRXZ +HlgPbc2PCzC4bjAhBgNVHREEGjAYgRZwZXRlci5ib2xpbmdAZ21haWwuY29tMCEG +A1UdEgQaMBiBFnBldGVyLmJvbGluZ0BnbWFpbC5jb20wDQYJKoZIhvcNAQELBQAD +ggGBAJbnUwfJQFPkBgH9cL7hoBfRtmWiCvdqdjeTmi04u8zVNCUox0A4gT982DE9 +wmuN12LpdajxZONqbXuzZvc+nb0StFwmFYZG6iDwaf4BPywm2e/Vmq0YG45vZXGR +L8yMDSK1cQXjmA+ZBKOHKWavxP6Vp7lWvjAhz8RFwqF9GuNIdhv9NpnCAWcMZtpm +GUPyIWw/Cw/2wZp74QzZj6Npx+LdXoLTF1HMSJXZ7/pkxLCsB8m4EFVdb/IrW/0k +kNSfjtAfBHO8nLGuqQZVH9IBD1i9K6aSs7pT6TW8itXUIlkIUI2tg5YzW6OFfPzq +QekSkX3lZfY+HTSp/o+YvKkqWLUV7PQ7xh1ZYDtocpaHwgxe/j3bBqHE+CUPH2vA +0V/FwdTRWcwsjVoOJTrYcff8pBZ8r2MvtAc54xfnnhGFzeRHfcltobgFxkAXdE6p +DVjBtqT23eugOqQ73umLcYDZkc36vnqGxUBSsXrzY9pzV5gGr2I8YUxMqf6ATrZt +L9nRqA== +-----END CERTIFICATE----- diff --git a/.gemtest b/docs/.nojekyll similarity index 100% rename from .gemtest rename to docs/.nojekyll diff --git a/docs/OmniAuth.html b/docs/OmniAuth.html new file mode 100644 index 0000000..8014019 --- /dev/null +++ b/docs/OmniAuth.html @@ -0,0 +1,117 @@ + + + + + + + Module: OmniAuth + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
+ + +

Module: OmniAuth + + + +

+
+ + + + + + + + + + + +
+
Defined in:
+
lib/omniauth/openid/version.rb,
+ lib/omniauth/strategies/open_id.rb
+
+
+ +
+ +

Defined Under Namespace

+

+ + + Modules: OpenID, Strategies + + + + +

+ + + + + + + + + +
+ + + +
+ + \ No newline at end of file diff --git a/docs/OmniAuth/OpenID.html b/docs/OmniAuth/OpenID.html new file mode 100644 index 0000000..82d2806 --- /dev/null +++ b/docs/OmniAuth/OpenID.html @@ -0,0 +1,132 @@ + + + + + + + Module: OmniAuth::OpenID + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
+ + +

Module: OmniAuth::OpenID + + + +

+
+ + + + + + +
+
Includes:
+
Version
+
+ + + + + + +
+
Defined in:
+
lib/omniauth/openid/version.rb
+
+ +
+ +

Defined Under Namespace

+

+ + + Modules: Version + + + + +

+ + + +

Constant Summary

+ +

Constants included + from Version

+

Version::VERSION

+ + + + + + + + + + + + + +
+ + + +
+ + \ No newline at end of file diff --git a/docs/OmniAuth/OpenID/Version.html b/docs/OmniAuth/OpenID/Version.html new file mode 100644 index 0000000..fbe9ab1 --- /dev/null +++ b/docs/OmniAuth/OpenID/Version.html @@ -0,0 +1,126 @@ + + + + + + + Module: OmniAuth::OpenID::Version + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
+ + +

Module: OmniAuth::OpenID::Version + + + +

+
+ + + + + + + + + +
+
Included in:
+
OmniAuth::OpenID
+
+ + + +
+
Defined in:
+
lib/omniauth/openid/version.rb
+
+ +
+ + + +

+ Constant Summary + collapse +

+ +
+ +
VERSION = + +
+
"2.0.2"
+ +
+ + + + + + + + + + +
+ + + +
+ + \ No newline at end of file diff --git a/docs/OmniAuth/Strategies.html b/docs/OmniAuth/Strategies.html new file mode 100644 index 0000000..28901bf --- /dev/null +++ b/docs/OmniAuth/Strategies.html @@ -0,0 +1,115 @@ + + + + + + + Module: OmniAuth::Strategies + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
+ + +

Module: OmniAuth::Strategies + + + +

+
+ + + + + + + + + + + +
+
Defined in:
+
lib/omniauth/strategies/open_id.rb
+
+ +
+ +

Defined Under Namespace

+

+ + + + + Classes: OpenID + + +

+ + + + + + + + + +
+ + + +
+ + \ No newline at end of file diff --git a/docs/OmniAuth/Strategies/OpenID.html b/docs/OmniAuth/Strategies/OpenID.html new file mode 100644 index 0000000..6c37deb --- /dev/null +++ b/docs/OmniAuth/Strategies/OpenID.html @@ -0,0 +1,772 @@ + + + + + + + Class: OmniAuth::Strategies::OpenID + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
+ + +

Class: OmniAuth::Strategies::OpenID + + + +

+
+ +
+
Inherits:
+
+ Object + +
    +
  • Object
  • + + + +
+ show all + +
+
+ + + + + + +
+
Includes:
+
OmniAuth::Strategy
+
+ + + + + + +
+
Defined in:
+
lib/omniauth/strategies/open_id.rb
+
+ +
+ +

Overview

+
+

OmniAuth strategy for connecting via OpenID. This allows for connection
+to a wide variety of sites, some of which are listed on the OpenID website.

+ + +
+
+
+ + +
+ +

+ Constant Summary + collapse +

+ +
+ +
AX = + +
+
{
+  email: "http://axschema.org/contact/email",
+  name: "http://axschema.org/namePerson",
+  nickname: "http://axschema.org/namePerson/friendly",
+  first_name: "http://axschema.org/namePerson/first",
+  last_name: "http://axschema.org/namePerson/last",
+  city: "http://axschema.org/contact/city/home",
+  state: "http://axschema.org/contact/state/home",
+  website: "http://axschema.org/contact/web/default",
+  image: "http://axschema.org/media/image/aspect11",
+}
+ +
+ + + + + + + + + +

+ Instance Method Summary + collapse +

+ + + + + + + +
+

Instance Method Details

+ + +
+

+ + #ax_user_infoObject + + + + + +

+ + + + +
+
+
+
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+
+
# File 'lib/omniauth/strategies/open_id.rb', line 121
+
+def 
+  ax = ::OpenID::AX::FetchResponse.from_success_response(openid_response)
+  return {} unless ax
+  {
+    "email" => ax.get_single(AX[:email]),
+    "first_name" => ax.get_single(AX[:first_name]),
+    "last_name" => ax.get_single(AX[:last_name]),
+    "name" => (ax.get_single(AX[:name]) || [ax.get_single(AX[:first_name]), ax.get_single(AX[:last_name])].join(" ")).strip,
+    "location" => ("#{ax.get_single(AX[:city])}, #{ax.get_single(AX[:state])}" if Array(ax.get_single(AX[:city])).any? && Array(ax.get_single(AX[:state])).any?),
+    "nickname" => ax.get_single(AX[:nickname]),
+    "urls" => ({"Website" => Array(ax.get_single(AX[:website])).first} if Array(ax.get_single(AX[:website])).any?),
+  }.each_with_object({}) { |(k, v), h|
+    h[k] = Array(v).first
+  }.reject { |k, v| v.nil? || v == "" }
+end
+
+
+ +
+

+ + #callback_phaseObject + + + + + +

+ + + + +
+
+
+
+96
+97
+98
+99
+
+
# File 'lib/omniauth/strategies/open_id.rb', line 96
+
+def callback_phase
+  return fail!(:invalid_credentials) unless openid_response && openid_response.status == :success
+  super
+end
+
+
+ +
+

+ + #dummy_appObject + + + + + +

+ + + + +
+
+
+
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+
+
# File 'lib/omniauth/strategies/open_id.rb', line 34
+
+def dummy_app
+  lambda { |env|
+    req = Rack::Request.new(env)
+    root_uri = "#{req.scheme}://#{req.host_with_port}/"
+
+    [
+      401,
+      {
+        "WWW-Authenticate" => Rack::OpenID.build_header(
+          identifier: identifier,
+          return_to: callback_url,
+          trust_root: options.trust_root || %r{^(https?://[^/]+)}.match(callback_url) { |m| m[1] },
+          required: options.required,
+          optional: options.optional,
+          method: "post",
+          immediate: options.immediate,
+          trust_root: options.trust_root.call(root_uri),
+        ),
+      },
+      [],
+    ]
+  }
+end
+
+
+ +
+

+ + #get_identifierObject + + + + + +

+ + + + +
+
+
+
+79
+80
+81
+82
+83
+84
+
+
# File 'lib/omniauth/strategies/open_id.rb', line 79
+
+def get_identifier
+  f = OmniAuth::Form.new(title: "OpenID Authentication")
+  f.label_field("OpenID Identifier", options.identifier_param)
+  f.input_field("url", options.identifier_param)
+  f.to_response
+end
+
+
+ +
+

+ + #identifierObject + + + + + +

+ + + + +
+
+
+
+58
+59
+60
+61
+62
+
+
# File 'lib/omniauth/strategies/open_id.rb', line 58
+
+def identifier
+  i = options.identifier || request.params[options.identifier_param.to_s]
+  i = nil if i == ""
+  i
+end
+
+
+ +
+

+ + #openid_responseObject + + + + + +

+ + + + +
+
+
+
+101
+102
+103
+104
+105
+106
+107
+108
+
+
# File 'lib/omniauth/strategies/open_id.rb', line 101
+
+def openid_response
+  unless @openid_response
+    openid = Rack::OpenID.new(lambda { |env| [200, {}, []] }, options[:store])
+    openid.call(env)
+    @openid_response = env.delete("rack.openid.response")
+  end
+  @openid_response
+end
+
+
+ +
+

+ + #request_phaseObject + + + + + +

+ + + + +
+
+
+
+64
+65
+66
+
+
# File 'lib/omniauth/strategies/open_id.rb', line 64
+
+def request_phase
+  identifier ? start : get_identifier
+end
+
+
+ +
+

+ + #sreg_user_infoObject + + + + + +

+ + + + +
+
+
+
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+
+
# File 'lib/omniauth/strategies/open_id.rb', line 110
+
+def 
+  sreg = ::OpenID::SReg::Response.from_success_response(openid_response)
+  return {} unless sreg
+  {
+    "email" => sreg["email"],
+    "name" => sreg["fullname"],
+    "location" => sreg["postcode"],
+    "nickname" => sreg["nickname"],
+  }.reject { |k, v| v.nil? || v == "" }
+end
+
+
+ +
+

+ + #startObject + + + + + +

+ + + + +
+
+
+
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+
+
# File 'lib/omniauth/strategies/open_id.rb', line 68
+
+def start
+  openid = Rack::OpenID.new(dummy_app, options[:store])
+  response = openid.call(env)
+  case env["rack.openid.response"]
+  when Rack::OpenID::MissingResponse, Rack::OpenID::TimeoutResponse
+    fail!(:connection_failed)
+  else
+    response
+  end
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/docs/_index.html b/docs/_index.html new file mode 100644 index 0000000..3732874 --- /dev/null +++ b/docs/_index.html @@ -0,0 +1,169 @@ + + + + + + + Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
+ + +

Documentation by YARD 0.9.37

+
+

Alphabetic Index

+ +

File Listing

+ + +
+

Namespace Listing A-Z

+ + + + + + + + +
+ + +
    +
  • O
  • +
      + +
    • + OmniAuth + +
    • + +
    • + OpenID + + (OmniAuth::Strategies) + +
    • + +
    • + OpenID + + (OmniAuth) + +
    • + +
    +
+ + + + + +
    +
  • V
  • +
      + +
    • + Version + + (OmniAuth::OpenID) + +
    • + +
    +
+ +
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/docs/class_list.html b/docs/class_list.html new file mode 100644 index 0000000..4daa6ec --- /dev/null +++ b/docs/class_list.html @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + Class List + + + +
+
+

Class List

+ + + +
+ + +
+ + diff --git a/docs/css/common.css b/docs/css/common.css new file mode 100644 index 0000000..cf25c45 --- /dev/null +++ b/docs/css/common.css @@ -0,0 +1 @@ +/* Override this file with custom rules */ \ No newline at end of file diff --git a/docs/css/full_list.css b/docs/css/full_list.css new file mode 100644 index 0000000..6eef5e4 --- /dev/null +++ b/docs/css/full_list.css @@ -0,0 +1,58 @@ +body { + margin: 0; + font-family: "Lucida Sans", "Lucida Grande", Verdana, Arial, sans-serif; + font-size: 13px; + height: 101%; + overflow-x: hidden; + background: #fafafa; +} + +h1 { padding: 12px 10px; padding-bottom: 0; margin: 0; font-size: 1.4em; } +.clear { clear: both; } +.fixed_header { position: fixed; background: #fff; width: 100%; padding-bottom: 10px; margin-top: 0; top: 0; z-index: 9999; height: 70px; } +#search { position: absolute; right: 5px; top: 9px; padding-left: 24px; } +#content.insearch #search, #content.insearch #noresults { background: url(data:image/gif;base64,R0lGODlhEAAQAPYAAP///wAAAPr6+pKSkoiIiO7u7sjIyNjY2J6engAAAI6OjsbGxjIyMlJSUuzs7KamppSUlPLy8oKCghwcHLKysqSkpJqamvT09Pj4+KioqM7OzkRERAwMDGBgYN7e3ujo6Ly8vCoqKjY2NkZGRtTU1MTExDw8PE5OTj4+PkhISNDQ0MrKylpaWrS0tOrq6nBwcKysrLi4uLq6ul5eXlxcXGJiYoaGhuDg4H5+fvz8/KKiohgYGCwsLFZWVgQEBFBQUMzMzDg4OFhYWBoaGvDw8NbW1pycnOLi4ubm5kBAQKqqqiQkJCAgIK6urnJyckpKSjQ0NGpqatLS0sDAwCYmJnx8fEJCQlRUVAoKCggICLCwsOTk5ExMTPb29ra2tmZmZmhoaNzc3KCgoBISEiIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCAAAACwAAAAAEAAQAAAHaIAAgoMgIiYlg4kACxIaACEJCSiKggYMCRselwkpghGJBJEcFgsjJyoAGBmfggcNEx0flBiKDhQFlIoCCA+5lAORFb4AJIihCRbDxQAFChAXw9HSqb60iREZ1omqrIPdJCTe0SWI09GBACH5BAkIAAAALAAAAAAQABAAAAdrgACCgwc0NTeDiYozCQkvOTo9GTmDKy8aFy+NOBA7CTswgywJDTIuEjYFIY0JNYMtKTEFiRU8Pjwygy4ws4owPyCKwsMAJSTEgiQlgsbIAMrO0dKDGMTViREZ14kYGRGK38nHguHEJcvTyIEAIfkECQgAAAAsAAAAABAAEAAAB2iAAIKDAggPg4iJAAMJCRUAJRIqiRGCBI0WQEEJJkWDERkYAAUKEBc4Po1GiKKJHkJDNEeKig4URLS0ICImJZAkuQAhjSi/wQyNKcGDCyMnk8u5rYrTgqDVghgZlYjcACTA1sslvtHRgQAh+QQJCAAAACwAAAAAEAAQAAAHZ4AAgoOEhYaCJSWHgxGDJCQARAtOUoQRGRiFD0kJUYWZhUhKT1OLhR8wBaaFBzQ1NwAlkIszCQkvsbOHL7Y4q4IuEjaqq0ZQD5+GEEsJTDCMmIUhtgk1lo6QFUwJVDKLiYJNUd6/hoEAIfkECQgAAAAsAAAAABAAEAAAB2iAAIKDhIWGgiUlh4MRgyQkjIURGRiGGBmNhJWHm4uen4ICCA+IkIsDCQkVACWmhwSpFqAABQoQF6ALTkWFnYMrVlhWvIKTlSAiJiVVPqlGhJkhqShHV1lCW4cMqSkAR1ofiwsjJyqGgQAh+QQJCAAAACwAAAAAEAAQAAAHZ4AAgoOEhYaCJSWHgxGDJCSMhREZGIYYGY2ElYebi56fhyWQniSKAKKfpaCLFlAPhl0gXYNGEwkhGYREUywag1wJwSkHNDU3D0kJYIMZQwk8MjPBLx9eXwuETVEyAC/BOKsuEjYFhoEAIfkECQgAAAAsAAAAABAAEAAAB2eAAIKDhIWGgiUlh4MRgyQkjIURGRiGGBmNhJWHm4ueICImip6CIQkJKJ4kigynKaqKCyMnKqSEK05StgAGQRxPYZaENqccFgIID4KXmQBhXFkzDgOnFYLNgltaSAAEpxa7BQoQF4aBACH5BAkIAAAALAAAAAAQABAAAAdogACCg4SFggJiPUqCJSWGgkZjCUwZACQkgxGEXAmdT4UYGZqCGWQ+IjKGGIUwPzGPhAc0NTewhDOdL7Ykji+dOLuOLhI2BbaFETICx4MlQitdqoUsCQ2vhKGjglNfU0SWmILaj43M5oEAOwAAAAAAAAAAAA==) no-repeat center left; } +#full_list { padding: 0; list-style: none; margin-left: 0; margin-top: 80px; font-size: 1.1em; } +#full_list ul { padding: 0; } +#full_list li { padding: 0; margin: 0; list-style: none; } +#full_list li .item { padding: 5px 5px 5px 12px; } +#noresults { padding: 7px 12px; background: #fff; } +#content.insearch #noresults { margin-left: 7px; } +li.collapsed ul { display: none; } +li a.toggle { cursor: default; position: relative; left: -5px; top: 4px; text-indent: -999px; width: 10px; height: 9px; margin-left: -10px; display: block; float: left; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAK8AAACvABQqw0mAAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTM5jWRgMAAAAVdEVYdENyZWF0aW9uIFRpbWUAMy8xNC8wOeNZPpQAAAE2SURBVDiNrZTBccIwEEXfelIAHUA6CZ24BGaWO+FuzZAK4k6gg5QAdGAq+Bxs2Yqx7BzyL7Llp/VfzZeQhCTc/ezuGzKKnKSzpCxXJM8fwNXda3df5RZETlIt6YUzSQDs93sl8w3wBZxCCE10GM1OcWbWjB2mWgEH4Mfdyxm3PSepBHibgQE2wLe7r4HjEidpnXMYdQPKEMJcsZ4zs2POYQOcaPfwMVOo58zsAdMt18BuoVDPxUJRacELbXv3hUIX2vYmOUvi8C8ydz/ThjXrqKqqLbDIAdsCKBd+Wo7GWa7o9qzOQHVVVXeAbs+yHHCH4aTsaCOQqunmUy1yBUAXkdMIfMlgF5EXLo2OpV/c/Up7jG4hhHcYLgWzAZXUc2b2ixsfvc/RmNNfOXD3Q/oeL9axJE1yT9IOoUu6MGUkAAAAAElFTkSuQmCC) no-repeat bottom left; } +li.collapsed a.toggle { cursor: default; background-position: top left; } +li { color: #666; cursor: pointer; } +li.deprecated { text-decoration: line-through; font-style: italic; } +li.odd { background: #f0f0f0; } +li.even { background: #fafafa; } +.item:hover { background: #ddd; } +li small:before { content: "("; } +li small:after { content: ")"; } +li small.search_info { display: none; } +a, a:visited { text-decoration: none; color: #05a; } +li.clicked > .item { background: #05a; color: #ccc; } +li.clicked > .item a, li.clicked > .item a:visited { color: #eee; } +li.clicked > .item a.toggle { opacity: 0.5; background-position: bottom right; } +li.collapsed.clicked a.toggle { background-position: top right; } +#search input { border: 1px solid #bbb; border-radius: 3px; } +#full_list_nav { margin-left: 10px; font-size: 0.9em; display: block; color: #aaa; } +#full_list_nav a, #nav a:visited { color: #358; } +#full_list_nav a:hover { background: transparent; color: #5af; } +#full_list_nav span:after { content: ' | '; } +#full_list_nav span:last-child:after { content: ''; } + +#content h1 { margin-top: 0; } +li { white-space: nowrap; cursor: normal; } +li small { display: block; font-size: 0.8em; } +li small:before { content: ""; } +li small:after { content: ""; } +li small.search_info { display: none; } +#search { width: 170px; position: static; margin: 3px; margin-left: 10px; font-size: 0.9em; color: #666; padding-left: 0; padding-right: 24px; } +#content.insearch #search { background-position: center right; } +#search input { width: 110px; } + +#full_list.insearch ul { display: block; } +#full_list.insearch .item { display: none; } +#full_list.insearch .found { display: block; padding-left: 11px !important; } +#full_list.insearch li a.toggle { display: none; } +#full_list.insearch li small.search_info { display: block; } diff --git a/docs/css/style.css b/docs/css/style.css new file mode 100644 index 0000000..f169a65 --- /dev/null +++ b/docs/css/style.css @@ -0,0 +1,503 @@ +html { + width: 100%; + height: 100%; +} +body { + font-family: "Lucida Sans", "Lucida Grande", Verdana, Arial, sans-serif; + font-size: 13px; + width: 100%; + margin: 0; + padding: 0; + display: flex; + display: -webkit-flex; + display: -ms-flexbox; +} + +#nav { + position: relative; + width: 100%; + height: 100%; + border: 0; + border-right: 1px dotted #eee; + overflow: auto; +} +.nav_wrap { + margin: 0; + padding: 0; + width: 20%; + height: 100%; + position: relative; + display: flex; + display: -webkit-flex; + display: -ms-flexbox; + flex-shrink: 0; + -webkit-flex-shrink: 0; + -ms-flex: 1 0; +} +#resizer { + position: absolute; + right: -5px; + top: 0; + width: 10px; + height: 100%; + cursor: col-resize; + z-index: 9999; +} +#main { + flex: 5 1; + -webkit-flex: 5 1; + -ms-flex: 5 1; + outline: none; + position: relative; + background: #fff; + padding: 1.2em; + padding-top: 0.2em; + box-sizing: border-box; +} + +@media (max-width: 920px) { + .nav_wrap { width: 100%; top: 0; right: 0; overflow: visible; position: absolute; } + #resizer { display: none; } + #nav { + z-index: 9999; + background: #fff; + display: none; + position: absolute; + top: 40px; + right: 12px; + width: 500px; + max-width: 80%; + height: 80%; + overflow-y: scroll; + border: 1px solid #999; + border-collapse: collapse; + box-shadow: -7px 5px 25px #aaa; + border-radius: 2px; + } +} + +@media (min-width: 920px) { + body { height: 100%; overflow: hidden; } + #main { height: 100%; overflow: auto; } + #search { display: none; } +} + +@media (max-width: 320px) { + body { height: 100%; overflow: hidden; overflow-wrap: break-word; } + #main { height: 100%; overflow: auto; } +} + +#main img { max-width: 100%; } +h1 { font-size: 25px; margin: 1em 0 0.5em; padding-top: 4px; border-top: 1px dotted #d5d5d5; } +h1.noborder { border-top: 0px; margin-top: 0; padding-top: 4px; } +h1.title { margin-bottom: 10px; } +h1.alphaindex { margin-top: 0; font-size: 22px; } +h2 { + padding: 0; + padding-bottom: 3px; + border-bottom: 1px #aaa solid; + font-size: 1.4em; + margin: 1.8em 0 0.5em; + position: relative; +} +h2 small { font-weight: normal; font-size: 0.7em; display: inline; position: absolute; right: 0; } +h2 small a { + display: block; + height: 20px; + border: 1px solid #aaa; + border-bottom: 0; + border-top-left-radius: 5px; + background: #f8f8f8; + position: relative; + padding: 2px 7px; +} +a { font-weight: 550; } +.clear { clear: both; } +.inline { display: inline; } +.inline p:first-child { display: inline; } +.docstring, .tags, #filecontents { font-size: 15px; line-height: 1.5145em; } +.docstring p > code, .docstring p > tt, .tags p > code, .tags p > tt { + color: #c7254e; background: #f9f2f4; padding: 2px 4px; font-size: 1em; + border-radius: 4px; +} +.docstring h1, .docstring h2, .docstring h3, .docstring h4 { padding: 0; border: 0; border-bottom: 1px dotted #bbb; } +.docstring h1 { font-size: 1.2em; } +.docstring h2 { font-size: 1.1em; } +.docstring h3, .docstring h4 { font-size: 1em; border-bottom: 0; padding-top: 10px; } +.summary_desc .object_link a, .docstring .object_link a { + font-family: monospace; font-size: 1.05em; + color: #05a; background: #EDF4FA; padding: 2px 4px; font-size: 1em; + border-radius: 4px; +} +.rdoc-term { padding-right: 25px; font-weight: bold; } +.rdoc-list p { margin: 0; padding: 0; margin-bottom: 4px; } +.summary_desc pre.code .object_link a, .docstring pre.code .object_link a { + padding: 0px; background: inherit; color: inherit; border-radius: inherit; +} + +/* style for */ +#filecontents table, .docstring table { border-collapse: collapse; } +#filecontents table th, #filecontents table td, +.docstring table th, .docstring table td { border: 1px solid #ccc; padding: 8px; padding-right: 17px; } +#filecontents table tr:nth-child(odd), +.docstring table tr:nth-child(odd) { background: #eee; } +#filecontents table tr:nth-child(even), +.docstring table tr:nth-child(even) { background: #fff; } +#filecontents table th, .docstring table th { background: #fff; } + +/* style for
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Tokens to Remember +Gem name Gem namespace +
Works with JRuby +JRuby 9.2 Compat JRuby 9.3 Compat JRuby 9.4 Compat JRuby 10.0 Compat JRuby HEAD Compat +
Works with MRI Ruby 3 +Ruby 3.0 Compat Ruby 3.1 Compat Ruby 3.2 Compat Ruby 3.3 Compat Ruby 3.4 Compat Ruby HEAD Compat +
Works with MRI Ruby 2 +Ruby 2.4 Compat Ruby 2.5 Compat Ruby 2.6 Compat Ruby 2.7 Compat +
Source +Source on GitLab.com Source on CodeBerg.org Source on Github.com The best SHA: dQw4w9WgXcQ! +
Documentation +Current release on RubyDoc.info YARD on Galtzo.com BDFL Blog Wiki +
Compliance +License: MIT 📄ilo-declaration-img Security Policy Contributor Covenant 2.1 SemVer 2.0.0 +
Style +Enforced Code Style Linter Keep-A-Changelog 1.0.0 Gitmoji Commits +
Support +Live Chat on Discord Get help from me on Upwork Get help from me on Codementor +
Enterprise Support +Get help from me on Tidelift
💡Subscribe for support guarantees covering all FLOSS dependencies!
💡Tidelift is part of Sonar!
💡Tidelift pays maintainers to maintain the software you depend on!
📊@Pointy Haired Boss: An enterprise support subscription is “never gonna let you down”, and supports open source maintainers!
Comrade BDFL 🎖️ +Follow Me on LinkedIn Follow Me on Ruby.Social Follow Me on Bluesky Contact BDFL My technical writing +
+... 💖 +Find Me on WellFound: Find Me on CrunchBase My LinkTree More About Me 🧊 🐙 🛖 🧪 +
+ +

✨ Installation

+ +

Install the gem and add to the application’s Gemfile by executing:

+ +
$ bundle add omniauth-openid
+
+ +

If bundler is not being used to manage dependencies, install the gem by executing:

+ +
$ gem install omniauth-openid
+
+ +

🔒 Secure Installation

+ +

omniauth-openid is cryptographically signed, and has verifiable SHA-256 and SHA-512 checksums by
+stone_checksums. Be sure the gem you install hasn’t been tampered with
+by following the instructions below.

+ +

Add my public key (if you haven’t already, expires 2045-04-29) as a trusted certificate:

+ +
gem cert --add <(curl -Ls https://raw.github.com/omniauth/omniauth-openid/main/certs/pboling.pem)
+
+ +

You only need to do that once. Then proceed to install with:

+ +
gem install omniauth-openid -P MediumSecurity
+
+ +

The MediumSecurity trust profile will verify signed gems, but allow the installation of unsigned dependencies.

+ +

This is necessary because not all of omniauth-openid’s dependencies are signed, so we cannot use HighSecurity.

+ +

If you want to up your security game full-time:

+ +
bundle config set --global trust-policy MediumSecurity
+
+ +

NOTE: Be prepared to track down certs for signed gems and add them the same way you added mine.

+ +

🔧 Compatibility

+ +

+ +

🔧 Basic Usage

+ +

Use the strategy as a middleware in your application:

+ +
require "omniauth-openid"
+require "openid/store/filesystem"
+
+use Rack::Session::Cookie
+use OmniAuth::Strategies::OpenID, store: OpenID::Store::Filesystem.new("/tmp")
+
+ +

Then simply direct users to /auth/open_id to prompt them for their OpenID identifier. You may also pre-set the identifier by passing an identifier parameter to the URL (Example: /auth/open_id?openid_url=yahoo.com).

+ +

A list of all OpenID stores is available at http://github.com/openid/ruby-openid/tree/master/lib/openid/store/

+ +

OmniAuth Builder

+ +

If OpenID is one of several authentication strategies, use the OmniAuth Builder:

+ +
require "omniauth-openid"
+require "openid/store/filesystem"
+
+use OmniAuth::Builder do
+  provider :open_id, store: OpenID::Store::Filesystem.new("/tmp")
+end
+
+ +

Configured Identifiers

+ +

You may pre-configure an OpenID identifier. For example, to use Google’s main OpenID endpoint:

+ +
use OmniAuth::Builder do
+  provider :open_id, nil, :name => 'google', :identifier => 'https://www.google.com/accounts/o8/id'
+end
+
+ +

Note the use of nil, which will trigger ruby-openid’s default Memory Store.

+ +

Please contribute some documentation if you have the gumption! The maintainer’s time is limited, and sometimes the authors of PRs with new options don’t update the this readme. 😭

+ +

🔐 Security

+ +

See SECURITY.md.

+ +

🤝 Contributing

+ +

If you need some ideas of where to help, you could work on adding more code coverage,
+or if it is already 💯 (see below) check issues, or PRs,
+or use the gem and think about how it could be better.

+ +

We Keep A Changelog so if you make changes, remember to update it.

+ +

See CONTRIBUTING.md for more detailed instructions.

+ +

🚀 Release Instructions

+ +

See CONTRIBUTING.md.

+ +

Code Coverage

+ +

Coverage Graph

+ +

🪇 Code of Conduct

+ +

Everyone interacting with this project’s codebases, issue trackers,
+chat rooms and mailing lists agrees to follow the Contributor Covenant 2.1.

+ +

🌈 Contributors

+ +

Contributors

+ +

Made with contributors-img.

+ +

⭐️ Star History

+ +

+ + + + Star History Chart + +

</a>

+ +

📌 Versioning

+ +

This Library adheres to Semantic Versioning 2.0.0.
+Violations of this scheme should be reported as bugs.
+Specifically, if a minor or patch version is released that breaks backward compatibility,
+a new version should be immediately released that restores compatibility.
+Breaking changes to the public API will only be introduced with new major versions.

+ +

📌 Is “Platform Support” part of the public API?

+ +

Yes. But I’m obligated to include notes…

+ +

SemVer should, but doesn’t explicitly, say that dropping support for specific Platforms
+is a breaking change to an API.
+It is obvious to many, but not all, and since the spec is silent, the bike shedding is endless.

+ +
+

dropping support for a platform is both obviously and objectively a breaking change

+
+ + + +

To get a better understanding of how SemVer is intended to work over a project’s lifetime,
+read this article from the creator of SemVer:

+ + + +

As a result of this policy, and the interpretive lens used by the maintainer,
+you can (and should) specify a dependency on these libraries using
+the Pessimistic Version Constraint with two digits of precision.

+ +

For example:

+ +
spec.add_dependency("omniauth-openid", "~> 3.1")
+
+ +

See CHANGELOG.md for a list of releases.

+ +

📄 License

+ +

The gem is available as open source under the terms of
+the MIT License License: MIT.
+See LICENSE.txt for the official Copyright Notice.

+ + + + + +

🤑 One more thing

+ +

You made it to the bottom of the page,
+so perhaps you’ll indulge me for another 20 seconds.
+I maintain many dozens of gems, including this one,
+because I want Ruby to be a great place for people to solve problems, big and small.
+Please consider supporting my efforts via the giant yellow link below,
+or one of the others at the head of this README.

+ +

Buy me a latte

+ + + + + + + + \ No newline at end of file diff --git a/docs/file.SECURITY.html b/docs/file.SECURITY.html new file mode 100644 index 0000000..d3753f7 --- /dev/null +++ b/docs/file.SECURITY.html @@ -0,0 +1,111 @@ + + + + + + + File: SECURITY + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
+ + +

Security Policy

+ +

Supported Versions

+ + + + + + + + + + + + + + + + + + +
VersionSupported
2.x
1.x
+ +

Security contact information

+ +

To report a security vulnerability, please use the
+Tidelift security contact.
+Tidelift will coordinate the fix and disclosure.

+ +

Additional Support

+ +

If you are interested in support for versions older than the latest release,
+please consider sponsoring the project / maintainer @ https://liberapay.com/pboling/donate,
+or find other sponsorship links in the README.

+ +

Enterprise Support

+ +

Available as part of the Tidelift Subscription.

+ +

The maintainers of this library and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source packages you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers for the exact packages you use. Learn more.

+ +
+ + + +
+ + \ No newline at end of file diff --git a/docs/file_list.html b/docs/file_list.html new file mode 100644 index 0000000..321a679 --- /dev/null +++ b/docs/file_list.html @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + File List + + + +
+
+

File List

+ + + +
+ + +
+ + diff --git a/docs/frames.html b/docs/frames.html new file mode 100644 index 0000000..6586005 --- /dev/null +++ b/docs/frames.html @@ -0,0 +1,22 @@ + + + + + Documentation by YARD 0.9.37 + + + + diff --git a/docs/images/logo/README.txt b/docs/images/logo/README.txt new file mode 100644 index 0000000..26ad9dc --- /dev/null +++ b/docs/images/logo/README.txt @@ -0,0 +1,38 @@ +Galtzo.com Logos +- galtzo-floss-logos-original.svg +- galtzo-floss-logos-wordless.svg + +© 2025 by Aboling0 (https://github.com/Aboling0) + +Licensed under CC BY-SA 4.0 + +https://creativecommons.org/licenses/by-sa/4.0/ + +--- + +The OmniAuth Logo - omniauth-logo-182px.jpeg (resized to square) + +Committed by https://github.com/tomeara to the old GH-Pages site for OmniAuth + +https://github.com/omniauth/omniauth/commit/89a03ef889cd9994cdfa8a61d5195d76884510ec + +Creator and License specifically are unknown, +but the code of the project and website was and is licensed under MIT. + +--- + +The OpenID Logo - openid_rgb-300dpi.png + +Logo Guidelines: The OpenID logo is to be displayed in its entirety on either a solid light or dark background—avoid mid-tones or strongly colored backgrounds. The logo should not be displayed in parts, with color variations, or with other elements superimposed on top of the logo. The stylized I+D symbol should not be modified or distorted. + +https://openid.net/policies/ + +--- + +The Ruby Logo - ruby-logo-124px.jpeg (resized) + +https://www.ruby-lang.org/en/about/logo/ + +Yukihiro Matsumoto, Ruby Visual Identity Team, CC BY-SA 2.5 + +https://creativecommons.org/licenses/by-sa/2.5 diff --git a/docs/images/logo/galtzo-floss-logos-original.svg b/docs/images/logo/galtzo-floss-logos-original.svg new file mode 100644 index 0000000..40358de --- /dev/null +++ b/docs/images/logo/galtzo-floss-logos-original.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/images/logo/galtzo-floss-logos-wordless.svg b/docs/images/logo/galtzo-floss-logos-wordless.svg new file mode 100644 index 0000000..45620af --- /dev/null +++ b/docs/images/logo/galtzo-floss-logos-wordless.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/images/logo/omniauth-logo-182px.png b/docs/images/logo/omniauth-logo-182px.png new file mode 100644 index 0000000000000000000000000000000000000000..8362552ea07c17305dca4df8969a4c368bbd9501 GIT binary patch literal 22567 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ӯ` zTLBA86a0>J-8~HiSt@_ZUjjQ6X)S~oC=*gI9E8cd?sqU$yC2E+7zF=}0Zxl+_9X-!5aZxe#e91Qq?bU{<4TZ(Yo!QSr4&I8|_|LwGJYFlzD7BF=EHx0? zrF(xM^UB0qwytzG5X6=mmibmfj}N_Sc%E9WIVZ|~ZV}mVet4K|!@U0GxLniMygY=h zc*ipOaC89P*PB}1MkX*mxAV4F#vA1)EI+XHGJgVtS2vu3*>A0?HuR1}B=xbw2vR&$ zU(^8WNaIi2TH-`xWT_wchvs>ff`XhN^xZyi6$fU(h)X6zQhgTeV(wqV42q&8@uYvb zY~@@2oxyPo9`D6ph49j2;>resukZk zyV|q1bRtKk11=chBo}pljZWP<7`Ll-44MKhOY!R)aZOv3vcauXfo80-1)~KiI;Gi} z1T+)-`=e7IQ9_KUaU4bE&($j81vZpNhs zNZDjm1F6IJDx2r2vYhKHRaxXiIi}kgsG;pU|EnBWtt@5RJ39ZR4 zNL3hImiEnSuu(KEH!V2*q(9NVIzPJXaY+TZq3<$aF<)z>&}FOFqx-2mgM`;5T+%e-PzZZeDmKrCG|Y2}EFBe+N^alhQ6 zP-LyjLDaLdP8bB!z<}2$U;3sP%~5EfaWW-mkvW*uQ_ybp=KnC2pL&izy^X~DzT#(7Qze@uN!mY*M@ZJ0ud0yzaN*B z9ABb6U?9p(i_CwpyA!3pQS}%HXnv4-Q^`{uIWo{;?5Htq13$VMhR`l?^!@G8fx6 z;9&8|-C-muIO&v*RYrtNHth2l>fR`)W38eM-I$!% zsh_9jOj_uTy&bC+KM8Lhd*l5sst!9*#X31xQd(nI`p{&jQN}iEdfnU+Gx3MtDghjJ z{`>~4%(FCfh{g$GIKN*@wN=E-(xkcP%aufxg?YQIClFL6)h2LlK@OqMIEchU5et0aaKgN^Z zpGyR@J%4}2&(|BhYo>h9jZ*ei`ib4ZINpn?FYi9}I1N8X>$)(Kv;*NSw-2ZDmwPT1 z8%tFd1H+I0Vln65)B(p+lThlKSBdZP=p=^fENLt9l+x+e%pzgDlm$-$;NP62bNGIT zZ%pa#Z*w2k7n$njUbWrp(BBk|wY>v9kfb6L;Z=zLygaW+B;(>*uubQ%iu6BSD;5$mu@Jq(hpm{WS#dmHNB1b&bE!=LC%HlmD0dJX?b+gD6556rK^J+!x z;r-E=D>{Nm;mqS2FyiF8FAgRp!m9CIR>vB?;AWfE$ZwmPdvg0SaBJ;hlV8l@sZROr z*WfJ1vYm1@#DW9MzYB63jkezX%*Yn~*rYUBGZ6FzV5Lu21Ki{nYwi{H+!Y6#8dtWO zOvVc;tkRPftr#w3@1Zb=LP7)ElBB?J>~@rUz;7l=*1qRiUFD)SSzkfmi1^V}@Mb+` zy}AGNNyjnP~Rh%nTF#rat_}K+3_?6cw}Yha83z zNY#Lfv-Yy;ALfagI;qxk#M1Bd4wjQm4z&F+=+240S~v6zDQ!ABsBYs#`85uI zdMKHkpZZd_wls6B>&M6kvNZV25k~KBmlf^Ba-WLM>BBWO|EAOZtj~OVXIFijIa>2E zf#pS`1trnNwd~sh+Qcy4Pv^CXetUQ{3B|DzdcR@qn=%YDT;+1|)PnI{xfiO$ATmtw zSO8qxf4KnmO@>X06Lecekzpb&AN3GT_mz-d;2zN}WHs~qkDl=Z(|`@kX}b7{StXk} z+BkEo+%mO;r!bkP)2)`A$=UM#M>JJT8-49K)8eJ9z9gGP*Ya!Kqm-`&&rloeSby}W zYx31`llWDcRS048ZpMWA|8u3ZQ1c;Jb80?c)TZ&ri!%0)f7jzjE{bAqrc6X+ay4CP zB;ue3h=2eQK_8J2W^PfwA1F^PnbZ=Srq6zdC2HR$RmO9DD=0|2WxQ3ea4XY%!}}(8 z)##fhWV~~ubVBwh<}q-9frOHwb|s=(xHW@Tefw^lF0L`t%;|UIkb|u(FG)he)3WjE zhVN%Etm@Q;RFYS^gWyWo8f1<2m2q-i@okKq-%$jB+(F#ZQ!$dD^7zS(w_s~vD@1NX zpw(a%0D!dY-WGDi1=UV1X1jpv2mNGPSXa4E)kX!1oXEcz^X#|rFrT*1(2khMtX@e? zTaW|eYm0|Tq_g)L=b*aLr?=BU1SDL(*5Be;v(}&A+q9-h%Fs1W$%c&HxXy-5i&=Uj zEs^4x@m#2;^7uX9Ui0$a-%Xxx=0dDTF={7ZF!4%;YGB3&s!Mx?>Smrigg2S`vv*Q1 z-Z_0usdT?p&el17w8>GpLzVrylJ+A;YGT06*1o@C-t}YH4oj}1`JbsJ`JbtE=HFFc z62$VQLt@GNvq2xf9E^+?rMjgJ4e$7ZVdY_qn`krB&&7Zsq(I+`%Y@f|X`4H3rRNhGe=cM>-&1)%=3s5C zK1qYi6@P94vXSls0d^tsVgI7Qo?WY7iKh;Q-8;Te*0wP;jPRfpSc}YpLd$41?COO; zc1EA(=_>k-croS*)BeoonFC$l;{Q(1CDi#&$`Bd3 z$~fQOG-YS6te$Me^WIns$u+T8^2Y4$r4x$TQq-l)oRTGzeZ*O;ze6S|2E!!_tT`q;ut6bExo z-B0I|c=bb|u^4lyTgE0*d+I>;S+ZBbo)7B+tkf*~wQ_vd-kj2vQ<|bak>c&kzYgJY zOWJ=!}s_3I6-R@0Fh&yQ$2Mgc39vUQ~`YHtjAuFtyg1YoY8!IBtnDNXMHC zX0zO&V2$tSxD4a9xuo#v97>2y$-6Z~pkWtV|El%ii|K<9Ex&3C*)aMketDzs+15UK ztG-vq7cUhSmXm>H$WA94tz;`}wzA|lDk^PfG;!64HI87GsSr<%{t2zXRh&}nJ~WY1 zvLV=Y!2Vm}W~&oPgNkK+zGi7cK4uh83hB(Qw}|x5+ZGy|$=b51&i{FqwQOUHGW*u_ z`zb3l@P`(s0cstSe-}RtIZ%OE4Ju2VG^cFu6wKkWAMe&J#a;9b0vuk%W(#(joL?{%sTRGo&6G-YVKnqceqF|pa zsp=fB1c(QwLJ)1m1~zY<=!w3!%*B-$6m--uRP5tVv%Cza~JzALdNkBue(G7k|dKNmygQf15$L) zdBta~6m6yQHn80JaOKIwKp(AeNKBo7{Jr>2jEa5RJ;>4YgO}(Jpcm zjO3Tac>cP_rPXzx_+J=^|9NOMkXJzj(@>p{lsR0!%BG+*^XawuRHeHP5oB}IQ^ulW z$9K&9GLjKZdp*~;b#Tsjh}d$i;K&SvpOBO526PZZ+_j=`v(`*&xkBKmGL|`%LJ6me zNdO18HWX!$rfl#?^(-D)m@L0E6KN?6x>;5SoI~320rBkP{AN*luS+1E<(ZJXjD?|A zWNHo{jm|3Gi%D}|kGeoUM%KgcpCp*=SRxIf@DuTULYbc4y9`irht6<7^t=kNAM60J zsR#4}Uk0|VMn;~kS?IiEotgn_=Wo}LvCaGw@+T1Q;^U9azvK5E=Qw?P8Qf`9+#K6AjP(&3^f1=hI&P6!QhFN7DH zlM|2jwqxrFz$}hwZl<*d=ROgKtSAMcNSyjC04OBlF2k-N0*J4Vz`@=XREYJ3>0SZ@ z;ujdr7I5yGf9wGo1+PX>RtJ;@>P`bZjXLwgA3@O;5v{>VhK(4}OG=Gxtt^Y>0Q2>TJHXavi z(vfi`*c%d`n}6~XglPjOzs~)+j~oM)URqPN;Xznt|ErbP?PnjG$&}n6k@nSHcvdvW zYVVr&igtqU*oIdjEs%7{GbRMbszloz89FD#4qO@ z`xF`+DP~Xtw@M*t96`b(y6u&xaORIwW8}~y3O3}?o2f^`Rz4waO&aa3JH8^%G7^GG zKWiR?MBfItpu5Vw3XpC)8BL5(6hsq?{{x{ETRf3(G8t_4PuOM$9t{<7IgQOXO9P+q@j`E${Kw-RdC9zz+`jQa2$*id1^5{T zU5BlEDgC+00X#P*cz5)hc3x{2p$+hZ|HQXof9Gm}f=q?H>8J+z_glduE&Y5$A}vRA z#Fh=7p4s}x_@VNE8X~r&HI0H6tl`W?IRC63E0~Z`)^x+4J&N7;>W@4)35<`b>!Hhb zRS8uvwlyr&J*3yp|X) z`+x`^%K0O4NsfMNP2^xPc$rZ^zKa1Ts#*9x=0kq|%Yu1b!!0OO^iZ~H+5S)1N4Gof zq7c|Bm1F*8qmm{_1F2;d+;MGasZ4(<<|oD^#5KK`my(E-o5O4fWOmT2)piw)yyo- zgvK9n+XStG6IV}-w7<^qD=~dF0xS+?XV+baE9(LwMri0AzkgQe-;uBJSDxFYHP_bS zUnFFGbPJLa{JPg|c)7N*t!CtAuIwcruSSfUnAR^9s!smZcqCM9t+bHS)v#hG;2ZP_ zU%6LDasEp~&r`EYvX>x!7Nh|TCB{EwFq?_V9!dW=w`UB-r^N7LZObifIk9m0(HzGe zmhW|+elbg3B~ZA_(?-n^B+sMwH!*!tbeJ0tBv-O_YgT_E#wjlE$d1@%qOa>ryG}5b zw@dO?($F0hmm)`MPwDvRZ;FsRAdg>8QviUNQB@;EtV2eSZpCluZ&Glcz+MU^!c%`r zc!TX3KsbSUuo5B&-V-|mNl)W@V&0DdB_DRiwr*X}@1>z4caH6K-u5cjs6zg2DM_{7 z2T;zS1fSh9#S(JwWT$RC^kqz|Jm&Jq&bOgd;K|ok(uYXj^Mx2hZ2>y7>&IA~9RU}I z>9qQi0@wvw7i+5i`+%&&Fr>ERJCn6FMbG{-tOT==-um89$8Oq7e8ObNTffxc2+-N- zXKd8%QdwOyy}7t|KNH4^b=0AqwUadn6js;qe7ok&1BF*(21V8f+Ly(T*pOBqi(fE? z`MbBQ_o&?d()#6UdGOr;yaU#_ThGL(LNnC&&$dmDIT6{_lbrnx9|aZAztiZNvtD)j zSrk%0b+}!9o}gV{#z@$uL%W@!dGoW>5rWL?Yz+32DbDY({$1JHB5$U~6@HEo)wG#U zR*Z0zcyByDCf9j#_}5yXMHWoe;>1oMhiL#DDmVRor4DRt`Gfd)dtw?-f!J%IW=@>* z1scdWWd`iTbu>QOZC22DOw8WtX~KK!nZ&QP@TScGfS>X$$wSX7G%QX~=Ls!S7APqb z3zs7^q8Ix85pU442!fL^NTFWWn2bA}2EBYN2k#S?I33xWvOZC;Q?>K6)O}3tZ*IBK z;Ayfm|M=y4bFqKV?S{&@!c}Bgt{b%Qf^zqxyCu<|*LtRlZ%qaO&6AJ+_*5ApZ4FjC zIe+D6S!&=B!qspopvsQ_g7Ui@y%V;tKo;?}QO?JSHxd~!ZPD5FilZj>>rFkIY!8BH zrFvF!g-(E)W1T%uq9?^3Sady~yffkLl1WC>6UZ&sms~k}0I0g>IM=FUv{~I2*zcH5 z_kPlnAz16T1F}%43n?kuT_QRlsY|6qb1Ji4zK?Ymx1=zmUdaGy2nJhsILqA2Q%>LMGZ@T+)t;csO;~r& z7ArZNRC5SuMhf>BkUoi!v*hiTvy_+ZnrB12S-Sq`v&N{Ii0P^%cne}oEHX?p>Br~P z1|Ba!yo$B{b#a;^qX8g0OEb6f{i&LsKBSiRcW@o;>4Qr+RWyhIYXzjPXf67@oj~(b z8~L%mR7%j4cU`YY%Q+LPmp-bio-honon~9rS#o>Hid=gx8|GH$xskl|QNaxet=fEb zmm~csUhGXqiT~S!W)6fS3CysoiwFKx4P+=`D>$;`^E`d{;3Kf6MzfKS7uUVmy7hzp zO#c!&6c;t}lX(HUGi>4UKHKqvGVUEDBW*?lQ0Lw5O4g?j<&sXDWxy*`uhbxK zUu*ryI<;fp`o#R8vcB=_ro&KToqE>c^0qzVO;*WTCRz(*#70p(Uq_`ipUH8Eq&(sM z0&-KNr}4!FHiXWLN<0YB)@gUk59YLC5u_9JBmR+%;eViZG767A@R}6U^~KD>rDaRXFrczZwY8F{8JSyvNx7_?4LQ2Ct`jaazA@wF%p^` zpJ)_)J|zg1j|+C`UX7t4gu+Q#!_}7lUfd770L-+aZFF2dI`1XjSLI{J-P9D+==*4n zG&pZ(NxTh}myrs+yipYD!vrx`^)PpHUeFv?W})IECeRIR7>DRdnM!4iO{lU&QFtAV zIWqucGjHsJ%--6_&)ao=KnY{J10M-Z|MY6A;}_lwbFv?a7uIq@q<0}$C`BX;p{gE9 z=WT)VbO|vZpU{i9(W=jLGSUs^zdL};)AT|jZJKsG7Blx3>uBY*KcLv9^W(EQ81g*Y z&R&z-%qsf>!qi#q_0pO=mD02Zi>x<80C}BD%eP@hDBip~lH<7q$#fn*P^Ud7ICHij z3rU{+SknHowOH`P)7vCDd<2lqW2J=riiwa_>&4N=zMz=3dZ(}7)UZz6uhW(hfq9}r ze8c9?OJDVVwK@`ScjtwkAHF5~rS~+~`5DJh3gUV1Las9*Iiwb2{^LBizlZ4zZ1HbZ zL~>kWOJBTkV<3!Q!{}r^%m=;8=IZkMb7ZM0bZ(~Z4?@v;6*74qlK0 zvFd%l3egKE?N{+H%iWjaG%XX(mq0*`cBwSrjN6%=u**?vVD za}i2X%A^Q$o!|g`5IX18e9HNHMK{g6J># zO*?9_5@UTgMk!%Z|6*)3Se5V{>XHZ!D8P<>TZL&x&z4A#14j=w2zi3sC2h5UVF-dV zS1wCI=x&ji{1-xP6a1brYt`yk!!vsIgBMmEEPDtBK@JVA8UEPNbIrX4_4Ih63}Tp} z>Y{n}u?w78+k}EwPxRe$g8Yk~ z$ZHjfSmPH~4$|Qzm}XlG%EkAM$zc4TCvV^16SU(Jow^=_1>4zBau3KZ_`dWq7M-m> zJ@D@1WVabsQbZ|ct;DJ9O8)DQu5MQMpx(R+=J0~c$giPy`k7Z6DgOs#B z{hjh&RU%T(7bdiOYoM0FD(xz;{<8Un-GPH?2Oj*`drNi?1m;t+%rQ2^7lt zr?Xp@0youczSNDXi*ya5ntpowBLE!SSfA{pBsaI)YNom$ha5x*21p?FuUY#?AaJ+T zHTs}E@^}z&>?4pbYOk;|mr6-Z3;;8C{>OFsG#8#sgy4vQyy-X_@J?z=Zc>*dv#*<} ztujg$;m`Khq4Uu>XwK}@fj#C>HQRv6o~LJq!>Th!DQT|5u>pTTKh!W^l7^+Y5gz_Dg3jbV@qNq#s>)+jGw&?v<@m@FtIq^`CL!KqAuWeXn z$D-h>#(35(&9h*8*WZ69n?nBX4anzDrOWQ{5!QK>phR9C_x*Ki^=jh3x@2L4)dWBCr z^#kgI&FcJiMiDWLy1a>B@X%Y>e&+nVj&AdhBomsls46(2 z!-^PUO7(}hE{DtfzGvIyGULK+_7pI>Ab&C`H?|2eLB!KTm$%sK{BUVC-fKYsus#qb zL7h6mpqj5+_e12J{gb{TU^*>yec;S#*GTa~8_UAlb&f`{Ad3;k*L=yV3vBW5>sbWS zIZ!b%kZ|_(Je_=tE2iVam2W``(?tK71}z)KguaBm?oT5yG_9{3?i#dUI0z}9(1x>W z)RW4ly^4)UxB$c_*v6HklI8q&$L=*>hzn6Ys=`yrLdJe{Z#WwmO9`g937iQB9|a3S z`|uMQmT*rekDo`6?UMZXP+FkiBM%*hzMEc+OU{L$M|$a>AcVu`H?jy<6_1}@tg9}5 z{Y(b`^&lhcf%n3?x`*N0gF6Qghe6cjE6EghDt7%Y*nQB1UXSNE^cvg%1 zJ)lHI)ha5ZtP7Pt{8w!VSsQN>&>$+B1iAbp2+Kc~DqZf;j}_i<=C?=O0QvxGEEX*< z&i1rdBqeU+iXlf}r3BhU)C~#y$1P{bi>=a&!;3S^3%ivb-~G8$%kzIR0KEa&#&Cl? zaCKQYS}T;5Uztb^RSbVR;cR{iZ^(d2$MaxA&POj~_dx*y`0(!D2OA2*Pj3(KuxXso z_ygt;d|*Xw#4sFnB!36Mb2JA}5Sa|yzbiCqIRpvD|7Dg`qmAIQ{QpiX#3XY;F*w2; z6e*_e8xGs79RIrz>X|I~??Tw-NyKDiCMc!>pY7sgyceFO@@guC|EUiBLwkaRF?AYu zW^Zx+gn@qyKiIm^I|0)kkr3Y>f0K}N>{lJyXy#(qM;;{W;66U23Wj5BR#GUc_Tj5V zTl&K-Ex?Yf0Aa94WdVj1f@bCL6I2Je2^~RN`d3iaK6QMa*7EUx3hxV&Ir$R20I;b< z1AcN-!$D&eAw?l25b4bgtoQa`(GXFBfq%MNMvR|u8w0b3*#mSjfvQJog=>-7zl=bh zgGTQs>EZh7zKox69pr!CLf8Q}!KHV3IQ285yVmxquI?6YNRhb08L)z+31QMtKflpH zWP)NI(R^+_hPK_;zhVDXqld#Fw^k7(C`|yhm}=K3{OH`Z#(L^Bx98;pLLmsB75BRU zfaJzi7DAycgs^xZ^BnXX7=AAyCmTW)?_=aa5DL5XfA29Rgk=@!KWFVD1Ug9Gj8lMv%7rbW4YZ#bRwpG|p3PpY7MWediQ5U0SZ`Lnre z@qPsr@H!M6tgp&FZ-8>H?wEgOJ!e_R-kNYDuUbb)6PBzUAdAj1Zv|1F&b0z9>NV7+2B4b;&1 z!YMoSp&5PpffPX$RJhmf=EF~5tsLP@1og7C-r{dPSVJ><#l$n~S?O_?btpg;E?{4{ zrwm?L%h9-jhhzU&au0rvK;Q<;i*^I9M0mBeZ8XF)-Ru3o+I(XGBxA@Ulr$o~}T}U8wDUKLn6T6FMtYt&8T;6VOe(q>|zKrQsf= z_+PF6Gw>4yj;5FH9omE^#-hJEcLs1lkN;~fRF4q$tW6{@Mk#T`lEX}QPXXFRd}!$! zoKXJv{&~t!xITD)35rDY{Kd(|MN8MkM95ZSd5G=*8ZaV+k^Tlh)*zkwli>>qZiq0V Z3-TWtSR+r;q;%XdLPbltMDbDh{{cSx!5jbp literal 0 HcmV?d00001 diff --git a/docs/images/logo/ruby-logo-124px.jpeg b/docs/images/logo/ruby-logo-124px.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..f1fc0df851631b4ca2cebd0c23da287f4b04cd87 GIT binary patch literal 3935 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 literal 0 HcmV?d00001 diff --git a/docs/images/logo/ruby-logo-198px.svg b/docs/images/logo/ruby-logo-198px.svg new file mode 100644 index 0000000..59cf324 --- /dev/null +++ b/docs/images/logo/ruby-logo-198px.svg @@ -0,0 +1,948 @@ + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..f919192 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,377 @@ + + + + + + + File: README + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
+ + +

+ + Galtzo.com Logo by Aboling0, CC BY-SA 4.0 + + + OmniAuth Logo possibly by Ted O'Meara, license unknown + + + OmniAuth Logo possibly by Ted O'Meara, license unknown + + + Yukihiro Matsumoto, Ruby Visual Identity Team, CC BY-SA 2.5 + +

+ +

🫵 OmniAuth::OpenID

+ +

Version License: MIT Downloads Rank Open Source Helpers Depfu CodeCov Test Coverage Coveralls Test Coverage QLTY Test Coverage QLTY Maintainability CI Heads CI Runtime Dependencies @ HEAD CI Current CI JRuby CI Supported CI Legacy CI Unsupported CI Ancient CI Test Coverage CI Style

+ +
+ +

Liberapay Goal Progress Sponsor Me on Github Buy me a coffee Donate on Polar Donate to my FLOSS or refugee efforts at ko-fi.com Donate to my FLOSS or refugee efforts using Patreon

+ +

Provides strategies for authenticating to providers using the OpenID v2 standard, which is deprecated, and very old. It is not for the modern OpenID Connect (OIDC) standard. For OpenID Connect (OIDC) check out: omniauth/omniauth_openid_connect

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Tokens to Remember +Gem name Gem namespace +
Works with JRuby +JRuby 9.2 Compat JRuby 9.3 Compat JRuby 9.4 Compat JRuby 10.0 Compat JRuby HEAD Compat +
Works with MRI Ruby 3 +Ruby 3.0 Compat Ruby 3.1 Compat Ruby 3.2 Compat Ruby 3.3 Compat Ruby 3.4 Compat Ruby HEAD Compat +
Works with MRI Ruby 2 +Ruby 2.4 Compat Ruby 2.5 Compat Ruby 2.6 Compat Ruby 2.7 Compat +
Source +Source on GitLab.com Source on CodeBerg.org Source on Github.com The best SHA: dQw4w9WgXcQ! +
Documentation +Current release on RubyDoc.info YARD on Galtzo.com BDFL Blog Wiki +
Compliance +License: MIT 📄ilo-declaration-img Security Policy Contributor Covenant 2.1 SemVer 2.0.0 +
Style +Enforced Code Style Linter Keep-A-Changelog 1.0.0 Gitmoji Commits +
Support +Live Chat on Discord Get help from me on Upwork Get help from me on Codementor +
Enterprise Support +Get help from me on Tidelift
💡Subscribe for support guarantees covering all FLOSS dependencies!
💡Tidelift is part of Sonar!
💡Tidelift pays maintainers to maintain the software you depend on!
📊@Pointy Haired Boss: An enterprise support subscription is “never gonna let you down”, and supports open source maintainers!
Comrade BDFL 🎖️ +Follow Me on LinkedIn Follow Me on Ruby.Social Follow Me on Bluesky Contact BDFL My technical writing +
+... 💖 +Find Me on WellFound: Find Me on CrunchBase My LinkTree More About Me 🧊 🐙 🛖 🧪 +
+ +

✨ Installation

+ +

Install the gem and add to the application’s Gemfile by executing:

+ +
$ bundle add omniauth-openid
+
+ +

If bundler is not being used to manage dependencies, install the gem by executing:

+ +
$ gem install omniauth-openid
+
+ +

🔒 Secure Installation

+ +

omniauth-openid is cryptographically signed, and has verifiable SHA-256 and SHA-512 checksums by
+stone_checksums. Be sure the gem you install hasn’t been tampered with
+by following the instructions below.

+ +

Add my public key (if you haven’t already, expires 2045-04-29) as a trusted certificate:

+ +
gem cert --add <(curl -Ls https://raw.github.com/omniauth/omniauth-openid/main/certs/pboling.pem)
+
+ +

You only need to do that once. Then proceed to install with:

+ +
gem install omniauth-openid -P MediumSecurity
+
+ +

The MediumSecurity trust profile will verify signed gems, but allow the installation of unsigned dependencies.

+ +

This is necessary because not all of omniauth-openid’s dependencies are signed, so we cannot use HighSecurity.

+ +

If you want to up your security game full-time:

+ +
bundle config set --global trust-policy MediumSecurity
+
+ +

NOTE: Be prepared to track down certs for signed gems and add them the same way you added mine.

+ +

🔧 Compatibility

+ +

+ +

🔧 Basic Usage

+ +

Use the strategy as a middleware in your application:

+ +
require "omniauth-openid"
+require "openid/store/filesystem"
+
+use Rack::Session::Cookie
+use OmniAuth::Strategies::OpenID, store: OpenID::Store::Filesystem.new("/tmp")
+
+ +

Then simply direct users to /auth/open_id to prompt them for their OpenID identifier. You may also pre-set the identifier by passing an identifier parameter to the URL (Example: /auth/open_id?openid_url=yahoo.com).

+ +

A list of all OpenID stores is available at http://github.com/openid/ruby-openid/tree/master/lib/openid/store/

+ +

OmniAuth Builder

+ +

If OpenID is one of several authentication strategies, use the OmniAuth Builder:

+ +
require "omniauth-openid"
+require "openid/store/filesystem"
+
+use OmniAuth::Builder do
+  provider :open_id, store: OpenID::Store::Filesystem.new("/tmp")
+end
+
+ +

Configured Identifiers

+ +

You may pre-configure an OpenID identifier. For example, to use Google’s main OpenID endpoint:

+ +
use OmniAuth::Builder do
+  provider :open_id, nil, :name => 'google', :identifier => 'https://www.google.com/accounts/o8/id'
+end
+
+ +

Note the use of nil, which will trigger ruby-openid’s default Memory Store.

+ +

Please contribute some documentation if you have the gumption! The maintainer’s time is limited, and sometimes the authors of PRs with new options don’t update the this readme. 😭

+ +

🔐 Security

+ +

See SECURITY.md.

+ +

🤝 Contributing

+ +

If you need some ideas of where to help, you could work on adding more code coverage,
+or if it is already 💯 (see below) check issues, or PRs,
+or use the gem and think about how it could be better.

+ +

We Keep A Changelog so if you make changes, remember to update it.

+ +

See CONTRIBUTING.md for more detailed instructions.

+ +

🚀 Release Instructions

+ +

See CONTRIBUTING.md.

+ +

Code Coverage

+ +

Coverage Graph

+ +

🪇 Code of Conduct

+ +

Everyone interacting with this project’s codebases, issue trackers,
+chat rooms and mailing lists agrees to follow the Contributor Covenant 2.1.

+ +

🌈 Contributors

+ +

Contributors

+ +

Made with contributors-img.

+ +

⭐️ Star History

+ +

+ + + + Star History Chart + +

</a>

+ +

📌 Versioning

+ +

This Library adheres to Semantic Versioning 2.0.0.
+Violations of this scheme should be reported as bugs.
+Specifically, if a minor or patch version is released that breaks backward compatibility,
+a new version should be immediately released that restores compatibility.
+Breaking changes to the public API will only be introduced with new major versions.

+ +

📌 Is “Platform Support” part of the public API?

+ +

Yes. But I’m obligated to include notes…

+ +

SemVer should, but doesn’t explicitly, say that dropping support for specific Platforms
+is a breaking change to an API.
+It is obvious to many, but not all, and since the spec is silent, the bike shedding is endless.

+ +
+

dropping support for a platform is both obviously and objectively a breaking change

+
+ + + +

To get a better understanding of how SemVer is intended to work over a project’s lifetime,
+read this article from the creator of SemVer:

+ + + +

As a result of this policy, and the interpretive lens used by the maintainer,
+you can (and should) specify a dependency on these libraries using
+the Pessimistic Version Constraint with two digits of precision.

+ +

For example:

+ +
spec.add_dependency("omniauth-openid", "~> 3.1")
+
+ +

See CHANGELOG.md for a list of releases.

+ +

📄 License

+ +

The gem is available as open source under the terms of
+the MIT License License: MIT.
+See LICENSE.txt for the official Copyright Notice.

+ + + +
    +
  • + Copyright (c) 2025 Peter H. Boling, of + + Galtzo.com + + Galtzo.com Logo by Aboling0, CC BY-SA 4.0 + + , and omniauth-openid contributors +
  • +
  • + 2010-2011 Michael Bleigh, and Intridea, Inc. +
  • +
+ +

🤑 One more thing

+ +

You made it to the bottom of the page,
+so perhaps you’ll indulge me for another 20 seconds.
+I maintain many dozens of gems, including this one,
+because I want Ruby to be a great place for people to solve problems, big and small.
+Please consider supporting my efforts via the giant yellow link below,
+or one of the others at the head of this README.

+ +

Buy me a latte

+ +
+ + + +
+ + \ No newline at end of file diff --git a/docs/js/app.js b/docs/js/app.js new file mode 100644 index 0000000..b5610ef --- /dev/null +++ b/docs/js/app.js @@ -0,0 +1,344 @@ +(function () { + var localStorage = {}, + sessionStorage = {}; + try { + localStorage = window.localStorage; + } catch (e) {} + try { + sessionStorage = window.sessionStorage; + } catch (e) {} + + function createSourceLinks() { + $(".method_details_list .source_code").before( + "[View source]" + ); + $(".toggleSource").toggle( + function () { + $(this).parent().nextAll(".source_code").slideDown(100); + $(this).text("Hide source"); + }, + function () { + $(this).parent().nextAll(".source_code").slideUp(100); + $(this).text("View source"); + } + ); + } + + function createDefineLinks() { + var tHeight = 0; + $(".defines").after(" more..."); + $(".toggleDefines").toggle( + function () { + tHeight = $(this).parent().prev().height(); + $(this).prev().css("display", "inline"); + $(this).parent().prev().height($(this).parent().height()); + $(this).text("(less)"); + }, + function () { + $(this).prev().hide(); + $(this).parent().prev().height(tHeight); + $(this).text("more..."); + } + ); + } + + function createFullTreeLinks() { + var tHeight = 0; + $(".inheritanceTree").toggle( + function () { + tHeight = $(this).parent().prev().height(); + $(this).parent().toggleClass("showAll"); + $(this).text("(hide)"); + $(this).parent().prev().height($(this).parent().height()); + }, + function () { + $(this).parent().toggleClass("showAll"); + $(this).parent().prev().height(tHeight); + $(this).text("show all"); + } + ); + } + + function searchFrameButtons() { + $(".full_list_link").click(function () { + toggleSearchFrame(this, $(this).attr("href")); + return false; + }); + window.addEventListener("message", function (e) { + if (e.data === "navEscape") { + $("#nav").slideUp(100); + $("#search a").removeClass("active inactive"); + $(window).focus(); + } + }); + + $(window).resize(function () { + if ($("#search:visible").length === 0) { + $("#nav").removeAttr("style"); + $("#search a").removeClass("active inactive"); + $(window).focus(); + } + }); + } + + function toggleSearchFrame(id, link) { + var frame = $("#nav"); + $("#search a").removeClass("active").addClass("inactive"); + if (frame.attr("src") === link && frame.css("display") !== "none") { + frame.slideUp(100); + $("#search a").removeClass("active inactive"); + } else { + $(id).addClass("active").removeClass("inactive"); + if (frame.attr("src") !== link) frame.attr("src", link); + frame.slideDown(100); + } + } + + function linkSummaries() { + $(".summary_signature").click(function () { + document.location = $(this).find("a").attr("href"); + }); + } + + function summaryToggle() { + $(".summary_toggle").click(function (e) { + e.preventDefault(); + localStorage.summaryCollapsed = $(this).text(); + $(".summary_toggle").each(function () { + $(this).text($(this).text() == "collapse" ? "expand" : "collapse"); + var next = $(this).parent().parent().nextAll("ul.summary").first(); + if (next.hasClass("compact")) { + next.toggle(); + next.nextAll("ul.summary").first().toggle(); + } else if (next.hasClass("summary")) { + var list = $('
    '); + list.html(next.html()); + list.find(".summary_desc, .note").remove(); + list.find("a").each(function () { + $(this).html($(this).find("strong").html()); + $(this).parent().html($(this)[0].outerHTML); + }); + next.before(list); + next.toggle(); + } + }); + return false; + }); + if (localStorage.summaryCollapsed == "collapse") { + $(".summary_toggle").first().click(); + } else { + localStorage.summaryCollapsed = "expand"; + } + } + + function constantSummaryToggle() { + $(".constants_summary_toggle").click(function (e) { + e.preventDefault(); + localStorage.summaryCollapsed = $(this).text(); + $(".constants_summary_toggle").each(function () { + $(this).text($(this).text() == "collapse" ? "expand" : "collapse"); + var next = $(this).parent().parent().nextAll("dl.constants").first(); + if (next.hasClass("compact")) { + next.toggle(); + next.nextAll("dl.constants").first().toggle(); + } else if (next.hasClass("constants")) { + var list = $('
    '); + list.html(next.html()); + list.find("dt").each(function () { + $(this).addClass("summary_signature"); + $(this).text($(this).text().split("=")[0]); + if ($(this).has(".deprecated").length) { + $(this).addClass("deprecated"); + } + }); + // Add the value of the constant as "Tooltip" to the summary object + list.find("pre.code").each(function () { + console.log($(this).parent()); + var dt_element = $(this).parent().prev(); + var tooltip = $(this).text(); + if (dt_element.hasClass("deprecated")) { + tooltip = "Deprecated. " + tooltip; + } + dt_element.attr("title", tooltip); + }); + list.find(".docstring, .tags, dd").remove(); + next.before(list); + next.toggle(); + } + }); + return false; + }); + if (localStorage.summaryCollapsed == "collapse") { + $(".constants_summary_toggle").first().click(); + } else { + localStorage.summaryCollapsed = "expand"; + } + } + + function generateTOC() { + if ($("#filecontents").length === 0) return; + var _toc = $('
      '); + var show = false; + var toc = _toc; + var counter = 0; + var tags = ["h2", "h3", "h4", "h5", "h6"]; + var i; + var curli; + if ($("#filecontents h1").length > 1) tags.unshift("h1"); + for (i = 0; i < tags.length; i++) { + tags[i] = "#filecontents " + tags[i]; + } + var lastTag = parseInt(tags[0][1], 10); + $(tags.join(", ")).each(function () { + if ($(this).parents(".method_details .docstring").length != 0) return; + if (this.id == "filecontents") return; + show = true; + var thisTag = parseInt(this.tagName[1], 10); + if (this.id.length === 0) { + var proposedId = $(this).attr("toc-id"); + if (typeof proposedId != "undefined") this.id = proposedId; + else { + var proposedId = $(this) + .text() + .replace(/[^a-z0-9-]/gi, "_"); + if ($("#" + proposedId).length > 0) { + proposedId += counter; + counter++; + } + this.id = proposedId; + } + } + if (thisTag > lastTag) { + for (i = 0; i < thisTag - lastTag; i++) { + if (typeof curli == "undefined") { + curli = $("
    1. "); + toc.append(curli); + } + toc = $("
        "); + curli.append(toc); + curli = undefined; + } + } + if (thisTag < lastTag) { + for (i = 0; i < lastTag - thisTag; i++) { + toc = toc.parent(); + toc = toc.parent(); + } + } + var title = $(this).attr("toc-title"); + if (typeof title == "undefined") title = $(this).text(); + curli = $('
      1. ' + title + "
      2. "); + toc.append(curli); + lastTag = thisTag; + }); + if (!show) return; + html = + ''; + $("#content").prepend(html); + $("#toc").append(_toc); + $("#toc .hide_toc").toggle( + function () { + $("#toc .top").slideUp("fast"); + $("#toc").toggleClass("hidden"); + $("#toc .title small").toggle(); + }, + function () { + $("#toc .top").slideDown("fast"); + $("#toc").toggleClass("hidden"); + $("#toc .title small").toggle(); + } + ); + } + + function navResizeFn(e) { + if (e.which !== 1) { + navResizeFnStop(); + return; + } + + sessionStorage.navWidth = e.pageX.toString(); + $(".nav_wrap").css("width", e.pageX); + $(".nav_wrap").css("-ms-flex", "inherit"); + } + + function navResizeFnStop() { + $(window).unbind("mousemove", navResizeFn); + window.removeEventListener("message", navMessageFn, false); + } + + function navMessageFn(e) { + if (e.data.action === "mousemove") navResizeFn(e.data.event); + if (e.data.action === "mouseup") navResizeFnStop(); + } + + function navResizer() { + $("#resizer").mousedown(function (e) { + e.preventDefault(); + $(window).mousemove(navResizeFn); + window.addEventListener("message", navMessageFn, false); + }); + $(window).mouseup(navResizeFnStop); + + if (sessionStorage.navWidth) { + navResizeFn({ which: 1, pageX: parseInt(sessionStorage.navWidth, 10) }); + } + } + + function navExpander() { + if (typeof pathId === "undefined") return; + var done = false, + timer = setTimeout(postMessage, 500); + function postMessage() { + if (done) return; + clearTimeout(timer); + var opts = { action: "expand", path: pathId }; + document.getElementById("nav").contentWindow.postMessage(opts, "*"); + done = true; + } + + window.addEventListener( + "message", + function (event) { + if (event.data === "navReady") postMessage(); + return false; + }, + false + ); + } + + function mainFocus() { + var hash = window.location.hash; + if (hash !== "" && $(hash)[0]) { + $(hash)[0].scrollIntoView(); + } + + setTimeout(function () { + $("#main").focus(); + }, 10); + } + + function navigationChange() { + // This works around the broken anchor navigation with the YARD template. + window.onpopstate = function () { + var hash = window.location.hash; + if (hash !== "" && $(hash)[0]) { + $(hash)[0].scrollIntoView(); + } + }; + } + + $(document).ready(function () { + navResizer(); + navExpander(); + createSourceLinks(); + createDefineLinks(); + createFullTreeLinks(); + searchFrameButtons(); + linkSummaries(); + summaryToggle(); + constantSummaryToggle(); + generateTOC(); + mainFocus(); + navigationChange(); + }); +})(); diff --git a/docs/js/full_list.js b/docs/js/full_list.js new file mode 100644 index 0000000..12bba48 --- /dev/null +++ b/docs/js/full_list.js @@ -0,0 +1,242 @@ +(function() { + +var $clicked = $(null); +var searchTimeout = null; +var searchCache = []; +var caseSensitiveMatch = false; +var ignoreKeyCodeMin = 8; +var ignoreKeyCodeMax = 46; +var commandKey = 91; + +RegExp.escape = function(text) { + return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); +} + +function escapeShortcut() { + $(document).keydown(function(evt) { + if (evt.which == 27) { + window.parent.postMessage('navEscape', '*'); + } + }); +} + +function navResizer() { + $(window).mousemove(function(e) { + window.parent.postMessage({ + action: 'mousemove', event: {pageX: e.pageX, which: e.which} + }, '*'); + }).mouseup(function(e) { + window.parent.postMessage({action: 'mouseup'}, '*'); + }); + window.parent.postMessage("navReady", "*"); +} + +function clearSearchTimeout() { + clearTimeout(searchTimeout); + searchTimeout = null; +} + +function enableLinks() { + // load the target page in the parent window + $('#full_list li').on('click', function(evt) { + $('#full_list li').removeClass('clicked'); + $clicked = $(this); + $clicked.addClass('clicked'); + evt.stopPropagation(); + + if (evt.target.tagName === 'A') return true; + + var elem = $clicked.find('> .item .object_link a')[0]; + var e = evt.originalEvent; + var newEvent = new MouseEvent(evt.originalEvent.type); + newEvent.initMouseEvent(e.type, e.canBubble, e.cancelable, e.view, e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget); + elem.dispatchEvent(newEvent); + evt.preventDefault(); + return false; + }); +} + +function enableToggles() { + // show/hide nested classes on toggle click + $('#full_list a.toggle').on('click', function(evt) { + evt.stopPropagation(); + evt.preventDefault(); + $(this).parent().parent().toggleClass('collapsed'); + $(this).attr('aria-expanded', function (i, attr) { + return attr == 'true' ? 'false' : 'true' + }); + highlight(); + }); + + // navigation of nested classes using keyboard + $('#full_list a.toggle').on('keypress',function(evt) { + // enter key is pressed + if (evt.which == 13) { + evt.stopPropagation(); + evt.preventDefault(); + $(this).parent().parent().toggleClass('collapsed'); + $(this).attr('aria-expanded', function (i, attr) { + return attr == 'true' ? 'false' : 'true' + }); + highlight(); + } + }); +} + +function populateSearchCache() { + $('#full_list li .item').each(function() { + var $node = $(this); + var $link = $node.find('.object_link a'); + if ($link.length > 0) { + searchCache.push({ + node: $node, + link: $link, + name: $link.text(), + fullName: $link.attr('title').split(' ')[0] + }); + } + }); +} + +function enableSearch() { + $('#search input').keyup(function(event) { + if (ignoredKeyPress(event)) return; + if (this.value === "") { + clearSearch(); + } else { + performSearch(this.value); + } + }); + + $('#full_list').after(""); +} + +function ignoredKeyPress(event) { + if ( + (event.keyCode > ignoreKeyCodeMin && event.keyCode < ignoreKeyCodeMax) || + (event.keyCode == commandKey) + ) { + return true; + } else { + return false; + } +} + +function clearSearch() { + clearSearchTimeout(); + $('#full_list .found').removeClass('found').each(function() { + var $link = $(this).find('.object_link a'); + $link.text($link.text()); + }); + $('#full_list, #content').removeClass('insearch'); + $clicked.parents().removeClass('collapsed'); + highlight(); +} + +function performSearch(searchString) { + clearSearchTimeout(); + $('#full_list, #content').addClass('insearch'); + $('#noresults').text('').hide(); + partialSearch(searchString, 0); +} + +function partialSearch(searchString, offset) { + var lastRowClass = ''; + var i = null; + for (i = offset; i < Math.min(offset + 50, searchCache.length); i++) { + var item = searchCache[i]; + var searchName = (searchString.indexOf('::') != -1 ? item.fullName : item.name); + var matchString = buildMatchString(searchString); + var matchRegexp = new RegExp(matchString, caseSensitiveMatch ? "" : "i"); + if (searchName.match(matchRegexp) == null) { + item.node.removeClass('found'); + item.link.text(item.link.text()); + } + else { + item.node.addClass('found'); + item.node.removeClass(lastRowClass).addClass(lastRowClass == 'r1' ? 'r2' : 'r1'); + lastRowClass = item.node.hasClass('r1') ? 'r1' : 'r2'; + item.link.html(item.name.replace(matchRegexp, "$&")); + } + } + if(i == searchCache.length) { + searchDone(); + } else { + searchTimeout = setTimeout(function() { + partialSearch(searchString, i); + }, 0); + } +} + +function searchDone() { + searchTimeout = null; + highlight(); + var found = $('#full_list li:visible').size(); + if (found === 0) { + $('#noresults').text('No results were found.'); + } else { + // This is read out to screen readers + $('#noresults').text('There are ' + found + ' results.'); + } + $('#noresults').show(); + $('#content').removeClass('insearch'); +} + +function buildMatchString(searchString, event) { + caseSensitiveMatch = searchString.match(/[A-Z]/) != null; + var regexSearchString = RegExp.escape(searchString); + if (caseSensitiveMatch) { + regexSearchString += "|" + + $.map(searchString.split(''), function(e) { return RegExp.escape(e); }). + join('.+?'); + } + return regexSearchString; +} + +function highlight() { + $('#full_list li:visible').each(function(n) { + $(this).removeClass('even odd').addClass(n % 2 == 0 ? 'odd' : 'even'); + }); +} + +/** + * Expands the tree to the target element and its immediate + * children. + */ +function expandTo(path) { + var $target = $(document.getElementById('object_' + path)); + $target.addClass('clicked'); + $target.removeClass('collapsed'); + $target.parentsUntil('#full_list', 'li').removeClass('collapsed'); + + $target.find('a.toggle').attr('aria-expanded', 'true') + $target.parentsUntil('#full_list', 'li').each(function(i, el) { + $(el).find('> div > a.toggle').attr('aria-expanded', 'true'); + }); + + if($target[0]) { + window.scrollTo(window.scrollX, $target.offset().top - 250); + highlight(); + } +} + +function windowEvents(event) { + var msg = event.data; + if (msg.action === "expand") { + expandTo(msg.path); + } + return false; +} + +window.addEventListener("message", windowEvents, false); + +$(document).ready(function() { + escapeShortcut(); + navResizer(); + enableLinks(); + enableToggles(); + populateSearchCache(); + enableSearch(); +}); + +})(); diff --git a/docs/js/jquery.js b/docs/js/jquery.js new file mode 100644 index 0000000..198b3ff --- /dev/null +++ b/docs/js/jquery.js @@ -0,0 +1,4 @@ +/*! jQuery v1.7.1 jquery.com | jquery.org/license */ +(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!ck[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cl||(cl=c.createElement("iframe"),cl.frameBorder=cl.width=cl.height=0),b.appendChild(cl);if(!cm||!cl.createElement)cm=(cl.contentWindow||cl.contentDocument).document,cm.write((c.compatMode==="CSS1Compat"?"":"")+""),cm.close();d=cm.createElement(a),cm.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cl)}ck[a]=e}return ck[a]}function cu(a,b){var c={};f.each(cq.concat.apply([],cq.slice(0,b)),function(){c[this]=a});return c}function ct(){cr=b}function cs(){setTimeout(ct,0);return cr=f.now()}function cj(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ci(){try{return new a.XMLHttpRequest}catch(b){}}function cc(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g0){if(c!=="border")for(;g=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c
        a",d=q.getElementsByTagName("*"),e=q.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=q.getElementsByTagName("input")[0],b={leadingWhitespace:q.firstChild.nodeType===3,tbody:!q.getElementsByTagName("tbody").length,htmlSerialize:!!q.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:q.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete q.test}catch(s){b.deleteExpando=!1}!q.addEventListener&&q.attachEvent&&q.fireEvent&&(q.attachEvent("onclick",function(){b.noCloneEvent=!1}),q.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),q.appendChild(i),k=c.createDocumentFragment(),k.appendChild(q.lastChild),b.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,k.removeChild(i),k.appendChild(q),q.innerHTML="",a.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",q.style.width="2px",q.appendChild(j),b.reliableMarginRight=(parseInt((a.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(q.attachEvent)for(o in{submit:1,change:1,focusin:1})n="on"+o,p=n in q,p||(q.setAttribute(n,"return;"),p=typeof q[n]=="function"),b[o+"Bubbles"]=p;k.removeChild(q),k=g=h=j=q=i=null,f(function(){var a,d,e,g,h,i,j,k,m,n,o,r=c.getElementsByTagName("body")[0];!r||(j=1,k="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",m="visibility:hidden;border:0;",n="style='"+k+"border:5px solid #000;padding:0;'",o="
        "+""+"
        ",a=c.createElement("div"),a.style.cssText=m+"width:0;height:0;position:static;top:0;margin-top:"+j+"px",r.insertBefore(a,r.firstChild),q=c.createElement("div"),a.appendChild(q),q.innerHTML="
        t
        ",l=q.getElementsByTagName("td"),p=l[0].offsetHeight===0,l[0].style.display="",l[1].style.display="none",b.reliableHiddenOffsets=p&&l[0].offsetHeight===0,q.innerHTML="",q.style.width=q.style.paddingLeft="1px",f.boxModel=b.boxModel=q.offsetWidth===2,typeof q.style.zoom!="undefined"&&(q.style.display="inline",q.style.zoom=1,b.inlineBlockNeedsLayout=q.offsetWidth===2,q.style.display="",q.innerHTML="
        ",b.shrinkWrapBlocks=q.offsetWidth!==2),q.style.cssText=k+m,q.innerHTML=o,d=q.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,i={doesNotAddBorder:e.offsetTop!==5,doesAddBorderForTableAndCells:h.offsetTop===5},e.style.position="fixed",e.style.top="20px",i.fixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",i.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,i.doesNotIncludeMarginInBodyOffset=r.offsetTop!==j,r.removeChild(a),q=a=null,f.extend(b,i))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;h=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/\bhover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")}; +f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;le&&i.push({elem:this,matches:d.slice(e)});for(j=0;j0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

        ";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
        ";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h0)for(h=g;h=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/",""],legend:[1,"
        ","
        "],thead:[1,"","
        "],tr:[2,"","
        "],td:[3,"","
        "],col:[2,"","
        "],area:[1,"",""],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div
        ","
        "]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function() +{for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1>");try{for(var c=0,d=this.length;c1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||!bc.test("<"+a.nodeName)?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");b===c?bh.appendChild(o):U(b).appendChild(o),o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]===""&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return br.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bq,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bq.test(g)?g.replace(bq,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,b){var c,d,e;b=b.replace(bs,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b)));return c}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f===null&&g&&(e=g[b])&&(f=e),!bt.test(f)&&bu.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f||0,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bD=/%20/g,bE=/\[\]$/,bF=/\r?\n/g,bG=/#.*$/,bH=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bI=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bJ=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bK=/^(?:GET|HEAD)$/,bL=/^\/\//,bM=/\?/,bN=/)<[^<]*)*<\/script>/gi,bO=/^(?:select|textarea)/i,bP=/\s+/,bQ=/([?&])_=[^&]*/,bR=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bS=f.fn.load,bT={},bU={},bV,bW,bX=["*/"]+["*"];try{bV=e.href}catch(bY){bV=c.createElement("a"),bV.href="",bV=bV.href}bW=bR.exec(bV.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bS)return bS.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("
        ").append(c.replace(bN,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bO.test(this.nodeName)||bI.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bF,"\r\n")}}):{name:b.name,value:c.replace(bF,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b_(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b_(a,b);return a},ajaxSettings:{url:bV,isLocal:bJ.test(bW[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bX},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bZ(bT),ajaxTransport:bZ(bU),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?cb(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cc(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bH.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bG,"").replace(bL,bW[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bP),d.crossDomain==null&&(r=bR.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bW[1]&&r[2]==bW[2]&&(r[3]||(r[1]==="http:"?80:443))==(bW[3]||(bW[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),b$(bT,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bK.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bM.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bQ,"$1_="+x);d.url=y+(y===d.url?(bM.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bX+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=b$(bU,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)ca(g,a[g],c,e);return d.join("&").replace(bD,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cd=f.now(),ce=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cd++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ce.test(b.url)||e&&ce.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ce,l),b.url===j&&(e&&(k=k.replace(ce,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cf=a.ActiveXObject?function(){for(var a in ch)ch[a](0,1)}:!1,cg=0,ch;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ci()||cj()}:ci,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cf&&delete ch[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cg,cf&&(ch||(ch={},f(a).unload(cf)),ch[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var ck={},cl,cm,cn=/^(?:toggle|show|hide)$/,co=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cp,cq=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cr;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cu("show",3),a,b,c);for(var g=0,h=this.length;g=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cy(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cy(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,d,"padding")):this[d]():null},f.fn["outer"+c]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,d,a?"margin":"border")):this[d]():null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNumeric(j)?j:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window); \ No newline at end of file diff --git a/docs/method_list.html b/docs/method_list.html new file mode 100644 index 0000000..1a193e3 --- /dev/null +++ b/docs/method_list.html @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + Method List + + + +
        +
        +

        Method List

        + + + +
        + + +
        + + diff --git a/docs/top-level-namespace.html b/docs/top-level-namespace.html new file mode 100644 index 0000000..40a8409 --- /dev/null +++ b/docs/top-level-namespace.html @@ -0,0 +1,110 @@ + + + + + + + Top Level Namespace + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
        + + +

        Top Level Namespace + + + +

        +
        + + + + + + + + + + + +
        + +

        Defined Under Namespace

        +

        + + + Modules: OmniAuth + + + + +

        + + + + + + + + + +
        + + + +
        + + \ No newline at end of file diff --git a/examples/sinatra.rb b/examples/sinatra.rb index ec72f0e..ea90f46 100644 --- a/examples/sinatra.rb +++ b/examples/sinatra.rb @@ -1,18 +1,18 @@ -require 'rubygems' -require 'bundler' +require "rubygems" +require "bundler" -Bundler.setup :default, :development, :example -require 'sinatra' -require 'omniauth-openid' -require 'openid/store/filesystem' +Bundler.setup(:default, :development, :example) +require "sinatra" +require "omniauth-openid" +require "openid/store/filesystem" use Rack::Session::Cookie use OmniAuth::Builder do - provider :open_id, store: OpenID::Store::Filesystem.new('/tmp') + provider :open_id, store: OpenID::Store::Filesystem.new("/tmp") end -get '/' do +get "/" do <<-HTML
        • Sign in with OpenID
        • @@ -21,8 +21,8 @@ end [:get, :post].each do |method| - send method, '/auth/:provider/callback' do - content_type 'text/plain' - request.env['omniauth.auth'].info.to_hash.inspect + send method, "/auth/:provider/callback" do + content_type "text/plain" + request.env["omniauth.auth"].info.to_hash.inspect end end diff --git a/gemfiles/audit.gemfile b/gemfiles/audit.gemfile new file mode 100644 index 0000000..55a3252 --- /dev/null +++ b/gemfiles/audit.gemfile @@ -0,0 +1,11 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec path: "../" + +eval_gemfile("modular/omniauth/r3/v2.1.gemfile") + +eval_gemfile("modular/audit.gemfile") + +eval_gemfile("modular/x_std_libs/r3/libs.gemfile") diff --git a/gemfiles/coverage.gemfile b/gemfiles/coverage.gemfile new file mode 100644 index 0000000..df99a74 --- /dev/null +++ b/gemfiles/coverage.gemfile @@ -0,0 +1,13 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gem "ostruct", "~> 0.6", ">= 0.6.1" + +gemspec path: "../" + +eval_gemfile("modular/omniauth/r3/v2.1.gemfile") + +eval_gemfile("modular/coverage.gemfile") + +eval_gemfile("modular/x_std_libs/r3/libs.gemfile") diff --git a/gemfiles/dep_heads.gemfile b/gemfiles/dep_heads.gemfile new file mode 100644 index 0000000..8bdbd09 --- /dev/null +++ b/gemfiles/dep_heads.gemfile @@ -0,0 +1,7 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec path: "../" + +eval_gemfile("modular/runtime_heads.gemfile") diff --git a/gemfiles/modular/audit.gemfile b/gemfiles/modular/audit.gemfile new file mode 100755 index 0000000..e5cc919 --- /dev/null +++ b/gemfiles/modular/audit.gemfile @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +# Many gems are dropping support for Ruby < 3, +# so we only want to run our security audit in CI on Ruby 3+ +gem "bundler-audit", "~> 0.9.2" diff --git a/gemfiles/modular/coverage.gemfile b/gemfiles/modular/coverage.gemfile new file mode 100755 index 0000000..5ef0c45 --- /dev/null +++ b/gemfiles/modular/coverage.gemfile @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +# We run code coverage on the latest version of Ruby only. + +# Coverage +gem "kettle-soup-cover", "~> 1.0", ">= 1.0.6", require: false diff --git a/gemfiles/modular/documentation.gemfile b/gemfiles/modular/documentation.gemfile new file mode 100755 index 0000000..7853390 --- /dev/null +++ b/gemfiles/modular/documentation.gemfile @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +# Documentation +gem "kramdown", "~> 2.5", ">= 2.5.1" # Ruby >= 2.5 +gem "kramdown-parser-gfm", "~> 1.1" # Ruby >= 2.3 +gem "yard", "~> 0.9", ">= 0.9.37", require: false +gem "yard-junk", "~> 0.0", ">= 0.0.10", github: "pboling/yard-junk", branch: "next", require: false +gem "yard-relative_markdown_links", "~> 0.5.0" + +# Std Lib extractions +gem "rdoc", "~> 6.11" diff --git a/gemfiles/modular/logger/r2.4/v1.5.3.gemfile b/gemfiles/modular/logger/r2.4/v1.5.3.gemfile new file mode 100644 index 0000000..a9236bc --- /dev/null +++ b/gemfiles/modular/logger/r2.4/v1.5.3.gemfile @@ -0,0 +1,3 @@ +# Ruby >= 2.3.0 +# Last version compatible with Ruby 2.4 +gem "logger", "~> 1.5.3" diff --git a/gemfiles/modular/logger/r2/v1.5.gemfile b/gemfiles/modular/logger/r2/v1.5.gemfile new file mode 100644 index 0000000..c4fc65e --- /dev/null +++ b/gemfiles/modular/logger/r2/v1.5.gemfile @@ -0,0 +1,3 @@ +# Ruby >= 2.3.0 +# Last version compatible with Ruby 2.4 +gem "logger", ">= 1.5.3", "< 2" diff --git a/gemfiles/modular/logger/r3/v1.7.gemfile b/gemfiles/modular/logger/r3/v1.7.gemfile new file mode 100644 index 0000000..f68bea9 --- /dev/null +++ b/gemfiles/modular/logger/r3/v1.7.gemfile @@ -0,0 +1,2 @@ +# Ruby >= 2.5.0 +gem "logger", "~> 1.7" diff --git a/gemfiles/modular/logger/vHEAD.gemfile b/gemfiles/modular/logger/vHEAD.gemfile new file mode 100644 index 0000000..81a6bb8 --- /dev/null +++ b/gemfiles/modular/logger/vHEAD.gemfile @@ -0,0 +1,2 @@ +# Ruby >= 2.5 (dependency of omniauth) +gem "logger", github: "ruby/logger", branch: "master" diff --git a/gemfiles/modular/mutex_m/r2.4/v0.1.gemfile b/gemfiles/modular/mutex_m/r2.4/v0.1.gemfile new file mode 100644 index 0000000..cabf980 --- /dev/null +++ b/gemfiles/modular/mutex_m/r2.4/v0.1.gemfile @@ -0,0 +1,3 @@ +# Ruby >= 0 +# Last version supporting Ruby <= 2.4 +gem "mutex_m", "~> 0.1" diff --git a/gemfiles/modular/mutex_m/r2/v0.3.gemfile b/gemfiles/modular/mutex_m/r2/v0.3.gemfile new file mode 100644 index 0000000..42e9d9b --- /dev/null +++ b/gemfiles/modular/mutex_m/r2/v0.3.gemfile @@ -0,0 +1,2 @@ +# Ruby >= 2.5 +gem "mutex_m", "~> 0.2" diff --git a/gemfiles/modular/mutex_m/r3/v0.3.gemfile b/gemfiles/modular/mutex_m/r3/v0.3.gemfile new file mode 100644 index 0000000..42e9d9b --- /dev/null +++ b/gemfiles/modular/mutex_m/r3/v0.3.gemfile @@ -0,0 +1,2 @@ +# Ruby >= 2.5 +gem "mutex_m", "~> 0.2" diff --git a/gemfiles/modular/mutex_m/vHEAD.gemfile b/gemfiles/modular/mutex_m/vHEAD.gemfile new file mode 100644 index 0000000..8af3b6f --- /dev/null +++ b/gemfiles/modular/mutex_m/vHEAD.gemfile @@ -0,0 +1,2 @@ +# Ruby >= 2.5 (dependency of omniauth) +gem "mutex_m", github: "ruby/mutex_m", branch: "master" diff --git a/gemfiles/modular/omniauth/r2/v1.0.gemfile b/gemfiles/modular/omniauth/r2/v1.0.gemfile new file mode 100644 index 0000000..fe51cfe --- /dev/null +++ b/gemfiles/modular/omniauth/r2/v1.0.gemfile @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +# Ruby >= 2.2 +# Released March 6, 2012 +gem "omniauth", "~> 1.0.3" diff --git a/gemfiles/modular/omniauth/r2/v1.1.gemfile b/gemfiles/modular/omniauth/r2/v1.1.gemfile new file mode 100644 index 0000000..053280c --- /dev/null +++ b/gemfiles/modular/omniauth/r2/v1.1.gemfile @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +# Ruby >= 2.2 +# Released April 8, 2013 +gem "omniauth", "~> 1.1.4" diff --git a/gemfiles/modular/omniauth/r2/v1.2.gemfile b/gemfiles/modular/omniauth/r2/v1.2.gemfile new file mode 100644 index 0000000..788293a --- /dev/null +++ b/gemfiles/modular/omniauth/r2/v1.2.gemfile @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +# Ruby >= 2.2 +# Released July 9, 2014 +gem "omniauth", "~> 1.2.2" diff --git a/gemfiles/modular/omniauth/r2/v1.3.gemfile b/gemfiles/modular/omniauth/r2/v1.3.gemfile new file mode 100644 index 0000000..1728f92 --- /dev/null +++ b/gemfiles/modular/omniauth/r2/v1.3.gemfile @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +# Ruby >= 2.2 +# Released January 17, 2017 +gem "omniauth", "~> 1.3.2" diff --git a/gemfiles/modular/omniauth/r2/v1.4.gemfile b/gemfiles/modular/omniauth/r2/v1.4.gemfile new file mode 100644 index 0000000..3bd871e --- /dev/null +++ b/gemfiles/modular/omniauth/r2/v1.4.gemfile @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +# Ruby >= 2.2 +# Released December 18, 2017 +gem "omniauth", "~> 1.4.3" diff --git a/gemfiles/modular/omniauth/r2/v1.5.gemfile b/gemfiles/modular/omniauth/r2/v1.5.gemfile new file mode 100644 index 0000000..387669b --- /dev/null +++ b/gemfiles/modular/omniauth/r2/v1.5.gemfile @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +# Ruby >= 2.1.9 +# Released February 11, 2017 +gem "omniauth", "~> 1.5.0" diff --git a/gemfiles/modular/omniauth/r2/v1.6.gemfile b/gemfiles/modular/omniauth/r2/v1.6.gemfile new file mode 100644 index 0000000..3eeab8a --- /dev/null +++ b/gemfiles/modular/omniauth/r2/v1.6.gemfile @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +# Ruby >= 2.1.9 +# Released February 18, 2017 +gem "omniauth", "~> 1.6.1" diff --git a/gemfiles/modular/omniauth/r2/v1.7.gemfile b/gemfiles/modular/omniauth/r2/v1.7.gemfile new file mode 100644 index 0000000..e91c085 --- /dev/null +++ b/gemfiles/modular/omniauth/r2/v1.7.gemfile @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +# Ruby >= 2.1.9 +# Released October 2, 2017 +gem "omniauth", "~> 1.7.1" diff --git a/gemfiles/modular/omniauth/r2/v1.8.gemfile b/gemfiles/modular/omniauth/r2/v1.8.gemfile new file mode 100644 index 0000000..92b60a3 --- /dev/null +++ b/gemfiles/modular/omniauth/r2/v1.8.gemfile @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +# Ruby >= 2.1.9 +# Released December 28, 2017 +gem "omniauth", "~> 1.8.1" diff --git a/gemfiles/modular/omniauth/r2/v1.9.gemfile b/gemfiles/modular/omniauth/r2/v1.9.gemfile new file mode 100644 index 0000000..7539d4f --- /dev/null +++ b/gemfiles/modular/omniauth/r2/v1.9.gemfile @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +# Ruby >= 2.2 +# Released August 18, 2022 +gem "omniauth", "~> 1.9.2" diff --git a/gemfiles/modular/omniauth/r2/v2.0.gemfile b/gemfiles/modular/omniauth/r2/v2.0.gemfile new file mode 100644 index 0000000..5682a6e --- /dev/null +++ b/gemfiles/modular/omniauth/r2/v2.0.gemfile @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +# Ruby >= 2.2 +# Released April 7, 2021 +gem "omniauth", "~> 2.0.4" diff --git a/gemfiles/modular/omniauth/r2/v2.1.gemfile b/gemfiles/modular/omniauth/r2/v2.1.gemfile new file mode 100644 index 0000000..38923d2 --- /dev/null +++ b/gemfiles/modular/omniauth/r2/v2.1.gemfile @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +# Ruby >= 2.2; first version compatible with Ruby >= 3 +# Released February 27, 2025 +gem "omniauth", "~> 2.1.3" diff --git a/gemfiles/modular/omniauth/r3/v2.1.gemfile b/gemfiles/modular/omniauth/r3/v2.1.gemfile new file mode 100644 index 0000000..38923d2 --- /dev/null +++ b/gemfiles/modular/omniauth/r3/v2.1.gemfile @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +# Ruby >= 2.2; first version compatible with Ruby >= 3 +# Released February 27, 2025 +gem "omniauth", "~> 2.1.3" diff --git a/gemfiles/modular/omniauth/vHEAD.gemfile b/gemfiles/modular/omniauth/vHEAD.gemfile new file mode 100644 index 0000000..a11e691 --- /dev/null +++ b/gemfiles/modular/omniauth/vHEAD.gemfile @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +# Ruby >= 2.2 +gem "omniauth", github: "omniauth/omniauth", branch: "master" diff --git a/gemfiles/modular/rack-openid/vHEAD.gemfile b/gemfiles/modular/rack-openid/vHEAD.gemfile new file mode 100644 index 0000000..32bafc5 --- /dev/null +++ b/gemfiles/modular/rack-openid/vHEAD.gemfile @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +# Ruby >= 2.2 +gem "rack-openid", github: "grosser/rack-openid", branch: "master" diff --git a/gemfiles/modular/runtime_heads.gemfile b/gemfiles/modular/runtime_heads.gemfile new file mode 100644 index 0000000..4d492bd --- /dev/null +++ b/gemfiles/modular/runtime_heads.gemfile @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +# Test against HEAD of runtime dependencies so we can proactively file bugs + +eval_gemfile("omniauth/vHEAD.gemfile") + +eval_gemfile("rack-openid/vHEAD.gemfile") + +# Ruby >= 2.2 +gem "version_gem", github: "oauth-xx/version_gem", branch: "main" + +eval_gemfile("x_std_libs/vHEAD.gemfile") diff --git a/gemfiles/modular/stringio/r2.4/v0.0.2.gemfile b/gemfiles/modular/stringio/r2.4/v0.0.2.gemfile new file mode 100644 index 0000000..94021cf --- /dev/null +++ b/gemfiles/modular/stringio/r2.4/v0.0.2.gemfile @@ -0,0 +1,4 @@ +# !!WARNING!! +# NOT SEMVER +# Last version to support Ruby <= 2.5 +gem "stringio", ">= 0.0.2" diff --git a/gemfiles/modular/stringio/r2/v3.0.gemfile b/gemfiles/modular/stringio/r2/v3.0.gemfile new file mode 100644 index 0000000..e85bb18 --- /dev/null +++ b/gemfiles/modular/stringio/r2/v3.0.gemfile @@ -0,0 +1,5 @@ +# !!WARNING!! +# NOT SEMVER +# Version 3.0.7 dropped support for Ruby <= 2.7 +# Version 3.0.0 dropped support for Ruby <= 2.4 +gem "stringio", ">= 3.0" diff --git a/gemfiles/modular/stringio/r3/v3.0.gemfile b/gemfiles/modular/stringio/r3/v3.0.gemfile new file mode 100644 index 0000000..e85bb18 --- /dev/null +++ b/gemfiles/modular/stringio/r3/v3.0.gemfile @@ -0,0 +1,5 @@ +# !!WARNING!! +# NOT SEMVER +# Version 3.0.7 dropped support for Ruby <= 2.7 +# Version 3.0.0 dropped support for Ruby <= 2.4 +gem "stringio", ">= 3.0" diff --git a/gemfiles/modular/stringio/vHEAD.gemfile b/gemfiles/modular/stringio/vHEAD.gemfile new file mode 100644 index 0000000..5f2a741 --- /dev/null +++ b/gemfiles/modular/stringio/vHEAD.gemfile @@ -0,0 +1,2 @@ +# Ruby >= 2.5 (dependency of omniauth) +gem "stringio", github: "ruby/stringio", branch: "master" diff --git a/gemfiles/modular/style.gemfile b/gemfiles/modular/style.gemfile new file mode 100755 index 0000000..ff260d7 --- /dev/null +++ b/gemfiles/modular/style.gemfile @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +# Use rubocop-lts to run rubocop on the latest version of Ruby +# with syntax support for the oldest allowed version of Ruby + +gem "reek", "~> 6.5" +gem "rubocop-lts", "~> 12.1", ">= 12.1.1" +gem "rubocop-packaging", "~> 0.6", ">= 0.6.0" +gem "rubocop-rspec", "~> 3.6" +gem "standard", ">= 1.50" + +# Std Lib extractions +gem "benchmark", "~> 0.4", ">= 0.4.1" # Removed from Std Lib in Ruby 3.5 diff --git a/gemfiles/modular/x_std_libs/r2.4/libs.gemfile b/gemfiles/modular/x_std_libs/r2.4/libs.gemfile new file mode 100644 index 0000000..2fad2c5 --- /dev/null +++ b/gemfiles/modular/x_std_libs/r2.4/libs.gemfile @@ -0,0 +1,3 @@ +eval_gemfile "../../mutex_m/r2.4/v0.1.gemfile" +eval_gemfile "../../stringio/r2.4/v0.0.2.gemfile" +eval_gemfile "../../logger/r2.4/v1.5.3.gemfile" diff --git a/gemfiles/modular/x_std_libs/r2/libs.gemfile b/gemfiles/modular/x_std_libs/r2/libs.gemfile new file mode 100644 index 0000000..9af481f --- /dev/null +++ b/gemfiles/modular/x_std_libs/r2/libs.gemfile @@ -0,0 +1,3 @@ +eval_gemfile "../../mutex_m/r2/v0.3.gemfile" +eval_gemfile "../../stringio/r2/v3.0.gemfile" +eval_gemfile "../../logger/r2/v1.5.gemfile" diff --git a/gemfiles/modular/x_std_libs/r3/libs.gemfile b/gemfiles/modular/x_std_libs/r3/libs.gemfile new file mode 100644 index 0000000..395cc00 --- /dev/null +++ b/gemfiles/modular/x_std_libs/r3/libs.gemfile @@ -0,0 +1,3 @@ +eval_gemfile "../../mutex_m/r3/v0.3.gemfile" +eval_gemfile "../../stringio/r3/v3.0.gemfile" +eval_gemfile "../../logger/r3/v1.7.gemfile" diff --git a/gemfiles/modular/x_std_libs/vHEAD.gemfile b/gemfiles/modular/x_std_libs/vHEAD.gemfile new file mode 100644 index 0000000..9624cb6 --- /dev/null +++ b/gemfiles/modular/x_std_libs/vHEAD.gemfile @@ -0,0 +1,3 @@ +eval_gemfile "../mutex_m/vHEAD.gemfile" +eval_gemfile "../stringio/vHEAD.gemfile" +eval_gemfile "../logger/vHEAD.gemfile" diff --git a/gemfiles/omniauth_v1.1_r2.4.gemfile b/gemfiles/omniauth_v1.1_r2.4.gemfile new file mode 100644 index 0000000..773eec6 --- /dev/null +++ b/gemfiles/omniauth_v1.1_r2.4.gemfile @@ -0,0 +1,9 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec path: "../" + +eval_gemfile("modular/omniauth/r2/v1.1.gemfile") + +eval_gemfile("modular/x_std_libs/r2.4/libs.gemfile") diff --git a/gemfiles/omniauth_v1.2_r2.gemfile b/gemfiles/omniauth_v1.2_r2.gemfile new file mode 100644 index 0000000..baf2ec1 --- /dev/null +++ b/gemfiles/omniauth_v1.2_r2.gemfile @@ -0,0 +1,9 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec path: "../" + +eval_gemfile("modular/omniauth/r2/v1.2.gemfile") + +eval_gemfile("modular/x_std_libs/r2/libs.gemfile") diff --git a/gemfiles/omniauth_v1.3_r2.gemfile b/gemfiles/omniauth_v1.3_r2.gemfile new file mode 100644 index 0000000..0947c42 --- /dev/null +++ b/gemfiles/omniauth_v1.3_r2.gemfile @@ -0,0 +1,9 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec path: "../" + +eval_gemfile("modular/omniauth/r2/v1.3.gemfile") + +eval_gemfile("modular/x_std_libs/r2/libs.gemfile") diff --git a/gemfiles/omniauth_v1.4_r2.gemfile b/gemfiles/omniauth_v1.4_r2.gemfile new file mode 100644 index 0000000..7a68339 --- /dev/null +++ b/gemfiles/omniauth_v1.4_r2.gemfile @@ -0,0 +1,9 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec path: "../" + +eval_gemfile("modular/omniauth/r2/v1.4.gemfile") + +eval_gemfile("modular/x_std_libs/r2/libs.gemfile") diff --git a/gemfiles/omniauth_v1.5_r2.gemfile b/gemfiles/omniauth_v1.5_r2.gemfile new file mode 100644 index 0000000..6d416f6 --- /dev/null +++ b/gemfiles/omniauth_v1.5_r2.gemfile @@ -0,0 +1,9 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec path: "../" + +eval_gemfile("modular/omniauth/r2/v1.5.gemfile") + +eval_gemfile("modular/x_std_libs/r2/libs.gemfile") diff --git a/gemfiles/omniauth_v1.6_r2.gemfile b/gemfiles/omniauth_v1.6_r2.gemfile new file mode 100644 index 0000000..1fcbc1f --- /dev/null +++ b/gemfiles/omniauth_v1.6_r2.gemfile @@ -0,0 +1,9 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec path: "../" + +eval_gemfile("modular/omniauth/r2/v1.6.gemfile") + +eval_gemfile("modular/x_std_libs/r2/libs.gemfile") diff --git a/gemfiles/omniauth_v1.7_r2.gemfile b/gemfiles/omniauth_v1.7_r2.gemfile new file mode 100644 index 0000000..266a5f8 --- /dev/null +++ b/gemfiles/omniauth_v1.7_r2.gemfile @@ -0,0 +1,9 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec path: "../" + +eval_gemfile("modular/omniauth/r2/v1.7.gemfile") + +eval_gemfile("modular/x_std_libs/r2/libs.gemfile") diff --git a/gemfiles/omniauth_v1.8_r2.gemfile b/gemfiles/omniauth_v1.8_r2.gemfile new file mode 100644 index 0000000..5df7524 --- /dev/null +++ b/gemfiles/omniauth_v1.8_r2.gemfile @@ -0,0 +1,9 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec path: "../" + +eval_gemfile("modular/omniauth/r2/v1.8.gemfile") + +eval_gemfile("modular/x_std_libs/r2/libs.gemfile") diff --git a/gemfiles/omniauth_v1.9_r2.gemfile b/gemfiles/omniauth_v1.9_r2.gemfile new file mode 100644 index 0000000..286ce71 --- /dev/null +++ b/gemfiles/omniauth_v1.9_r2.gemfile @@ -0,0 +1,9 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec path: "../" + +eval_gemfile("modular/omniauth/r2/v1.9.gemfile") + +eval_gemfile("modular/x_std_libs/r2/libs.gemfile") diff --git a/gemfiles/omniauth_v2.0_r2.gemfile b/gemfiles/omniauth_v2.0_r2.gemfile new file mode 100644 index 0000000..634cd1d --- /dev/null +++ b/gemfiles/omniauth_v2.0_r2.gemfile @@ -0,0 +1,9 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec path: "../" + +eval_gemfile("modular/omniauth/r2/v2.0.gemfile") + +eval_gemfile("modular/x_std_libs/r2/libs.gemfile") diff --git a/gemfiles/omniauth_v2.1_r3.0.gemfile b/gemfiles/omniauth_v2.1_r3.0.gemfile new file mode 100644 index 0000000..d1bd23e --- /dev/null +++ b/gemfiles/omniauth_v2.1_r3.0.gemfile @@ -0,0 +1,9 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec path: "../" + +eval_gemfile("modular/omniauth/r3/v2.1.gemfile") + +eval_gemfile("modular/x_std_libs/r3/libs.gemfile") diff --git a/gemfiles/omniauth_v2.1_r3.gemfile b/gemfiles/omniauth_v2.1_r3.gemfile new file mode 100644 index 0000000..d1bd23e --- /dev/null +++ b/gemfiles/omniauth_v2.1_r3.gemfile @@ -0,0 +1,9 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec path: "../" + +eval_gemfile("modular/omniauth/r3/v2.1.gemfile") + +eval_gemfile("modular/x_std_libs/r3/libs.gemfile") diff --git a/gemfiles/style.gemfile b/gemfiles/style.gemfile new file mode 100644 index 0000000..c296a99 --- /dev/null +++ b/gemfiles/style.gemfile @@ -0,0 +1,11 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gemspec path: "../" + +eval_gemfile("modular/style.gemfile") + +eval_gemfile("modular/omniauth/r3/v2.1.gemfile") + +eval_gemfile("modular/x_std_libs/r3/libs.gemfile") diff --git a/lib/omniauth-openid.rb b/lib/omniauth-openid.rb index ca1fec0..e44db9e 100644 --- a/lib/omniauth-openid.rb +++ b/lib/omniauth-openid.rb @@ -1,2 +1,13 @@ -require 'omniauth-openid/version' -require 'omniauth/strategies/open_id' +# external gems +require "version_gem" + +# this library's version +require "omniauth/openid/version" + +# Configure version before loading the rest of the library +OmniAuth::OpenID::Version.class_eval do + extend VersionGem::Basic +end + +# This library +require "omniauth/strategies/open_id" diff --git a/lib/omniauth-openid/version.rb b/lib/omniauth-openid/version.rb index ed5fa19..d73c3fc 100644 --- a/lib/omniauth-openid/version.rb +++ b/lib/omniauth-openid/version.rb @@ -1,5 +1,18 @@ -module OmniAuth - module OpenID - VERSION = '2.0.1' +# DEPRECATED +# TODO[v3]: Remove this file entirely with v3 release. +# :nocov: +unless defined?(OmniAuth::Identity::Version::VERSION) + # external gems + require "version_gem" + + # this library's version + require "omniauth/openid/version" + + # Configure version before loading the rest of the library + OmniAuth::OpenID::Version.class_eval do + extend VersionGem::Basic end + + warn "[DEPRECATION][omniauth-openid v2] Change `require 'omniauth-openid/version'` to `require 'omniauth/openid/version'`. Support for `require 'omniauth-openid/version'` will be removed in v3." end +# :nocov: diff --git a/lib/omniauth/openid/version.rb b/lib/omniauth/openid/version.rb new file mode 100644 index 0000000..83557bf --- /dev/null +++ b/lib/omniauth/openid/version.rb @@ -0,0 +1,8 @@ +module OmniAuth + module OpenID + module Version + VERSION = "2.0.2" + end + include Version # => Makes VERSION available at the usual spot + end +end diff --git a/lib/omniauth/strategies/open_id.rb b/lib/omniauth/strategies/open_id.rb index 5f01d78..fdb3a29 100644 --- a/lib/omniauth/strategies/open_id.rb +++ b/lib/omniauth/strategies/open_id.rb @@ -1,6 +1,6 @@ -require 'omniauth' -require 'rack/openid' -require 'openid/store/memory' +require "omniauth" +require "rack/openid" +require "openid/store/memory" module OmniAuth module Strategies @@ -10,50 +10,57 @@ class OpenID include OmniAuth::Strategy AX = { - :email => 'http://axschema.org/contact/email', - :name => 'http://axschema.org/namePerson', - :nickname => 'http://axschema.org/namePerson/friendly', - :first_name => 'http://axschema.org/namePerson/first', - :last_name => 'http://axschema.org/namePerson/last', - :city => 'http://axschema.org/contact/city/home', - :state => 'http://axschema.org/contact/state/home', - :website => 'http://axschema.org/contact/web/default', - :image => 'http://axschema.org/media/image/aspect11' + email: "http://axschema.org/contact/email", + name: "http://axschema.org/namePerson", + nickname: "http://axschema.org/namePerson/friendly", + first_name: "http://axschema.org/namePerson/first", + last_name: "http://axschema.org/namePerson/last", + city: "http://axschema.org/contact/city/home", + state: "http://axschema.org/contact/state/home", + website: "http://axschema.org/contact/web/default", + image: "http://axschema.org/media/image/aspect11", } option :name, :open_id - option :required, [AX[:email], AX[:name], AX[:first_name], AX[:last_name], 'email', 'fullname'] - option :optional, [AX[:nickname], AX[:city], AX[:state], AX[:website], AX[:image], 'postcode', 'nickname'] + option :required, [AX[:email], AX[:name], AX[:first_name], AX[:last_name], "email", "fullname"] + option :optional, [AX[:nickname], AX[:city], AX[:state], AX[:website], AX[:image], "postcode", "nickname"] option :immediate, false - option :trust_root, proc{|root_uri| nil } + option :trust_root, proc { |root_uri| nil } option :store, ::OpenID::Store::Memory.new option :identifier, nil - option :identifier_param, 'openid_url' + option :identifier_param, "openid_url" option :trust_root, nil def dummy_app - lambda{|env| + lambda { |env| req = Rack::Request.new(env) root_uri = "#{req.scheme}://#{req.host_with_port}/" - [401, {"WWW-Authenticate" => Rack::OpenID.build_header( - :identifier => identifier, - :return_to => callback_url, - :trust_root => options.trust_root || %r{^(https?://[^/]+)}.match(callback_url) {|m| m[1]}, - :required => options.required, - :optional => options.optional, - :method => 'post', - :immediate => options.immediate, - :trust_root => options.trust_root.call(root_uri) - )}, []]} + [ + 401, + { + "WWW-Authenticate" => Rack::OpenID.build_header( + identifier: identifier, + return_to: callback_url, + trust_root: options.trust_root || %r{^(https?://[^/]+)}.match(callback_url) { |m| m[1] }, + required: options.required, + optional: options.optional, + method: "post", + immediate: options.immediate, + trust_root: options.trust_root.call(root_uri), + ), + }, + [], + ] + } end def identifier i = options.identifier || request.params[options.identifier_param.to_s] - i = nil if i == '' + i = nil if i == "" i end - + def request_phase identifier ? start : get_identifier end @@ -61,7 +68,7 @@ def request_phase def start openid = Rack::OpenID.new(dummy_app, options[:store]) response = openid.call(env) - case env['rack.openid.response'] + case env["rack.openid.response"] when Rack::OpenID::MissingResponse, Rack::OpenID::TimeoutResponse fail!(:connection_failed) else @@ -70,9 +77,9 @@ def start end def get_identifier - f = OmniAuth::Form.new(:title => 'OpenID Authentication') - f.label_field('OpenID Identifier', options.identifier_param) - f.input_field('url', options.identifier_param) + f = OmniAuth::Form.new(title: "OpenID Authentication") + f.label_field("OpenID Identifier", options.identifier_param) + f.input_field("url", options.identifier_param) f.to_response end @@ -83,7 +90,7 @@ def get_identifier end extra do - {'response' => openid_response} + {"response" => openid_response} end def callback_phase @@ -93,9 +100,9 @@ def callback_phase def openid_response unless @openid_response - openid = Rack::OpenID.new(lambda{|env| [200,{},[]]}, options[:store]) + openid = Rack::OpenID.new(lambda { |env| [200, {}, []] }, options[:store]) openid.call(env) - @openid_response = env.delete('rack.openid.response') + @openid_response = env.delete("rack.openid.response") end @openid_response end @@ -104,29 +111,31 @@ def sreg_user_info sreg = ::OpenID::SReg::Response.from_success_response(openid_response) return {} unless sreg { - 'email' => sreg['email'], - 'name' => sreg['fullname'], - 'location' => sreg['postcode'], - 'nickname' => sreg['nickname'] - }.reject{|k,v| v.nil? || v == ''} + "email" => sreg["email"], + "name" => sreg["fullname"], + "location" => sreg["postcode"], + "nickname" => sreg["nickname"], + }.reject { |k, v| v.nil? || v == "" } end def ax_user_info ax = ::OpenID::AX::FetchResponse.from_success_response(openid_response) return {} unless ax { - 'email' => ax.get_single(AX[:email]), - 'first_name' => ax.get_single(AX[:first_name]), - 'last_name' => ax.get_single(AX[:last_name]), - 'name' => (ax.get_single(AX[:name]) || [ax.get_single(AX[:first_name]), ax.get_single(AX[:last_name])].join(' ')).strip, - 'location' => ("#{ax.get_single(AX[:city])}, #{ax.get_single(AX[:state])}" if Array(ax.get_single(AX[:city])).any? && Array(ax.get_single(AX[:state])).any?), - 'nickname' => ax.get_single(AX[:nickname]), - 'urls' => ({'Website' => Array(ax.get_single(AX[:website])).first} if Array(ax.get_single(AX[:website])).any?) - }.inject({}){|h,(k,v)| h[k] = Array(v).first; h}.reject{|k,v| v.nil? || v == ''} + "email" => ax.get_single(AX[:email]), + "first_name" => ax.get_single(AX[:first_name]), + "last_name" => ax.get_single(AX[:last_name]), + "name" => (ax.get_single(AX[:name]) || [ax.get_single(AX[:first_name]), ax.get_single(AX[:last_name])].join(" ")).strip, + "location" => ("#{ax.get_single(AX[:city])}, #{ax.get_single(AX[:state])}" if Array(ax.get_single(AX[:city])).any? && Array(ax.get_single(AX[:state])).any?), + "nickname" => ax.get_single(AX[:nickname]), + "urls" => ({"Website" => Array(ax.get_single(AX[:website])).first} if Array(ax.get_single(AX[:website])).any?), + }.each_with_object({}) { |(k, v), h| + h[k] = Array(v).first + }.reject { |k, v| v.nil? || v == "" } end end end end -OmniAuth.config.add_camelization 'openid', 'OpenID' -OmniAuth.config.add_camelization 'open_id', 'OpenID' +OmniAuth.config.add_camelization("openid", "OpenID") +OmniAuth.config.add_camelization("open_id", "OpenID") diff --git a/omniauth-openid.gemspec b/omniauth-openid.gemspec index 791b958..926d38a 100644 --- a/omniauth-openid.gemspec +++ b/omniauth-openid.gemspec @@ -1,20 +1,100 @@ # encoding: utf-8 -require File.expand_path('../lib/omniauth-openid/version', __FILE__) - -Gem::Specification.new do |gem| - gem.add_dependency 'omniauth', ['>= 1.0', '< 3.0'] - gem.add_dependency 'rack-openid', '~> 1.4.0' - - gem.authors = ['Michael Bleigh', 'Erik Michaels-Ober', 'Tom Milewski'] - gem.description = %q{OpenID strategy for OmniAuth.} - gem.email = ['michael@intridea.com', 'sferik@gmail.com', 'tmilewski@gmail.com'] - gem.files = `git ls-files`.split("\n") - gem.homepage = 'https://github.com/intridea/omniauth-openid' - gem.name = 'omniauth-openid' - gem.require_paths = ['lib'] - gem.license = 'MIT' - gem.required_rubygems_version = Gem::Requirement.new('>= 1.3.6') if gem.respond_to? :required_rubygems_version= - gem.summary = gem.description - gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") - gem.version = OmniAuth::OpenID::VERSION + +gem_version = + if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.1") + # Loading the version from an anonymous module allows version.rb to get code coverage from SimpleCov! + # See: https://github.com/simplecov-ruby/simplecov/issues/557#issuecomment-2630782358 + Module.new.tap { |mod| Kernel.load("lib/omniauth/openid/version.rb", mod) }::OmniAuth::OpenID::Version::VERSION + else + require_relative "lib/omniauth/openid/version" + OmniAuth::OpenID::Version::VERSION + end + +Gem::Specification.new do |spec| + spec.name = "omniauth-openid" + spec.version = gem_version + spec.authors = ["Peter Boling", "Michael Bleigh", "Erik Michaels-Ober", "Tom Milewski"] + spec.email = ["floss@galtzo.com"] + + # Linux distros often package gems and securely certify them independent + # of the official RubyGem certification process. Allowed via ENV["SKIP_GEM_SIGNING"] + # Ref: https://gitlab.com/oauth-xx/version_gem/-/issues/3 + # Hence, only enable signing if `SKIP_GEM_SIGNING` is not set in ENV. + # See CONTRIBUTING.md + unless ENV.include?("SKIP_GEM_SIGNING") + user_cert = "certs/#{ENV.fetch("GEM_CERT_USER", ENV["USER"])}.pem" + cert_file_path = File.join(__dir__, user_cert) + cert_chain = cert_file_path.split(",") + cert_chain.select! { |fp| File.exist?(fp) } + if cert_file_path && cert_chain.any? + spec.cert_chain = cert_chain + if $PROGRAM_NAME.end_with?("gem") && ARGV[0] == "build" + spec.signing_key = File.join(Gem.user_home, ".ssh", "gem-private_key.pem") + end + end + end + + spec.summary = "OpenID strategy for OmniAuth." + spec.description = "OpenID (not OIDC) strategy for OmniAuth." + spec.homepage = "https://github.com/omniauth/#{spec.name}" + spec.license = "MIT" + spec.required_ruby_version = ">= 2.4.0" + + spec.metadata["homepage_uri"] = "https://railsbling.com/tags/#{spec.name}/" + spec.metadata["source_code_uri"] = "#{spec.homepage}/tree/v#{spec.version}" + spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/v#{spec.version}/CHANGELOG.md" + spec.metadata["bug_tracker_uri"] = "#{spec.homepage}/issues" + spec.metadata["documentation_uri"] = "https://www.rubydoc.info/gems/#{spec.name}/#{spec.version}" + spec.metadata["wiki_uri"] = "#{spec.homepage}/wiki" + spec.metadata["funding_uri"] = "https://liberapay.com/pboling" + spec.metadata["news_uri"] = "https://www.railsbling.com/tags/#{spec.name}" + spec.metadata["rubygems_mfa_required"] = "true" + + # Specify which files should be added to the gem when it is released. + spec.files = Dir[ + # Splats (alphabetical) + "lib/**/*.rb", + ] + # Automatically included with gem package, no need to list again in files. + spec.extra_rdoc_files = Dir[ + # Files (alphabetical) + "CHANGELOG.md", + "CODE_OF_CONDUCT.md", + "CONTRIBUTING.md", + "LICENSE.txt", + "README.md", + "SECURITY.md", + ] + spec.rdoc_options += [ + "--title", + "#{spec.name} - #{spec.summary}", + "--main", + "CHANGELOG.md", + "CODE_OF_CONDUCT.md", + "CONTRIBUTING.md", + "LICENSE.txt", + "README.md", + "SECURITY.md", + "--line-numbers", + "--inline-source", + "--quiet", + ] + spec.bindir = "exe" + spec.require_paths = ["lib"] + + spec.add_dependency("omniauth", ">= 1.1") + spec.add_dependency("rack-openid", "~> 1.4") + spec.add_dependency("ruby-openid", "~> 2.1", ">= 2.1.8") + spec.add_dependency("version_gem", "~> 1.1", ">= 1.1.8") + + ### Testing + spec.add_development_dependency("rack-session", ">= 1") + spec.add_development_dependency("rack-test", "~> 2.2") + spec.add_development_dependency("rake", "~> 13") + spec.add_development_dependency("rspec", "~> 3") + spec.add_development_dependency("rspec-block_is_expected", "~> 1.0", ">= 1.0.6") + spec.add_development_dependency("webmock", "~> 3.18", ">= 3.18.1") + + ### Releasing + spec.add_development_dependency("stone_checksums", "~> 1.0") # ruby >= 2.2 end diff --git a/spec/config/omniauth.rb b/spec/config/omniauth.rb new file mode 100644 index 0000000..4c36492 --- /dev/null +++ b/spec/config/omniauth.rb @@ -0,0 +1,7 @@ +require "logger" +require "omniauth" + +if OmniAuth.config.respond_to?(:logger=) + logger = Logger.new($stdout) + OmniAuth.config.logger = logger +end diff --git a/spec/config/rspec/rack_test.rb b/spec/config/rspec/rack_test.rb new file mode 100644 index 0000000..0fc97ca --- /dev/null +++ b/spec/config/rspec/rack_test.rb @@ -0,0 +1,5 @@ +require "rack/test" + +RSpec.configure do |config| + config.include Rack::Test::Methods +end diff --git a/spec/config/rspec/rspec_block_is_expected.rb b/spec/config/rspec/rspec_block_is_expected.rb new file mode 100644 index 0000000..ab140fa --- /dev/null +++ b/spec/config/rspec/rspec_block_is_expected.rb @@ -0,0 +1,2 @@ +require "rspec/block_is_expected" +require "rspec/block_is_expected/matchers/not" diff --git a/spec/config/rspec/rspec_core.rb b/spec/config/rspec/rspec_core.rb new file mode 100644 index 0000000..c2da671 --- /dev/null +++ b/spec/config/rspec/rspec_core.rb @@ -0,0 +1,11 @@ +RSpec.configure do |config| + # Enable flags like --only-failures and --next-failure + config.example_status_persistence_file_path = ".rspec_status" + + # Disable RSpec exposing methods globally on `Module` and `main` + config.disable_monkey_patching! + + config.expect_with :rspec do |c| + c.syntax = :expect + end +end diff --git a/spec/config/rspec/version_gem.rb b/spec/config/rspec/version_gem.rb new file mode 100644 index 0000000..1517e9c --- /dev/null +++ b/spec/config/rspec/version_gem.rb @@ -0,0 +1 @@ +require "version_gem/rspec" diff --git a/spec/omniauth/openid/version_spec.rb b/spec/omniauth/openid/version_spec.rb new file mode 100644 index 0000000..71568dd --- /dev/null +++ b/spec/omniauth/openid/version_spec.rb @@ -0,0 +1,19 @@ +# rubocop:disable RSpec/SpecFilePathFormat + +RSpec.describe OmniAuth::OpenID::Version do + it_behaves_like "a Version module", described_class + + it "is greater than 1.0.0" do + expect(Gem::Version.new(described_class) >= Gem::Version.new("1.0.0")).to be(true) + end + + it "includes into parent namespace" do + expect(OmniAuth::OpenID.included_modules).to include(OmniAuth::OpenID::Version) + end + + it "has VERSION in parent namespace" do + expect(OmniAuth::OpenID.const_get("VERSION")).to eq(OmniAuth::OpenID::Version::VERSION) + end +end + +# rubocop:enable RSpec/SpecFilePathFormat diff --git a/spec/omniauth/strategies/open_id_spec.rb b/spec/omniauth/strategies/open_id_spec.rb index 1e53856..1e01d14 100644 --- a/spec/omniauth/strategies/open_id_spec.rb +++ b/spec/omniauth/strategies/open_id_spec.rb @@ -1,35 +1,31 @@ -require 'spec_helper' -require 'rack/openid' -require 'omniauth-openid' - -describe OmniAuth::Strategies::OpenID, :type => :strategy do +RSpec.describe OmniAuth::Strategies::OpenID, type: :strategy do def app strat = OmniAuth::Strategies::OpenID Rack::Builder.new { - use Rack::Session::Cookie, secret: 'foobar' + use Rack::Session::Cookie, secret: SecureRandom.hex(64) use strat - run lambda {|env| [404, {'Content-Type' => 'text/plain'}, [nil || env.key?('omniauth.auth').to_s]] } + run lambda { |env| [404, {"Content-Type" => "text/plain"}, [nil || env.key?("omniauth.auth").to_s]] } }.to_app end def expired_query_string - 'openid=consumer&janrain_nonce=2011-07-21T20%3A14%3A56ZJ8LP3T&openid.assoc_handle=%7BHMAC-SHA1%7D%7B4e284c39%7D%7B9nvQeg%3D%3D%7D&openid.claimed_id=http%3A%2F%2Flocalhost%3A1123%2Fjohn.doe%3Fopenid.success%3Dtrue&openid.identity=http%3A%2F%2Flocalhost%3A1123%2Fjohn.doe%3Fopenid.success%3Dtrue&openid.mode=id_res&openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0&openid.op_endpoint=http%3A%2F%2Flocalhost%3A1123%2Fserver%2F%3Fopenid.success%3Dtrue&openid.response_nonce=2011-07-21T20%3A14%3A56Zf9gC8S&openid.return_to=http%3A%2F%2Flocalhost%3A8888%2FDevelopment%2FWordpress%2Fwp_openid%2F%3Fopenid%3Dconsumer%26janrain_nonce%3D2011-07-21T20%253A14%253A56ZJ8LP3T&openid.sig=GufV13SUJt8VgmSZ92jGZCFBEvQ%3D&openid.signed=assoc_handle%2Cclaimed_id%2Cidentity%2Cmode%2Cns%2Cop_endpoint%2Cresponse_nonce%2Creturn_to%2Csigned' + "openid=consumer&janrain_nonce=2011-07-21T20%3A14%3A56ZJ8LP3T&openid.assoc_handle=%7BHMAC-SHA1%7D%7B4e284c39%7D%7B9nvQeg%3D%3D%7D&openid.claimed_id=http%3A%2F%2Flocalhost%3A1123%2Fjohn.doe%3Fopenid.success%3Dtrue&openid.identity=http%3A%2F%2Flocalhost%3A1123%2Fjohn.doe%3Fopenid.success%3Dtrue&openid.mode=id_res&openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0&openid.op_endpoint=http%3A%2F%2Flocalhost%3A1123%2Fserver%2F%3Fopenid.success%3Dtrue&openid.response_nonce=2011-07-21T20%3A14%3A56Zf9gC8S&openid.return_to=http%3A%2F%2Flocalhost%3A8888%2FDevelopment%2FWordpress%2Fwp_openid%2F%3Fopenid%3Dconsumer%26janrain_nonce%3D2011-07-21T20%253A14%253A56ZJ8LP3T&openid.sig=GufV13SUJt8VgmSZ92jGZCFBEvQ%3D&openid.signed=assoc_handle%2Cclaimed_id%2Cidentity%2Cmode%2Cns%2Cop_endpoint%2Cresponse_nonce%2Creturn_to%2Csigned" end - describe '/auth/open_id without an identifier URL' do + describe "/auth/open_id without an identifier URL" do before do - post '/auth/open_id' + post "/auth/open_id" end - it 'should respond with OK' do + it "responds with OK" do expect(last_response).to be_ok end - it 'should respond with HTML' do - expect(last_response.content_type).to eq 'text/html' + it "responds with HTML" do + expect(last_response.content_type).to eq "text/html" end - it 'should render an identifier URL input' do + it "renders an identifier URL input" do expect(last_response.body).to match %r{]*openid_url} end end @@ -55,8 +51,8 @@ def expired_query_string # end # end - describe 'followed by /auth/open_id/callback' do - context 'successful' do + describe "followed by /auth/open_id/callback" do + context "successful" do # before do # @identifier_url = 'http://me.example.org' # # TODO: change this mock to actually return some sort of OpenID response @@ -73,13 +69,9 @@ def expired_query_string # end end - context 'unsuccessful' do - describe 'returning with expired credentials' do - before do - # get '/auth/open_id/callback?' + expired_query_string - end - - it 'it should redirect to invalid credentials' do + context "unsuccessful" do + describe "returning with expired credentials" do + it "redirects to invalid credentials" do pending expect(last_response).to be_redirect expect(last_response).to match %r{invalid_credentials} diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index a09eb86..51022f3 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,11 +1,33 @@ -$:.unshift File.dirname(__FILE__) + '/../lib' +# Std Libs +require "securerandom" -require 'simplecov' -SimpleCov.start -require 'rspec' -require 'rack/test' -require 'webmock/rspec' -require 'omniauth-openid' +# Bugfixes +# JRuby needed an explicit "require 'logger'" for Rails < 7.1 +# See: https://github.com/rails/rails/issues/54260#issuecomment-2594650047 +# Placing above omniauth because it is a dependency of omniauth, +# which is undeclared in older versions. +require "logger" + +# External library dependencies +require "rack/test" +require "rack/session" +require "rack/openid" +require "webmock/rspec" +require "version_gem/ruby" + +require "omniauth" +require "omniauth/version" + +# RSpec Configs +require "config/omniauth" +require "config/rspec/rack_test" +require "config/rspec/rspec_block_is_expected" +require "config/rspec/rspec_core" +require "config/rspec/version_gem" + +# RSpec Support +spec_root_matcher = %r{#{__dir__}/(.+)\.rb\Z} +Dir.glob(Pathname.new(__dir__).join("support/**/", "*.rb")).each { |f| require f.match(spec_root_matcher)[1] } RSpec.configure do |config| config.include WebMock::API @@ -15,3 +37,17 @@ if OmniAuth.config.respond_to?(:request_validation_phase) OmniAuth.config.request_validation_phase = ->(env) {} end + +# The last thing before loading this gem is to set up code coverage +begin + # This does not require "simplecov", but + require "kettle-soup-cover" + # this next line has a side effect of running `.simplecov` + require "simplecov" if defined?(Kettle::Soup::Cover) && Kettle::Soup::Cover::DO_COV +rescue LoadError => error + # check the error message and conditionally re-raise + raise error unless error.message.include?("kettle") +end + +# This gem +require "omniauth-openid" From b2aa9bf45a048a1b98f0f3132dd8141fa3eddb35 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Sun, 8 Jun 2025 06:39:52 +0700 Subject: [PATCH 2/5] =?UTF-8?q?=F0=9F=9A=A8=20Linting?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .rubocop_gradual.lock | 2 +- docs/OmniAuth.html | 2 +- docs/OmniAuth/OpenID.html | 2 +- docs/OmniAuth/OpenID/Version.html | 2 +- docs/OmniAuth/Strategies.html | 2 +- docs/OmniAuth/Strategies/OpenID.html | 2 +- docs/_index.html | 2 +- docs/file.CHANGELOG.html | 2 +- docs/file.CITATION.html | 2 +- docs/file.CODE_OF_CONDUCT.html | 2 +- docs/file.CONTRIBUTING.html | 2 +- docs/file.LICENSE.html | 2 +- docs/file.README.html | 2 +- docs/file.SECURITY.html | 2 +- docs/index.html | 2 +- docs/top-level-namespace.html | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.rubocop_gradual.lock b/.rubocop_gradual.lock index 34f6804..daae9fe 100644 --- a/.rubocop_gradual.lock +++ b/.rubocop_gradual.lock @@ -5,7 +5,7 @@ "lib/omniauth/strategies/open_id.rb:3703196606": [ [50, 17, 10, "Lint/DuplicateHashKey: Duplicated key in hash literal.", 3672542120] ], - "omniauth-openid.gemspec:1451907988": [ + "omniauth-openid.gemspec:1698529195": [ [4, 23, 12, "Gemspec/RubyVersionGlobalsUsage: Do not use `RUBY_VERSION` in gemspec file.", 31296028] ], "spec/omniauth/openid/version_spec.rb:4155563924": [ diff --git a/docs/OmniAuth.html b/docs/OmniAuth.html index 8014019..6c28639 100644 --- a/docs/OmniAuth.html +++ b/docs/OmniAuth.html @@ -107,7 +107,7 @@

          Defined Under Namespace

        diff --git a/docs/OmniAuth/OpenID.html b/docs/OmniAuth/OpenID.html index 82d2806..99f272e 100644 --- a/docs/OmniAuth/OpenID.html +++ b/docs/OmniAuth/OpenID.html @@ -122,7 +122,7 @@

        Constants included diff --git a/docs/OmniAuth/OpenID/Version.html b/docs/OmniAuth/OpenID/Version.html index fbe9ab1..3bec143 100644 --- a/docs/OmniAuth/OpenID/Version.html +++ b/docs/OmniAuth/OpenID/Version.html @@ -116,7 +116,7 @@

        diff --git a/docs/OmniAuth/Strategies.html b/docs/OmniAuth/Strategies.html index 28901bf..42241de 100644 --- a/docs/OmniAuth/Strategies.html +++ b/docs/OmniAuth/Strategies.html @@ -105,7 +105,7 @@

        Defined Under Namespace

        diff --git a/docs/OmniAuth/Strategies/OpenID.html b/docs/OmniAuth/Strategies/OpenID.html index 6c37deb..9f79a3b 100644 --- a/docs/OmniAuth/Strategies/OpenID.html +++ b/docs/OmniAuth/Strategies/OpenID.html @@ -762,7 +762,7 @@

        diff --git a/docs/_index.html b/docs/_index.html index 3732874..f81d1dd 100644 --- a/docs/_index.html +++ b/docs/_index.html @@ -159,7 +159,7 @@

        Namespace Listing A-Z

        diff --git a/docs/file.CHANGELOG.html b/docs/file.CHANGELOG.html index 5784083..47471a5 100644 --- a/docs/file.CHANGELOG.html +++ b/docs/file.CHANGELOG.html @@ -128,7 +128,7 @@

        diff --git a/docs/file.CITATION.html b/docs/file.CITATION.html index 4e578cf..8ede7cf 100644 --- a/docs/file.CITATION.html +++ b/docs/file.CITATION.html @@ -82,7 +82,7 @@ diff --git a/docs/file.CODE_OF_CONDUCT.html b/docs/file.CODE_OF_CONDUCT.html index d590919..1531c38 100644 --- a/docs/file.CODE_OF_CONDUCT.html +++ b/docs/file.CODE_OF_CONDUCT.html @@ -192,7 +192,7 @@

        Attribution

        diff --git a/docs/file.CONTRIBUTING.html b/docs/file.CONTRIBUTING.html index 5ab3f94..48ef845 100644 --- a/docs/file.CONTRIBUTING.html +++ b/docs/file.CONTRIBUTING.html @@ -192,7 +192,7 @@

        To release a new version:

        diff --git a/docs/file.LICENSE.html b/docs/file.LICENSE.html index 69379f4..eb4b01c 100644 --- a/docs/file.LICENSE.html +++ b/docs/file.LICENSE.html @@ -60,7 +60,7 @@
        MIT License

        Copyright (c) 2025 Peter H. Boling, and omniauth-openid contributors
        Copyright (c) 2010-2011 Michael Bleigh, and Intridea, Inc.

        Permission is hereby granted, free of charge, to any person obtaining
        a copy of this software and associated documentation files (the
        "Software"), to deal in the Software without restriction, including
        without limitation the rights to use, copy, modify, merge, publish,
        distribute, sublicense, and/or sell copies of the Software, and to
        permit persons to whom the Software is furnished to do so, subject to
        the following conditions:

        The above copyright notice and this permission notice shall be
        included in all copies or substantial portions of the Software.

        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
        EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
        MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
        NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
        LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
        OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
        WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
        diff --git a/docs/file.README.html b/docs/file.README.html index acb4ce6..8186766 100644 --- a/docs/file.README.html +++ b/docs/file.README.html @@ -367,7 +367,7 @@

        🤑 One more thing

        diff --git a/docs/file.SECURITY.html b/docs/file.SECURITY.html index d3753f7..51dbbd9 100644 --- a/docs/file.SECURITY.html +++ b/docs/file.SECURITY.html @@ -101,7 +101,7 @@

        Enterprise Support

        diff --git a/docs/index.html b/docs/index.html index f919192..27ccf3c 100644 --- a/docs/index.html +++ b/docs/index.html @@ -367,7 +367,7 @@

        🤑 One more thing

        diff --git a/docs/top-level-namespace.html b/docs/top-level-namespace.html index 40a8409..27f988a 100644 --- a/docs/top-level-namespace.html +++ b/docs/top-level-namespace.html @@ -100,7 +100,7 @@

        Defined Under Namespace

        From 7689ca3303af714c5542f83040a81df2adc67bf1 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Sun, 8 Jun 2025 06:47:59 +0700 Subject: [PATCH 3/5] =?UTF-8?q?=F0=9F=91=B7=20Temporarily=20disable=20QLTY?= =?UTF-8?q?.sh?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/coverage.yml | 14 +++++++------- README.md | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 56595ef..1dd5a45 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -47,7 +47,7 @@ jobs: # Coverage - ruby: "ruby" appraisal_name: "coverage" - exec_cmd: "rake spec:orm:all" + exec_cmd: "rake spec" gemfile: "Appraisal.root" rubygems: latest bundler: latest @@ -99,12 +99,12 @@ jobs: github-token: ${{ secrets.GITHUB_TOKEN }} continue-on-error: ${{ matrix.experimental != 'false' }} - - name: Upload coverage to QLTY - uses: qltysh/qlty-action/coverage@main - with: - token: ${{secrets.QLTY_COVERAGE_TOKEN}} - files: coverage/.resultset.json - continue-on-error: ${{ matrix.experimental != 'false' }} +# - name: Upload coverage to QLTY +# uses: qltysh/qlty-action/coverage@main +# with: +# token: ${{secrets.QLTY_COVERAGE_TOKEN}} +# files: coverage/.resultset.json +# continue-on-error: ${{ matrix.experimental != 'false' }} # Build will fail here if coverage upload fails # which will hopefully be noticed for the lack of code coverage comments diff --git a/README.md b/README.md index 97c980b..ad61a21 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ # 🫵 OmniAuth::OpenID -[![Version][👽versioni]][👽version] [![License: MIT][📄license-img]][📄license-ref] [![Downloads Rank][👽dl-ranki]][👽dl-rank] [![Open Source Helpers][👽oss-helpi]][👽oss-help] [![Depfu][🔑depfui♻️]][🔑depfu] [![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 JRuby][🚎10-j-wfi]][🚎10-j-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] +[![Version][👽versioni]][👽version] [![License: MIT][📄license-img]][📄license-ref] [![Downloads Rank][👽dl-ranki]][👽dl-rank] [![Open Source Helpers][👽oss-helpi]][👽oss-help] [![Depfu][🔑depfui♻️]][🔑depfu] [![CodeCov Test Coverage][🔑codecovi♻️]][🔑codecov] [![Coveralls Test Coverage][🔑coveralls-img]][🔑coveralls] [![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 JRuby][🚎10-j-wfi]][🚎10-j-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] --- From ae4b58c564496d38c36be690104ac27c66baf108 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Sun, 8 Jun 2025 06:50:43 +0700 Subject: [PATCH 4/5] =?UTF-8?q?=F0=9F=91=B7=20Temporarily=20disable=20truf?= =?UTF-8?q?fleruby?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/heads.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/heads.yml b/.github/workflows/heads.yml index ad171bd..3dffcf2 100644 --- a/.github/workflows/heads.yml +++ b/.github/workflows/heads.yml @@ -46,12 +46,12 @@ jobs: bundler: default # # truffleruby-head - - ruby: "truffleruby-head" - appraisal_name: "omniauth-v2.1-r3" - exec_cmd: "rake spec" - gemfile: "Appraisal.root" - rubygems: default - bundler: default +# - ruby: "truffleruby-head" +# appraisal_name: "omniauth-v2.1-r3" +# exec_cmd: "rake spec" +# gemfile: "Appraisal.root" +# rubygems: default +# bundler: default # jruby-head - ruby: "jruby-head" From a859ad6ac68b6f0e3ea75ea5a5bc75bc6d2e66a4 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Sun, 8 Jun 2025 06:55:42 +0700 Subject: [PATCH 5/5] =?UTF-8?q?=F0=9F=93=9D=20KLOC=20&=20CodeCov?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ad61a21..887a0f4 100644 --- a/README.md +++ b/README.md @@ -312,7 +312,7 @@ or one of the others at the head of this README. [🔑qlty-cov]: https://qlty.sh/gh/omniauth/projects/omniauth-openid [🔑qlty-covi♻️]: https://qlty.sh/badges/c2eb0211-c105-4fc6-9b36-650307c67e06/test_coverage.svg [🔑codecov]: https://codecov.io/gh/omniauth/omniauth-openid -[🔑codecovi♻️]: https://codecov.io/gh/omniauth/omniauth-openid/branch/main/graph/badge.svg?token=cc6UdZCpAL +[🔑codecovi♻️]: https://codecov.io/gh/omniauth/omniauth-openid/branch/main/graph/badge.svg?token=E1fzzcuB8f [🔑coveralls]: https://coveralls.io/github/omniauth/omniauth-openid?branch=main [🔑coveralls-img]: https://coveralls.io/repos/github/omniauth/omniauth-openid/badge.svg?branch=main [🔑depfu]: https://depfu.com/github/omniauth/omniauth-openid?project_id=22381 @@ -367,7 +367,7 @@ or one of the others at the head of this README. [🤝gh-issues]: https://github.com/omniauth/omniauth-openid/issues [🤝gh-pulls]: https://github.com/omniauth/omniauth-openid/pulls [🤝contributing]: CONTRIBUTING.md -[🔑codecov-g♻️]: https://codecov.io/gh/omniauth/omniauth-openid/graphs/tree.svg?token=cc6UdZCpAL +[🔑codecov-g♻️]: https://codecov.io/gh/omniauth/omniauth-openid/graphs/tree.svg?token=E1fzzcuB8f [🖐contrib-rocks]: https://contrib.rocks [🖐contributors]: https://github.com/omniauth/omniauth-openid/graphs/contributors [🖐contributors-img]: https://contrib.rocks/image?repo=omniauth/omniauth-openid @@ -385,7 +385,7 @@ or one of the others at the head of this README. [📌gitmoji]:https://gitmoji.dev [📌gitmoji-img]:https://img.shields.io/badge/gitmoji_commits-%20😜%20😍-34495e.svg?style=flat-square [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ -[🧮kloc-img]: https://img.shields.io/badge/KLOC-0.378-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue +[🧮kloc-img]: https://img.shields.io/badge/KLOC-0.080-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue [🔐security]: SECURITY.md [🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat [📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year