Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
李少辉-开发者
gitlab-foss
提交
01afaf85
G
gitlab-foss
项目概览
李少辉-开发者
/
gitlab-foss
通知
15
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
gitlab-foss
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
01afaf85
编写于
10月 30, 2018
作者:
J
James Lopez
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Update code to use API scope on PAT auth
上级
3b601b82
变更
28
隐藏空白更改
内联
并排
Showing
28 changed file
with
538 addition
and
281 deletion
+538
-281
app/controllers/application_controller.rb
app/controllers/application_controller.rb
+1
-22
app/controllers/concerns/sessionless_authentication.rb
app/controllers/concerns/sessionless_authentication.rb
+28
-0
app/controllers/dashboard/projects_controller.rb
app/controllers/dashboard/projects_controller.rb
+1
-0
app/controllers/dashboard_controller.rb
app/controllers/dashboard_controller.rb
+3
-0
app/controllers/graphql_controller.rb
app/controllers/graphql_controller.rb
+1
-0
app/controllers/groups_controller.rb
app/controllers/groups_controller.rb
+3
-0
app/controllers/projects/commits_controller.rb
app/controllers/projects/commits_controller.rb
+1
-0
app/controllers/projects/issues_controller.rb
app/controllers/projects/issues_controller.rb
+9
-8
app/controllers/projects/tags_controller.rb
app/controllers/projects/tags_controller.rb
+2
-0
app/controllers/projects_controller.rb
app/controllers/projects_controller.rb
+2
-0
app/controllers/users_controller.rb
app/controllers/users_controller.rb
+1
-0
changelogs/unreleased/security-fix-pat-web-access.yml
changelogs/unreleased/security-fix-pat-web-access.yml
+5
-0
config/initializers/rack_attack_global.rb
config/initializers/rack_attack_global.rb
+5
-5
lib/gitlab/auth/request_authenticator.rb
lib/gitlab/auth/request_authenticator.rb
+10
-4
lib/gitlab/auth/user_auth_finders.rb
lib/gitlab/auth/user_auth_finders.rb
+37
-2
spec/controllers/application_controller_spec.rb
spec/controllers/application_controller_spec.rb
+0
-151
spec/controllers/dashboard/projects_controller_spec.rb
spec/controllers/dashboard/projects_controller_spec.rb
+5
-0
spec/controllers/dashboard_controller_spec.rb
spec/controllers/dashboard_controller_spec.rb
+18
-13
spec/controllers/graphql_controller_spec.rb
spec/controllers/graphql_controller_spec.rb
+45
-2
spec/controllers/groups_controller_spec.rb
spec/controllers/groups_controller_spec.rb
+20
-0
spec/controllers/projects/commits_controller_spec.rb
spec/controllers/projects/commits_controller_spec.rb
+83
-55
spec/controllers/projects/issues_controller_spec.rb
spec/controllers/projects/issues_controller_spec.rb
+36
-0
spec/controllers/projects/tags_controller_spec.rb
spec/controllers/projects/tags_controller_spec.rb
+22
-0
spec/controllers/projects_controller_spec.rb
spec/controllers/projects_controller_spec.rb
+22
-0
spec/controllers/users_controller_spec.rb
spec/controllers/users_controller_spec.rb
+8
-0
spec/lib/gitlab/auth/request_authenticator_spec.rb
spec/lib/gitlab/auth/request_authenticator_spec.rb
+9
-9
spec/lib/gitlab/auth/user_auth_finders_spec.rb
spec/lib/gitlab/auth/user_auth_finders_spec.rb
+69
-10
spec/support/controllers/sessionless_auth_controller_shared_examples.rb
...ontrollers/sessionless_auth_controller_shared_examples.rb
+92
-0
未找到文件。
app/controllers/application_controller.rb
浏览文件 @
01afaf85
...
...
@@ -12,11 +12,11 @@ class ApplicationController < ActionController::Base
include
WorkhorseHelper
include
EnforcesTwoFactorAuthentication
include
WithPerformanceBar
include
SessionlessAuthentication
# this can be removed after switching to rails 5
# https://gitlab.com/gitlab-org/gitlab-ce/issues/51908
include
InvalidUTF8ErrorHandler
unless
Gitlab
.
rails5?
before_action
:authenticate_sessionless_user!
before_action
:authenticate_user!
before_action
:enforce_terms!
,
if: :should_enforce_terms?
before_action
:validate_user_service_ticket!
...
...
@@ -153,13 +153,6 @@ class ApplicationController < ActionController::Base
end
end
# This filter handles personal access tokens, and atom requests with rss tokens
def
authenticate_sessionless_user!
user
=
Gitlab
::
Auth
::
RequestAuthenticator
.
new
(
request
).
find_sessionless_user
sessionless_sign_in
(
user
)
if
user
end
def
log_exception
(
exception
)
Raven
.
capture_exception
(
exception
)
if
sentry_enabled?
...
...
@@ -426,25 +419,11 @@ class ApplicationController < ActionController::Base
Gitlab
::
I18n
.
with_user_locale
(
current_user
,
&
block
)
end
def
sessionless_sign_in
(
user
)
if
user
&&
can?
(
user
,
:log_in
)
# Notice we are passing store false, so the user is not
# actually stored in the session and a token is needed
# for every request. If you want the token to work as a
# sign in token, you can simply remove store: false.
sign_in
(
user
,
store:
false
,
message: :sessionless_sign_in
)
end
end
def
set_page_title_header
# Per https://tools.ietf.org/html/rfc5987, headers need to be ISO-8859-1, not UTF-8
response
.
headers
[
'Page-Title'
]
=
URI
.
escape
(
page_title
(
'GitLab'
))
end
def
sessionless_user?
current_user
&&
!
session
.
keys
.
include?
(
'warden.user.user.key'
)
end
def
peek_request?
request
.
path
.
start_with?
(
'/-/peek'
)
end
...
...
app/controllers/concerns/sessionless_authentication.rb
0 → 100644
浏览文件 @
01afaf85
# frozen_string_literal: true
# == SessionlessAuthentication
#
# Controller concern to handle PAT and RSS token authentication methods
#
module
SessionlessAuthentication
# This filter handles personal access tokens, and atom requests with rss tokens
def
authenticate_sessionless_user!
(
request_format
)
user
=
Gitlab
::
Auth
::
RequestAuthenticator
.
new
(
request
).
find_sessionless_user
(
request_format
)
sessionless_sign_in
(
user
)
if
user
end
def
sessionless_user?
current_user
&&
!
session
.
keys
.
include?
(
'warden.user.user.key'
)
end
def
sessionless_sign_in
(
user
)
if
user
&&
can?
(
user
,
:log_in
)
# Notice we are passing store false, so the user is not
# actually stored in the session and a token is needed
# for every request. If you want the token to work as a
# sign in token, you can simply remove store: false.
sign_in
(
user
,
store:
false
,
message: :sessionless_sign_in
)
end
end
end
app/controllers/dashboard/projects_controller.rb
浏览文件 @
01afaf85
...
...
@@ -4,6 +4,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
include
ParamsBackwardCompatibility
include
RendersMemberAccess
prepend_before_action
(
only:
[
:index
])
{
authenticate_sessionless_user!
(
:rss
)
}
before_action
:set_non_archived_param
before_action
:default_sorting
skip_cross_project_access_check
:index
,
:starred
...
...
app/controllers/dashboard_controller.rb
浏览文件 @
01afaf85
...
...
@@ -4,6 +4,9 @@ class DashboardController < Dashboard::ApplicationController
include
IssuesAction
include
MergeRequestsAction
prepend_before_action
(
only:
[
:issues
])
{
authenticate_sessionless_user!
(
:rss
)
}
prepend_before_action
(
only:
[
:issues_calendar
])
{
authenticate_sessionless_user!
(
:ics
)
}
before_action
:event_filter
,
only: :activity
before_action
:projects
,
only:
[
:issues
,
:merge_requests
]
before_action
:set_show_full_reference
,
only:
[
:issues
,
:merge_requests
]
...
...
app/controllers/graphql_controller.rb
浏览文件 @
01afaf85
...
...
@@ -3,6 +3,7 @@
class
GraphqlController
<
ApplicationController
# Unauthenticated users have access to the API for public data
skip_before_action
:authenticate_user!
prepend_before_action
(
only:
[
:execute
])
{
authenticate_sessionless_user!
(
:api
)
}
before_action
:check_graphql_feature_flag!
...
...
app/controllers/groups_controller.rb
浏览文件 @
01afaf85
...
...
@@ -9,6 +9,9 @@ class GroupsController < Groups::ApplicationController
respond_to
:html
prepend_before_action
(
only:
[
:show
,
:issues
])
{
authenticate_sessionless_user!
(
:rss
)
}
prepend_before_action
(
only:
[
:issues_calendar
])
{
authenticate_sessionless_user!
(
:ics
)
}
before_action
:authenticate_user!
,
only:
[
:new
,
:create
]
before_action
:group
,
except:
[
:index
,
:new
,
:create
]
...
...
app/controllers/projects/commits_controller.rb
浏览文件 @
01afaf85
...
...
@@ -6,6 +6,7 @@ class Projects::CommitsController < Projects::ApplicationController
include
ExtractsPath
include
RendersCommits
prepend_before_action
(
only:
[
:show
])
{
authenticate_sessionless_user!
(
:rss
)
}
before_action
:whitelist_query_limiting
,
except: :commits_root
before_action
:require_non_empty_project
before_action
:assign_ref_vars
,
except: :commits_root
...
...
app/controllers/projects/issues_controller.rb
浏览文件 @
01afaf85
...
...
@@ -9,10 +9,6 @@ class Projects::IssuesController < Projects::ApplicationController
include
IssuesCalendar
include
SpammableActions
def
self
.
authenticate_user_only_actions
%i[new]
end
def
self
.
issue_except_actions
%i[index calendar new create bulk_update]
end
...
...
@@ -21,7 +17,10 @@ class Projects::IssuesController < Projects::ApplicationController
%i[index calendar]
end
prepend_before_action
:authenticate_user!
,
only:
authenticate_user_only_actions
prepend_before_action
(
only:
[
:index
])
{
authenticate_sessionless_user!
(
:rss
)
}
prepend_before_action
(
only:
[
:calendar
])
{
authenticate_sessionless_user!
(
:ics
)
}
prepend_before_action
:authenticate_new_issue!
,
only:
[
:new
]
prepend_before_action
:store_uri
,
only:
[
:new
,
:show
]
before_action
:whitelist_query_limiting
,
only:
[
:create
,
:create_merge_request
,
:move
,
:bulk_update
]
before_action
:check_issues_available!
...
...
@@ -230,16 +229,18 @@ class Projects::IssuesController < Projects::ApplicationController
]
+
[{
label_ids:
[],
assignee_ids:
[]
}]
end
def
authenticate_
user
!
def
authenticate_
new_issue
!
return
if
current_user
notice
=
"Please sign in to create the new issue."
redirect_to
new_user_session_path
,
notice:
notice
end
def
store_uri
if
request
.
get?
&&
!
request
.
xhr?
store_location_for
:user
,
request
.
fullpath
end
redirect_to
new_user_session_path
,
notice:
notice
end
def
serializer
...
...
app/controllers/projects/tags_controller.rb
浏览文件 @
01afaf85
...
...
@@ -3,6 +3,8 @@
class
Projects::TagsController
<
Projects
::
ApplicationController
include
SortingHelper
prepend_before_action
(
only:
[
:index
])
{
authenticate_sessionless_user!
(
:rss
)
}
# Authorize
before_action
:require_non_empty_project
before_action
:authorize_download_code!
...
...
app/controllers/projects_controller.rb
浏览文件 @
01afaf85
...
...
@@ -7,6 +7,8 @@ class ProjectsController < Projects::ApplicationController
include
PreviewMarkdown
include
SendFileUpload
prepend_before_action
(
only:
[
:show
])
{
authenticate_sessionless_user!
(
:rss
)
}
before_action
:whitelist_query_limiting
,
only:
[
:create
]
before_action
:authenticate_user!
,
except:
[
:index
,
:show
,
:activity
,
:refs
]
before_action
:redirect_git_extension
,
only:
[
:show
]
...
...
app/controllers/users_controller.rb
浏览文件 @
01afaf85
...
...
@@ -14,6 +14,7 @@ class UsersController < ApplicationController
calendar_activities:
true
skip_before_action
:authenticate_user!
prepend_before_action
(
only:
[
:show
])
{
authenticate_sessionless_user!
(
:rss
)
}
before_action
:user
,
except:
[
:exists
]
before_action
:authorize_read_user_profile!
,
only:
[
:calendar
,
:calendar_activities
,
:groups
,
:projects
,
:contributed_projects
,
:snippets
]
...
...
changelogs/unreleased/security-fix-pat-web-access.yml
0 → 100644
浏览文件 @
01afaf85
---
title
:
Restrict Personal Access Tokens to API scope on web requests
merge_request
:
author
:
type
:
security
config/initializers/rack_attack_global.rb
浏览文件 @
01afaf85
...
...
@@ -33,22 +33,22 @@ class Rack::Attack
throttle
(
'throttle_authenticated_api'
,
Gitlab
::
Throttle
.
authenticated_api_options
)
do
|
req
|
Gitlab
::
Throttle
.
settings
.
throttle_authenticated_api_enabled
&&
req
.
api_request?
&&
req
.
authenticated_user_id
req
.
authenticated_user_id
([
:api
])
end
throttle
(
'throttle_authenticated_web'
,
Gitlab
::
Throttle
.
authenticated_web_options
)
do
|
req
|
Gitlab
::
Throttle
.
settings
.
throttle_authenticated_web_enabled
&&
req
.
web_request?
&&
req
.
authenticated_user_id
req
.
authenticated_user_id
([
:api
,
:rss
,
:ics
])
end
class
Request
def
unauthenticated?
!
authenticated_user_id
!
authenticated_user_id
([
:api
,
:rss
,
:ics
])
end
def
authenticated_user_id
Gitlab
::
Auth
::
RequestAuthenticator
.
new
(
self
).
user
&
.
id
def
authenticated_user_id
(
request_formats
)
Gitlab
::
Auth
::
RequestAuthenticator
.
new
(
self
).
user
(
request_formats
)
&
.
id
end
def
api_request?
...
...
lib/gitlab/auth/request_authenticator.rb
浏览文件 @
01afaf85
...
...
@@ -13,12 +13,18 @@ module Gitlab
@request
=
request
end
def
user
find_sessionless_user
||
find_user_from_warden
def
user
(
request_formats
)
request_formats
.
each
do
|
format
|
user
=
find_sessionless_user
(
format
)
return
user
if
user
end
find_user_from_warden
end
def
find_sessionless_user
find_user_from_
access_token
||
find_user_from_feed_token
def
find_sessionless_user
(
request_format
)
find_user_from_
web_access_token
(
request_format
)
||
find_user_from_feed_token
(
request_format
)
rescue
Gitlab
::
Auth
::
AuthenticationError
nil
end
...
...
lib/gitlab/auth/user_auth_finders.rb
浏览文件 @
01afaf85
...
...
@@ -27,8 +27,8 @@ module Gitlab
current_request
.
env
[
'warden'
]
&
.
authenticate
if
verified_request?
end
def
find_user_from_feed_token
return
unless
rss_request?
||
ics_request?
def
find_user_from_feed_token
(
request_format
)
return
unless
valid_rss_format?
(
request_format
)
# NOTE: feed_token was renamed from rss_token but both needs to be supported because
# users might have already added the feed to their RSS reader before the rename
...
...
@@ -38,6 +38,17 @@ module Gitlab
User
.
find_by_feed_token
(
token
)
||
raise
(
UnauthorizedError
)
end
# We only allow Private Access Tokens with `api` scope to be used by web
# requests on RSS feeds or ICS files for backwards compatibility.
# It is also used by GraphQL/API requests.
def
find_user_from_web_access_token
(
request_format
)
return
unless
access_token
&&
valid_web_access_format?
(
request_format
)
validate_access_token!
(
scopes:
[
:api
])
access_token
.
user
||
raise
(
UnauthorizedError
)
end
def
find_user_from_access_token
return
unless
access_token
...
...
@@ -109,6 +120,26 @@ module Gitlab
@current_request
||=
ensure_action_dispatch_request
(
request
)
end
def
valid_web_access_format?
(
request_format
)
case
request_format
when
:rss
rss_request?
when
:ics
ics_request?
when
:api
api_request?
end
end
def
valid_rss_format?
(
request_format
)
case
request_format
when
:rss
rss_request?
when
:ics
ics_request?
end
end
def
rss_request?
current_request
.
path
.
ends_with?
(
'.atom'
)
||
current_request
.
format
.
atom?
end
...
...
@@ -116,6 +147,10 @@ module Gitlab
def
ics_request?
current_request
.
path
.
ends_with?
(
'.ics'
)
||
current_request
.
format
.
ics?
end
def
api_request?
current_request
.
path
.
starts_with?
(
"/api/"
)
end
end
end
end
spec/controllers/application_controller_spec.rb
浏览文件 @
01afaf85
...
...
@@ -107,59 +107,6 @@ describe ApplicationController do
end
end
describe
"#authenticate_user_from_personal_access_token!"
do
before
do
stub_authentication_activity_metrics
(
debug:
false
)
end
controller
(
described_class
)
do
def
index
render
text:
'authenticated'
end
end
let
(
:personal_access_token
)
{
create
(
:personal_access_token
,
user:
user
)
}
context
"when the 'personal_access_token' param is populated with the personal access token"
do
it
"logs the user in"
do
expect
(
authentication_metrics
)
.
to
increment
(
:user_authenticated_counter
)
.
and
increment
(
:user_session_override_counter
)
.
and
increment
(
:user_sessionless_authentication_counter
)
get
:index
,
private_token:
personal_access_token
.
token
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
(
response
.
body
).
to
eq
(
'authenticated'
)
end
end
context
"when the 'PERSONAL_ACCESS_TOKEN' header is populated with the personal access token"
do
it
"logs the user in"
do
expect
(
authentication_metrics
)
.
to
increment
(
:user_authenticated_counter
)
.
and
increment
(
:user_session_override_counter
)
.
and
increment
(
:user_sessionless_authentication_counter
)
@request
.
headers
[
"PRIVATE-TOKEN"
]
=
personal_access_token
.
token
get
:index
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
(
response
.
body
).
to
eq
(
'authenticated'
)
end
end
it
"doesn't log the user in otherwise"
do
expect
(
authentication_metrics
)
.
to
increment
(
:user_unauthenticated_counter
)
get
:index
,
private_token:
"token"
expect
(
response
.
status
).
not_to
eq
(
200
)
expect
(
response
.
body
).
not_to
eq
(
'authenticated'
)
end
end
describe
'session expiration'
do
controller
(
described_class
)
do
# The anonymous controller will report 401 and fail to run any actions.
...
...
@@ -224,74 +171,6 @@ describe ApplicationController do
end
end
describe
'#authenticate_sessionless_user!'
do
before
do
stub_authentication_activity_metrics
(
debug:
false
)
end
describe
'authenticating a user from a feed token'
do
controller
(
described_class
)
do
def
index
render
text:
'authenticated'
end
end
context
"when the 'feed_token' param is populated with the feed token"
do
context
'when the request format is atom'
do
it
"logs the user in"
do
expect
(
authentication_metrics
)
.
to
increment
(
:user_authenticated_counter
)
.
and
increment
(
:user_session_override_counter
)
.
and
increment
(
:user_sessionless_authentication_counter
)
get
:index
,
feed_token:
user
.
feed_token
,
format: :atom
expect
(
response
).
to
have_gitlab_http_status
200
expect
(
response
.
body
).
to
eq
'authenticated'
end
end
context
'when the request format is ics'
do
it
"logs the user in"
do
expect
(
authentication_metrics
)
.
to
increment
(
:user_authenticated_counter
)
.
and
increment
(
:user_session_override_counter
)
.
and
increment
(
:user_sessionless_authentication_counter
)
get
:index
,
feed_token:
user
.
feed_token
,
format: :ics
expect
(
response
).
to
have_gitlab_http_status
200
expect
(
response
.
body
).
to
eq
'authenticated'
end
end
context
'when the request format is neither atom nor ics'
do
it
"doesn't log the user in"
do
expect
(
authentication_metrics
)
.
to
increment
(
:user_unauthenticated_counter
)
get
:index
,
feed_token:
user
.
feed_token
expect
(
response
.
status
).
not_to
have_gitlab_http_status
200
expect
(
response
.
body
).
not_to
eq
'authenticated'
end
end
end
context
"when the 'feed_token' param is populated with an invalid feed token"
do
it
"doesn't log the user"
do
expect
(
authentication_metrics
)
.
to
increment
(
:user_unauthenticated_counter
)
get
:index
,
feed_token:
'token'
,
format: :atom
expect
(
response
.
status
).
not_to
eq
200
expect
(
response
.
body
).
not_to
eq
'authenticated'
end
end
end
end
describe
'#route_not_found'
do
it
'renders 404 if authenticated'
do
allow
(
controller
).
to
receive
(
:current_user
).
and_return
(
user
)
...
...
@@ -557,36 +436,6 @@ describe ApplicationController do
expect
(
response
).
to
have_gitlab_http_status
(
200
)
end
context
'for sessionless users'
do
render_views
before
do
sign_out
user
end
it
'renders a 403 when the sessionless user did not accept the terms'
do
get
:index
,
feed_token:
user
.
feed_token
,
format: :atom
expect
(
response
).
to
have_gitlab_http_status
(
403
)
end
it
'renders the error message when the format was html'
do
get
:index
,
private_token:
create
(
:personal_access_token
,
user:
user
).
token
,
format: :html
expect
(
response
.
body
).
to
have_content
/accept the terms of service/i
end
it
'renders a 200 when the sessionless user accepted the terms'
do
accept_terms
(
user
)
get
:index
,
feed_token:
user
.
feed_token
,
format: :atom
expect
(
response
).
to
have_gitlab_http_status
(
200
)
end
end
end
end
...
...
spec/controllers/dashboard/projects_controller_spec.rb
0 → 100644
浏览文件 @
01afaf85
require
'spec_helper'
describe
Dashboard
::
ProjectsController
do
it_behaves_like
'authenticates sessionless user'
,
:index
,
:atom
end
spec/controllers/dashboard_controller_spec.rb
浏览文件 @
01afaf85
require
'spec_helper'
describe
DashboardController
do
let
(
:user
)
{
create
(
:user
)
}
let
(
:project
)
{
create
(
:project
)
}
context
'signed in'
do
let
(
:user
)
{
create
(
:user
)
}
let
(
:project
)
{
create
(
:project
)
}
before
do
project
.
add_maintainer
(
user
)
sign_in
(
user
)
end
before
do
project
.
add_maintainer
(
user
)
sign_in
(
user
)
end
describe
'GET issues'
do
it_behaves_like
'issuables list meta-data'
,
:issue
,
:issues
it_behaves_like
'issuables requiring filter'
,
:issues
end
describe
'GET issues'
do
it_behaves_like
'issuables list meta-data'
,
:issue
,
:issues
it_behaves_like
'issuables requiring filter'
,
:issues
end
describe
'GET merge requests'
do
it_behaves_like
'issuables list meta-data'
,
:merge_request
,
:merge_requests
it_behaves_like
'issuables requiring filter'
,
:merge_requests
describe
'GET merge requests'
do
it_behaves_like
'issuables list meta-data'
,
:merge_request
,
:merge_requests
it_behaves_like
'issuables requiring filter'
,
:merge_requests
end
end
it_behaves_like
'authenticates sessionless user'
,
:issues
,
:atom
,
author_id:
User
.
first
it_behaves_like
'authenticates sessionless user'
,
:issues_calendar
,
:ics
end
spec/controllers/graphql_controller_spec.rb
浏览文件 @
01afaf85
...
...
@@ -52,15 +52,58 @@ describe GraphqlController do
end
end
context
'token authentication'
do
before
do
stub_authentication_activity_metrics
(
debug:
false
)
end
let
(
:user
)
{
create
(
:user
,
username:
'Simon'
)
}
let
(
:personal_access_token
)
{
create
(
:personal_access_token
,
user:
user
)
}
context
"when the 'personal_access_token' param is populated with the personal access token"
do
it
'logs the user in'
do
expect
(
authentication_metrics
)
.
to
increment
(
:user_authenticated_counter
)
.
and
increment
(
:user_session_override_counter
)
.
and
increment
(
:user_sessionless_authentication_counter
)
run_test_query!
(
private_token:
personal_access_token
.
token
)
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
(
query_response
).
to
eq
(
'echo'
=>
'"Simon" says: test success'
)
end
end
context
'when the personal access token has no api scope'
do
it
'does not log the user in'
do
personal_access_token
.
update
(
scopes:
[
:read_user
])
run_test_query!
(
private_token:
personal_access_token
.
token
)
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
(
query_response
).
to
eq
(
'echo'
=>
'nil says: test success'
)
end
end
context
'without token'
do
it
'shows public data'
do
run_test_query!
expect
(
query_response
).
to
eq
(
'echo'
=>
'nil says: test success'
)
end
end
end
# Chosen to exercise all the moving parts in GraphqlController#execute
def
run_test_query!
(
variables:
{
'text'
=>
'test success'
})
def
run_test_query!
(
variables:
{
'text'
=>
'test success'
}
,
private_token:
nil
)
query
=
<<~
QUERY
query Echo($text: String) {
echo(text: $text)
}
QUERY
post
:execute
,
query:
query
,
operationName:
'Echo'
,
variables:
variables
post
:execute
,
query:
query
,
operationName:
'Echo'
,
variables:
variables
,
private_token:
private_token
end
def
query_response
...
...
spec/controllers/groups_controller_spec.rb
浏览文件 @
01afaf85
...
...
@@ -606,4 +606,24 @@ describe GroupsController do
end
end
end
context
'token authentication'
do
it_behaves_like
'authenticates sessionless user'
,
:show
,
:atom
,
public:
true
do
before
do
default_params
.
merge!
(
id:
group
)
end
end
it_behaves_like
'authenticates sessionless user'
,
:issues
,
:atom
,
public:
true
do
before
do
default_params
.
merge!
(
id:
group
,
author_id:
user
.
id
)
end
end
it_behaves_like
'authenticates sessionless user'
,
:issues_calendar
,
:ics
,
public:
true
do
before
do
default_params
.
merge!
(
id:
group
)
end
end
end
end
spec/controllers/projects/commits_controller_spec.rb
浏览文件 @
01afaf85
...
...
@@ -5,87 +5,115 @@ describe Projects::CommitsController do
let
(
:user
)
{
create
(
:user
)
}
before
do
sign_in
(
user
)
project
.
add_maintainer
(
user
)
end
describe
"GET commits_root"
do
context
"no ref is provided"
do
it
'should redirect to the default branch of the project'
do
get
(
:commits_root
,
namespace_id:
project
.
namespace
,
project_id:
project
)
context
'signed in'
do
before
do
sign_in
(
user
)
end
describe
"GET commits_root"
do
context
"no ref is provided"
do
it
'should redirect to the default branch of the project'
do
get
(
:commits_root
,
namespace_id:
project
.
namespace
,
project_id:
project
)
expect
(
response
).
to
redirect_to
project_commits_path
(
project
)
expect
(
response
).
to
redirect_to
project_commits_path
(
project
)
end
end
end
end
describe
"GET show"
do
render_views
describe
"GET show"
do
render_views
context
'with file path'
do
before
do
get
(
:show
,
namespace_id:
project
.
namespace
,
project_id:
project
,
id:
id
)
end
context
'with file path'
do
before
do
get
(
:show
,
namespace_id:
project
.
namespace
,
project_id:
project
,
id:
id
)
end
context
"valid branch, valid file"
do
let
(
:id
)
{
'master/README.md'
}
context
"valid branch, valid file"
do
let
(
:id
)
{
'master/README.md'
}
it
{
is_expected
.
to
respond_with
(
:success
)
}
end
it
{
is_expected
.
to
respond_with
(
:success
)
}
end
context
"valid branch, invalid file"
do
let
(
:id
)
{
'master/invalid-path.rb'
}
context
"valid branch, invalid file"
do
let
(
:id
)
{
'master/invalid-path.rb'
}
it
{
is_expected
.
to
respond_with
(
:not_found
)
}
end
it
{
is_expected
.
to
respond_with
(
:not_found
)
}
end
context
"invalid branch, valid file"
do
let
(
:id
)
{
'invalid-branch/README.md'
}
context
"invalid branch, valid file"
do
let
(
:id
)
{
'invalid-branch/README.md'
}
it
{
is_expected
.
to
respond_with
(
:not_found
)
}
it
{
is_expected
.
to
respond_with
(
:not_found
)
}
end
end
end
context
"when the ref name ends in .atom"
do
context
"when the ref does not exist with the suffix"
do
before
do
get
(
:show
,
namespace_id:
project
.
namespace
,
project_id:
project
,
id:
"master.atom"
)
context
"when the ref name ends in .atom"
do
context
"when the ref does not exist with the suffix"
do
before
do
get
(
:show
,
namespace_id:
project
.
namespace
,
project_id:
project
,
id:
"master.atom"
)
end
it
"renders as atom"
do
expect
(
response
).
to
be_success
expect
(
response
.
content_type
).
to
eq
(
'application/atom+xml'
)
end
it
'renders summary with type=html'
do
expect
(
response
.
body
).
to
include
(
'<summary type="html">'
)
end
end
it
"renders as atom"
do
expect
(
response
).
to
be_success
expect
(
response
.
content_type
).
to
eq
(
'application/atom+xml'
)
end
context
"when the ref exists with the suffix"
do
before
do
commit
=
project
.
repository
.
commit
(
'master'
)
it
'renders summary with type=html'
do
expect
(
response
.
body
).
to
include
(
'<summary type="html">'
)
allow_any_instance_of
(
Repository
).
to
receive
(
:commit
).
and_call_original
allow_any_instance_of
(
Repository
).
to
receive
(
:commit
).
with
(
'master.atom'
).
and_return
(
commit
)
get
(
:show
,
namespace_id:
project
.
namespace
,
project_id:
project
,
id:
"master.atom"
)
end
it
"renders as HTML"
do
expect
(
response
).
to
be_success
expect
(
response
.
content_type
).
to
eq
(
'text/html'
)
end
end
end
end
end
context
"when the ref exists with the suffix"
do
context
'token authentication'
do
context
'public project'
do
it_behaves_like
'authenticates sessionless user'
,
:show
,
:atom
,
public:
true
do
before
do
commit
=
project
.
repository
.
commit
(
'master'
)
public_project
=
create
(
:project
,
:repository
,
:public
)
allow_any_instance_of
(
Repository
).
to
receive
(
:commit
).
and_call_original
allow_any_instance_of
(
Repository
).
to
receive
(
:commit
).
with
(
'master.atom'
).
and_return
(
commit
)
get
(
:show
,
namespace_id:
project
.
namespace
,
project_id:
project
,
id:
"master.atom"
)
default_params
.
merge!
(
namespace_id:
public_project
.
namespace
,
project_id:
public_project
,
id:
"master.atom"
)
end
end
end
context
'private project'
do
it_behaves_like
'authenticates sessionless user'
,
:show
,
:atom
,
public:
false
do
before
do
private_project
=
create
(
:project
,
:repository
,
:private
)
private_project
.
add_maintainer
(
user
)
it
"renders as HTML"
do
expect
(
response
).
to
be_success
expect
(
response
.
content_type
).
to
eq
(
'text/html'
)
default_params
.
merge!
(
namespace_id:
private_project
.
namespace
,
project_id:
private_project
,
id:
"master.atom"
)
end
end
end
...
...
spec/controllers/projects/issues_controller_spec.rb
浏览文件 @
01afaf85
...
...
@@ -1068,4 +1068,40 @@ describe Projects::IssuesController do
end
end
end
context
'private project with token authentication'
do
let
(
:private_project
)
{
create
(
:project
,
:private
)
}
it_behaves_like
'authenticates sessionless user'
,
:index
,
:atom
do
before
do
default_params
.
merge!
(
project_id:
private_project
,
namespace_id:
private_project
.
namespace
)
private_project
.
add_maintainer
(
user
)
end
end
it_behaves_like
'authenticates sessionless user'
,
:calendar
,
:ics
do
before
do
default_params
.
merge!
(
project_id:
private_project
,
namespace_id:
private_project
.
namespace
)
private_project
.
add_maintainer
(
user
)
end
end
end
context
'public project with token authentication'
do
let
(
:public_project
)
{
create
(
:project
,
:public
)
}
it_behaves_like
'authenticates sessionless user'
,
:index
,
:atom
,
public:
true
do
before
do
default_params
.
merge!
(
project_id:
public_project
,
namespace_id:
public_project
.
namespace
)
end
end
it_behaves_like
'authenticates sessionless user'
,
:calendar
,
:ics
,
public:
true
do
before
do
default_params
.
merge!
(
project_id:
public_project
,
namespace_id:
public_project
.
namespace
)
end
end
end
end
spec/controllers/projects/tags_controller_spec.rb
浏览文件 @
01afaf85
...
...
@@ -35,4 +35,26 @@ describe Projects::TagsController do
it
{
is_expected
.
to
respond_with
(
:not_found
)
}
end
end
context
'private project with token authentication'
do
let
(
:private_project
)
{
create
(
:project
,
:repository
,
:private
)
}
it_behaves_like
'authenticates sessionless user'
,
:index
,
:atom
do
before
do
default_params
.
merge!
(
project_id:
private_project
,
namespace_id:
private_project
.
namespace
)
private_project
.
add_maintainer
(
user
)
end
end
end
context
'public project with token authentication'
do
let
(
:public_project
)
{
create
(
:project
,
:repository
,
:public
)
}
it_behaves_like
'authenticates sessionless user'
,
:index
,
:atom
,
public:
true
do
before
do
default_params
.
merge!
(
project_id:
public_project
,
namespace_id:
public_project
.
namespace
)
end
end
end
end
spec/controllers/projects_controller_spec.rb
浏览文件 @
01afaf85
...
...
@@ -882,6 +882,28 @@ describe ProjectsController do
end
end
context
'private project with token authentication'
do
let
(
:private_project
)
{
create
(
:project
,
:private
)
}
it_behaves_like
'authenticates sessionless user'
,
:show
,
:atom
do
before
do
default_params
.
merge!
(
id:
private_project
,
namespace_id:
private_project
.
namespace
)
private_project
.
add_maintainer
(
user
)
end
end
end
context
'public project with token authentication'
do
let
(
:public_project
)
{
create
(
:project
,
:public
)
}
it_behaves_like
'authenticates sessionless user'
,
:show
,
:atom
,
public:
true
do
before
do
default_params
.
merge!
(
id:
public_project
,
namespace_id:
public_project
.
namespace
)
end
end
end
def
project_moved_message
(
redirect_route
,
project
)
"Project '
#{
redirect_route
.
path
}
' was moved to '
#{
project
.
full_path
}
'. Please update any links and bookmarks that may still have the old path."
end
...
...
spec/controllers/users_controller_spec.rb
浏览文件 @
01afaf85
...
...
@@ -395,6 +395,14 @@ describe UsersController do
end
end
context
'token authentication'
do
it_behaves_like
'authenticates sessionless user'
,
:show
,
:atom
,
public:
true
do
before
do
default_params
.
merge!
(
username:
user
.
username
)
end
end
end
def
user_moved_message
(
redirect_route
,
user
)
"User '
#{
redirect_route
.
path
}
' was moved to '
#{
user
.
full_path
}
'. Please update any links and bookmarks that may still have the old path."
end
...
...
spec/lib/gitlab/auth/request_authenticator_spec.rb
浏览文件 @
01afaf85
...
...
@@ -19,17 +19,17 @@ describe Gitlab::Auth::RequestAuthenticator do
allow_any_instance_of
(
described_class
).
to
receive
(
:find_sessionless_user
).
and_return
(
sessionless_user
)
allow_any_instance_of
(
described_class
).
to
receive
(
:find_user_from_warden
).
and_return
(
session_user
)
expect
(
subject
.
user
).
to
eq
sessionless_user
expect
(
subject
.
user
([
:api
])
).
to
eq
sessionless_user
end
it
'returns session user if no sessionless user found'
do
allow_any_instance_of
(
described_class
).
to
receive
(
:find_user_from_warden
).
and_return
(
session_user
)
expect
(
subject
.
user
).
to
eq
session_user
expect
(
subject
.
user
([
:api
])
).
to
eq
session_user
end
it
'returns nil if no user found'
do
expect
(
subject
.
user
).
to
be_blank
expect
(
subject
.
user
([
:api
])
).
to
be_blank
end
it
'bubbles up exceptions'
do
...
...
@@ -42,26 +42,26 @@ describe Gitlab::Auth::RequestAuthenticator do
let!
(
:feed_token_user
)
{
build
(
:user
)
}
it
'returns access_token user first'
do
allow_any_instance_of
(
described_class
).
to
receive
(
:find_user_from_access_token
).
and_return
(
access_token_user
)
allow_any_instance_of
(
described_class
).
to
receive
(
:find_user_from_
web_
access_token
).
and_return
(
access_token_user
)
allow_any_instance_of
(
described_class
).
to
receive
(
:find_user_from_feed_token
).
and_return
(
feed_token_user
)
expect
(
subject
.
find_sessionless_user
).
to
eq
access_token_user
expect
(
subject
.
find_sessionless_user
([
:api
])
).
to
eq
access_token_user
end
it
'returns feed_token user if no access_token user found'
do
allow_any_instance_of
(
described_class
).
to
receive
(
:find_user_from_feed_token
).
and_return
(
feed_token_user
)
expect
(
subject
.
find_sessionless_user
).
to
eq
feed_token_user
expect
(
subject
.
find_sessionless_user
([
:api
])
).
to
eq
feed_token_user
end
it
'returns nil if no user found'
do
expect
(
subject
.
find_sessionless_user
).
to
be_blank
expect
(
subject
.
find_sessionless_user
([
:api
])
).
to
be_blank
end
it
'rescue Gitlab::Auth::AuthenticationError exceptions'
do
allow_any_instance_of
(
described_class
).
to
receive
(
:find_user_from_access_token
).
and_raise
(
Gitlab
::
Auth
::
UnauthorizedError
)
allow_any_instance_of
(
described_class
).
to
receive
(
:find_user_from_
web_
access_token
).
and_raise
(
Gitlab
::
Auth
::
UnauthorizedError
)
expect
(
subject
.
find_sessionless_user
).
to
be_blank
expect
(
subject
.
find_sessionless_user
([
:api
])
).
to
be_blank
end
end
end
spec/lib/gitlab/auth/user_auth_finders_spec.rb
浏览文件 @
01afaf85
...
...
@@ -9,7 +9,7 @@ describe Gitlab::Auth::UserAuthFinders do
'rack.input'
=>
''
}
end
let
(
:request
)
{
Rack
::
Request
.
new
(
env
)}
let
(
:request
)
{
Rack
::
Request
.
new
(
env
)
}
def
set_param
(
key
,
value
)
request
.
update_param
(
key
,
value
)
...
...
@@ -49,6 +49,7 @@ describe Gitlab::Auth::UserAuthFinders do
describe
'#find_user_from_feed_token'
do
context
'when the request format is atom'
do
before
do
env
[
'SCRIPT_NAME'
]
=
'url.atom'
env
[
'HTTP_ACCEPT'
]
=
'application/atom+xml'
end
...
...
@@ -56,17 +57,17 @@ describe Gitlab::Auth::UserAuthFinders do
it
'returns user if valid feed_token'
do
set_param
(
:feed_token
,
user
.
feed_token
)
expect
(
find_user_from_feed_token
).
to
eq
user
expect
(
find_user_from_feed_token
(
:rss
)
).
to
eq
user
end
it
'returns nil if feed_token is blank'
do
expect
(
find_user_from_feed_token
).
to
be_nil
expect
(
find_user_from_feed_token
(
:rss
)
).
to
be_nil
end
it
'returns exception if invalid feed_token'
do
set_param
(
:feed_token
,
'invalid_token'
)
expect
{
find_user_from_feed_token
}.
to
raise_error
(
Gitlab
::
Auth
::
UnauthorizedError
)
expect
{
find_user_from_feed_token
(
:rss
)
}.
to
raise_error
(
Gitlab
::
Auth
::
UnauthorizedError
)
end
end
...
...
@@ -74,34 +75,38 @@ describe Gitlab::Auth::UserAuthFinders do
it
'returns user if valid rssd_token'
do
set_param
(
:rss_token
,
user
.
feed_token
)
expect
(
find_user_from_feed_token
).
to
eq
user
expect
(
find_user_from_feed_token
(
:rss
)
).
to
eq
user
end
it
'returns nil if rss_token is blank'
do
expect
(
find_user_from_feed_token
).
to
be_nil
expect
(
find_user_from_feed_token
(
:rss
)
).
to
be_nil
end
it
'returns exception if invalid rss_token'
do
set_param
(
:rss_token
,
'invalid_token'
)
expect
{
find_user_from_feed_token
}.
to
raise_error
(
Gitlab
::
Auth
::
UnauthorizedError
)
expect
{
find_user_from_feed_token
(
:rss
)
}.
to
raise_error
(
Gitlab
::
Auth
::
UnauthorizedError
)
end
end
end
context
'when the request format is not atom'
do
it
'returns nil'
do
env
[
'SCRIPT_NAME'
]
=
'json'
set_param
(
:feed_token
,
user
.
feed_token
)
expect
(
find_user_from_feed_token
).
to
be_nil
expect
(
find_user_from_feed_token
(
:rss
)
).
to
be_nil
end
end
context
'when the request format is empty'
do
it
'the method call does not modify the original value'
do
env
[
'SCRIPT_NAME'
]
=
'url.atom'
env
.
delete
(
'action_dispatch.request.formats'
)
find_user_from_feed_token
find_user_from_feed_token
(
:rss
)
expect
(
env
[
'action_dispatch.request.formats'
]).
to
be_nil
end
...
...
@@ -111,8 +116,12 @@ describe Gitlab::Auth::UserAuthFinders do
describe
'#find_user_from_access_token'
do
let
(
:personal_access_token
)
{
create
(
:personal_access_token
,
user:
user
)
}
before
do
env
[
'SCRIPT_NAME'
]
=
'url.atom'
end
it
'returns nil if no access_token present'
do
expect
(
find_
personal
_access_token
).
to
be_nil
expect
(
find_
user_from
_access_token
).
to
be_nil
end
context
'when validate_access_token! returns valid'
do
...
...
@@ -131,9 +140,59 @@ describe Gitlab::Auth::UserAuthFinders do
end
end
describe
'#find_user_from_web_access_token'
do
let
(
:personal_access_token
)
{
create
(
:personal_access_token
,
user:
user
)
}
before
do
env
[
Gitlab
::
Auth
::
UserAuthFinders
::
PRIVATE_TOKEN_HEADER
]
=
personal_access_token
.
token
end
it
'returns exception if token has no user'
do
allow_any_instance_of
(
PersonalAccessToken
).
to
receive
(
:user
).
and_return
(
nil
)
expect
{
find_user_from_access_token
}.
to
raise_error
(
Gitlab
::
Auth
::
UnauthorizedError
)
end
context
'no feed or API requests'
do
it
'returns nil if the request is not RSS'
do
expect
(
find_user_from_web_access_token
(
:rss
)).
to
be_nil
end
it
'returns nil if the request is not ICS'
do
expect
(
find_user_from_web_access_token
(
:ics
)).
to
be_nil
end
it
'returns nil if the request is not API'
do
expect
(
find_user_from_web_access_token
(
:api
)).
to
be_nil
end
end
it
'returns the user for RSS requests'
do
env
[
'SCRIPT_NAME'
]
=
'url.atom'
expect
(
find_user_from_web_access_token
(
:rss
)).
to
eq
(
user
)
end
it
'returns the user for ICS requests'
do
env
[
'SCRIPT_NAME'
]
=
'url.ics'
expect
(
find_user_from_web_access_token
(
:ics
)).
to
eq
(
user
)
end
it
'returns the user for API requests'
do
env
[
'SCRIPT_NAME'
]
=
'/api/endpoint'
expect
(
find_user_from_web_access_token
(
:api
)).
to
eq
(
user
)
end
end
describe
'#find_personal_access_token'
do
let
(
:personal_access_token
)
{
create
(
:personal_access_token
,
user:
user
)
}
before
do
env
[
'SCRIPT_NAME'
]
=
'url.atom'
end
context
'passed as header'
do
it
'returns token if valid personal_access_token'
do
env
[
Gitlab
::
Auth
::
UserAuthFinders
::
PRIVATE_TOKEN_HEADER
]
=
personal_access_token
.
token
...
...
spec/support/controllers/sessionless_auth_controller_shared_examples.rb
0 → 100644
浏览文件 @
01afaf85
shared_examples
'authenticates sessionless user'
do
|
path
,
format
,
params
|
params
||=
{}
before
do
stub_authentication_activity_metrics
(
debug:
false
)
end
let
(
:user
)
{
create
(
:user
)
}
let
(
:personal_access_token
)
{
create
(
:personal_access_token
,
user:
user
)
}
let
(
:default_params
)
{
{
format:
format
}.
merge
(
params
.
except
(
:public
)
||
{})
}
context
"when the 'personal_access_token' param is populated with the personal access token"
do
it
'logs the user in'
do
expect
(
authentication_metrics
)
.
to
increment
(
:user_authenticated_counter
)
.
and
increment
(
:user_session_override_counter
)
.
and
increment
(
:user_sessionless_authentication_counter
)
get
path
,
default_params
.
merge
(
private_token:
personal_access_token
.
token
)
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
(
controller
.
current_user
).
to
eq
(
user
)
end
it
'does not log the user in if page is public'
,
if:
params
[
:public
]
do
get
path
,
default_params
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
(
controller
.
current_user
).
to
be_nil
end
end
context
'when the personal access token has no api scope'
,
unless:
params
[
:public
]
do
it
'does not log the user in'
do
expect
(
authentication_metrics
)
.
to
increment
(
:user_unauthenticated_counter
)
personal_access_token
.
update
(
scopes:
[
:read_user
])
get
path
,
default_params
.
merge
(
private_token:
personal_access_token
.
token
)
expect
(
response
).
not_to
have_gitlab_http_status
(
200
)
end
end
context
"when the 'PERSONAL_ACCESS_TOKEN' header is populated with the personal access token"
do
it
'logs the user in'
do
expect
(
authentication_metrics
)
.
to
increment
(
:user_authenticated_counter
)
.
and
increment
(
:user_session_override_counter
)
.
and
increment
(
:user_sessionless_authentication_counter
)
@request
.
headers
[
'PRIVATE-TOKEN'
]
=
personal_access_token
.
token
get
path
,
default_params
expect
(
response
).
to
have_gitlab_http_status
(
200
)
end
end
context
"when the 'feed_token' param is populated with the feed token"
,
if:
format
==
:rss
do
it
"logs the user in"
do
expect
(
authentication_metrics
)
.
to
increment
(
:user_authenticated_counter
)
.
and
increment
(
:user_session_override_counter
)
.
and
increment
(
:user_sessionless_authentication_counter
)
get
path
,
default_params
.
merge
(
feed_token:
user
.
feed_token
)
expect
(
response
).
to
have_gitlab_http_status
200
end
end
context
"when the 'feed_token' param is populated with an invalid feed token"
,
if:
format
==
:rss
,
unless:
params
[
:public
]
do
it
"logs the user"
do
expect
(
authentication_metrics
)
.
to
increment
(
:user_unauthenticated_counter
)
get
path
,
default_params
.
merge
(
feed_token:
'token'
)
expect
(
response
.
status
).
not_to
eq
200
end
end
it
"doesn't log the user in otherwise"
,
unless:
params
[
:public
]
do
expect
(
authentication_metrics
)
.
to
increment
(
:user_unauthenticated_counter
)
get
path
,
default_params
.
merge
(
private_token:
'token'
)
expect
(
response
.
status
).
not_to
eq
(
200
)
end
end
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录