Skip to content

Enable self service#175

Merged
elliotBraem merged 170 commits intomainfrom
staging
Jun 20, 2025
Merged

Enable self service#175
elliotBraem merged 170 commits intomainfrom
staging

Conversation

@elliotBraem
Copy link
Collaborator

@elliotBraem elliotBraem commented Jun 17, 2025

Summary by CodeRabbit

  • New Features

    • Added a user profile settings page with platform account connection and listing.
    • Introduced unified authentication context and NEAR wallet integration for sign-in/sign-out.
    • Added moderation permission checks and endpoints for feeds.
    • Enabled Telegram integration configuration for feeds.
    • Provided hooks and UI for connecting social platform accounts.
    • Introduced typed API hooks for activity, leaderboard, feeds, moderation, plugins, submissions, Twitter, and users.
    • Added centralized API client with authentication support and error handling.
    • Added NEAR Social profile fetching hook and utilities.
    • Added Crosspost SDK integration with hooks for connected accounts and account linking.
    • Introduced refined database schema with feed creators and admin management.
    • Added new error classes for authorization and moderation service errors.
    • Introduced a new ConnectPlatform button component for social account connections.
    • Added detailed feed output stream configuration with AI and Telegram plugins.
    • Added React Query hooks for plugin management replacing deprecated plugin hooks.
    • Added route for profile settings and simplified profile route structure.
    • Added API endpoint and hook to check feed moderation permissions.
  • Improvements

    • Refactored user authentication and profile management for consistency and NEAR account support.
    • Enhanced moderation, user, and feed APIs with strong validation, error handling, and response schemas.
    • Simplified and unified state management for authentication and feed creation.
    • Updated and optimized database schema for user and feed admin management.
    • Improved error serialization to better handle validation errors.
    • Updated UI components to use new auth context and social profile hooks.
    • Consolidated moderation mutation hooks into a single unified hook.
    • Streamlined API route handlers with schema validation and structured responses.
    • Improved database repository methods with consistent naming and error handling.
    • Generalized feed distribution badges to support multiple plugins.
    • Replaced legacy wallet selector with direct NEAR wallet integration.
    • Refined route tree structure by removing intermediate profile routes and adding profile settings route.
    • Simplified database ORM initialization with explicit casing option.
    • Improved logging and error handling in moderation and user services.
    • Updated dependency versions and removed unused packages.
    • Enhanced feed creation form with detailed output stream and Telegram integration.
    • Replaced multiple authentication and profile hooks with a single unified auth context.
    • Improved API client with typed hooks and integrated authentication context.
    • Updated UserMenu and ProfileHeader components to use new auth and profile hooks.
    • Streamlined state management for platform accounts and removed redundant stores.
    • Improved database migration scripts with explicit type casting in timestamp columns.
    • Added feature flag support for distribution enabling in configuration and distribution services.
    • Improved Docker and development environment setup for database migration and seeding.
  • Bug Fixes

    • Standardized error responses and improved error logging across API routes.
    • Fixed issues with user deletion and NEAR account handling.
  • Removals

    • Removed legacy Web3Auth authentication, modal-based auth flows, and related state stores.
    • Deleted unused or redundant files related to old authentication and user management.
    • Removed deprecated plugin API hooks and Twitter action utilities.
    • Removed old Near wallet provider and related wallet selector packages.
    • Deleted legacy API client and authentication service files.
    • Removed authorization event bus and related hooks.
    • Removed user activity and authorization status hooks no longer in use.
    • Removed legacy authentication context and web3auth hooks.
    • Deleted multiple authentication modal components and related UI.
    • Removed old feed plugin API hooks in favor of new plugin hooks.
    • Removed deprecated near-method blockchain interaction utilities.
    • Removed platform accounts store and related hooks.
    • Removed rspack bundler configuration and related plugins from shared-db package.
  • Chores

    • Updated dependencies and streamlined TypeScript, build, and Docker configurations.
    • Cleaned up and reorganized database migration and seeding scripts.
    • Improved codebase structure and type safety with new shared types and schemas.
    • Simplified TypeScript configs to inherit from root configurations.
    • Added global TypeScript declarations for FastIntear on window object.
    • Streamlined development environment setup script for database migrations and seeding.
    • Updated docker-compose to focus on development migrations and seeding.
    • Added new API modules and re-exported them for centralized imports.
    • Improved logging in error handlers and service methods.
    • Refactored imports and code organization for clarity and consistency.
    • Removed unused imports and commented out deprecated UI components and features.

itexpert120 and others added 30 commits March 24, 2025 21:25
* Get basic working

* adds rss feeds

* added stablewatch founder and stablecoin intern from messaria as approvers on stablecoins feed

* fixes to config for grants, sui, and telegram channels (#102)

* add query param for selective processing (#103)

* adds query param to process

* add query param for processing

* simplify

* add tags

* Feat: implement frontend leaderboard (#93)

* feat: implement frontend leaderboard

* feat: implement a leaderboard in frontend

* feat: implemented leaderboard

* fix: rebuild implement leaderboard

* fix: prettier

* fix: prettier

* fix: reimplement frontend leaderboard

* fix: implement frontend leaderboard

* approval rate

* sets approval rate and hides curator

---------

Co-authored-by: Elliot Braem <elliot@ejlbraem.com>

* remove tailwind-scrollbar

* added bob to desci feed

* Get basic working

* set .env.example

* nitpicks

---------

Co-authored-by: Elliot Braem <elliot@ejlbraem.com>
Co-authored-by: codingshot <45281667+codingshot@users.noreply.github.com>
Co-authored-by: Elliot Braem <elliot@everything.dev>
Co-authored-by: Louis <112561517+louisdevzz@users.noreply.github.com>
* Explore Page - commit-1

* Explore Page - commit-2

* explore page - commit-3

* explore page - commit - 4

* explore page - commit - prettier

* explore page responsiveness + code Rabbit Comments

* code Rabbit Comments resolved

* css updates

* css changes 2

* header update + mobile responsive

* conflicts resolved

* Rebase and changes

* Fix fmt
* Explore Page - commit-1

* Explore Page - commit-2

* explore page - commit-3

* explore page - commit - 4

* explore page - commit - prettier

* explore page responsiveness + code Rabbit Comments

* code Rabbit Comments resolved

* css updates

* css changes 2

* header update + mobile responsive

* conflicts resolved

* Rebase and changes

* Fix fmt

* Header Updates + Web3Auth getUserInfo + Explore Page changes

* fmt

* coderabbit comments resolved
* Update the FE to have the profile page (header and tabs init)

* Move tabs to it's own component

* Add stats and top badges to overview

* Finish the overview tab

* Update overview page and init content page

* feat(profile-page): add Content and My Feed tags

* feat(profile-page): finish profile page static UI

* refactor: fmt
* Curate Engine Step 1

* content-progress-configuration step-1

* Curation Settings Part 2 and 3

* CodeRabbit Comments Resolved + Mobile Responsive

* Responsiveness: empty State, JSON check

---------

Co-authored-by: Elliot Braem <elliot@everything.dev>
* Submissions Page + Feed Page + Mobile Responsiveness

* fixes

* craete-feed authenticated user condition

* fmt

* remove sqlite

---------

Co-authored-by: Elliot Braem <elliot@ejlbraem.com>
* feat: Add connect button to feed page

* fix: recommit

* added back to stablecoins feed since stablewatch forked their own

* fix packages, update pg, and ignore cloudflare sockets

* fmt

---------

Co-authored-by: ethnclark <ethanclark1310@gmail.com>
Co-authored-by: codingshot <45281667+codingshot@users.noreply.github.com>
Co-authored-by: Elliot Braem <elliot@ejlbraem.com>
* fix: Sort By Oldest

* fix: Sort By Oldest

* fix: Fix RecentSubmissions Sort Order Update

* fix: All feed should be hidden, remove double title

---------

Co-authored-by: vohuunhan1310@gmail.com <ethanclark1310@gmail.com>
* UI fixes

* fmt

---------

Co-authored-by: Elliot Braem <elliot@everything.dev>
* fix: Leaderboard improvements

* fix: fmt

* reorganize

* remove unused

* rename

* clean up

* fmt

---------

Co-authored-by: Elliot Braem <elliot@ejlbraem.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
apps/api/src/services/moderation.service.ts (1)

136-136: Replace hardcoded platform string with enum or constant.

The hardcoded "twitter" string is used throughout the file, creating maintenance overhead and potential for typos.

Extract this to a constant or use a SubmissionPlatform enum:

+const SUBMISSION_PLATFORM = "twitter" as const;

-      const submissionPlatform = "twitter";
+      const submissionPlatform = SUBMISSION_PLATFORM;

This same pattern appears at lines 393 and should be consistently addressed.

🧹 Nitpick comments (3)
apps/api/src/services/moderation.service.ts (3)

173-197: Consider extracting permission check logic for better maintainability.

While the duplication mentioned in past reviews has been partially addressed, the permission checking logic is still complex and could benefit from extraction.

Consider extracting the authorization logic:

+  private async checkModerationAuthorization(
+    actingAccountId: string,
+    submissionPlatform: string,
+    configuredApproverPlatformIds: string[]
+  ): Promise<{ isAuthorized: boolean; adminIdForHistory: string }> {
+    // Check if super admin first
+    if (isSuperAdmin(actingAccountId, this.superAdminAccounts)) {
+      return { isAuthorized: true, adminIdForHistory: actingAccountId };
+    }
+
+    // Check against configured platform-specific approvers
+    for (const configuredApproverId of configuredApproverPlatformIds) {
+      if (await this.canModerateSubmission(actingAccountId, submissionPlatform, configuredApproverId)) {
+        return { isAuthorized: true, adminIdForHistory: configuredApproverId };
+      }
+    }
+
+    return { isAuthorized: false, adminIdForHistory: actingAccountId };
+  }

-      let isAuthorized = false;
-      let adminIdForHistory = actingAccountId; // Default to NEAR ID (for super admins or if no specific platform match is made but still authorized)
-
-      // Check if super admin first
-      if (isSuperAdmin(actingAccountId, this.superAdminAccounts)) {
-        isAuthorized = true;
-        // adminIdForHistory remains actingAccountId (NEAR ID) for super admin actions
-      } else {
-        // If not super admin, check against configured platform-specific approvers
-        for (const configuredApproverId of configuredApproverPlatformIds) {
-          // configuredApproverId is a platform username like "twitterUser123"
-          // canModerateSubmission checks if actingAccountId (NEAR) is linked to this configuredApproverId (platform username)
-          if (
-            await this.canModerateSubmission(
-              actingAccountId,
-              submissionPlatform,
-              configuredApproverId,
-            )
-          ) {
-            isAuthorized = true;
-            adminIdForHistory = configuredApproverId; // Log the platform-specific ID that granted permission
-            break;
-          }
-        }
-      }
+      const { isAuthorized, adminIdForHistory } = await this.checkModerationAuthorization(
+        actingAccountId,
+        submissionPlatform,
+        configuredApproverPlatformIds
+      );

284-294: Improve error handling consistency in updateStatusAndProcess.

The error handling improvements look good, but consider the error message consistency and logging patterns.

The error handling is well-structured. Consider making the error message more descriptive:

-        throw new NotFoundError(
-          `Feed configuration for feed ${feedEntry.feedId}`,
-        );
+        throw new NotFoundError(
+          "Feed configuration",
+          `feed ${feedEntry.feedId}`
+        );

409-431: Potential performance concern with sequential API calls.

The method loops through configured approvers and makes sequential calls to canModerateSubmission, each potentially calling the Crosspost API.

Consider optimizing by fetching connected accounts once:

+  private async getConnectedAccountsForUser(actingAccountId: string): Promise<ConnectedAccountsResponse['accounts'] | null> {
+    try {
+      const crosspost = new CrosspostClient();
+      crosspost.setAccountHeader(actingAccountId);
+      const response = await crosspost.auth.getConnectedAccounts();
+      return response.success ? response.data?.accounts || null : null;
+    } catch (error) {
+      this.logger.error({ actingAccountId, error }, "Failed to fetch connected accounts");
+      return null;
+    }
+  }

Then modify the permission check to use the cached connected accounts instead of making repeated API calls.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2a9db51 and e2b8161.

📒 Files selected for processing (2)
  • apps/api/src/services/moderation.service.ts (7 hunks)
  • apps/app/src/components/FeedItem.tsx (8 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/app/src/components/FeedItem.tsx
🔇 Additional comments (1)
apps/api/src/services/moderation.service.ts (1)

446-474: Excellent addition of schema validation for API responses.

The addition of ModerationActionSchema.parse() validation ensures data integrity and type safety for API responses.

This approach prevents potential runtime errors from malformed data and provides better error messages when validation fails.

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (3)
apps/api/src/services/moderation.service.ts (3)

54-110: Address performance and error handling concerns from previous review.

This method still creates a new CrosspostClient instance on every permission check and has the error handling issues previously identified.

The concerns raised in the previous review about optimizing CrosspostClient usage and improving error handling remain valid and should be addressed.


144-221: Extract duplicated authorization logic and eliminate magic strings.

This permission checking code duplicates the same authorization pattern found in canModerateSubmission and checkUserFeedModerationPermission. The hardcoded "twitter" string should also be replaced with a constant.

As mentioned in the previous review, consolidate the duplicated permission logic by extracting a single private helper method that all public methods can delegate to. Also replace the magic string with a proper constant or enum.

+ private static readonly DEFAULT_SUBMISSION_PLATFORM = "twitter";
+
+ private async _isAuthorizedModerator(
+   actingAccountId: string,
+   feedId: string,
+   platform: string = ModerationService.DEFAULT_SUBMISSION_PLATFORM
+ ): Promise<{ isAuthorized: boolean; adminIdForHistory: string }> {
+   // Consolidated authorization logic here
+ }

- const submissionPlatform = "twitter";
+ const submissionPlatform = ModerationService.DEFAULT_SUBMISSION_PLATFORM;

368-455: Consolidate the duplicated permission checking logic.

This method re-implements the same authorization logic as canModerateSubmission and the permission checks in createModerationAction, violating the DRY principle.

Extract the repeated super admin check and platform approver validation into a shared private helper method as mentioned in the previous review. This will reduce maintenance overhead and prevent future divergence.

🧹 Nitpick comments (1)
apps/api/src/services/moderation.service.ts (1)

1-1: Fix Prettier formatting issues.

The pipeline indicates formatting issues that need to be resolved.

Run the following command to fix the formatting:

npx prettier --write apps/api/src/services/moderation.service.ts
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e2b8161 and a23e5fd.

📒 Files selected for processing (2)
  • apps/api/src/services/moderation.service.ts (7 hunks)
  • apps/app/src/lib/near.ts (1 hunks)
🧰 Additional context used
🪛 GitHub Actions: CI
apps/api/src/services/moderation.service.ts

[warning] 1-1: Prettier formatting warning: Code style issues found. Run Prettier with --write to fix.

apps/app/src/lib/near.ts

[error] 7-7: Prettier syntax error: ':' expected at line 7. Syntax issue likely due to malformed type annotation or export statement.

🪛 Biome (1.9.4)
apps/app/src/lib/near.ts

[error] 6-7: expected : but instead found export

Remove export

(parse)


[error] 7-7: Shouldn't redeclare 'near'. Consider to delete it or rename it.

'near' is defined here:

(lint/suspicious/noRedeclare)

🔇 Additional comments (3)
apps/api/src/services/moderation.service.ts (3)

1-45: LGTM on imports and constructor changes.

The new imports for Crosspost SDK, error types, and auth utilities are well-organized and support the enhanced moderation functionality. The constructor update to include superAdminAccounts is appropriate.


288-360: Well-implemented error handling and transaction management.

The enhanced error handling with custom error types and comprehensive logging in this helper method is excellent. The transaction-based approach ensures data consistency.


458-486: Good use of schema validation in data retrieval methods.

The new data retrieval methods properly use ModerationActionSchema.parse() for validation, ensuring type safety and data consistency.

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@elliotBraem elliotBraem merged commit ebf386c into main Jun 20, 2025
6 of 8 checks passed
@elliotBraem elliotBraem deleted the staging branch June 20, 2025 16:01
@elliotBraem elliotBraem restored the staging branch June 20, 2025 16:01
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (2)
apps/api/src/services/moderation.service.ts (2)

47-69: Consolidate duplicated authorization logic.

The permission checking logic is duplicated between checkModerationAuthorization, canModerateSubmission, and checkUserFeedModerationPermission. This increases maintenance overhead and risks divergence.

Extract the common authorization logic into a private helper method to eliminate duplication and ensure consistency across all permission checks.

Also applies to: 356-443


480-480: Optimize CrosspostClient instantiation.

Creating a new CrosspostClient instance for each permission check impacts performance and doesn't leverage connection pooling or caching.

Consider initializing a single CrosspostClient instance as a class property to reuse across multiple calls, or implement a caching mechanism for connected accounts.

🧹 Nitpick comments (2)
apps/api/src/services/config.service.ts (2)

15-15: Remove unnecessary constructor.

The constructor is empty and unnecessary. TypeScript will automatically generate a default constructor.

-  public constructor() {}

10-12: Simplify Boolean conversion logic.

The Boolean() wrapper is redundant since the || false already handles falsy values correctly.

 export const featureFlags = {
-  enableDistribution: Boolean(process.env.ENABLE_DISTRIBUTION) || false,
+  enableDistribution: !!process.env.ENABLE_DISTRIBUTION,
 };
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 136ac33 and c9acc8d.

📒 Files selected for processing (4)
  • apps/api/src/services/config.service.ts (1 hunks)
  • apps/api/src/services/distribution.service.ts (5 hunks)
  • apps/api/src/services/moderation.service.ts (7 hunks)
  • apps/api/src/utils/service-provider.ts (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/api/src/utils/service-provider.ts
🧰 Additional context used
🪛 Biome (1.9.4)
apps/api/src/services/config.service.ts

[error] 15-15: This constructor is unnecessary.

Unsafe fix: Remove the unnecessary constructor.

(lint/complexity/noUselessConstructor)

🔇 Additional comments (4)
apps/api/src/services/distribution.service.ts (2)

5-5: LGTM! Clean refactoring to use dynamic feature flags.

The dependency injection of ConfigService and replacement of static isStaging checks with dynamic feature flag evaluation is well-implemented. This provides better runtime control and flexibility.

Also applies to: 16-16, 43-43


58-61: Good addition of feature flag state to error context.

Including the current feature flag state in error details will help with debugging and monitoring. This provides valuable context for understanding the system state when errors occur.

Also applies to: 83-86

apps/api/src/services/moderation.service.ts (2)

122-270: Approve comprehensive permission checking implementation.

The createModerationAction method implements robust authorization checks with proper error handling and transaction management. The integration with feed configuration and platform-specific approvers is well-designed.


446-452: Good addition of schema validation for API responses.

The use of ModerationActionSchema.parse() for validating moderation data ensures type safety and runtime validation, which is a best practice for API boundaries.

Also applies to: 454-462, 467-474

feedEntry,
submissionStatusZodEnum.Enum.approved,
tx,
const submissionPlatform = "twitter";
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Replace hardcoded platform string with enum.

The hardcoded "twitter" string is used throughout the codebase, creating a maintenance risk and potential for typos.

+enum SubmissionPlatform {
+  TWITTER = "twitter"
+}

-const submissionPlatform = "twitter";
+const submissionPlatform = SubmissionPlatform.TWITTER;

Also applies to: 393-393

🤖 Prompt for AI Agents
In apps/api/src/services/moderation.service.ts at lines 154 and 393, replace the
hardcoded string "twitter" with the appropriate enum value representing the
Twitter platform. Identify the enum used for platforms in the codebase and
substitute the string with that enum constant to ensure consistency and reduce
maintenance risks.

Comment on lines +484 to +491
if (response.success && response.data?.accounts) {
return response.data.accounts;
}
this.logger.warn(
{ actingAccountId, error: response.errors }, // Assuming 'errors' is the correct property
"Failed to fetch connected accounts from Crosspost API or no accounts found.",
);
return null;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve error handling for Crosspost API calls.

The current error handling assumes response.errors exists but should handle cases where the response structure might be different.

     if (response.success && response.data?.accounts) {
       return response.data.accounts;
     }
     this.logger.warn(
-      { actingAccountId, error: response.errors }, // Assuming 'errors' is the correct property
+      { actingAccountId, error: response.success ? 'No accounts found' : response.error },
       "Failed to fetch connected accounts from Crosspost API or no accounts found.",
     );
📝 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.

Suggested change
if (response.success && response.data?.accounts) {
return response.data.accounts;
}
this.logger.warn(
{ actingAccountId, error: response.errors }, // Assuming 'errors' is the correct property
"Failed to fetch connected accounts from Crosspost API or no accounts found.",
);
return null;
if (response.success && response.data?.accounts) {
return response.data.accounts;
}
this.logger.warn(
{ actingAccountId, error: response.success ? 'No accounts found' : response.error },
"Failed to fetch connected accounts from Crosspost API or no accounts found.",
);
return null;
🤖 Prompt for AI Agents
In apps/api/src/services/moderation.service.ts around lines 484 to 491, improve
error handling by checking if the response contains an errors property before
logging it. If errors are not present, log a generic error message or the entire
response to ensure all failure cases are captured. Update the logger.warn call
to handle different response structures gracefully without assuming the presence
of response.errors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants