Skip to content

Commit

Permalink
add more user centric mutations to gql (#4258)
Browse files Browse the repository at this point in the history
  • Loading branch information
callensm authored Jun 30, 2023
1 parent 70c567a commit 5de03ce
Show file tree
Hide file tree
Showing 8 changed files with 181 additions and 28 deletions.
60 changes: 60 additions & 0 deletions backend/native/backpack-api/src/routes/graphql/clients/hasura.ts
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,37 @@ export class Hasura {
return createConnection(nodes, false, false);
}

/**
* Delete a public key table entry for the user matching the arguments.
* @param {string} userId
* @param {ProviderId} provider
* @param {string} address
* @returns {Promise<number>}
* @memberof Hasura
*/
async removeUserPublicKey(
userId: string,
provider: ProviderId,
address: string
): Promise<number> {
const resp = await this.#chain("mutation")(
{
delete_auth_public_keys: [
{
where: {
user_id: { _eq: userId },
blockchain: { _eq: provider.toLowerCase() },
public_key: { _eq: address },
},
},
{ affected_rows: true },
],
},
{ operationName: "RemoveUserPublicKey" }
);
return resp.delete_auth_public_keys?.affected_rows ?? 0;
}

/**
* Updates the notification cursor for the argued user if applicable.
* @param {string} userId
Expand Down Expand Up @@ -541,4 +572,33 @@ export class Hasura {
);
return resp.update_auth_notifications?.affected_rows;
}

/**
* Update the argued user's avatar to the provider ID
* and NFT address combination provided in the arguments.
* @param {string} userId
* @param {ProviderId} providerId
* @param {string} nft
* @returns {Promise<number>}
* @memberof Hasura
*/
async updateUserAvatar(
userId: string,
providerId: ProviderId,
nft: string
): Promise<number> {
const response = await this.#chain("mutation")(
{
update_auth_users: [
{
_set: { avatar_nft: `${providerId.toLowerCase()}/${nft}` },
where: { id: { _eq: userId } },
},
{ affected_rows: true },
],
},
{ operationName: "UpdateUserAvatar" }
);
return response.update_auth_users?.affected_rows ?? 0;
}
}
44 changes: 16 additions & 28 deletions backend/native/backpack-api/src/routes/graphql/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,30 @@ import { applyMiddleware } from "graphql-middleware";
import { allow, shield } from "graphql-shield";
import { join } from "path";

import {
authenticateMutationResolver,
deauthenticateMutationResolver,
friendshipTypeResolvers,
importPublicKeyMutationResolver,
jsonObjectScalar,
markNotificationsAsReadMutationResolver,
notificationTypeResolvers,
sendFriendRequestMutationResolver,
tokenListQueryResolver,
userQueryResolver,
userTypeResolvers,
walletQueryResolver,
walletTypeResolvers,
} from "./resolvers";
import * as handlers from "./resolvers";
import { authorized } from "./rules";
import type { MutationResolvers, QueryResolvers, Resolvers } from "./types";

/**
* Root `Mutation` object resolver.
*/
const mutationResolvers: MutationResolvers = {
authenticate: authenticateMutationResolver,
deauthenticate: deauthenticateMutationResolver,
importPublicKey: importPublicKeyMutationResolver,
markNotificationsAsRead: markNotificationsAsReadMutationResolver,
sendFriendRequest: sendFriendRequestMutationResolver,
authenticate: handlers.authenticateMutationResolver,
deauthenticate: handlers.deauthenticateMutationResolver,
importPublicKey: handlers.importPublicKeyMutationResolver,
markNotificationsAsRead: handlers.markNotificationsAsReadMutationResolver,
removePublicKey: handlers.removePublicKeyMutationResolver,
sendFriendRequest: handlers.sendFriendRequestMutationResolver,
setAvatar: handlers.setAvatarMutationResolver,
};

/**
* Root `Query` object resolver.
*/
const queryResolvers: QueryResolvers = {
tokenList: tokenListQueryResolver,
user: userQueryResolver,
wallet: walletQueryResolver,
tokenList: handlers.tokenListQueryResolver,
user: handlers.userQueryResolver,
wallet: handlers.walletQueryResolver,
};

/**
Expand All @@ -48,11 +36,11 @@ const queryResolvers: QueryResolvers = {
const resolvers: Resolvers = {
Query: queryResolvers,
Mutation: mutationResolvers,
Friendship: friendshipTypeResolvers,
Notification: notificationTypeResolvers,
User: userTypeResolvers,
Wallet: walletTypeResolvers,
JSONObject: jsonObjectScalar,
Friendship: handlers.friendshipTypeResolvers,
Notification: handlers.notificationTypeResolvers,
User: handlers.userTypeResolvers,
Wallet: handlers.walletTypeResolvers,
JSONObject: handlers.jsonObjectScalar,
};

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from "./authentication";
export * from "./friendship";
export * from "./notifications";
export * from "./user";
export * from "./wallets";
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import type { GraphQLResolveInfo } from "graphql";

import type { ApiContext } from "../../context";
import type { MutationResolvers, MutationSetAvatarArgs } from "../../types";

/**
* Handler for the mutation to import a new public key to a user account.
* @param {{}} _parent
* @param {MutationSetAvatarArgs} args
* @param {ApiContext} ctx
* @param {GraphQLResolveInfo} _info
* @returns {Promise<boolean>}
*/
export const setAvatarMutationResolver: MutationResolvers["setAvatar"] = async (
_parent: {},
args: MutationSetAvatarArgs,
ctx: ApiContext,
_info: GraphQLResolveInfo
): Promise<boolean> => {
const affectedRows = await ctx.dataSources.hasura.updateUserAvatar(
ctx.authorization.userId!,
args.providerId,
args.nft
);
return affectedRows > 0;
};
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { CreatePublicKeys } from "../../../../validation/user";
import type { ApiContext } from "../../context";
import type {
MutationImportPublicKeyArgs,
MutationRemovePublicKeyArgs,
MutationResolvers,
} from "../../types";

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

return resp.isPrimary;
};

/**
* Handler for the mutation to remove a user public key from the database.
* @param {{}} _parent
* @param {MutationRemovePublicKeyArgs} args
* @param {ApiContext} ctx
* @param {GraphQLResolveInfo} _info
* @returns {Promise<boolean>}
*/
export const removePublicKeyMutationResolver: MutationResolvers["removePublicKey"] =
async (
_parent: {},
args: MutationRemovePublicKeyArgs,
ctx: ApiContext,
_info: GraphQLResolveInfo
): Promise<boolean> => {
const affectedRows = await ctx.dataSources.hasura.removeUserPublicKey(
ctx.authorization.userId!,
args.providerId,
args.address
);
return affectedRows > 0;
};
28 changes: 28 additions & 0 deletions backend/native/backpack-api/src/routes/graphql/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,12 @@ export type Mutation = {
importPublicKey?: Maybe<Scalars["Boolean"]>;
/** Set the `viewed` status of the argued notification IDs are `true`. */
markNotificationsAsRead: Scalars["Int"];
/** Deletes a public key registered to the active user account. */
removePublicKey: Scalars["Boolean"];
/** Allows users to send friend requests to another remote user. */
sendFriendRequest?: Maybe<Scalars["Boolean"]>;
/** Set a user's avatar to a new image. */
setAvatar: Scalars["Boolean"];
};

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

/** Root level mutation type. */
export type MutationRemovePublicKeyArgs = {
address: Scalars["String"];
providerId: ProviderId;
};

/** Root level mutation type. */
export type MutationSendFriendRequestArgs = {
accept: Scalars["Boolean"];
otherUserId: Scalars["String"];
};

/** Root level mutation type. */
export type MutationSetAvatarArgs = {
nft: Scalars["String"];
providerId: ProviderId;
};

/** Generic NFT object type definition to provide on-chain and off-chain metadata. */
export type Nft = Node & {
__typename?: "Nft";
Expand Down Expand Up @@ -1040,12 +1056,24 @@ export type MutationResolvers<
ContextType,
RequireFields<MutationMarkNotificationsAsReadArgs, "ids">
>;
removePublicKey?: Resolver<
ResolversTypes["Boolean"],
ParentType,
ContextType,
RequireFields<MutationRemovePublicKeyArgs, "address" | "providerId">
>;
sendFriendRequest?: Resolver<
Maybe<ResolversTypes["Boolean"]>,
ParentType,
ContextType,
RequireFields<MutationSendFriendRequestArgs, "accept" | "otherUserId">
>;
setAvatar?: Resolver<
ResolversTypes["Boolean"],
ParentType,
ContextType,
RequireFields<MutationSetAvatarArgs, "nft" | "providerId">
>;
}>;

export type NftResolvers<
Expand Down
10 changes: 10 additions & 0 deletions backend/native/backpack-api/src/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,20 @@ type Mutation {
"""
markNotificationsAsRead(ids: [Int!]!): Int!

"""
Deletes a public key registered to the active user account.
"""
removePublicKey(providerId: ProviderID!, address: String!): Boolean!

"""
Allows users to send friend requests to another remote user.
"""
sendFriendRequest(otherUserId: String!, accept: Boolean!): Boolean

"""
Set a user's avatar to a new image.
"""
setAvatar(providerId: ProviderID!, nft: String!): Boolean!
}

"""
Expand Down
16 changes: 16 additions & 0 deletions packages/data-components/src/apollo/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,12 @@ export type Mutation = {
importPublicKey?: Maybe<Scalars["Boolean"]>;
/** Set the `viewed` status of the argued notification IDs are `true`. */
markNotificationsAsRead: Scalars["Int"];
/** Deletes a public key registered to the active user account. */
removePublicKey: Scalars["Boolean"];
/** Allows users to send friend requests to another remote user. */
sendFriendRequest?: Maybe<Scalars["Boolean"]>;
/** Set a user's avatar to a new image. */
setAvatar: Scalars["Boolean"];
};

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

/** Root level mutation type. */
export type MutationRemovePublicKeyArgs = {
address: Scalars["String"];
providerId: ProviderId;
};

/** Root level mutation type. */
export type MutationSendFriendRequestArgs = {
accept: Scalars["Boolean"];
otherUserId: Scalars["String"];
};

/** Root level mutation type. */
export type MutationSetAvatarArgs = {
nft: Scalars["String"];
providerId: ProviderId;
};

/** Generic NFT object type definition to provide on-chain and off-chain metadata. */
export type Nft = Node & {
__typename?: "Nft";
Expand Down

1 comment on commit 5de03ce

@vercel
Copy link

@vercel vercel bot commented on 5de03ce Jun 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.