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
6e440f27
Commit
6e440f27
authored
Dec 17, 2021
by
Samantha Ming
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Connect secuity configuration to a local mutation
Issue:
https://gitlab.com/gitlab-org/gitlab/-/issues/347414
parent
9d90d5a3
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
154 additions
and
33 deletions
+154
-33
app/assets/javascripts/security_configuration/components/training_provider_list.vue
...urity_configuration/components/training_provider_list.vue
+41
-1
app/assets/javascripts/security_configuration/graphql/configure_security_training_providers.mutation.graphql
...ql/configure_security_training_providers.mutation.graphql
+8
-0
app/assets/javascripts/security_configuration/index.js
app/assets/javascripts/security_configuration/index.js
+1
-29
app/assets/javascripts/security_configuration/resolver.js
app/assets/javascripts/security_configuration/resolver.js
+56
-0
spec/frontend/security_configuration/components/training_provider_list_spec.js
...y_configuration/components/training_provider_list_spec.js
+42
-1
spec/frontend/security_configuration/mock_data.js
spec/frontend/security_configuration/mock_data.js
+6
-2
No files found.
app/assets/javascripts/security_configuration/components/training_provider_list.vue
View file @
6e440f27
<
script
>
import
{
GlCard
,
GlToggle
,
GlLink
,
GlSkeletonLoader
}
from
'
@gitlab/ui
'
;
import
securityTrainingProvidersQuery
from
'
../graphql/security_training_providers.query.graphql
'
;
import
configureSecurityTrainingProvidersMutation
from
'
../graphql/configure_security_training_providers.mutation.graphql
'
;
export
default
{
components
:
{
...
...
@@ -9,6 +10,7 @@ export default {
GlLink
,
GlSkeletonLoader
,
},
inject
:
[
'
projectPath
'
],
apollo
:
{
securityTrainingProviders
:
{
query
:
securityTrainingProvidersQuery
,
...
...
@@ -16,6 +18,7 @@ export default {
},
data
()
{
return
{
toggleLoading
:
false
,
securityTrainingProviders
:
[],
};
},
...
...
@@ -24,6 +27,37 @@ export default {
return
this
.
$apollo
.
queries
.
securityTrainingProviders
.
loading
;
},
},
methods
:
{
toggleProvider
(
selectedProviderId
)
{
const
toggledProviders
=
this
.
securityTrainingProviders
.
map
((
provider
)
=>
({
...
provider
,
...(
provider
.
id
===
selectedProviderId
&&
{
isEnabled
:
!
provider
.
isEnabled
}),
}));
this
.
storeEnabledProviders
(
toggledProviders
);
},
storeEnabledProviders
(
toggledProviders
)
{
const
enabledProviderIds
=
toggledProviders
.
filter
(({
isEnabled
})
=>
isEnabled
)
.
map
(({
id
})
=>
id
);
this
.
toggleLoading
=
true
;
return
this
.
$apollo
.
mutate
({
mutation
:
configureSecurityTrainingProvidersMutation
,
variables
:
{
input
:
{
enabledProviders
:
enabledProviderIds
,
fullPath
:
this
.
projectPath
,
},
},
})
.
then
(()
=>
{
this
.
toggleLoading
=
false
;
});
},
},
};
</
script
>
...
...
@@ -46,7 +80,13 @@ export default {
>
<gl-card>
<div
class=
"gl-display-flex"
>
<gl-toggle
:value=
"isEnabled"
:label=
"__('Training mode')"
label-position=
"hidden"
/>
<gl-toggle
:value=
"isEnabled"
:label=
"__('Training mode')"
label-position=
"hidden"
:is-loading=
"toggleLoading"
@
change=
"toggleProvider(id)"
/>
<div
class=
"gl-ml-5"
>
<h3
class=
"gl-font-lg gl-m-0 gl-mb-2"
>
{{
name
}}
</h3>
<p>
...
...
app/assets/javascripts/security_configuration/graphql/configure_security_training_providers.mutation.graphql
0 → 100644
View file @
6e440f27
mutation
configureSecurityTrainingProviders
(
$input
:
configureSecurityTrainingProvidersInput
!)
{
configureSecurityTrainingProviders
(
input
:
$input
)
@client
{
securityTrainingProviders
{
id
isEnabled
}
}
}
app/assets/javascripts/security_configuration/index.js
View file @
6e440f27
...
...
@@ -2,38 +2,10 @@ import Vue from 'vue';
import
VueApollo
from
'
vue-apollo
'
;
import
createDefaultClient
from
'
~/lib/graphql
'
;
import
{
parseBooleanDataAttributes
}
from
'
~/lib/utils/dom_utils
'
;
import
{
__
}
from
'
~/locale
'
;
import
SecurityConfigurationApp
from
'
./components/app.vue
'
;
import
{
securityFeatures
,
complianceFeatures
}
from
'
./components/constants
'
;
import
{
augmentFeatures
}
from
'
./utils
'
;
// Note: this is behind a feature flag and only a placeholder
// until the actual GraphQL fields have been added
// https://gitlab.com/gitlab-org/gi tlab/-/issues/346480
export
const
tempResolvers
=
{
Query
:
{
securityTrainingProviders
()
{
return
[
{
__typename
:
'
SecurityTrainingProvider
'
,
id
:
101
,
name
:
__
(
'
Kontra
'
),
description
:
__
(
'
Interactive developer security education.
'
),
url
:
'
https://application.security/
'
,
isEnabled
:
false
,
},
{
__typename
:
'
SecurityTrainingProvider
'
,
id
:
102
,
name
:
__
(
'
SecureCodeWarrior
'
),
description
:
__
(
'
Security training with guide and learning pathways.
'
),
url
:
'
https://www.securecodewarrior.com/
'
,
isEnabled
:
true
,
},
];
},
},
};
import
tempResolvers
from
'
./resolver
'
;
export
const
initSecurityConfiguration
=
(
el
)
=>
{
if
(
!
el
)
{
...
...
app/assets/javascripts/security_configuration/resolver.js
0 → 100644
View file @
6e440f27
import
produce
from
'
immer
'
;
import
{
__
}
from
'
~/locale
'
;
import
securityTrainingProvidersQuery
from
'
./graphql/security_training_providers.query.graphql
'
;
// Note: this is behind a feature flag and only a placeholder
// until the actual GraphQL fields have been added
// https://gitlab.com/gitlab-org/gi tlab/-/issues/346480
export
default
{
Query
:
{
securityTrainingProviders
()
{
return
[
{
__typename
:
'
SecurityTrainingProvider
'
,
id
:
101
,
name
:
__
(
'
Kontra
'
),
description
:
__
(
'
Interactive developer security education.
'
),
url
:
'
https://application.security/
'
,
isEnabled
:
false
,
},
{
__typename
:
'
SecurityTrainingProvider
'
,
id
:
102
,
name
:
__
(
'
SecureCodeWarrior
'
),
description
:
__
(
'
Security training with guide and learning pathways.
'
),
url
:
'
https://www.securecodewarrior.com/
'
,
isEnabled
:
true
,
},
];
},
},
Mutation
:
{
configureSecurityTrainingProviders
:
(
_
,
{
input
:
{
enabledProviders
,
primaryProvider
}
},
{
cache
},
)
=>
{
const
sourceData
=
cache
.
readQuery
({
query
:
securityTrainingProvidersQuery
,
});
const
data
=
produce
(
sourceData
.
securityTrainingProviders
,
(
draftData
)
=>
{
/* eslint-disable no-param-reassign */
draftData
.
forEach
((
provider
)
=>
{
provider
.
isPrimary
=
provider
.
id
===
primaryProvider
;
provider
.
isEnabled
=
provider
.
id
===
primaryProvider
||
enabledProviders
.
includes
(
provider
.
id
);
});
});
return
{
__typename
:
'
configureSecurityTrainingProvidersPayload
'
,
securityTrainingProviders
:
data
,
};
},
},
};
spec/frontend/security_configuration/components/training_provider_list_spec.js
View file @
6e440f27
...
...
@@ -4,8 +4,14 @@ import Vue from 'vue';
import
VueApollo
from
'
vue-apollo
'
;
import
createMockApollo
from
'
helpers/mock_apollo_helper
'
;
import
TrainingProviderList
from
'
~/security_configuration/components/training_provider_list.vue
'
;
import
configureSecurityTrainingProvidersMutation
from
'
~/security_configuration/graphql/configure_security_training_providers.mutation.graphql
'
;
import
waitForPromises
from
'
helpers/wait_for_promises
'
;
import
{
securityTrainingProviders
,
mockResolvers
}
from
'
../mock_data
'
;
import
{
securityTrainingProviders
,
mockResolvers
,
testProjectPath
,
textProviderIds
,
}
from
'
../mock_data
'
;
Vue
.
use
(
VueApollo
);
...
...
@@ -18,6 +24,9 @@ describe('TrainingProviderList component', () => {
mockApollo
=
createMockApollo
([],
mockResolvers
);
wrapper
=
shallowMount
(
TrainingProviderList
,
{
provide
:
{
projectPath
:
testProjectPath
,
},
apolloProvider
:
mockApollo
,
});
};
...
...
@@ -85,4 +94,36 @@ describe('TrainingProviderList component', () => {
});
});
});
describe
(
'
success mutation
'
,
()
=>
{
const
firstToggle
=
()
=>
findToggles
().
at
(
0
);
beforeEach
(
async
()
=>
{
jest
.
spyOn
(
mockApollo
.
defaultClient
,
'
mutate
'
);
await
waitForQueryToBeLoaded
();
firstToggle
().
vm
.
$emit
(
'
change
'
);
});
it
(
'
calls mutation when toggle is changed
'
,
()
=>
{
expect
(
mockApollo
.
defaultClient
.
mutate
).
toHaveBeenCalledWith
(
expect
.
objectContaining
({
mutation
:
configureSecurityTrainingProvidersMutation
,
variables
:
{
input
:
{
enabledProviders
:
textProviderIds
,
fullPath
:
testProjectPath
}
},
}),
);
});
it
.
each
`
loading | wait | desc
${
true
}
|
${
false
}
|
${
'
enables loading of GlToggle when mutation is called
'
}
${
false
}
|
${
true
}
|
${
'
disables loading of GlToggle when mutation is complete
'
}
`
(
'
$desc
'
,
async
({
loading
,
wait
})
=>
{
if
(
wait
)
{
await
waitForPromises
();
}
expect
(
firstToggle
().
props
(
'
isLoading
'
)).
toBe
(
loading
);
});
});
});
spec/frontend/security_configuration/mock_data.js
View file @
6e440f27
export
const
testProjectPath
=
'
foo/bar
'
;
export
const
textProviderIds
=
[
101
,
102
];
export
const
securityTrainingProviders
=
[
{
id
:
101
,
id
:
textProviderIds
[
0
]
,
name
:
'
Kontra
'
,
description
:
'
Interactive developer security education.
'
,
url
:
'
https://application.security/
'
,
isEnabled
:
false
,
},
{
id
:
102
,
id
:
textProviderIds
[
1
]
,
name
:
'
SecureCodeWarrior
'
,
description
:
'
Security training with guide and learning pathways.
'
,
url
:
'
https://www.securecodewarrior.com/
'
,
...
...
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