-
Notifications
You must be signed in to change notification settings - Fork 76
Fix: Update Mock Auth with Roles #186
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
base: main
Are you sure you want to change the base?
Fix: Update Mock Auth with Roles #186
Conversation
WalkthroughAdds a new mock-auth configuration module and updates the auth hook to support role-based mock users (guest/host/dual), localStorage persistence, and a refactored wallet login flow using a memo-based challenge transaction. The auth context now exposes a loginAsMockUser(role) method and initializes mock state when MOCK_AUTH is enabled. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant UI as App UI
participant Auth as AuthProvider
participant Config as authConfig (MOCK_USERS)
participant LS as localStorage
rect rgb(235, 245, 255)
note over Auth,Config: Mock Auth Mode
User->>UI: Select "Login as Mock (role)"
UI->>Auth: loginAsMockUser(role)
Auth->>Config: Get MOCK_USERS[role]
Config-->>Auth: MockUser
Auth->>LS: Save mock user + authType=mock
Auth-->>UI: Update context state
end
sequenceDiagram
autonumber
actor User
participant UI as App UI
participant Auth as AuthProvider
participant Wallet as Wallet Adapter
participant Backend as API
participant LS as localStorage
note over UI,Auth: Wallet Auth Flow (refactored)
User->>UI: Login with Wallet
UI->>Auth: loginWithWallet(walletPublicKey)
Auth->>Auth: Validate public key
Auth->>Backend: Request challenge (memo-based)
Backend-->>Auth: Challenge tx/memo
Auth->>Wallet: Sign challenge
Wallet-->>Auth: Signature
Auth->>Backend: Submit signature for auth
Backend-->>Auth: Auth OK + user profile
Auth->>LS: Persist user + authType=wallet
Auth-->>UI: Update context state
UI-->>User: Logged in
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (3 warnings)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🧹 Nitpick comments (1)
apps/web/src/hooks/auth/use-auth.tsx (1)
183-188: Simplify repeated type assertions.Lines 184-185 repeat the same type assertion. Extract the user object first for cleaner code.
Apply this diff:
+ const responseUser = authResponse.user as { id: string; name?: string }; const userData: User = { - id: (authResponse.user as { id: string; name?: string }).id, - name: (authResponse.user as { id: string; name?: string }).name || 'Wallet User', + id: responseUser.id, + name: responseUser.name || 'Wallet User', publicKey: walletPublicKey, authType: 'wallet', };
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
apps/web/src/config/auth.config.ts(1 hunks)apps/web/src/hooks/auth/use-auth.tsx(8 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
apps/web/src/hooks/auth/use-auth.tsx (5)
apps/backend/src/types/auth.types.ts (1)
User(9-13)apps/web/src/config/auth.config.ts (1)
authConfig(2-58)apps/web/src/services/api.ts (2)
apiUtils(102-135)authAPI(347-384)apps/web/src/lib/network-utils.ts (3)
logNetworkInfo(32-39)getNetworkPassphrase(3-13)getNetworkName(15-25)apps/web/src/lib/freighter-utils.ts (1)
signTransactionWithFreighter(181-211)
| // Mock users for testing | ||
| MOCK_USERS: { | ||
| guest: { | ||
| id: 'mock-guest-123', | ||
| name: 'Demo Guest', | ||
| email: 'guest@stellarent.com', | ||
| role: 'guest' as const, | ||
| hostStatus: 'none' as const, | ||
| hasProperties: false, | ||
| propertyCount: 0, | ||
| hasBookings: true, | ||
| bookingCount: 3, | ||
| }, | ||
| host: { | ||
| id: 'mock-host-456', | ||
| name: 'Demo Host', | ||
| email: 'host@stellarent.com', | ||
| role: 'host' as const, | ||
| hostStatus: 'verified' as const, | ||
| hasProperties: true, | ||
| propertyCount: 3, | ||
| hasBookings: false, | ||
| bookingCount: 0, | ||
| hostSince: '2024-01-15', | ||
| }, | ||
| dual: { | ||
| id: 'mock-dual-789', | ||
| name: 'Demo Dual User', | ||
| email: 'dual@stellarent.com', | ||
| role: 'dual' as const, | ||
| hostStatus: 'verified' as const, | ||
| hasProperties: true, | ||
| propertyCount: 2, | ||
| hasBookings: true, | ||
| bookingCount: 5, | ||
| hostSince: '2024-03-20', | ||
| }, | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add missing fields to maintain consistency with MOCK_USER.
The MOCK_USERS objects are missing the publicKey and authType fields that are present in MOCK_USER (lines 16-17). In apps/web/src/hooks/auth/use-auth.tsx at line 62, the code accesses mockUser.authType, which will be undefined for these mock users, though it does fall back to 'email'. To maintain consistency and avoid confusion, add these fields to each mock user.
Apply this diff to add the missing fields:
MOCK_USERS: {
guest: {
id: 'mock-guest-123',
name: 'Demo Guest',
email: 'guest@stellarent.com',
role: 'guest' as const,
hostStatus: 'none' as const,
hasProperties: false,
propertyCount: 0,
hasBookings: true,
bookingCount: 3,
+ publicKey: 'GBXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
+ authType: 'email' as const,
},
host: {
id: 'mock-host-456',
name: 'Demo Host',
email: 'host@stellarent.com',
role: 'host' as const,
hostStatus: 'verified' as const,
hasProperties: true,
propertyCount: 3,
hasBookings: false,
bookingCount: 0,
hostSince: '2024-01-15',
+ publicKey: 'GBXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
+ authType: 'email' as const,
},
dual: {
id: 'mock-dual-789',
name: 'Demo Dual User',
email: 'dual@stellarent.com',
role: 'dual' as const,
hostStatus: 'verified' as const,
hasProperties: true,
propertyCount: 2,
hasBookings: true,
bookingCount: 5,
hostSince: '2024-03-20',
+ publicKey: 'GBXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
+ authType: 'email' as const,
},
},📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Mock users for testing | |
| MOCK_USERS: { | |
| guest: { | |
| id: 'mock-guest-123', | |
| name: 'Demo Guest', | |
| email: 'guest@stellarent.com', | |
| role: 'guest' as const, | |
| hostStatus: 'none' as const, | |
| hasProperties: false, | |
| propertyCount: 0, | |
| hasBookings: true, | |
| bookingCount: 3, | |
| }, | |
| host: { | |
| id: 'mock-host-456', | |
| name: 'Demo Host', | |
| email: 'host@stellarent.com', | |
| role: 'host' as const, | |
| hostStatus: 'verified' as const, | |
| hasProperties: true, | |
| propertyCount: 3, | |
| hasBookings: false, | |
| bookingCount: 0, | |
| hostSince: '2024-01-15', | |
| }, | |
| dual: { | |
| id: 'mock-dual-789', | |
| name: 'Demo Dual User', | |
| email: 'dual@stellarent.com', | |
| role: 'dual' as const, | |
| hostStatus: 'verified' as const, | |
| hasProperties: true, | |
| propertyCount: 2, | |
| hasBookings: true, | |
| bookingCount: 5, | |
| hostSince: '2024-03-20', | |
| }, | |
| }, | |
| // Mock users for testing | |
| MOCK_USERS: { | |
| guest: { | |
| id: 'mock-guest-123', | |
| name: 'Demo Guest', | |
| email: 'guest@stellarent.com', | |
| role: 'guest' as const, | |
| hostStatus: 'none' as const, | |
| hasProperties: false, | |
| propertyCount: 0, | |
| hasBookings: true, | |
| bookingCount: 3, | |
| publicKey: 'GBXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', | |
| authType: 'email' as const, | |
| }, | |
| host: { | |
| id: 'mock-host-456', | |
| name: 'Demo Host', | |
| email: 'host@stellarent.com', | |
| role: 'host' as const, | |
| hostStatus: 'verified' as const, | |
| hasProperties: true, | |
| propertyCount: 3, | |
| hasBookings: false, | |
| bookingCount: 0, | |
| hostSince: '2024-01-15', | |
| publicKey: 'GBXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', | |
| authType: 'email' as const, | |
| }, | |
| dual: { | |
| id: 'mock-dual-789', | |
| name: 'Demo Dual User', | |
| email: 'dual@stellarent.com', | |
| role: 'dual' as const, | |
| hostStatus: 'verified' as const, | |
| hasProperties: true, | |
| propertyCount: 2, | |
| hasBookings: true, | |
| bookingCount: 5, | |
| hostSince: '2024-03-20', | |
| publicKey: 'GBXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', | |
| authType: 'email' as const, | |
| }, | |
| }, |
🤖 Prompt for AI Agents
In apps/web/src/config/auth.config.ts around lines 20 to 57, the MOCK_USERS
entries (guest, host, dual) are missing the publicKey and authType fields
present on MOCK_USER, causing undefined authType when code reads
mockUser.authType; update each mock user object to include a publicKey (use a
mock value consistent with existing id patterns, e.g., 'pk-mock-...') and an
authType (e.g., 'email') so the shape matches MOCK_USER and downstream code no
longer sees missing fields.
| // --- MOCK USER LOGIN --- | ||
| const loginAsMockUser = (role: Role) => { | ||
| if (!authConfig.MOCK_USERS[role]) return; | ||
| const mockUser = authConfig.MOCK_USERS[role]; | ||
| setUser(mockUser); | ||
| setAuthType(mockUser.authType || 'email'); | ||
| localStorage.setItem('user', JSON.stringify(mockUser)); | ||
| localStorage.setItem('authType', mockUser.authType || 'email'); | ||
| console.log('✅ Logged in as mock user:', role); | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add console logs to list available mock users.
The PR objectives specify: "Add console logs to list available mock users and current role in use-auth hook." Currently, only a confirmation log is emitted after login. Consider adding a log that lists all available mock roles when mock auth is initialized.
Add this code at the start of the loginAsMockUser function:
const loginAsMockUser = (role: Role) => {
+ console.log('📋 Available mock roles:', Object.keys(authConfig.MOCK_USERS));
if (!authConfig.MOCK_USERS[role]) return;
const mockUser = authConfig.MOCK_USERS[role];
setUser(mockUser);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // --- MOCK USER LOGIN --- | |
| const loginAsMockUser = (role: Role) => { | |
| if (!authConfig.MOCK_USERS[role]) return; | |
| const mockUser = authConfig.MOCK_USERS[role]; | |
| setUser(mockUser); | |
| setAuthType(mockUser.authType || 'email'); | |
| localStorage.setItem('user', JSON.stringify(mockUser)); | |
| localStorage.setItem('authType', mockUser.authType || 'email'); | |
| console.log('✅ Logged in as mock user:', role); | |
| }; | |
| // --- MOCK USER LOGIN --- | |
| const loginAsMockUser = (role: Role) => { | |
| console.log('📋 Available mock roles:', Object.keys(authConfig.MOCK_USERS)); | |
| if (!authConfig.MOCK_USERS[role]) return; | |
| const mockUser = authConfig.MOCK_USERS[role]; | |
| setUser(mockUser); | |
| setAuthType(mockUser.authType || 'email'); | |
| localStorage.setItem('user', JSON.stringify(mockUser)); | |
| localStorage.setItem('authType', mockUser.authType || 'email'); | |
| console.log('✅ Logged in as mock user:', role); | |
| }; |
🤖 Prompt for AI Agents
In apps/web/src/hooks/auth/use-auth.tsx around lines 57 to 66, the
loginAsMockUser function only logs a confirmation after logging in; add an
initial console log that lists all available mock user roles and the currently
selected role when mock auth is initialized or when loginAsMockUser is invoked.
Specifically, at the start of loginAsMockUser log
Object.keys(authConfig.MOCK_USERS) (or a mapped list of roles) and the incoming
role value, then proceed with the existing checks and login flow; keep logs
concise and guard against missing MOCK_USERS to avoid runtime errors.
| // --- CHECK LOCAL STORAGE ON INIT --- | ||
| useEffect(() => { | ||
| const checkAuth = () => { | ||
| if (authConfig.MOCK_AUTH) { | ||
| const storedUser = localStorage.getItem('user'); | ||
| const storedAuthType = localStorage.getItem('authType') as 'email' | 'wallet' | null; | ||
|
|
||
| if (storedUser) { | ||
| try { | ||
| const parsedUser = JSON.parse(storedUser); | ||
| setUser(parsedUser); | ||
| setUser(JSON.parse(storedUser)); | ||
| setAuthType(storedAuthType); | ||
| console.log('🔥 MOCK AUTH MODE ENABLED'); | ||
| } catch (error) { | ||
| console.error('Error parsing stored user:', error); | ||
| apiUtils.clearAuth(); | ||
| } | ||
| } | ||
| }; | ||
|
|
||
| checkAuth(); | ||
| } | ||
| }, []); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Log available mock users on initialization.
The console log at line 78 only fires when a stored user is found. Per the PR objectives, you should log the available mock users when MOCK_AUTH is enabled, regardless of whether a stored user exists. This helps developers understand what mock roles are available.
Apply this diff:
useEffect(() => {
if (authConfig.MOCK_AUTH) {
+ console.log('🔥 MOCK AUTH MODE ENABLED');
+ console.log('📋 Available mock roles:', Object.keys(authConfig.MOCK_USERS));
+
const storedUser = localStorage.getItem('user');
const storedAuthType = localStorage.getItem('authType') as 'email' | 'wallet' | null;
if (storedUser) {
try {
setUser(JSON.parse(storedUser));
setAuthType(storedAuthType);
- console.log('🔥 MOCK AUTH MODE ENABLED');
} catch (error) {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // --- CHECK LOCAL STORAGE ON INIT --- | |
| useEffect(() => { | |
| const checkAuth = () => { | |
| if (authConfig.MOCK_AUTH) { | |
| const storedUser = localStorage.getItem('user'); | |
| const storedAuthType = localStorage.getItem('authType') as 'email' | 'wallet' | null; | |
| if (storedUser) { | |
| try { | |
| const parsedUser = JSON.parse(storedUser); | |
| setUser(parsedUser); | |
| setUser(JSON.parse(storedUser)); | |
| setAuthType(storedAuthType); | |
| console.log('🔥 MOCK AUTH MODE ENABLED'); | |
| } catch (error) { | |
| console.error('Error parsing stored user:', error); | |
| apiUtils.clearAuth(); | |
| } | |
| } | |
| }; | |
| checkAuth(); | |
| } | |
| }, []); | |
| // --- CHECK LOCAL STORAGE ON INIT --- | |
| useEffect(() => { | |
| if (authConfig.MOCK_AUTH) { | |
| console.log('🔥 MOCK AUTH MODE ENABLED'); | |
| console.log('📋 Available mock roles:', Object.keys(authConfig.MOCK_USERS)); | |
| const storedUser = localStorage.getItem('user'); | |
| const storedAuthType = localStorage.getItem('authType') as 'email' | 'wallet' | null; | |
| if (storedUser) { | |
| try { | |
| setUser(JSON.parse(storedUser)); | |
| setAuthType(storedAuthType); | |
| } catch (error) { | |
| console.error('Error parsing stored user:', error); | |
| apiUtils.clearAuth(); | |
| } | |
| } | |
| } | |
| }, []); |
🤖 Prompt for AI Agents
In apps/web/src/hooks/auth/use-auth.tsx around lines 68 to 85, when MOCK_AUTH is
enabled the current console.log only runs if a stored user exists; update the
effect so it logs the available mock users immediately when authConfig.MOCK_AUTH
is true (before or regardless of checking localStorage). Retrieve the mock users
from the existing config (e.g., authConfig.MOCK_USERS or the module that defines
mock roles), and call console.log with a clear message and the list of mock
users; keep the existing stored-user parsing/setting logic intact and avoid
logging any sensitive tokens.
| const { TransactionBuilder, Account, Memo, BASE_FEE } = await import('@stellar/stellar-sdk'); | ||
| const challengeText = challengeResponse.challenge; | ||
| if (challengeText.length > 28) throw new Error('Challenge too long for transaction memo'); | ||
|
|
||
| const walletNetworkPassphrase = networkPassphrase || getNetworkPassphrase(network); | ||
| const targetNetworkName = getNetworkName(network); | ||
|
|
||
| const account = new Account(walletPublicKey, '0'); | ||
| const transaction = new TransactionBuilder(account, { | ||
| fee: BASE_FEE, | ||
| networkPassphrase: walletNetworkPassphrase, | ||
| }) | ||
| .addMemo(Memo.text(challengeText)) | ||
| .setTimeout(30) | ||
| .build(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Validate memo length in bytes, not characters.
At line 154, the validation challengeText.length > 28 checks the string length (UTF-16 code units), but Memo.text() enforces a 28-byte limit. If the challenge contains multi-byte UTF-8 characters, the byte count could exceed 28 even when the string length is ≤28, causing the transaction to fail later. Validate the byte length instead.
Apply this diff:
const { TransactionBuilder, Account, Memo, BASE_FEE } = await import('@stellar/stellar-sdk');
const challengeText = challengeResponse.challenge;
- if (challengeText.length > 28) throw new Error('Challenge too long for transaction memo');
+ const byteLength = new TextEncoder().encode(challengeText).length;
+ if (byteLength > 28) throw new Error('Challenge too long for transaction memo (max 28 bytes)');
const walletNetworkPassphrase = networkPassphrase || getNetworkPassphrase(network);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const { TransactionBuilder, Account, Memo, BASE_FEE } = await import('@stellar/stellar-sdk'); | |
| const challengeText = challengeResponse.challenge; | |
| if (challengeText.length > 28) throw new Error('Challenge too long for transaction memo'); | |
| const walletNetworkPassphrase = networkPassphrase || getNetworkPassphrase(network); | |
| const targetNetworkName = getNetworkName(network); | |
| const account = new Account(walletPublicKey, '0'); | |
| const transaction = new TransactionBuilder(account, { | |
| fee: BASE_FEE, | |
| networkPassphrase: walletNetworkPassphrase, | |
| }) | |
| .addMemo(Memo.text(challengeText)) | |
| .setTimeout(30) | |
| .build(); | |
| const { TransactionBuilder, Account, Memo, BASE_FEE } = await import('@stellar/stellar-sdk'); | |
| const challengeText = challengeResponse.challenge; | |
| const byteLength = new TextEncoder().encode(challengeText).length; | |
| if (byteLength > 28) throw new Error('Challenge too long for transaction memo (max 28 bytes)'); | |
| const walletNetworkPassphrase = networkPassphrase || getNetworkPassphrase(network); | |
| const targetNetworkName = getNetworkName(network); | |
| const account = new Account(walletPublicKey, '0'); | |
| const transaction = new TransactionBuilder(account, { | |
| fee: BASE_FEE, | |
| networkPassphrase: walletNetworkPassphrase, | |
| }) | |
| .addMemo(Memo.text(challengeText)) | |
| .setTimeout(30) | |
| .build(); |
🤖 Prompt for AI Agents
In apps/web/src/hooks/auth/use-auth.tsx around lines 152 to 166, the code
currently checks challengeText.length > 28 (characters) but Memo.text() limits
the memo to 28 bytes; change the validation to measure UTF-8 byte length (e.g.,
use TextEncoder().encode(challengeText).length or
Buffer.byteLength(challengeText, 'utf8')) and throw the same error if the byte
length exceeds 28 so multi-byte characters are correctly validated before
creating the transaction.
Closes #164
Summary by CodeRabbit
New Features
Refactor