[ARVADOS] updated: 2.1.0-978-g650df43af
Git user
git at public.arvados.org
Thu Jun 24 14:47:20 UTC 2021
Summary of changes:
doc/_config.yml | 1 -
doc/api/tokens_sso.html.textile.liquid | 78 ---------------
doc/install/salt-multi-host.html.textile.liquid | 30 ++++--
doc/install/salt.html.textile.liquid | 106 +++++++++++++++++----
.../topics/storage-classes.html.textile.liquid | 14 ++-
lib/config/config.default.yml | 2 +-
lib/config/generated_config.go | 15 +--
lib/controller/rpc/conn_test.go | 7 +-
sdk/cwl/arvados_cwl/fsaccess.py | 2 +-
...ling-slash-dir.cwl => 17801-runtime-outdir.cwl} | 2 +-
sdk/cwl/tests/arvados-tests.yml | 34 +++++++
sdk/python/tests/run_test_server.py | 13 +--
.../api/app/assets/stylesheets/application.css | 2 +-
.../app/controllers/user_sessions_controller.rb | 6 +-
.../api/app/views/layouts/application.html.erb | 1 -
services/api/app/views/static/intro.html.erb | 15 +--
.../api/app/views/static/login_failure.html.erb | 2 +-
services/api/test/test_helper.rb | 1 -
services/fuse/arvados_fuse/__init__.py | 8 --
services/fuse/arvados_fuse/command.py | 19 +++-
services/fuse/arvados_fuse/fusedir.py | 39 +++++---
services/fuse/tests/test_mount.py | 29 ++++++
services/fuse/tests/test_tmp_collection.py | 10 ++
services/keepproxy/keepproxy.go | 33 ++++---
services/keepproxy/keepproxy_test.go | 22 +++++
25 files changed, 300 insertions(+), 191 deletions(-)
delete mode 100644 doc/api/tokens_sso.html.textile.liquid
copy sdk/cwl/tests/{10380-trailing-slash-dir.cwl => 17801-runtime-outdir.cwl} (92%)
discards 703bd34f1582ee56c738969a7979fd78b85655e1 (commit)
discards 5ade025ff305e91ec0238a0415b79f379e6d0157 (commit)
discards 4918b6707e949e2c2dffba7960ff5786e8d2b6ef (commit)
discards 320f5ec1cca21186d0aa00bc2fd9910a07172428 (commit)
discards 958a4eeb2011708d1c38f0d12f790a1462038e85 (commit)
via 650df43af72632e22b7b99dfe7f55a1b5466e355 (commit)
via ac2d17c4377e8fecb3fba392f2eb47ae85764961 (commit)
via 0ce66018616c5177bc9268280119d6f08f339d4d (commit)
via 465d79c490f67c5d0eb8c6b311fdc8c7c9bfb679 (commit)
via 8869a15d200638f873882c145d427f296c33fb19 (commit)
via cbc613e6f91b7fe5685f8551832972968fe677e0 (commit)
via d6e8bf4f423aa174f38b552161dd7bc2dd1ecb18 (commit)
via c1fa7d1c6840ce03e763191c92d3548da8494388 (commit)
via 375b16dac0338924d8d8146ad176bf50f007bf61 (commit)
via 78df70aa7c773716ccb73a7ab3213444f465d03a (commit)
via afbb3f058e8fcf056d6942b59ffeb4d2494b4fd7 (commit)
via 1da6be3bc6c4afb3a38147507293abddcc7f15bf (commit)
via d063c8fca8d2b50ffb384af1b0d73ace384c65f7 (commit)
via a34999d53489f83f87687ee876750085673d023d (commit)
via 6508ed82fe3d784b30efacfb6a97d3f0968dddf6 (commit)
via 8890d0fe46b0f0437aad15c9c2c7103ca8428ce1 (commit)
via c381502b54b67080ba76667c6482c3711d3c10a4 (commit)
via 4c67d48807b549622a91cc12204301ecd8e92ae1 (commit)
via 8655bd8d309537ee7bb9c696c909ebffe3501483 (commit)
via d02322793e6182040afd5b4f3964da9bd0e177e5 (commit)
This update added new revisions after undoing existing revisions. That is
to say, the old revision is not a strict subset of the new revision. This
situation occurs when you --force push a change and generate a repository
containing something like this:
* -- * -- B -- O -- O -- O (703bd34f1582ee56c738969a7979fd78b85655e1)
\
N -- N -- N (650df43af72632e22b7b99dfe7f55a1b5466e355)
When this happens we assume that you've already had alert emails for all
of the O revisions, and so we here report only the revisions in the N
branch from the common base, B.
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
commit 650df43af72632e22b7b99dfe7f55a1b5466e355
Author: Peter Amstutz <peter.amstutz at curii.com>
Date: Thu Jun 24 10:46:44 2021 -0400
17829: Remove additional references to SSO and omniauth
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <peter.amstutz at curii.com>
diff --git a/doc/_config.yml b/doc/_config.yml
index 55987c062..06d159521 100644
--- a/doc/_config.yml
+++ b/doc/_config.yml
@@ -113,7 +113,6 @@ navbar:
- api/requests.html.textile.liquid
- api/methods.html.textile.liquid
- api/resources.html.textile.liquid
- - api/tokens_sso.html.textile.liquid
- Permission and authentication:
- api/methods/api_client_authorizations.html.textile.liquid
- api/methods/api_clients.html.textile.liquid
diff --git a/doc/api/tokens_sso.html.textile.liquid b/doc/api/tokens_sso.html.textile.liquid
deleted file mode 100644
index 5d5246573..000000000
--- a/doc/api/tokens_sso.html.textile.liquid
+++ /dev/null
@@ -1,78 +0,0 @@
----
-layout: default
-navsection: api
-title: API Authorization with SSO (deprecated)
-...
-{% comment %}
-Copyright (C) The Arvados Authors. All rights reserved.
-
-SPDX-License-Identifier: CC-BY-SA-3.0
-{% endcomment %}
-
-{% include 'notebox_begin_warning' %}
-This page describes the deprecated login flow via the SSO server. SSO server authentication will be removed in a future Arvados release and should not be used for new installations. See "Set up web based login":{{site.baseurl}}/install/setup-login.html for more information.
-{% include 'notebox_end' %}
-
-All requests to the API server must have an API token. API tokens can be issued by going though the login flow, or created via the API. At this time, only browser based applications can perform login from email/password. Command line applications and services must use an API token provided via the @ARVADOS_API_TOKEN@ environment variable or configuration file.
-
-h2. Browser login
-
-Browser based applications can perform log in via the following highlevel flow:
-
-# The web application presents a "login" link to @/login@ on the API server with a @return_to@ parameter provided in the query portion of the URL. For example @https://{{ site.arvados_api_host }}/login?return_to=XXX@ , where @return_to=XXX@ is the URL of the login page for the web application.
-# The "login" link takes the browser to the login page (this may involve several redirects)
-# The user logs in. API server authenticates the user and issues a new API token.
-# The browser is redirected to the login page URL provided in @return_to=XXX@ with the addition of @?api_token=xxxxapitokenxxxx at .
-# The web application gets the login request with the included authorization token.
-
-!{{site.baseurl}}/images/Session_Establishment_with_SSO.svg!
-
-The "browser authentication process is documented in detail on the Arvados wiki.":https://dev.arvados.org/projects/arvados/wiki/Workbench_authentication_process
-
-h2. User activation
-
-"Creation and activation of new users is described here.":{{site.baseurl}}/admin/user-management.html
-
-h2. Creating tokens via the API
-
-The browser login method above issues a new token. Using that token, it is possible to make API calls to create additional tokens. To do so, use the @create@ method of the "API client authorizations":{{site.baseurl}}/api/methods/api_client_authorizations.html resource.
-
-h2. Trusted API clients
-
-The "api_clients":{{site.baseurl}}/api/methods/api_clients.html resource determines if web applications that have gone through the browser login flow may create or list API tokens.
-
-After the user has authenticated, but before an authorization token is issued and browser redirect sent (sending the browser back to the @return_to@ login page bearing @api_token@), the server strips the path and query portion from @return_to@ to get @url_prefix at . The @url_prefix@ is used to find or create an ApiClient object. The newly issued API client authorization (API token) is associated with this ApiClient object.
-
-API clients may be marked as "trusted" by making an API call to create or update an "api_clients":{{site.baseurl}}/api/methods/api_clients.html resource and set the @is_trusted@ flag to @true at . An authorization token associated with a "trusted" client is permitted to list authorization tokens on "API client authorizations":{{site.baseurl}}/api/methods/api_client_authorizations.html .
-
-A authorization token which is not associated with a trusted client may only use the @current@ method to query its own api_client_authorization object. The "untrusted" token is forbidden performing any other operations on API client authorizations, such as listing other authorizations or creating new authorizations.
-
-Authorization tokens which are not issued via the browser login flow (created directly via the API) inherit the api client of the token used to create them. They will always be "trusted" because untrusted API clients cannot create tokens.
-
-h2(#scopes). Scopes
-
-Scopes can restrict a token so it may only access certain resources. This is in addition to normal permission checks for the user associated with the token.
-
-Each entry in scopes consists of a @request_method@ and @request_path at . The @request_method@ is a HTTP method (one of @GET@, @POST@, @PATCH@ or @DELETE@) and @request_path@ is the request URI. A given request is permitted if it matches a scopes exactly, or the scope ends with @/@ and the request string is a prefix of the scope.
-
-As a special case, a scope of @["all"]@ allows all resources. This is the default if no scope is given.
-
-Using scopes is also described on the "Securing API access with scoped tokens":{{site.baseurl}}/admin/scoped-tokens.html page of the admin documentation.
-
-h3. Scope examples
-
-A scope of @GET /arvados/v1/collections@ permits listing collections.
-
-* Requests with different methods, such as creating a new collection using @POST /arvados/v1/collections@, will be rejected.
-* Requests to access other resources, such as @GET /arvados/v1/groups@, will be rejected.
-* Be aware that requests for specific records, such as @GET /arvados/v1/collections/962eh-4zz18-xi32mpz2621o8km@ will also be rejected. This is because the scope @GET /arvados/v1/collections@ does not end in @/@
-
-A scope of @GET /arvados/v1/collections/@ (with @/@ suffix) will permit access to individual collections.
-
-* The request @GET /arvados/v1/collections/962eh-4zz18-xi32mpz2621o8km@ will succeed
-* Be aware that requests for listing @GET /arvados/v1/collections@ (no @/@ suffix) will be rejected, because it is not a match with the rule @GET /arvados/v1/collections/@
-* A listing request @GET /arvados/v1/collections/@ will have the trailing @/@ suffix trimmed before the scope check, as a result it will not match the rule @GET /arvados/v1/collections/@.
-
-To allow both listing objects and requesting individual objects, include both in the scope: @["GET /arvados/v1/collections", "GET /arvados/v1/collections/"]@
-
-A narrow scope such as @GET /arvados/v1/collections/962eh-4zz18-xi32mpz2621o8km@ will disallow listing objects as well as disallow requesting any object other than those listed in the scope.
diff --git a/lib/config/config.default.yml b/lib/config/config.default.yml
index 1f76f6366..645da5671 100644
--- a/lib/config/config.default.yml
+++ b/lib/config/config.default.yml
@@ -552,7 +552,7 @@ Clusters:
MaxSessions: 100
Login:
- # One of the following mechanisms (SSO, Google, PAM, LDAP, or
+ # One of the following mechanisms (Google, PAM, LDAP, or
# LoginCluster) should be enabled; see
# https://doc.arvados.org/install/setup-login.html
diff --git a/lib/config/generated_config.go b/lib/config/generated_config.go
index d5e0f200b..1bdc269c0 100644
--- a/lib/config/generated_config.go
+++ b/lib/config/generated_config.go
@@ -58,9 +58,6 @@ Clusters:
DispatchCloud:
InternalURLs: {SAMPLE: {}}
ExternalURL: "-"
- SSO:
- InternalURLs: {SAMPLE: {}}
- ExternalURL: ""
Keepproxy:
InternalURLs: {SAMPLE: {}}
ExternalURL: ""
@@ -561,7 +558,7 @@ Clusters:
MaxSessions: 100
Login:
- # One of the following mechanisms (SSO, Google, PAM, LDAP, or
+ # One of the following mechanisms (Google, PAM, LDAP, or
# LoginCluster) should be enabled; see
# https://doc.arvados.org/install/setup-login.html
@@ -742,16 +739,6 @@ Clusters:
# originally supplied by the user will be used.
UsernameAttribute: uid
- SSO:
- # Authenticate with a separate SSO server. (Deprecated)
- Enable: false
-
- # ProviderAppID and ProviderAppSecret are generated during SSO
- # setup; see
- # https://doc.arvados.org/v2.0/install/install-sso.html#update-config
- ProviderAppID: ""
- ProviderAppSecret: ""
-
Test:
# Authenticate users listed here in the config file. This
# feature is intended to be used in test environments, and
diff --git a/lib/controller/rpc/conn_test.go b/lib/controller/rpc/conn_test.go
index cf4dbc476..eee8db9ac 100644
--- a/lib/controller/rpc/conn_test.go
+++ b/lib/controller/rpc/conn_test.go
@@ -50,9 +50,8 @@ func (s *RPCSuite) TestLogin(c *check.C) {
opts := arvados.LoginOptions{
ReturnTo: "https://foo.example.com/bar",
}
- resp, err := s.conn.Login(s.ctx, opts)
- c.Check(err, check.IsNil)
- c.Check(resp.RedirectLocation, check.Equals, "/auth/joshid?return_to="+url.QueryEscape(","+opts.ReturnTo))
+ _, err := s.conn.Login(s.ctx, opts)
+ c.Check(err.(*arvados.TransactionError).StatusCode, check.Equals, 404)
}
func (s *RPCSuite) TestLogout(c *check.C) {
@@ -62,7 +61,7 @@ func (s *RPCSuite) TestLogout(c *check.C) {
}
resp, err := s.conn.Logout(s.ctx, opts)
c.Check(err, check.IsNil)
- c.Check(resp.RedirectLocation, check.Equals, "http://localhost:3002/users/sign_out?redirect_uri="+url.QueryEscape(opts.ReturnTo))
+ c.Check(resp.RedirectLocation, check.Equals, opts.ReturnTo)
}
func (s *RPCSuite) TestCollectionCreate(c *check.C) {
diff --git a/sdk/python/tests/run_test_server.py b/sdk/python/tests/run_test_server.py
index 917d6100a..c022e6c87 100644
--- a/sdk/python/tests/run_test_server.py
+++ b/sdk/python/tests/run_test_server.py
@@ -755,9 +755,6 @@ def setup_config():
"http://%s:%s"%(localhost, keep_web_dl_port): {},
},
},
- "SSO": {
- "ExternalURL": "http://localhost:3002",
- },
}
config = {
@@ -769,10 +766,14 @@ def setup_config():
"RequestTimeout": "30s",
},
"Login": {
- "SSO": {
+ "Test": {
"Enable": True,
- "ProviderAppID": "arvados-server",
- "ProviderAppSecret": "608dbf356a327e2d0d4932b60161e212c2d8d8f5e25690d7b622f850a990cd33",
+ "Users": {
+ "alice": {
+ "Email": "alice at example.com",
+ "Password": "xyzzy"
+ }
+ }
},
},
"SystemLogs": {
diff --git a/services/api/app/assets/stylesheets/application.css b/services/api/app/assets/stylesheets/application.css
index 721ff801c..18895f6ef 100644
--- a/services/api/app/assets/stylesheets/application.css
+++ b/services/api/app/assets/stylesheets/application.css
@@ -62,7 +62,7 @@ div#header span.beta > span {
border-bottom: 1px solid #fff;
font-size: 0.8em;
}
-img.curoverse-logo {
+img.arvados-logo {
height: 66px;
}
#intropage {
diff --git a/services/api/app/controllers/user_sessions_controller.rb b/services/api/app/controllers/user_sessions_controller.rb
index aec586ecd..ae34fa760 100644
--- a/services/api/app/controllers/user_sessions_controller.rb
+++ b/services/api/app/controllers/user_sessions_controller.rb
@@ -90,14 +90,14 @@ class UserSessionsController < ApplicationController
flash[:notice] = params[:message]
end
- # logout - Clear our rack session BUT essentially redirect to the provider
- # to clean up the Devise session from there too !
+ # logout - this gets intercepted by controller, so this is probably
+ # mostly dead code at this point.
def logout
session[:user_id] = nil
flash[:notice] = 'You have logged off'
return_to = params[:return_to] || root_url
- redirect_to "#{Rails.configuration.Services.SSO.ExternalURL}users/sign_out?redirect_uri=#{CGI.escape return_to}"
+ redirect_to return_to
end
# login. Redirect to LoginCluster.
diff --git a/services/api/app/views/layouts/application.html.erb b/services/api/app/views/layouts/application.html.erb
index 881d1be13..b4f60de34 100644
--- a/services/api/app/views/layouts/application.html.erb
+++ b/services/api/app/views/layouts/application.html.erb
@@ -39,7 +39,6 @@ SPDX-License-Identifier: AGPL-3.0 %>
<% if current_user or session['invite_code'] %>
<div id="footer">
- <div style="float:right">Questions → <a href="mailto:arvados at curoverse.com">arvados at curoverse.com</a></div>
<div style="clear:both"></div>
</div>
<% end %>
diff --git a/services/api/app/views/static/intro.html.erb b/services/api/app/views/static/intro.html.erb
index 58943038d..8bab0b2ac 100644
--- a/services/api/app/views/static/intro.html.erb
+++ b/services/api/app/views/static/intro.html.erb
@@ -8,27 +8,20 @@ $(function(){
});
<% end %>
<div id="intropage">
- <img class="curoverse-logo" src="<%= asset_path('logo.png') %>" style="display:block; margin:2em auto"/>
+ <img class="arvados-logo" src="<%= asset_path('logo.png') %>" style="display:block; margin:2em auto"/>
<div style="width:30em; margin:2em auto 0 auto">
<h1>Welcome</h1>
- <h4>Curoverse ARVADOS</h4>
+ <h4>ARVADOS</h4>
<% if !current_user and session['invite_code'] %>
- <p>Curoverse Arvados lets you manage and process human genomes and exomes. You can start using the private beta
- now with your Google account.</p>
+ <p>Arvados lets you manage and process biomedical data.</p>
<p style="float:right;margin-top:1em">
- <button class="login" href="/auth/joshid">Log in and get started</button>
+ <button class="login" href="/login">Log in and get started</button>
</p>
<% else %>
- <p>Curoverse ARVADOS is transforming how researchers and
- clinical geneticists use whole genome sequences. </p>
- <p>If you’re interested in learning more, we’d love to hear
- from you —
- contact <a href="mailto:arvados at curoverse.com">arvados at curoverse.com</a>.</p>
-
<% if !current_user %>
<p style="float:right;margin-top:1em">
<a href="/login">Log in here.</a>
diff --git a/services/api/app/views/static/login_failure.html.erb b/services/api/app/views/static/login_failure.html.erb
index b3c6e70d9..6b81a33e8 100644
--- a/services/api/app/views/static/login_failure.html.erb
+++ b/services/api/app/views/static/login_failure.html.erb
@@ -10,7 +10,7 @@ $(function(){
<div id="intropage">
- <img class="curoverse-logo" src="<%= asset_path('logo.png') rescue '/logo.png' %>" style="display:block; margin:2em auto"/>
+ <img class="arvados-logo" src="<%= asset_path('logo.png') rescue '/logo.png' %>" style="display:block; margin:2em auto"/>
<div style="width:30em; margin:2em auto 0 auto">
<h1>Error</h1>
diff --git a/services/api/test/test_helper.rb b/services/api/test/test_helper.rb
index ee7dac4cd..843d4f1b2 100644
--- a/services/api/test/test_helper.rb
+++ b/services/api/test/test_helper.rb
@@ -25,7 +25,6 @@ unless ENV["NO_COVERAGE_TEST"]
SimpleCov.start do
add_filter '/test/'
add_filter 'initializers/secret_token'
- add_filter 'initializers/omniauth'
end
rescue Exception => e
$stderr.puts "SimpleCov unavailable (#{e}). Proceeding without."
commit ac2d17c4377e8fecb3fba392f2eb47ae85764961
Author: Peter Amstutz <peter.amstutz at curii.com>
Date: Wed Jun 23 10:22:16 2021 -0400
17829: Remove more SSO-related configuration
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <peter.amstutz at curii.com>
diff --git a/lib/config/config.default.yml b/lib/config/config.default.yml
index 93edae981..1f76f6366 100644
--- a/lib/config/config.default.yml
+++ b/lib/config/config.default.yml
@@ -52,9 +52,6 @@ Clusters:
DispatchCloud:
InternalURLs: {SAMPLE: {}}
ExternalURL: "-"
- SSO:
- InternalURLs: {SAMPLE: {}}
- ExternalURL: ""
Keepproxy:
InternalURLs: {SAMPLE: {}}
ExternalURL: ""
diff --git a/sdk/go/arvados/config.go b/sdk/go/arvados/config.go
index 23bc258cb..7fdea2c74 100644
--- a/sdk/go/arvados/config.go
+++ b/sdk/go/arvados/config.go
@@ -322,7 +322,6 @@ type Services struct {
Keepproxy Service
Keepstore Service
RailsAPI Service
- SSO Service
WebDAVDownload Service
WebDAV Service
WebShell Service
diff --git a/services/api/config/arvados_config.rb b/services/api/config/arvados_config.rb
index 2c259919a..a6f1730e8 100644
--- a/services/api/config/arvados_config.rb
+++ b/services/api/config/arvados_config.rb
@@ -28,22 +28,6 @@ rescue LoadError
# configured by application.yml (i.e., here!) instead.
end
-if (File.exist?(File.expand_path '../omniauth.rb', __FILE__) and
- not defined? WARNED_OMNIAUTH_CONFIG)
- Rails.logger.warn <<-EOS
-DEPRECATED CONFIGURATION:
- Please move your SSO provider config into config/application.yml
- and delete config/initializers/omniauth.rb.
-EOS
- # Real values will be copied from globals by omniauth_init.rb. For
- # now, assign some strings so the generic *.yml config loader
- # doesn't overwrite them or complain that they're missing.
- Rails.configuration.Login["SSO"]["ProviderAppID"] = 'xxx'
- Rails.configuration.Login["SSO"]["ProviderAppSecret"] = 'xxx'
- Rails.configuration.Services["SSO"]["ExternalURL"] = '//xxx'
- WARNED_OMNIAUTH_CONFIG = true
-end
-
# Load the defaults, used by config:migrate and fallback loading
# legacy application.yml
defaultYAML, stderr, status = Open3.capture3("arvados-server", "config-dump", "-config=-", "-skip-legacy", stdin_data: "Clusters: {xxxxx: {}}")
@@ -114,14 +98,11 @@ arvcfg.declare_config "Users.EmailSubjectPrefix", String, :email_subject_prefix
arvcfg.declare_config "Users.UserNotifierEmailFrom", String, :user_notifier_email_from
arvcfg.declare_config "Users.NewUserNotificationRecipients", Hash, :new_user_notification_recipients, ->(cfg, k, v) { arrayToHash cfg, "Users.NewUserNotificationRecipients", v }
arvcfg.declare_config "Users.NewInactiveUserNotificationRecipients", Hash, :new_inactive_user_notification_recipients, method(:arrayToHash)
-arvcfg.declare_config "Login.SSO.ProviderAppSecret", String, :sso_app_secret
-arvcfg.declare_config "Login.SSO.ProviderAppID", String, :sso_app_id
arvcfg.declare_config "Login.LoginCluster", String
arvcfg.declare_config "Login.TrustedClients", Hash
arvcfg.declare_config "Login.RemoteTokenRefresh", ActiveSupport::Duration
arvcfg.declare_config "Login.TokenLifetime", ActiveSupport::Duration
arvcfg.declare_config "TLS.Insecure", Boolean, :sso_insecure
-arvcfg.declare_config "Services.SSO.ExternalURL", String, :sso_provider_url
arvcfg.declare_config "AuditLogs.MaxAge", ActiveSupport::Duration, :max_audit_log_age
arvcfg.declare_config "AuditLogs.MaxDeleteBatch", Integer, :max_audit_log_delete_batch
arvcfg.declare_config "AuditLogs.UnloggedAttributes", Hash, :unlogged_attributes, ->(cfg, k, v) { arrayToHash cfg, "AuditLogs.UnloggedAttributes", v }
commit 0ce66018616c5177bc9268280119d6f08f339d4d
Author: Peter Amstutz <peter.amstutz at curii.com>
Date: Wed Jun 23 10:07:19 2021 -0400
17829: Remove SSO from config, controller, and tests
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <peter.amstutz at curii.com>
diff --git a/lib/config/config.default.yml b/lib/config/config.default.yml
index f0794a7e5..93edae981 100644
--- a/lib/config/config.default.yml
+++ b/lib/config/config.default.yml
@@ -736,16 +736,6 @@ Clusters:
# originally supplied by the user will be used.
UsernameAttribute: uid
- SSO:
- # Authenticate with a separate SSO server. (Deprecated)
- Enable: false
-
- # ProviderAppID and ProviderAppSecret are generated during SSO
- # setup; see
- # https://doc.arvados.org/v2.0/install/install-sso.html#update-config
- ProviderAppID: ""
- ProviderAppSecret: ""
-
Test:
# Authenticate users listed here in the config file. This
# feature is intended to be used in test environments, and
diff --git a/lib/config/deprecated.go b/lib/config/deprecated.go
index 5e68bbfce..efc9f0837 100644
--- a/lib/config/deprecated.go
+++ b/lib/config/deprecated.go
@@ -103,18 +103,6 @@ func (ldr *Loader) applyDeprecatedConfig(cfg *arvados.Config) error {
*dst = *n
}
- // Provider* moved to SSO.Provider*
- if dst, n := &cluster.Login.SSO.ProviderAppID, dcluster.Login.ProviderAppID; n != nil && *n != *dst {
- *dst = *n
- if *n != "" {
- // In old config, non-empty ID meant enable
- cluster.Login.SSO.Enable = true
- }
- }
- if dst, n := &cluster.Login.SSO.ProviderAppSecret, dcluster.Login.ProviderAppSecret; n != nil && *n != *dst {
- *dst = *n
- }
-
cfg.Clusters[id] = cluster
}
return nil
diff --git a/lib/config/export.go b/lib/config/export.go
index 23d0b6bff..32a528b3c 100644
--- a/lib/config/export.go
+++ b/lib/config/export.go
@@ -173,10 +173,6 @@ var whitelist = map[string]bool{
"Login.PAM.Enable": true,
"Login.PAM.Service": false,
"Login.RemoteTokenRefresh": true,
- "Login.SSO": true,
- "Login.SSO.Enable": true,
- "Login.SSO.ProviderAppID": false,
- "Login.SSO.ProviderAppSecret": false,
"Login.Test": true,
"Login.Test.Enable": true,
"Login.Test.Users": false,
diff --git a/lib/controller/handler_test.go b/lib/controller/handler_test.go
index 2911a4f03..9b71c349a 100644
--- a/lib/controller/handler_test.go
+++ b/lib/controller/handler_test.go
@@ -164,34 +164,6 @@ func (s *HandlerSuite) TestProxyNotFound(c *check.C) {
c.Check(jresp["errors"], check.FitsTypeOf, []interface{}{})
}
-func (s *HandlerSuite) TestProxyRedirect(c *check.C) {
- s.cluster.Login.SSO.Enable = true
- s.cluster.Login.SSO.ProviderAppID = "test"
- s.cluster.Login.SSO.ProviderAppSecret = "test"
- req := httptest.NewRequest("GET", "https://0.0.0.0:1/login?return_to=foo", nil)
- resp := httptest.NewRecorder()
- s.handler.ServeHTTP(resp, req)
- if !c.Check(resp.Code, check.Equals, http.StatusFound) {
- c.Log(resp.Body.String())
- }
- // Old "proxy entire request" code path returns an absolute
- // URL. New lib/controller/federation code path returns a
- // relative URL.
- c.Check(resp.Header().Get("Location"), check.Matches, `(https://0.0.0.0:1)?/auth/joshid\?return_to=%2Cfoo&?`)
-}
-
-func (s *HandlerSuite) TestLogoutSSO(c *check.C) {
- s.cluster.Login.SSO.Enable = true
- s.cluster.Login.SSO.ProviderAppID = "test"
- req := httptest.NewRequest("GET", "https://0.0.0.0:1/logout?return_to=https://example.com/foo", nil)
- resp := httptest.NewRecorder()
- s.handler.ServeHTTP(resp, req)
- if !c.Check(resp.Code, check.Equals, http.StatusFound) {
- c.Log(resp.Body.String())
- }
- c.Check(resp.Header().Get("Location"), check.Equals, "http://localhost:3002/users/sign_out?"+url.Values{"redirect_uri": {"https://example.com/foo"}}.Encode())
-}
-
func (s *HandlerSuite) TestLogoutGoogle(c *check.C) {
s.cluster.Login.Google.Enable = true
s.cluster.Login.Google.ClientID = "test"
diff --git a/lib/controller/localdb/login.go b/lib/controller/localdb/login.go
index 0d6f2ef02..3c7b01baa 100644
--- a/lib/controller/localdb/login.go
+++ b/lib/controller/localdb/login.go
@@ -30,15 +30,14 @@ type loginController interface {
func chooseLoginController(cluster *arvados.Cluster, parent *Conn) loginController {
wantGoogle := cluster.Login.Google.Enable
wantOpenIDConnect := cluster.Login.OpenIDConnect.Enable
- wantSSO := cluster.Login.SSO.Enable
wantPAM := cluster.Login.PAM.Enable
wantLDAP := cluster.Login.LDAP.Enable
wantTest := cluster.Login.Test.Enable
wantLoginCluster := cluster.Login.LoginCluster != "" && cluster.Login.LoginCluster != cluster.ClusterID
switch {
- case 1 != countTrue(wantGoogle, wantOpenIDConnect, wantSSO, wantPAM, wantLDAP, wantTest, wantLoginCluster):
+ case 1 != countTrue(wantGoogle, wantOpenIDConnect, wantPAM, wantLDAP, wantTest, wantLoginCluster):
return errorLoginController{
- error: errors.New("configuration problem: exactly one of Login.Google, Login.OpenIDConnect, Login.SSO, Login.PAM, Login.LDAP, Login.Test, or Login.LoginCluster must be set"),
+ error: errors.New("configuration problem: exactly one of Login.Google, Login.OpenIDConnect, Login.PAM, Login.LDAP, Login.Test, or Login.LoginCluster must be set"),
}
case wantGoogle:
return &oidcLoginController{
@@ -66,8 +65,6 @@ func chooseLoginController(cluster *arvados.Cluster, parent *Conn) loginControll
AcceptAccessToken: cluster.Login.OpenIDConnect.AcceptAccessToken,
AcceptAccessTokenScope: cluster.Login.OpenIDConnect.AcceptAccessTokenScope,
}
- case wantSSO:
- return &ssoLoginController{Parent: parent}
case wantPAM:
return &pamLoginController{Cluster: cluster, Parent: parent}
case wantLDAP:
@@ -93,20 +90,6 @@ func countTrue(vals ...bool) int {
return n
}
-// Login and Logout are passed through to the parent's railsProxy;
-// UserAuthenticate is rejected.
-type ssoLoginController struct{ Parent *Conn }
-
-func (ctrl *ssoLoginController) Login(ctx context.Context, opts arvados.LoginOptions) (arvados.LoginResponse, error) {
- return ctrl.Parent.railsProxy.Login(ctx, opts)
-}
-func (ctrl *ssoLoginController) Logout(ctx context.Context, opts arvados.LogoutOptions) (arvados.LogoutResponse, error) {
- return ctrl.Parent.railsProxy.Logout(ctx, opts)
-}
-func (ctrl *ssoLoginController) UserAuthenticate(ctx context.Context, opts arvados.UserAuthenticateOptions) (arvados.APIClientAuthorization, error) {
- return arvados.APIClientAuthorization{}, httpserver.ErrorWithStatus(errors.New("username/password authentication is not available"), http.StatusBadRequest)
-}
-
type errorLoginController struct{ error }
func (ctrl errorLoginController) Login(context.Context, arvados.LoginOptions) (arvados.LoginResponse, error) {
diff --git a/lib/controller/localdb/login_oidc_test.go b/lib/controller/localdb/login_oidc_test.go
index c9d6133c4..3d1650074 100644
--- a/lib/controller/localdb/login_oidc_test.go
+++ b/lib/controller/localdb/login_oidc_test.go
@@ -63,7 +63,6 @@ func (s *OIDCLoginSuite) SetUpTest(c *check.C) {
c.Assert(err, check.IsNil)
s.cluster, err = cfg.GetCluster("")
c.Assert(err, check.IsNil)
- s.cluster.Login.SSO.Enable = false
s.cluster.Login.Google.Enable = true
s.cluster.Login.Google.ClientID = "test%client$id"
s.cluster.Login.Google.ClientSecret = "test#client/secret"
diff --git a/sdk/go/arvados/config.go b/sdk/go/arvados/config.go
index 403d501b4..23bc258cb 100644
--- a/sdk/go/arvados/config.go
+++ b/sdk/go/arvados/config.go
@@ -176,11 +176,6 @@ type Cluster struct {
Service string
DefaultEmailDomain string
}
- SSO struct {
- Enable bool
- ProviderAppID string
- ProviderAppSecret string
- }
Test struct {
Enable bool
Users map[string]TestUser
commit 465d79c490f67c5d0eb8c6b311fdc8c7c9bfb679
Author: Peter Amstutz <peter.amstutz at curii.com>
Date: Tue Jun 22 17:11:51 2021 -0400
17829: Fix test
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <peter.amstutz at curii.com>
diff --git a/services/api/test/integration/login_workflow_test.rb b/services/api/test/integration/login_workflow_test.rb
index f0741fcfd..ba3b2ac6e 100644
--- a/services/api/test/integration/login_workflow_test.rb
+++ b/services/api/test/integration/login_workflow_test.rb
@@ -30,7 +30,7 @@ class LoginWorkflowTest < ActionDispatch::IntegrationTest
params: {specimen: {}},
headers: {'HTTP_ACCEPT' => 'text/html'})
assert_response 302
- assert_match(%r{/auth/joshid$}, @response.headers['Location'],
+ assert_match(%r{http://www.example.com/login$}, @response.headers['Location'],
"HTML login prompt did not include expected redirect")
end
end
commit 8869a15d200638f873882c145d427f296c33fb19
Author: Peter Amstutz <peter.amstutz at curii.com>
Date: Tue Jun 22 16:49:32 2021 -0400
17829: Update tests to use 'controller' provider
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <peter.amstutz at curii.com>
diff --git a/services/api/app/controllers/user_sessions_controller.rb b/services/api/app/controllers/user_sessions_controller.rb
index 84dfcdbc9..aec586ecd 100644
--- a/services/api/app/controllers/user_sessions_controller.rb
+++ b/services/api/app/controllers/user_sessions_controller.rb
@@ -27,7 +27,7 @@ class UserSessionsController < ApplicationController
authinfo = SafeJSON.load(params[:auth_info])
max_expires_at = authinfo["expires_at"]
else
- # Legacy code path, fail?
+ return send_error "Legacy code path no longer supported", status: 404
end
if !authinfo['user_uuid'].blank?
@@ -132,7 +132,7 @@ class UserSessionsController < ApplicationController
p << "return_to=#{CGI.escape(params[:return_to])}" if params[:return_to]
redirect_to "#{login_cluster}/login?#{p.join('&')}"
else
- # legacy code path, fail?
+ return send_error "Legacy code path no longer supported", status: 404
end
end
diff --git a/services/api/test/functional/user_sessions_controller_test.rb b/services/api/test/functional/user_sessions_controller_test.rb
index 1f9196893..66aff787b 100644
--- a/services/api/test/functional/user_sessions_controller_test.rb
+++ b/services/api/test/functional/user_sessions_controller_test.rb
@@ -9,9 +9,8 @@ class UserSessionsControllerTest < ActionController::TestCase
test "redirect to joshid" do
api_client_page = 'http://client.example.com/home'
get :login, params: {return_to: api_client_page}
- assert_response :redirect
- assert_equal("http://test.host/auth/joshid?return_to=%2Chttp%3A%2F%2Fclient.example.com%2Fhome", @response.redirect_url)
- assert_nil assigns(:api_client)
+ # Not supported any more
+ assert_response 404
end
test "send token when user is already logged in" do
@@ -107,9 +106,8 @@ class UserSessionsControllerTest < ActionController::TestCase
Rails.configuration.Login.LoginCluster = 'zzzzz'
api_client_page = 'http://client.example.com/home'
get :login, params: {return_to: api_client_page}
- assert_response :redirect
- assert_equal("http://test.host/auth/joshid?return_to=%2Chttp%3A%2F%2Fclient.example.com%2Fhome", @response.redirect_url)
- assert_nil assigns(:api_client)
+ # Doesn't redirect, just fail.
+ assert_response 404
end
test "controller cannot create session without SystemRootToken" do
diff --git a/services/api/test/integration/user_sessions_test.rb b/services/api/test/integration/user_sessions_test.rb
index 6e951499a..76659f320 100644
--- a/services/api/test/integration/user_sessions_test.rb
+++ b/services/api/test/integration/user_sessions_test.rb
@@ -15,21 +15,17 @@ class UserSessionsApiTest < ActionDispatch::IntegrationTest
def mock_auth_with(email: nil, username: nil, identity_url: nil, remote: nil, expected_response: :redirect)
mock = {
- 'provider' => 'josh_id',
- 'uid' => 'https://edward.example.com',
- 'info' => {
'identity_url' => 'https://edward.example.com',
'name' => 'Edward Example',
'first_name' => 'Edward',
'last_name' => 'Example',
- },
}
- mock['info']['email'] = email unless email.nil?
- mock['info']['username'] = username unless username.nil?
- mock['info']['identity_url'] = identity_url unless identity_url.nil?
- post('/auth/josh_id/callback',
- params: {return_to: client_url(remote: remote)},
- headers: {'omniauth.auth' => mock})
+ mock['email'] = email unless email.nil?
+ mock['username'] = username unless username.nil?
+ mock['identity_url'] = identity_url unless identity_url.nil?
+ post('/auth/controller/callback',
+ params: {return_to: client_url(remote: remote), :auth_info => SafeJSON.dump(mock)},
+ headers: {'Authorization' => 'Bearer ' + Rails.configuration.SystemRootToken})
errors = {
:redirect => 'Did not redirect to client with token',
commit cbc613e6f91b7fe5685f8551832972968fe677e0
Author: Peter Amstutz <peter.amstutz at curii.com>
Date: Mon Jun 21 22:19:17 2021 -0400
17829: Remove omniauth
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <peter.amstutz at curii.com>
diff --git a/services/api/Gemfile b/services/api/Gemfile
index 7fc7f8757..39ce5def1 100644
--- a/services/api/Gemfile
+++ b/services/api/Gemfile
@@ -44,10 +44,6 @@ gem 'passenger'
# Locking to 5.10.3 to workaround issue in 5.11.1 (https://github.com/seattlerb/minitest/issues/730)
gem 'minitest', '5.10.3'
-# Restricted because omniauth >= 1.5.0 requires Ruby >= 2.1.9:
-gem 'omniauth', '~> 1.4.0'
-gem 'omniauth-oauth2', '~> 1.1'
-
gem 'andand'
gem 'optimist'
diff --git a/services/api/Gemfile.lock b/services/api/Gemfile.lock
index 7a3180d24..ddecd4a18 100644
--- a/services/api/Gemfile.lock
+++ b/services/api/Gemfile.lock
@@ -110,7 +110,6 @@ GEM
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
signet (~> 0.7)
- hashie (3.6.0)
highline (2.0.1)
httpclient (2.8.3)
i18n (0.9.5)
@@ -148,7 +147,6 @@ GEM
mocha (1.8.0)
metaclass (~> 0.0.1)
multi_json (1.15.0)
- multi_xml (0.6.0)
multipart-post (2.1.1)
net-scp (2.0.0)
net-ssh (>= 2.6.5, < 6.0.0)
@@ -161,19 +159,7 @@ GEM
nokogiri (1.11.7)
mini_portile2 (~> 2.5.0)
racc (~> 1.4)
- oauth2 (1.4.1)
- faraday (>= 0.8, < 0.16.0)
- jwt (>= 1.0, < 3.0)
- multi_json (~> 1.3)
- multi_xml (~> 0.5)
- rack (>= 1.2, < 3)
oj (3.9.2)
- omniauth (1.4.3)
- hashie (>= 1.2, < 4)
- rack (>= 1.6.2, < 3)
- omniauth-oauth2 (1.5.0)
- oauth2 (~> 1.1)
- omniauth (~> 1.2)
optimist (3.0.0)
os (1.1.1)
passenger (6.0.2)
@@ -297,8 +283,6 @@ DEPENDENCIES
mocha
multi_json
oj
- omniauth (~> 1.4.0)
- omniauth-oauth2 (~> 1.1)
optimist
passenger
pg (~> 1.0)
diff --git a/services/api/app/controllers/application_controller.rb b/services/api/app/controllers/application_controller.rb
index e1ae76ed2..fc33dde44 100644
--- a/services/api/app/controllers/application_controller.rb
+++ b/services/api/app/controllers/application_controller.rb
@@ -397,7 +397,7 @@ class ApplicationController < ActionController::Base
if not current_user
respond_to do |format|
format.json { send_error("Not logged in", status: 401) }
- format.html { redirect_to '/auth/joshid' }
+ format.html { redirect_to '/login' }
end
false
end
diff --git a/services/api/app/controllers/user_sessions_controller.rb b/services/api/app/controllers/user_sessions_controller.rb
index 8e9a26b7a..84dfcdbc9 100644
--- a/services/api/app/controllers/user_sessions_controller.rb
+++ b/services/api/app/controllers/user_sessions_controller.rb
@@ -11,7 +11,7 @@ class UserSessionsController < ApplicationController
respond_to :html
- # omniauth callback method
+ # create a new session
def create
if !Rails.configuration.Login.LoginCluster.empty? and Rails.configuration.Login.LoginCluster != Rails.configuration.ClusterID
raise "Local login disabled when LoginCluster is set"
@@ -27,9 +27,7 @@ class UserSessionsController < ApplicationController
authinfo = SafeJSON.load(params[:auth_info])
max_expires_at = authinfo["expires_at"]
else
- # omniauth middleware verified the user and is passing auth_info
- # in request.env.
- authinfo = request.env['omniauth.auth']['info'].with_indifferent_access
+ # Legacy code path, fail?
end
if !authinfo['user_uuid'].blank?
@@ -102,9 +100,7 @@ class UserSessionsController < ApplicationController
redirect_to "#{Rails.configuration.Services.SSO.ExternalURL}users/sign_out?redirect_uri=#{CGI.escape return_to}"
end
- # login - Just bounce to /auth/joshid. The only purpose of this function is
- # to save the return_to parameter (if it exists; see the application
- # controller). /auth/joshid bypasses the application controller.
+ # login. Redirect to LoginCluster.
def login
if params[:remote] !~ /^[0-9a-z]{5}$/ && !params[:remote].nil?
return send_error 'Invalid remote cluster id', status: 400
@@ -136,13 +132,7 @@ class UserSessionsController < ApplicationController
p << "return_to=#{CGI.escape(params[:return_to])}" if params[:return_to]
redirect_to "#{login_cluster}/login?#{p.join('&')}"
else
- if params[:return_to]
- # Encode remote param inside callback's return_to, so that we'll get it on
- # create() after login.
- remote_param = params[:remote].nil? ? '' : params[:remote]
- p << "return_to=#{CGI.escape(remote_param + ',' + params[:return_to])}"
- end
- redirect_to "/auth/joshid?#{p.join('&')}"
+ # legacy code path, fail?
end
end
diff --git a/services/api/app/views/layouts/application.html.erb b/services/api/app/views/layouts/application.html.erb
index a99b6f165..881d1be13 100644
--- a/services/api/app/views/layouts/application.html.erb
+++ b/services/api/app/views/layouts/application.html.erb
@@ -23,8 +23,6 @@ SPDX-License-Identifier: AGPL-3.0 %>
<% end %>
•
<a class="logout" href="/logout">Log out</a>
- <% else %>
- <!--<a class="logout" href="/auth/joshid">Log in</a>-->
<% end %>
<% if current_user and session[:real_uid] and session[:switch_back_to] and User.find(session[:real_uid].to_i).verify_userswitch_cookie(session[:switch_back_to]) %>
diff --git a/services/api/app/views/static/intro.html.erb b/services/api/app/views/static/intro.html.erb
index bdefaa5c1..58943038d 100644
--- a/services/api/app/views/static/intro.html.erb
+++ b/services/api/app/views/static/intro.html.erb
@@ -31,7 +31,7 @@ $(function(){
<% if !current_user %>
<p style="float:right;margin-top:1em">
- <a href="/auth/joshid">Log in here.</a>
+ <a href="/login">Log in here.</a>
</p>
<% end %>
diff --git a/services/api/app/views/user_sessions/failure.html.erb b/services/api/app/views/user_sessions/failure.html.erb
index 81c5be27c..e8c5b0846 100644
--- a/services/api/app/views/user_sessions/failure.html.erb
+++ b/services/api/app/views/user_sessions/failure.html.erb
@@ -7,4 +7,4 @@ SPDX-License-Identifier: AGPL-3.0 %>
<%= notice %>
<br/>
-<a href="/auth/joshid">Retry Login</a>
+<a href="/login">Retry Login</a>
diff --git a/services/api/config/environment.rb b/services/api/config/environment.rb
index b82ba27f9..cd706940a 100644
--- a/services/api/config/environment.rb
+++ b/services/api/config/environment.rb
@@ -4,7 +4,6 @@
# Load the rails application
require_relative 'application'
-require 'josh_id'
# Initialize the rails application
Rails.application.initialize!
diff --git a/services/api/config/initializers/omniauth_init.rb b/services/api/config/initializers/omniauth_init.rb
deleted file mode 100644
index a1b2356bd..000000000
--- a/services/api/config/initializers/omniauth_init.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-# This file is called omniauth_init.rb instead of omniauth.rb because
-# older versions had site configuration in omniauth.rb.
-#
-# It must come after omniauth.rb in (lexical) load order.
-
-if defined? CUSTOM_PROVIDER_URL
- Rails.logger.warn "Copying omniauth from globals in legacy config file."
- Rails.configuration.Login["SSO"]["ProviderAppID"] = APP_ID
- Rails.configuration.Login["SSO"]["ProviderAppSecret"] = APP_SECRET
- Rails.configuration.Services["SSO"]["ExternalURL"] = CUSTOM_PROVIDER_URL.sub(/\/$/, "") + "/"
-else
- Rails.application.config.middleware.use OmniAuth::Builder do
- provider(:josh_id,
- Rails.configuration.Login["SSO"]["ProviderAppID"],
- Rails.configuration.Login["SSO"]["ProviderAppSecret"],
- Rails.configuration.Services["SSO"]["ExternalURL"])
- end
- OmniAuth.config.on_failure = StaticController.action(:login_failure)
-end
diff --git a/services/api/lib/josh_id.rb b/services/api/lib/josh_id.rb
deleted file mode 100644
index f18c0edda..000000000
--- a/services/api/lib/josh_id.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-# Copyright (C) The Arvados Authors. All rights reserved.
-#
-# SPDX-License-Identifier: AGPL-3.0
-
-require 'omniauth-oauth2'
-module OmniAuth
- module Strategies
- class JoshId < OmniAuth::Strategies::OAuth2
-
- args [:client_id, :client_secret, :custom_provider_url]
-
- option :custom_provider_url, ''
-
- uid { raw_info['id'] }
-
- option :client_options, {}
-
- info do
- {
- :first_name => raw_info['info']['first_name'],
- :last_name => raw_info['info']['last_name'],
- :email => raw_info['info']['email'],
- :identity_url => raw_info['info']['identity_url'],
- :username => raw_info['info']['username'],
- }
- end
-
- extra do
- {
- 'raw_info' => raw_info
- }
- end
-
- def authorize_params
- options.authorize_params[:auth_provider] = request.params['auth_provider']
- super
- end
-
- def client
- options.client_options[:site] = options[:custom_provider_url]
- options.client_options[:authorize_url] = "#{options[:custom_provider_url]}/auth/josh_id/authorize"
- options.client_options[:access_token_url] = "#{options[:custom_provider_url]}/auth/josh_id/access_token"
- if Rails.configuration.TLS.Insecure
- options.client_options[:ssl] = {verify_mode: OpenSSL::SSL::VERIFY_NONE}
- end
- ::OAuth2::Client.new(options.client_id, options.client_secret, deep_symbolize(options.client_options))
- end
-
- def callback_url
- full_host + script_name + callback_path + "?return_to=" + CGI.escape(request.params['return_to'] || '')
- end
-
- def raw_info
- @raw_info ||= access_token.get("/auth/josh_id/user.json?oauth_token=#{access_token.token}").parsed
- end
- end
- end
-end
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list