add list folder policy api

This commit is contained in:
Hongbo Wu 2024-06-10 19:25:58 +08:00
parent 25ca4c7791
commit 7940c3f4ea
11 changed files with 578 additions and 4 deletions

View file

@ -7,6 +7,11 @@ import {
} from 'typeorm'
import { User } from './user'
export enum FolderPolicyAction {
DELETE = 'DELETE',
ARCHIVE = 'ARCHIVE',
}
@Entity({ name: 'folder_policy' })
export class FolderPolicy {
@PrimaryGeneratedColumn('uuid')
@ -22,8 +27,8 @@ export class FolderPolicy {
@Column('text')
folder!: string
@Column('text')
action!: string
@Column('enum', { enum: FolderPolicyAction })
action!: FolderPolicyAction
@Column('int')
afterDays!: number

View file

@ -349,6 +349,30 @@ export type CreateArticleSuccess = {
user: User;
};
export type CreateFolderPolicyError = {
__typename?: 'CreateFolderPolicyError';
errorCodes: Array<CreateFolderPolicyErrorCode>;
};
export enum CreateFolderPolicyErrorCode {
BadRequest = 'BAD_REQUEST',
Unauthorized = 'UNAUTHORIZED'
}
export type CreateFolderPolicyInput = {
action: FolderPolicyAction;
afterDays: Scalars['Int'];
folder: Scalars['String'];
minimumItems?: InputMaybe<Scalars['Int']>;
};
export type CreateFolderPolicyResult = CreateFolderPolicyError | CreateFolderPolicySuccess;
export type CreateFolderPolicySuccess = {
__typename?: 'CreateFolderPolicySuccess';
policy: FolderPolicy;
};
export type CreateGroupError = {
__typename?: 'CreateGroupError';
errorCodes: Array<CreateGroupErrorCode>;
@ -619,6 +643,23 @@ export type DeleteFilterSuccess = {
filter: Filter;
};
export type DeleteFolderPolicyError = {
__typename?: 'DeleteFolderPolicyError';
errorCodes: Array<DeleteFolderPolicyErrorCode>;
};
export enum DeleteFolderPolicyErrorCode {
BadRequest = 'BAD_REQUEST',
Unauthorized = 'UNAUTHORIZED'
}
export type DeleteFolderPolicyResult = DeleteFolderPolicyError | DeleteFolderPolicySuccess;
export type DeleteFolderPolicySuccess = {
__typename?: 'DeleteFolderPolicySuccess';
success: Scalars['Boolean'];
};
export type DeleteHighlightError = {
__typename?: 'DeleteHighlightError';
errorCodes: Array<DeleteHighlightErrorCode>;
@ -1081,6 +1122,39 @@ export type FiltersSuccess = {
filters: Array<Filter>;
};
export type FolderPoliciesError = {
__typename?: 'FolderPoliciesError';
errorCodes: Array<FolderPoliciesErrorCode>;
};
export enum FolderPoliciesErrorCode {
BadRequest = 'BAD_REQUEST',
Unauthorized = 'UNAUTHORIZED'
}
export type FolderPoliciesResult = FolderPoliciesError | FolderPoliciesSuccess;
export type FolderPoliciesSuccess = {
__typename?: 'FolderPoliciesSuccess';
policies: Array<FolderPolicy>;
};
export type FolderPolicy = {
__typename?: 'FolderPolicy';
action: FolderPolicyAction;
afterDays: Scalars['Int'];
createdAt: Scalars['Date'];
folder: Scalars['String'];
id: Scalars['ID'];
minimumItems: Scalars['Int'];
updatedAt: Scalars['Date'];
};
export enum FolderPolicyAction {
Archive = 'ARCHIVE',
Delete = 'DELETE'
}
export type GenerateApiKeyError = {
__typename?: 'GenerateApiKeyError';
errorCodes: Array<GenerateApiKeyErrorCode>;
@ -1723,6 +1797,7 @@ export type Mutation = {
bulkAction: BulkActionResult;
createArticle: CreateArticleResult;
createArticleSavingRequest: CreateArticleSavingRequestResult;
createFolderPolicy: CreateFolderPolicyResult;
createGroup: CreateGroupResult;
createHighlight: CreateHighlightResult;
createLabel: CreateLabelResult;
@ -1731,6 +1806,7 @@ export type Mutation = {
deleteDiscoverArticle: DeleteDiscoverArticleResult;
deleteDiscoverFeed: DeleteDiscoverFeedResult;
deleteFilter: DeleteFilterResult;
deleteFolderPolicy: DeleteFolderPolicyResult;
deleteHighlight: DeleteHighlightResult;
deleteIntegration: DeleteIntegrationResult;
deleteLabel: DeleteLabelResult;
@ -1780,6 +1856,7 @@ export type Mutation = {
unsubscribe: UnsubscribeResult;
updateEmail: UpdateEmailResult;
updateFilter: UpdateFilterResult;
updateFolderPolicy: UpdateFolderPolicyResult;
updateHighlight: UpdateHighlightResult;
updateLabel: UpdateLabelResult;
updateNewsletterEmail: UpdateNewsletterEmailResult;
@ -1822,6 +1899,11 @@ export type MutationCreateArticleSavingRequestArgs = {
};
export type MutationCreateFolderPolicyArgs = {
input: CreateFolderPolicyInput;
};
export type MutationCreateGroupArgs = {
input: CreateGroupInput;
};
@ -1862,6 +1944,11 @@ export type MutationDeleteFilterArgs = {
};
export type MutationDeleteFolderPolicyArgs = {
id: Scalars['ID'];
};
export type MutationDeleteHighlightArgs = {
highlightId: Scalars['ID'];
};
@ -2095,6 +2182,11 @@ export type MutationUpdateFilterArgs = {
};
export type MutationUpdateFolderPolicyArgs = {
input: UpdateFolderPolicyInput;
};
export type MutationUpdateHighlightArgs = {
input: UpdateHighlightInput;
};
@ -2280,6 +2372,7 @@ export type Query = {
discoverTopics: GetDiscoverTopicResults;
feeds: FeedsResult;
filters: FiltersResult;
folderPolicies: FolderPoliciesResult;
getDiscoverFeedArticles: GetDiscoverFeedArticleResults;
getUserPersonalization: GetUserPersonalizationResult;
groups: GroupsResult;
@ -3555,6 +3648,30 @@ export type UpdateFilterSuccess = {
filter: Filter;
};
export type UpdateFolderPolicyError = {
__typename?: 'UpdateFolderPolicyError';
errorCodes: Array<UpdateFolderPolicyErrorCode>;
};
export enum UpdateFolderPolicyErrorCode {
BadRequest = 'BAD_REQUEST',
Unauthorized = 'UNAUTHORIZED'
}
export type UpdateFolderPolicyInput = {
action?: InputMaybe<FolderPolicyAction>;
afterDays?: InputMaybe<Scalars['Int']>;
id: Scalars['ID'];
minimumItems?: InputMaybe<Scalars['Int']>;
};
export type UpdateFolderPolicyResult = UpdateFolderPolicyError | UpdateFolderPolicySuccess;
export type UpdateFolderPolicySuccess = {
__typename?: 'UpdateFolderPolicySuccess';
policy: FolderPolicy;
};
export type UpdateHighlightError = {
__typename?: 'UpdateHighlightError';
errorCodes: Array<UpdateHighlightErrorCode>;
@ -4180,6 +4297,11 @@ export type ResolversTypes = {
CreateArticleSavingRequestResult: ResolversTypes['CreateArticleSavingRequestError'] | ResolversTypes['CreateArticleSavingRequestSuccess'];
CreateArticleSavingRequestSuccess: ResolverTypeWrapper<CreateArticleSavingRequestSuccess>;
CreateArticleSuccess: ResolverTypeWrapper<CreateArticleSuccess>;
CreateFolderPolicyError: ResolverTypeWrapper<CreateFolderPolicyError>;
CreateFolderPolicyErrorCode: CreateFolderPolicyErrorCode;
CreateFolderPolicyInput: CreateFolderPolicyInput;
CreateFolderPolicyResult: ResolversTypes['CreateFolderPolicyError'] | ResolversTypes['CreateFolderPolicySuccess'];
CreateFolderPolicySuccess: ResolverTypeWrapper<CreateFolderPolicySuccess>;
CreateGroupError: ResolverTypeWrapper<CreateGroupError>;
CreateGroupErrorCode: CreateGroupErrorCode;
CreateGroupInput: CreateGroupInput;
@ -4234,6 +4356,10 @@ export type ResolversTypes = {
DeleteFilterErrorCode: DeleteFilterErrorCode;
DeleteFilterResult: ResolversTypes['DeleteFilterError'] | ResolversTypes['DeleteFilterSuccess'];
DeleteFilterSuccess: ResolverTypeWrapper<DeleteFilterSuccess>;
DeleteFolderPolicyError: ResolverTypeWrapper<DeleteFolderPolicyError>;
DeleteFolderPolicyErrorCode: DeleteFolderPolicyErrorCode;
DeleteFolderPolicyResult: ResolversTypes['DeleteFolderPolicyError'] | ResolversTypes['DeleteFolderPolicySuccess'];
DeleteFolderPolicySuccess: ResolverTypeWrapper<DeleteFolderPolicySuccess>;
DeleteHighlightError: ResolverTypeWrapper<DeleteHighlightError>;
DeleteHighlightErrorCode: DeleteHighlightErrorCode;
DeleteHighlightReplyError: ResolverTypeWrapper<DeleteHighlightReplyError>;
@ -4324,6 +4450,12 @@ export type ResolversTypes = {
FiltersResult: ResolversTypes['FiltersError'] | ResolversTypes['FiltersSuccess'];
FiltersSuccess: ResolverTypeWrapper<FiltersSuccess>;
Float: ResolverTypeWrapper<Scalars['Float']>;
FolderPoliciesError: ResolverTypeWrapper<FolderPoliciesError>;
FolderPoliciesErrorCode: FolderPoliciesErrorCode;
FolderPoliciesResult: ResolversTypes['FolderPoliciesError'] | ResolversTypes['FolderPoliciesSuccess'];
FolderPoliciesSuccess: ResolverTypeWrapper<FolderPoliciesSuccess>;
FolderPolicy: ResolverTypeWrapper<FolderPolicy>;
FolderPolicyAction: FolderPolicyAction;
GenerateApiKeyError: ResolverTypeWrapper<GenerateApiKeyError>;
GenerateApiKeyErrorCode: GenerateApiKeyErrorCode;
GenerateApiKeyInput: GenerateApiKeyInput;
@ -4659,6 +4791,11 @@ export type ResolversTypes = {
UpdateFilterInput: UpdateFilterInput;
UpdateFilterResult: ResolversTypes['UpdateFilterError'] | ResolversTypes['UpdateFilterSuccess'];
UpdateFilterSuccess: ResolverTypeWrapper<UpdateFilterSuccess>;
UpdateFolderPolicyError: ResolverTypeWrapper<UpdateFolderPolicyError>;
UpdateFolderPolicyErrorCode: UpdateFolderPolicyErrorCode;
UpdateFolderPolicyInput: UpdateFolderPolicyInput;
UpdateFolderPolicyResult: ResolversTypes['UpdateFolderPolicyError'] | ResolversTypes['UpdateFolderPolicySuccess'];
UpdateFolderPolicySuccess: ResolverTypeWrapper<UpdateFolderPolicySuccess>;
UpdateHighlightError: ResolverTypeWrapper<UpdateHighlightError>;
UpdateHighlightErrorCode: UpdateHighlightErrorCode;
UpdateHighlightInput: UpdateHighlightInput;
@ -4794,6 +4931,10 @@ export type ResolversParentTypes = {
CreateArticleSavingRequestResult: ResolversParentTypes['CreateArticleSavingRequestError'] | ResolversParentTypes['CreateArticleSavingRequestSuccess'];
CreateArticleSavingRequestSuccess: CreateArticleSavingRequestSuccess;
CreateArticleSuccess: CreateArticleSuccess;
CreateFolderPolicyError: CreateFolderPolicyError;
CreateFolderPolicyInput: CreateFolderPolicyInput;
CreateFolderPolicyResult: ResolversParentTypes['CreateFolderPolicyError'] | ResolversParentTypes['CreateFolderPolicySuccess'];
CreateFolderPolicySuccess: CreateFolderPolicySuccess;
CreateGroupError: CreateGroupError;
CreateGroupInput: CreateGroupInput;
CreateGroupResult: ResolversParentTypes['CreateGroupError'] | ResolversParentTypes['CreateGroupSuccess'];
@ -4837,6 +4978,9 @@ export type ResolversParentTypes = {
DeleteFilterError: DeleteFilterError;
DeleteFilterResult: ResolversParentTypes['DeleteFilterError'] | ResolversParentTypes['DeleteFilterSuccess'];
DeleteFilterSuccess: DeleteFilterSuccess;
DeleteFolderPolicyError: DeleteFolderPolicyError;
DeleteFolderPolicyResult: ResolversParentTypes['DeleteFolderPolicyError'] | ResolversParentTypes['DeleteFolderPolicySuccess'];
DeleteFolderPolicySuccess: DeleteFolderPolicySuccess;
DeleteHighlightError: DeleteHighlightError;
DeleteHighlightReplyError: DeleteHighlightReplyError;
DeleteHighlightReplyResult: ResolversParentTypes['DeleteHighlightReplyError'] | ResolversParentTypes['DeleteHighlightReplySuccess'];
@ -4906,6 +5050,10 @@ export type ResolversParentTypes = {
FiltersResult: ResolversParentTypes['FiltersError'] | ResolversParentTypes['FiltersSuccess'];
FiltersSuccess: FiltersSuccess;
Float: Scalars['Float'];
FolderPoliciesError: FolderPoliciesError;
FolderPoliciesResult: ResolversParentTypes['FolderPoliciesError'] | ResolversParentTypes['FolderPoliciesSuccess'];
FolderPoliciesSuccess: FolderPoliciesSuccess;
FolderPolicy: FolderPolicy;
GenerateApiKeyError: GenerateApiKeyError;
GenerateApiKeyInput: GenerateApiKeyInput;
GenerateApiKeyResult: ResolversParentTypes['GenerateApiKeyError'] | ResolversParentTypes['GenerateApiKeySuccess'];
@ -5166,6 +5314,10 @@ export type ResolversParentTypes = {
UpdateFilterInput: UpdateFilterInput;
UpdateFilterResult: ResolversParentTypes['UpdateFilterError'] | ResolversParentTypes['UpdateFilterSuccess'];
UpdateFilterSuccess: UpdateFilterSuccess;
UpdateFolderPolicyError: UpdateFolderPolicyError;
UpdateFolderPolicyInput: UpdateFolderPolicyInput;
UpdateFolderPolicyResult: ResolversParentTypes['UpdateFolderPolicyError'] | ResolversParentTypes['UpdateFolderPolicySuccess'];
UpdateFolderPolicySuccess: UpdateFolderPolicySuccess;
UpdateHighlightError: UpdateHighlightError;
UpdateHighlightInput: UpdateHighlightInput;
UpdateHighlightReplyError: UpdateHighlightReplyError;
@ -5469,6 +5621,20 @@ export type CreateArticleSuccessResolvers<ContextType = ResolverContext, ParentT
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
export type CreateFolderPolicyErrorResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['CreateFolderPolicyError'] = ResolversParentTypes['CreateFolderPolicyError']> = {
errorCodes?: Resolver<Array<ResolversTypes['CreateFolderPolicyErrorCode']>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
export type CreateFolderPolicyResultResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['CreateFolderPolicyResult'] = ResolversParentTypes['CreateFolderPolicyResult']> = {
__resolveType: TypeResolveFn<'CreateFolderPolicyError' | 'CreateFolderPolicySuccess', ParentType, ContextType>;
};
export type CreateFolderPolicySuccessResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['CreateFolderPolicySuccess'] = ResolversParentTypes['CreateFolderPolicySuccess']> = {
policy?: Resolver<ResolversTypes['FolderPolicy'], ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
export type CreateGroupErrorResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['CreateGroupError'] = ResolversParentTypes['CreateGroupError']> = {
errorCodes?: Resolver<Array<ResolversTypes['CreateGroupErrorCode']>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
@ -5627,6 +5793,20 @@ export type DeleteFilterSuccessResolvers<ContextType = ResolverContext, ParentTy
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
export type DeleteFolderPolicyErrorResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['DeleteFolderPolicyError'] = ResolversParentTypes['DeleteFolderPolicyError']> = {
errorCodes?: Resolver<Array<ResolversTypes['DeleteFolderPolicyErrorCode']>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
export type DeleteFolderPolicyResultResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['DeleteFolderPolicyResult'] = ResolversParentTypes['DeleteFolderPolicyResult']> = {
__resolveType: TypeResolveFn<'DeleteFolderPolicyError' | 'DeleteFolderPolicySuccess', ParentType, ContextType>;
};
export type DeleteFolderPolicySuccessResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['DeleteFolderPolicySuccess'] = ResolversParentTypes['DeleteFolderPolicySuccess']> = {
success?: Resolver<ResolversTypes['Boolean'], ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
export type DeleteHighlightErrorResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['DeleteHighlightError'] = ResolversParentTypes['DeleteHighlightError']> = {
errorCodes?: Resolver<Array<ResolversTypes['DeleteHighlightErrorCode']>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
@ -5992,6 +6172,31 @@ export type FiltersSuccessResolvers<ContextType = ResolverContext, ParentType ex
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
export type FolderPoliciesErrorResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['FolderPoliciesError'] = ResolversParentTypes['FolderPoliciesError']> = {
errorCodes?: Resolver<Array<ResolversTypes['FolderPoliciesErrorCode']>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
export type FolderPoliciesResultResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['FolderPoliciesResult'] = ResolversParentTypes['FolderPoliciesResult']> = {
__resolveType: TypeResolveFn<'FolderPoliciesError' | 'FolderPoliciesSuccess', ParentType, ContextType>;
};
export type FolderPoliciesSuccessResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['FolderPoliciesSuccess'] = ResolversParentTypes['FolderPoliciesSuccess']> = {
policies?: Resolver<Array<ResolversTypes['FolderPolicy']>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
export type FolderPolicyResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['FolderPolicy'] = ResolversParentTypes['FolderPolicy']> = {
action?: Resolver<ResolversTypes['FolderPolicyAction'], ParentType, ContextType>;
afterDays?: Resolver<ResolversTypes['Int'], ParentType, ContextType>;
createdAt?: Resolver<ResolversTypes['Date'], ParentType, ContextType>;
folder?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>;
minimumItems?: Resolver<ResolversTypes['Int'], ParentType, ContextType>;
updatedAt?: Resolver<ResolversTypes['Date'], ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
export type GenerateApiKeyErrorResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['GenerateApiKeyError'] = ResolversParentTypes['GenerateApiKeyError']> = {
errorCodes?: Resolver<Array<ResolversTypes['GenerateApiKeyErrorCode']>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
@ -6486,6 +6691,7 @@ export type MutationResolvers<ContextType = ResolverContext, ParentType extends
bulkAction?: Resolver<ResolversTypes['BulkActionResult'], ParentType, ContextType, RequireFields<MutationBulkActionArgs, 'action' | 'query'>>;
createArticle?: Resolver<ResolversTypes['CreateArticleResult'], ParentType, ContextType, RequireFields<MutationCreateArticleArgs, 'input'>>;
createArticleSavingRequest?: Resolver<ResolversTypes['CreateArticleSavingRequestResult'], ParentType, ContextType, RequireFields<MutationCreateArticleSavingRequestArgs, 'input'>>;
createFolderPolicy?: Resolver<ResolversTypes['CreateFolderPolicyResult'], ParentType, ContextType, RequireFields<MutationCreateFolderPolicyArgs, 'input'>>;
createGroup?: Resolver<ResolversTypes['CreateGroupResult'], ParentType, ContextType, RequireFields<MutationCreateGroupArgs, 'input'>>;
createHighlight?: Resolver<ResolversTypes['CreateHighlightResult'], ParentType, ContextType, RequireFields<MutationCreateHighlightArgs, 'input'>>;
createLabel?: Resolver<ResolversTypes['CreateLabelResult'], ParentType, ContextType, RequireFields<MutationCreateLabelArgs, 'input'>>;
@ -6494,6 +6700,7 @@ export type MutationResolvers<ContextType = ResolverContext, ParentType extends
deleteDiscoverArticle?: Resolver<ResolversTypes['DeleteDiscoverArticleResult'], ParentType, ContextType, RequireFields<MutationDeleteDiscoverArticleArgs, 'input'>>;
deleteDiscoverFeed?: Resolver<ResolversTypes['DeleteDiscoverFeedResult'], ParentType, ContextType, RequireFields<MutationDeleteDiscoverFeedArgs, 'input'>>;
deleteFilter?: Resolver<ResolversTypes['DeleteFilterResult'], ParentType, ContextType, RequireFields<MutationDeleteFilterArgs, 'id'>>;
deleteFolderPolicy?: Resolver<ResolversTypes['DeleteFolderPolicyResult'], ParentType, ContextType, RequireFields<MutationDeleteFolderPolicyArgs, 'id'>>;
deleteHighlight?: Resolver<ResolversTypes['DeleteHighlightResult'], ParentType, ContextType, RequireFields<MutationDeleteHighlightArgs, 'highlightId'>>;
deleteIntegration?: Resolver<ResolversTypes['DeleteIntegrationResult'], ParentType, ContextType, RequireFields<MutationDeleteIntegrationArgs, 'id'>>;
deleteLabel?: Resolver<ResolversTypes['DeleteLabelResult'], ParentType, ContextType, RequireFields<MutationDeleteLabelArgs, 'id'>>;
@ -6543,6 +6750,7 @@ export type MutationResolvers<ContextType = ResolverContext, ParentType extends
unsubscribe?: Resolver<ResolversTypes['UnsubscribeResult'], ParentType, ContextType, RequireFields<MutationUnsubscribeArgs, 'name'>>;
updateEmail?: Resolver<ResolversTypes['UpdateEmailResult'], ParentType, ContextType, RequireFields<MutationUpdateEmailArgs, 'input'>>;
updateFilter?: Resolver<ResolversTypes['UpdateFilterResult'], ParentType, ContextType, RequireFields<MutationUpdateFilterArgs, 'input'>>;
updateFolderPolicy?: Resolver<ResolversTypes['UpdateFolderPolicyResult'], ParentType, ContextType, RequireFields<MutationUpdateFolderPolicyArgs, 'input'>>;
updateHighlight?: Resolver<ResolversTypes['UpdateHighlightResult'], ParentType, ContextType, RequireFields<MutationUpdateHighlightArgs, 'input'>>;
updateLabel?: Resolver<ResolversTypes['UpdateLabelResult'], ParentType, ContextType, RequireFields<MutationUpdateLabelArgs, 'input'>>;
updateNewsletterEmail?: Resolver<ResolversTypes['UpdateNewsletterEmailResult'], ParentType, ContextType, RequireFields<MutationUpdateNewsletterEmailArgs, 'input'>>;
@ -6639,6 +6847,7 @@ export type QueryResolvers<ContextType = ResolverContext, ParentType extends Res
discoverTopics?: Resolver<ResolversTypes['GetDiscoverTopicResults'], ParentType, ContextType>;
feeds?: Resolver<ResolversTypes['FeedsResult'], ParentType, ContextType, RequireFields<QueryFeedsArgs, 'input'>>;
filters?: Resolver<ResolversTypes['FiltersResult'], ParentType, ContextType>;
folderPolicies?: Resolver<ResolversTypes['FolderPoliciesResult'], ParentType, ContextType>;
getDiscoverFeedArticles?: Resolver<ResolversTypes['GetDiscoverFeedArticleResults'], ParentType, ContextType, RequireFields<QueryGetDiscoverFeedArticlesArgs, 'discoverTopicId'>>;
getUserPersonalization?: Resolver<ResolversTypes['GetUserPersonalizationResult'], ParentType, ContextType>;
groups?: Resolver<ResolversTypes['GroupsResult'], ParentType, ContextType>;
@ -7391,6 +7600,20 @@ export type UpdateFilterSuccessResolvers<ContextType = ResolverContext, ParentTy
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
export type UpdateFolderPolicyErrorResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['UpdateFolderPolicyError'] = ResolversParentTypes['UpdateFolderPolicyError']> = {
errorCodes?: Resolver<Array<ResolversTypes['UpdateFolderPolicyErrorCode']>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
export type UpdateFolderPolicyResultResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['UpdateFolderPolicyResult'] = ResolversParentTypes['UpdateFolderPolicyResult']> = {
__resolveType: TypeResolveFn<'UpdateFolderPolicyError' | 'UpdateFolderPolicySuccess', ParentType, ContextType>;
};
export type UpdateFolderPolicySuccessResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['UpdateFolderPolicySuccess'] = ResolversParentTypes['UpdateFolderPolicySuccess']> = {
policy?: Resolver<ResolversTypes['FolderPolicy'], ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
export type UpdateHighlightErrorResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['UpdateHighlightError'] = ResolversParentTypes['UpdateHighlightError']> = {
errorCodes?: Resolver<Array<ResolversTypes['UpdateHighlightErrorCode']>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
@ -7734,6 +7957,9 @@ export type Resolvers<ContextType = ResolverContext> = {
CreateArticleSavingRequestResult?: CreateArticleSavingRequestResultResolvers<ContextType>;
CreateArticleSavingRequestSuccess?: CreateArticleSavingRequestSuccessResolvers<ContextType>;
CreateArticleSuccess?: CreateArticleSuccessResolvers<ContextType>;
CreateFolderPolicyError?: CreateFolderPolicyErrorResolvers<ContextType>;
CreateFolderPolicyResult?: CreateFolderPolicyResultResolvers<ContextType>;
CreateFolderPolicySuccess?: CreateFolderPolicySuccessResolvers<ContextType>;
CreateGroupError?: CreateGroupErrorResolvers<ContextType>;
CreateGroupResult?: CreateGroupResultResolvers<ContextType>;
CreateGroupSuccess?: CreateGroupSuccessResolvers<ContextType>;
@ -7768,6 +7994,9 @@ export type Resolvers<ContextType = ResolverContext> = {
DeleteFilterError?: DeleteFilterErrorResolvers<ContextType>;
DeleteFilterResult?: DeleteFilterResultResolvers<ContextType>;
DeleteFilterSuccess?: DeleteFilterSuccessResolvers<ContextType>;
DeleteFolderPolicyError?: DeleteFolderPolicyErrorResolvers<ContextType>;
DeleteFolderPolicyResult?: DeleteFolderPolicyResultResolvers<ContextType>;
DeleteFolderPolicySuccess?: DeleteFolderPolicySuccessResolvers<ContextType>;
DeleteHighlightError?: DeleteHighlightErrorResolvers<ContextType>;
DeleteHighlightReplyError?: DeleteHighlightReplyErrorResolvers<ContextType>;
DeleteHighlightReplyResult?: DeleteHighlightReplyResultResolvers<ContextType>;
@ -7833,6 +8062,10 @@ export type Resolvers<ContextType = ResolverContext> = {
FiltersError?: FiltersErrorResolvers<ContextType>;
FiltersResult?: FiltersResultResolvers<ContextType>;
FiltersSuccess?: FiltersSuccessResolvers<ContextType>;
FolderPoliciesError?: FolderPoliciesErrorResolvers<ContextType>;
FolderPoliciesResult?: FolderPoliciesResultResolvers<ContextType>;
FolderPoliciesSuccess?: FolderPoliciesSuccessResolvers<ContextType>;
FolderPolicy?: FolderPolicyResolvers<ContextType>;
GenerateApiKeyError?: GenerateApiKeyErrorResolvers<ContextType>;
GenerateApiKeyResult?: GenerateApiKeyResultResolvers<ContextType>;
GenerateApiKeySuccess?: GenerateApiKeySuccessResolvers<ContextType>;
@ -8054,6 +8287,9 @@ export type Resolvers<ContextType = ResolverContext> = {
UpdateFilterError?: UpdateFilterErrorResolvers<ContextType>;
UpdateFilterResult?: UpdateFilterResultResolvers<ContextType>;
UpdateFilterSuccess?: UpdateFilterSuccessResolvers<ContextType>;
UpdateFolderPolicyError?: UpdateFolderPolicyErrorResolvers<ContextType>;
UpdateFolderPolicyResult?: UpdateFolderPolicyResultResolvers<ContextType>;
UpdateFolderPolicySuccess?: UpdateFolderPolicySuccessResolvers<ContextType>;
UpdateHighlightError?: UpdateHighlightErrorResolvers<ContextType>;
UpdateHighlightReplyError?: UpdateHighlightReplyErrorResolvers<ContextType>;
UpdateHighlightReplyResult?: UpdateHighlightReplyResultResolvers<ContextType>;

View file

@ -307,6 +307,28 @@ type CreateArticleSuccess {
user: User!
}
type CreateFolderPolicyError {
errorCodes: [CreateFolderPolicyErrorCode!]!
}
enum CreateFolderPolicyErrorCode {
BAD_REQUEST
UNAUTHORIZED
}
input CreateFolderPolicyInput {
action: FolderPolicyAction!
afterDays: Int!
folder: String!
minimumItems: Int
}
union CreateFolderPolicyResult = CreateFolderPolicyError | CreateFolderPolicySuccess
type CreateFolderPolicySuccess {
policy: FolderPolicy!
}
type CreateGroupError {
errorCodes: [CreateGroupErrorCode!]!
}
@ -557,6 +579,21 @@ type DeleteFilterSuccess {
filter: Filter!
}
type DeleteFolderPolicyError {
errorCodes: [DeleteFolderPolicyErrorCode!]!
}
enum DeleteFolderPolicyErrorCode {
BAD_REQUEST
UNAUTHORIZED
}
union DeleteFolderPolicyResult = DeleteFolderPolicyError | DeleteFolderPolicySuccess
type DeleteFolderPolicySuccess {
success: Boolean!
}
type DeleteHighlightError {
errorCodes: [DeleteHighlightErrorCode!]!
}
@ -972,6 +1009,36 @@ type FiltersSuccess {
filters: [Filter!]!
}
type FolderPoliciesError {
errorCodes: [FolderPoliciesErrorCode!]!
}
enum FolderPoliciesErrorCode {
BAD_REQUEST
UNAUTHORIZED
}
union FolderPoliciesResult = FolderPoliciesError | FolderPoliciesSuccess
type FolderPoliciesSuccess {
policies: [FolderPolicy!]!
}
type FolderPolicy {
action: FolderPolicyAction!
afterDays: Int!
createdAt: Date!
folder: String!
id: ID!
minimumItems: Int!
updatedAt: Date!
}
enum FolderPolicyAction {
ARCHIVE
DELETE
}
type GenerateApiKeyError {
errorCodes: [GenerateApiKeyErrorCode!]!
}
@ -1555,6 +1622,7 @@ type Mutation {
bulkAction(action: BulkActionType!, arguments: JSON, async: Boolean, expectedCount: Int, labelIds: [ID!], query: String!): BulkActionResult!
createArticle(input: CreateArticleInput!): CreateArticleResult!
createArticleSavingRequest(input: CreateArticleSavingRequestInput!): CreateArticleSavingRequestResult!
createFolderPolicy(input: CreateFolderPolicyInput!): CreateFolderPolicyResult!
createGroup(input: CreateGroupInput!): CreateGroupResult!
createHighlight(input: CreateHighlightInput!): CreateHighlightResult!
createLabel(input: CreateLabelInput!): CreateLabelResult!
@ -1563,6 +1631,7 @@ type Mutation {
deleteDiscoverArticle(input: DeleteDiscoverArticleInput!): DeleteDiscoverArticleResult!
deleteDiscoverFeed(input: DeleteDiscoverFeedInput!): DeleteDiscoverFeedResult!
deleteFilter(id: ID!): DeleteFilterResult!
deleteFolderPolicy(id: ID!): DeleteFolderPolicyResult!
deleteHighlight(highlightId: ID!): DeleteHighlightResult!
deleteIntegration(id: ID!): DeleteIntegrationResult!
deleteLabel(id: ID!): DeleteLabelResult!
@ -1612,6 +1681,7 @@ type Mutation {
unsubscribe(name: String!, subscriptionId: ID): UnsubscribeResult!
updateEmail(input: UpdateEmailInput!): UpdateEmailResult!
updateFilter(input: UpdateFilterInput!): UpdateFilterResult!
updateFolderPolicy(input: UpdateFolderPolicyInput!): UpdateFolderPolicyResult!
updateHighlight(input: UpdateHighlightInput!): UpdateHighlightResult!
updateLabel(input: UpdateLabelInput!): UpdateLabelResult!
updateNewsletterEmail(input: UpdateNewsletterEmailInput!): UpdateNewsletterEmailResult!
@ -1754,6 +1824,7 @@ type Query {
discoverTopics: GetDiscoverTopicResults!
feeds(input: FeedsInput!): FeedsResult!
filters: FiltersResult!
folderPolicies: FolderPoliciesResult!
getDiscoverFeedArticles(after: String, discoverTopicId: String!, feedId: ID, first: Int): GetDiscoverFeedArticleResults!
getUserPersonalization: GetUserPersonalizationResult!
groups: GroupsResult!
@ -2835,6 +2906,28 @@ type UpdateFilterSuccess {
filter: Filter!
}
type UpdateFolderPolicyError {
errorCodes: [UpdateFolderPolicyErrorCode!]!
}
enum UpdateFolderPolicyErrorCode {
BAD_REQUEST
UNAUTHORIZED
}
input UpdateFolderPolicyInput {
action: FolderPolicyAction
afterDays: Int
id: ID!
minimumItems: Int
}
union UpdateFolderPolicyResult = UpdateFolderPolicyError | UpdateFolderPolicySuccess
type UpdateFolderPolicySuccess {
policy: FolderPolicy!
}
type UpdateHighlightError {
errorCodes: [UpdateHighlightErrorCode!]!
}

View file

@ -0,0 +1,23 @@
import { FolderPolicy } from '../../entity/folder_policy'
import {
FolderPoliciesError,
FolderPoliciesSuccess,
} from '../../generated/graphql'
import { findFolderPoliciesByUserId } from '../../services/folder_policy'
import { Merge } from '../../util'
import { authorized } from '../../utils/gql-utils'
type PartialFolderPoliciesSuccess = Merge<
FolderPoliciesSuccess,
{ policies: FolderPolicy[] }
>
export const folderPoliciesResolver = authorized<
PartialFolderPoliciesSuccess,
FolderPoliciesError
>(async (_, __, { uid }) => {
const policies = await findFolderPoliciesByUserId(uid)
return {
policies,
}
})

View file

@ -5,6 +5,7 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { createHmac } from 'crypto'
import { isError } from 'lodash'
import { FolderPolicy } from '../entity/folder_policy'
import { Highlight } from '../entity/highlight'
import { LibraryItem } from '../entity/library_item'
import {
@ -52,6 +53,7 @@ import {
saveDiscoverArticleResolver,
} from './discover_feeds'
import { optInFeatureResolver } from './features'
import { folderPoliciesResolver } from './folder_policy'
import { highlightsResolver } from './highlight'
import {
hiddenHomeSectionResolver,
@ -342,6 +344,7 @@ export const functionResolvers = {
subscription: subscriptionResolver,
hiddenHomeSection: hiddenHomeSectionResolver,
highlights: highlightsResolver,
folderPolicies: folderPoliciesResolver,
},
User: {
async intercomHash(user: User) {
@ -880,4 +883,5 @@ export const functionResolvers = {
...resultResolveTypeResolver('RefreshHome'),
...resultResolveTypeResolver('HiddenHomeSection'),
...resultResolveTypeResolver('Highlights'),
...resultResolveTypeResolver('FolderPolicies'),
}

View file

@ -3247,6 +3247,101 @@ const schema = gql`
BAD_REQUEST
}
type FolderPolicy {
id: ID!
folder: String!
action: FolderPolicyAction!
afterDays: Int!
minimumItems: Int!
createdAt: Date!
updatedAt: Date!
}
enum FolderPolicyAction {
ARCHIVE
DELETE
}
union FolderPoliciesResult = FolderPoliciesSuccess | FolderPoliciesError
type FolderPoliciesSuccess {
policies: [FolderPolicy!]!
}
type FolderPoliciesError {
errorCodes: [FolderPoliciesErrorCode!]!
}
enum FolderPoliciesErrorCode {
UNAUTHORIZED
BAD_REQUEST
}
input CreateFolderPolicyInput {
folder: String! @sanitize(minLength: 1, maxLength: 255)
action: FolderPolicyAction!
afterDays: Int!
minimumItems: Int
}
union CreateFolderPolicyResult =
CreateFolderPolicySuccess
| CreateFolderPolicyError
type CreateFolderPolicySuccess {
policy: FolderPolicy!
}
type CreateFolderPolicyError {
errorCodes: [CreateFolderPolicyErrorCode!]!
}
enum CreateFolderPolicyErrorCode {
UNAUTHORIZED
BAD_REQUEST
}
union DeleteFolderPolicyResult =
DeleteFolderPolicySuccess
| DeleteFolderPolicyError
type DeleteFolderPolicySuccess {
success: Boolean!
}
type DeleteFolderPolicyError {
errorCodes: [DeleteFolderPolicyErrorCode!]!
}
enum DeleteFolderPolicyErrorCode {
UNAUTHORIZED
BAD_REQUEST
}
union UpdateFolderPolicyResult =
UpdateFolderPolicySuccess
| UpdateFolderPolicyError
type UpdateFolderPolicySuccess {
policy: FolderPolicy!
}
type UpdateFolderPolicyError {
errorCodes: [UpdateFolderPolicyErrorCode!]!
}
enum UpdateFolderPolicyErrorCode {
UNAUTHORIZED
BAD_REQUEST
}
input UpdateFolderPolicyInput {
id: ID!
action: FolderPolicyAction
afterDays: Int
minimumItems: Int
}
# Mutations
type Mutation {
googleLogin(input: GoogleLoginInput!): LoginResult!
@ -3373,6 +3468,13 @@ const schema = gql`
editDiscoverFeed(input: EditDiscoverFeedInput!): EditDiscoverFeedResult!
emptyTrash: EmptyTrashResult!
refreshHome: RefreshHomeResult!
createFolderPolicy(
input: CreateFolderPolicyInput!
): CreateFolderPolicyResult!
updateFolderPolicy(
input: UpdateFolderPolicyInput!
): UpdateFolderPolicyResult!
deleteFolderPolicy(id: ID!): DeleteFolderPolicyResult!
}
# FIXME: remove sort from feedArticles after all cached tabs are closed
@ -3447,6 +3549,7 @@ const schema = gql`
subscription(id: ID!): SubscriptionResult!
hiddenHomeSection: HiddenHomeSectionResult!
highlights(after: String, first: Int, query: String): HighlightsResult!
folderPolicies: FolderPoliciesResult!
}
schema {

View file

@ -0,0 +1,38 @@
import { FolderPolicy, FolderPolicyAction } from '../entity/folder_policy'
import { getRepository } from '../repository'
export const createFolderPolicy = async (folderPolicy: {
userId: string
folder: string
action: FolderPolicyAction
afterDays: number
minimumItems: number
}) => {
return getRepository(FolderPolicy).save(folderPolicy)
}
export const findFolderPoliciesByUserId = async (userId: string) => {
return getRepository(FolderPolicy).find({
where: { userId },
order: { folder: 'ASC' },
})
}
export const updateFolderPolicy = async (
id: string,
update: Partial<FolderPolicy>
) => {
return getRepository(FolderPolicy).update(id, update)
}
export const deleteFolderPolicy = async (id: string) => {
return getRepository(FolderPolicy).delete(id)
}
export const findFolderPolicies = async () => {
return getRepository(FolderPolicy).find()
}
export const findFolderPolicyById = async (id: string) => {
return getRepository(FolderPolicy).findOneBy({ id })
}

View file

@ -0,0 +1,59 @@
import { FolderPolicyAction } from '../../src/entity/folder_policy'
import { User } from '../../src/entity/user'
import { createFolderPolicy } from '../../src/services/folder_policy'
import { deleteUser } from '../../src/services/user'
import { createTestUser } from '../db'
import { graphqlRequest, loginAndGetAuthToken } from '../util'
import { expect } from 'chai'
describe('Folder Policy API', () => {
let loginUser: User
let authToken: string
before(async () => {
// create test user and login
loginUser = await createTestUser('loginUser')
authToken = await loginAndGetAuthToken(loginUser.email)
})
after(async () => {
await deleteUser(loginUser.id)
})
describe('List Folder Policy', () => {
const query = `
query {
folderPolicies {
... on FolderPoliciesSuccess {
policies {
id
folder
action
createdAt
updatedAt
}
}
... on FolderPoliciesError {
errorCodes
}
}
}
`
it('should return a list of folder policy of the user', async () => {
const existingPolicy = await createFolderPolicy({
userId: loginUser.id,
folder: 'test-folder',
action: FolderPolicyAction.ARCHIVE,
afterDays: 30,
minimumItems: 10,
})
const res = await graphqlRequest(query, authToken).expect(200)
const policies = res.body.data.folderPolicies.policies as any[]
expect(policies).to.have.lengthOf(1)
expect(policies[0].id).to.equal(existingPolicy.id)
})
})
})

View file

@ -60,3 +60,11 @@ export const generateFakeUuid = () => {
export const generateFakeShortId = () => {
return nanoid(8)
}
export const loginAndGetAuthToken = async (email: string) => {
const res = await request
.post('/local/debug/fake-user-login')
.send({ fakeEmail: email })
return res.body.authToken as string
}

View file

@ -4,15 +4,18 @@
BEGIN;
CREATE TYPE folder_action AS ENUM ('DELETE', 'ARCHIVE');
CREATE TABLE omnivore.folder_policy (
id UUID PRIMARY KEY DEFAULT uuid_generate_v1mc(),
user_id UUID NOT NULL REFERENCES omnivore.user(id) ON DELETE CASCADE,
folder TEXT NOT NULL, -- folder name in lowercase
action TEXT NOT NULL, -- delete or archive
action folder_action NOT NULL, -- delete or archive
after_days INT NOT NULL, -- number of days after which the action should be taken
minimum_items INT NOT NULL DEFAULT 0, -- minimum number of items to keep in the folder
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE (user_id, folder) -- only one policy per folder per user
);
CREATE TRIGGER update_folder_policy_modtime BEFORE UPDATE ON omnivore.folder_policy FOR EACH ROW EXECUTE PROCEDURE update_updated_at_column();

View file

@ -6,4 +6,6 @@ BEGIN;
DROP TABLE omnivore.folder_policy;
DROP TYPE folder_action;
COMMIT;