All files / src/services authService.ts

87.23% Statements 41/47
71.42% Branches 10/14
100% Functions 5/5
87.23% Lines 41/47

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89  1x                       1x                 1x 1x 1x             1x 1x 1x         1x 3x 3x 3x 1x 3x 2x 2x 2x 2x       2x 2x 1x 1x 1x 1x 2x     2x 3x           1x 2x 2x 1x 2x 1x 1x 1x 1x 1x     2x         1x 1x 1x    
//#region dependency injection
import {
  createUserWithEmailAndPassword,
  EmailAuthProvider,
  fetchSignInMethodsForEmail,
  GithubAuthProvider,
  GoogleAuthProvider,
  linkWithCredential,
  signInWithEmailAndPassword,
  signInWithPopup,
  signOut,
  type User
} from 'firebase/auth';
import {auth} from '@/config/firebase'; // ← 統一
//#endregion dependency injection
 
//#region method
/**
 * メールログイン
 * @param email
 * @param password
 */
export const loginWithEmail = async (email: string, password: string) => {
  return await signInWithEmailAndPassword(auth, email, password);
}
 
/**
 * メール登録
 * @param email
 * @param password
 */
export const registerWithEmail = async (email: string, password: string) => {
  return await createUserWithEmailAndPassword(auth, email, password);
}
 
/**
 * プロバイダログイン(Googleのみ)+アカウント統合
 */
export const loginWithGoogle = async (): Promise<User> => {
  const provider = new GoogleAuthProvider();
  try {
    const result = await signInWithPopup(auth, provider);
    return result.user;
  } catch (error: any) {
    if (error.code === 'auth/account-exists-with-different-credential') {
      const email = error.customData?.email;
      const pendingCred = error.credential;
      if (!email || !pendingCred) {
        throw new Error('このアカウントは別の方法で登録されています(統合できません)');
      }
 
      const methods = await fetchSignInMethodsForEmail(auth, email);
      if (methods.includes(EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD)) {
        throw new Error('email/passwordでログインしてからGoogle連携を行ってください');
      } else {
        throw new Error('このアカウントは別の方法で登録されています');
      }
    } else {
      throw error;
    }
  }
}
 
/**
 * GitHubリンク(ログイン後)
 * @param user
 */
export const linkWithGithub = async (user: User) => {
  try {
    const result = await signInWithPopup(auth, new GithubAuthProvider());
    const credential = GithubAuthProvider.credentialFromResult(result);
    if (!credential) throw new Error('GitHub認証情報が取得できませんでした');
    await linkWithCredential(user, credential);
  } catch (e: any) {
    if (e.code === 'auth/credential-already-in-use') {
      throw new Error('このGitHubアカウントはすでに他のアカウントと紐づいています');
    }
    throw e;
  }
}
 
/**
 * ログアウト
 */
export const logout = async () => {
  await signOut(auth);
}
//#endregion method