๐ฃ 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
& distriator combo
- ๐ฆ Storing user data securely in
localStorageusing 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 &
! โค๏ธ
| Vote | For | Witness |
|---|---|---|
| sagarkothari88 | ||
| threespeak |