Initial commit: Add logistics and order_detail message types
Some checks failed
Lock Threads / action (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
Publish Chatwoot EE docker images / build (linux/amd64, ubuntu-latest) (push) Has been cancelled
Publish Chatwoot EE docker images / build (linux/arm64, ubuntu-22.04-arm) (push) Has been cancelled
Publish Chatwoot EE docker images / merge (push) Has been cancelled
Publish Chatwoot CE docker images / build (linux/amd64, ubuntu-latest) (push) Has been cancelled
Publish Chatwoot CE docker images / build (linux/arm64, ubuntu-22.04-arm) (push) Has been cancelled
Publish Chatwoot CE docker images / merge (push) Has been cancelled
Run Chatwoot CE spec / lint-backend (push) Has been cancelled
Run Chatwoot CE spec / lint-frontend (push) Has been cancelled
Run Chatwoot CE spec / frontend-tests (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (0, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (1, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (10, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (11, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (12, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (13, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (14, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (15, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (2, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (3, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (4, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (5, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (6, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (7, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (8, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (9, 16) (push) Has been cancelled
Run Linux nightly installer / nightly (push) Has been cancelled

- Add Logistics component with progress tracking
- Add OrderDetail component for order information
- Support data-driven steps and actions
- Add blue color scale to widget SCSS
- Fix node overflow and progress bar rendering issues
- Add English translations for dashboard components

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Liang XJ
2026-01-26 11:16:56 +08:00
commit 092fb2e083
7646 changed files with 975643 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
class Mfa::AuthenticationService
pattr_initialize [:user!, :otp_code, :backup_code]
def authenticate
return false unless user
return authenticate_with_otp if otp_code.present?
return authenticate_with_backup_code if backup_code.present?
false
end
private
def authenticate_with_otp
user.validate_and_consume_otp!(otp_code)
end
def authenticate_with_backup_code
mfa_service = Mfa::ManagementService.new(user: user)
mfa_service.validate_backup_code!(backup_code)
end
end

View File

@@ -0,0 +1,88 @@
class Mfa::ManagementService
pattr_initialize [:user!]
def enable_two_factor!
user.otp_secret = User.generate_otp_secret
user.save!
end
def disable_two_factor!
user.otp_secret = nil
user.otp_required_for_login = false
user.otp_backup_codes = nil
user.save!
end
def verify_and_activate!
ActiveRecord::Base.transaction do
user.update!(otp_required_for_login: true)
backup_codes_generated? ? nil : generate_backup_codes!
end
end
def two_factor_provisioning_uri
return nil if user.otp_secret.blank?
issuer = 'Chatwoot'
label = user.email
user.otp_provisioning_uri(label, issuer: issuer)
end
def generate_backup_codes!
codes = Array.new(10) { SecureRandom.hex(4).upcase }
user.otp_backup_codes = codes
user.save!
codes
end
def validate_backup_code!(code)
return false unless valid_backup_code_input?(code)
codes = user.otp_backup_codes
found_index = find_matching_code_index(codes, code)
return false if found_index.nil?
mark_code_as_used(codes, found_index)
end
private
def valid_backup_code_input?(code)
user.otp_backup_codes.present? && code.present?
end
def find_matching_code_index(codes, code)
found_index = nil
# Constant-time comparison to prevent timing attacks
codes.each_with_index do |stored_code, idx|
is_match = ActiveSupport::SecurityUtils.secure_compare(stored_code, code)
is_unused = stored_code != 'XXXXXXXX'
found_index = idx if is_match && is_unused
end
found_index
end
def mark_code_as_used(codes, index)
codes[index] = 'XXXXXXXX'
user.otp_backup_codes = codes
user.save!
true
end
public
def backup_codes_generated?
user.otp_backup_codes.present?
end
def mfa_enabled?
user.otp_required_for_login?
end
def two_factor_setup_pending?
user.otp_secret.present? && !user.otp_required_for_login?
end
end

View File

@@ -0,0 +1,28 @@
class Mfa::TokenService < BaseTokenService
pattr_initialize [:user, :token]
MFA_TOKEN_EXPIRY = 5.minutes
def generate_token
@payload = build_payload
super
end
def verify_token
decoded = decode_token
return nil if decoded.blank?
User.find(decoded[:user_id])
rescue ActiveRecord::RecordNotFound
nil
end
private
def build_payload
{
user_id: user.id,
exp: MFA_TOKEN_EXPIRY.from_now.to_i
}
end
end