Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix user storage to avoid saving empty data #252

Merged
merged 3 commits into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 45 additions & 42 deletions context/AuthContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
} from 'firebase/auth'
import { auth } from '../firebase/initFirebase.js'
import { getUserFromFirestore, createUserinFirestore, updateUserGithub } from '../lib/user.js'
import { useTranslation } from "react-i18next"
import { useTranslation } from 'react-i18next'

const AuthContext = createContext()

Expand Down Expand Up @@ -71,9 +71,9 @@ export function AuthProvider({ children }) {
const signup = (data) => {
setLoading(true)
createUserWithEmailAndPassword(auth, data.email, data.password)
.then((userCredential) => {
.then(async (userCredential) => {
setUser(userCredential.user)
createUserinFirestore(userCredential.user)
await createUserinFirestore(userCredential.user)
Router.push('/courses')
toast.success(t('messages.registration_success'), {
toastParameters,
Expand Down Expand Up @@ -122,7 +122,35 @@ export function AuthProvider({ children }) {
}

const loginGithub = async () => {
return loginWithProvider(GithubAuthProvider)
setLoading(true)
try {
const result = await signInWithPopup(auth, new GithubAuthProvider())
await handleGithubLogin(result.user)
} catch (error) {
console.error('GitHub login error:', error)
toast.error(t('messages.something_wrong_try_again'), {
toastParameters,
})
} finally {
setLoading(false)
}
}

const handleGithubLogin = async (user) => {
const userData = await getUserFromFirestore(user)
if (!userData) {
await createUserinFirestore(user)
}
setUser(user)
const providerData = user.providerData.find((provider) => provider.providerId === 'github.com')
if (providerData) {
const githubUrl = `https://github.com/${providerData.uid}`
await updateUserGithub(githubUrl, user.uid)
}
Router.push('/courses')
toast.success(t('messages.login_success'), {
toastParameters,
})
}

const loginWithProvider = async (Provider) => {
Expand All @@ -133,51 +161,26 @@ export function AuthProvider({ children }) {

useEffect(() => {
async function fetchUser() {
await getRedirectResult(auth)
.then(async (result) => {
const user = result?.user
if (!user) return
const cred = JSON.parse(sessionStorage.getItem('credential'))

if (cred?.providerId == 'github.com') {
await linkGithub(cred, user)
}
const providerObj = user.reloadUserInfo.providerUserInfo[0]
if (providerObj.providerId !== 'github.com') return
await getUserFromFirestore(user)
githubUrl = `https://${providerObj.providerId}/${providerObj.screenName}`
await updateUserGithub(githubUrl, user.uid)
sessionStorage.clear()

toast.success(t('messages.login_success'), {
toastParameters,
})
})
.catch((error) => {
console.log(error)
if (error.code === 'auth/account-exists-with-different-credential') {
const credential = OAuthProvider.credentialFromResult(error.customData)
sessionStorage.setItem('credential', JSON.stringify(credential))
Router.push('/auth')
}
})
try {
const result = await getRedirectResult(auth)
if (result?.user) {
await handleGithubLogin(result.user)
}
} catch (error) {
console.error('Redirect result error:', error)
if (error.code === 'auth/account-exists-with-different-credential') {
const credential = OAuthProvider.credentialFromResult(error.customData)
sessionStorage.setItem('credential', JSON.stringify(credential))
Router.push('/auth')
}
}
}
fetchUser()
if (user) {
mixpanel.identify(user?.uid)
mixpanel.people.set(user)
}
}, [auth.currentUser])

async function linkGithub(cred, user) {
if (user) {
const credential = GithubAuthProvider.credential(cred.accessToken)
const userCredential = await linkWithCredential(user, credential)
githubUrl = JSON.parse(userCredential._tokenResponse.rawUserInfo).html_url
await updateUserGithub(githubUrl, user.uid)
await getUserFromFirestore(user, user.providerData)
}
}
const logout = async () => {
try {
sessionStorage.clear()
Expand Down
14 changes: 3 additions & 11 deletions functions/lib/mailchimp.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,11 @@ exports.createUser = async function (user) {
const result = await mailchimp.lists.addListMember('b578d43584', {
email_address: user.email,
status: 'subscribed',
merge_fields: objectWithUppercasedKeys(user),
full_name: user.name,
merge_fields: { WALLET: user.wallet_address, NAME: user.name },
})
console.log('User added to Mailchimp successfully:')
} catch (error) {
console.error(error)
}
}

function objectWithUppercasedKeys(object) {
const newObject = {}
Object.keys(object).forEach((key) => {
if(object[key]) {
newObject[key.toUpperCase()] = object[key]
}
})
return newObject
}
48 changes: 25 additions & 23 deletions functions/test/lib/mailchimp.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,56 +5,58 @@ jest.mock('@mailchimp/mailchimp_marketing', () => ({
setConfig: jest.fn(),
lists: {
addListMember: jest.fn(),
}
},
}))

describe('add User to list', function() {
describe('add User to list', function () {
beforeEach(() => {
mailchimp.lists.addListMember.mockClear()
})
it("Should add users to list correctly", async () => {
it('Should add users to list correctly', async () => {
const emailData = {
user_email: "[email protected]",
firstName: "John",
lastName: "Doe",
user_email: '[email protected]',
firstName: 'John',
lastName: 'Doe',
params: {
cohort: "test",
course: "test",
cohort: 'cohort_list_id',
course: 'course_list_id',
},
}
await addUserToList(emailData)
expect(mailchimp.setConfig).toHaveBeenCalledTimes(1)
expect(mailchimp.lists.addListMember).toHaveBeenCalledWith("test", {
email_address: "[email protected]",
expect(mailchimp.lists.addListMember).toHaveBeenCalledWith('cohort_list_id', {
email_address: '[email protected]',
status: 'subscribed',
})
expect(mailchimp.lists.addListMember).toHaveBeenCalledWith('course_list_id', {
email_address: '[email protected]',
status: 'subscribed',
})

expect(mailchimp.lists.addListMember).toHaveBeenCalledTimes(2)
})
})

describe("create user in mailchimp", () => {
describe('create user in mailchimp', () => {
beforeEach(() => {
mailchimp.lists.addListMember.mockClear()
})

const user = {
email: "[email protected]",
firstName: "John",
lastName: "Doe",
email: '[email protected]',
name: 'John',
wallet_address: '0x1234567890abcdef',
}

it("Should create user in mailchimp", async () => {
it('Should create user in mailchimp', async () => {
await createUser(user)

expect(mailchimp.lists.addListMember).toHaveBeenCalledWith("b578d43584", {
email_address: "[email protected]",
status: "subscribed",
expect(mailchimp.lists.addListMember).toHaveBeenCalledWith('b578d43584', {
email_address: '[email protected]',
status: 'subscribed',
merge_fields: {
EMAIL: "[email protected]",
FIRSTNAME: "John",
LASTNAME: "Doe",
NAME: 'John',
WALLET: '0x1234567890abcdef',
},
})
})
})
})
32 changes: 20 additions & 12 deletions lib/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,24 @@ export const getUserFromFirestore = async (userCredential) => {
}

export const createUserinFirestore = async (userCredential) => {
const docRef = doc(collectionRef, userCredential.uid)
const docSnap = await getDoc(docRef)

if (docSnap.exists()) {
console.log('User already exists in Firestore')
return
}

let githubUrl = ''
if (userCredential?.providerData) {
const github_id = userCredential.providerData.find(
(item) => item.providerId == 'github.com'
)?.uid
await fetch(`https://api.github.com/user/${github_id}`)
.then((res) => res.json())
.then(async (data) => {
githubUrl = data.html_url
})
if (userCredential.providerData && Array.isArray(userCredential.providerData)) {
const githubProvider = userCredential.providerData.find(
(item) => item.providerId === 'github.com'
)
if (githubProvider) {
githubUrl = `https://github.com/${githubProvider.uid}`
}
}

const userProps = {
uid: userCredential?.uid,
name: userCredential?.displayName || null,
Expand Down Expand Up @@ -65,6 +72,7 @@ export const createUserinFirestore = async (userCredential) => {
},
],
}

mixpanel.track('user_created', userProps)
await setDoc(doc(collectionRef, userProps.uid), userProps)
}
Expand Down Expand Up @@ -168,7 +176,7 @@ export const submitLessonInFirestore = async (

export const findSocialLinks = (name, user) => user?.socialLinks?.find((link) => link.name === name)

export const getUserByDiscordId = async(discordId) => {
export const getUserByDiscordId = async (discordId) => {
const q = query(usersRef, where('discord.id', '==', discordId))
const querySnapshot = await getDocs(q)

Expand All @@ -193,10 +201,10 @@ export const registerUserInStudyGroupInFirestore = async (studyGroupId, userCred
}),
study_group_ids: arrayUnion(studyGroupId),
}

await updateDoc(doc(collectionRef, userCredential), userProps)
mixpanel.track('study_group_signup', studyGroupData)
} else {
console.error(`Study group with ID ${studyGroupId} does not exist`)
}
}
}
Loading