-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Kathurima Kimathi <kathurimakimathi415@gmail.com>
- Loading branch information
1 parent
4c4133d
commit f21f502
Showing
25 changed files
with
1,087 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package utils | ||
|
||
import ( | ||
"hash" | ||
|
||
"github.com/savannahghi/onboarding-service/pkg/onboarding/infrastructure" | ||
) | ||
|
||
// Options is a struct for custom values of salt length, number of iterations, the encoded key's length, | ||
// and the hash function being used. If set to `nil`, default options are used: | ||
// &Options{ 256, 10000, 512, "sha512" } | ||
type Options struct { | ||
SaltLen int | ||
Iterations int | ||
KeyLen int | ||
HashFunction func() hash.Hash | ||
} | ||
|
||
// EncryptUID takes two arguments, a raw uid, and a pointer to an Options struct. | ||
// In order to use default options, pass `nil` as the second argument. | ||
// It returns the generated salt and encoded key for the user. | ||
func EncryptUID(rawUID string, options *Options) (string, string) { | ||
interactor := infrastructure.NewInteractor() | ||
return interactor.PINExtension.EncryptPIN(rawUID, nil) | ||
} | ||
|
||
// CompareUID takes four arguments, the raw UID, its generated salt, the encoded UID, | ||
// and a pointer to the Options struct, and returns a boolean value determining whether the UID is the correct one or not. | ||
// Passing `nil` as the last argument resorts to default options. | ||
func CompareUID(rawUID string, salt string, encodedUID string, options *Options) bool { | ||
|
||
interactor := infrastructure.NewInteractor() | ||
return interactor.PINExtension.ComparePIN(rawUID, salt, encodedUID, nil) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
package utils | ||
|
||
import ( | ||
"encoding/hex" | ||
"reflect" | ||
"testing" | ||
|
||
"github.com/savannahghi/onboarding/pkg/onboarding/application/extension" | ||
"github.com/tj/assert" | ||
) | ||
|
||
const ( | ||
// DefaultSaltLen is the length of generated salt for the user is 256 | ||
DefaultSaltLen = 256 | ||
// DefaultKeyLen is the length of encoded key in PBKDF2 function is 512 | ||
DefaultKeyLen = 512 | ||
) | ||
|
||
func TestEncryptUID(t *testing.T) { | ||
type args struct { | ||
rawUID string | ||
options *Options | ||
} | ||
|
||
customOptions := Options{ | ||
// salt length should be greater than 0 | ||
SaltLen: 0, | ||
Iterations: 2, | ||
KeyLen: 1, | ||
HashFunction: extension.DefaultHashFunction, | ||
} | ||
tests := []struct { | ||
name string | ||
args args | ||
want string | ||
want1 string | ||
wantError bool | ||
}{ | ||
{ | ||
name: "success: correct default options have been used to encrypt uid", | ||
args: args{ | ||
rawUID: "1235", | ||
options: nil, | ||
}, | ||
wantError: false, | ||
}, | ||
{ | ||
name: "failure: incorrect custom options have been used to encrypt uid", | ||
args: args{ | ||
rawUID: "1235", | ||
options: &customOptions, | ||
}, | ||
wantError: true, | ||
}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
salt, encoded := EncryptUID(tt.args.rawUID, tt.args.options) | ||
if tt.wantError { | ||
encodedBytes, err := hex.DecodeString(encoded) | ||
if err != nil { | ||
t.Error("Encrypted uid not hex encoded properly") | ||
} | ||
assert.Equal(t, len(encodedBytes), DefaultKeyLen) | ||
} | ||
if !tt.wantError { | ||
if !reflect.DeepEqual(len([]byte(salt)), DefaultSaltLen) { | ||
t.Error("Received length of salt:", len([]byte(salt)), "Expected length of salt:", DefaultSaltLen) | ||
return | ||
} | ||
encodedBytes, err := hex.DecodeString(encoded) | ||
if err != nil { | ||
t.Error("Encrypted uid not hex encoded properly") | ||
} | ||
assert.Equal(t, len(encodedBytes), DefaultKeyLen) | ||
} | ||
|
||
}) | ||
} | ||
} | ||
|
||
func TestCompareUID(t *testing.T) { | ||
salt, encoded := EncryptUID("1234", nil) | ||
type args struct { | ||
rawUID string | ||
salt string | ||
encodedUID string | ||
options *Options | ||
} | ||
tests := []struct { | ||
name string | ||
args args | ||
want bool | ||
wantError bool | ||
}{ | ||
{ | ||
name: "success: correct uid supplied that has been encrypted correctly", | ||
args: args{ | ||
rawUID: "1234", // this is the same uid that was encrypted | ||
salt: salt, | ||
encodedUID: encoded, | ||
options: nil, | ||
}, | ||
want: true, | ||
wantError: false, | ||
}, | ||
{ | ||
name: "failure: incorrect uid supplied that has been encrypted correctly", | ||
args: args{ | ||
rawUID: "4567", // this uid was never encrypted | ||
salt: salt, | ||
encodedUID: encoded, | ||
options: nil, | ||
}, | ||
want: false, | ||
wantError: true, | ||
}, | ||
{ | ||
name: "failure: wrong custom options have been used to encrypt uid", | ||
args: args{ | ||
rawUID: "12345", | ||
salt: "some random salt", | ||
encodedUID: "uncoded string", | ||
options: nil, | ||
}, | ||
want: false, | ||
wantError: true, | ||
}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
isEncypted := CompareUID(tt.args.rawUID, tt.args.salt, tt.args.encodedUID, tt.args.options) | ||
if !tt.wantError { | ||
assert.True(t, isEncypted) | ||
assert.Equal(t, tt.want, isEncypted) | ||
} | ||
if tt.wantError { | ||
assert.False(t, isEncypted) | ||
assert.Equal(t, tt.want, isEncypted) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,62 @@ | ||
package domain | ||
|
||
import ( | ||
"fmt" | ||
"io" | ||
"log" | ||
"strconv" | ||
) | ||
|
||
// MetricType is a list of all the metrics type to be colected. | ||
type MetricType string | ||
|
||
// metrics type constants | ||
const ( | ||
EngagementMetrics MetricType = "Engagement" | ||
SatisfactionMetrics MetricType = "Satisfaction" | ||
UserInteractionMetrics MetricType = "UserInteraction" | ||
PerformanceMetrics MetricType = "Performance" | ||
) | ||
|
||
// AllMetrics is a set of a valid and known metric types. | ||
var AllMetrics = []MetricType{ | ||
EngagementMetrics, | ||
SatisfactionMetrics, | ||
UserInteractionMetrics, | ||
PerformanceMetrics, | ||
} | ||
|
||
// IsValid returns true if a metric is valid | ||
func (m MetricType) IsValid() bool { | ||
switch m { | ||
case EngagementMetrics, SatisfactionMetrics, UserInteractionMetrics, PerformanceMetrics: | ||
return true | ||
} | ||
return false | ||
} | ||
|
||
func (m MetricType) String() string { | ||
return string(m) | ||
} | ||
|
||
// UnmarshalGQL converts the supplied value to a metric type. | ||
func (m *MetricType) UnmarshalGQL(v interface{}) error { | ||
str, ok := v.(string) | ||
if !ok { | ||
return fmt.Errorf("enums must be strings") | ||
} | ||
|
||
*m = MetricType(str) | ||
if !m.IsValid() { | ||
return fmt.Errorf("%s is not a valid MetricType", str) | ||
} | ||
return nil | ||
} | ||
|
||
// MarshalGQL writes the metric type to the supplied writer | ||
func (m MetricType) MarshalGQL(w io.Writer) { | ||
_, err := fmt.Fprint(w, strconv.Quote(m.String())) | ||
if err != nil { | ||
log.Printf("%v\n", err) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.