📣 Hello Hive Community Members!
Welcome back to my wild ReactJS learning ride 🎢 — and guess what? We’re already on Day 8! If you've missed previous episodes, don't worry. Grab some popcorn 🍿 and catch up below:
📖 ReactJS Journey So Far
- 📚 Day One: Fresh React app + AIOHA integration!
- 🧭 Day Two: Routing drama & rebellious NavBar 😤
- 🛠️ Day Three: Fixed Layouts, Routing & AIOHA 💥
- 🧠 Day Four: useState, useEffect, and .env headaches 😅
- 🧹 Day Five: Path Aliases to clean up relative path spaghetti 🍝
- 📡 Day Six: Create Context Provider & call API
- 🍞 Day Seven: Show a toast message
🚀 What’s New in Day 8?
In this episode, I went full-on security ninja. 🥷 Here's what I implemented:
- 🔐 Login API with @aioha & distriator combo
- 📦 Storing user data securely in
localStorage
using AES encryption & base64 encoding - ✅ Upsert logic for managing multiple Hive logins
🧠 Data Modeling Like a Boss
📁 Folder: src/types/LoginApiRequestResponse.tsx
export interface LoginRequestDTO {
challenge: string;
proof: string;
pubkey: string;
username: string;
}
export interface LoginSuccessResponseDTO {
token: string;
type: string;
}
export interface LocalStorageUserDTO {
token: string;
type: string;
challenge: string;
proof: string;
pubkey: string;
username: string;
}
export interface LoginErrorResponseDTO {
error: string;
}
💾 Encrypting User Data in LocalStorage
📁 File: src/utils/LocalStorageUtils.tsx
Let’s bring in the secret scrolls of utility magic! 🧙
🔐 Base64 Helper Spells
function toBase64(str: string): string {
return typeof window !== "undefined"
? window.btoa(unescape(encodeURIComponent(str)))
: Buffer.from(str, "utf-8").toString("base64");
}
function fromBase64(b64: string): string {
return typeof window !== "undefined"
? decodeURIComponent(escape(window.atob(b64)))
: Buffer.from(b64, "base64").toString("utf-8");
}
📥 Retrieve Users from LocalStorage (aka Decrypt Scroll)
export function getLoggedInUsers(): LocalStorageUserDTO[] {
const apiKey = import.meta.env.VITE_LOCAL_KEY;
const data = localStorage.getItem("logged-in-users") || "";
const decrypteText = CryptoJS.AES.decrypt(data, apiKey).toString(
CryptoJS.enc.Utf8
);
if (!data) return [];
try {
const jsonStr = fromBase64(decrypteText);
return JSON.parse(jsonStr);
} catch (e) {
console.error("Failed to decode/parse localStorage ", e);
return [];
}
}
📝 Steps:
- Get 🔐 key from
.env
- Decrypt → decode → parse → return!
📝 Store/Update New Logged-In Users (Avengers-like registry 🦸)
export function setLoggedInUsers(users: LocalStorageUserDTO[]): void {
try {
const apiKey = import.meta.env.VITE_DEKEY;
const jsonStr = JSON.stringify(users);
const base64Str = toBase64(jsonStr);
const encryptedText = CryptoJS.AES.encrypt(base64Str, apiKey).toString();
localStorage.setItem("logged-in-users", encryptedText);
} catch (e) {
console.error("Failed to encode/set localStorage ", e);
}
}
🔄 Save/Update User Info (like a React-powered CRM 😎)
export function saveOrUpdateUser(newUser: LocalStorageUserDTO): void {
const users = getLoggedInUsers();
const idx = users.findIndex((user) => user.username === newUser.username);
if (idx !== -1) {
users[idx] = newUser;
} else {
users.push(newUser);
}
setLoggedInUsers(users);
}
🙅♂️ No remove logic yet — coming with future logout feature. Stay tuned!
🔌 Calling the Login API – FTW!
📁 File: src/api/LoginApi.tsx
Here’s how the server handshake looks:
export const loginApi = async (challenge, proof, pubkey, username): Promise<null | string> => {
try {
const rqst: LoginRequestDTO = { challenge, proof, pubkey, username };
const response = await fetch("https://beta-api.distriator.com/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(rqst),
});
if (!response.ok) {
const errorBody: LoginErrorResponseDTO = await response.json();
console.error("Login failed:", errorBody);
return `Error - ${errorBody.error}`;
}
const success: LoginSuccessResponseDTO = await response.json();
const updatedUser: LocalStorageUserDTO = { ...rqst, token: success.token, type: success.type };
saveOrUpdateUser(updatedUser);
return null;
} catch (error) {
console.error("Network error:", error);
return `Network error - ${error.message}`;
}
};
🔥 Boom! Now you're securely logged in and your data is sealed like Wakanda tech! 🛡️
🤝 AIOHA + Distriator Login Combo 💪
📁 File: src/components/HiveUserAvatarButton.tsx
We've glued it all together using @aioha/react-ui
. 🧩
<AiohaModal
displayed={modalDisplayed}
loginOptions={{
msg: proof,
keyType: KeyTypes.Posting,
}}
onLogin={performLogin}
onClose={setModalDisplayed}
/>
And here’s the magic performLogin
function:
async function performLogin(result: LoginResult) {
if (result.success) {
const loginResult = await loginApi(result.result, proof, result.publicKey || "none", result.username);
if (loginResult == null) {
console.log("🎉 Logged in successfully!");
} else {
console.error(`Login failed: ${loginResult}`);
}
} else {
console.error(result.error || "Something went wrong");
}
}
🎯 Wrapping Up
This was a deep dive into login flows, secure data handling & functional integration of blockchain login workflows! 🧩
That's it for now, folks! Thank you so much for reading my post. 💙
More power to the Hive Blockchain 🐝
More power to all our community members 🙌
Until next time, Happy Coding! 💻✨
📝 Final Note
- I asked AI to help optimize this post to make it more readable and viewer-friendly.
- Here is the link where you can find both original content & improvements made by AI
- https://www.perplexity.ai/search/e4abc965-4e52-442b-b001-ab6942995dff
🚀 My Contributions to ♦️ Hive Ecosystem
Contribution | To | Hive | Ecosystem |
---|---|---|---|
Hive Witness Node | Hive API Node (in progress) | 3Speak Video Encoder Node Operator (highest number of nodes) | 3Speak Mobile App Developer |
3Speak Podcast App Developer | 3Speak Shorts App Developer | 3Speak Support & Maintenance Team | Distriator Developer |
CheckinWithXYZ | Hive Inbox | HiFind | Hive Donate App |
Contributed to HiveAuth Mobile App | Ecency ↔ 3Speak Integration | Ecency ↔ InLeo Integration | Ecency ↔ Actifit Integration |
Hive Stats App | Vote for Witness App | HiveFlutterKit | New 3Speak App |
🙌 Support Back
❤️ Appreciate my work? Consider supporting @threespeak & @sagarkothari88! ❤️
Vote | For | Witness |
---|---|---|
sagarkothari88 | @sagarkothari88 | |
threespeak | @threespeak |