-
Couldn't load subscription status.
- Fork 0
Refactor key generator to reuse crypto helper #1
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
base: master
Are you sure you want to change the base?
Refactor key generator to reuse crypto helper #1
Conversation
WalkthroughThis update introduces support for client-side WireGuard peer key generation and configurable private key storage. It adds configuration options, updates API schemas and backend logic, implements frontend cryptographic helpers, and enhances user interface messaging and localization. The changes ensure private keys can be generated and/or stored according to new settings, with clear user guidance. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Browser (Frontend)
participant API Server
participant Database
User->>Browser (Frontend): Open Peer Edit Modal
Browser (Frontend)->>API Server: Fetch settings (ClientSidePeerKeygen, StorePrivateKeys)
API Server-->>Browser (Frontend): Return settings
alt Client-side keygen enabled
Browser (Frontend)->>Browser (Frontend): Generate keypair & preshared key
Browser (Frontend)->>API Server: Submit peer data (public key only)
API Server->>Database: Store peer (no private key)
else Server-side keygen
Browser (Frontend)->>API Server: Request peer creation (no keys)
API Server->>API Server: Generate keypair & preshared key
API Server->>Database: Store peer (with/without private key per config)
end
Note over Browser (Frontend): Show info message about key generation/storage
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (3)
🧰 Additional context used🧬 Code Graph Analysis (1)internal/domain/crypto_test.go (1)
🪛 golangci-lint (1.64.8)internal/app/mail/manager.go222-222: expected '(', found generatePeerQr (typecheck) 249-249: expected '}', found 'EOF' (typecheck) 🔇 Additional comments (4)
✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. 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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this 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
🧹 Nitpick comments (4)
frontend/src/helpers/crypto.js (1)
29-36: Consider using modern APIs for better performance.While the current implementation is correct, you could improve performance by using
btoa(String.fromCharCode(...new Uint8Array(buffer)))directly instead of the loop.-export function arrayBufferToBase64(buffer) { - const bytes = new Uint8Array(buffer); - let binary = ""; - for (let i = 0; i < bytes.byteLength; ++i) { - binary += String.fromCharCode(bytes[i]); - } - return btoa(binary); -} +export function arrayBufferToBase64(buffer) { + const bytes = new Uint8Array(buffer); + return btoa(String.fromCharCode(...bytes)); +}internal/app/api/core/assets/doc/v0_swagger.json (1)
2252-2253: Fix JSON formatting inconsistency.The formatting is inconsistent with the rest of the JSON structure. Consider aligning with the standard formatting used elsewhere in the file.
- ,"ClientSidePeerKeygen": {"type": "boolean"} - ,"StorePrivateKeys": {"type": "boolean"} + "ClientSidePeerKeygen": { + "type": "boolean" + }, + "StorePrivateKeys": { + "type": "boolean" + }frontend/src/components/PeerEditModal.vue (2)
109-115: Consider making the notification dismissible or showing it only once per session.While the informational notification is helpful, showing it every time the modal opens might become repetitive for frequent users.
Consider implementing a session-based flag to show the notification only once:
+const hasShownCryptoMessage = ref(false); watch( () => props.visible, async (newValue, oldValue) => { if (oldValue === false && newValue === true) { // if modal is shown - notify({ - title: "Info", - text: cryptoMessage.value, - type: "info", - }); + if (!hasShownCryptoMessage.value) { + notify({ + title: "Info", + text: cryptoMessage.value, + type: "info", + duration: 10000, // Show for 10 seconds + }); + hasShownCryptoMessage.value = true; + }
217-234: Consider debouncing the watcher to avoid excessive updates.The watcher updates all overridable flags whenever
IgnoreGlobalSettingschanges. While the logic is correct, it might trigger multiple reactive updates.Consider batching the updates:
watch( () => formData.value.IgnoreGlobalSettings, async (newValue, oldValue) => { - formData.value.Endpoint.Overridable = !newValue; - formData.value.EndpointPublicKey.Overridable = !newValue; - formData.value.AllowedIPs.Overridable = !newValue; - formData.value.PersistentKeepalive.Overridable = !newValue; - formData.value.Dns.Overridable = !newValue; - formData.value.DnsSearch.Overridable = !newValue; - formData.value.Mtu.Overridable = !newValue; - formData.value.FirewallMark.Overridable = !newValue; - formData.value.RoutingTable.Overridable = !newValue; - formData.value.PreUp.Overridable = !newValue; - formData.value.PostUp.Overridable = !newValue; - formData.value.PreDown.Overridable = !newValue; - formData.value.PostDown.Overridable = !newValue; + const overridableFields = [ + 'Endpoint', 'EndpointPublicKey', 'AllowedIPs', 'PersistentKeepalive', + 'Dns', 'DnsSearch', 'Mtu', 'FirewallMark', 'RoutingTable', + 'PreUp', 'PostUp', 'PreDown', 'PostDown' + ]; + + overridableFields.forEach(field => { + if (formData.value[field]) { + formData.value[field].Overridable = !newValue; + } + }); }, );
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (24)
docs/documentation/configuration/overview.md(2 hunks)frontend/src/components/PeerEditModal.vue(1 hunks)frontend/src/helpers/crypto.js(1 hunks)frontend/src/lang/translations/de.json(1 hunks)frontend/src/lang/translations/en.json(1 hunks)frontend/src/lang/translations/fr.json(1 hunks)frontend/src/lang/translations/ko.json(1 hunks)frontend/src/lang/translations/pt.json(1 hunks)frontend/src/lang/translations/ru.json(1 hunks)frontend/src/lang/translations/uk.json(1 hunks)frontend/src/lang/translations/vi.json(1 hunks)frontend/src/lang/translations/zh.json(1 hunks)frontend/src/views/KeyGeneraterView.vue(1 hunks)internal/app/api/core/assets/doc/v0_swagger.json(2 hunks)internal/app/api/core/assets/doc/v0_swagger.yaml(2 hunks)internal/app/api/v0/backend/peer_service.go(2 hunks)internal/app/api/v0/handlers/endpoint_config.go(2 hunks)internal/app/api/v0/handlers/endpoint_peers.go(2 hunks)internal/app/api/v0/model/models.go(1 hunks)internal/app/api/v0/model/models_peer.go(1 hunks)internal/app/mail/manager.go(5 hunks)internal/app/wireguard/wireguard.go(2 hunks)internal/app/wireguard/wireguard_peers.go(6 hunks)internal/config/config.go(3 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
internal/app/api/v0/handlers/endpoint_config.go (1)
internal/config/auth.go (1)
Auth(12-24)
internal/app/api/v0/backend/peer_service.go (2)
internal/domain/peer.go (1)
PeerIdentifier(15-15)internal/app/api/v0/handlers/endpoint_peers.go (1)
PeerService(17-44)
internal/app/wireguard/wireguard_peers.go (2)
internal/domain/crypto.go (2)
KeyPair(9-12)NewFreshKeypair(37-47)internal/domain/interface.go (1)
Interface(27-75)
🔇 Additional comments (40)
frontend/src/helpers/crypto.js (3)
1-7: Base64url to base64 conversion looks correct.The implementation properly handles the character substitutions and padding. This is a standard and secure conversion method.
9-21: X25519 key generation implementation is secure and correct.The function properly uses the Web Crypto API with appropriate parameters for WireGuard key generation. The JWK export and base64url to base64 conversion are handled correctly.
23-27: Secure random key generation for preshared keys.Using
window.crypto.getRandomValues()is the correct approach for cryptographically secure random number generation. The 32-byte length is appropriate for WireGuard preshared keys.internal/app/api/v0/model/models.go (1)
15-16: Configuration fields for client-side key generation added correctly.The new boolean fields
ClientSidePeerKeygenandStorePrivateKeysare properly defined with appropriate JSON tags and align with the feature requirements.internal/app/api/v0/model/models_peer.go (1)
185-189: Private keys field added for client-side key generation support.The
PrivateKeys map[string]stringfield appropriately supports the new client-side key generation feature. Ensure that these private keys are handled securely throughout the request lifecycle and not logged or cached inappropriately.internal/app/wireguard/wireguard.go (2)
120-120: Correct logic to disable auto-creation when client-side key generation is enabled.The additional
ClientSidePeerKeygencheck appropriately prevents automatic peer creation when users will be generating keys client-side instead.
141-141: Consistent logic applied to login event handler.The same
ClientSidePeerKeygencheck is correctly applied to the user login event, maintaining consistency with the user creation event handler.internal/app/api/v0/handlers/endpoint_config.go (2)
101-105: Expose new client-side keygen and storage flags for anonymous users
TheClientSidePeerKeygenandStorePrivateKeysfields are correctly added to the minimal settings response for unauthenticated sessions.
114-116: Include new configuration flags in authenticated settings response
The same new flags are properly exposed alongside existing fields in the full settings payload for logged-in users.internal/config/config.go (3)
29-30: Add new Core config flags
TheClientSidePeerKeygenandStorePrivateKeysbooleans are correctly declared with appropriate YAML tags.
83-84: Log new config flags at startup
The new flags are being output in the debug log alongside other Core feature flags, matching the existing logging style.
118-119: Set default values for new flags
Defaults (falsefor client-side keygen,truefor storing keys) are initialized indefaultConfigto maintain backward compatibility.frontend/src/lang/translations/en.json (1)
483-486: Add informational strings for key generation and storage
The newinfo-entries provide clear guidance on client vs. server keygen and private key handling. JSON syntax and comma placement are correct.frontend/src/lang/translations/vi.json (1)
392-395: Insert Vietnamese messages for keygen and private key safety
The added entries align with English originals and maintain valid JSON structure.frontend/src/lang/translations/ko.json (1)
431-434: Include Korean translations for new peer-edit info keys
The four new keys are localized correctly and integrate seamlessly into the existing JSON.frontend/src/lang/translations/pt.json (1)
451-454: PT translations for peer-edit info added correctly.The new entries use consistent key names (
info-client-keygen,info-server-keygen,info-not-saved,info-safety), follow the same punctuation conventions as other sentences in this file, and are properly formatted as valid JSON.frontend/src/lang/translations/uk.json (1)
415-418: UK translations for peer-edit info added correctly.The keys match those in other locales, the Ukrainian strings are full sentences with proper punctuation, and JSON syntax is valid.
frontend/src/lang/translations/ru.json (1)
392-395: RU translations for peer-edit info added correctly.The entries align with the shared key schema, maintain consistent sentence structure and punctuation, and the JSON remains well-formed.
frontend/src/lang/translations/fr.json (1)
415-418: FR translations for peer-edit info added correctly.The new French sentences correspond precisely to the feature context, use the correct keys, and adhere to existing formatting.
frontend/src/lang/translations/de.json (1)
482-485: DE translations for peer-edit info added correctly.The German strings correctly reflect the informational messages, reuse the established key names, and keep the file’s JSON structure intact.
docs/documentation/configuration/overview.md (1)
27-28: LGTM! Well-documented configuration options.The new configuration options are clearly documented with appropriate defaults and comprehensive descriptions. The conservative defaults (client-side generation disabled, private key storage enabled) provide a good balance between security and usability.
Also applies to: 166-173
internal/app/api/core/assets/doc/v0_swagger.yaml (2)
333-336: LGTM! Appropriate API schema extension.The
PrivateKeysfield addition toPeerMailRequestcorrectly supports the new client-side key generation functionality. The type definition asadditionalPropertieswith string values is appropriate for a key-value mapping.
395-398: LGTM! Settings model properly extended.The new boolean fields
ClientSidePeerKeygenandStorePrivateKeyscorrectly expose the configuration options to the frontend, enabling the UI to adapt based on server settings.frontend/src/lang/translations/zh.json (1)
391-394:✅ Verification successful
LGTM! Important security-focused user guidance.
The new translation entries provide clear information about key generation methods and emphasize the importance of private key security. The translations appropriately inform users about:
- Client-side vs server-side key generation
- Private key storage policies
- Security best practices
Verify that similar translation updates are made to other language files for consistency:
🏁 Script executed:
#!/bin/bash # Description: Check if similar peer-edit translation keys exist in other language files # Find all translation files and check for the new keys fd "\.json$" frontend/src/lang/translations/ --exec grep -l "info-client-keygen\|info-server-keygen\|info-not-saved\|info-safety" {}Length of output: 487
Translation consistency confirmed across all language files
All four new security-focused translation keys (
info-client-keygen,info-server-keygen,info-not-saved,info-safety) are present in every supported locale:
- frontend/src/lang/translations/en.json
- frontend/src/lang/translations/fr.json
- frontend/src/lang/translations/de.json
- frontend/src/lang/translations/pt.json
- frontend/src/lang/translations/ru.json
- frontend/src/lang/translations/vi.json
- frontend/src/lang/translations/uk.json
- frontend/src/lang/translations/ko.json
- frontend/src/lang/translations/zh.json
No further action required.
internal/app/api/v0/handlers/endpoint_peers.go (2)
467-467: LGTM! Correctly updated method call.The call to
SendPeerEmailis properly updated to passreq.PrivateKeysas the newprivKeysparameter, maintaining the correct argument order and types.
41-41:✅ Verification successful
Interface signature change requires verification.
The addition of the
privKeys map[string]stringparameter to theSendPeerEmailinterface method is correctly implemented and aligns with the new client-side key generation functionality.Verify that all implementations of the
PeerServiceinterface have been updated to match this new signature:
🏁 Script executed:
#!/bin/bash # Description: Find all implementations of SendPeerEmail method to ensure they match the new signature # Search for SendPeerEmail method implementations ast-grep --pattern $'func ($$$) SendPeerEmail($_) error { $$$ }' # Also search for interface implementations that might contain SendPeerEmail rg -A 10 "SendPeerEmail.*context\.Context.*bool.*map\[string\]string"Length of output: 3265
All
SendPeerEmailimplementations updated ✅The new
privKeys map[string]stringparameter has been applied consistently across the codebase:
- internal/app/mail/manager.go: updated
Manager.SendPeerEmailimplementation- internal/app/api/v0/backend/peer_service.go: updated interface stub and
PeerService.SendPeerEmailmethod- internal/app/api/v0/handlers/endpoint_peers.go: handler signature and call site aligned
No further action required.
frontend/src/views/KeyGeneraterView.vue (1)
3-8: LGTM! Good refactoring to centralize crypto utilities.This change successfully removes duplicated cryptographic code by importing the functions from a dedicated helper module, aligning perfectly with the PR objective.
internal/app/api/core/assets/doc/v0_swagger.json (1)
2156-2162: LGTM! Correct API schema for private key transmission.The new
PrivateKeysproperty properly supports the client-side key generation feature by allowing private keys to be transmitted in peer email requests.internal/app/api/v0/backend/peer_service.go (2)
35-35: LGTM! Correct interface signature update.The interface correctly adds the
privKeys map[string]stringparameter to support private key transmission in email operations.
106-107: LGTM! Implementation correctly matches interface.The method implementation properly passes the
privKeysparameter to the underlying mailer, maintaining consistency with the updated interface.internal/app/wireguard/wireguard_peers.go (4)
106-113: LGTM! Correct conditional key generation logic.The implementation properly skips server-side key generation when
ClientSidePeerKeygenis enabled, allowing clients to generate their own keys.
125-128: LGTM! Appropriate peer identifier handling for client-side keygen.Setting the peer identifier to an empty string when client-side key generation is enabled is correct, as the client will provide the public key later.
270-274: LGTM! Consistent private key clearing for multiple peers.The logic correctly clears private keys for all peers when
StorePrivateKeysis disabled, maintaining consistency with the single peer creation logic.
339-341: LGTM! Comprehensive private key clearing in update scenarios.The implementation correctly handles private key clearing in both peer re-identification and normal update scenarios when
StorePrivateKeysis disabled.Also applies to: 352-354
internal/app/mail/manager.go (3)
98-98: LGTM! The addition ofprivKeysparameter enables client-side key generation support.The new parameter allows passing client-generated private keys to be included in peer emails, which aligns with the PR's objective of supporting client-side key generation.
125-127: LGTM! Secure handling of client-provided private keys.The implementation correctly replaces the peer's interface private key with the client-provided one before sending the email. This ensures that users receive configurations with their own generated keys.
161-161:❓ Verification inconclusive
Verify the rationale for changing from
configFilestotplHandlerfor peer config retrieval.The change from
m.configFiles.GetPeerConfigtom.tplHandler.GetPeerConfigsuggests a different approach to generating peer configurations. This might be related to the need to handle client-provided private keys dynamically.Run the following script to understand the differences between these two methods:
🏁 Script executed:
#!/bin/bash # Description: Compare the GetPeerConfig implementations to understand the change # Find the tplHandler.GetPeerConfig implementation echo "=== Looking for tplHandler.GetPeerConfig implementation ===" ast-grep --pattern 'GetPeerConfig($_) $_' # Find the configFiles.GetPeerConfig implementation echo -e "\n=== Looking for configFiles.GetPeerConfig implementation ===" rg -A 10 "GetPeerConfig.*\(.*Peer" --type goLength of output: 13584
Ensure correct preconditions when bypassing
configFiles.GetPeerConfigSwitching from:
- peerCfgReader, err := m.configFiles.GetPeerConfig(ctx, peer.Identifier) + peerConfig, err := m.tplHandler.GetPeerConfig(peer)bypasses the internal fetch (
m.wg.GetPeer) and access‐check (domain.ValidateUserAccessRights) performed byconfigfile.Manager.GetPeerConfig. Since the mail manager already:
- loads the peer (
m.peers.GetPeer)- enforces access rights
- applies any client‐provided private‐key overrides on
peerconfirm that all of those steps occur before invoking
tplHandler.GetPeerConfig(peer). Otherwise, you risk missing authorization checks or using an uninitialized key.frontend/src/components/PeerEditModal.vue (3)
35-44: LGTM! Clear and informative messaging for users.The
cryptoMessagecomputed property provides excellent user guidance by:
- Explaining whether keys are generated client-side or server-side
- Warning when private keys won't be stored
- Including a general safety reminder
This transparency helps users understand the security implications of their configuration.
118-130: LGTM! Well-implemented client-side key generation with proper fallback.The implementation correctly:
- Checks the
ClientSidePeerKeygensetting- Generates keypair and preshared key client-side when enabled
- Falls back to server-prepared keys when disabled
- Uses the public key as the identifier consistently
195-212: LGTM! Correct logic for detecting overridden settings.The logic properly sets
IgnoreGlobalSettingsto true when any of the overridable fields are set to non-overridable, which correctly reflects that the peer has custom settings.
| func generatePeerQr(cfgData io.Reader) (io.Reader, error) { | ||
| sb := strings.Builder{} | ||
| scanner := bufio.NewScanner(cfgData) | ||
| for scanner.Scan() { | ||
| line := strings.TrimSpace(scanner.Text()) | ||
| if !strings.HasPrefix(line, "#") { | ||
| sb.WriteString(line) | ||
| sb.WriteString("\n") | ||
| } | ||
| } | ||
| if err := scanner.Err(); err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| code, err := qrcode.NewWith(sb.String(), qrcode.WithErrorCorrectionLevel(qrcode.ErrorCorrectionLow), qrcode.WithEncodingMode(qrcode.EncModeByte)) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| buf := bytes.NewBuffer(nil) | ||
| wr := nopCloser{Writer: buf} | ||
| option := compressed.Option{Padding: 8, BlockSize: 4} | ||
| qrWriter := compressed.NewWithWriter(wr, &option) | ||
| if err := code.Save(qrWriter); err != nil { | ||
| return nil, err | ||
| } | ||
| return buf, nil | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Consider adding input validation and improving error messages.
The generatePeerQr function correctly strips comments and generates QR codes. However, there are a few improvements to consider:
- The function assumes
nopClosertype exists but it's not defined in this file - Consider validating that the resulting configuration is not empty after stripping comments
- The error messages could be more descriptive
First, let's verify if nopCloser is defined elsewhere:
Here's an improved version with validation and the missing type:
+type nopCloser struct {
+ io.Writer
+}
+
+func (nopCloser) Close() error { return nil }
+
func generatePeerQr(cfgData io.Reader) (io.Reader, error) {
sb := strings.Builder{}
scanner := bufio.NewScanner(cfgData)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if !strings.HasPrefix(line, "#") {
sb.WriteString(line)
sb.WriteString("\n")
}
}
if err := scanner.Err(); err != nil {
- return nil, err
+ return nil, fmt.Errorf("failed to read config data: %w", err)
}
+ configStr := sb.String()
+ if strings.TrimSpace(configStr) == "" {
+ return nil, fmt.Errorf("configuration is empty after removing comments")
+ }
+
- code, err := qrcode.NewWith(sb.String(), qrcode.WithErrorCorrectionLevel(qrcode.ErrorCorrectionLow), qrcode.WithEncodingMode(qrcode.EncModeByte))
+ code, err := qrcode.NewWith(configStr, qrcode.WithErrorCorrectionLevel(qrcode.ErrorCorrectionLow), qrcode.WithEncodingMode(qrcode.EncModeByte))
if err != nil {
- return nil, err
+ return nil, fmt.Errorf("failed to create QR code: %w", err)
}
buf := bytes.NewBuffer(nil)
wr := nopCloser{Writer: buf}
option := compressed.Option{Padding: 8, BlockSize: 4}
qrWriter := compressed.NewWithWriter(wr, &option)
if err := code.Save(qrWriter); err != nil {
- return nil, err
+ return nil, fmt.Errorf("failed to save QR code: %w", err)
}
return buf, nil
}🏁 Script executed:
#!/bin/bash
# Description: Search for nopCloser type definition
# Search for nopCloser type definition
echo "=== Searching for nopCloser type ==="
rg -A 5 "type nopCloser" --type go
# If not found, search for any nopCloser references
echo -e "\n=== Searching for any nopCloser references ==="
rg "nopCloser" --type goLength of output: 924
🏁 Script executed:
#!/bin/bash
echo "=== Showing package and import section of internal/app/mail/manager.go ==="
sed -n '1,30p' internal/app/mail/manager.goLength of output: 1042
Add missing nopCloser type and validate non-empty config in generatePeerQr
The code in internal/app/mail/manager.go currently references nopCloser without defining it in the mail package. In addition, it should guard against an empty configuration after stripping comments and surface more descriptive errors.
Please update as follows:
• Define nopCloser at the top of internal/app/mail/manager.go:
// nopCloser wraps an io.Writer to satisfy io.WriteCloser.
type nopCloser struct {
io.Writer
}
func (nopCloser) Close() error { return nil }• In generatePeerQr, after scanning:
- if err := scanner.Err(); err != nil {
- return nil, err
- }
+ if err := scanner.Err(); err != nil {
+ return nil, fmt.Errorf("failed to read config data: %w", err)
+ }
+
+ configStr := sb.String()
+ if strings.TrimSpace(configStr) == "" {
+ return nil, fmt.Errorf("configuration is empty after removing comments")
+ }• Improve downstream errors:
- code, err := qrcode.NewWith(sb.String(), …)
- if err != nil {
- return nil, err
- }
+ code, err := qrcode.NewWith(configStr, …)
+ if err != nil {
+ return nil, fmt.Errorf("failed to create QR code: %w", err)
+ }
…
- if err := code.Save(qrWriter); err != nil {
- return nil, err
- }
+ if err := code.Save(qrWriter); err != nil {
+ return nil, fmt.Errorf("failed to save QR code: %w", err)
+ }🤖 Prompt for AI Agents
In internal/app/mail/manager.go around lines 202 to 229, the function
generatePeerQr uses an undefined type nopCloser, lacks validation for empty
configuration after stripping comments, and has generic error messages. Define
the nopCloser type at the top of the file as a struct embedding io.Writer with a
Close method returning nil. In generatePeerQr, after scanning and building the
config string, check if the resulting string is empty and return a descriptive
error if so. Also, wrap or replace error returns with more descriptive messages
indicating which step failed, such as scanning input, creating QR code, or
saving QR code data.
…frontend` Docstrings generation was requested by @deel77. * #1 (comment) The following files were modified: * `frontend/src/helpers/crypto.js` * `internal/app/api/v0/model/models_peer.go` * `internal/app/mail/manager.go` * `internal/config/config.go`
|
Note Generated docstrings for this pull request at #2 |
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
…gFzywydZ0oSqAvSJI1c5w1TjJnodAp8KELdfeWHf3NSnGhxFPeVawzHw2IITJUR5G 📝 Add docstrings to `codex/make-key-pair-generation-configurable-for-frontend`
There was a problem hiding this 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 (1)
internal/app/mail/manager.go (1)
217-246: Implement missing improvements from past review.The
generatePeerQrfunction still lacks the validation and error message improvements suggested in the previous review. The current implementation doesn't validate for empty configuration after comment removal and uses generic error messages.Apply the suggested improvements from the past review:
func generatePeerQr(cfgData io.Reader) (io.Reader, error) { sb := strings.Builder{} scanner := bufio.NewScanner(cfgData) for scanner.Scan() { line := strings.TrimSpace(scanner.Text()) if !strings.HasPrefix(line, "#") { sb.WriteString(line) sb.WriteString("\n") } } if err := scanner.Err(); err != nil { - return nil, err + return nil, fmt.Errorf("failed to read config data: %w", err) } - code, err := qrcode.NewWith(sb.String(), qrcode.WithErrorCorrectionLevel(qrcode.ErrorCorrectionLow), qrcode.WithEncodingMode(qrcode.EncModeByte)) + configStr := sb.String() + if strings.TrimSpace(configStr) == "" { + return nil, fmt.Errorf("configuration is empty after removing comments") + } + + code, err := qrcode.NewWith(configStr, qrcode.WithErrorCorrectionLevel(qrcode.ErrorCorrectionLow), qrcode.WithEncodingMode(qrcode.EncModeByte)) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to create QR code: %w", err) } buf := bytes.NewBuffer(nil) wr := nopCloser{Writer: buf} option := compressed.Option{Padding: 8, BlockSize: 4} qrWriter := compressed.NewWithWriter(wr, &option) if err := code.Save(qrWriter); err != nil { - return nil, err + return nil, fmt.Errorf("failed to save QR code: %w", err) } return buf, nil }🧰 Tools
🪛 golangci-lint (1.64.8)
219-219: expected '(', found generatePeerQr
(typecheck)
246-246: expected '}', found 'EOF'
(typecheck)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
internal/app/mail/manager.go(7 hunks)
🧰 Additional context used
🪛 golangci-lint (1.64.8)
internal/app/mail/manager.go
219-219: expected '(', found generatePeerQr
(typecheck)
246-246: expected '}', found 'EOF'
(typecheck)
🔇 Additional comments (5)
internal/app/mail/manager.go (5)
4-13: LGTM! Imports added correctly for QR code functionality.The new imports support the QR code generation feature and are properly organized.
19-26: LGTM! nopCloser type implemented as suggested in past review.The implementation correctly addresses the previous review feedback by defining the missing
nopClosertype with appropriate documentation.
81-82: LGTM! Improved function documentation.The expanded comment provides better clarity about the function's purpose and error conditions.
108-108: LGTM! Function signature updated to support private key injection.The addition of the
privKeysparameter correctly enables client-side key generation functionality as described in the PR objectives.
171-179: LGTM! Correctly switched to template handler and added QR generation.The change from
configFiles.GetPeerConfigtotplHandler.GetPeerConfigand the addition ofgeneratePeerQraligns with the refactoring objectives.
| if line != "" && !strings.HasPrefix(line, "#") { | ||
| return nil, fmt.Errorf("failed to scan config data: %w", err) | ||
| } | ||
|
|
||
| cfg := strings.TrimSpace(sb.String()) | ||
| if cfg == "" { | ||
| return nil, fmt.Errorf("peer configuration is empty") | ||
| code, err := qrcode.NewWith(cfg, qrcode.WithErrorCorrectionLevel(qrcode.ErrorCorrectionLow), qrcode.WithEncodingMode(qrcode.EncModeByte)) | ||
| return nil, fmt.Errorf("failed to create QR code: %w", err) | ||
| return nil, fmt.Errorf("failed to save QR code image: %w", err) | ||
| }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical: Malformed code fragments causing syntax errors.
These lines appear to be misplaced fragments from the generatePeerQr function, causing syntax errors flagged by static analysis tools. This code is in the wrong location and breaks the file structure.
Remove these malformed lines entirely:
- if line != "" && !strings.HasPrefix(line, "#") {
- return nil, fmt.Errorf("failed to scan config data: %w", err)
- }
-
- cfg := strings.TrimSpace(sb.String())
- if cfg == "" {
- return nil, fmt.Errorf("peer configuration is empty")
- code, err := qrcode.NewWith(cfg, qrcode.WithErrorCorrectionLevel(qrcode.ErrorCorrectionLow), qrcode.WithEncodingMode(qrcode.EncModeByte))
- return nil, fmt.Errorf("failed to create QR code: %w", err)
- return nil, fmt.Errorf("failed to save QR code image: %w", err)📝 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.
| if line != "" && !strings.HasPrefix(line, "#") { | |
| return nil, fmt.Errorf("failed to scan config data: %w", err) | |
| } | |
| cfg := strings.TrimSpace(sb.String()) | |
| if cfg == "" { | |
| return nil, fmt.Errorf("peer configuration is empty") | |
| code, err := qrcode.NewWith(cfg, qrcode.WithErrorCorrectionLevel(qrcode.ErrorCorrectionLow), qrcode.WithEncodingMode(qrcode.EncModeByte)) | |
| return nil, fmt.Errorf("failed to create QR code: %w", err) | |
| return nil, fmt.Errorf("failed to save QR code image: %w", err) | |
| }) |
🧰 Tools
🪛 golangci-lint (1.64.8)
202-202: expected statement, found ')'
(typecheck)
🤖 Prompt for AI Agents
In internal/app/mail/manager.go around lines 192 to 202, there are malformed and
misplaced code fragments from the generatePeerQr function causing syntax errors.
Remove these incorrect lines entirely to restore proper file structure and
syntax correctness.
| if pk, ok := privKeys[string(peerId)]; ok { | ||
| peer.Interface.PrivateKey = pk | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Verify security implications of private key replacement.
The logic correctly replaces the peer's private key when provided in the privKeys map. However, ensure that this doesn't compromise security by allowing unauthorized key substitution.
Consider adding validation to ensure the provided private key is valid:
🏁 Script executed:
#!/bin/bash
# Description: Check if there are any validation functions for WireGuard private keys in the codebase
# Expected: Find functions that validate private key format or correctness
echo "=== Searching for private key validation functions ==="
rg -A 5 -B 2 "PrivateKey.*valid|valid.*PrivateKey|validatePrivateKey" --type go
echo "=== Searching for WireGuard key validation ==="
rg -A 5 -B 2 "wgkey|wireguard.*key.*valid" --type goLength of output: 657
Validate the provided private keys before assignment
No existing validation for WireGuard private keys was found in the codebase. To prevent unauthorized or malformed key substitution, you should verify each pk before setting it on the peer.
- File: internal/app/mail/manager.go (around lines 135–137)
- Issue:
peer.Interface.PrivateKey = pkis assigned blindly whenprivKeyscontains an entry.
Suggested update:
- if pk, ok := privKeys[string(peerId)]; ok {
- peer.Interface.PrivateKey = pk
- }
+ if pk, ok := privKeys[string(peerId)]; ok {
+ // Validate that pk is a well-formed WireGuard private key
+ if crypto.PublicKeyFromPrivateKey(pk) == "" {
+ return fmt.Errorf("invalid private key for peer %s", peerId)
+ }
+ peer.Interface.PrivateKey = pk
+ }• If you prefer a dedicated validator, add a ValidatePrivateKey(pk string) error function in internal/domain/crypto and call it here.
• Add unit tests to cover both valid and invalid keys.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In internal/app/mail/manager.go around lines 135 to 137, the code assigns a
private key from privKeys to peer.Interface.PrivateKey without validation, which
risks unauthorized or malformed key substitution. To fix this, implement a
validation step before assignment: create a ValidatePrivateKey function in
internal/domain/crypto that checks the key's format and correctness, then call
this validator here to verify pk before setting it. Also, add unit tests to
cover scenarios with valid and invalid keys to ensure robustness.
Summary
Testing
make test(fails: pattern frontend-dist/assets/ not found)*https://chatgpt.com/codex/tasks/task_e_683f730b4af0832b821e0b5c36adf652
Summary by CodeRabbit
New Features
Bug Fixes
Documentation
Localization