-
Notifications
You must be signed in to change notification settings - Fork 2
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
Replace the deprecated SecKeychain with SecItem #46
Changes from all commits
8c73db9
9fc29ce
372d4fe
cd0cb40
77c6e10
85a1a50
0fcd405
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -7,117 +7,103 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||
// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
#import "org_cryptomator_macos_keychain_MacKeychain_Native.h" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
#import <Foundation/Foundation.h> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
#import <Security/Security.h> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
JNIEXPORT jint JNICALL Java_org_cryptomator_macos_keychain_MacKeychain_00024Native_storePassword(JNIEnv *env, jobject thisObj, jbyteArray service, jbyteArray key, jbyteArray password) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
const int serviceLen = (*env)->GetArrayLength(env, service); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
jbyte *serviceStr = (*env)->GetByteArrayElements(env, service, NULL); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
const int keyLen = (*env)->GetArrayLength(env, key); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
jbyte *keyStr = (*env)->GetByteArrayElements(env, key, NULL); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
const int pwLen = (*env)->GetArrayLength(env, password); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
jbyte *pwStr = (*env)->GetByteArrayElements(env, password, NULL); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
jsize length = (*env)->GetArrayLength(env, password); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
// find existing: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
SecKeychainItemRef itemRef = NULL; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
OSStatus status = SecKeychainFindGenericPassword( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
NULL, // default keychain | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
serviceLen, // length of service name | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(char *)serviceStr, // service name | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
keyLen, // length of account name | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(char *)keyStr, // account name | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
NULL, // length of password | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
NULL, // pointer to password data | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
&itemRef // the item reference | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (status == errSecSuccess) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
NSDictionary *query = @{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(__bridge id)kSecAttrService: [NSString stringWithCString:(char *)serviceStr encoding:NSUTF8StringEncoding], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(__bridge id)kSecAttrAccount: [NSString stringWithCString:(char *)keyStr encoding:NSUTF8StringEncoding], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(__bridge id)kSecReturnAttributes: @YES, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(__bridge id)kSecReturnData: @YES, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(__bridge id)kSecMatchLimit: (__bridge id)kSecMatchLimitOne | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
CFDictionaryRef result = NULL; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&result); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (status == errSecSuccess && result != NULL) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
// update existing: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
status = SecKeychainItemModifyAttributesAndData( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
itemRef, // the item reference | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
NULL, // no change to attributes | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
pwLen, // length of password | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
pwStr // pointer to password data | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
NSDictionary *attributesToUpdate = @{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(__bridge id)kSecValueData: [NSData dataWithBytes:pwStr length:length] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)attributesToUpdate); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else if (status == errSecItemNotFound) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
// add new: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
status = SecKeychainAddGenericPassword( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
NULL, // default keychain | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
serviceLen, // length of service name | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(char *)serviceStr, // service name | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
keyLen, // length of account name | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(char *)keyStr, // account name | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
pwLen, // length of password | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
pwStr, // pointer to password data | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
NULL // the item reference | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
NSDictionary *attributes = @{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(__bridge id)kSecAttrService: [NSString stringWithCString:(char *)serviceStr encoding:NSUTF8StringEncoding], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(__bridge id)kSecAttrAccount: [NSString stringWithCString:(char *)keyStr encoding:NSUTF8StringEncoding], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(__bridge id)kSecValueData: [NSData dataWithBytes:pwStr length:length] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
status = SecItemAdd((__bridge CFDictionaryRef)attributes, NULL); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
NSLog(@"Error storing item in keychain. Status code: %d", (int)status); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
(*env)->ReleaseByteArrayElements(env, service, serviceStr, JNI_ABORT); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(*env)->ReleaseByteArrayElements(env, key, keyStr, JNI_ABORT); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(*env)->ReleaseByteArrayElements(env, password, pwStr, JNI_ABORT); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (itemRef) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
CFRelease(itemRef); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
return status; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
JNIEXPORT jbyteArray JNICALL Java_org_cryptomator_macos_keychain_MacKeychain_00024Native_loadPassword(JNIEnv *env, jobject thisObj, jbyteArray service, jbyteArray key) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
const int serviceLen = (*env)->GetArrayLength(env, service); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
jbyte *serviceStr = (*env)->GetByteArrayElements(env, service, NULL); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
const int keyLen = (*env)->GetArrayLength(env, key); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
jbyte *keyStr = (*env)->GetByteArrayElements(env, key, NULL); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
void *pwStr = NULL; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
UInt32 pwLen; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
OSStatus status = SecKeychainFindGenericPassword( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
NULL, // default keychain | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
serviceLen, // length of service name | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(char *)serviceStr, // service name | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
keyLen, // length of account name | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(char *)keyStr, // account name | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
&pwLen, // length of password | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
&pwStr, // pointer to password data | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
NULL // the item reference | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
jbyteArray result; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (status == errSecSuccess) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
result = (*env)->NewByteArray(env, pwLen); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(*env)->SetByteArrayRegion(env, result, 0, pwLen, pwStr); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
result = NULL; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
// find existing: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
NSDictionary *query = @{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(__bridge id)kSecAttrService: [NSString stringWithCString:(char *)serviceStr encoding:NSUTF8StringEncoding], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(__bridge id)kSecAttrAccount: [NSString stringWithCString:(char *)keyStr encoding:NSUTF8StringEncoding], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(__bridge id)kSecReturnAttributes: @YES, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(__bridge id)kSecReturnData: @YES, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(__bridge id)kSecMatchLimit: (__bridge id)kSecMatchLimitOne | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
CFDictionaryRef result = NULL; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&result); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
jbyteArray password = NULL; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (status == errSecSuccess && result != NULL) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
// retrieve password: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
NSDictionary *attributes = (__bridge_transfer NSDictionary *)result; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
NSData *passwordData = attributes[(__bridge id)kSecValueData]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
password = (*env)->NewByteArray(env, (int)passwordData.length); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(*env)->SetByteArrayRegion(env, password, 0, (int)passwordData.length, (jbyte *)passwordData.bytes); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else if (status != errSecItemNotFound) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
NSLog(@"Error retrieving item from keychain. Status code: %d", (int)status); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+69
to
79
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Refactor to improve error handling and reduce code duplication. The current code can be refactored to use a switch statement for better readability and maintainability. - if (status == errSecSuccess && result != NULL) {
- // retrieve password:
- NSDictionary *attributes = (__bridge_transfer NSDictionary *)result;
- NSData *passwordData = attributes[(__bridge id)kSecValueData];
- password = (*env)->NewByteArray(env, (int)passwordData.length);
- (*env)->SetByteArrayRegion(env, password, 0, (int)passwordData.length, (jbyte *)passwordData.bytes);
- } else if (status != errSecItemNotFound) {
- NSLog(@"Error retrieving item from keychain. Status code: %d", (int)status);
- }
+ switch (status) {
+ case errSecSuccess:
+ if (result != NULL) {
+ NSDictionary *attributes = (__bridge_transfer NSDictionary *)result;
+ NSData *passwordData = attributes[(__bridge id)kSecValueData];
+ password = (*env)->NewByteArray(env, (int)passwordData.length);
+ (*env)->SetByteArrayRegion(env, password, 0, (int)passwordData.length, (jbyte *)passwordData.bytes);
+ }
+ break;
+ default:
+ NSLog(@"Error retrieving item from keychain. Status code: %d", (int)status);
+ break;
+ } Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
(*env)->ReleaseByteArrayElements(env, service, serviceStr, JNI_ABORT); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(*env)->ReleaseByteArrayElements(env, key, keyStr, JNI_ABORT); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (pwStr) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
SecKeychainItemFreeContent(NULL, pwStr); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
return result; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
return password; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
JNIEXPORT jint JNICALL Java_org_cryptomator_macos_keychain_MacKeychain_00024Native_deletePassword(JNIEnv *env, jobject thisObj, jbyteArray service, jbyteArray key) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
const int serviceLen = (*env)->GetArrayLength(env, service); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
jbyte *serviceStr = (*env)->GetByteArrayElements(env, service, NULL); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
const int keyLen = (*env)->GetArrayLength(env, key); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
jbyte *keyStr = (*env)->GetByteArrayElements(env, key, NULL); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
SecKeychainItemRef itemRef = NULL; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
OSStatus status = SecKeychainFindGenericPassword( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
NULL, // default keychain | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
serviceLen, // length of service name | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(char *)serviceStr, // service name | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
keyLen, // length of account name | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(char *)keyStr, // account name | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
NULL, // length of password | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
NULL, // pointer to password data | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
&itemRef // the item reference | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (status == errSecSuccess) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
status = SecKeychainItemDelete( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
itemRef // the item reference | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
// find existing: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
NSDictionary *query = @{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(__bridge id)kSecAttrService: [NSString stringWithCString:(char *)serviceStr encoding:NSUTF8StringEncoding], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(__bridge id)kSecAttrAccount: [NSString stringWithCString:(char *)keyStr encoding:NSUTF8StringEncoding], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(__bridge id)kSecMatchLimit: (__bridge id)kSecMatchLimitOne | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
CFDictionaryRef result = NULL; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&result); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (status == errSecSuccess && result != NULL) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
// delete: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
status = SecItemDelete((__bridge CFDictionaryRef)query); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else if (status != errSecItemNotFound) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
NSLog(@"Error deleting item from keychain. Status code: %d", (int)status); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+98
to
104
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Refactor to improve error handling and reduce code duplication. The current code can be refactored to use a switch statement for better readability and maintainability. - if (status == errSecSuccess && result != NULL) {
- // delete:
- status = SecItemDelete((__bridge CFDictionaryRef)query);
- } else if (status != errSecItemNotFound) {
- NSLog(@"Error deleting item from keychain. Status code: %d", (int)status);
- }
+ switch (status) {
+ case errSecSuccess:
+ if (result != NULL) {
+ status = SecItemDelete((__bridge CFDictionaryRef)query);
+ }
+ break;
+ default:
+ NSLog(@"Error deleting item from keychain. Status code: %d", (int)status);
+ break;
+ } Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
(*env)->ReleaseByteArrayElements(env, service, serviceStr, JNI_ABORT); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
(*env)->ReleaseByteArrayElements(env, key, keyStr, JNI_ABORT); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (itemRef) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
CFRelease(itemRef); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
return status; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} |
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.
Refactor to improve error handling and reduce code duplication.
The current code can be refactored to use a switch statement for better readability and maintainability.
Committable suggestion