Commit 3e24318c authored by Sean Arnold's avatar Sean Arnold

Minor tweaks including check for dup usernames

Update docs
parent 1a5fa2b7
......@@ -10970,27 +10970,27 @@ Describes an incident management on-call rotation
"""
type IncidentManagementOncallRotation {
"""
ID of the on-call rotation
ID of the on-call rotation.
"""
id: IncidentManagementOncallRotationID!
"""
Time zone of the on-call schedule
Length of the on-call schedule, in the units specified by lengthUnit.
"""
length: Int
"""
Unit of the on-call rotation length
Unit of the on-call rotation length.
"""
lengthUnit: OncallRotationUnitEnum
"""
Name of the on-call rotation
Name of the on-call rotation.
"""
name: String!
"""
Participants of the on-call rotation
Participants of the on-call rotation.
"""
participants(
"""
......@@ -11015,7 +11015,7 @@ type IncidentManagementOncallRotation {
): OncallParticipantTypeConnection
"""
Start date of the on-call rotation
Start date of the on-call rotation.
"""
startsAt: Time
}
......@@ -15715,7 +15715,7 @@ input OncallRotationCreateInput {
scheduleIid: String!
"""
The start date and time of the on-call rotation
The start date and time of the on-call rotation, in the timezone of the on-call schedule
"""
startsAt: OncallRotationDateInputType!
}
......@@ -15775,17 +15775,17 @@ Rotation length unit of an on-call rotation
"""
enum OncallRotationUnitEnum {
"""
One Days
Days
"""
DAYS
"""
One Hours
Hours
"""
HOURS
"""
One Weeks
Weeks
"""
WEEKS
}
......@@ -15940,12 +15940,13 @@ The rotation user and color palette
"""
input OncallUserInputType {
"""
The color palette to assign to the on-call user, for example: "blue".
A value of DataVisualizationColorEnum. The color from the palette to assign to the on-call user.
"""
colorPalette: DataVisualizationColorEnum
"""
The color weight to assign to for the on-call user, for example "500". Max 4 chars. For easy identification of the user.
A value of DataVisualizationWeightEnum. The color weight to assign to for the
on-call user, for example "500". Max 4 chars.
"""
colorWeight: DataVisualizationWeightEnum
......
......@@ -30050,7 +30050,7 @@
"fields": [
{
"name": "id",
"description": "ID of the on-call rotation",
"description": "ID of the on-call rotation.",
"args": [
],
......@@ -30068,7 +30068,7 @@
},
{
"name": "length",
"description": "Time zone of the on-call schedule",
"description": "Length of the on-call schedule, in the units specified by lengthUnit.",
"args": [
],
......@@ -30082,7 +30082,7 @@
},
{
"name": "lengthUnit",
"description": "Unit of the on-call rotation length",
"description": "Unit of the on-call rotation length.",
"args": [
],
......@@ -30096,7 +30096,7 @@
},
{
"name": "name",
"description": "Name of the on-call rotation",
"description": "Name of the on-call rotation.",
"args": [
],
......@@ -30114,7 +30114,7 @@
},
{
"name": "participants",
"description": "Participants of the on-call rotation",
"description": "Participants of the on-call rotation.",
"args": [
{
"name": "after",
......@@ -30167,7 +30167,7 @@
},
{
"name": "startsAt",
"description": "Start date of the on-call rotation",
"description": "Start date of the on-call rotation.",
"args": [
],
......@@ -46650,7 +46650,7 @@
},
{
"name": "startsAt",
"description": "The start date and time of the on-call rotation",
"description": "The start date and time of the on-call rotation, in the timezone of the on-call schedule",
"type": {
"kind": "NON_NULL",
"name": null,
......@@ -46868,19 +46868,19 @@
"enumValues": [
{
"name": "HOURS",
"description": "One Hours",
"description": "Hours",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "DAYS",
"description": "One Days",
"description": "Days",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "WEEKS",
"description": "One Weeks",
"description": "Weeks",
"isDeprecated": false,
"deprecationReason": null
}
......@@ -47311,7 +47311,7 @@
},
{
"name": "colorPalette",
"description": "The color palette to assign to the on-call user, for example: \"blue\".",
"description": "A value of DataVisualizationColorEnum. The color from the palette to assign to the on-call user.",
"type": {
"kind": "ENUM",
"name": "DataVisualizationColorEnum",
......@@ -47321,7 +47321,7 @@
},
{
"name": "colorWeight",
"description": "The color weight to assign to for the on-call user, for example \"500\". Max 4 chars. For easy identification of the user.",
"description": "A value of DataVisualizationWeightEnum. The color weight to assign to for the on-call user, for example \"500\". Max 4 chars.",
"type": {
"kind": "ENUM",
"name": "DataVisualizationWeightEnum",
......@@ -1718,12 +1718,12 @@ Describes an incident management on-call rotation.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `id` | IncidentManagementOncallRotationID! | ID of the on-call rotation |
| `length` | Int | Time zone of the on-call schedule |
| `lengthUnit` | OncallRotationUnitEnum | Unit of the on-call rotation length |
| `name` | String! | Name of the on-call rotation |
| `participants` | OncallParticipantTypeConnection | Participants of the on-call rotation |
| `startsAt` | Time | Start date of the on-call rotation |
| `id` | IncidentManagementOncallRotationID! | ID of the on-call rotation. |
| `length` | Int | Length of the on-call schedule, in the units specified by lengthUnit. |
| `lengthUnit` | OncallRotationUnitEnum | Unit of the on-call rotation length. |
| `name` | String! | Name of the on-call rotation. |
| `participants` | OncallParticipantTypeConnection | Participants of the on-call rotation. |
| `startsAt` | Time | Start date of the on-call rotation. |
### IncidentManagementOncallSchedule
......@@ -4645,9 +4645,9 @@ Rotation length unit of an on-call rotation.
| Value | Description |
| ----- | ----------- |
| `DAYS` | One Days |
| `HOURS` | One Hours |
| `WEEKS` | One Weeks |
| `DAYS` | Days |
| `HOURS` | Hours |
| `WEEKS` | Weeks |
### PackageTypeEnum
......
......@@ -13,10 +13,10 @@ module Mutations
private
def response(result, errors = nil)
def response(result)
{
oncall_rotation: result.payload[:oncall_rotation],
errors: errors.presence || result.errors
errors: result.errors
}
end
end
......
......@@ -23,7 +23,7 @@ module Mutations
argument :starts_at, Types::IncidentManagement::OncallRotationDateInputType,
required: true,
description: 'The start date and time of the on-call rotation'
description: 'The start date and time of the on-call rotation, in the timezone of the on-call schedule'
argument :rotation_length, Types::IncidentManagement::OncallRotationLengthInputType,
required: true,
......@@ -37,7 +37,7 @@ module Mutations
MAXIMUM_PARTICIPANTS = 100
def resolve(iid:, project_path:, participants:, **args)
project = authorized_find!(full_path: project_path)
project = Project.find_by_full_path(project_path)
schedule = ::IncidentManagement::OncallSchedulesFinder.new(current_user, project, iid: iid)
.execute
......@@ -45,21 +45,24 @@ module Mutations
raise_schedule_not_found unless schedule
result = ::IncidentManagement::OncallRotations::CreateService.new(
schedule,
project,
current_user,
prepare_params(schedule, participants, args)
).execute
begin
result = ::IncidentManagement::OncallRotations::CreateService.new(
schedule,
project,
current_user,
create_service_params(schedule, participants, args)
).execute
errors = result.error? ? [result.message] : []
rescue ActiveRecord::RecordInvalid => e
raise Gitlab::Graphql::Errors::ArgumentError, e.message
end
response(result, errors)
response(result)
end
private
def prepare_params(schedule, participants, args)
def create_service_params(schedule, participants, args)
rotation_length = args[:rotation_length][:length]
rotation_length_unit = args[:rotation_length][:unit]
starts_at = parse_start_time(schedule, args)
......@@ -76,16 +79,13 @@ module Mutations
args[:starts_at].asctime.in_time_zone(schedule.timezone)
end
def find_object(full_path:)
resolve_project(full_path: full_path)
end
def find_participants(user_array)
raise_too_many_users_error if user_array.size > MAXIMUM_PARTICIPANTS
usernames = user_array.map {|h| h[:username] }
matched_users = UsersFinder.new(current_user, username: usernames).execute.order_by(:username)
raise_duplicate_users_error if usernames.size != usernames.uniq.size
matched_users = UsersFinder.new(current_user, username: usernames).execute.order_by(:username)
raise_user_not_found if matched_users.size != user_array.size
user_array = user_array.sort_by! { |h| h[:username] }
......@@ -101,6 +101,10 @@ module Mutations
raise Gitlab::Graphql::Errors::ArgumentError, "A maximum of #{MAXIMUM_PARTICIPANTS} participants can be added"
end
def raise_duplicate_users_error
raise Gitlab::Graphql::Errors::ArgumentError, "A duplicate username is included in the participant list"
end
def raise_user_not_found
raise Gitlab::Graphql::Errors::ArgumentError, 'A username that was provided could not be matched to a user'
end
......
......@@ -7,7 +7,7 @@ module Types
description 'Rotation length unit of an on-call rotation'
::IncidentManagement::OncallRotation.length_units.keys.each do |unit|
value unit.upcase, value: unit, description: "One #{unit.titleize}"
value unit.upcase, value: unit, description: "#{unit.titleize}"
end
end
end
......
......@@ -11,32 +11,32 @@ module Types
field :id,
Types::GlobalIDType[::IncidentManagement::OncallRotation],
null: false,
description: 'ID of the on-call rotation'
description: 'ID of the on-call rotation.'
field :name,
GraphQL::STRING_TYPE,
null: false,
description: 'Name of the on-call rotation'
description: 'Name of the on-call rotation.'
field :starts_at,
Types::TimeType,
null: true,
description: 'Start date of the on-call rotation'
description: 'Start date of the on-call rotation.'
field :length,
GraphQL::INT_TYPE,
null: true,
description: 'Time zone of the on-call schedule'
description: 'Length of the on-call schedule, in the units specified by lengthUnit.'
field :length_unit,
Types::IncidentManagement::OncallRotationLengthUnitEnum,
null: true,
description: 'Unit of the on-call rotation length'
description: 'Unit of the on-call rotation length.'
field :participants,
::Types::IncidentManagement::OncallParticipantType.connection_type,
null: true,
description: 'Participants of the on-call rotation'
description: 'Participants of the on-call rotation.'
end
end
end
......@@ -13,11 +13,11 @@ module Types
argument :color_palette, ::Types::DataVisualizationPalette::ColorEnum,
required: false,
description: 'The color palette to assign to the on-call user, for example: "blue".'
description: 'A value of DataVisualizationColorEnum. The color from the palette to assign to the on-call user.'
argument :color_weight, ::Types::DataVisualizationPalette::WeightEnum,
required: false,
description: 'The color weight to assign to for the on-call user, for example "500". Max 4 chars. For easy identification of the user.'
description: 'A value of DataVisualizationWeightEnum. The color weight to assign to for the on-call user, for example "500". Max 4 chars.'
end
# rubocop: enable Graphql/AuthorizeTypes
end
......
......@@ -26,8 +26,6 @@ RSpec.describe Mutations::IncidentManagement::OncallRotation::Create do
}
end
specify { expect(described_class).to require_graphql_authorizations(:admin_incident_management_oncall_schedule) }
describe '#resolve' do
subject(:resolve) { mutation_for(project, current_user).resolve(iid: schedule.iid, project_path: project.full_path, participants: args[:participants], **args) }
......@@ -87,7 +85,17 @@ RSpec.describe Mutations::IncidentManagement::OncallRotation::Create do
end
it 'raises an error' do
expect { resolve }.to raise_error(ActiveRecord::RecordInvalid, /User does not have access to the project/)
expect { resolve }.to raise_error(Gitlab::Graphql::Errors::ArgumentError, /User does not have access to the project/)
end
end
context 'duplicate participants' do
before do
args[:participants] << args[:participants].first
end
it 'raises an error' do
expect { resolve }.to raise_error(Gitlab::Graphql::Errors::ArgumentError, 'A duplicate username is included in the participant list')
end
end
......@@ -113,7 +121,7 @@ RSpec.describe Mutations::IncidentManagement::OncallRotation::Create do
context 'when resource is not accessible to the user' do
it 'raises an error' do
expect { resolve }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
expect { resolve }.to raise_error(Gitlab::Graphql::Errors::ArgumentError, 'The schedule could not be found')
end
end
end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment