Skip to content
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

Added command lines to enable/disable openid from console #527

Merged
merged 7 commits into from
Dec 20, 2024

Conversation

lelemm
Copy link
Contributor

@lelemm lelemm commented Dec 19, 2024

Added command lines to enable/disable openid from console

@actual-github-bot actual-github-bot bot changed the title Added command lines to enable/disable openid from console [WIP] Added command lines to enable/disable openid from console Dec 19, 2024
@lelemm lelemm changed the title [WIP] Added command lines to enable/disable openid from console Added command lines to enable/disable openid from console Dec 19, 2024
Copy link
Contributor

coderabbitai bot commented Dec 19, 2024

Walkthrough

This pull request introduces two new scripts, enable-openid.js and disable-openid.js, to manage OpenID authentication in the application. The package.json file has been updated to include corresponding npm scripts that execute these new JavaScript files.

The enable-openid.js script checks if the system needs bootstrapping and verifies the current login method before attempting to enable OpenID authentication. It includes error handling and provides guidance for reporting issues if something goes wrong during the process.

Similarly, the disable-openid.js script performs checks to ensure the system is ready, prompts for a password, and attempts to disable OpenID authentication. The script provides user feedback and error handling, including instructions for reporting unexpected issues.

Additionally, modifications were made to the src/accounts/openid.js file to enhance the loginWithOpenIdFinalize function and to the src/account-db.js file to improve the disableOpenID function with transaction management. A new optional property authMethod was added to the openId interface in src/config-types.ts, expanding configuration options for OpenID authentication methods.

Possibly related PRs

Suggested labels

sparkles: Merged

Suggested reviewers

  • MikesGlitch
  • jfdoming

Tip

CodeRabbit's docstrings feature is now available as part of our Early Access Program! Simply use the command @coderabbitai generate docstrings to have CodeRabbit automatically generate docstrings for your pull request. We would love to hear your feedback on Discord.


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 2ec5b1c and 6e39e40.

📒 Files selected for processing (2)
  • src/account-db.js (1 hunks)
  • src/scripts/enable-openid.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/scripts/enable-openid.js
🔇 Additional comments (1)
src/account-db.js (1)

172-190: 🛠️ Refactor suggestion

Ensure transaction atomicity and thorough error handling.
Wrapping the deletion statements in a transaction is a good step toward ensuring data integrity. However, verify that failures inside the callback correctly trigger a rollback. Depending on the database driver, you might need to explicitly handle rollbacks on errors inside the transaction block. Also consider providing more context in the error message (e.g., which deletion caused the error).

Here is a script to locate all other calls to “transaction” in the codebase to verify consistency of transaction usage:

✅ Verification successful

Let me gather more information about the transaction implementation to verify the rollback behavior.


Let me try a different approach to check the transaction implementation.


Transaction implementation is safe and handles rollbacks correctly

The codebase uses better-sqlite3 which automatically handles transaction rollbacks on errors. The implementation in src/db.js correctly delegates to the underlying SQLite driver's transaction support through this.db.transaction(fn)(). When any error occurs within the transaction callback, better-sqlite3 will automatically roll back the transaction. The error handling in the reviewed code is also appropriate as it catches and logs any transaction errors.

  • The error handling could be enhanced by including which operation failed, but this is a minor improvement suggestion rather than a critical issue.
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Identify all usage of the `transaction` function for consistent error handling.
rg -A 5 "transaction\\(" 

Length of output: 3827


Script:

#!/bin/bash
# Check the implementation of transaction in the database layer
ast-grep --pattern 'transaction($_) {
  $$$
}'

Length of output: 48


Script:

#!/bin/bash
# Check the database implementation file content
cat src/db.js

Length of output: 1084


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@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: 4

🧹 Nitpick comments (3)
src/scripts/disable-openid.js (2)

23-25: Enhance password handling security

The password handling could be improved for security:

  1. Consider adding a maximum retry limit
  2. Implement timing-safe password comparison
  3. Clear the password from memory after use

Would you like me to provide a secure implementation for these suggestions?


26-32: Improve error handling information

The error handling could be more informative to help users resolve issues:

  1. Add specific error codes or types
  2. Provide more context about what might have gone wrong
  3. Suggest possible solutions based on the error
     if (error) {
-      console.log('Error disabling OpenID:', error);
+      console.log('Failed to disable OpenID:', error);
+      console.log('Common solutions:');
+      console.log('1. Verify your password is correct');
+      console.log('2. Ensure you have proper permissions');
+      console.log('3. Check server connectivity');
       console.log(
         'Please report this as an issue: https://github.com/actualbudget/actual-server/issues',
       );
src/scripts/enable-openid.js (1)

8-14: Improve bootstrap check message

The bootstrap message could be clearer about the requirements and next steps.

   console.log(
-    'It looks like you don't have a password set yet. Password is the fallback authentication method when using OpenID. Execute the command reset-password before using this command!',
+    'Server setup required before enabling OpenID:\n' +
+    '1. A password must be set as a fallback authentication method\n' +
+    '2. Run "yarn reset-password" to set up the password\n' +
+    '3. Then try enabling OpenID again'
   );
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between efb50ed and 191247b.

⛔ Files ignored due to path filters (1)
  • upcoming-release-notes/527.md is excluded by !**/*.md
📒 Files selected for processing (3)
  • package.json (1 hunks)
  • src/scripts/disable-openid.js (1 hunks)
  • src/scripts/enable-openid.js (1 hunks)
🔇 Additional comments (1)
package.json (1)

20-21: Verify OpenID dependencies

The scripts require the openid-client package which is correctly listed in dependencies. However, consider:

  1. Pinning the version for security
  2. Adding @types/openid-client for TypeScript support

src/scripts/disable-openid.js Show resolved Hide resolved
src/scripts/disable-openid.js Outdated Show resolved Hide resolved
src/scripts/enable-openid.js Show resolved Hide resolved
src/scripts/enable-openid.js Show resolved Hide resolved
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link
Contributor

@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

🧹 Nitpick comments (1)
src/scripts/disable-openid.js (1)

24-24: Add null check for error object destructuring.

The current destructuring could throw if disableOpenID returns undefined.

- const { error } = (await disableOpenID({ password })) || {};
+ const result = await disableOpenID({ password });
+ const error = result?.error;
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 191247b and 39da3b1.

📒 Files selected for processing (1)
  • src/scripts/disable-openid.js (1 hunks)
🧰 Additional context used
🪛 eslint
src/scripts/disable-openid.js

[error] 9-9: Replace 'System·needs·to·be·bootstrapped·first.·Please·set·up·the·server·before·managing·OpenID.' with ⏎····'System·needs·to·be·bootstrapped·first.·Please·set·up·the·server·before·managing·OpenID.',⏎··

(prettier/prettier)

🪛 GitHub Check: lint
src/scripts/disable-openid.js

[failure] 9-9:
Replace 'System·needs·to·be·bootstrapped·first.·Please·set·up·the·server·before·managing·OpenID.' with ⏎····'System·needs·to·be·bootstrapped·first.·Please·set·up·the·server·before·managing·OpenID.',⏎··

🔇 Additional comments (4)
src/scripts/disable-openid.js (4)

1-6: LGTM! Clean and specific imports.

The imports are well-organized and all imported functions are utilized in the code.


18-21: 🛠️ Refactor suggestion

Revise exit code for "already disabled" state.

When OpenID is already disabled, this should be considered a success state.

 if (loginMethod === 'password') {
   console.log('OpenID already disabled.');
-  process.exit(1);
+  process.exit(0);  // Already in desired state is a success
 }

Likely invalid or redundant comment.


26-43: 🛠️ Refactor suggestion

Standardize error handling and exit codes.

The error handling paths should use consistent exit codes and logging patterns.

 if (error) {
   console.log('Error disabling OpenID:', error);
   console.log(
     'Please report this as an issue: https://github.com/actualbudget/actual-server/issues',
   );
-  process.exit(1);
+  process.exit(2);  // Unexpected error during operation
 }
 console.log('OpenID disabled!');
 console.log(
   'Note: you will need to log in with the password on any browsers or devices that are currently logged in.',
 );
+process.exit(0);  // Explicit success exit
} catch (err) {
 console.log('Unexpected error:', err);
 console.log(
   'Please report this as an issue: https://github.com/actualbudget/actual-server/issues',
 );
-process.exit(1);
+process.exit(2);  // Unexpected error
}

Likely invalid or redundant comment.


1-6: Verify the imported function signatures.

Let's ensure the imported functions are properly implemented in their respective files.

✅ Verification successful

Let me try a different approach to verify these imports by searching for the function names without the exact export syntax, as they might be exported differently.


All imported functions are properly implemented and match the usage

The verification results show that:

  • All imported functions exist in their respective source files
  • Function signatures and implementations are correct:
    • needsBootstrap() in src/account-db.js
    • getActiveLoginMethod() in src/account-db.js
    • disableOpenID({ password }) in src/account-db.js
    • promptPassword() in src/util/prompt.js
  • The imports are correctly referenced from their source locations
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check implementation of imported functions
echo "Checking account-db.js implementations..."
ast-grep --pattern 'export function needsBootstrap()' 
ast-grep --pattern 'export function getActiveLoginMethod()'
ast-grep --pattern 'export async function disableOpenID({ password })'

echo "Checking prompt.js implementation..."
ast-grep --pattern 'export async function promptPassword()'

Length of output: 428


Script:

#!/bin/bash
# Search for function implementations with more flexible patterns
echo "Searching in account-db.js..."
rg "needsBootstrap" -A 2
rg "getActiveLoginMethod" -A 2
rg "disableOpenID" -A 2

echo -e "\nSearching in util/prompt.js..."
rg "promptPassword" -A 2

# Also check the actual files to ensure they exist
echo -e "\nChecking file existence..."
fd "account-db.js$"
fd "prompt.js$"

Length of output: 5966

src/scripts/disable-openid.js Outdated Show resolved Hide resolved
@lelemm
Copy link
Contributor Author

lelemm commented Dec 19, 2024

Testing the config.json openid parameters, I noticed that during code review of server, code rabbit made me do a change that removes the ability to login with github. I'm reverting this change on this PR too

Copy link
Contributor

@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

🧹 Nitpick comments (2)
src/accounts/openid.js (2)

173-174: Consider using const for immutable variable.

The tokenSet variable is only assigned once in each conditional branch.

-    let tokenSet = null;
+    const tokenSet = 

175-188: Consider adding logging for authentication method used.

For debugging purposes, it would be helpful to log which authentication method is being used.

     if (!config.authMethod || config.authMethod === 'openid') {
+      console.log('Using OpenID Connect authentication flow');
       const params = { code: body.code, state: body.state };
       tokenSet = await client.callback(client.redirect_uris[0], params, {
         code_verifier,
         state: body.state,
       });
     } else {
+      console.log('Using OAuth2 authentication flow');
       tokenSet = await client.grant({
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between c468d0f and 2ec5b1c.

⛔ Files ignored due to path filters (1)
  • upcoming-release-notes/527.md is excluded by !**/*.md
📒 Files selected for processing (2)
  • src/accounts/openid.js (1 hunks)
  • src/config-types.ts (1 hunks)
🔇 Additional comments (2)
src/config-types.ts (1)

35-35: LGTM! Verify documentation updates.

The addition of the optional authMethod property with strict typing is well-implemented and maintains backward compatibility.

Let's verify if the documentation has been updated to reflect this new configuration option:

src/accounts/openid.js (1)

175-188: Verify token validation for both flows.

The code assumes both flows will provide compatible token responses. We should verify this assumption across the codebase.

✅ Verification successful

Let me gather more information about the token validation flows.


Let me try one more verification to understand the token handling better.


Token validation is properly handled for both flows

Based on the code analysis:

  1. Both flows use the official openid-client library which handles token validation internally
  2. The client is configured with validate_id_token: true for both flows
  3. Token responses are consistently handled:
    • Access tokens are used identically for userinfo retrieval
    • Expiration times are handled uniformly with proper fallbacks
    • The same session token generation and storage logic applies to both flows

The assumption about compatible token responses is valid as both flows are implemented using the standard OpenID Connect library's methods (callback and grant), which return standardized token responses.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check token usage patterns in the codebase
rg -A 3 "tokenSet\." 

Length of output: 593


Script:

#!/bin/bash
# Check the token validation and usage implementation
ast-grep --pattern 'const tokenSet = $_'

# Check OpenID client configuration and setup
rg -A 5 "new (Issuer|Client)" 

# Check token-related error handling
rg -B 2 -A 3 "catch.*token"

Length of output: 503


Script:

#!/bin/bash
# Check how tokenSet is used in the entire file
cat src/accounts/openid.js

# Look for token validation or verification patterns
rg -B 2 -A 3 "validate.*token|verify.*token"

# Check for any token-related types or interfaces
rg -A 3 "interface.*Token|type.*Token"

Length of output: 9744

src/accounts/openid.js Show resolved Hide resolved
@MikesGlitch
Copy link
Collaborator

MikesGlitch commented Dec 19, 2024

I got this when running yarn disable-openid:

Unexpected error: SqliteError: FOREIGN KEY constraint failed
    at WrappedDatabase.mutate (file:///D:/GitWork/actual-server/src/db.js:39:21)
    at disableOpenID (file:///D:/GitWork/actual-server/src/account-db.js:173:18)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async file:///D:/GitWork/actual-server/src/scripts/disable-openid.js:24:24 {
  code: 'SQLITE_CONSTRAINT_FOREIGNKEY'
}

@lelemm
Copy link
Contributor Author

lelemm commented Dec 20, 2024

I got this when running yarn disable-openid:

Unexpected error: SqliteError: FOREIGN KEY constraint failed
    at WrappedDatabase.mutate (file:///D:/GitWork/actual-server/src/db.js:39:21)
    at disableOpenID (file:///D:/GitWork/actual-server/src/account-db.js:173:18)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async file:///D:/GitWork/actual-server/src/scripts/disable-openid.js:24:24 {
  code: 'SQLITE_CONSTRAINT_FOREIGNKEY'
}

fixed

@lelemm lelemm requested a review from MikesGlitch December 20, 2024 03:18
@MikesGlitch
Copy link
Collaborator

LGTM

@MikesGlitch MikesGlitch merged commit 2ef3971 into actualbudget:master Dec 20, 2024
8 checks passed
@lelemm lelemm deleted the enchance/openid_commands branch December 20, 2024 14:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants