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
297aa92b
Commit
297aa92b
authored
May 27, 2020
by
Jarka Košanová
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Create graphQL endpoint for Jira users import
- add mutation, JiraUser graphql type - call repective service
parent
ac9e467e
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
499 additions
and
2 deletions
+499
-2
app/graphql/mutations/jira_import/import_users.rb
app/graphql/mutations/jira_import/import_users.rb
+44
-0
app/graphql/types/jira_user_type.rb
app/graphql/types/jira_user_type.rb
+19
-0
app/graphql/types/mutation_type.rb
app/graphql/types/mutation_type.rb
+1
-0
app/services/jira_import/users_importer.rb
app/services/jira_import/users_importer.rb
+2
-0
app/services/service_response.rb
app/services/service_response.rb
+6
-0
changelogs/unreleased/216145-jira-users-import-endpoint.yml
changelogs/unreleased/216145-jira-users-import-endpoint.yml
+5
-0
doc/api/graphql/reference/gitlab_schema.graphql
doc/api/graphql/reference/gitlab_schema.graphql
+63
-0
doc/api/graphql/reference/gitlab_schema.json
doc/api/graphql/reference/gitlab_schema.json
+224
-0
doc/api/graphql/reference/index.md
doc/api/graphql/reference/index.md
+19
-0
spec/requests/api/graphql/mutations/jira_import/import_users_spec.rb
...ts/api/graphql/mutations/jira_import/import_users_spec.rb
+104
-0
spec/services/jira_import/users_importer_spec.rb
spec/services/jira_import/users_importer_spec.rb
+2
-2
spec/services/service_response_spec.rb
spec/services/service_response_spec.rb
+10
-0
No files found.
app/graphql/mutations/jira_import/import_users.rb
0 → 100644
View file @
297aa92b
# frozen_string_literal: true
module
Mutations
module
JiraImport
class
ImportUsers
<
BaseMutation
include
ResolvesProject
graphql_name
'JiraImportUsers'
field
:jira_users
,
[
Types
::
JiraUserType
],
null:
true
,
description:
'Users returned from Jira, matched by email and name if possible.'
argument
:project_path
,
GraphQL
::
ID_TYPE
,
required:
true
,
description:
'The project to import the Jira users into'
argument
:start_at
,
GraphQL
::
INT_TYPE
,
required:
false
,
description:
'The index of the record the import should started at, default 0 (50 records returned)'
def
resolve
(
project_path
:,
start_at
:)
project
=
authorized_find!
(
full_path:
project_path
)
service_response
=
::
JiraImport
::
UsersImporter
.
new
(
context
[
:current_user
],
project
,
start_at
).
execute
{
jira_users:
service_response
.
payload
,
errors:
service_response
.
errors
}
end
private
def
find_object
(
full_path
:)
resolve_project
(
full_path:
full_path
)
end
def
authorized_resource?
(
project
)
Ability
.
allowed?
(
context
[
:current_user
],
:admin_project
,
project
)
end
end
end
end
app/graphql/types/jira_user_type.rb
0 → 100644
View file @
297aa92b
# frozen_string_literal: true
module
Types
# rubocop: disable Graphql/AuthorizeTypes
# Authorization is at project level for owners or admins on mutation level
class
JiraUserType
<
BaseObject
graphql_name
'JiraUser'
field
:jira_account_id
,
GraphQL
::
STRING_TYPE
,
null:
false
,
description:
'Account id of the Jira user'
field
:jira_display_name
,
GraphQL
::
STRING_TYPE
,
null:
false
,
description:
'Display name of the Jira user'
field
:jira_email
,
GraphQL
::
STRING_TYPE
,
null:
true
,
description:
'Email of the Jira user, returned only for users with public emails'
field
:gitlab_id
,
GraphQL
::
INT_TYPE
,
null:
true
,
description:
'Id of the matched GitLab user'
end
# rubocop: enable Graphql/AuthorizeTypes
end
app/graphql/types/mutation_type.rb
View file @
297aa92b
...
...
@@ -48,6 +48,7 @@ module Types
mount_mutation
Mutations
::
Snippets
::
Create
mount_mutation
Mutations
::
Snippets
::
MarkAsSpam
mount_mutation
Mutations
::
JiraImport
::
Start
mount_mutation
Mutations
::
JiraImport
::
ImportUsers
mount_mutation
Mutations
::
DesignManagement
::
Upload
,
calls_gitaly:
true
mount_mutation
Mutations
::
DesignManagement
::
Delete
,
calls_gitaly:
true
mount_mutation
Mutations
::
ContainerExpirationPolicies
::
Update
...
...
app/services/jira_import/users_importer.rb
View file @
297aa92b
...
...
@@ -22,6 +22,8 @@ module JiraImport
rescue
Timeout
::
Error
,
Errno
::
EINVAL
,
Errno
::
ECONNRESET
,
Errno
::
ECONNREFUSED
,
URI
::
InvalidURIError
,
JIRA
::
HTTPError
,
OpenSSL
::
SSL
::
SSLError
=>
error
Gitlab
::
ErrorTracking
.
track_exception
(
error
,
project_id:
project
.
id
,
request:
url
)
ServiceResponse
.
error
(
message:
"There was an error when communicating to Jira:
#{
error
.
message
}
"
)
rescue
Projects
::
ImportService
::
Error
=>
error
ServiceResponse
.
error
(
message:
error
.
message
)
end
private
...
...
app/services/service_response.rb
View file @
297aa92b
...
...
@@ -26,6 +26,12 @@ class ServiceResponse
status
==
:error
end
def
errors
return
[]
unless
error?
Array
.
wrap
(
message
)
end
private
attr_writer
:status
,
:message
,
:http_status
,
:payload
...
...
changelogs/unreleased/216145-jira-users-import-endpoint.yml
0 → 100644
View file @
297aa92b
---
title
:
Create graphQL endpoint for Jira users import
merge_request
:
33501
author
:
type
:
added
doc/api/graphql/reference/gitlab_schema.graphql
View file @
297aa92b
...
...
@@ -5926,6 +5926,46 @@ type JiraImportStartPayload {
jiraImport
:
JiraImport
}
"""
Autogenerated input type of JiraImportUsers
"""
input
JiraImportUsersInput
{
"""
A
unique
identifier
for
the
client
performing
the
mutation
.
"""
clientMutationId
:
String
"""
The
project
to
import
the
Jira
users
into
"""
projectPath
:
ID
!
"""
The
index
of
the
record
the
import
should
started
at
,
default
0
(50
records
returned
)
"""
startAt
:
Int
}
"""
Autogenerated return type of JiraImportUsers
"""
type
JiraImportUsersPayload
{
"""
A
unique
identifier
for
the
client
performing
the
mutation
.
"""
clientMutationId
:
String
"""
Errors
encountered
during
execution
of
the
mutation
.
"""
errors
:
[
String
!]!
"""
Users
returned
from
Jira
,
matched
by
email
and
name
if
possible
.
"""
jiraUsers
:
[
JiraUser
!]
}
type
JiraProject
{
"""
Key
of
the
Jira
project
...
...
@@ -6020,6 +6060,28 @@ type JiraService implements Service {
type
:
String
}
type
JiraUser
{
"""
Id
of
the
matched
GitLab
user
"""
gitlabId
:
Int
"""
Account
id
of
the
Jira
user
"""
jiraAccountId
:
String
!
"""
Display
name
of
the
Jira
user
"""
jiraDisplayName
:
String
!
"""
Email
of
the
Jira
user
,
returned
only
for
users
with
public
emails
"""
jiraEmail
:
String
}
type
Label
{
"""
Background
color
of
the
label
...
...
@@ -7259,6 +7321,7 @@ type Mutation {
issueSetIteration
(
input
:
IssueSetIterationInput
!):
IssueSetIterationPayload
issueSetWeight
(
input
:
IssueSetWeightInput
!):
IssueSetWeightPayload
jiraImportStart
(
input
:
JiraImportStartInput
!):
JiraImportStartPayload
jiraImportUsers
(
input
:
JiraImportUsersInput
!):
JiraImportUsersPayload
markAsSpamSnippet
(
input
:
MarkAsSpamSnippetInput
!):
MarkAsSpamSnippetPayload
mergeRequestCreate
(
input
:
MergeRequestCreateInput
!):
MergeRequestCreatePayload
mergeRequestSetAssignees
(
input
:
MergeRequestSetAssigneesInput
!):
MergeRequestSetAssigneesPayload
...
...
doc/api/graphql/reference/gitlab_schema.json
View file @
297aa92b
...
...
@@ -16341,6 +16341,126 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "JiraImportUsersInput",
"description": "Autogenerated input type of JiraImportUsers",
"fields": null,
"inputFields": [
{
"name": "projectPath",
"description": "The project to import the Jira users into",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "startAt",
"description": "The index of the record the import should started at, default 0 (50 records returned)",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"defaultValue": null
},
{
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
}
],
"interfaces": null,
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "JiraImportUsersPayload",
"description": "Autogenerated return type of JiraImportUsers",
"fields": [
{
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "errors",
"description": "Errors encountered during execution of the mutation.",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
}
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "jiraUsers",
"description": "Users returned from Jira, matched by email and name if possible.",
"args": [
],
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "JiraUser",
"ofType": null
}
}
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "JiraProject",
...
...
@@ -16624,6 +16744,83 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "JiraUser",
"description": null,
"fields": [
{
"name": "gitlabId",
"description": "Id of the matched GitLab user",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "jiraAccountId",
"description": "Account id of the Jira user",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "jiraDisplayName",
"description": "Display name of the Jira user",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "jiraEmail",
"description": "Email of the Jira user, returned only for users with public emails",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "Label",
...
...
@@ -21014,6 +21211,33 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "jiraImportUsers",
"description": null,
"args": [
{
"name": "input",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "INPUT_OBJECT",
"name": "JiraImportUsersInput",
"ofType": null
}
},
"defaultValue": null
}
],
"type": {
"kind": "OBJECT",
"name": "JiraImportUsersPayload",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "markAsSpamSnippet",
"description": null,
doc/api/graphql/reference/index.md
View file @
297aa92b
...
...
@@ -869,6 +869,16 @@ Autogenerated return type of JiraImportStart
|
`errors`
| String! => Array | Errors encountered during execution of the mutation. |
|
`jiraImport`
| JiraImport | The Jira import data after mutation |
## JiraImportUsersPayload
Autogenerated return type of JiraImportUsers
| Name | Type | Description |
| --- | ---- | ---------- |
|
`clientMutationId`
| String | A unique identifier for the client performing the mutation. |
|
`errors`
| String! => Array | Errors encountered during execution of the mutation. |
|
`jiraUsers`
| JiraUser! => Array | Users returned from Jira, matched by email and name if possible. |
## JiraProject
| Name | Type | Description |
...
...
@@ -885,6 +895,15 @@ Autogenerated return type of JiraImportStart
|
`projects`
| JiraProjectConnection | List of Jira projects fetched through Jira REST API |
|
`type`
| String | Class name of the service |
## JiraUser
| Name | Type | Description |
| --- | ---- | ---------- |
|
`gitlabId`
| Int | Id of the matched GitLab user |
|
`jiraAccountId`
| String! | Account id of the Jira user |
|
`jiraDisplayName`
| String! | Display name of the Jira user |
|
`jiraEmail`
| String | Email of the Jira user, returned only for users with public emails |
## Label
| Name | Type | Description |
...
...
spec/requests/api/graphql/mutations/jira_import/import_users_spec.rb
0 → 100644
View file @
297aa92b
# frozen_string_literal: true
require
'spec_helper'
describe
'Importing Jira Users'
do
include
JiraServiceHelper
include
GraphqlHelpers
let_it_be
(
:user
)
{
create
(
:user
)
}
let_it_be
(
:project
)
{
create
(
:project
)
}
let
(
:project_path
)
{
project
.
full_path
}
let
(
:start_at
)
{
7
}
let
(
:mutation
)
do
variables
=
{
start_at:
start_at
,
project_path:
project_path
}
graphql_mutation
(
:jira_import_users
,
variables
)
end
def
mutation_response
graphql_mutation_response
(
:jira_import_users
)
end
def
jira_import
mutation_response
[
'jiraUsers'
]
end
context
'with anonymous user'
do
let
(
:current_user
)
{
nil
}
it_behaves_like
'a mutation that returns top-level errors'
,
errors:
[
Gitlab
::
Graphql
::
Authorize
::
AuthorizeResource
::
RESOURCE_ACCESS_ERROR
]
end
context
'with user without permissions'
do
let
(
:current_user
)
{
user
}
before
do
project
.
add_developer
(
current_user
)
end
it_behaves_like
'a mutation that returns top-level errors'
,
errors:
[
Gitlab
::
Graphql
::
Authorize
::
AuthorizeResource
::
RESOURCE_ACCESS_ERROR
]
end
context
'when the user has permissions'
do
let
(
:current_user
)
{
user
}
before
do
project
.
add_maintainer
(
current_user
)
end
context
'when the project path is invalid'
do
let
(
:project_path
)
{
'foobar'
}
it
'returns an an error'
do
post_graphql_mutation
(
mutation
,
current_user:
current_user
)
errors
=
json_response
[
'errors'
]
expect
(
errors
.
first
[
'message'
]).
to
eq
(
Gitlab
::
Graphql
::
Authorize
::
AuthorizeResource
::
RESOURCE_ACCESS_ERROR
)
end
end
context
'when all params and permissions are ok'
do
let
(
:importer
)
{
instance_double
(
JiraImport
::
UsersImporter
)
}
before
do
expect
(
JiraImport
::
UsersImporter
).
to
receive
(
:new
).
with
(
current_user
,
project
,
7
)
.
and_return
(
importer
)
end
context
'when service returns a successful response'
do
it
'returns imported users'
do
users
=
[{
jira_account_id:
'12a'
,
jira_display_name:
'user 1'
}]
result
=
ServiceResponse
.
success
(
payload:
users
)
expect
(
importer
).
to
receive
(
:execute
).
and_return
(
result
)
post_graphql_mutation
(
mutation
,
current_user:
current_user
)
expect
(
jira_import
.
length
).
to
eq
(
1
)
expect
(
jira_import
.
first
[
'jiraAccountId'
]).
to
eq
(
'12a'
)
expect
(
jira_import
.
first
[
'jiraDisplayName'
]).
to
eq
(
'user 1'
)
end
end
context
'when service returns an error response'
do
it
'returns an error messaege'
do
result
=
ServiceResponse
.
error
(
message:
'Some error'
)
expect
(
importer
).
to
receive
(
:execute
).
and_return
(
result
)
post_graphql_mutation
(
mutation
,
current_user:
current_user
)
expect
(
mutation_response
[
'errors'
]).
to
eq
([
'Some error'
])
end
end
end
end
end
spec/services/jira_import/users_importer_spec.rb
View file @
297aa92b
...
...
@@ -20,8 +20,8 @@ describe JiraImport::UsersImporter do
end
context
'when Jira import is not configured properly'
do
it
'r
aise
s an error'
do
expect
{
subject
}.
to
raise_error
(
Projects
::
ImportService
::
Error
)
it
'r
eturn
s an error'
do
expect
(
subject
.
errors
).
to
eq
([
'Jira integration not configured.'
]
)
end
end
...
...
spec/services/service_response_spec.rb
View file @
297aa92b
...
...
@@ -84,4 +84,14 @@ describe ServiceResponse do
expect
(
described_class
.
error
(
message:
'Bad apple'
).
error?
).
to
eq
(
true
)
end
end
describe
'#errors'
do
it
'returns an empty array for a successful response'
do
expect
(
described_class
.
success
.
errors
).
to
be_empty
end
it
'returns an array with a correct message for an error response'
do
expect
(
described_class
.
error
(
message:
'error message'
).
errors
).
to
eq
([
'error message'
])
end
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