diff --git a/amplify/auth/post-confirmation/graphql/API.ts b/amplify/auth/post-confirmation/graphql/API.ts deleted file mode 100644 index 5c55eed..0000000 --- a/amplify/auth/post-confirmation/graphql/API.ts +++ /dev/null @@ -1,308 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// This file was automatically generated and should not be edited. - -export type User = { - __typename: "User"; - createdAt: string; - email?: string | null; - firstName?: string | null; - id: string; - lastName?: string | null; - owner?: string | null; - updatedAt: string; -}; - -export type ModelUserFilterInput = { - and?: Array | null; - createdAt?: ModelStringInput | null; - email?: ModelStringInput | null; - firstName?: ModelStringInput | null; - id?: ModelIDInput | null; - lastName?: ModelStringInput | null; - not?: ModelUserFilterInput | null; - or?: Array | null; - owner?: ModelStringInput | null; - updatedAt?: ModelStringInput | null; -}; - -export type ModelStringInput = { - attributeExists?: boolean | null; - attributeType?: ModelAttributeTypes | null; - beginsWith?: string | null; - between?: Array | null; - contains?: string | null; - eq?: string | null; - ge?: string | null; - gt?: string | null; - le?: string | null; - lt?: string | null; - ne?: string | null; - notContains?: string | null; - size?: ModelSizeInput | null; -}; - -export enum ModelAttributeTypes { - _null = "_null", - binary = "binary", - binarySet = "binarySet", - bool = "bool", - list = "list", - map = "map", - number = "number", - numberSet = "numberSet", - string = "string", - stringSet = "stringSet", -} - -export type ModelSizeInput = { - between?: Array | null; - eq?: number | null; - ge?: number | null; - gt?: number | null; - le?: number | null; - lt?: number | null; - ne?: number | null; -}; - -export type ModelIDInput = { - attributeExists?: boolean | null; - attributeType?: ModelAttributeTypes | null; - beginsWith?: string | null; - between?: Array | null; - contains?: string | null; - eq?: string | null; - ge?: string | null; - gt?: string | null; - le?: string | null; - lt?: string | null; - ne?: string | null; - notContains?: string | null; - size?: ModelSizeInput | null; -}; - -export type ModelUserConnection = { - __typename: "ModelUserConnection"; - items: Array; - nextToken?: string | null; -}; - -export type ModelUserConditionInput = { - and?: Array | null; - createdAt?: ModelStringInput | null; - email?: ModelStringInput | null; - firstName?: ModelStringInput | null; - lastName?: ModelStringInput | null; - not?: ModelUserConditionInput | null; - or?: Array | null; - owner?: ModelStringInput | null; - updatedAt?: ModelStringInput | null; -}; - -export type CreateUserInput = { - email?: string | null; - firstName?: string | null; - id?: string | null; - lastName?: string | null; -}; - -export type DeleteUserInput = { - id: string; -}; - -export type UpdateUserInput = { - email?: string | null; - firstName?: string | null; - id: string; - lastName?: string | null; -}; - -export type ModelSubscriptionUserFilterInput = { - and?: Array | null; - createdAt?: ModelSubscriptionStringInput | null; - email?: ModelSubscriptionStringInput | null; - firstName?: ModelSubscriptionStringInput | null; - id?: ModelSubscriptionIDInput | null; - lastName?: ModelSubscriptionStringInput | null; - or?: Array | null; - owner?: ModelStringInput | null; - updatedAt?: ModelSubscriptionStringInput | null; -}; - -export type ModelSubscriptionStringInput = { - beginsWith?: string | null; - between?: Array | null; - contains?: string | null; - eq?: string | null; - ge?: string | null; - gt?: string | null; - in?: Array | null; - le?: string | null; - lt?: string | null; - ne?: string | null; - notContains?: string | null; - notIn?: Array | null; -}; - -export type ModelSubscriptionIDInput = { - beginsWith?: string | null; - between?: Array | null; - contains?: string | null; - eq?: string | null; - ge?: string | null; - gt?: string | null; - in?: Array | null; - le?: string | null; - lt?: string | null; - ne?: string | null; - notContains?: string | null; - notIn?: Array | null; -}; - -export type GetUserQueryVariables = { - id: string; -}; - -export type GetUserQuery = { - getUser?: { - __typename: "User"; - createdAt: string; - email?: string | null; - firstName?: string | null; - id: string; - lastName?: string | null; - owner?: string | null; - updatedAt: string; - } | null; -}; - -export type ListUsersQueryVariables = { - filter?: ModelUserFilterInput | null; - limit?: number | null; - nextToken?: string | null; -}; - -export type ListUsersQuery = { - listUsers?: { - __typename: "ModelUserConnection"; - items: Array<{ - __typename: "User"; - createdAt: string; - email?: string | null; - firstName?: string | null; - id: string; - lastName?: string | null; - owner?: string | null; - updatedAt: string; - } | null>; - nextToken?: string | null; - } | null; -}; - -export type CreateUserMutationVariables = { - condition?: ModelUserConditionInput | null; - input: CreateUserInput; -}; - -export type CreateUserMutation = { - createUser?: { - __typename: "User"; - createdAt: string; - email?: string | null; - firstName?: string | null; - id: string; - lastName?: string | null; - owner?: string | null; - updatedAt: string; - } | null; -}; - -export type DeleteUserMutationVariables = { - condition?: ModelUserConditionInput | null; - input: DeleteUserInput; -}; - -export type DeleteUserMutation = { - deleteUser?: { - __typename: "User"; - createdAt: string; - email?: string | null; - firstName?: string | null; - id: string; - lastName?: string | null; - owner?: string | null; - updatedAt: string; - } | null; -}; - -export type UpdateUserMutationVariables = { - condition?: ModelUserConditionInput | null; - input: UpdateUserInput; -}; - -export type UpdateUserMutation = { - updateUser?: { - __typename: "User"; - createdAt: string; - email?: string | null; - firstName?: string | null; - id: string; - lastName?: string | null; - owner?: string | null; - updatedAt: string; - } | null; -}; - -export type OnCreateUserSubscriptionVariables = { - filter?: ModelSubscriptionUserFilterInput | null; - owner?: string | null; -}; - -export type OnCreateUserSubscription = { - onCreateUser?: { - __typename: "User"; - createdAt: string; - email?: string | null; - firstName?: string | null; - id: string; - lastName?: string | null; - owner?: string | null; - updatedAt: string; - } | null; -}; - -export type OnDeleteUserSubscriptionVariables = { - filter?: ModelSubscriptionUserFilterInput | null; - owner?: string | null; -}; - -export type OnDeleteUserSubscription = { - onDeleteUser?: { - __typename: "User"; - createdAt: string; - email?: string | null; - firstName?: string | null; - id: string; - lastName?: string | null; - owner?: string | null; - updatedAt: string; - } | null; -}; - -export type OnUpdateUserSubscriptionVariables = { - filter?: ModelSubscriptionUserFilterInput | null; - owner?: string | null; -}; - -export type OnUpdateUserSubscription = { - onUpdateUser?: { - __typename: "User"; - createdAt: string; - email?: string | null; - firstName?: string | null; - id: string; - lastName?: string | null; - owner?: string | null; - updatedAt: string; - } | null; -}; diff --git a/amplify/auth/post-confirmation/graphql/mutations.ts b/amplify/auth/post-confirmation/graphql/mutations.ts deleted file mode 100644 index bdcd0fd..0000000 --- a/amplify/auth/post-confirmation/graphql/mutations.ts +++ /dev/null @@ -1,68 +0,0 @@ -/* tslint:disable */ - -/* eslint-disable */ -// this is an auto generated file. This will be overwritten -import * as APITypes from "./API"; - -type GeneratedMutation = string & { - __generatedMutationInput: InputType; - __generatedMutationOutput: OutputType; -}; - -export const createUser = /* GraphQL */ `mutation CreateUser( - $condition: ModelUserConditionInput - $input: CreateUserInput! -) { - createUser(condition: $condition, input: $input) { - createdAt - email - firstName - id - lastName - owner - updatedAt - __typename - } -} -` as GeneratedMutation< - APITypes.CreateUserMutationVariables, - APITypes.CreateUserMutation ->; -export const deleteUser = /* GraphQL */ `mutation DeleteUser( - $condition: ModelUserConditionInput - $input: DeleteUserInput! -) { - deleteUser(condition: $condition, input: $input) { - createdAt - email - firstName - id - lastName - owner - updatedAt - __typename - } -} -` as GeneratedMutation< - APITypes.DeleteUserMutationVariables, - APITypes.DeleteUserMutation ->; -export const updateUser = /* GraphQL */ `mutation UpdateUser( - $condition: ModelUserConditionInput - $input: UpdateUserInput! -) { - updateUser(condition: $condition, input: $input) { - createdAt - email - firstName - id - lastName - owner - updatedAt - __typename - } -} -` as GeneratedMutation< - APITypes.UpdateUserMutationVariables, - APITypes.UpdateUserMutation ->; diff --git a/amplify/auth/post-confirmation/graphql/queries.ts b/amplify/auth/post-confirmation/graphql/queries.ts deleted file mode 100644 index b7e5c12..0000000 --- a/amplify/auth/post-confirmation/graphql/queries.ts +++ /dev/null @@ -1,45 +0,0 @@ -/* tslint:disable */ - -/* eslint-disable */ -// this is an auto generated file. This will be overwritten -import * as APITypes from "./API"; - -type GeneratedQuery = string & { - __generatedQueryInput: InputType; - __generatedQueryOutput: OutputType; -}; - -export const getUser = /* GraphQL */ `query GetUser($id: ID!) { - getUser(id: $id) { - createdAt - email - firstName - id - lastName - owner - updatedAt - __typename - } -} -` as GeneratedQuery; -export const listUsers = /* GraphQL */ `query ListUsers( - $filter: ModelUserFilterInput - $limit: Int - $nextToken: String -) { - listUsers(filter: $filter, limit: $limit, nextToken: $nextToken) { - items { - createdAt - email - firstName - id - lastName - owner - updatedAt - __typename - } - nextToken - __typename - } -} -` as GeneratedQuery; diff --git a/amplify/auth/post-confirmation/graphql/subscriptions.ts b/amplify/auth/post-confirmation/graphql/subscriptions.ts deleted file mode 100644 index 19300de..0000000 --- a/amplify/auth/post-confirmation/graphql/subscriptions.ts +++ /dev/null @@ -1,68 +0,0 @@ -/* tslint:disable */ - -/* eslint-disable */ -// this is an auto generated file. This will be overwritten -import * as APITypes from "./API"; - -type GeneratedSubscription = string & { - __generatedSubscriptionInput: InputType; - __generatedSubscriptionOutput: OutputType; -}; - -export const onCreateUser = /* GraphQL */ `subscription OnCreateUser( - $filter: ModelSubscriptionUserFilterInput - $owner: String -) { - onCreateUser(filter: $filter, owner: $owner) { - createdAt - email - firstName - id - lastName - owner - updatedAt - __typename - } -} -` as GeneratedSubscription< - APITypes.OnCreateUserSubscriptionVariables, - APITypes.OnCreateUserSubscription ->; -export const onDeleteUser = /* GraphQL */ `subscription OnDeleteUser( - $filter: ModelSubscriptionUserFilterInput - $owner: String -) { - onDeleteUser(filter: $filter, owner: $owner) { - createdAt - email - firstName - id - lastName - owner - updatedAt - __typename - } -} -` as GeneratedSubscription< - APITypes.OnDeleteUserSubscriptionVariables, - APITypes.OnDeleteUserSubscription ->; -export const onUpdateUser = /* GraphQL */ `subscription OnUpdateUser( - $filter: ModelSubscriptionUserFilterInput - $owner: String -) { - onUpdateUser(filter: $filter, owner: $owner) { - createdAt - email - firstName - id - lastName - owner - updatedAt - __typename - } -} -` as GeneratedSubscription< - APITypes.OnUpdateUserSubscriptionVariables, - APITypes.OnUpdateUserSubscription ->; diff --git a/amplify/auth/post-confirmation/handler.ts b/amplify/auth/post-confirmation/handler.ts index 7c39cb0..4fb5028 100644 --- a/amplify/auth/post-confirmation/handler.ts +++ b/amplify/auth/post-confirmation/handler.ts @@ -1,54 +1,22 @@ -import { env } from "$amplify/env/post-confirmation"; -import { Amplify } from "aws-amplify"; -import { generateClient } from "aws-amplify/data"; import type { PostConfirmationTriggerHandler } from "aws-lambda"; -import { type Schema } from "../../data/resource"; -import { createUser } from "./graphql/mutations"; +import { + AdminAddUserToGroupCommand, + CognitoIdentityProviderClient, +} from "@aws-sdk/client-cognito-identity-provider"; -Amplify.configure( - { - API: { - GraphQL: { - endpoint: env.AMPLIFY_DATA_GRAPHQL_ENDPOINT, - region: env.AWS_REGION, - defaultAuthMode: "iam", - }, - }, - }, - { - Auth: { - credentialsProvider: { - getCredentialsAndIdentityId: async () => ({ - credentials: { - accessKeyId: env.AWS_ACCESS_KEY_ID, - secretAccessKey: env.AWS_SECRET_ACCESS_KEY, - sessionToken: env.AWS_SESSION_TOKEN, - }, - }), - clearCredentialsAndIdentityId: () => { - /* noop */ - }, - }, - }, - }, -); - -const client = generateClient({ - authMode: "iam", -}); +const cognitoClient = new CognitoIdentityProviderClient(); export const handler: PostConfirmationTriggerHandler = async (event) => { - await client.graphql({ - query: createUser, - variables: { - input: { - email: event.request.userAttributes.email, - firstName: event.request.userAttributes.given_name, - lastName: event.request.userAttributes.family_name, - }, - }, + const command = new AdminAddUserToGroupCommand({ + GroupName: "GuestUser", + Username: event.userName, + UserPoolId: event.userPoolId, }); - - return event; + const response = await cognitoClient.send(command); + if (response.$metadata.httpStatusCode === 200) { + return event; + } else { + throw new Error("Failed to add user to group"); + } }; diff --git a/amplify/auth/post-confirmation/resource.ts b/amplify/auth/post-confirmation/resource.ts index df226d4..8e56c49 100644 --- a/amplify/auth/post-confirmation/resource.ts +++ b/amplify/auth/post-confirmation/resource.ts @@ -2,6 +2,6 @@ import { defineFunction } from "@aws-amplify/backend"; export const postConfirmation = defineFunction({ name: "post-confirmation", - runtime: 20, entry: "./handler.ts", + runtime: 20, }); diff --git a/amplify/auth/pre-sign-up/handler.ts b/amplify/auth/pre-sign-up/handler.ts new file mode 100644 index 0000000..8257240 --- /dev/null +++ b/amplify/auth/pre-sign-up/handler.ts @@ -0,0 +1,60 @@ +import { Amplify } from "aws-amplify"; +import { generateClient } from "aws-amplify/data"; +import type { PreSignUpTriggerHandler } from "aws-lambda"; + +import { type Schema } from "@/../../amplify/data/resource"; +import { data } from "@/../../amplify_outputs.json"; + +Amplify.configure( + { + API: { + GraphQL: { + endpoint: process.env.AMPLIFY_DATA_GRAPHQL_ENDPOINT as string, + region: process.env.AWS_REGION, + defaultAuthMode: "identityPool", + modelIntrospection: data.model_introspection as any, + }, + }, + }, + { + Auth: { + credentialsProvider: { + getCredentialsAndIdentityId: async () => ({ + credentials: { + accessKeyId: process.env.AWS_ACCESS_KEY_ID as string, + secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY as string, + sessionToken: process.env.AWS_SESSION_TOKEN as string, + }, + }), + clearCredentialsAndIdentityId: () => { + /* noop */ + }, + }, + }, + }, +); + +export const dataClient = generateClient(); + +export const handler: PreSignUpTriggerHandler = async (event) => { + return await dataClient.models.User.create({ + firstName: "Default", + lastName: "Name", + role: "GuestUser", + id: event.userName, + email: event.request.userAttributes.email, + totalEarnings: 0, + // profileOwner: `${event.userName}::${event.userName}`, + }) + .then((user) => { + if (user.errors) { + throw new Error("Failed to create user in DB"); + } + console.log("User created", user); + return event; + }) + .catch((error) => { + console.error(error); + throw error; + }); +}; diff --git a/amplify/auth/pre-sign-up/resource.ts b/amplify/auth/pre-sign-up/resource.ts new file mode 100644 index 0000000..283da90 --- /dev/null +++ b/amplify/auth/pre-sign-up/resource.ts @@ -0,0 +1,7 @@ +import { defineFunction } from "@aws-amplify/backend"; + +export const preSignUp = defineFunction({ + name: "pre-sign-up", + entry: "./handler.ts", + runtime: 20, +}); diff --git a/amplify/auth/resource.ts b/amplify/auth/resource.ts index 3b9c785..10e5854 100644 --- a/amplify/auth/resource.ts +++ b/amplify/auth/resource.ts @@ -1,6 +1,7 @@ import { defineAuth } from "@aws-amplify/backend"; import { postConfirmation } from "./post-confirmation/resource"; +import { preSignUp } from "./pre-sign-up/resource"; /** * Define and configure your auth resource @@ -10,7 +11,10 @@ export const auth = defineAuth({ loginWith: { email: true, }, + groups: ["AdminUser", "GuestUser"], triggers: { postConfirmation, + preSignUp, }, + access: (allow) => [allow.resource(postConfirmation).to(["addUserToGroup"])], }); diff --git a/amplify/data/resource.ts b/amplify/data/resource.ts index 1b31dcb..9429e11 100644 --- a/amplify/data/resource.ts +++ b/amplify/data/resource.ts @@ -1,9 +1,6 @@ -import { identifyUser } from "aws-amplify/analytics"; -import { Session } from "inspector"; - import { type ClientSchema, a, defineData } from "@aws-amplify/backend"; -import { postConfirmation } from "../auth/post-confirmation/resource"; +import { preSignUp } from "../auth/pre-sign-up/resource"; /*== STEP 1 =============================================================== The section below creates a Todo database table with a "content" field. Try @@ -19,13 +16,13 @@ const schema = a email: a.string().required(), firstName: a.string().required(), lastName: a.string().required(), + role: a.string().default("GuestUser"), totalEarnings: a.float(), sessionsAttended: a.hasMany("SessionsAttended", "sessionAttendedId"), }) .authorization((allow) => [ - // allow.group("Guest").to(["read"]), - // allow.group("Admin").to(["read", "update", "delete"]), - allow.authenticated(), + allow.group("GuestUser").to(["read"]), + allow.group("AdminUser").to(["read", "update", "delete"]), ]), SessionsAttended: a .model({ @@ -35,12 +32,11 @@ const schema = a date: a.belongsTo("User", "sessionAttendedId"), }) .authorization((allow) => [ - // allow.group("Guest").to(["read"]), - // allow.group("Admin").to(["read", "update", "delete"]), - allow.authenticated(), + allow.group("GuestUser").to(["read"]), + allow.group("AdminUser").to(["read", "update", "delete"]), ]), }) - .authorization((allow) => [allow.resource(postConfirmation)]); + .authorization((allow) => [allow.resource(preSignUp).to(["mutate"])]); export type Schema = ClientSchema; diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 83991f2..39bd83e 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -6,7 +6,11 @@ import Link from "next/link"; import { useRouter } from "next/navigation"; import { useEffect, useState } from "react"; -export default function Header({ isSignedIn }: { isSignedIn: boolean }) { +export default function Header({ + isSignedIn, +}: { + isSignedIn: boolean | undefined; +}) { const [authCheck, setAuthCheck] = useState(isSignedIn); const router = useRouter(); diff --git a/src/components/contexts/UserContext.tsx b/src/components/contexts/UserContext.tsx index 07ea8a3..bf34295 100644 --- a/src/components/contexts/UserContext.tsx +++ b/src/components/contexts/UserContext.tsx @@ -12,8 +12,8 @@ interface Props { } export enum UserType { - Admin = "Admin", - Guest = "Guest", + AdminUser = "AdminUser", + GuestUser = "GuestUser", } export interface IUser { @@ -38,7 +38,7 @@ export const UserContext = createContext({} as IUserReturn); export function UserContextProvider({ children }: Props) { const [currentUser, setCurrentUser] = useState({ username: "", - type: UserType.Guest, + type: UserType.GuestUser, populated: false, }); // TO DO load other user info from table @@ -85,7 +85,7 @@ export function UserContextProvider({ children }: Props) { if (String(err).includes("No user")) { setCurrentUser({ username: "", - type: UserType.Guest, + type: UserType.GuestUser, populated: true, }); console.info("Not Logged in"); diff --git a/src/components/contexts/amplifyUtils.ts b/src/components/contexts/amplifyUtils.ts index 184af64..8fbb706 100644 --- a/src/components/contexts/amplifyUtils.ts +++ b/src/components/contexts/amplifyUtils.ts @@ -16,7 +16,7 @@ export async function isAuthenticated() { try { const currentUser = await runWithAmplifyServerContext({ nextServerContext: { cookies }, - operation: (contextSpec) => fetchAuthSession(contextSpec), + operation: (contextSpec: any) => fetchAuthSession(contextSpec), }); return !!currentUser;