Skip to content

Commit

Permalink
feat: add register user rest endpoint (#115)
Browse files Browse the repository at this point in the history
  • Loading branch information
ochom committed Aug 30, 2021
1 parent e8a155f commit 75510e4
Show file tree
Hide file tree
Showing 6 changed files with 288 additions and 61 deletions.
17 changes: 9 additions & 8 deletions pkg/onboarding/application/dto/input.go
Expand Up @@ -471,12 +471,13 @@ type RoleRevocationInput struct {
// RegisterUserInput is the data required to creat a new user.
// this data can be used by cross service requests
type RegisterUserInput struct {
FirstName string `json:"lastName"`
LastName string `json:"firstName"`
Gender enumutils.Gender `json:"gender"`
PhoneNumber string `json:"phoneNumber"`
Email string `json:"email"`
DateOfBirth scalarutils.Date `json:"dateOfBirth"`
RoleIDs []string `json:"roleIDs"`
WelcomeMessage string `json:"welcomeMessage,omitempty"`
UID *string `json:"uid,omitempty"`
FirstName *string `json:"firstName,omitempty"`
LastName *string `json:"lastName,omitempty"`
Gender *enumutils.Gender `json:"gender,omitempty"`
PhoneNumber *string `json:"phoneNumber,omitempty"`
Email *string `json:"email,omitempty"`
DateOfBirth *scalarutils.Date `json:"dateOfBirth,omitempty"`
RoleIDs []string `json:"roleIDs,omitempty"`
WelcomeMessage *string `json:"welcomeMessage,omitempty"`
}
33 changes: 32 additions & 1 deletion pkg/onboarding/presentation/rest/handlers.go
Expand Up @@ -1306,7 +1306,38 @@ func (h *HandlersInterfacesImpl) RegisterUser() http.HandlerFunc {
input := &dto.RegisterUserInput{}
serverutils.DecodeJSONToTargetStruct(rw, r, input)

profile, err := h.interactor.Signup.RegisterUser(ctx, *input)
if input.UID == nil {
err := fmt.Errorf("expected `UID` to be defined")
errorcodeutil.ReportErr(rw, err, http.StatusBadRequest)
return
}

if input.FirstName == nil {
err := fmt.Errorf("expected `firstName` to be defined")
errorcodeutil.ReportErr(rw, err, http.StatusBadRequest)
return
}

if input.LastName == nil {
err := fmt.Errorf("expected `lastName` to be defined")
errorcodeutil.ReportErr(rw, err, http.StatusBadRequest)
return
}

if input.PhoneNumber == nil {
err := fmt.Errorf("expected `phoneNumber` to be defined")
errorcodeutil.ReportErr(rw, err, http.StatusBadRequest)
return
}

if input.Gender == nil {
err := fmt.Errorf("expected `gender` to be defined")
errorcodeutil.ReportErr(rw, err, http.StatusBadRequest)
return
}
context := addUIDToContext(ctx, *input.UID)

profile, err := h.interactor.Signup.RegisterUser(context, *input)
if err != nil {
serverutils.WriteJSONResponse(rw, err, http.StatusInternalServerError)
return
Expand Down
11 changes: 11 additions & 0 deletions pkg/onboarding/presentation/rest/handlers_helpers.go
@@ -1,9 +1,12 @@
package rest

import (
"context"
"fmt"
"net/http"

"firebase.google.com/go/auth"
"github.com/savannahghi/firebasetools"
"github.com/savannahghi/onboarding/pkg/onboarding/application/dto"
"github.com/savannahghi/serverutils"
"go.opentelemetry.io/otel/attribute"
Expand Down Expand Up @@ -51,3 +54,11 @@ func decodeOTPPayload(

return payload, nil
}

func addUIDToContext(ctx context.Context, uid string) context.Context {
return context.WithValue(
context.Background(),
firebasetools.AuthTokenContextKey,
&auth.Token{UID: uid},
)
}
225 changes: 203 additions & 22 deletions pkg/onboarding/presentation/rest/handlers_test.go
Expand Up @@ -16,6 +16,7 @@ import (
"time"

"github.com/google/uuid"
"github.com/savannahghi/enumutils"
"github.com/savannahghi/feedlib"
"github.com/savannahghi/interserviceclient"
"github.com/savannahghi/onboarding/pkg/onboarding/application/dto"
Expand Down Expand Up @@ -135,15 +136,138 @@ func composeValidRolePayload(t *testing.T, phone string, role profileutils.RoleT
}

func composeValidUserPayload(t *testing.T, phoneNumber string) *bytes.Buffer {
uid := uuid.NewString()
fName := "Test"
lName := "Test"
dob := scalarutils.Date{
Month: 1,
Day: 1,
Year: 2002,
}
gender := "male"
inputData := &dto.RegisterUserInput{
FirstName: "Test",
LastName: "Test",
PhoneNumber: phoneNumber,
DateOfBirth: scalarutils.Date{
Month: 1,
Day: 1,
Year: 2002,
},
UID: &uid,
FirstName: &fName,
LastName: &lName,
PhoneNumber: &phoneNumber,
DateOfBirth: &dob,
Gender: (*enumutils.Gender)(&gender),
}
bs, err := json.Marshal(inputData)
if err != nil {
t.Errorf("unable to marshal token string to JSON: %s", err)
}
return bytes.NewBuffer(bs)
}

func composeInvalidUserPayload0(t *testing.T, phoneNumber string) *bytes.Buffer {
fName := "Test"
lName := "Test"
dob := scalarutils.Date{
Month: 1,
Day: 1,
Year: 2002,
}
gender := "male"
inputData := &dto.RegisterUserInput{
FirstName: &fName,
LastName: &lName,
PhoneNumber: &phoneNumber,
DateOfBirth: &dob,
Gender: (*enumutils.Gender)(&gender),
}
bs, err := json.Marshal(inputData)
if err != nil {
t.Errorf("unable to marshal token string to JSON: %s", err)
}
return bytes.NewBuffer(bs)
}

func composeInvalidUserPayload1(t *testing.T, phoneNumber string) *bytes.Buffer {
uid := uuid.NewString()
lName := "Test"
dob := scalarutils.Date{
Month: 1,
Day: 1,
Year: 2002,
}
gender := "male"
inputData := &dto.RegisterUserInput{
UID: &uid,
LastName: &lName,
PhoneNumber: &phoneNumber,
DateOfBirth: &dob,
Gender: (*enumutils.Gender)(&gender),
}
bs, err := json.Marshal(inputData)
if err != nil {
t.Errorf("unable to marshal token string to JSON: %s", err)
}
return bytes.NewBuffer(bs)
}

func composeInvalidUserPayload2(t *testing.T, phoneNumber string) *bytes.Buffer {
uid := uuid.NewString()
fName := "Test"
dob := scalarutils.Date{
Month: 1,
Day: 1,
Year: 2002,
}
gender := "male"
inputData := &dto.RegisterUserInput{
UID: &uid,
FirstName: &fName,
PhoneNumber: &phoneNumber,
DateOfBirth: &dob,
Gender: (*enumutils.Gender)(&gender),
}
bs, err := json.Marshal(inputData)
if err != nil {
t.Errorf("unable to marshal token string to JSON: %s", err)
}
return bytes.NewBuffer(bs)
}

func composeInvalidUserPayload3(t *testing.T, phoneNumber string) *bytes.Buffer {
uid := uuid.NewString()
fName := "Test"
lName := "Test"
dob := scalarutils.Date{
Month: 1,
Day: 1,
Year: 2002,
}
inputData := &dto.RegisterUserInput{
UID: &uid,
FirstName: &fName,
LastName: &lName,
PhoneNumber: &phoneNumber,
DateOfBirth: &dob,
}
bs, err := json.Marshal(inputData)
if err != nil {
t.Errorf("unable to marshal token string to JSON: %s", err)
}
return bytes.NewBuffer(bs)
}

func composeInvalidUserPayload4(t *testing.T, phoneNumber string) *bytes.Buffer {
uid := uuid.NewString()
fName := "Test"
lName := "Test"
dob := scalarutils.Date{
Month: 1,
Day: 1,
Year: 2002,
}
gender := "male"
inputData := &dto.RegisterUserInput{
UID: &uid,
FirstName: &fName,
LastName: &lName,
DateOfBirth: &dob,
Gender: (*enumutils.Gender)(&gender),
}
bs, err := json.Marshal(inputData)
if err != nil {
Expand Down Expand Up @@ -4320,34 +4444,91 @@ func TestHandlersInterfacesImpl_RegisterUser(t *testing.T) {
email := "test@email.com"

payload := composeValidUserPayload(t, phoneNumber)
payload1 := composeInvalidUserPayload0(t, phoneNumber)
payload2 := composeInvalidUserPayload1(t, phoneNumber)
payload3 := composeInvalidUserPayload2(t, phoneNumber)
payload4 := composeInvalidUserPayload3(t, phoneNumber)
payload5 := composeInvalidUserPayload4(t, phoneNumber)

type args struct {
url string
httpMethod string
body io.Reader
}

input := args{
url: fmt.Sprintf("%s/interna/register_user", serverUrl),
httpMethod: http.MethodPost,
body: payload,
}

tests := []struct {
name string
args args
wantStatus int
wantErr bool
}{
{
name: "sad: unable to create user profile",
args: input,
name: "sad: expected UID",
args: args{
url: fmt.Sprintf("%s/interna/register_user", serverUrl),
httpMethod: http.MethodPost,
body: payload1,
},
wantStatus: http.StatusBadRequest,
wantErr: true,
},
{
name: "sad: expected firstName",
args: args{
url: fmt.Sprintf("%s/interna/register_user", serverUrl),
httpMethod: http.MethodPost,
body: payload2,
},
wantStatus: http.StatusBadRequest,
wantErr: true,
},
{
name: "sad: expected lastName",
args: args{
url: fmt.Sprintf("%s/interna/register_user", serverUrl),
httpMethod: http.MethodPost,
body: payload3,
},
wantStatus: http.StatusBadRequest,
wantErr: true,
},
{
name: "sad: expected gender",
args: args{
url: fmt.Sprintf("%s/interna/register_user", serverUrl),
httpMethod: http.MethodPost,
body: payload4,
},
wantStatus: http.StatusBadRequest,
wantErr: true,
},
{
name: "sad: expected phoneNumber",
args: args{
url: fmt.Sprintf("%s/interna/register_user", serverUrl),
httpMethod: http.MethodPost,
body: payload5,
},
wantStatus: http.StatusBadRequest,
wantErr: true,
},
{
name: "sad: unable to create user profile",
args: args{
url: fmt.Sprintf("%s/interna/register_user", serverUrl),
httpMethod: http.MethodPost,
body: payload,
},
wantStatus: http.StatusInternalServerError,
wantErr: true,
},
{
name: "happy: registered user",
args: input,
name: "happy: registered user",
args: args{
url: fmt.Sprintf("%s/interna/register_user", serverUrl),
httpMethod: http.MethodPost,
body: payload,
},
wantStatus: http.StatusBadRequest,
wantErr: false,
},
Expand All @@ -4363,14 +4544,14 @@ func TestHandlersInterfacesImpl_RegisterUser(t *testing.T) {
response := httptest.NewRecorder()

if tt.name == "sad: unable to create user profile" {
fakeBaseExt.GetLoggedInUserFn = func(ctx context.Context) (*dto.UserInfo, error) {
return nil, fmt.Errorf("unable to get user profile")
fakeBaseExt.GetLoggedInUserUIDFn = func(ctx context.Context) (string, error) {
return "", fmt.Errorf("unable to get logged in user")
}
}

if tt.name == "happy: registered user" {
fakeBaseExt.GetLoggedInUserFn = func(ctx context.Context) (*dto.UserInfo, error) {
return &dto.UserInfo{UID: uuid.NewString()}, nil
fakeBaseExt.GetLoggedInUserUIDFn = func(ctx context.Context) (string, error) {
return uuid.NewString(), nil
}
fakeRepo.GetUserProfileByUIDFn = func(ctx context.Context, uid string, suspended bool) (*profileutils.UserProfile, error) {
return &profileutils.UserProfile{ID: uuid.NewString()}, nil
Expand Down

0 comments on commit 75510e4

Please sign in to comment.