From 6abbd38d5675d2c13757600cf682ed4021b1da2a Mon Sep 17 00:00:00 2001 From: Matnabru Date: Fri, 4 Aug 2023 15:19:39 +0200 Subject: [PATCH] gei-users edit user --- packages/integrations/gei-users/package.json | 5 +- .../integrations/gei-users/schema.graphql | 16 +++- .../gei-users/src/Mutation/editUser.ts | 34 ++++++++ packages/integrations/gei-users/src/index.ts | 6 ++ .../src/models/EditUserResponseModel.ts | 3 + .../gei-users/src/models/index.ts | 2 + .../integrations/gei-users/src/zeus/const.ts | 5 ++ .../integrations/gei-users/src/zeus/index.ts | 45 ++++++++++- packages/integrations/gei-users/stucco.json | 77 ++++++++++++------- 9 files changed, 158 insertions(+), 35 deletions(-) create mode 100644 packages/integrations/gei-users/src/Mutation/editUser.ts create mode 100644 packages/integrations/gei-users/src/models/EditUserResponseModel.ts diff --git a/packages/integrations/gei-users/package.json b/packages/integrations/gei-users/package.json index cb8d615..652906d 100644 --- a/packages/integrations/gei-users/package.json +++ b/packages/integrations/gei-users/package.json @@ -1,6 +1,6 @@ { "name": "gei-users", - "version": "0.7.1", + "version": "0.7.2", "description": "Automatically generated by graphql-editor-cli", "main": "lib/index.js", "scripts": { @@ -8,7 +8,8 @@ "build": "tsc", "watch": "tsc --watch", "update": "gecli codegen models && gecli schema && gecli codegen typings", - "integrate": "gecli gei integrate" + "integrate": "gecli gei integrate", + "integrate:env": "dotenv -e .env gecli gei integrate" }, "author": "GraphQL Editor Centaur Generator", "license": "ISC", diff --git a/packages/integrations/gei-users/schema.graphql b/packages/integrations/gei-users/schema.graphql index 5fcb15f..ed719d4 100644 --- a/packages/integrations/gei-users/schema.graphql +++ b/packages/integrations/gei-users/schema.graphql @@ -105,6 +105,18 @@ type Mutation{ ): Boolean! } +enum EditUserError { + USERNAME_ALREADY_TAKEN + FAILED_MONGO_UPDATE + USER_DOES_NOT_EXIST +} + +type EditUserResponse{ + result: Boolean + hasError: EditUserError +} + + enum VerifyEmailError{ TOKEN_CANNOT_BE_FOUND } @@ -240,7 +252,9 @@ input RemoveUserFromTeamInput{ } input UpdateUserInput{ - username: String! + userId: String! + username: String + fullName: String } input GenerateOAuthTokenInput{ diff --git a/packages/integrations/gei-users/src/Mutation/editUser.ts b/packages/integrations/gei-users/src/Mutation/editUser.ts new file mode 100644 index 0000000..c3db1c5 --- /dev/null +++ b/packages/integrations/gei-users/src/Mutation/editUser.ts @@ -0,0 +1,34 @@ +import { FieldResolveInput } from 'stucco-js'; +import { orm } from '../db/orm.js'; +import { EditUserError, resolverFor } from '../zeus/index.js'; + +export const handler = async (input: FieldResolveInput) => + resolverFor('Mutation', 'editUser', async ({ updatedUser }) => { + const o = await orm(); + const { userId, username, fullName } = updatedUser; + const userCollection = o('UserCollection').collection; + + const user = await userCollection.findOne({ userId }); + if (!user) { + return { hasError: EditUserError.USER_DOES_NOT_EXIST }; + } + + if (username !== undefined && username !== null) { + const existingUser = await userCollection.findOne({ username, userId: { $ne: userId } }); + if (existingUser) { + return { hasError: EditUserError.USERNAME_ALREADY_TAKEN }; + } + } + const update: any = {}; + if (username !== undefined && username !== null) { + update.username = username; + } + if (fullName !== undefined && fullName !== null) { + update.fullName = fullName; + } + + const res = await userCollection.updateOne({ userId }, { $set: update }); + if (res.modifiedCount === 0) { + return { hasError: EditUserError.FAILED_MONGO_UPDATE }; + } + })(input.arguments); diff --git a/packages/integrations/gei-users/src/index.ts b/packages/integrations/gei-users/src/index.ts index 949a959..bd5415d 100644 --- a/packages/integrations/gei-users/src/index.ts +++ b/packages/integrations/gei-users/src/index.ts @@ -17,6 +17,7 @@ import { handler as requestForForgotPassword } from './Query/requestForForgotPas import { handler as createTeam } from './Mutation/createTeam.js'; import { handler as verifyEmail } from './Mutation/verifyEmail.js'; import { handler as changePasswordWhenLogged } from './Mutation/changePasswordWhenLogged.js'; +import { handler as editUser} from './Mutation/editUser.js' import { handler as integrateSocialAccount } from './Mutation/integrateSocialAccount.js'; import { handler as changePasswordWithToken } from './Mutation/changePasswordWithToken.js'; @@ -106,6 +107,11 @@ export const integration = NewIntegration({ description: 'Provide team name and become the owner of the new team', handler: createTeam, }, + editUser: { + name: 'EditUser', + description: 'Edit user data', + handler: editUser, + }, verifyEmail: { name: 'VerifyEmail', description: diff --git a/packages/integrations/gei-users/src/models/EditUserResponseModel.ts b/packages/integrations/gei-users/src/models/EditUserResponseModel.ts new file mode 100644 index 0000000..333a88a --- /dev/null +++ b/packages/integrations/gei-users/src/models/EditUserResponseModel.ts @@ -0,0 +1,3 @@ +import { ModelTypes } from '../zeus/index.js'; + +export type EditUserResponseModel = ModelTypes['EditUserResponse']; \ No newline at end of file diff --git a/packages/integrations/gei-users/src/models/index.ts b/packages/integrations/gei-users/src/models/index.ts index 3e82d8b..334987b 100644 --- a/packages/integrations/gei-users/src/models/index.ts +++ b/packages/integrations/gei-users/src/models/index.ts @@ -1,6 +1,7 @@ import { QueryModel } from './QueryModel.js' import { UserMemberModel } from './UserMemberModel.js' import { MutationModel } from './MutationModel.js' +import { EditUserResponseModel } from './EditUserResponseModel.js' import { VerifyEmailResponseModel } from './VerifyEmailResponseModel.js' import { ChangePasswordWhenLoggedResponseModel } from './ChangePasswordWhenLoggedResponseModel.js' import { ChangePasswordWithTokenResponseModel } from './ChangePasswordWithTokenResponseModel.js' @@ -33,6 +34,7 @@ export type Models = { QueryModel: QueryModel; UserMemberModel: UserMemberModel; MutationModel: MutationModel; + EditUserResponseModel: EditUserResponseModel; VerifyEmailResponseModel: VerifyEmailResponseModel; ChangePasswordWhenLoggedResponseModel: ChangePasswordWhenLoggedResponseModel; ChangePasswordWithTokenResponseModel: ChangePasswordWithTokenResponseModel; diff --git a/packages/integrations/gei-users/src/zeus/const.ts b/packages/integrations/gei-users/src/zeus/const.ts index 9cd1aee..3f29b16 100644 --- a/packages/integrations/gei-users/src/zeus/const.ts +++ b/packages/integrations/gei-users/src/zeus/const.ts @@ -78,6 +78,7 @@ export const AllTypesProps: Record = { updatedUser:"UpdateUserInput" } }, + EditUserError: "enum" as const, VerifyEmailError: "enum" as const, ChangePasswordWhenLoggedError: "enum" as const, ChangePasswordWithTokenError: "enum" as const, @@ -180,6 +181,10 @@ export const ReturnTypes: Record = { generateOAuthToken:"GenerateOAuthTokenResponse", editUser:"Boolean" }, + EditUserResponse:{ + result:"Boolean", + hasError:"EditUserError" + }, VerifyEmailResponse:{ result:"Boolean", hasError:"VerifyEmailError" diff --git a/packages/integrations/gei-users/src/zeus/index.ts b/packages/integrations/gei-users/src/zeus/index.ts index 196ba30..e985fdb 100644 --- a/packages/integrations/gei-users/src/zeus/index.ts +++ b/packages/integrations/gei-users/src/zeus/index.ts @@ -878,6 +878,12 @@ integrateSocialAccount?: [{ userData: ValueTypes["SimpleUserInput"] | Variable},ValueTypes["GenerateOAuthTokenResponse"]], editUser?: [{ updatedUser: ValueTypes["UpdateUserInput"] | Variable},boolean | `@${string}`], __typename?: boolean | `@${string}` +}>; + ["EditUserError"]:EditUserError; + ["EditUserResponse"]: AliasType<{ + result?:boolean | `@${string}`, + hasError?:boolean | `@${string}`, + __typename?: boolean | `@${string}` }>; ["VerifyEmailError"]:VerifyEmailError; ["VerifyEmailResponse"]: AliasType<{ @@ -956,7 +962,9 @@ editUser?: [{ updatedUser: ValueTypes["UpdateUserInput"] | Variable teamId: string | Variable }; ["UpdateUserInput"]: { - username: string | Variable + userId: string | Variable, + username?: string | undefined | null | Variable, + fullName?: string | undefined | null | Variable }; ["GenerateOAuthTokenInput"]: { social: ValueTypes["SocialKind"] | Variable, @@ -1173,6 +1181,12 @@ integrateSocialAccount?: [{ userData: ResolverInputTypes["SimpleUserInput"]},Res generateOAuthToken?: [{ tokenData: ResolverInputTypes["GenerateOAuthTokenInput"]},ResolverInputTypes["GenerateOAuthTokenResponse"]], editUser?: [{ updatedUser: ResolverInputTypes["UpdateUserInput"]},boolean | `@${string}`], __typename?: boolean | `@${string}` +}>; + ["EditUserError"]:EditUserError; + ["EditUserResponse"]: AliasType<{ + result?:boolean | `@${string}`, + hasError?:boolean | `@${string}`, + __typename?: boolean | `@${string}` }>; ["VerifyEmailError"]:VerifyEmailError; ["VerifyEmailResponse"]: AliasType<{ @@ -1251,7 +1265,9 @@ editUser?: [{ updatedUser: ResolverInputTypes["UpdateUserInput"]},boolean | `@${ teamId: string }; ["UpdateUserInput"]: { - username: string + userId: string, + username?: string | undefined | null, + fullName?: string | undefined | null }; ["GenerateOAuthTokenInput"]: { social: ResolverInputTypes["SocialKind"], @@ -1465,6 +1481,11 @@ export type ModelTypes = { integrateSocialAccount: ModelTypes["IntegrateSocialAccountResponse"], generateOAuthToken: ModelTypes["GenerateOAuthTokenResponse"], editUser: boolean +}; + ["EditUserError"]:EditUserError; + ["EditUserResponse"]: { + result?: boolean | undefined, + hasError?: ModelTypes["EditUserError"] | undefined }; ["VerifyEmailError"]:VerifyEmailError; ["VerifyEmailResponse"]: { @@ -1531,7 +1552,9 @@ export type ModelTypes = { teamId: string }; ["UpdateUserInput"]: { - username: string + userId: string, + username?: string | undefined, + fullName?: string | undefined }; ["GenerateOAuthTokenInput"]: { social: ModelTypes["SocialKind"], @@ -1724,6 +1747,12 @@ export type GraphQLTypes = { integrateSocialAccount: GraphQLTypes["IntegrateSocialAccountResponse"], generateOAuthToken: GraphQLTypes["GenerateOAuthTokenResponse"], editUser: boolean +}; + ["EditUserError"]: EditUserError; + ["EditUserResponse"]: { + __typename: "EditUserResponse", + result?: boolean | undefined, + hasError?: GraphQLTypes["EditUserError"] | undefined }; ["VerifyEmailError"]: VerifyEmailError; ["VerifyEmailResponse"]: { @@ -1802,7 +1831,9 @@ export type GraphQLTypes = { teamId: string }; ["UpdateUserInput"]: { - username: string + userId: string, + username?: string | undefined, + fullName?: string | undefined }; ["GenerateOAuthTokenInput"]: { social: GraphQLTypes["SocialKind"], @@ -1977,6 +2008,11 @@ export const enum MustBeTeamMemberError { USER_IS_NOT_A_TEAM_MEMBER = "USER_IS_NOT_A_TEAM_MEMBER", TEAM_DOES_NOT_EXIST = "TEAM_DOES_NOT_EXIST" } +export const enum EditUserError { + USERNAME_ALREADY_TAKEN = "USERNAME_ALREADY_TAKEN", + FAILED_MONGO_UPDATE = "FAILED_MONGO_UPDATE", + USER_DOES_NOT_EXIST = "USER_DOES_NOT_EXIST" +} export const enum VerifyEmailError { TOKEN_CANNOT_BE_FOUND = "TOKEN_CANNOT_BE_FOUND" } @@ -2070,6 +2106,7 @@ export const enum ProviderErrors { type ZEUS_VARIABLES = { ["MustBeTeamMemberError"]: ValueTypes["MustBeTeamMemberError"]; ["GetOAuthInput"]: ValueTypes["GetOAuthInput"]; + ["EditUserError"]: ValueTypes["EditUserError"]; ["VerifyEmailError"]: ValueTypes["VerifyEmailError"]; ["ChangePasswordWhenLoggedError"]: ValueTypes["ChangePasswordWhenLoggedError"]; ["ChangePasswordWithTokenError"]: ValueTypes["ChangePasswordWithTokenError"]; diff --git a/packages/integrations/gei-users/stucco.json b/packages/integrations/gei-users/stucco.json index 5872c95..3451c6f 100644 --- a/packages/integrations/gei-users/stucco.json +++ b/packages/integrations/gei-users/stucco.json @@ -30,133 +30,133 @@ }, "Query.getGoogleOAuthLink": { "name": "GetGoogleOAuthLink", - "description": "GetGoogleOAuthLink", + "description": "Get Google OAuth link for login user with his Google account", "resolve": { "name": "Query.getGoogleOAuthLink.handler" } }, "Query.getGithubOAuthLink": { "name": "GetGithubOAuthLink", - "description": "getGithubOAuthLink", + "description": "Get Github OAuth link for login user with his Github account", "resolve": { "name": "Query.getGithubOAuthLink.handler" } }, "Query.getAppleOAuthLink": { "name": "GetAppleOAuthLink", - "description": "getAppleOAuthLink", + "description": "Get Apple OAuth link for login user with his Apple account", "resolve": { "name": "Query.getAppleOAuthLink.handler" } }, "Query.showTeamInvitations": { "name": "ShowTeamInvitations", - "description": "showTeamInvitations", + "description": "Show all private team invitations that were sent for you or from this team to emails to users", "resolve": { "name": "Query.showTeamInvitations.handler" } }, "Query.requestForForgotPassword": { "name": "RequestForForgotPassword", - "description": "requestForForgotPassword", + "description": "Provide your email, send this request and get link for create new password", "resolve": { "name": "Query.requestForForgotPassword.handler" } }, "Query.getMicrosoftOAuthLink": { "name": "GetMicrosoftOAuthLink", - "description": "getMicrosoftOAuthLink", + "description": "Get Microsoft OAuth link for login user with his Microsoft account", "resolve": { "name": "Query.getMicrosoftOAuthLink.handler" } }, "Query.mustBeTeamMember": { "name": "MustBeTeamMember", - "description": "mustBeTeamMember", + "description": "Provide token via headers to check if user is member this team. Returns User object and Team object. If user is not team member in throws an error", "resolve": { "name": "Query.mustBeTeamMember.handler" } }, "Mutation.createTeam": { "name": "CreateTeam", - "description": "createTeam", + "description": "Provide team name and become the owner of the new team", "resolve": { "name": "Mutation.createTeam.handler" } }, "Mutation.verifyEmail": { "name": "VerifyEmail", - "description": "verifyEmail", + "description": "Provide token which you will receive by mail after registration to confirm verify your email address", "resolve": { "name": "Mutation.verifyEmail.handler" } }, "Mutation.changePasswordWhenLogged": { "name": "ChangePasswordWhenLogged", - "description": "changePasswordWhenLogged", + "description": "Provide email, old and new password to change password", "resolve": { "name": "Mutation.changePasswordWhenLogged.handler" } }, "Mutation.changePasswordWithToken": { "name": "changePasswordWithToken", - "description": "changePasswordWithToken", + "description": "Provide email, new password and token which you will receive by mail after sending a request for forgot password", "resolve": { "name": "Mutation.changePasswordWithToken.handler" } }, "Mutation.generateInviteToken": { "name": "GenerateInviteToken", - "description": "generateInviteToken", + "description": "Provide teamId, and generate team invite token for send to anyone", "resolve": { "name": "Mutation.generateInviteToken.handler" } }, "Mutation.sendInvitationToTeam": { "name": "sendInvitationToTeam", - "description": "sendInvitationToTeam", + "description": "Provide teamId and email of the user to send to him private team invitation", "resolve": { "name": "Mutation.sendInvitationToTeam.handler" } }, "Mutation.joinToTeam": { "name": "JoinToTeam", - "description": "joinToTeam", + "description": "If you received private invitation to the team, then provide here teamId and be joined", "resolve": { "name": "Mutation.joinToTeam.handler" } }, "Mutation.removeUserFromTeam": { "name": "RemoveUserFromTeam", - "description": "removeUserFromTeam", + "description": "Provide teamId and userId to remove this user from this team", "resolve": { "name": "Mutation.removeUserFromTeam.handler" } }, "Mutation.squashAccounts": { "name": "SquashAccounts", - "description": "squashAccounts", + "description": "This mutation basically serves accounts registered by password before login by providers. This case have create two accounts with one email. You can merge them into one - simply run it without arguments. Also you can merge accounts registered with different emails, if provide in arguments password. Now the password is _id of the user account you want be merge with. New account will have the email of the profile from which run this mutation. But if one of the profiles has hide email, then it anyway will be replaced", "resolve": { "name": "Mutation.squashAccounts.handler" } }, "Mutation.integrateSocialAccount": { "name": "integrateSocialAccount", - "description": "integrateSocialAccount", + "description": "Endpoint using to merge user social account which is pointed with parameters", "resolve": { "name": "Mutation.integrateSocialAccount.handler" } }, "Mutation.joinToTeamWithInvitationToken": { "name": "JoinToTeamWithInvitationToken", - "description": "joinToTeamWithInvitationToken", + "description": "This mutation for registered users to join to team by invite token. Provide token and be joined", "resolve": { "name": "Mutation.joinToTeamWithInvitationToken.handler" } }, "Mutation.generateOAuthToken": { "name": "GenerateOAuthToken", - "description": "generateOAuthToken", + "description": "This endpoint send to social api (google/github/apple) request for get information about user which have code as his identify", "resolve": { "name": "Mutation.generateOAuthToken.handler" } @@ -169,60 +169,81 @@ } }, "User.teams": { - "name": "Teams", - "description": "Show your teams with members", + "name": "ShowMyTeams", + "description": "Show all your teams with members", "resolve": { "name": "User.teams.handler" } }, "LoginQuery.password": { "name": "Password", - "description": "Login with password", + "description": "Login with email and password", "resolve": { "name": "LoginQuery.password.handler" } }, "LoginQuery.provider": { "name": "Provider", - "description": "Login with provider", + "description": "Login with provider. Use with resolvers google/github/apple/microsoft", "resolve": { "name": "LoginQuery.provider.handler" } }, "ProviderLoginQuery.apple": { "name": "Apple", - "description": "Login with apple", + "description": "Login with apple. Provide here the code that you will get by the link from resolver getAppleOAuthLink", "resolve": { "name": "ProviderLoginQuery.apple.handler" } }, "ProviderLoginQuery.github": { "name": "Github", - "description": "Login with github", + "description": "Login with github. Provide here the code that you will get by the link from resolver getGithubOAuthLink", "resolve": { "name": "ProviderLoginQuery.github.handler" } }, "ProviderLoginQuery.microsoft": { "name": "Microsoft", - "description": "Login with microsoft", + "description": "Login with microsoft. Provide here the code that you will get by the link from resolver getMicrosoftOAuthLink", "resolve": { "name": "ProviderLoginQuery.microsoft.handler" } }, "ProviderLoginQuery.google": { "name": "Google", - "description": "Login with google", + "description": "Login with google. Provide here the code that you will get by the link from resolver getGoogleOAuthLink", "resolve": { "name": "ProviderLoginQuery.google.handler" } }, "LoginQuery.refreshToken": { "name": "RefreshToken", - "description": "get new accessToken by refreshToken", + "description": "Get new accessToken by refreshToken", "resolve": { "name": "LoginQuery.refreshToken.handler" } + }, + "Query.showInviteTokens": { + "name": "ShowInviteTokens", + "description": "Show all invite tokens, that were generated by this team", + "resolve": { + "name": "Query.showInviteTokens.handler" + } + }, + "Mutation.editUser": { + "name": "EditUser", + "description": "Edit user data", + "resolve": { + "name": "Mutation.editUser.handler" + } + }, + "Mutation.deleteInvitation": { + "name": "DeleteInvitationOrInviteToken", + "description": "Provide invitationId or inviteTokenId to delete it", + "resolve": { + "name": "Mutation.deleteInvitation.handler" + } } } } \ No newline at end of file