Commit affacae0 authored by Rajendra Kadam's avatar Rajendra Kadam Committed by Douglas Barbosa Alexandre

Fix errored force push by changing all files to previous state

Change and update code to match missed files
parent a7ccc61e
# frozen_string_literal: true
module Mutations
module CustomEmoji
class Create < BaseMutation
include Mutations::ResolvesGroup
graphql_name 'CreateCustomEmoji'
authorize :create_custom_emoji
field :custom_emoji,
Types::CustomEmojiType,
null: true,
description: 'The new custom emoji'
argument :group_path, GraphQL::ID_TYPE,
required: true,
description: 'Namespace full path the emoji is associated with'
argument :name, GraphQL::STRING_TYPE,
required: true,
description: 'Name of the emoji'
argument :url, GraphQL::STRING_TYPE,
required: true,
as: :file,
description: 'Location of the emoji file'
def resolve(group_path:, **args)
group = authorized_find!(group_path: group_path)
# See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37911#note_444682238
args[:external] = true
custom_emoji = group.custom_emoji.create(args)
{
custom_emoji: custom_emoji.valid? ? custom_emoji : nil,
errors: errors_on_object(custom_emoji)
}
end
private
def find_object(group_path:)
resolve_group(full_path: group_path)
end
end
end
end
# frozen_string_literal: true
module Types
class CustomEmojiType < BaseObject
graphql_name 'CustomEmoji'
description 'A custom emoji uploaded by user'
authorize :read_custom_emoji
field :id, ::Types::GlobalIDType[::CustomEmoji],
null: false,
description: 'The ID of the emoji'
field :name, GraphQL::STRING_TYPE,
null: false,
description: 'The name of the emoji'
field :url, GraphQL::STRING_TYPE,
null: false,
method: :file,
description: 'The link to file of the emoji'
field :external, GraphQL::BOOLEAN_TYPE,
null: false,
description: 'Whether the emoji is an external link'
end
end
......@@ -17,6 +17,10 @@ module Types
group.avatar_url(only_path: false)
end
field :custom_emoji, Types::CustomEmojiType.connection_type, null: true,
description: 'Custom emoji within this namespace',
feature_flag: :custom_emoji
field :share_with_group_lock, GraphQL::BOOLEAN_TYPE, null: true,
description: 'Indicates if sharing a project with another group within this group is prevented'
......
......@@ -29,6 +29,7 @@ module Types
mount_mutation Mutations::Boards::Lists::Destroy
mount_mutation Mutations::Branches::Create, calls_gitaly: true
mount_mutation Mutations::Commits::Create, calls_gitaly: true
mount_mutation Mutations::CustomEmoji::Create, feature_flag: :custom_emoji
mount_mutation Mutations::Discussions::ToggleResolve
mount_mutation Mutations::Issues::Create
mount_mutation Mutations::Issues::SetAssignees
......
# frozen_string_literal: true
module Types
module PermissionTypes
class CustomEmoji < BasePermissionType
graphql_name 'CustomEmojiPermissions'
abilities :create_custom_emoji, :read_custom_emoji
end
end
end
......@@ -3,14 +3,21 @@
class CustomEmoji < ApplicationRecord
belongs_to :namespace, inverse_of: :custom_emoji
belongs_to :group, -> { where(type: 'Group') }, foreign_key: 'namespace_id'
# For now only external emoji are supported. See https://gitlab.com/gitlab-org/gitlab/-/issues/230467
validates :external, inclusion: { in: [true] }
validates :file, public_url: true, if: :external
validate :valid_emoji_name
validates :namespace, presence: true
validates :group, presence: true
validates :name,
uniqueness: { scope: [:namespace_id, :name] },
presence: true,
length: { maximum: 36 },
format: { with: /\A\w+\z/ }
format: { with: /\A([a-z0-9]+[-_]?)+[a-z0-9]+\z/ }
private
......
# frozen_string_literal: true
class CustomEmojiPolicy < BasePolicy
delegate { @subject.group }
end
......@@ -101,6 +101,7 @@ class GroupPolicy < BasePolicy
enable :read_label
enable :read_board
enable :read_group_member
enable :read_custom_emoji
end
rule { ~can?(:read_group) }.policy do
......@@ -114,6 +115,7 @@ class GroupPolicy < BasePolicy
enable :create_metrics_dashboard_annotation
enable :delete_metrics_dashboard_annotation
enable :update_metrics_dashboard_annotation
enable :create_custom_emoji
end
rule { reporter }.policy do
......
---
name: custom_emoji
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37911
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/231317
milestone: '13.6'
type: development
group: group::project management
default_enabled: false
......@@ -3834,6 +3834,51 @@ type CreateClusterAgentPayload {
errors: [String!]!
}
"""
Autogenerated input type of CreateCustomEmoji
"""
input CreateCustomEmojiInput {
"""
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
"""
Namespace full path the emoji is associated with
"""
groupPath: ID!
"""
Name of the emoji
"""
name: String!
"""
Location of the emoji file
"""
url: String!
}
"""
Autogenerated return type of CreateCustomEmoji
"""
type CreateCustomEmojiPayload {
"""
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
"""
The new custom emoji
"""
customEmoji: CustomEmoji
"""
Errors encountered during execution of the mutation.
"""
errors: [String!]!
}
"""
Autogenerated input type of CreateDiffNote
"""
......@@ -4431,6 +4476,71 @@ interface CurrentUserTodos {
): TodoConnection!
}
"""
A custom emoji uploaded by user
"""
type CustomEmoji {
"""
Whether the emoji is an external link
"""
external: Boolean!
"""
The ID of the emoji
"""
id: CustomEmojiID!
"""
The name of the emoji
"""
name: String!
"""
The link to file of the emoji
"""
url: String!
}
"""
The connection type for CustomEmoji.
"""
type CustomEmojiConnection {
"""
A list of edges.
"""
edges: [CustomEmojiEdge]
"""
A list of nodes.
"""
nodes: [CustomEmoji]
"""
Information to aid in pagination.
"""
pageInfo: PageInfo!
}
"""
An edge in a connection.
"""
type CustomEmojiEdge {
"""
A cursor for use in pagination.
"""
cursor: String!
"""
The item at the end of the edge.
"""
node: CustomEmoji
}
"""
Identifier of CustomEmoji
"""
scalar CustomEmojiID
"""
Autogenerated input type of DastOnDemandScanCreate
"""
......@@ -8516,6 +8626,31 @@ type Group {
"""
containsLockedProjects: Boolean!
"""
Custom emoji within this namespace. Available only when feature flag `custom_emoji` is enabled
"""
customEmoji(
"""
Returns the elements in the list that come after the specified cursor.
"""
after: String
"""
Returns the elements in the list that come before the specified cursor.
"""
before: String
"""
Returns the first _n_ elements from the list.
"""
first: Int
"""
Returns the last _n_ elements from the list.
"""
last: Int
): CustomEmojiConnection
"""
Description of the namespace
"""
......@@ -13501,6 +13636,11 @@ type Mutation {
createBoard(input: CreateBoardInput!): CreateBoardPayload
createBranch(input: CreateBranchInput!): CreateBranchPayload
createClusterAgent(input: CreateClusterAgentInput!): CreateClusterAgentPayload
"""
. Available only when feature flag `custom_emoji` is enabled
"""
createCustomEmoji(input: CreateCustomEmojiInput!): CreateCustomEmojiPayload
createDiffNote(input: CreateDiffNoteInput!): CreateDiffNotePayload
createEpic(input: CreateEpicInput!): CreateEpicPayload
createImageDiffNote(input: CreateImageDiffNoteInput!): CreateImageDiffNotePayload
......
......@@ -630,6 +630,16 @@ Autogenerated return type of CreateClusterAgent.
| `clusterAgent` | ClusterAgent | Cluster agent created after mutation |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
### CreateCustomEmojiPayload
Autogenerated return type of CreateCustomEmoji.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `customEmoji` | CustomEmoji | The new custom emoji |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
### CreateDiffNotePayload
Autogenerated return type of CreateDiffNote.
......@@ -721,6 +731,17 @@ Autogenerated return type of CreateTestCase.
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `testCase` | Issue | The test case created |
### CustomEmoji
A custom emoji uploaded by user.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `external` | Boolean! | Whether the emoji is an external link |
| `id` | CustomEmojiID! | The ID of the emoji |
| `name` | String! | The name of the emoji |
| `url` | String! | The link to file of the emoji |
### DastOnDemandScanCreatePayload
Autogenerated return type of DastOnDemandScanCreate.
......@@ -1392,6 +1413,7 @@ Autogenerated return type of EpicTreeReorder.
| `codeCoverageActivities` | CodeCoverageActivityConnection | Represents the code coverage activity for this group. Available only when feature flag `group_coverage_data_report_graph` is enabled |
| `containerRepositories` | ContainerRepositoryConnection | Container repositories of the project |
| `containsLockedProjects` | Boolean! | Includes at least one project where the repository size exceeds the limit |
| `customEmoji` | CustomEmojiConnection | Custom emoji within this namespace. Available only when feature flag `custom_emoji` is enabled |
| `description` | String | Description of the namespace |
| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` |
| `emailsDisabled` | Boolean | Indicates if a group has email notifications disabled |
......
......@@ -4,6 +4,7 @@ FactoryBot.define do
factory :custom_emoji, class: 'CustomEmoji' do
sequence(:name) { |n| "custom_emoji#{n}" }
namespace
file { fixture_file_upload(Rails.root.join('spec/fixtures/dk.png')) }
group
file { 'https://gitlab.com/images/partyparrot.png' }
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GitlabSchema.types['CustomEmoji'] do
specify { expect(described_class.graphql_name).to eq('CustomEmoji') }
specify { expect(described_class).to require_graphql_authorizations(:read_custom_emoji) }
specify { expect(described_class).to have_graphql_fields(:id, :name, :url, :external) }
end
......@@ -13,20 +13,28 @@ RSpec.describe CustomEmoji do
describe 'exclusion of duplicated emoji' do
let(:emoji_name) { Gitlab::Emoji.emojis_names.sample }
let(:group) { create(:group, :private) }
it 'disallows emoji names of built-in emoji' do
new_emoji = build(:custom_emoji, name: emoji_name)
new_emoji = build(:custom_emoji, name: emoji_name, group: group)
expect(new_emoji).not_to be_valid
expect(new_emoji.errors.messages).to eq(name: ["#{emoji_name} is already being used for another emoji"])
end
it 'disallows duplicate custom emoji names within namespace' do
old_emoji = create(:custom_emoji)
new_emoji = build(:custom_emoji, name: old_emoji.name, namespace: old_emoji.namespace)
old_emoji = create(:custom_emoji, group: group)
new_emoji = build(:custom_emoji, name: old_emoji.name, namespace: old_emoji.namespace, group: group)
expect(new_emoji).not_to be_valid
expect(new_emoji.errors.messages).to eq(name: ["has already been taken"])
end
it 'disallows non http and https file value' do
emoji = build(:custom_emoji, name: 'new-name', group: group, file: 'ftp://some-url.in')
expect(emoji).not_to be_valid
expect(emoji.errors.messages).to eq(file: ["is blocked: Only allowed schemes are http, https"])
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'getting custom emoji within namespace' do
include GraphqlHelpers
let_it_be(:current_user) { create(:user) }
let_it_be(:group) { create(:group, :private) }
let_it_be(:custom_emoji) { create(:custom_emoji, group: group) }
before do
stub_feature_flags(custom_emoji: true)
group.add_developer(current_user)
end
describe "Query CustomEmoji on Group" do
def custom_emoji_query(group)
graphql_query_for('group', 'fullPath' => group.full_path)
end
it 'returns emojis when authorised' do
post_graphql(custom_emoji_query(group), current_user: current_user)
expect(response).to have_gitlab_http_status(:ok)
expect(graphql_data['group']['customEmoji']['nodes'].count). to eq(1)
expect(graphql_data['group']['customEmoji']['nodes'].first['name']). to eq(custom_emoji.name)
end
it 'returns nil when unauthorised' do
user = create(:user)
post_graphql(custom_emoji_query(group), current_user: user)
expect(graphql_data['group']).to be_nil
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Creation of a new Custom Emoji' do
include GraphqlHelpers
let_it_be(:current_user) { create(:user) }
let_it_be(:group) { create(:group) }
let(:attributes) do
{
name: 'my_new_emoji',
url: 'https://example.com/image.png',
group_path: group.full_path
}
end
let(:mutation) do
graphql_mutation(:create_custom_emoji, attributes)
end
context 'when the user has no permission' do
it 'does not create custom emoji' do
expect { post_graphql_mutation(mutation, current_user: current_user) }.not_to change(CustomEmoji, :count)
end
end
context 'when user has permission' do
before do
group.add_developer(current_user)
end
it 'creates custom emoji' do
expect { post_graphql_mutation(mutation, current_user: current_user) }.to change(CustomEmoji, :count).by(1)
gql_response = graphql_mutation_response(:create_custom_emoji)
expect(gql_response['errors']).to eq([])
expect(gql_response['customEmoji']['name']).to eq(attributes[:name])
expect(gql_response['customEmoji']['url']).to eq(attributes[:url])
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