@grantjs/schema 1.19.0 → 1.20.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/events/event-catalog.ts +3 -0
- package/src/generated/graphql.ts +144 -0
- package/src/generated/resolvers.ts +74 -0
- package/src/generated/schema-types.ts +95 -0
- package/src/operations/project-users/exportProjectUserCredentials.graphql +11 -0
- package/src/operations/users/setProjectUserPassword.graphql +9 -0
- package/src/schema/project-users/inputs/export-project-user-credentials.graphql +8 -0
- package/src/schema/project-users/queries/export-project-user-credentials.graphql +12 -0
- package/src/schema/project-users/types/credential-kind.graphql +8 -0
- package/src/schema/project-users/types/project-user-credential-export.graphql +22 -0
- package/src/schema/project-users/types/project-user-password-credential.graphql +14 -0
- package/src/schema/users/inputs/set-project-user-password.graphql +9 -0
- package/src/schema/users/mutations/set-project-user-password.graphql +10 -0
- package/src/schema/users/types/user.graphql +7 -0
- package/src/sdl-contract.test.ts +9 -2
package/package.json
CHANGED
|
@@ -152,6 +152,7 @@ export const EVENT_TYPES = [
|
|
|
152
152
|
'user.deleted',
|
|
153
153
|
'project.user_updated',
|
|
154
154
|
'project.user_email_changed',
|
|
155
|
+
'project.user_password_set',
|
|
155
156
|
'api_key.deleted',
|
|
156
157
|
'tag.created',
|
|
157
158
|
'tag.updated',
|
|
@@ -228,6 +229,8 @@ export const EVENT_CATALOG: Readonly<Record<EventType, EventCatalogEntry>> = {
|
|
|
228
229
|
'user.deleted': webhookOnly('membership'),
|
|
229
230
|
'project.user_updated': webhookOnly('membership'),
|
|
230
231
|
'project.user_email_changed': webhookOnly('membership'),
|
|
232
|
+
// Every project-credential write that changes the stored hash, any source. data.after = { projectId, userId, source }: never a hash or a password.
|
|
233
|
+
'project.user_password_set': webhookOnly('membership'),
|
|
231
234
|
'api_key.deleted': webhookOnly('security'),
|
|
232
235
|
'tag.created': webhookOnly('iam'),
|
|
233
236
|
'tag.updated': webhookOnly('iam'),
|
package/src/generated/graphql.ts
CHANGED
|
@@ -1310,6 +1310,16 @@ export type UpsertProjectOAuthConnectionMutation = {
|
|
|
1310
1310
|
};
|
|
1311
1311
|
};
|
|
1312
1312
|
|
|
1313
|
+
export type ExportProjectUserCredentialsQueryVariables = Exact<{
|
|
1314
|
+
input: Types.ExportProjectUserCredentialsInput;
|
|
1315
|
+
}>;
|
|
1316
|
+
|
|
1317
|
+
export type ExportProjectUserCredentialsQuery = {
|
|
1318
|
+
exportProjectUserCredentials: {
|
|
1319
|
+
users: Array<{ userId: string; password: { algorithm: string; hash: string } | null }>;
|
|
1320
|
+
};
|
|
1321
|
+
};
|
|
1322
|
+
|
|
1313
1323
|
export type CancelProjectSyncMutationVariables = Exact<{
|
|
1314
1324
|
id: string | number;
|
|
1315
1325
|
scope: Types.Scope;
|
|
@@ -2188,6 +2198,20 @@ export type SetProjectUserEmailMutation = {
|
|
|
2188
2198
|
};
|
|
2189
2199
|
};
|
|
2190
2200
|
|
|
2201
|
+
export type SetProjectUserPasswordMutationVariables = Exact<{
|
|
2202
|
+
input: Types.SetProjectUserPasswordInput;
|
|
2203
|
+
}>;
|
|
2204
|
+
|
|
2205
|
+
export type SetProjectUserPasswordMutation = {
|
|
2206
|
+
setProjectUserPassword: {
|
|
2207
|
+
id: string;
|
|
2208
|
+
name: string;
|
|
2209
|
+
metadata: Record<string, unknown>;
|
|
2210
|
+
createdAt: Date;
|
|
2211
|
+
updatedAt: Date;
|
|
2212
|
+
};
|
|
2213
|
+
};
|
|
2214
|
+
|
|
2191
2215
|
export type UpdateUserMutationVariables = Exact<{
|
|
2192
2216
|
id: string | number;
|
|
2193
2217
|
input: Types.UpdateUserInput;
|
|
@@ -7467,6 +7491,74 @@ export const UpsertProjectOAuthConnectionDocument = {
|
|
|
7467
7491
|
UpsertProjectOAuthConnectionMutation,
|
|
7468
7492
|
UpsertProjectOAuthConnectionMutationVariables
|
|
7469
7493
|
>;
|
|
7494
|
+
export const ExportProjectUserCredentialsDocument = {
|
|
7495
|
+
kind: 'Document',
|
|
7496
|
+
definitions: [
|
|
7497
|
+
{
|
|
7498
|
+
kind: 'OperationDefinition',
|
|
7499
|
+
operation: 'query',
|
|
7500
|
+
name: { kind: 'Name', value: 'ExportProjectUserCredentials' },
|
|
7501
|
+
variableDefinitions: [
|
|
7502
|
+
{
|
|
7503
|
+
kind: 'VariableDefinition',
|
|
7504
|
+
variable: { kind: 'Variable', name: { kind: 'Name', value: 'input' } },
|
|
7505
|
+
type: {
|
|
7506
|
+
kind: 'NonNullType',
|
|
7507
|
+
type: {
|
|
7508
|
+
kind: 'NamedType',
|
|
7509
|
+
name: { kind: 'Name', value: 'ExportProjectUserCredentialsInput' },
|
|
7510
|
+
},
|
|
7511
|
+
},
|
|
7512
|
+
},
|
|
7513
|
+
],
|
|
7514
|
+
selectionSet: {
|
|
7515
|
+
kind: 'SelectionSet',
|
|
7516
|
+
selections: [
|
|
7517
|
+
{
|
|
7518
|
+
kind: 'Field',
|
|
7519
|
+
name: { kind: 'Name', value: 'exportProjectUserCredentials' },
|
|
7520
|
+
arguments: [
|
|
7521
|
+
{
|
|
7522
|
+
kind: 'Argument',
|
|
7523
|
+
name: { kind: 'Name', value: 'input' },
|
|
7524
|
+
value: { kind: 'Variable', name: { kind: 'Name', value: 'input' } },
|
|
7525
|
+
},
|
|
7526
|
+
],
|
|
7527
|
+
selectionSet: {
|
|
7528
|
+
kind: 'SelectionSet',
|
|
7529
|
+
selections: [
|
|
7530
|
+
{
|
|
7531
|
+
kind: 'Field',
|
|
7532
|
+
name: { kind: 'Name', value: 'users' },
|
|
7533
|
+
selectionSet: {
|
|
7534
|
+
kind: 'SelectionSet',
|
|
7535
|
+
selections: [
|
|
7536
|
+
{ kind: 'Field', name: { kind: 'Name', value: 'userId' } },
|
|
7537
|
+
{
|
|
7538
|
+
kind: 'Field',
|
|
7539
|
+
name: { kind: 'Name', value: 'password' },
|
|
7540
|
+
selectionSet: {
|
|
7541
|
+
kind: 'SelectionSet',
|
|
7542
|
+
selections: [
|
|
7543
|
+
{ kind: 'Field', name: { kind: 'Name', value: 'algorithm' } },
|
|
7544
|
+
{ kind: 'Field', name: { kind: 'Name', value: 'hash' } },
|
|
7545
|
+
],
|
|
7546
|
+
},
|
|
7547
|
+
},
|
|
7548
|
+
],
|
|
7549
|
+
},
|
|
7550
|
+
},
|
|
7551
|
+
],
|
|
7552
|
+
},
|
|
7553
|
+
},
|
|
7554
|
+
],
|
|
7555
|
+
},
|
|
7556
|
+
},
|
|
7557
|
+
],
|
|
7558
|
+
} as unknown as DocumentNode<
|
|
7559
|
+
ExportProjectUserCredentialsQuery,
|
|
7560
|
+
ExportProjectUserCredentialsQueryVariables
|
|
7561
|
+
>;
|
|
7470
7562
|
export const CancelProjectSyncDocument = {
|
|
7471
7563
|
kind: 'Document',
|
|
7472
7564
|
definitions: [
|
|
@@ -11215,6 +11307,58 @@ export const SetProjectUserEmailDocument = {
|
|
|
11215
11307
|
},
|
|
11216
11308
|
],
|
|
11217
11309
|
} as unknown as DocumentNode<SetProjectUserEmailMutation, SetProjectUserEmailMutationVariables>;
|
|
11310
|
+
export const SetProjectUserPasswordDocument = {
|
|
11311
|
+
kind: 'Document',
|
|
11312
|
+
definitions: [
|
|
11313
|
+
{
|
|
11314
|
+
kind: 'OperationDefinition',
|
|
11315
|
+
operation: 'mutation',
|
|
11316
|
+
name: { kind: 'Name', value: 'SetProjectUserPassword' },
|
|
11317
|
+
variableDefinitions: [
|
|
11318
|
+
{
|
|
11319
|
+
kind: 'VariableDefinition',
|
|
11320
|
+
variable: { kind: 'Variable', name: { kind: 'Name', value: 'input' } },
|
|
11321
|
+
type: {
|
|
11322
|
+
kind: 'NonNullType',
|
|
11323
|
+
type: {
|
|
11324
|
+
kind: 'NamedType',
|
|
11325
|
+
name: { kind: 'Name', value: 'SetProjectUserPasswordInput' },
|
|
11326
|
+
},
|
|
11327
|
+
},
|
|
11328
|
+
},
|
|
11329
|
+
],
|
|
11330
|
+
selectionSet: {
|
|
11331
|
+
kind: 'SelectionSet',
|
|
11332
|
+
selections: [
|
|
11333
|
+
{
|
|
11334
|
+
kind: 'Field',
|
|
11335
|
+
name: { kind: 'Name', value: 'setProjectUserPassword' },
|
|
11336
|
+
arguments: [
|
|
11337
|
+
{
|
|
11338
|
+
kind: 'Argument',
|
|
11339
|
+
name: { kind: 'Name', value: 'input' },
|
|
11340
|
+
value: { kind: 'Variable', name: { kind: 'Name', value: 'input' } },
|
|
11341
|
+
},
|
|
11342
|
+
],
|
|
11343
|
+
selectionSet: {
|
|
11344
|
+
kind: 'SelectionSet',
|
|
11345
|
+
selections: [
|
|
11346
|
+
{ kind: 'Field', name: { kind: 'Name', value: 'id' } },
|
|
11347
|
+
{ kind: 'Field', name: { kind: 'Name', value: 'name' } },
|
|
11348
|
+
{ kind: 'Field', name: { kind: 'Name', value: 'metadata' } },
|
|
11349
|
+
{ kind: 'Field', name: { kind: 'Name', value: 'createdAt' } },
|
|
11350
|
+
{ kind: 'Field', name: { kind: 'Name', value: 'updatedAt' } },
|
|
11351
|
+
],
|
|
11352
|
+
},
|
|
11353
|
+
},
|
|
11354
|
+
],
|
|
11355
|
+
},
|
|
11356
|
+
},
|
|
11357
|
+
],
|
|
11358
|
+
} as unknown as DocumentNode<
|
|
11359
|
+
SetProjectUserPasswordMutation,
|
|
11360
|
+
SetProjectUserPasswordMutationVariables
|
|
11361
|
+
>;
|
|
11218
11362
|
export const UpdateUserDocument = {
|
|
11219
11363
|
kind: 'Document',
|
|
11220
11364
|
definitions: [
|
|
@@ -271,6 +271,7 @@ export type ResolversTypes = ResolversObject<{
|
|
|
271
271
|
CreateUserSessionInput: Types.CreateUserSessionInput;
|
|
272
272
|
CreateWebhookSubscriptionMutationInput: Types.CreateWebhookSubscriptionMutationInput;
|
|
273
273
|
CredentialExportData: ResolverTypeWrapper<Types.CredentialExportData>;
|
|
274
|
+
CredentialKind: Types.CredentialKind;
|
|
274
275
|
Date: ResolverTypeWrapper<Types.Scalars['Date']['output']>;
|
|
275
276
|
DeleteApiKeyInput: Types.DeleteApiKeyInput;
|
|
276
277
|
DeleteMyAccountsInput: Types.DeleteMyAccountsInput;
|
|
@@ -281,6 +282,9 @@ export type ResolversTypes = ResolversObject<{
|
|
|
281
282
|
EmailVerificationProofType: Types.EmailVerificationProofType;
|
|
282
283
|
ExchangeApiKeyInput: Types.ExchangeApiKeyInput;
|
|
283
284
|
ExchangeApiKeyResult: ResolverTypeWrapper<Types.ExchangeApiKeyResult>;
|
|
285
|
+
ExportProjectUserCredentialsInput: Types.ExportProjectUserCredentialsInput;
|
|
286
|
+
ExportedPasswordCredential: ResolverTypeWrapper<Types.ExportedPasswordCredential>;
|
|
287
|
+
ExportedProjectUserCredential: ResolverTypeWrapper<Types.ExportedProjectUserCredential>;
|
|
284
288
|
GenerateMyMfaRecoveryCodesInput: Types.GenerateMyMfaRecoveryCodesInput;
|
|
285
289
|
GetUserAuthenticationMethodsInput: Types.GetUserAuthenticationMethodsInput;
|
|
286
290
|
GetUserSessionsInput: Types.GetUserSessionsInput;
|
|
@@ -385,7 +389,9 @@ export type ResolversTypes = ResolversObject<{
|
|
|
385
389
|
ProjectTag: ResolverTypeWrapper<Types.ProjectTag>;
|
|
386
390
|
ProjectUser: ResolverTypeWrapper<Types.ProjectUser>;
|
|
387
391
|
ProjectUserApiKey: ResolverTypeWrapper<Types.ProjectUserApiKey>;
|
|
392
|
+
ProjectUserCredentialExport: ResolverTypeWrapper<Types.ProjectUserCredentialExport>;
|
|
388
393
|
ProjectUserGroup: ResolverTypeWrapper<Types.ProjectUserGroup>;
|
|
394
|
+
ProjectUserPasswordCredential: ResolverTypeWrapper<Types.ProjectUserPasswordCredential>;
|
|
389
395
|
ProjectUserPermission: ResolverTypeWrapper<Types.ProjectUserPermission>;
|
|
390
396
|
Query: ResolverTypeWrapper<Record<PropertyKey, never>>;
|
|
391
397
|
QueryAccountProjectApiKeysInput: Types.QueryAccountProjectApiKeysInput;
|
|
@@ -502,6 +508,7 @@ export type ResolversTypes = ResolversObject<{
|
|
|
502
508
|
SetMyNotificationPreferenceInput: Types.SetMyNotificationPreferenceInput;
|
|
503
509
|
SetMyPrimaryMfaDeviceInput: Types.SetMyPrimaryMfaDeviceInput;
|
|
504
510
|
SetProjectUserEmailInput: Types.SetProjectUserEmailInput;
|
|
511
|
+
SetProjectUserPasswordInput: Types.SetProjectUserPasswordInput;
|
|
505
512
|
SigningKey: ResolverTypeWrapper<Types.SigningKey>;
|
|
506
513
|
SortOrder: Types.SortOrder;
|
|
507
514
|
StartProjectExportInput: Types.StartProjectExportInput;
|
|
@@ -692,6 +699,9 @@ export type ResolversParentTypes = ResolversObject<{
|
|
|
692
699
|
EmailVerificationProofInput: Types.EmailVerificationProofInput;
|
|
693
700
|
ExchangeApiKeyInput: Types.ExchangeApiKeyInput;
|
|
694
701
|
ExchangeApiKeyResult: Types.ExchangeApiKeyResult;
|
|
702
|
+
ExportProjectUserCredentialsInput: Types.ExportProjectUserCredentialsInput;
|
|
703
|
+
ExportedPasswordCredential: Types.ExportedPasswordCredential;
|
|
704
|
+
ExportedProjectUserCredential: Types.ExportedProjectUserCredential;
|
|
695
705
|
GenerateMyMfaRecoveryCodesInput: Types.GenerateMyMfaRecoveryCodesInput;
|
|
696
706
|
GetUserAuthenticationMethodsInput: Types.GetUserAuthenticationMethodsInput;
|
|
697
707
|
GetUserSessionsInput: Types.GetUserSessionsInput;
|
|
@@ -772,7 +782,9 @@ export type ResolversParentTypes = ResolversObject<{
|
|
|
772
782
|
ProjectTag: Types.ProjectTag;
|
|
773
783
|
ProjectUser: Types.ProjectUser;
|
|
774
784
|
ProjectUserApiKey: Types.ProjectUserApiKey;
|
|
785
|
+
ProjectUserCredentialExport: Types.ProjectUserCredentialExport;
|
|
775
786
|
ProjectUserGroup: Types.ProjectUserGroup;
|
|
787
|
+
ProjectUserPasswordCredential: Types.ProjectUserPasswordCredential;
|
|
776
788
|
ProjectUserPermission: Types.ProjectUserPermission;
|
|
777
789
|
Query: Record<PropertyKey, never>;
|
|
778
790
|
QueryAccountProjectApiKeysInput: Types.QueryAccountProjectApiKeysInput;
|
|
@@ -885,6 +897,7 @@ export type ResolversParentTypes = ResolversObject<{
|
|
|
885
897
|
SetMyNotificationPreferenceInput: Types.SetMyNotificationPreferenceInput;
|
|
886
898
|
SetMyPrimaryMfaDeviceInput: Types.SetMyPrimaryMfaDeviceInput;
|
|
887
899
|
SetProjectUserEmailInput: Types.SetProjectUserEmailInput;
|
|
900
|
+
SetProjectUserPasswordInput: Types.SetProjectUserPasswordInput;
|
|
888
901
|
SigningKey: Types.SigningKey;
|
|
889
902
|
StartProjectExportInput: Types.StartProjectExportInput;
|
|
890
903
|
String: Types.Scalars['String']['output'];
|
|
@@ -1325,6 +1338,28 @@ export type ExchangeApiKeyResultResolvers<
|
|
|
1325
1338
|
expiresIn?: Resolver<ResolversTypes['Int'], ParentType, ContextType>;
|
|
1326
1339
|
}>;
|
|
1327
1340
|
|
|
1341
|
+
export type ExportedPasswordCredentialResolvers<
|
|
1342
|
+
ContextType = any,
|
|
1343
|
+
ParentType extends ResolversParentTypes['ExportedPasswordCredential'] =
|
|
1344
|
+
ResolversParentTypes['ExportedPasswordCredential'],
|
|
1345
|
+
> = ResolversObject<{
|
|
1346
|
+
algorithm?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
|
|
1347
|
+
hash?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
|
|
1348
|
+
}>;
|
|
1349
|
+
|
|
1350
|
+
export type ExportedProjectUserCredentialResolvers<
|
|
1351
|
+
ContextType = any,
|
|
1352
|
+
ParentType extends ResolversParentTypes['ExportedProjectUserCredential'] =
|
|
1353
|
+
ResolversParentTypes['ExportedProjectUserCredential'],
|
|
1354
|
+
> = ResolversObject<{
|
|
1355
|
+
password?: Resolver<
|
|
1356
|
+
Types.Maybe<ResolversTypes['ExportedPasswordCredential']>,
|
|
1357
|
+
ParentType,
|
|
1358
|
+
ContextType
|
|
1359
|
+
>;
|
|
1360
|
+
userId?: Resolver<ResolversTypes['ID'], ParentType, ContextType>;
|
|
1361
|
+
}>;
|
|
1362
|
+
|
|
1328
1363
|
export type GroupResolvers<
|
|
1329
1364
|
ContextType = any,
|
|
1330
1365
|
ParentType extends ResolversParentTypes['Group'] = ResolversParentTypes['Group'],
|
|
@@ -1968,6 +2003,12 @@ export type MutationResolvers<
|
|
|
1968
2003
|
ContextType,
|
|
1969
2004
|
RequireFields<Types.MutationSetProjectUserEmailArgs, 'input'>
|
|
1970
2005
|
>;
|
|
2006
|
+
setProjectUserPassword?: Resolver<
|
|
2007
|
+
ResolversTypes['User'],
|
|
2008
|
+
ParentType,
|
|
2009
|
+
ContextType,
|
|
2010
|
+
RequireFields<Types.MutationSetProjectUserPasswordArgs, 'input'>
|
|
2011
|
+
>;
|
|
1971
2012
|
setupMfa?: Resolver<ResolversTypes['MfaSetupResponse'], ParentType, ContextType>;
|
|
1972
2013
|
startProjectExport?: Resolver<
|
|
1973
2014
|
ResolversTypes['ProjectSyncJob'],
|
|
@@ -2846,6 +2887,14 @@ export type ProjectUserApiKeyResolvers<
|
|
|
2846
2887
|
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
|
2847
2888
|
}>;
|
|
2848
2889
|
|
|
2890
|
+
export type ProjectUserCredentialExportResolvers<
|
|
2891
|
+
ContextType = any,
|
|
2892
|
+
ParentType extends ResolversParentTypes['ProjectUserCredentialExport'] =
|
|
2893
|
+
ResolversParentTypes['ProjectUserCredentialExport'],
|
|
2894
|
+
> = ResolversObject<{
|
|
2895
|
+
users?: Resolver<Array<ResolversTypes['ExportedProjectUserCredential']>, ParentType, ContextType>;
|
|
2896
|
+
}>;
|
|
2897
|
+
|
|
2849
2898
|
export type ProjectUserGroupResolvers<
|
|
2850
2899
|
ContextType = any,
|
|
2851
2900
|
ParentType extends ResolversParentTypes['ProjectUserGroup'] =
|
|
@@ -2861,6 +2910,16 @@ export type ProjectUserGroupResolvers<
|
|
|
2861
2910
|
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
|
2862
2911
|
}>;
|
|
2863
2912
|
|
|
2913
|
+
export type ProjectUserPasswordCredentialResolvers<
|
|
2914
|
+
ContextType = any,
|
|
2915
|
+
ParentType extends ResolversParentTypes['ProjectUserPasswordCredential'] =
|
|
2916
|
+
ResolversParentTypes['ProjectUserPasswordCredential'],
|
|
2917
|
+
> = ResolversObject<{
|
|
2918
|
+
fingerprint?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
|
|
2919
|
+
source?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
|
|
2920
|
+
updatedAt?: Resolver<ResolversTypes['Date'], ParentType, ContextType>;
|
|
2921
|
+
}>;
|
|
2922
|
+
|
|
2864
2923
|
export type ProjectUserPermissionResolvers<
|
|
2865
2924
|
ContextType = any,
|
|
2866
2925
|
ParentType extends ResolversParentTypes['ProjectUserPermission'] =
|
|
@@ -2888,6 +2947,12 @@ export type QueryResolvers<
|
|
|
2888
2947
|
RequireFields<Types.QueryApiKeysArgs, 'scope'>
|
|
2889
2948
|
>;
|
|
2890
2949
|
authSignupPolicy?: Resolver<ResolversTypes['AuthSignupPolicy'], ParentType, ContextType>;
|
|
2950
|
+
exportProjectUserCredentials?: Resolver<
|
|
2951
|
+
ResolversTypes['ProjectUserCredentialExport'],
|
|
2952
|
+
ParentType,
|
|
2953
|
+
ContextType,
|
|
2954
|
+
RequireFields<Types.QueryExportProjectUserCredentialsArgs, 'input'>
|
|
2955
|
+
>;
|
|
2891
2956
|
groups?: Resolver<
|
|
2892
2957
|
ResolversTypes['GroupPage'],
|
|
2893
2958
|
ParentType,
|
|
@@ -3445,6 +3510,11 @@ export type UserResolvers<
|
|
|
3445
3510
|
id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>;
|
|
3446
3511
|
metadata?: Resolver<ResolversTypes['JSON'], ParentType, ContextType>;
|
|
3447
3512
|
name?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
|
|
3513
|
+
passwordCredential?: Resolver<
|
|
3514
|
+
Types.Maybe<ResolversTypes['ProjectUserPasswordCredential']>,
|
|
3515
|
+
ParentType,
|
|
3516
|
+
ContextType
|
|
3517
|
+
>;
|
|
3448
3518
|
permissionCount?: Resolver<ResolversTypes['Int'], ParentType, ContextType>;
|
|
3449
3519
|
pictureUrl?: Resolver<Types.Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
|
3450
3520
|
primaryTag?: Resolver<Types.Maybe<ResolversTypes['Tag']>, ParentType, ContextType>;
|
|
@@ -3766,6 +3836,8 @@ export type Resolvers<ContextType = any> = ResolversObject<{
|
|
|
3766
3836
|
CredentialExportData?: CredentialExportDataResolvers<ContextType>;
|
|
3767
3837
|
Date?: GraphQLScalarType;
|
|
3768
3838
|
ExchangeApiKeyResult?: ExchangeApiKeyResultResolvers<ContextType>;
|
|
3839
|
+
ExportedPasswordCredential?: ExportedPasswordCredentialResolvers<ContextType>;
|
|
3840
|
+
ExportedProjectUserCredential?: ExportedProjectUserCredentialResolvers<ContextType>;
|
|
3769
3841
|
Group?: GroupResolvers<ContextType>;
|
|
3770
3842
|
GroupPage?: GroupPageResolvers<ContextType>;
|
|
3771
3843
|
GroupPermission?: GroupPermissionResolvers<ContextType>;
|
|
@@ -3824,7 +3896,9 @@ export type Resolvers<ContextType = any> = ResolversObject<{
|
|
|
3824
3896
|
ProjectTag?: ProjectTagResolvers<ContextType>;
|
|
3825
3897
|
ProjectUser?: ProjectUserResolvers<ContextType>;
|
|
3826
3898
|
ProjectUserApiKey?: ProjectUserApiKeyResolvers<ContextType>;
|
|
3899
|
+
ProjectUserCredentialExport?: ProjectUserCredentialExportResolvers<ContextType>;
|
|
3827
3900
|
ProjectUserGroup?: ProjectUserGroupResolvers<ContextType>;
|
|
3901
|
+
ProjectUserPasswordCredential?: ProjectUserPasswordCredentialResolvers<ContextType>;
|
|
3828
3902
|
ProjectUserPermission?: ProjectUserPermissionResolvers<ContextType>;
|
|
3829
3903
|
Query?: QueryResolvers<ContextType>;
|
|
3830
3904
|
RefreshSessionResponse?: RefreshSessionResponseResolvers<ContextType>;
|
|
@@ -808,6 +808,15 @@ export type CredentialExportData = {
|
|
|
808
808
|
updatedAt: Scalars['Date']['output'];
|
|
809
809
|
};
|
|
810
810
|
|
|
811
|
+
/**
|
|
812
|
+
* A kind of credential that can be exported. Extensible: a later kind is added here,
|
|
813
|
+
* not as a second export.
|
|
814
|
+
*/
|
|
815
|
+
export enum CredentialKind {
|
|
816
|
+
/** The project password credential (bcrypt hash). */
|
|
817
|
+
Password = 'PASSWORD',
|
|
818
|
+
}
|
|
819
|
+
|
|
811
820
|
export type DeleteApiKeyInput = {
|
|
812
821
|
hardDelete?: InputMaybe<Scalars['Boolean']['input']>;
|
|
813
822
|
id: Scalars['ID']['input'];
|
|
@@ -853,6 +862,31 @@ export type ExchangeApiKeyResult = {
|
|
|
853
862
|
expiresIn: Scalars['Int']['output'];
|
|
854
863
|
};
|
|
855
864
|
|
|
865
|
+
export type ExportProjectUserCredentialsInput = {
|
|
866
|
+
/** Credential kinds to export. Defaults to `[PASSWORD]`. */
|
|
867
|
+
kinds?: InputMaybe<Array<CredentialKind>>;
|
|
868
|
+
/** Project scope the members belong to. */
|
|
869
|
+
scope: Scope;
|
|
870
|
+
/** Project members to export. Every id must be a member of the project, otherwise the whole call fails with not found (no partial export). */
|
|
871
|
+
userIds: Array<Scalars['ID']['input']>;
|
|
872
|
+
};
|
|
873
|
+
|
|
874
|
+
/** A stored password hash in CDM shape. Secret-equivalent: handle like a credential. */
|
|
875
|
+
export type ExportedPasswordCredential = {
|
|
876
|
+
__typename?: 'ExportedPasswordCredential';
|
|
877
|
+
/** Hash algorithm, for example `bcrypt`. */
|
|
878
|
+
algorithm: Scalars['String']['output'];
|
|
879
|
+
/** The stored hash string. */
|
|
880
|
+
hash: Scalars['String']['output'];
|
|
881
|
+
};
|
|
882
|
+
|
|
883
|
+
export type ExportedProjectUserCredential = {
|
|
884
|
+
__typename?: 'ExportedProjectUserCredential';
|
|
885
|
+
/** `null` when the member has no project password credential. */
|
|
886
|
+
password?: Maybe<ExportedPasswordCredential>;
|
|
887
|
+
userId: Scalars['ID']['output'];
|
|
888
|
+
};
|
|
889
|
+
|
|
856
890
|
export type GenerateMyMfaRecoveryCodesInput = {
|
|
857
891
|
factorId?: InputMaybe<Scalars['ID']['input']>;
|
|
858
892
|
};
|
|
@@ -1295,6 +1329,14 @@ export type Mutation = {
|
|
|
1295
1329
|
* `project.user_email_changed` carries ids only, never the address.
|
|
1296
1330
|
*/
|
|
1297
1331
|
setProjectUserEmail: User;
|
|
1332
|
+
/**
|
|
1333
|
+
* Set or replace a project member's password. Project scopes only: the operator supplies the
|
|
1334
|
+
* password, and the password policy is enforced server-side. Writes the project credential with
|
|
1335
|
+
* source `admin-set` (a later CDM import never overwrites it) and revokes the user's project-app grants.
|
|
1336
|
+
* The password is never returned, logged or carried by any event; `project.user_password_set`
|
|
1337
|
+
* carries ids and the credential source only.
|
|
1338
|
+
*/
|
|
1339
|
+
setProjectUserPassword: User;
|
|
1298
1340
|
setupMfa: MfaSetupResponse;
|
|
1299
1341
|
/**
|
|
1300
1342
|
* Enqueue an asynchronous CDM **export** job for the given project. The worker
|
|
@@ -1661,6 +1703,10 @@ export type MutationSetProjectUserEmailArgs = {
|
|
|
1661
1703
|
input: SetProjectUserEmailInput;
|
|
1662
1704
|
};
|
|
1663
1705
|
|
|
1706
|
+
export type MutationSetProjectUserPasswordArgs = {
|
|
1707
|
+
input: SetProjectUserPasswordInput;
|
|
1708
|
+
};
|
|
1709
|
+
|
|
1664
1710
|
export type MutationStartProjectExportArgs = {
|
|
1665
1711
|
id: Scalars['ID']['input'];
|
|
1666
1712
|
input: StartProjectExportInput;
|
|
@@ -2534,6 +2580,12 @@ export type ProjectUserApiKey = Auditable & {
|
|
|
2534
2580
|
userId: Scalars['ID']['output'];
|
|
2535
2581
|
};
|
|
2536
2582
|
|
|
2583
|
+
/** Result of `exportProjectUserCredentials`. This is the one place a credential hash leaves Grant. */
|
|
2584
|
+
export type ProjectUserCredentialExport = {
|
|
2585
|
+
__typename?: 'ProjectUserCredentialExport';
|
|
2586
|
+
users: Array<ExportedProjectUserCredential>;
|
|
2587
|
+
};
|
|
2588
|
+
|
|
2537
2589
|
export type ProjectUserGroup = Auditable & {
|
|
2538
2590
|
__typename?: 'ProjectUserGroup';
|
|
2539
2591
|
createdAt: Scalars['Date']['output'];
|
|
@@ -2545,6 +2597,20 @@ export type ProjectUserGroup = Auditable & {
|
|
|
2545
2597
|
userId: Scalars['ID']['output'];
|
|
2546
2598
|
};
|
|
2547
2599
|
|
|
2600
|
+
/** Non-secret facts about a user's project password credential. Never contains the hash or the password. */
|
|
2601
|
+
export type ProjectUserPasswordCredential = {
|
|
2602
|
+
__typename?: 'ProjectUserPasswordCredential';
|
|
2603
|
+
/**
|
|
2604
|
+
* Lowercase hex SHA-256 of the stored hash string. A change detector, not a secret: it lets a
|
|
2605
|
+
* caller see that the password changed without learning anything usable from it.
|
|
2606
|
+
*/
|
|
2607
|
+
fingerprint: Scalars['String']['output'];
|
|
2608
|
+
/** How the credential was written (for example `reset`, `cdm-import` or `admin-set`). A plain string: the schema has no credential-source enum. */
|
|
2609
|
+
source: Scalars['String']['output'];
|
|
2610
|
+
/** When the stored credential last changed. */
|
|
2611
|
+
updatedAt: Scalars['Date']['output'];
|
|
2612
|
+
};
|
|
2613
|
+
|
|
2548
2614
|
export type ProjectUserPermission = Auditable & {
|
|
2549
2615
|
__typename?: 'ProjectUserPermission';
|
|
2550
2616
|
createdAt: Scalars['Date']['output'];
|
|
@@ -2562,6 +2628,14 @@ export type Query = {
|
|
|
2562
2628
|
apiKeys: ApiKeyPage;
|
|
2563
2629
|
/** Public signup policy. No authentication required. */
|
|
2564
2630
|
authSignupPolicy: AuthSignupPolicy;
|
|
2631
|
+
/**
|
|
2632
|
+
* Export project members' password hashes in CDM shape, for a downstream identity mirror.
|
|
2633
|
+
* This is the one audited exception to "APIs expose only whether a password exists": it
|
|
2634
|
+
* requires `ProjectUser:ExportCredentials` (held by no standard group), every call is audited,
|
|
2635
|
+
* and it returns hashes. Any non-member in `userIds` fails the whole call; members without a
|
|
2636
|
+
* project credential are listed with `password: null`.
|
|
2637
|
+
*/
|
|
2638
|
+
exportProjectUserCredentials: ProjectUserCredentialExport;
|
|
2565
2639
|
groups: GroupPage;
|
|
2566
2640
|
invitation?: Maybe<OrganizationInvitation>;
|
|
2567
2641
|
/** Evaluate authorization for the current session or API key token. */
|
|
@@ -2630,6 +2704,10 @@ export type QueryApiKeysArgs = {
|
|
|
2630
2704
|
sort?: InputMaybe<ApiKeySortInput>;
|
|
2631
2705
|
};
|
|
2632
2706
|
|
|
2707
|
+
export type QueryExportProjectUserCredentialsArgs = {
|
|
2708
|
+
input: ExportProjectUserCredentialsInput;
|
|
2709
|
+
};
|
|
2710
|
+
|
|
2633
2711
|
export type QueryGroupsArgs = {
|
|
2634
2712
|
ids?: InputMaybe<Array<Scalars['ID']['input']>>;
|
|
2635
2713
|
limit?: InputMaybe<Scalars['Int']['input']>;
|
|
@@ -3565,6 +3643,16 @@ export type SetProjectUserEmailInput = {
|
|
|
3565
3643
|
userId: Scalars['ID']['input'];
|
|
3566
3644
|
};
|
|
3567
3645
|
|
|
3646
|
+
export type SetProjectUserPasswordInput = {
|
|
3647
|
+
/**
|
|
3648
|
+
* The new password, chosen by the operator. Project-scope only. The password policy is enforced
|
|
3649
|
+
* server-side; the value is never returned, logged or carried by any event.
|
|
3650
|
+
*/
|
|
3651
|
+
password: Scalars['String']['input'];
|
|
3652
|
+
scope: Scope;
|
|
3653
|
+
userId: Scalars['ID']['input'];
|
|
3654
|
+
};
|
|
3655
|
+
|
|
3568
3656
|
/**
|
|
3569
3657
|
* Signing key for a scope (e.g. project). Used for RS256 API key tokens; public key is exposed in JWKS.
|
|
3570
3658
|
* Only project scopes (accountProject, organizationProject) have manageable keys; system key is internal.
|
|
@@ -4135,6 +4223,13 @@ export type User = Auditable & {
|
|
|
4135
4223
|
id: Scalars['ID']['output'];
|
|
4136
4224
|
metadata: Scalars['JSON']['output'];
|
|
4137
4225
|
name: Scalars['String']['output'];
|
|
4226
|
+
/**
|
|
4227
|
+
* Non-secret facts about the user's password credential in the request's project scope. `null` outside a
|
|
4228
|
+
* project scope, when the user has no project credential there, or when the caller lacks
|
|
4229
|
+
* `ProjectUser:ExportCredentials` (never an error). `fingerprint` is the lowercase hex SHA-256 of the
|
|
4230
|
+
* stored hash string: a change detector, not a secret. The password and the hash are never returned here.
|
|
4231
|
+
*/
|
|
4232
|
+
passwordCredential?: Maybe<ProjectUserPasswordCredential>;
|
|
4138
4233
|
permissionCount: Scalars['Int']['output'];
|
|
4139
4234
|
pictureUrl?: Maybe<Scalars['String']['output']>;
|
|
4140
4235
|
primaryTag?: Maybe<Tag>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
input ExportProjectUserCredentialsInput {
|
|
2
|
+
"Project scope the members belong to."
|
|
3
|
+
scope: Scope!
|
|
4
|
+
"Project members to export. Every id must be a member of the project, otherwise the whole call fails with not found (no partial export)."
|
|
5
|
+
userIds: [ID!]!
|
|
6
|
+
"Credential kinds to export. Defaults to `[PASSWORD]`."
|
|
7
|
+
kinds: [CredentialKind!] = [PASSWORD]
|
|
8
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
extend type Query {
|
|
2
|
+
"""
|
|
3
|
+
Export project members' password hashes in CDM shape, for a downstream identity mirror.
|
|
4
|
+
This is the one audited exception to "APIs expose only whether a password exists": it
|
|
5
|
+
requires `ProjectUser:ExportCredentials` (held by no standard group), every call is audited,
|
|
6
|
+
and it returns hashes. Any non-member in `userIds` fails the whole call; members without a
|
|
7
|
+
project credential are listed with `password: null`.
|
|
8
|
+
"""
|
|
9
|
+
exportProjectUserCredentials(
|
|
10
|
+
input: ExportProjectUserCredentialsInput!
|
|
11
|
+
): ProjectUserCredentialExport!
|
|
12
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Result of `exportProjectUserCredentials`. This is the one place a credential hash leaves Grant.
|
|
3
|
+
"""
|
|
4
|
+
type ProjectUserCredentialExport {
|
|
5
|
+
users: [ExportedProjectUserCredential!]!
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
type ExportedProjectUserCredential {
|
|
9
|
+
userId: ID!
|
|
10
|
+
"`null` when the member has no project password credential."
|
|
11
|
+
password: ExportedPasswordCredential
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
"""
|
|
15
|
+
A stored password hash in CDM shape. Secret-equivalent: handle like a credential.
|
|
16
|
+
"""
|
|
17
|
+
type ExportedPasswordCredential {
|
|
18
|
+
"Hash algorithm, for example `bcrypt`."
|
|
19
|
+
algorithm: String!
|
|
20
|
+
"The stored hash string."
|
|
21
|
+
hash: String!
|
|
22
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Non-secret facts about a user's project password credential. Never contains the hash or the password.
|
|
3
|
+
"""
|
|
4
|
+
type ProjectUserPasswordCredential {
|
|
5
|
+
"How the credential was written (for example `reset`, `cdm-import` or `admin-set`). A plain string: the schema has no credential-source enum."
|
|
6
|
+
source: String!
|
|
7
|
+
"When the stored credential last changed."
|
|
8
|
+
updatedAt: Date!
|
|
9
|
+
"""
|
|
10
|
+
Lowercase hex SHA-256 of the stored hash string. A change detector, not a secret: it lets a
|
|
11
|
+
caller see that the password changed without learning anything usable from it.
|
|
12
|
+
"""
|
|
13
|
+
fingerprint: String!
|
|
14
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
input SetProjectUserPasswordInput {
|
|
2
|
+
userId: ID!
|
|
3
|
+
"""
|
|
4
|
+
The new password, chosen by the operator. Project-scope only. The password policy is enforced
|
|
5
|
+
server-side; the value is never returned, logged or carried by any event.
|
|
6
|
+
"""
|
|
7
|
+
password: String!
|
|
8
|
+
scope: Scope!
|
|
9
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
extend type Mutation {
|
|
2
|
+
"""
|
|
3
|
+
Set or replace a project member's password. Project scopes only: the operator supplies the
|
|
4
|
+
password, and the password policy is enforced server-side. Writes the project credential with
|
|
5
|
+
source `admin-set` (a later CDM import never overwrites it) and revokes the user's project-app grants.
|
|
6
|
+
The password is never returned, logged or carried by any event; `project.user_password_set`
|
|
7
|
+
carries ids and the credential source only.
|
|
8
|
+
"""
|
|
9
|
+
setProjectUserPassword(input: SetProjectUserPasswordInput!): User!
|
|
10
|
+
}
|
|
@@ -14,6 +14,13 @@ type User implements Auditable {
|
|
|
14
14
|
tagCount: Int!
|
|
15
15
|
authenticationMethods: [UserAuthenticationMethod!]
|
|
16
16
|
accounts: [Account!]
|
|
17
|
+
"""
|
|
18
|
+
Non-secret facts about the user's password credential in the request's project scope. `null` outside a
|
|
19
|
+
project scope, when the user has no project credential there, or when the caller lacks
|
|
20
|
+
`ProjectUser:ExportCredentials` (never an error). `fingerprint` is the lowercase hex SHA-256 of the
|
|
21
|
+
stored hash string: a change detector, not a secret. The password and the hash are never returned here.
|
|
22
|
+
"""
|
|
23
|
+
passwordCredential: ProjectUserPasswordCredential
|
|
17
24
|
createdAt: Date!
|
|
18
25
|
updatedAt: Date!
|
|
19
26
|
deletedAt: Date
|
package/src/sdl-contract.test.ts
CHANGED
|
@@ -52,10 +52,11 @@ describe('operation documents', () => {
|
|
|
52
52
|
// 136 after closed-install: AuthSignupPolicyDocument (publicSignupEnabled, bootstrapOpen).
|
|
53
53
|
// 137 after CDM imports by reference: RequestProjectSyncUploadUrlDocument.
|
|
54
54
|
// 138 after operator-set-email: SetProjectUserEmailDocument.
|
|
55
|
+
// 140 after operator-set-password: SetProjectUserPasswordDocument, ExportProjectUserCredentialsDocument.
|
|
55
56
|
// Updating this number is the point of the pin, not a nuisance: every change
|
|
56
57
|
// to it should be a line in a commit message.
|
|
57
58
|
it('finds every document under src/operations', () => {
|
|
58
|
-
expect(files).toHaveLength(
|
|
59
|
+
expect(files).toHaveLength(140);
|
|
59
60
|
});
|
|
60
61
|
|
|
61
62
|
it.each(files.map((f) => [relative(process.cwd(), f), f]))('%s validates', (_label, file) => {
|
|
@@ -68,7 +69,7 @@ describe('graph reachability', () => {
|
|
|
68
69
|
const schema = buildMergedSchema();
|
|
69
70
|
|
|
70
71
|
/**
|
|
71
|
-
* 175 of
|
|
72
|
+
* 175 of 389 declared types cannot be reached from Query or Mutation. They are
|
|
72
73
|
* not dead: most are consumed as generated TypeScript by apps/api, and the
|
|
73
74
|
* *SearchableField enums are runtime search configuration. But every one of them
|
|
74
75
|
* ships in the schema `makeExecutableSchema` serves.
|
|
@@ -81,6 +82,12 @@ describe('graph reachability', () => {
|
|
|
81
82
|
* Was 181 of 388 before pass 5 slice 4 removed six declarations that were
|
|
82
83
|
* unreferenced in SDL and in all TypeScript. The reachable count did not change
|
|
83
84
|
* (207 before and after), which is what makes those six safe to have deleted.
|
|
85
|
+
*
|
|
86
|
+
* operator-set-password declared seven types (382 -> 389 declared). While
|
|
87
|
+
* `passwordCredential` sat on `ProjectUser`, which no query or mutation returns,
|
|
88
|
+
* `ProjectUserPasswordCredential` was unreachable and the pin was 176. It now sits on
|
|
89
|
+
* `User`, so the type is reachable and the pin is back to 175; the other six new
|
|
90
|
+
* types are reachable through the new mutation and query.
|
|
84
91
|
*/
|
|
85
92
|
const UNREACHABLE_FROM_ROOT = 175;
|
|
86
93
|
|