Skip to content

Commit 5de03ce

Browse files
authored
add more user centric mutations to gql (#4258)
1 parent 70c567a commit 5de03ce

File tree

8 files changed

+181
-28
lines changed

8 files changed

+181
-28
lines changed

backend/native/backpack-api/src/routes/graphql/clients/hasura.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,37 @@ export class Hasura {
470470
return createConnection(nodes, false, false);
471471
}
472472

473+
/**
474+
* Delete a public key table entry for the user matching the arguments.
475+
* @param {string} userId
476+
* @param {ProviderId} provider
477+
* @param {string} address
478+
* @returns {Promise<number>}
479+
* @memberof Hasura
480+
*/
481+
async removeUserPublicKey(
482+
userId: string,
483+
provider: ProviderId,
484+
address: string
485+
): Promise<number> {
486+
const resp = await this.#chain("mutation")(
487+
{
488+
delete_auth_public_keys: [
489+
{
490+
where: {
491+
user_id: { _eq: userId },
492+
blockchain: { _eq: provider.toLowerCase() },
493+
public_key: { _eq: address },
494+
},
495+
},
496+
{ affected_rows: true },
497+
],
498+
},
499+
{ operationName: "RemoveUserPublicKey" }
500+
);
501+
return resp.delete_auth_public_keys?.affected_rows ?? 0;
502+
}
503+
473504
/**
474505
* Updates the notification cursor for the argued user if applicable.
475506
* @param {string} userId
@@ -541,4 +572,33 @@ export class Hasura {
541572
);
542573
return resp.update_auth_notifications?.affected_rows;
543574
}
575+
576+
/**
577+
* Update the argued user's avatar to the provider ID
578+
* and NFT address combination provided in the arguments.
579+
* @param {string} userId
580+
* @param {ProviderId} providerId
581+
* @param {string} nft
582+
* @returns {Promise<number>}
583+
* @memberof Hasura
584+
*/
585+
async updateUserAvatar(
586+
userId: string,
587+
providerId: ProviderId,
588+
nft: string
589+
): Promise<number> {
590+
const response = await this.#chain("mutation")(
591+
{
592+
update_auth_users: [
593+
{
594+
_set: { avatar_nft: `${providerId.toLowerCase()}/${nft}` },
595+
where: { id: { _eq: userId } },
596+
},
597+
{ affected_rows: true },
598+
],
599+
},
600+
{ operationName: "UpdateUserAvatar" }
601+
);
602+
return response.update_auth_users?.affected_rows ?? 0;
603+
}
544604
}

backend/native/backpack-api/src/routes/graphql/index.ts

Lines changed: 16 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,42 +4,30 @@ import { applyMiddleware } from "graphql-middleware";
44
import { allow, shield } from "graphql-shield";
55
import { join } from "path";
66

7-
import {
8-
authenticateMutationResolver,
9-
deauthenticateMutationResolver,
10-
friendshipTypeResolvers,
11-
importPublicKeyMutationResolver,
12-
jsonObjectScalar,
13-
markNotificationsAsReadMutationResolver,
14-
notificationTypeResolvers,
15-
sendFriendRequestMutationResolver,
16-
tokenListQueryResolver,
17-
userQueryResolver,
18-
userTypeResolvers,
19-
walletQueryResolver,
20-
walletTypeResolvers,
21-
} from "./resolvers";
7+
import * as handlers from "./resolvers";
228
import { authorized } from "./rules";
239
import type { MutationResolvers, QueryResolvers, Resolvers } from "./types";
2410

2511
/**
2612
* Root `Mutation` object resolver.
2713
*/
2814
const mutationResolvers: MutationResolvers = {
29-
authenticate: authenticateMutationResolver,
30-
deauthenticate: deauthenticateMutationResolver,
31-
importPublicKey: importPublicKeyMutationResolver,
32-
markNotificationsAsRead: markNotificationsAsReadMutationResolver,
33-
sendFriendRequest: sendFriendRequestMutationResolver,
15+
authenticate: handlers.authenticateMutationResolver,
16+
deauthenticate: handlers.deauthenticateMutationResolver,
17+
importPublicKey: handlers.importPublicKeyMutationResolver,
18+
markNotificationsAsRead: handlers.markNotificationsAsReadMutationResolver,
19+
removePublicKey: handlers.removePublicKeyMutationResolver,
20+
sendFriendRequest: handlers.sendFriendRequestMutationResolver,
21+
setAvatar: handlers.setAvatarMutationResolver,
3422
};
3523

3624
/**
3725
* Root `Query` object resolver.
3826
*/
3927
const queryResolvers: QueryResolvers = {
40-
tokenList: tokenListQueryResolver,
41-
user: userQueryResolver,
42-
wallet: walletQueryResolver,
28+
tokenList: handlers.tokenListQueryResolver,
29+
user: handlers.userQueryResolver,
30+
wallet: handlers.walletQueryResolver,
4331
};
4432

4533
/**
@@ -48,11 +36,11 @@ const queryResolvers: QueryResolvers = {
4836
const resolvers: Resolvers = {
4937
Query: queryResolvers,
5038
Mutation: mutationResolvers,
51-
Friendship: friendshipTypeResolvers,
52-
Notification: notificationTypeResolvers,
53-
User: userTypeResolvers,
54-
Wallet: walletTypeResolvers,
55-
JSONObject: jsonObjectScalar,
39+
Friendship: handlers.friendshipTypeResolvers,
40+
Notification: handlers.notificationTypeResolvers,
41+
User: handlers.userTypeResolvers,
42+
Wallet: handlers.walletTypeResolvers,
43+
JSONObject: handlers.jsonObjectScalar,
5644
};
5745

5846
/**
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export * from "./authentication";
22
export * from "./friendship";
33
export * from "./notifications";
4+
export * from "./user";
45
export * from "./wallets";
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import type { GraphQLResolveInfo } from "graphql";
2+
3+
import type { ApiContext } from "../../context";
4+
import type { MutationResolvers, MutationSetAvatarArgs } from "../../types";
5+
6+
/**
7+
* Handler for the mutation to import a new public key to a user account.
8+
* @param {{}} _parent
9+
* @param {MutationSetAvatarArgs} args
10+
* @param {ApiContext} ctx
11+
* @param {GraphQLResolveInfo} _info
12+
* @returns {Promise<boolean>}
13+
*/
14+
export const setAvatarMutationResolver: MutationResolvers["setAvatar"] = async (
15+
_parent: {},
16+
args: MutationSetAvatarArgs,
17+
ctx: ApiContext,
18+
_info: GraphQLResolveInfo
19+
): Promise<boolean> => {
20+
const affectedRows = await ctx.dataSources.hasura.updateUserAvatar(
21+
ctx.authorization.userId!,
22+
args.providerId,
23+
args.nft
24+
);
25+
return affectedRows > 0;
26+
};

backend/native/backpack-api/src/routes/graphql/resolvers/mutation/wallets.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { CreatePublicKeys } from "../../../../validation/user";
1010
import type { ApiContext } from "../../context";
1111
import type {
1212
MutationImportPublicKeyArgs,
13+
MutationRemovePublicKeyArgs,
1314
MutationResolvers,
1415
} from "../../types";
1516

@@ -86,3 +87,26 @@ export const importPublicKeyMutationResolver: MutationResolvers["importPublicKey
8687

8788
return resp.isPrimary;
8889
};
90+
91+
/**
92+
* Handler for the mutation to remove a user public key from the database.
93+
* @param {{}} _parent
94+
* @param {MutationRemovePublicKeyArgs} args
95+
* @param {ApiContext} ctx
96+
* @param {GraphQLResolveInfo} _info
97+
* @returns {Promise<boolean>}
98+
*/
99+
export const removePublicKeyMutationResolver: MutationResolvers["removePublicKey"] =
100+
async (
101+
_parent: {},
102+
args: MutationRemovePublicKeyArgs,
103+
ctx: ApiContext,
104+
_info: GraphQLResolveInfo
105+
): Promise<boolean> => {
106+
const affectedRows = await ctx.dataSources.hasura.removeUserPublicKey(
107+
ctx.authorization.userId!,
108+
args.providerId,
109+
args.address
110+
);
111+
return affectedRows > 0;
112+
};

backend/native/backpack-api/src/routes/graphql/types.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,12 @@ export type Mutation = {
177177
importPublicKey?: Maybe<Scalars["Boolean"]>;
178178
/** Set the `viewed` status of the argued notification IDs are `true`. */
179179
markNotificationsAsRead: Scalars["Int"];
180+
/** Deletes a public key registered to the active user account. */
181+
removePublicKey: Scalars["Boolean"];
180182
/** Allows users to send friend requests to another remote user. */
181183
sendFriendRequest?: Maybe<Scalars["Boolean"]>;
184+
/** Set a user's avatar to a new image. */
185+
setAvatar: Scalars["Boolean"];
182186
};
183187

184188
/** Root level mutation type. */
@@ -201,12 +205,24 @@ export type MutationMarkNotificationsAsReadArgs = {
201205
ids: Array<Scalars["Int"]>;
202206
};
203207

208+
/** Root level mutation type. */
209+
export type MutationRemovePublicKeyArgs = {
210+
address: Scalars["String"];
211+
providerId: ProviderId;
212+
};
213+
204214
/** Root level mutation type. */
205215
export type MutationSendFriendRequestArgs = {
206216
accept: Scalars["Boolean"];
207217
otherUserId: Scalars["String"];
208218
};
209219

220+
/** Root level mutation type. */
221+
export type MutationSetAvatarArgs = {
222+
nft: Scalars["String"];
223+
providerId: ProviderId;
224+
};
225+
210226
/** Generic NFT object type definition to provide on-chain and off-chain metadata. */
211227
export type Nft = Node & {
212228
__typename?: "Nft";
@@ -1040,12 +1056,24 @@ export type MutationResolvers<
10401056
ContextType,
10411057
RequireFields<MutationMarkNotificationsAsReadArgs, "ids">
10421058
>;
1059+
removePublicKey?: Resolver<
1060+
ResolversTypes["Boolean"],
1061+
ParentType,
1062+
ContextType,
1063+
RequireFields<MutationRemovePublicKeyArgs, "address" | "providerId">
1064+
>;
10431065
sendFriendRequest?: Resolver<
10441066
Maybe<ResolversTypes["Boolean"]>,
10451067
ParentType,
10461068
ContextType,
10471069
RequireFields<MutationSendFriendRequestArgs, "accept" | "otherUserId">
10481070
>;
1071+
setAvatar?: Resolver<
1072+
ResolversTypes["Boolean"],
1073+
ParentType,
1074+
ContextType,
1075+
RequireFields<MutationSetAvatarArgs, "nft" | "providerId">
1076+
>;
10491077
}>;
10501078

10511079
export type NftResolvers<

backend/native/backpack-api/src/schema.graphql

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,20 @@ type Mutation {
5050
"""
5151
markNotificationsAsRead(ids: [Int!]!): Int!
5252

53+
"""
54+
Deletes a public key registered to the active user account.
55+
"""
56+
removePublicKey(providerId: ProviderID!, address: String!): Boolean!
57+
5358
"""
5459
Allows users to send friend requests to another remote user.
5560
"""
5661
sendFriendRequest(otherUserId: String!, accept: Boolean!): Boolean
62+
63+
"""
64+
Set a user's avatar to a new image.
65+
"""
66+
setAvatar(providerId: ProviderID!, nft: String!): Boolean!
5767
}
5868

5969
"""

packages/data-components/src/apollo/graphql.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,12 @@ export type Mutation = {
171171
importPublicKey?: Maybe<Scalars["Boolean"]>;
172172
/** Set the `viewed` status of the argued notification IDs are `true`. */
173173
markNotificationsAsRead: Scalars["Int"];
174+
/** Deletes a public key registered to the active user account. */
175+
removePublicKey: Scalars["Boolean"];
174176
/** Allows users to send friend requests to another remote user. */
175177
sendFriendRequest?: Maybe<Scalars["Boolean"]>;
178+
/** Set a user's avatar to a new image. */
179+
setAvatar: Scalars["Boolean"];
176180
};
177181

178182
/** Root level mutation type. */
@@ -195,12 +199,24 @@ export type MutationMarkNotificationsAsReadArgs = {
195199
ids: Array<Scalars["Int"]>;
196200
};
197201

202+
/** Root level mutation type. */
203+
export type MutationRemovePublicKeyArgs = {
204+
address: Scalars["String"];
205+
providerId: ProviderId;
206+
};
207+
198208
/** Root level mutation type. */
199209
export type MutationSendFriendRequestArgs = {
200210
accept: Scalars["Boolean"];
201211
otherUserId: Scalars["String"];
202212
};
203213

214+
/** Root level mutation type. */
215+
export type MutationSetAvatarArgs = {
216+
nft: Scalars["String"];
217+
providerId: ProviderId;
218+
};
219+
204220
/** Generic NFT object type definition to provide on-chain and off-chain metadata. */
205221
export type Nft = Node & {
206222
__typename?: "Nft";

0 commit comments

Comments
 (0)