@libreapps/auth 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/.turbo/turbo-build.log +4 -0
  2. package/CHANGELOG.md +20 -0
  3. package/LICENSE.md +21 -0
  4. package/README.md +61 -0
  5. package/components/auth-widget.tsx +110 -0
  6. package/components/email-password-form.tsx +96 -0
  7. package/components/index.ts +4 -0
  8. package/components/login-panel.tsx +207 -0
  9. package/components/signup-panel.tsx +213 -0
  10. package/dist/components/auth-widget.d.ts +13 -0
  11. package/dist/components/auth-widget.js +33 -0
  12. package/dist/components/auth-widget.js.map +1 -0
  13. package/dist/components/email-password-form.d.ts +8 -0
  14. package/dist/components/email-password-form.js +25 -0
  15. package/dist/components/email-password-form.js.map +1 -0
  16. package/dist/components/index.d.ts +4 -0
  17. package/dist/components/index.js +5 -0
  18. package/dist/components/index.js.map +1 -0
  19. package/dist/components/login-panel.d.ts +13 -0
  20. package/dist/components/login-panel.js +104 -0
  21. package/dist/components/login-panel.js.map +1 -0
  22. package/dist/components/signup-panel.d.ts +13 -0
  23. package/dist/components/signup-panel.js +104 -0
  24. package/dist/components/signup-panel.js.map +1 -0
  25. package/dist/icons/ethereum.d.ts +4 -0
  26. package/dist/icons/ethereum.js +6 -0
  27. package/dist/icons/ethereum.js.map +1 -0
  28. package/dist/icons/facebook.d.ts +4 -0
  29. package/dist/icons/facebook.js +6 -0
  30. package/dist/icons/facebook.js.map +1 -0
  31. package/dist/icons/github.d.ts +4 -0
  32. package/dist/icons/github.js +6 -0
  33. package/dist/icons/github.js.map +1 -0
  34. package/dist/icons/google.d.ts +4 -0
  35. package/dist/icons/google.js +6 -0
  36. package/dist/icons/google.js.map +1 -0
  37. package/dist/icons/index.d.ts +6 -0
  38. package/dist/icons/index.js +7 -0
  39. package/dist/icons/index.js.map +1 -0
  40. package/dist/index.d.ts +24 -0
  41. package/dist/index.js +24 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/server/firebase-support.d.ts +8 -0
  44. package/dist/server/firebase-support.js +151 -0
  45. package/dist/server/firebase-support.js.map +1 -0
  46. package/dist/server/index.d.ts +4 -0
  47. package/dist/server/index.js +7 -0
  48. package/dist/server/index.js.map +1 -0
  49. package/dist/server/rest-api-handlers.d.ts +4 -0
  50. package/dist/server/rest-api-handlers.js +23 -0
  51. package/dist/server/rest-api-handlers.js.map +1 -0
  52. package/dist/server/stub-server.d.ts +14 -0
  53. package/dist/server/stub-server.js +23 -0
  54. package/dist/server/stub-server.js.map +1 -0
  55. package/dist/service/auth-service.d.ts +29 -0
  56. package/dist/service/auth-service.js +2 -0
  57. package/dist/service/auth-service.js.map +1 -0
  58. package/dist/service/context.d.ts +9 -0
  59. package/dist/service/context.js +16 -0
  60. package/dist/service/context.js.map +1 -0
  61. package/dist/service/get-singleton.d.ts +4 -0
  62. package/dist/service/get-singleton.js +24 -0
  63. package/dist/service/get-singleton.js.map +1 -0
  64. package/dist/service/impl/firebase-support.d.ts +34 -0
  65. package/dist/service/impl/firebase-support.js +190 -0
  66. package/dist/service/impl/firebase-support.js.map +1 -0
  67. package/dist/service/impl/index.d.ts +32 -0
  68. package/dist/service/impl/index.js +179 -0
  69. package/dist/service/impl/index.js.map +1 -0
  70. package/dist/service/impl/stub-auth-service.d.ts +42 -0
  71. package/dist/service/impl/stub-auth-service.js +97 -0
  72. package/dist/service/impl/stub-auth-service.js.map +1 -0
  73. package/dist/service/impl/wallet-support.d.ts +8 -0
  74. package/dist/service/impl/wallet-support.js +82 -0
  75. package/dist/service/impl/wallet-support.js.map +1 -0
  76. package/dist/service/index.d.ts +4 -0
  77. package/dist/service/index.js +4 -0
  78. package/dist/service/index.js.map +1 -0
  79. package/dist/service/provider-registry.d.ts +37 -0
  80. package/dist/service/provider-registry.js +58 -0
  81. package/dist/service/provider-registry.js.map +1 -0
  82. package/dist/types/api-response.d.ts +8 -0
  83. package/dist/types/api-response.js +2 -0
  84. package/dist/types/api-response.js.map +1 -0
  85. package/dist/types/auth-service-conf.d.ts +5 -0
  86. package/dist/types/auth-service-conf.js +2 -0
  87. package/dist/types/auth-service-conf.js.map +1 -0
  88. package/dist/types/index.d.ts +4 -0
  89. package/dist/types/index.js +2 -0
  90. package/dist/types/index.js.map +1 -0
  91. package/dist/types/libreapps-user-info-value.d.ts +6 -0
  92. package/dist/types/libreapps-user-info-value.js +2 -0
  93. package/dist/types/libreapps-user-info-value.js.map +1 -0
  94. package/dist/types/libreapps-user-info.d.ts +6 -0
  95. package/dist/types/libreapps-user-info.js +2 -0
  96. package/dist/types/libreapps-user-info.js.map +1 -0
  97. package/dist/util/analytics.d.ts +9 -0
  98. package/dist/util/analytics.js +10 -0
  99. package/dist/util/analytics.js.map +1 -0
  100. package/icons/ethereum.tsx +18 -0
  101. package/icons/facebook.tsx +11 -0
  102. package/icons/github.tsx +14 -0
  103. package/icons/google.tsx +13 -0
  104. package/icons/index.ts +16 -0
  105. package/index.ts +51 -0
  106. package/libreapps-ui.d.ts +23 -0
  107. package/package.json +57 -0
  108. package/server/firebase-support.ts +176 -0
  109. package/server/index.ts +14 -0
  110. package/server/rest-api-handlers.ts +33 -0
  111. package/server/stub-server.ts +28 -0
  112. package/service/auth-service.ts +21 -0
  113. package/service/context.tsx +46 -0
  114. package/service/get-singleton.ts +37 -0
  115. package/service/impl/firebase-support.ts +241 -0
  116. package/service/impl/index.ts +231 -0
  117. package/service/impl/stub-auth-service.ts +131 -0
  118. package/service/impl/wallet-support.ts +100 -0
  119. package/service/index.ts +11 -0
  120. package/service/provider-registry.ts +71 -0
  121. package/tsconfig.json +15 -0
  122. package/types/api-response.ts +5 -0
  123. package/types/auth-service-conf.ts +9 -0
  124. package/types/index.ts +6 -0
  125. package/types/libreapps-user-info-value.ts +9 -0
  126. package/types/libreapps-user-info.ts +9 -0
  127. package/util/analytics.ts +21 -0
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Stub Authentication Service
3
+ *
4
+ * This implementation is used when no auth provider is configured.
5
+ * All auth operations return unsuccessful results gracefully.
6
+ */
7
+
8
+ import { makeAutoObservable, makeObservable, computed } from 'mobx'
9
+
10
+ import type AuthService from '../auth-service'
11
+ import type { AuthServiceConf, LibreAppsUserInfo, LibreAppsUserInfoValue } from '../../types'
12
+
13
+ class LibreAppsUserInfoStore implements LibreAppsUserInfo {
14
+
15
+ constructor() {
16
+ makeAutoObservable(this)
17
+ }
18
+
19
+ _email: string = ''
20
+ _displayName: string | null = null
21
+ _walletAddress: string | null = null
22
+
23
+ get email(): string { return this._email}
24
+ get displayName(): string | null { return this._displayName}
25
+ get walletAddress(): string | null { return this._walletAddress}
26
+
27
+ clear():void {
28
+ this._email = ''
29
+ this._displayName = null
30
+ this._walletAddress = null
31
+ }
32
+
33
+ set(v: LibreAppsUserInfoValue):void {
34
+ this._email = v.email
35
+ this._displayName = v.displayName
36
+ this._walletAddress = v.walletAddress
37
+ }
38
+
39
+ get isValid(): boolean {
40
+ return (this._email.length > 0)
41
+ }
42
+ }
43
+
44
+ /**
45
+ * Stub auth service that does nothing but returns graceful failures.
46
+ * Used when no auth provider is configured.
47
+ */
48
+ export class StubAuthService implements AuthService {
49
+
50
+ private _hzUser = new LibreAppsUserInfoStore()
51
+
52
+ constructor(conf: AuthServiceConf, user: LibreAppsUserInfoValue | null) {
53
+ makeObservable(this, {
54
+ loggedIn: computed,
55
+ user: computed
56
+ })
57
+
58
+ if (user) {
59
+ this._hzUser.set(user)
60
+ }
61
+ }
62
+
63
+ get user(): LibreAppsUserInfo | null {
64
+ return this._hzUser.isValid ? this._hzUser : null
65
+ }
66
+
67
+ get loggedIn(): boolean {
68
+ return this._hzUser.isValid
69
+ }
70
+
71
+ signupEmailAndPassword = async (
72
+ _email: string,
73
+ _password: string
74
+ ): Promise<{success: boolean, userInfo: LibreAppsUserInfo | null, message?: string}> => {
75
+ console.warn('Auth provider not configured. Install @libreapps/auth-firebase or another auth provider.')
76
+ return {
77
+ success: false,
78
+ userInfo: null,
79
+ message: 'Auth provider not configured'
80
+ }
81
+ }
82
+
83
+ loginEmailAndPassword = async (
84
+ _email: string,
85
+ _password: string
86
+ ): Promise<{success: boolean, userInfo: LibreAppsUserInfo | null, message?: string}> => {
87
+ console.warn('Auth provider not configured. Install @libreapps/auth-firebase or another auth provider.')
88
+ return {
89
+ success: false,
90
+ userInfo: null,
91
+ message: 'Auth provider not configured'
92
+ }
93
+ }
94
+
95
+ loginWithProvider = async (
96
+ _provider: 'google' | 'facebook' | 'github'
97
+ ): Promise<{success: boolean, userInfo: LibreAppsUserInfo | null}> => {
98
+ console.warn('Auth provider not configured. Install @libreapps/auth-firebase or another auth provider.')
99
+ return {
100
+ success: false,
101
+ userInfo: null
102
+ }
103
+ }
104
+
105
+ loginWithCustomToken = async (
106
+ _token: string
107
+ ): Promise<{success: boolean, userInfo: LibreAppsUserInfo | null}> => {
108
+ console.warn('Auth provider not configured. Install @libreapps/auth-firebase or another auth provider.')
109
+ return {
110
+ success: false,
111
+ userInfo: null
112
+ }
113
+ }
114
+
115
+ associateWallet = async (): Promise<void> => {
116
+ console.warn('Auth provider not configured. Install @libreapps/auth-firebase or another auth provider.')
117
+ }
118
+
119
+ logout = async (): Promise<{ success: boolean }> => {
120
+ this._hzUser.clear()
121
+ return { success: true }
122
+ }
123
+
124
+ setServerSideUser = (user: LibreAppsUserInfoValue | null) => {
125
+ if (user) {
126
+ this._hzUser.set(user)
127
+ }
128
+ }
129
+ }
130
+
131
+ export default StubAuthService
@@ -0,0 +1,100 @@
1
+
2
+ import { collection, doc, getDoc, setDoc } from 'firebase/firestore'
3
+
4
+ import { auth, db } from './firebase-support'
5
+
6
+ const isObject = (obj: any): obj is Record<any, any> => typeof obj === 'object' && obj !== null
7
+ const isGlobalThisEthereum = (obj: any): obj is { ethereum: { request: <R = any>(payload: Record<any, any>) => Promise<R> } } => isObject(obj) && isObject(obj.ethereum) && typeof obj.ethereum.request === 'function'
8
+ const getEthereum = (obj: any) => isGlobalThisEthereum(obj) ? obj.ethereum : null
9
+
10
+ const ethereum = getEthereum(globalThis)
11
+
12
+ let signMessage = (opts: { siteName: string, address: string }) => `${opts.siteName} wants you to sign in with your Ethereum account:\n${opts.address}`
13
+
14
+ const USER_INFO_COLLECTION = 'HZ_USER_INFO'
15
+
16
+ async function connectWalletAddress(siteName?: string) {
17
+ if (!ethereum) {
18
+ throw new Error('No ethereum provider found')
19
+ }
20
+
21
+ if (!auth) {
22
+ throw new Error('Firebase auth not configured')
23
+ }
24
+
25
+ const [account] = await ethereum.request<string[]>({ method: 'eth_requestAccounts' })
26
+
27
+ if (!account) {
28
+ throw new Error('No account found')
29
+ }
30
+
31
+ const signed = await ethereum.request<string>({
32
+ method: 'personal_sign',
33
+ params: [
34
+ signMessage({
35
+ siteName: siteName ?? auth.app.options.projectId ?? globalThis.location.hostname,
36
+ address: account,
37
+ }),
38
+ account,
39
+ auth.app.options.appId,
40
+ ],
41
+ })
42
+
43
+ if (!signed) {
44
+ throw new Error('Not signed')
45
+ }
46
+
47
+ return {account, signed}
48
+ }
49
+
50
+ export async function associateWalletAddressWithAccount(userEmail: string, siteName?: string) {
51
+ const {account} = await connectWalletAddress(siteName)
52
+
53
+ if (!db) {
54
+ return { result: null, error: new Error('Firebase Firestore not configured') }
55
+ }
56
+
57
+ let result = null
58
+ let error = null
59
+ const accountsRef = collection(db, USER_INFO_COLLECTION)
60
+
61
+ try {
62
+ try {
63
+ await setDoc(doc(accountsRef, userEmail), { walletAddress: account })
64
+ result = account
65
+ } catch (e) {
66
+ console.error(e)
67
+ error = e
68
+ }
69
+ } catch (e) {
70
+ console.error(e)
71
+ error = e
72
+ }
73
+
74
+ return { result, error }
75
+ }
76
+
77
+ export async function getAssociatedWalletAddress(userEmail: string) : Promise<{error: any, result?: string}> {
78
+ if (!db) {
79
+ return { error: new Error('Firebase Firestore not configured'), result: undefined }
80
+ }
81
+
82
+ let result = undefined
83
+ let error = null
84
+ try {
85
+ try {
86
+ const docRef = await getDoc(doc(db, USER_INFO_COLLECTION, userEmail))
87
+ result = docRef.data() ? docRef.data()!.walletAddress as string : undefined
88
+ }
89
+ catch (e) {
90
+ console.error(e)
91
+ error = e
92
+ }
93
+ }
94
+ catch (e) {
95
+ console.error(e)
96
+ error = e
97
+ }
98
+
99
+ return { result, error }
100
+ }
@@ -0,0 +1,11 @@
1
+ export type { default as AuthService, AuthProvider } from './auth-service'
2
+ export { useAuth, AuthServiceProvider } from './context'
3
+ export {
4
+ registerAuthProvider,
5
+ setActiveProvider,
6
+ getActiveProvider,
7
+ hasAuthProvider,
8
+ getRegisteredProviders,
9
+ type AuthServiceFactory
10
+ } from './provider-registry'
11
+ export { StubAuthService } from './impl/stub-auth-service'
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Auth Provider Registry
3
+ *
4
+ * Allows registration of pluggable auth providers.
5
+ * Firebase support is available via @libreapps/auth-firebase (optional).
6
+ */
7
+
8
+ import type AuthService from './auth-service'
9
+ import type { AuthServiceConf, LibreAppsUserInfoValue } from '../types'
10
+
11
+ export type AuthServiceFactory = new (
12
+ conf: AuthServiceConf,
13
+ user: LibreAppsUserInfoValue | null
14
+ ) => AuthService
15
+
16
+ // Registry of available auth providers
17
+ const providers = new Map<string, AuthServiceFactory>()
18
+
19
+ // Current active provider
20
+ let activeProvider: string | null = null
21
+
22
+ /**
23
+ * Register an auth provider
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * import { FirebaseAuthService } from '@libreapps/auth-firebase'
28
+ * import { registerAuthProvider } from '@libreapps/auth'
29
+ *
30
+ * registerAuthProvider('firebase', FirebaseAuthService)
31
+ * ```
32
+ */
33
+ export function registerAuthProvider(name: string, factory: AuthServiceFactory): void {
34
+ providers.set(name, factory)
35
+ // Auto-activate if this is the first provider
36
+ if (!activeProvider) {
37
+ activeProvider = name
38
+ }
39
+ }
40
+
41
+ /**
42
+ * Set the active auth provider by name
43
+ */
44
+ export function setActiveProvider(name: string): void {
45
+ if (!providers.has(name)) {
46
+ throw new Error(`Auth provider '${name}' is not registered`)
47
+ }
48
+ activeProvider = name
49
+ }
50
+
51
+ /**
52
+ * Get the active auth provider factory
53
+ */
54
+ export function getActiveProvider(): AuthServiceFactory | null {
55
+ if (!activeProvider) return null
56
+ return providers.get(activeProvider) ?? null
57
+ }
58
+
59
+ /**
60
+ * Check if any auth provider is registered
61
+ */
62
+ export function hasAuthProvider(): boolean {
63
+ return providers.size > 0
64
+ }
65
+
66
+ /**
67
+ * Get list of registered provider names
68
+ */
69
+ export function getRegisteredProviders(): string[] {
70
+ return Array.from(providers.keys())
71
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "extends": "../tsconfig.libreapps.base.json",
3
+ "include": [
4
+ "**/*.ts",
5
+ "**/*.tsx",
6
+ ],
7
+ "exclude": [
8
+ "node_modules",
9
+ "dist"
10
+ ],
11
+ "compilerOptions": {
12
+ "noEmit": false,
13
+ "declaration": true
14
+ }
15
+ }
@@ -0,0 +1,5 @@
1
+ type APIResponse<T = object> = { success: true; data: T } | { success: false; error: string };
2
+
3
+ export {
4
+ type APIResponse as default
5
+ }
@@ -0,0 +1,9 @@
1
+
2
+ interface AuthServiceConf {
3
+ firestoreDB: string
4
+ userInfoCollection: string
5
+ }
6
+
7
+ export {
8
+ type AuthServiceConf as default
9
+ }
package/types/index.ts ADDED
@@ -0,0 +1,6 @@
1
+ export type { default as LibreAppsUserInfo } from './libreapps-user-info'
2
+ export type { default as APIResponse } from './api-response'
3
+ export type { default as AuthServiceConf } from './auth-service-conf'
4
+ export type { default as LibreAppsUserInfoValue } from './libreapps-user-info-value'
5
+
6
+
@@ -0,0 +1,9 @@
1
+ type LibreAppsUserInfoValue = {
2
+ email: string
3
+ displayName: string | null
4
+ walletAddress: string | null
5
+ }
6
+
7
+ export {
8
+ type LibreAppsUserInfoValue as default
9
+ }
@@ -0,0 +1,9 @@
1
+ interface LibreAppsUserInfo {
2
+ get email(): string
3
+ get displayName(): string | null
4
+ get walletAddress(): string | null
5
+ }
6
+
7
+ export {
8
+ type LibreAppsUserInfo as default
9
+ }
@@ -0,0 +1,21 @@
1
+ declare global {
2
+ interface Window {
3
+ fbq: Function;
4
+ gtag: Function;
5
+ }
6
+ }
7
+
8
+ // https://developers.facebook.com/docs/meta-pixel/reference
9
+ const sendFBEvent = (name: string, options = {}) => {
10
+ window.fbq('track', name, options)
11
+ }
12
+
13
+ // https://developers.google.com/analytics/devguides/collection/ga4/ecommerce?client_type=gtag
14
+ const sendGAEvent = (name: string, options = {}) => {
15
+ window.gtag('event', name, options)
16
+ }
17
+
18
+ export {
19
+ sendFBEvent,
20
+ sendGAEvent,
21
+ }