omnibiofex 2.8.2 → 2.8.3

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omnibiofex",
3
- "version": "2.8.2",
3
+ "version": "2.8.3",
4
4
  "description": "OmniBioFex X - The Autonomous Research Terminal for AI-powered research missions",
5
5
  "main": "bin/obx",
6
6
  "bin": {
@@ -1,7 +1,7 @@
1
1
  const chalk = require('chalk');
2
2
  const open = require('open');
3
3
  const { getAuthToken, isAuthenticated } = require('../auth');
4
- const { db, auth } = require('../firebase');
4
+ const { db, getCurrentUserUid, getCurrentUserEmail } = require('../firebase');
5
5
  const { PremiumSpinner, sleep } = require('../utils/display');
6
6
  const { collection, query, where, getDocs } = require('firebase/firestore');
7
7
 
@@ -61,22 +61,24 @@ async function usage() {
61
61
  return;
62
62
  }
63
63
 
64
+ // Get user UID from stored token
65
+ const uid = getCurrentUserUid();
66
+ const email = getCurrentUserEmail();
67
+
68
+ if (!uid) {
69
+ console.error(chalk.red('āœ— Could not extract user ID from token.'));
70
+ console.error(chalk.gray('Please run: obx login'));
71
+ return;
72
+ }
73
+
64
74
  const spinner = new PremiumSpinner('Fetching usage statistics');
65
75
  spinner.start();
66
76
 
67
77
  try {
68
- const user = auth.currentUser;
69
-
70
- if (!user) {
71
- spinner.fail('Not authenticated');
72
- console.error(chalk.red('Please run: obx login'));
73
- return;
74
- }
75
-
76
78
  // Fetch ALL missions (real data)
77
79
  const allMissionsQuery = query(
78
80
  collection(db, 'missions'),
79
- where('uid', '==', user.uid)
81
+ where('uid', '==', uid)
80
82
  );
81
83
 
82
84
  const allMissionsSnapshot = await getDocs(allMissionsQuery);
@@ -99,7 +101,7 @@ async function usage() {
99
101
  // Fetch published missions for earnings
100
102
  const publishedQuery = query(
101
103
  collection(db, 'missions'),
102
- where('uid', '==', user.uid),
104
+ where('uid', '==', uid),
103
105
  where('isPublished', '==', true)
104
106
  );
105
107
 
@@ -122,7 +124,10 @@ async function usage() {
122
124
  console.log(chalk.white.bold('šŸ“Š USAGE STATISTICS'));
123
125
  console.log(chalk.hex('#F24E1E')('═══════════════════════════════════════════════════════════\n'));
124
126
 
125
- console.log(chalk.white(` šŸŽÆ Total Missions: ${chalk.green(totalMissions)}`));
127
+ console.log(chalk.gray(` šŸ‘¤ User: ${chalk.white(email || 'Unknown')}`));
128
+ console.log(chalk.gray(` šŸ†” UID: ${chalk.gray(uid.substring(0, 16))}...`));
129
+
130
+ console.log(chalk.white(`\n šŸŽÆ Total Missions: ${chalk.green(totalMissions)}`));
126
131
  console.log(chalk.white(` āœ… Completed: ${chalk.green(completedMissions)}`));
127
132
  console.log(chalk.white(` ā³ Active: ${chalk.yellow(activeMissions)}`));
128
133
  console.log(chalk.white(` ⛽ RCC Spent: ${chalk.green(totalRCCSpent.toLocaleString())}`));
@@ -1,6 +1,6 @@
1
1
  const chalk = require('chalk');
2
- const { getAuthToken, isAuthenticated } = require('../auth');
3
- const { db, auth } = require('../firebase');
2
+ const { isAuthenticated } = require('../auth');
3
+ const { db, getCurrentUserUid, getCurrentUserEmail, isTokenValid } = require('../firebase');
4
4
  const { PremiumSpinner, sleep } = require('../utils/display');
5
5
  const { collection, query, where, orderBy, limit, getDocs } = require('firebase/firestore');
6
6
 
@@ -10,22 +10,24 @@ async function earnings() {
10
10
  return;
11
11
  }
12
12
 
13
+ // Get user UID from stored token (NOT from auth.currentUser)
14
+ const uid = getCurrentUserUid();
15
+ const email = getCurrentUserEmail();
16
+
17
+ if (!uid) {
18
+ console.error(chalk.red('āœ— Could not extract user ID from token.'));
19
+ console.error(chalk.gray('Please run: obx login'));
20
+ return;
21
+ }
22
+
13
23
  const spinner = new PremiumSpinner('Fetching your earnings data');
14
24
  spinner.start();
15
25
 
16
26
  try {
17
- const user = auth.currentUser;
18
-
19
- if (!user) {
20
- spinner.fail('Not authenticated');
21
- console.error(chalk.red('Please run: obx login'));
22
- return;
23
- }
24
-
25
27
  // Fetch real published missions with earnings data
26
28
  const publishedQuery = query(
27
29
  collection(db, 'missions'),
28
- where('uid', '==', user.uid),
30
+ where('uid', '==', uid),
29
31
  where('isPublished', '==', true),
30
32
  orderBy('publishedAt', 'desc'),
31
33
  limit(100)
@@ -73,8 +75,11 @@ async function earnings() {
73
75
  console.log(chalk.hex('#F24E1E')('\n═══════════════════════════════════════════════════════════'));
74
76
  console.log(chalk.white.bold('šŸ’° EARNINGS DASHBOARD'));
75
77
  console.log(chalk.hex('#F24E1E')('═══════════════════════════════════════════════════════════\n'));
78
+
79
+ console.log(chalk.gray(` šŸ‘¤ User: ${chalk.white(email || 'Unknown')}`));
80
+ console.log(chalk.gray(` šŸ†” UID: ${chalk.gray(uid.substring(0, 16))}...`));
76
81
 
77
- console.log(chalk.white.bold('šŸ“Š OVERVIEW'));
82
+ console.log(chalk.white.bold('\n\nšŸ“Š OVERVIEW'));
78
83
  console.log(chalk.gray('─'.repeat(60)));
79
84
  console.log(chalk.white(`\n šŸ’° Total Earnings: ${chalk.green('₹' + totalEarnings.toLocaleString())}`));
80
85
  console.log(chalk.white(` šŸ“… This Month: ${chalk.green('₹' + thisMonthEarnings.toLocaleString())}`));
@@ -112,6 +117,9 @@ async function earnings() {
112
117
  console.log(chalk.white(` šŸ’° Earnings: ${chalk.green('₹' + (m.earnings || 0).toLocaleString())}`));
113
118
  console.log(chalk.gray(` šŸ“… Published: ${publishedDate}`));
114
119
  });
120
+ } else {
121
+ console.log(chalk.yellow('\n\n āš ļø No published research yet.'));
122
+ console.log(chalk.gray(' Run "obx publish" to publish your first research and start earning.\n'));
115
123
  }
116
124
 
117
125
  console.log(chalk.hex('#F24E1E')('\n═══════════════════════════════════════════════════════════\n'));
@@ -1,7 +1,7 @@
1
1
  const chalk = require('chalk');
2
2
  const inquirer = require('inquirer');
3
3
  const { getAuthToken, isAuthenticated } = require('../auth');
4
- const { db, auth } = require('../firebase');
4
+ const { db, getCurrentUserUid, getCurrentUserEmail } = require('../firebase');
5
5
  const { PremiumSpinner, sleep } = require('../utils/display');
6
6
  const { collection, query, where, orderBy, limit, getDocs, doc, updateDoc } = require('firebase/firestore');
7
7
 
@@ -11,30 +11,35 @@ async function publish(missionId) {
11
11
  return;
12
12
  }
13
13
 
14
+ // Get user UID from stored token
15
+ const uid = getCurrentUserUid();
16
+ const email = getCurrentUserEmail();
17
+
18
+ if (!uid) {
19
+ console.error(chalk.red('āœ— Could not extract user ID from token.'));
20
+ console.error(chalk.gray('Please run: obx login'));
21
+ return;
22
+ }
23
+
14
24
  console.log(chalk.hex('#F24E1E')('\n═══════════════════════════════════════════════════════════'));
15
25
  console.log(chalk.white.bold('šŸ“¤ PUBLISH RESEARCH'));
16
26
  console.log(chalk.hex('#F24E1E')('═══════════════════════════════════════════════════════════\n'));
27
+
28
+ console.log(chalk.gray(` šŸ‘¤ User: ${chalk.white(email || 'Unknown')}`));
29
+ console.log(chalk.gray(` šŸ†” UID: ${chalk.gray(uid.substring(0, 16))}...`));
17
30
 
18
31
  // If no mission ID provided, fetch real missions from Firestore
19
32
  if (!missionId) {
20
- console.log(chalk.gray('Fetching your completed missions...\n'));
33
+ console.log(chalk.gray('\nFetching your completed missions...\n'));
21
34
 
22
35
  const spinner = new PremiumSpinner('Loading missions from database');
23
36
  spinner.start();
24
37
 
25
38
  try {
26
- const user = auth.currentUser;
27
-
28
- if (!user) {
29
- spinner.fail('Not authenticated');
30
- console.error(chalk.red('Please run: obx login'));
31
- return;
32
- }
33
-
34
39
  // Fetch real completed missions from Firestore
35
40
  const missionsQuery = query(
36
41
  collection(db, 'missions'),
37
- where('uid', '==', user.uid),
42
+ where('uid', '==', uid),
38
43
  where('status', '==', 'completed'),
39
44
  where('isPublished', '==', false),
40
45
  orderBy('createdAt', 'desc'),
@@ -140,8 +145,8 @@ async function publish(missionId) {
140
145
  downloads: 0,
141
146
  citations: 0,
142
147
  earnings: 0,
143
- authorName: missionData.authorName || 'Anonymous Researcher',
144
- authorEmail: missionData.authorEmail || 'unknown@example.com'
148
+ authorName: email || 'Anonymous Researcher',
149
+ authorEmail: email || 'unknown@example.com'
145
150
  });
146
151
 
147
152
  spinner.succeed('Research published successfully!');
package/src/firebase.js CHANGED
@@ -1,6 +1,7 @@
1
1
  const { initializeApp, getApps } = require('firebase/app');
2
2
  const { getAuth } = require('firebase/auth');
3
3
  const { getFirestore } = require('firebase/firestore');
4
+ const Conf = require('conf');
4
5
 
5
6
  const firebaseConfig = {
6
7
  apiKey: "AIzaSyDlgXId4pLlYqm-MDuhfz3dLH24KBRHkw8",
@@ -22,4 +23,82 @@ if (getApps().length === 0) {
22
23
  const auth = getAuth(app);
23
24
  const db = getFirestore(app);
24
25
 
25
- module.exports = { app, auth, db };
26
+ // Shared Conf storage for tokens
27
+ const tokenStore = new Conf({
28
+ projectName: 'omnibiofex',
29
+ schema: {
30
+ token: { type: 'string' },
31
+ refreshToken: { type: 'string' },
32
+ expiresAt: { type: 'number' }
33
+ }
34
+ });
35
+
36
+ /**
37
+ * Decode JWT token to extract user info
38
+ * @returns {Object|null} - { uid, email } or null if no token
39
+ */
40
+ function decodeToken() {
41
+ const token = tokenStore.get('token');
42
+ if (!token) return null;
43
+
44
+ try {
45
+ // JWT format: header.payload.signature
46
+ const parts = token.split('.');
47
+ if (parts.length !== 3) return null;
48
+
49
+ // Decode payload (base64url)
50
+ const payload = parts[1];
51
+ const decoded = Buffer.from(payload, 'base64').toString('utf8');
52
+ const data = JSON.parse(decoded);
53
+
54
+ return {
55
+ uid: data.user_id || data.sub,
56
+ email: data.email,
57
+ exp: data.exp
58
+ };
59
+ } catch (error) {
60
+ return null;
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Get current user UID from stored token
66
+ * @returns {string|null} - User UID or null
67
+ */
68
+ function getCurrentUserUid() {
69
+ const decoded = decodeToken();
70
+ return decoded ? decoded.uid : null;
71
+ }
72
+
73
+ /**
74
+ * Get current user email from stored token
75
+ * @returns {string|null} - User email or null
76
+ */
77
+ function getCurrentUserEmail() {
78
+ const decoded = decodeToken();
79
+ return decoded ? decoded.email : null;
80
+ }
81
+
82
+ /**
83
+ * Check if token is valid (not expired)
84
+ * @returns {boolean}
85
+ */
86
+ function isTokenValid() {
87
+ const decoded = decodeToken();
88
+ if (!decoded || !decoded.exp) return false;
89
+
90
+ // JWT exp is in seconds, Date.now() is in milliseconds
91
+ const now = Math.floor(Date.now() / 1000);
92
+ return decoded.exp > now;
93
+ }
94
+
95
+ module.exports = {
96
+ app,
97
+ auth,
98
+ db,
99
+ tokenStore,
100
+ decodeToken,
101
+ getCurrentUserUid,
102
+ getCurrentUserEmail,
103
+ isTokenValid
104
+ };