Browse Source

Feature: Mobile - Add missing OverviewPolicy.

Martin Gruner 2 years ago
parent
commit
5ce0a49d32

+ 2 - 2
app/frontend/apps/mobile/modules/home/__tests__/moving-ticket-overview.spec.ts

@@ -1,6 +1,6 @@
 // Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
 
-import { OverviewsDocument } from '@shared/entities/ticket/graphql/queries/overviews.api'
+import { TicketOverviewsDocument } from '@shared/entities/ticket/graphql/queries/ticket/overviews.api'
 import { getAllByTestId, getByTestId, within } from '@testing-library/vue'
 import createMockClient from '@tests/support/mock-apollo-client'
 import { visitView } from '@tests/support/components/visitView'
@@ -21,7 +21,7 @@ describe('playing with overviews', () => {
     createMockClient(
       [
         {
-          operationDocument: OverviewsDocument,
+          operationDocument: TicketOverviewsDocument,
           handler: async () => ({ data: getApiTicketOverviews() }),
         },
       ],

+ 2 - 2
app/frontend/apps/mobile/modules/home/__tests__/opening-home.spec.ts

@@ -1,6 +1,6 @@
 // Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
 
-import { OverviewsDocument } from '@shared/entities/ticket/graphql/queries/overviews.api'
+import { TicketOverviewsDocument } from '@shared/entities/ticket/graphql/queries/ticket/overviews.api'
 import { visitView } from '@tests/support/components/visitView'
 import { mockAccount } from '@tests/support/mock-account'
 import createMockClient from '@tests/support/mock-apollo-client'
@@ -13,7 +13,7 @@ describe('home page', () => {
     mockAccount({ id: '666' })
     createMockClient([
       {
-        operationDocument: OverviewsDocument,
+        operationDocument: TicketOverviewsDocument,
         handler: async () => ({ data: getApiTicketOverviews() }),
       },
     ])

+ 11 - 8
app/frontend/apps/mobile/modules/home/stores/ticketOverviews.ts

@@ -2,8 +2,8 @@
 
 import { defineStore } from 'pinia'
 import { QueryHandler } from '@shared/server/apollo/handler'
-import { useOverviewsQuery } from '@shared/entities/ticket/graphql/queries/overviews.api'
-import { OverviewsQuery } from '@shared/graphql/types'
+import { useTicketOverviewsQuery } from '@shared/entities/ticket/graphql/queries/ticket/overviews.api'
+import { TicketOverviewsQuery } from '@shared/graphql/types'
 import { ref, computed } from 'vue'
 import { keyBy } from 'lodash-es'
 import { watchOnce } from '@vueuse/core'
@@ -11,16 +11,19 @@ import { ConfidentTake } from '@shared/types/utils'
 import { getTicketOverviewStorage } from '../helpers/ticketOverviewStorage'
 
 export type TicketOverview = ConfidentTake<
-  OverviewsQuery,
-  'overviews.edges.node'
+  TicketOverviewsQuery,
+  'ticketOverviews.edges.node'
 >
 
-let overviewHandler: QueryHandler<OverviewsQuery, { withTicketCount: boolean }>
+let overviewHandler: QueryHandler<
+  TicketOverviewsQuery,
+  { withTicketCount: boolean }
+>
 
 const getOverviewHandler = () => {
   if (!overviewHandler) {
     overviewHandler = new QueryHandler(
-      useOverviewsQuery({ withTicketCount: true }),
+      useTicketOverviewsQuery({ withTicketCount: true }),
     )
   }
 
@@ -33,10 +36,10 @@ export const useTicketsOverviews = defineStore('tickets-overview', () => {
   const overviewsLoading = handler.loading()
 
   const overviews = computed(() => {
-    if (!overviewsRaw.value?.overviews.edges) return []
+    if (!overviewsRaw.value?.ticketOverviews.edges) return []
 
     return (
-      overviewsRaw.value.overviews.edges
+      overviewsRaw.value.ticketOverviews.edges
         .filter((overview) => overview?.node?.id)
         // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
         .map((edge) => edge!.node!)

+ 0 - 45
app/frontend/shared/entities/ticket/graphql/queries/overviews.api.ts

@@ -1,45 +0,0 @@
-import * as Types from '../../../../graphql/types';
-
-import gql from 'graphql-tag';
-import * as VueApolloComposable from '@vue/apollo-composable';
-import * as VueCompositionApi from 'vue';
-export type ReactiveFunction<TParam> = () => TParam;
-
-export const OverviewsDocument = gql`
-    query overviews($withTicketCount: Boolean!) {
-  overviews {
-    edges {
-      node {
-        id
-        name
-        link
-        prio
-        orderBy
-        orderDirection
-        viewColumns {
-          key
-          value
-        }
-        orderColumns {
-          key
-          value
-        }
-        active
-        ticketCount @include(if: $withTicketCount)
-      }
-      cursor
-    }
-    pageInfo {
-      endCursor
-      hasNextPage
-    }
-  }
-}
-    `;
-export function useOverviewsQuery(variables: Types.OverviewsQueryVariables | VueCompositionApi.Ref<Types.OverviewsQueryVariables> | ReactiveFunction<Types.OverviewsQueryVariables>, options: VueApolloComposable.UseQueryOptions<Types.OverviewsQuery, Types.OverviewsQueryVariables> | VueCompositionApi.Ref<VueApolloComposable.UseQueryOptions<Types.OverviewsQuery, Types.OverviewsQueryVariables>> | ReactiveFunction<VueApolloComposable.UseQueryOptions<Types.OverviewsQuery, Types.OverviewsQueryVariables>> = {}) {
-  return VueApolloComposable.useQuery<Types.OverviewsQuery, Types.OverviewsQueryVariables>(OverviewsDocument, variables, options);
-}
-export function useOverviewsLazyQuery(variables: Types.OverviewsQueryVariables | VueCompositionApi.Ref<Types.OverviewsQueryVariables> | ReactiveFunction<Types.OverviewsQueryVariables>, options: VueApolloComposable.UseQueryOptions<Types.OverviewsQuery, Types.OverviewsQueryVariables> | VueCompositionApi.Ref<VueApolloComposable.UseQueryOptions<Types.OverviewsQuery, Types.OverviewsQueryVariables>> | ReactiveFunction<VueApolloComposable.UseQueryOptions<Types.OverviewsQuery, Types.OverviewsQueryVariables>> = {}) {
-  return VueApolloComposable.useLazyQuery<Types.OverviewsQuery, Types.OverviewsQueryVariables>(OverviewsDocument, variables, options);
-}
-export type OverviewsQueryCompositionFunctionResult = VueApolloComposable.UseQueryReturn<Types.OverviewsQuery, Types.OverviewsQueryVariables>;

+ 45 - 0
app/frontend/shared/entities/ticket/graphql/queries/ticket/overviews.api.ts

@@ -0,0 +1,45 @@
+import * as Types from '../../../../../graphql/types';
+
+import gql from 'graphql-tag';
+import * as VueApolloComposable from '@vue/apollo-composable';
+import * as VueCompositionApi from 'vue';
+export type ReactiveFunction<TParam> = () => TParam;
+
+export const TicketOverviewsDocument = gql`
+    query ticketOverviews($withTicketCount: Boolean!) {
+  ticketOverviews {
+    edges {
+      node {
+        id
+        name
+        link
+        prio
+        orderBy
+        orderDirection
+        viewColumns {
+          key
+          value
+        }
+        orderColumns {
+          key
+          value
+        }
+        active
+        ticketCount @include(if: $withTicketCount)
+      }
+      cursor
+    }
+    pageInfo {
+      endCursor
+      hasNextPage
+    }
+  }
+}
+    `;
+export function useTicketOverviewsQuery(variables: Types.TicketOverviewsQueryVariables | VueCompositionApi.Ref<Types.TicketOverviewsQueryVariables> | ReactiveFunction<Types.TicketOverviewsQueryVariables>, options: VueApolloComposable.UseQueryOptions<Types.TicketOverviewsQuery, Types.TicketOverviewsQueryVariables> | VueCompositionApi.Ref<VueApolloComposable.UseQueryOptions<Types.TicketOverviewsQuery, Types.TicketOverviewsQueryVariables>> | ReactiveFunction<VueApolloComposable.UseQueryOptions<Types.TicketOverviewsQuery, Types.TicketOverviewsQueryVariables>> = {}) {
+  return VueApolloComposable.useQuery<Types.TicketOverviewsQuery, Types.TicketOverviewsQueryVariables>(TicketOverviewsDocument, variables, options);
+}
+export function useTicketOverviewsLazyQuery(variables: Types.TicketOverviewsQueryVariables | VueCompositionApi.Ref<Types.TicketOverviewsQueryVariables> | ReactiveFunction<Types.TicketOverviewsQueryVariables>, options: VueApolloComposable.UseQueryOptions<Types.TicketOverviewsQuery, Types.TicketOverviewsQueryVariables> | VueCompositionApi.Ref<VueApolloComposable.UseQueryOptions<Types.TicketOverviewsQuery, Types.TicketOverviewsQueryVariables>> | ReactiveFunction<VueApolloComposable.UseQueryOptions<Types.TicketOverviewsQuery, Types.TicketOverviewsQueryVariables>> = {}) {
+  return VueApolloComposable.useLazyQuery<Types.TicketOverviewsQuery, Types.TicketOverviewsQueryVariables>(TicketOverviewsDocument, variables, options);
+}
+export type TicketOverviewsQueryCompositionFunctionResult = VueApolloComposable.UseQueryReturn<Types.TicketOverviewsQuery, Types.TicketOverviewsQueryVariables>;

+ 2 - 2
app/frontend/shared/entities/ticket/graphql/queries/overviews.graphql → app/frontend/shared/entities/ticket/graphql/queries/ticket/overviews.graphql

@@ -1,5 +1,5 @@
-query overviews($withTicketCount: Boolean!) {
-  overviews {
+query ticketOverviews($withTicketCount: Boolean!) {
+  ticketOverviews {
     edges {
       node {
         id

+ 13 - 13
app/frontend/shared/graphql/types.ts

@@ -379,14 +379,14 @@ export type Queries = {
   node?: Maybe<Node>;
   /** Fetches a list of objects given a list of IDs. */
   nodes: Array<Maybe<Node>>;
-  /** Ticket overviews available in the system */
-  overviews: OverviewConnection;
   /** The sessionId of the currently authenticated user. */
   sessionId: Scalars['String'];
   /** Fetch a ticket by ID */
   ticket: Ticket;
   /** Fetch a ticket by ID */
   ticketArticles: TicketArticleConnection;
+  /** Ticket overviews available in the system */
+  ticketOverviews: OverviewConnection;
   /** Fetch tickets of a given ticket overview */
   ticketsByOverview: TicketConnection;
   /** Translations for a given locale */
@@ -425,15 +425,6 @@ export type QueriesNodesArgs = {
 };
 
 
-/** All available queries */
-export type QueriesOverviewsArgs = {
-  after?: InputMaybe<Scalars['String']>;
-  before?: InputMaybe<Scalars['String']>;
-  first?: InputMaybe<Scalars['Int']>;
-  last?: InputMaybe<Scalars['Int']>;
-};
-
-
 /** All available queries */
 export type QueriesTicketArgs = {
   ticketId?: InputMaybe<Scalars['ID']>;
@@ -452,6 +443,15 @@ export type QueriesTicketArticlesArgs = {
 };
 
 
+/** All available queries */
+export type QueriesTicketOverviewsArgs = {
+  after?: InputMaybe<Scalars['String']>;
+  before?: InputMaybe<Scalars['String']>;
+  first?: InputMaybe<Scalars['Int']>;
+  last?: InputMaybe<Scalars['Int']>;
+};
+
+
 /** All available queries */
 export type QueriesTicketsByOverviewArgs = {
   after?: InputMaybe<Scalars['String']>;
@@ -877,12 +877,12 @@ export type FormSchemaQueryVariables = Exact<{
 
 export type FormSchemaQuery = { __typename?: 'Queries', formSchema: any };
 
-export type OverviewsQueryVariables = Exact<{
+export type TicketOverviewsQueryVariables = Exact<{
   withTicketCount: Scalars['Boolean'];
 }>;
 
 
-export type OverviewsQuery = { __typename?: 'Queries', overviews: { __typename?: 'OverviewConnection', edges: Array<{ __typename?: 'OverviewEdge', cursor: string, node: { __typename?: 'Overview', id: string, name: string, link: string, prio: number, orderBy: string, orderDirection: OrderDirection, active: boolean, ticketCount?: number, viewColumns: Array<{ __typename?: 'KeyValue', key: string, value?: string | null }>, orderColumns: Array<{ __typename?: 'KeyValue', key: string, value?: string | null }> } }>, pageInfo: { __typename?: 'PageInfo', endCursor?: string | null, hasNextPage: boolean } } };
+export type TicketOverviewsQuery = { __typename?: 'Queries', ticketOverviews: { __typename?: 'OverviewConnection', edges: Array<{ __typename?: 'OverviewEdge', cursor: string, node: { __typename?: 'Overview', id: string, name: string, link: string, prio: number, orderBy: string, orderDirection: OrderDirection, active: boolean, ticketCount?: number, viewColumns: Array<{ __typename?: 'KeyValue', key: string, value?: string | null }>, orderColumns: Array<{ __typename?: 'KeyValue', key: string, value?: string | null }> } }>, pageInfo: { __typename?: 'PageInfo', endCursor?: string | null, hasNextPage: boolean } } };
 
 export type ErrorsFragment = { __typename?: 'UserError', message: string, field?: string | null };
 

+ 5 - 5
app/frontend/tests/support/mocks/ticket-overviews.ts

@@ -1,12 +1,12 @@
 // Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
 
-import { OverviewsDocument } from '@shared/entities/ticket/graphql/queries/overviews.api'
-import { OrderDirection, OverviewsQuery } from '@shared/graphql/types'
+import { TicketOverviewsDocument } from '@shared/entities/ticket/graphql/queries/ticket/overviews.api'
+import { OrderDirection, TicketOverviewsQuery } from '@shared/graphql/types'
 import { mock } from 'vitest-mock-extended'
 import { mockGraphQLApi } from '../mock-graphql-api'
 
-export const getApiTicketOverviews = (): OverviewsQuery => ({
-  overviews: mock<OverviewsQuery['overviews']>(
+export const getApiTicketOverviews = (): TicketOverviewsQuery => ({
+  ticketOverviews: mock<TicketOverviewsQuery['ticketOverviews']>(
     {
       pageInfo: {
         endCursor: null,
@@ -71,5 +71,5 @@ export const getApiTicketOverviews = (): OverviewsQuery => ({
 })
 
 export const mockTicketOverviews = () => {
-  return mockGraphQLApi(OverviewsDocument).willResolve(getApiTicketOverviews())
+  return mockGraphQLApi(TicketOverviewsDocument).willResolve(getApiTicketOverviews())
 }

+ 3 - 2
app/graphql/gql/queries/overviews.rb → app/graphql/gql/queries/ticket/overviews.rb

@@ -1,13 +1,14 @@
 # Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
 
 module Gql::Queries
-  class Overviews < BaseQuery
+  class Ticket::Overviews < BaseQuery
 
     description 'Ticket overviews available in the system'
 
     type Gql::Types::OverviewType.connection_type, null: false
 
-    def resolve(...)
+    def resolve
+      # This effectively scopes the overviews by `:use?` permission.
       ::Ticket::Overviews.all(current_user: context.current_user)
     end
 

+ 1 - 1
app/graphql/gql/queries/tickets_by_overview.rb

@@ -12,7 +12,7 @@ module Gql::Queries
     type Gql::Types::TicketType.connection_type, null: false
 
     def resolve(overview_id: nil, order_by: nil, order_direction: nil)
-      overview = Gql::ZammadSchema.verified_object_from_id(overview_id, type: ::Overview)
+      overview = Gql::ZammadSchema.authorized_object_from_id(overview_id, type: ::Overview, user: context.current_user)
       # This will fetch tickets with 'overview' permissions, which logically include 'read' permissions.
       ::Ticket::Overviews.tickets_for_overview(overview, context.current_user, order_by: order_by, order_direction: order_direction)
     end

Some files were not shown because too many files changed in this diff