Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
7e3f9e25
Commit
7e3f9e25
authored
Mar 22, 2019
by
Heinrich Lee Yu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement initial configuration page
Adds page to add / remove namespaces within Jira
parent
f651af6b
Changes
29
Show whitespace changes
Inline
Side-by-side
Showing
29 changed files
with
641 additions
and
97 deletions
+641
-97
app/policies/namespace_policy.rb
app/policies/namespace_policy.rb
+2
-0
db/schema.rb
db/schema.rb
+12
-0
doc/development/README.md
doc/development/README.md
+4
-0
doc/development/integrations/jira_connect.md
doc/development/integrations/jira_connect.md
+41
-0
ee/app/controllers/jira_connect/app_descriptor_controller.rb
ee/app/controllers/jira_connect/app_descriptor_controller.rb
+5
-2
ee/app/controllers/jira_connect/application_controller.rb
ee/app/controllers/jira_connect/application_controller.rb
+15
-4
ee/app/controllers/jira_connect/configuration_controller.rb
ee/app/controllers/jira_connect/configuration_controller.rb
+0
-30
ee/app/controllers/jira_connect/events_controller.rb
ee/app/controllers/jira_connect/events_controller.rb
+4
-2
ee/app/controllers/jira_connect/subscriptions_controller.rb
ee/app/controllers/jira_connect/subscriptions_controller.rb
+43
-0
ee/app/models/jira_connect_installation.rb
ee/app/models/jira_connect_installation.rb
+4
-1
ee/app/models/jira_connect_subscription.rb
ee/app/models/jira_connect_subscription.rb
+11
-0
ee/app/policies/ee/group_policy.rb
ee/app/policies/ee/group_policy.rb
+4
-0
ee/app/policies/ee/namespace_policy.rb
ee/app/policies/ee/namespace_policy.rb
+13
-0
ee/app/services/jira_connect_subscriptions/base_service.rb
ee/app/services/jira_connect_subscriptions/base_service.rb
+11
-0
ee/app/services/jira_connect_subscriptions/create_service.rb
ee/app/services/jira_connect_subscriptions/create_service.rb
+35
-0
ee/app/views/jira_connect/subscriptions/index.html.haml
ee/app/views/jira_connect/subscriptions/index.html.haml
+69
-0
ee/app/views/layouts/jira_connect.html.haml
ee/app/views/layouts/jira_connect.html.haml
+13
-0
ee/config/routes/jira_connect.rb
ee/config/routes/jira_connect.rb
+1
-1
ee/db/migrate/20190321103531_create_jira_connect_subscriptions.rb
...grate/20190321103531_create_jira_connect_subscriptions.rb
+20
-0
ee/spec/controllers/jira_connect/app_descriptor_controller_spec.rb
...ontrollers/jira_connect/app_descriptor_controller_spec.rb
+1
-1
ee/spec/controllers/jira_connect/configuration_controller_spec.rb
...controllers/jira_connect/configuration_controller_spec.rb
+0
-52
ee/spec/controllers/jira_connect/events_controller_spec.rb
ee/spec/controllers/jira_connect/events_controller_spec.rb
+10
-0
ee/spec/controllers/jira_connect/subscriptions_controller_spec.rb
...controllers/jira_connect/subscriptions_controller_spec.rb
+167
-0
ee/spec/factories/jira_connect_subscription.rb
ee/spec/factories/jira_connect_subscription.rb
+8
-0
ee/spec/models/jira_connect_installation_spec.rb
ee/spec/models/jira_connect_installation_spec.rb
+5
-0
ee/spec/models/jira_connect_subscription_spec.rb
ee/spec/models/jira_connect_subscription_spec.rb
+15
-0
ee/spec/policies/group_policy_spec.rb
ee/spec/policies/group_policy_spec.rb
+44
-0
ee/spec/policies/namespace_policy_spec.rb
ee/spec/policies/namespace_policy_spec.rb
+24
-4
ee/spec/services/jira_connect_subscriptions/create_service_spec.rb
...ervices/jira_connect_subscriptions/create_service_spec.rb
+60
-0
No files found.
app/policies/namespace_policy.rb
View file @
7e3f9e25
...
...
@@ -15,3 +15,5 @@ class NamespacePolicy < BasePolicy
rule
{
personal_project
&
~
can_create_personal_project
}.
prevent
:create_projects
end
NamespacePolicy
.
prepend
(
EE
::
NamespacePolicy
)
db/schema.rb
View file @
7e3f9e25
...
...
@@ -1648,6 +1648,16 @@ ActiveRecord::Schema.define(version: 20190408163745) do
t
.
index
[
"client_key"
],
name:
"index_jira_connect_installations_on_client_key"
,
unique:
true
,
using: :btree
end
create_table
"jira_connect_subscriptions"
,
force: :cascade
do
|
t
|
t
.
bigint
"jira_connect_installation_id"
,
null:
false
t
.
integer
"namespace_id"
,
null:
false
t
.
datetime_with_timezone
"created_at"
,
null:
false
t
.
datetime_with_timezone
"updated_at"
,
null:
false
t
.
index
[
"jira_connect_installation_id"
,
"namespace_id"
],
name:
"idx_jira_connect_subscriptions_on_installation_id_namespace_id"
,
unique:
true
,
using: :btree
t
.
index
[
"jira_connect_installation_id"
],
name:
"idx_jira_connect_subscriptions_on_installation_id"
,
using: :btree
t
.
index
[
"namespace_id"
],
name:
"index_jira_connect_subscriptions_on_namespace_id"
,
using: :btree
end
create_table
"keys"
,
id: :serial
,
force: :cascade
do
|
t
|
t
.
integer
"user_id"
t
.
datetime
"created_at"
...
...
@@ -3578,6 +3588,8 @@ ActiveRecord::Schema.define(version: 20190408163745) do
add_foreign_key
"issues"
,
"users"
,
column:
"author_id"
,
name:
"fk_05f1e72feb"
,
on_delete: :nullify
add_foreign_key
"issues"
,
"users"
,
column:
"closed_by_id"
,
name:
"fk_c63cbf6c25"
,
on_delete: :nullify
add_foreign_key
"issues"
,
"users"
,
column:
"updated_by_id"
,
name:
"fk_ffed080f01"
,
on_delete: :nullify
add_foreign_key
"jira_connect_subscriptions"
,
"jira_connect_installations"
,
on_delete: :cascade
add_foreign_key
"jira_connect_subscriptions"
,
"namespaces"
,
on_delete: :cascade
add_foreign_key
"label_links"
,
"labels"
,
name:
"fk_d97dd08678"
,
on_delete: :cascade
add_foreign_key
"label_priorities"
,
"labels"
,
on_delete: :cascade
add_foreign_key
"label_priorities"
,
"projects"
,
on_delete: :cascade
...
...
doc/development/README.md
View file @
7e3f9e25
...
...
@@ -104,6 +104,10 @@ description: 'Learn how to contribute to GitLab.'
-
[
Query Count Limits
](
query_count_limits.md
)
-
[
Database helper modules
](
database_helpers.md
)
## Integration guides
-
[
Jira Connect app
](
integrations/jira_connect.md
)
## Testing guides
-
[
Testing standards and style guidelines
](
testing_guide/index.md
)
...
...
doc/development/integrations/jira_connect.md
0 → 100644
View file @
7e3f9e25
# Setting up a development environment
The following are required to install and test the app:
1.
A Jira Cloud instance
Atlassian provides free instances for development and testing.
[
Click here to sign up
](
http://go.atlassian.com/cloud-dev
)
.
1.
A GitLab instance available over the internet
For the app to work, Jira Cloud should be able to connect to the GitLab instance through the internet.
To easily expose your local development environment, you can use tools like
[
serveo
](
https://serveo.net
)
or
[
ngrok
](
https://ngrok.com
)
.
These also take care of SSL for you because Jira requires all connections to the app host to be over SSL.
> This feature is currently behind the `:jira_connect_app` feature flag
# Installing the app in Jira
1.
Enable Jira development mode to install apps that are not from the Atlassian Marketplace
1.
Navigate to
**Jira settings**
(cog icon) >
**Apps**
>
**Manage apps**
.
1.
Scroll to the bottom of the
**Manage apps**
page and click
**Settings**
.
1.
Select
**Enable development mode**
and click
**Apply**
.
1.
Install the app
1.
Navigate to Jira, then choose
**Jira settings**
(cog icon) >
**Apps**
>
**Manage apps**
.
1.
Click
**Upload app**
.
1.
In the
**From this URL**
field, provide a link to the app descriptor. The host and port must point to your GitLab instance.
For example:
```
https://xxxx.serveo.net/-/jira_connect/app_descriptor.json
```
1.
Click
**Upload**
.
If the install was successful, you should see the
**GitLab for Jira**
app under
**Manage apps**
.
You can also click
**Getting Started**
to open the configuration page rendered from your GitLab instance.
_Note that any changes to the app descriptor requires you to uninstall then reinstall the app._
ee/app/controllers/jira_connect/app_descriptor_controller.rb
View file @
7e3f9e25
...
...
@@ -12,7 +12,7 @@ class JiraConnect::AppDescriptorController < JiraConnect::ApplicationController
name:
"GitLab for Jira (
#{
Gitlab
.
config
.
gitlab
.
host
}
)"
,
description:
'Integrate commits, branches and merge requests from GitLab into Jira'
,
key:
"gitlab-jira-connect-
#{
Gitlab
.
config
.
gitlab
.
host
}
"
,
baseUrl:
jira_connect_base_url
,
baseUrl:
jira_connect_base_url
(
protocol:
'https'
)
,
lifecycle:
{
installed:
relative_to_base_path
(
jira_connect_events_installed_path
),
uninstalled:
relative_to_base_path
(
jira_connect_events_uninstalled_path
)
...
...
@@ -44,8 +44,11 @@ class JiraConnect::AppDescriptorController < JiraConnect::ApplicationController
name:
{
value:
'GitLab Configuration'
},
url:
relative_to_base_path
(
jira_connect_
configuration
_path
)
url:
relative_to_base_path
(
jira_connect_
subscriptions
_path
)
}
},
apiMigrations:
{
gdpr:
true
}
}
end
...
...
ee/app/controllers/jira_connect/application_controller.rb
View file @
7e3f9e25
...
...
@@ -4,6 +4,7 @@ class JiraConnect::ApplicationController < ApplicationController
include
Gitlab
::
Utils
::
StrongMemoize
skip_before_action
:authenticate_user!
skip_before_action
:verify_authenticity_token
before_action
:check_feature_flag_enabled!
before_action
:verify_atlassian_jwt!
...
...
@@ -21,14 +22,20 @@ class JiraConnect::ApplicationController < ApplicationController
@current_jira_installation
=
installation_from_jwt
end
def
verify_qsh_claim!
payload
,
_
=
decode_auth_token!
# Make sure `qsh` claim matches the current request
render_403
unless
payload
[
'qsh'
]
==
Atlassian
::
Jwt
.
create_query_string_hash
(
request
.
method
,
request
.
url
,
jira_connect_base_url
)
rescue
render_403
end
def
atlassian_jwt_valid?
return
false
unless
installation_from_jwt
# Verify JWT signature with our stored `shared_secret`
payload
,
_
=
Atlassian
::
Jwt
.
decode
(
auth_token
,
installation_from_jwt
.
shared_secret
)
# Make sure `qsh` claim matches the current request
payload
[
'qsh'
]
==
Atlassian
::
Jwt
.
create_query_string_hash
(
request
.
method
,
request
.
url
,
jira_connect_base_url
)
decode_auth_token!
rescue
JWT
::
DecodeError
false
end
...
...
@@ -43,6 +50,10 @@ class JiraConnect::ApplicationController < ApplicationController
end
end
def
decode_auth_token!
Atlassian
::
Jwt
.
decode
(
auth_token
,
installation_from_jwt
.
shared_secret
)
end
def
auth_token
strong_memoize
(
:auth_token
)
do
params
[
:jwt
]
||
request
.
headers
[
'Authorization'
]
&
.
split
(
' '
,
2
)
&
.
last
...
...
ee/app/controllers/jira_connect/configuration_controller.rb
deleted
100644 → 0
View file @
f651af6b
# frozen_string_literal: true
class
JiraConnect::ConfigurationController
<
JiraConnect
::
ApplicationController
before_action
:allow_rendering_in_iframe
def
show
sample_html
=
<<~
HEREDOC
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://unpkg.com/@atlaskit/css-reset@2.0.0/dist/bundle.css" media="all">
<script src="https://connect-cdn.atl-paas.net/all.js" async></script>
</head>
<body>
<section id="content" class="ac-content" style="padding: 20px;">
<h1>Hello from GitLab!</h1>
</section>
</body>
</html>
HEREDOC
render
html:
sample_html
.
html_safe
end
private
def
allow_rendering_in_iframe
response
.
headers
.
delete
(
'X-Frame-Options'
)
end
end
ee/app/controllers/jira_connect/events_controller.rb
View file @
7e3f9e25
# frozen_string_literal: true
class
JiraConnect::EventsController
<
JiraConnect
::
ApplicationController
skip_before_action
:verify_authenticity_token
skip_before_action
:verify_atlassian_jwt!
,
only: :installed
before_action
:verify_qsh_claim!
,
only: :uninstalled
def
installed
if
JiraConnectInstallation
.
create
(
install_params
)
installation
=
JiraConnectInstallation
.
new
(
install_params
)
if
installation
.
save
head
:ok
else
head
:unprocessable_entity
...
...
ee/app/controllers/jira_connect/subscriptions_controller.rb
0 → 100644
View file @
7e3f9e25
# frozen_string_literal: true
class
JiraConnect::SubscriptionsController
<
JiraConnect
::
ApplicationController
layout
'jira_connect'
before_action
:allow_rendering_in_iframe
,
only: :index
before_action
:verify_qsh_claim!
,
only: :index
before_action
:authenticate_user!
,
only: :create
def
index
@subscriptions
=
current_jira_installation
.
subscriptions
.
preload_namespace_route
end
def
create
result
=
create_service
.
execute
if
result
[
:status
]
==
:success
render
json:
{
success:
true
}
else
render
json:
{
error:
result
[
:message
]
},
status:
result
[
:http_status
]
end
end
def
destroy
subscription
=
current_jira_installation
.
subscriptions
.
find
(
params
[
:id
])
if
subscription
.
destroy
render
json:
{
success:
true
}
else
render
json:
{
error:
subscription
.
errors
.
full_messages
.
join
(
', '
)
},
status: :unprocessable_entity
end
end
private
def
create_service
JiraConnectSubscriptions
::
CreateService
.
new
(
current_jira_installation
,
current_user
,
namespace_path:
params
[
'namespace_path'
])
end
def
allow_rendering_in_iframe
response
.
headers
.
delete
(
'X-Frame-Options'
)
end
end
ee/app/models/jira_connect_installation.rb
View file @
7e3f9e25
...
...
@@ -6,6 +6,9 @@ class JiraConnectInstallation < ApplicationRecord
algorithm:
'aes-256-gcm'
,
key:
Settings
.
attr_encrypted_db_key_base_32
validates
:client_key
,
:shared_secret
,
presence:
true
has_many
:subscriptions
,
class_name:
'JiraConnectSubscription'
validates
:client_key
,
presence:
true
,
uniqueness:
true
validates
:shared_secret
,
presence:
true
validates
:base_url
,
presence:
true
,
public_url:
true
end
ee/app/models/jira_connect_subscription.rb
0 → 100644
View file @
7e3f9e25
# frozen_string_literal: true
class
JiraConnectSubscription
<
ApplicationRecord
belongs_to
:installation
,
class_name:
'JiraConnectInstallation'
,
foreign_key:
'jira_connect_installation_id'
belongs_to
:namespace
validates
:installation
,
presence:
true
validates
:namespace
,
presence:
true
,
uniqueness:
{
scope: :jira_connect_installation_id
,
message:
'has already been added'
}
scope
:preload_namespace_route
,
->
{
preload
(
namespace: :route
)
}
end
ee/app/policies/ee/group_policy.rb
View file @
7e3f9e25
...
...
@@ -26,6 +26,10 @@ module EE
enable
:admin_board
end
rule
{
maintainer
}.
policy
do
enable
:create_jira_connect_subscription
end
rule
{
can?
(
:read_group
)
&
contribution_analytics_available
}
.
enable
:read_group_contribution_analytics
...
...
ee/app/policies/ee/namespace_policy.rb
0 → 100644
View file @
7e3f9e25
# frozen_string_literal: true
module
EE
module
NamespacePolicy
extend
ActiveSupport
::
Concern
prepended
do
rule
{
owner
|
admin
}.
policy
do
enable
:create_jira_connect_subscription
end
end
end
end
ee/app/services/jira_connect_subscriptions/base_service.rb
0 → 100644
View file @
7e3f9e25
# frozen_string_literal: true
module
JiraConnectSubscriptions
class
BaseService
<
::
BaseService
attr_accessor
:jira_connect_installation
,
:current_user
,
:params
def
initialize
(
jira_connect_installation
,
user
=
nil
,
params
=
{})
@jira_connect_installation
,
@current_user
,
@params
=
jira_connect_installation
,
user
,
params
.
dup
end
end
end
ee/app/services/jira_connect_subscriptions/create_service.rb
0 → 100644
View file @
7e3f9e25
# frozen_string_literal: true
module
JiraConnectSubscriptions
class
CreateService
<
::
JiraConnectSubscriptions
::
BaseService
include
Gitlab
::
Utils
::
StrongMemoize
def
execute
unless
namespace
&&
can?
(
current_user
,
:create_jira_connect_subscription
,
namespace
)
return
error
(
'Invalid namespace. Please make sure you have sufficient permissions'
,
401
)
end
return
error
(
'This feature is not available'
,
422
)
unless
namespace
.
feature_available?
(
:jira_dev_panel_integration
)
create_subscription
end
private
def
create_subscription
subscription
=
JiraConnectSubscription
.
new
(
installation:
jira_connect_installation
,
namespace:
namespace
)
if
subscription
.
save
success
else
error
(
subscription
.
errors
.
full_messages
.
join
(
', '
),
422
)
end
end
def
namespace
strong_memoize
(
:namespace
)
do
Namespace
.
find_by_full_path
(
params
[
:namespace_path
])
end
end
end
end
ee/app/views/jira_connect/subscriptions/index.html.haml
0 → 100644
View file @
7e3f9e25
%h1
GitLab for Jira Configuration
%form
#add-subscription-form
{
style:
'margin-bottom: 20px;'
}
.ak-field-group
%label
Namespace
%input
#namespace-input
.ak-field-text
{
type:
'text'
,
required:
true
}
.ak-field-group
%button
.ak-button.ak-button__appearance-primary
{
type:
'submit'
}
Link namespace to Jira
%table
.subscriptions
%thead
%tr
%th
Namespace
%th
Added
%th
%tbody
-
@subscriptions
.
each
do
|
subscription
|
%tr
%td
=
subscription
.
namespace
.
full_path
%td
=
subscription
.
created_at
%td
=
link_to
'Remove'
,
jira_connect_subscription_path
(
subscription
),
class:
'remove-subscription'
:javascript
window
.
onload
=
function
()
{
$
(
'
#add-subscription-form
'
).
submit
(
function
(
e
)
{
e
.
preventDefault
();
AP
.
context
.
getToken
(
function
(
token
)
{
$
.
post
(
'
/-/jira_connect/subscriptions
'
,
{
jwt
:
token
,
namespace_path
:
$
(
'
#namespace-input
'
).
val
(),
format
:
'
json
'
,
})
.
done
(
function
(
response
)
{
AP
.
navigator
.
reload
();
})
.
fail
(
function
(
xhr
)
{
alert
(
xhr
.
responseJSON
.
error
);
});
});
});
$
(
'
.remove-subscription
'
).
click
(
function
(
e
)
{
e
.
preventDefault
();
var
href
=
$
(
this
).
attr
(
'
href
'
);
AP
.
context
.
getToken
(
function
(
token
)
{
$
.
ajax
({
url
:
href
,
method
:
'
DELETE
'
,
data
:
{
jwt
:
token
,
format
:
'
json
'
,
},
})
.
done
(
function
(
response
)
{
AP
.
navigator
.
reload
();
})
.
fail
(
function
(
xhr
)
{
alert
(
xhr
.
responseJSON
.
error
);
});
});
});
};
ee/app/views/layouts/jira_connect.html.haml
0 → 100644
View file @
7e3f9e25
%html
{
lang:
"en"
}
%head
%meta
{
content:
"text/html; charset=utf-8"
,
"http-equiv"
=>
"Content-Type"
}
%title
GitLab
=
stylesheet_link_tag
'https://unpkg.com/@atlaskit/css-reset@3.0.6/dist/bundle.css'
=
stylesheet_link_tag
'https://unpkg.com/@atlaskit/reduced-ui-pack@10.5.5/dist/bundle.css'
=
javascript_include_tag
'https://connect-cdn.atl-paas.net/all.js'
=
javascript_include_tag
'https://unpkg.com/jquery@3.3.1/dist/jquery.min.js'
=
yield
:head
%body
.ac-content
{
style:
'margin: 20px;'
}
=
yield
ee/config/routes/jira_connect.rb
View file @
7e3f9e25
...
...
@@ -11,5 +11,5 @@ namespace :jira_connect do
post
'uninstalled'
end
get
'configuration'
=>
'configuration#show'
resources
:subscriptions
,
only:
[
:index
,
:create
,
:destroy
]
end
ee/db/migrate/20190321103531_create_jira_connect_subscriptions.rb
0 → 100644
View file @
7e3f9e25
# frozen_string_literal: true
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class
CreateJiraConnectSubscriptions
<
ActiveRecord
::
Migration
[
5.0
]
include
Gitlab
::
Database
::
MigrationHelpers
DOWNTIME
=
false
def
change
create_table
:jira_connect_subscriptions
,
id: :bigserial
do
|
t
|
t
.
references
:jira_connect_installation
,
type: :bigint
,
foreign_key:
{
on_delete: :cascade
},
index:
{
name:
'idx_jira_connect_subscriptions_on_installation_id'
},
null:
false
t
.
references
:namespace
,
foreign_key:
{
on_delete: :cascade
},
null:
false
t
.
timestamps_with_timezone
end
add_index
:jira_connect_subscriptions
,
[
:jira_connect_installation_id
,
:namespace_id
],
unique:
true
,
name:
'idx_jira_connect_subscriptions_on_installation_id_namespace_id'
end
end
ee/spec/controllers/jira_connect/app_descriptor_controller_spec.rb
View file @
7e3f9e25
...
...
@@ -26,7 +26,7 @@ describe JiraConnect::AppDescriptorController do
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
(
json_response
).
to
include
(
'baseUrl'
=>
'http://test.host/-/jira_connect'
,
'baseUrl'
=>
'http
s
://test.host/-/jira_connect'
,
'lifecycle'
=>
{
'installed'
=>
'/events/installed'
,
'uninstalled'
=>
'/events/uninstalled'
...
...
ee/spec/controllers/jira_connect/configuration_controller_spec.rb
deleted
100644 → 0
View file @
f651af6b
# frozen_string_literal: true
require
'spec_helper'
describe
JiraConnect
::
ConfigurationController
do
describe
'#show'
do
context
'feature disabled'
do
before
do
stub_feature_flags
(
jira_connect_app:
false
)
end
it
'returns 404'
do
get
:show
expect
(
response
).
to
have_gitlab_http_status
(
404
)
end
end
context
'feature enabled'
do
before
do
stub_feature_flags
(
jira_connect_app:
true
)
end
context
'without JWT'
do
it
'returns 403'
do
get
:show
expect
(
response
).
to
have_gitlab_http_status
(
403
)
end
end
context
'with correct JWT'
do
let
(
:installation
)
{
create
(
:jira_connect_installation
)
}
let
(
:qsh
)
{
Atlassian
::
Jwt
.
create_query_string_hash
(
'GET'
,
'/configuration'
)
}
before
do
get
:show
,
params:
{
jwt:
Atlassian
::
Jwt
.
encode
({
iss:
installation
.
client_key
,
qsh:
qsh
},
installation
.
shared_secret
)
}
end
it
'returns 200'
do
expect
(
response
).
to
have_gitlab_http_status
(
200
)
end
it
'removes X-Frame-Options to allow rendering in iframe'
do
expect
(
response
.
headers
[
'X-Frame-Options'
]).
to
be_nil
end
end
end
end
end
ee/spec/controllers/jira_connect/events_controller_spec.rb
View file @
7e3f9e25
...
...
@@ -51,6 +51,16 @@ describe JiraConnect::EventsController do
expect
(
installation
.
shared_secret
).
to
eq
(
'secret'
)
expect
(
installation
.
base_url
).
to
eq
(
'https://test.atlassian.net'
)
end
context
'client key already exists'
do
it
'returns 422'
do
create
(
:jira_connect_installation
,
client_key:
'1234'
)
subject
expect
(
response
).
to
have_gitlab_http_status
(
422
)
end
end
end
describe
'#uninstalled'
do
...
...
ee/spec/controllers/jira_connect/subscriptions_controller_spec.rb
0 → 100644
View file @
7e3f9e25
# frozen_string_literal: true
require
'spec_helper'
describe
JiraConnect
::
SubscriptionsController
do
context
'feature disabled'
do
before
do
stub_feature_flags
(
jira_connect_app:
false
)
end
describe
'#index'
do
it
'returns 404'
do
get
:index
expect
(
response
).
to
have_gitlab_http_status
(
404
)
end
end
describe
'#create'
do
it
'#create returns 404'
do
post
:create
expect
(
response
).
to
have_gitlab_http_status
(
404
)
end
end
describe
'#destroy'
do
let
(
:subscription
)
{
create
(
:jira_connect_subscription
)
}
it
'#destroy returns 404'
do
delete
:destroy
,
params:
{
id:
subscription
.
id
}
expect
(
response
).
to
have_gitlab_http_status
(
404
)
end
end
end
context
'feature enabled'
do
before
do
stub_feature_flags
(
jira_connect_app:
true
)
end
let
(
:installation
)
{
create
(
:jira_connect_installation
)
}
describe
'#index'
do
before
do
get
:index
,
params:
{
jwt:
jwt
}
end
context
'without JWT'
do
let
(
:jwt
)
{
nil
}
it
'returns 403'
do
expect
(
response
).
to
have_gitlab_http_status
(
403
)
end
end
context
'with valid JWT'
do
let
(
:qsh
)
{
Atlassian
::
Jwt
.
create_query_string_hash
(
'GET'
,
'/subscriptions'
)
}
let
(
:jwt
)
{
Atlassian
::
Jwt
.
encode
({
iss:
installation
.
client_key
,
qsh:
qsh
},
installation
.
shared_secret
)
}
it
'returns 200'
do
expect
(
response
).
to
have_gitlab_http_status
(
200
)
end
it
'removes X-Frame-Options to allow rendering in iframe'
do
expect
(
response
.
headers
[
'X-Frame-Options'
]).
to
be_nil
end
end
end
describe
'#create'
do
let
(
:group
)
{
create
(
:group
)
}
let
(
:user
)
{
create
(
:user
)
}
let
(
:current_user
)
{
user
}
before
do
group
.
add_maintainer
(
user
)
end
subject
{
post
:create
,
params:
{
jwt:
jwt
,
namespace_path:
group
.
path
,
format: :json
}
}
context
'without JWT'
do
let
(
:jwt
)
{
nil
}
it
'returns 403'
do
sign_in
(
user
)
subject
expect
(
response
).
to
have_gitlab_http_status
(
403
)
end
end
context
'with valid JWT'
do
let
(
:jwt
)
{
Atlassian
::
Jwt
.
encode
({
iss:
installation
.
client_key
},
installation
.
shared_secret
)
}
context
'signed in to GitLab'
do
before
do
sign_in
(
user
)
end
context
'dev panel integration is available'
do
before
do
stub_licensed_features
(
jira_dev_panel_integration:
true
)
end
it
'creates a subscription'
do
expect
{
subject
}.
to
change
{
installation
.
subscriptions
.
count
}.
from
(
0
).
to
(
1
)
end
it
'returns 200'
do
subject
expect
(
response
).
to
have_gitlab_http_status
(
200
)
end
end
context
'dev panel integration is not available'
do
before
do
stub_licensed_features
(
jira_dev_panel_integration:
false
)
end
it
'returns 422'
do
subject
expect
(
response
).
to
have_gitlab_http_status
(
422
)
end
end
end
context
'not signed in to GitLab'
do
it
'returns 401'
do
subject
expect
(
response
).
to
have_gitlab_http_status
(
401
)
end
end
end
end
describe
'#destroy'
do
let
(
:subscription
)
{
create
(
:jira_connect_subscription
,
installation:
installation
)
}
before
do
delete
:destroy
,
params:
{
jwt:
jwt
,
id:
subscription
.
id
}
end
context
'without JWT'
do
let
(
:jwt
)
{
nil
}
it
'returns 403'
do
expect
(
response
).
to
have_gitlab_http_status
(
403
)
end
end
context
'with valid JWT'
do
let
(
:jwt
)
{
Atlassian
::
Jwt
.
encode
({
iss:
installation
.
client_key
},
installation
.
shared_secret
)
}
it
'deletes the subscription'
do
expect
{
subscription
.
reload
}.
to
raise_error
ActiveRecord
::
RecordNotFound
expect
(
response
).
to
have_gitlab_http_status
(
200
)
end
end
end
end
end
ee/spec/factories/jira_connect_subscription.rb
0 → 100644
View file @
7e3f9e25
# frozen_string_literal: true
FactoryBot
.
define
do
factory
:jira_connect_subscription
do
association
:installation
,
factory: :jira_connect_installation
association
:namespace
,
factory: :group
end
end
ee/spec/models/jira_connect_installation_spec.rb
View file @
7e3f9e25
...
...
@@ -3,8 +3,13 @@
require
'spec_helper'
describe
JiraConnectInstallation
do
describe
'associations'
do
it
{
is_expected
.
to
have_many
(
:subscriptions
).
class_name
(
'JiraConnectSubscription'
)
}
end
describe
'validations'
do
it
{
is_expected
.
to
validate_presence_of
(
:client_key
)
}
it
{
is_expected
.
to
validate_uniqueness_of
(
:client_key
)
}
it
{
is_expected
.
to
validate_presence_of
(
:shared_secret
)
}
it
{
is_expected
.
to
validate_presence_of
(
:base_url
)
}
...
...
ee/spec/models/jira_connect_subscription_spec.rb
0 → 100644
View file @
7e3f9e25
# frozen_string_literal: true
require
'spec_helper'
describe
JiraConnectSubscription
do
describe
'associations'
do
it
{
is_expected
.
to
belong_to
(
:installation
).
class_name
(
'JiraConnectInstallation'
)
}
it
{
is_expected
.
to
belong_to
(
:namespace
).
class_name
(
'Namespace'
)
}
end
describe
'validations'
do
it
{
is_expected
.
to
validate_presence_of
(
:installation
)
}
it
{
is_expected
.
to
validate_presence_of
(
:namespace
)
}
end
end
ee/spec/policies/group_policy_spec.rb
View file @
7e3f9e25
...
...
@@ -146,6 +146,50 @@ describe GroupPolicy do
end
end
describe
'create_jira_connect_subscription'
do
context
'admin'
do
let
(
:current_user
)
{
admin
}
it
{
is_expected
.
to
be_allowed
(
:create_jira_connect_subscription
)
}
end
context
'with owner'
do
let
(
:current_user
)
{
owner
}
it
{
is_expected
.
to
be_allowed
(
:create_jira_connect_subscription
)
}
end
context
'with maintainer'
do
let
(
:current_user
)
{
maintainer
}
it
{
is_expected
.
to
be_allowed
(
:create_jira_connect_subscription
)
}
end
context
'with reporter'
do
let
(
:current_user
)
{
reporter
}
it
{
is_expected
.
to
be_disallowed
(
:create_jira_connect_subscription
)
}
end
context
'with guest'
do
let
(
:current_user
)
{
guest
}
it
{
is_expected
.
to
be_disallowed
(
:create_jira_connect_subscription
)
}
end
context
'with non member'
do
let
(
:current_user
)
{
create
(
:user
)
}
it
{
is_expected
.
to
be_disallowed
(
:create_jira_connect_subscription
)
}
end
context
'with anonymous'
do
let
(
:current_user
)
{
nil
}
it
{
is_expected
.
to
be_disallowed
(
:create_jira_connect_subscription
)
}
end
end
describe
'read_group_security_dashboard'
do
before
do
stub_licensed_features
(
security_dashboard:
true
)
...
...
ee/spec/policies/namespace_policy_spec.rb
View file @
7e3f9e25
...
...
@@ -3,17 +3,17 @@
require
'spec_helper'
describe
NamespacePolicy
do
let
(
:owner
)
{
create
(
:user
)
}
let
(
:namespace
)
{
create
(
:namespace
,
owner:
owner
)
}
let
(
:owner
)
{
build_stubbed
(
:user
)
}
let
(
:namespace
)
{
build_stubbed
(
:namespace
,
owner:
owner
)
}
let
(
:owner_permissions
)
{
[
:create_projects
,
:admin_namespace
,
:read_namespace
]
}
subject
{
described_class
.
new
(
current_user
,
namespace
)
}
context
'auditor'
do
let
(
:current_user
)
{
create
(
:user
,
:auditor
)
}
let
(
:current_user
)
{
build_stubbed
(
:user
,
:auditor
)
}
context
'owner'
do
let
(
:namespace
)
{
create
(
:namespace
,
owner:
current_user
)
}
let
(
:namespace
)
{
build_stubbed
(
:namespace
,
owner:
current_user
)
}
it
{
is_expected
.
to
be_allowed
(
*
owner_permissions
)
}
end
...
...
@@ -22,4 +22,24 @@ describe NamespacePolicy do
it
{
is_expected
.
to
be_disallowed
(
*
owner_permissions
)
}
end
end
describe
'create_jira_connect_subscription'
do
context
'admin'
do
let
(
:current_user
)
{
build_stubbed
(
:admin
)
}
it
{
is_expected
.
to
be_allowed
(
:create_jira_connect_subscription
)
}
end
context
'owner'
do
let
(
:current_user
)
{
owner
}
it
{
is_expected
.
to
be_allowed
(
:create_jira_connect_subscription
)
}
end
context
'other user'
do
let
(
:current_user
)
{
build_stubbed
(
:user
)
}
it
{
is_expected
.
to
be_disallowed
(
:create_jira_connect_subscription
)
}
end
end
end
ee/spec/services/jira_connect_subscriptions/create_service_spec.rb
0 → 100644
View file @
7e3f9e25
# frozen_string_literal: true
require
'spec_helper'
describe
JiraConnectSubscriptions
::
CreateService
do
let
(
:installation
)
{
create
(
:jira_connect_installation
)
}
let
(
:current_user
)
{
create
(
:user
)
}
let
(
:group
)
{
create
(
:group
)
}
let
(
:path
)
{
group
.
full_path
}
subject
{
described_class
.
new
(
installation
,
current_user
,
namespace_path:
path
).
execute
}
before
do
group
.
add_maintainer
(
current_user
)
end
shared_examples
'a failed execution'
do
it
'does not create a subscription'
do
expect
{
subject
}.
not_to
change
{
installation
.
subscriptions
.
count
}
end
it
'returns an error status'
do
expect
(
subject
[
:status
]).
to
eq
(
:error
)
end
end
context
'when jira_dev_panel_integration is available'
do
before
do
stub_licensed_features
(
jira_dev_panel_integration:
true
)
end
it
'creates a subscription'
do
expect
{
subject
}.
to
change
{
installation
.
subscriptions
.
count
}.
from
(
0
).
to
(
1
)
end
it
'returns success'
do
expect
(
subject
[
:status
]).
to
eq
(
:success
)
end
context
'when path is invalid'
do
let
(
:path
)
{
'some_invalid_namespace_path'
}
it_behaves_like
'a failed execution'
end
context
'when user does not have access'
do
subject
{
described_class
.
new
(
installation
,
create
(
:user
),
namespace_path:
path
).
execute
}
it_behaves_like
'a failed execution'
end
end
context
'when jira_dev_panel_integration is not available'
do
before
do
stub_licensed_features
(
jira_dev_panel_integration:
false
)
end
it_behaves_like
'a failed execution'
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment