Skip to content

Commit

Permalink
Add #343 Add individual endpoints in service
Browse files Browse the repository at this point in the history
  • Loading branch information
albinpa authored and georgepadayatti committed Oct 30, 2023
1 parent eb0e73c commit 0e07755
Show file tree
Hide file tree
Showing 6 changed files with 343 additions and 1 deletion.
113 changes: 113 additions & 0 deletions src/v2/handler/individual/service_create_individual.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package individual

import (
"encoding/json"
"fmt"
"io"
"log"
"net/http"

"github.com/asaskevich/govalidator"
"github.com/bb-consent/api/src/common"
"github.com/bb-consent/api/src/config"
"github.com/bb-consent/api/src/v2/individual"
"go.mongodb.org/mongo-driver/bson/primitive"
)

func createIamRegisterRequestFromAddRequestBody(requestBody addServiceIndividualReq, iamRegReq iamIndividualRegisterReq) iamIndividualRegisterReq {

iamRegReq.Username = requestBody.Individual.Email
iamRegReq.Firstname = requestBody.Individual.Name
iamRegReq.Email = requestBody.Individual.Email
iamRegReq.Enabled = true
iamRegReq.RequiredActions = []string{"UPDATE_PASSWORD"}

return iamRegReq
}
func updateIndividualFromAddRequestBody(requestBody addServiceIndividualReq, newIndividual individual.Individual) individual.Individual {
newIndividual.ExternalId = requestBody.Individual.ExternalId
newIndividual.ExternalIdType = requestBody.Individual.ExternalIdType
newIndividual.IdentityProviderId = requestBody.Individual.IdentityProviderId
newIndividual.Name = requestBody.Individual.Name
newIndividual.Email = requestBody.Individual.Email
newIndividual.Phone = requestBody.Individual.Phone

return newIndividual
}

type addServiceIndividualReq struct {
Individual individual.Individual `json:"individual"`
}

type addServiceIndividualResp struct {
Individual individual.Individual `json:"individual"`
}

// ServiceCreateIndividual
func ServiceCreateIndividual(w http.ResponseWriter, r *http.Request) {
// Headers
organisationId := r.Header.Get(config.OrganizationId)
organisationId = common.Sanitize(organisationId)

// Request body
var individualReq addServiceIndividualReq
b, _ := io.ReadAll(r.Body)
defer r.Body.Close()
json.Unmarshal(b, &individualReq)

// Validate request body
valid, err := govalidator.ValidateStruct(individualReq)
if !valid {
common.HandleErrorV2(w, http.StatusBadRequest, err.Error(), err)
return
}

var iamRegReq iamIndividualRegisterReq

iamRegReq = createIamRegisterRequestFromAddRequestBody(individualReq, iamRegReq)

client := getClient()

t, err := getAdminToken(client)
if err != nil {
log.Printf("Failed to get admin token, user: %v registration", individualReq.Individual.Email)
common.HandleErrorV2(w, http.StatusBadRequest, err.Error(), err)
return
}

iamId, err := registerUser(iamRegReq, t.AccessToken, client)
if err != nil {
log.Printf("Failed to register user: %v err: %v", individualReq.Individual.Email, err)
common.HandleErrorV2(w, http.StatusBadRequest, err.Error(), err)
return
}

var newIndividual individual.Individual
newIndividual.Id = primitive.NewObjectID()
newIndividual.IamId = iamId
newIndividual = updateIndividualFromAddRequestBody(individualReq, newIndividual)
newIndividual.OrganisationId = organisationId
newIndividual.IsDeleted = false
newIndividual.IsOnboardedFromId = false

// Repository
individualRepo := individual.IndividualRepository{}
individualRepo.Init(organisationId)

// Save the individual to db
savedIndividual, err := individualRepo.Add(newIndividual)
if err != nil {
m := fmt.Sprintf("Failed to create new individual: %v", newIndividual.Name)
common.HandleErrorV2(w, http.StatusInternalServerError, m, err)
return
}

resp := addServiceIndividualResp{
Individual: savedIndividual,
}

response, _ := json.Marshal(resp)
w.Header().Set(config.ContentTypeHeader, config.ContentTypeJSON)
w.WriteHeader(http.StatusOK)
w.Write(response)
}
68 changes: 68 additions & 0 deletions src/v2/handler/individual/service_list_individuals.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package individual

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

"github.com/bb-consent/api/src/common"
"github.com/bb-consent/api/src/config"
"github.com/bb-consent/api/src/v2/individual"
"github.com/bb-consent/api/src/v2/paginate"
)

type listServiceIndividualsResp struct {
Individuals interface{} `json:"individuals"`
Pagination paginate.Pagination `json:"pagination"`
}

// ServiceListIndividuals
func ServiceListIndividuals(w http.ResponseWriter, r *http.Request) {
fmt.Println()

organisationId := r.Header.Get(config.OrganizationId)
organisationId = common.Sanitize(organisationId)

// Repository
individualRepo := individual.IndividualRepository{}
individualRepo.Init(organisationId)

// Query params
offset, limit := paginate.ParsePaginationQueryParams(r)
log.Printf("Offset: %v and limit: %v\n", offset, limit)

var resp listServiceIndividualsResp

// Return all individuals
var individuals []individual.Individual
query := paginate.PaginateDBObjectsQuery{
Filter: individualRepo.DefaultFilter,
Collection: individual.Collection(),
Context: context.Background(),
Limit: limit,
Offset: offset,
}
result, err := paginate.PaginateDBObjects(query, &individuals)
if err != nil {
if errors.Is(err, paginate.EmptyDBError) {
emptyIndividuals := make([]interface{}, 0)
resp = listServiceIndividualsResp{
Individuals: emptyIndividuals,
Pagination: result.Pagination,
}
common.ReturnHTTPResponse(resp, w)
return
}
m := "Failed to paginate data attribute"
common.HandleErrorV2(w, http.StatusInternalServerError, m, err)
return

}
resp = listServiceIndividualsResp{
Individuals: result.Items,
Pagination: result.Pagination,
}
common.ReturnHTTPResponse(resp, w)
}
46 changes: 46 additions & 0 deletions src/v2/handler/individual/service_read_individual.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package individual

import (
"encoding/json"
"fmt"
"net/http"

"github.com/bb-consent/api/src/common"
"github.com/bb-consent/api/src/config"
"github.com/bb-consent/api/src/v2/individual"
"github.com/gorilla/mux"
)

type readServiceIndividualResp struct {
Individual individual.Individual `json:"individual"`
}

func ServiceReadIndividual(w http.ResponseWriter, r *http.Request) {
// Headers
organisationId := r.Header.Get(config.OrganizationId)
organisationId = common.Sanitize(organisationId)

individualId := mux.Vars(r)[config.IndividualId]
individualId = common.Sanitize(individualId)

// Repository
individualRepo := individual.IndividualRepository{}
individualRepo.Init(organisationId)

individual, err := individualRepo.Get(individualId)
if err != nil {
m := fmt.Sprintf("Failed to fetch individual: %v", individualId)
common.HandleErrorV2(w, http.StatusInternalServerError, m, err)
return
}

resp := readServiceIndividualResp{
Individual: individual,
}

response, _ := json.Marshal(resp)
w.Header().Set(config.ContentTypeHeader, config.ContentTypeJSON)
w.WriteHeader(http.StatusOK)
w.Write(response)

}
104 changes: 104 additions & 0 deletions src/v2/handler/individual/service_update_individual.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package individual

import (
"encoding/json"
"fmt"
"io"
"net/http"

"github.com/asaskevich/govalidator"
"github.com/bb-consent/api/src/common"
"github.com/bb-consent/api/src/config"
"github.com/bb-consent/api/src/v2/individual"
"github.com/gorilla/mux"
)

func updateIamUpdateRequestFromUpdateRequestBody(requestBody updateServiceIndividualReq) iamIndividualUpdateReq {
var iamIndividualReq iamIndividualUpdateReq

iamIndividualReq.Username = requestBody.Individual.Email
iamIndividualReq.Firstname = requestBody.Individual.Name
iamIndividualReq.Email = requestBody.Individual.Email

return iamIndividualReq
}

func updateIndividualFromUpdateIndividualServiceRequestBody(requestBody updateServiceIndividualReq, tobeUpdatedIndividual individual.Individual) individual.Individual {
tobeUpdatedIndividual.ExternalId = requestBody.Individual.ExternalId
tobeUpdatedIndividual.ExternalIdType = requestBody.Individual.ExternalIdType
tobeUpdatedIndividual.IdentityProviderId = requestBody.Individual.IdentityProviderId
tobeUpdatedIndividual.Name = requestBody.Individual.Name
tobeUpdatedIndividual.Email = requestBody.Individual.Email
tobeUpdatedIndividual.Phone = requestBody.Individual.Phone

return tobeUpdatedIndividual
}

type updateServiceIndividualReq struct {
Individual individual.Individual `json:"individual"`
}

type updateServiceIndividualResp struct {
Individual individual.Individual `json:"individual"`
}

func ServiceUpdateIndividual(w http.ResponseWriter, r *http.Request) {
// Headers
organisationId := r.Header.Get(config.OrganizationId)
organisationId = common.Sanitize(organisationId)

individualId := mux.Vars(r)[config.IndividualId]
individualId = common.Sanitize(individualId)

// Request body
var individualReq updateServiceIndividualReq
b, _ := io.ReadAll(r.Body)
defer r.Body.Close()
json.Unmarshal(b, &individualReq)

// Validate request body
// validating request payload
valid, err := govalidator.ValidateStruct(individualReq)
if !valid {
common.HandleErrorV2(w, http.StatusBadRequest, err.Error(), err)
return
}

// Repository
individualRepo := individual.IndividualRepository{}
individualRepo.Init(organisationId)

tobeUpdatedIndividual, err := individualRepo.Get(individualId)
if err != nil {
m := fmt.Sprintf("Failed to fetch individual: %v", individualId)
common.HandleErrorV2(w, http.StatusInternalServerError, m, err)
return
}

iamUpdateReq := updateIamUpdateRequestFromUpdateRequestBody(individualReq)

err = updateIamIndividual(iamUpdateReq, tobeUpdatedIndividual.IamId)
if err != nil {
m := fmt.Sprintf("Failed to update IAM user by id:%v", individualId)
common.HandleErrorV2(w, http.StatusInternalServerError, m, err)
return
}

tobeUpdatedIndividual = updateIndividualFromUpdateIndividualServiceRequestBody(individualReq, tobeUpdatedIndividual)

savedIndividual, err := individualRepo.Update(tobeUpdatedIndividual)
if err != nil {
m := fmt.Sprintf("Failed to update individual: %v", individualId)
common.HandleErrorV2(w, http.StatusInternalServerError, m, err)
return
}

resp := updateServiceIndividualResp{
Individual: savedIndividual,
}

response, _ := json.Marshal(resp)
w.Header().Set(config.ContentTypeHeader, config.ContentTypeJSON)
w.WriteHeader(http.StatusOK)
w.Write(response)
}
7 changes: 6 additions & 1 deletion src/v2/http_path/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ func SetRoutes(r *mux.Router, e *casbin.Enforcer) {
r.Handle(ConfigReadIndividual, m.Chain(individualHandler.ConfigReadIndividual, m.Logger(), m.Authorize(e), m.SetApplicationMode(), m.Authenticate(), m.AddContentType())).Methods("GET")
r.Handle(ConfigCreateIndividual, m.Chain(individualHandler.ConfigCreateIndividual, m.Logger(), m.Authorize(e), m.SetApplicationMode(), m.Authenticate(), m.AddContentType())).Methods("POST")
r.Handle(ConfigUpdateIndividual, m.Chain(individualHandler.ConfigUpdateIndividual, m.Logger(), m.Authorize(e), m.SetApplicationMode(), m.Authenticate(), m.AddContentType())).Methods("PUT")
r.Handle(ConfigDeleteIndividual, m.Chain(individualHandler.ConfigDeleteIndividual, m.Logger(), m.Authorize(e), m.SetApplicationMode(), m.Authenticate(), m.AddContentType())).Methods("DELETE")
r.Handle(ConfigListIndividuals, m.Chain(individualHandler.ConfigListIndividuals, m.Logger(), m.Authorize(e), m.SetApplicationMode(), m.Authenticate(), m.AddContentType())).Methods("GET")

// Api key related api(s)
Expand Down Expand Up @@ -121,6 +120,12 @@ func SetRoutes(r *mux.Router, e *casbin.Enforcer) {
r.Handle(ServiceReadOrganisationLogoImage, m.Chain(serviceHandler.ServiceReadOrganisationLogoImage, m.Logger(), m.Authorize(e), m.SetApplicationMode(), m.Authenticate(), m.AddContentType())).Methods("GET")
r.Handle(ServiceReadOrganisationCoverImage, m.Chain(serviceHandler.ServiceReadOrganisationCoverImage, m.Logger(), m.Authorize(e), m.SetApplicationMode(), m.Authenticate(), m.AddContentType())).Methods("GET")

// Individual related api(s)
r.Handle(ServiceReadIndividual, m.Chain(individualHandler.ServiceReadIndividual, m.Logger(), m.Authorize(e), m.SetApplicationMode(), m.Authenticate(), m.AddContentType())).Methods("GET")
r.Handle(ServiceCreateIndividual, m.Chain(individualHandler.ServiceCreateIndividual, m.Logger(), m.Authorize(e), m.SetApplicationMode(), m.Authenticate(), m.AddContentType())).Methods("POST")
r.Handle(ServiceUpdateIndividual, m.Chain(individualHandler.ServiceUpdateIndividual, m.Logger(), m.Authorize(e), m.SetApplicationMode(), m.Authenticate(), m.AddContentType())).Methods("PUT")
r.Handle(ServiceListIndividuals, m.Chain(individualHandler.ServiceListIndividuals, m.Logger(), m.Authorize(e), m.SetApplicationMode(), m.Authenticate(), m.AddContentType())).Methods("GET")

// Audit api(s)

r.Handle(AuditListDataAgreementRecords, m.Chain(auditHandler.AuditListDataAgreementRecords, m.Logger(), m.Authorize(e), m.SetApplicationMode(), m.Authenticate(), m.AddContentType())).Methods("GET")
Expand Down
6 changes: 6 additions & 0 deletions src/v2/http_path/service_paths.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,9 @@ const ServiceReadIdp = "/v2/service/idp/open-id/{idpId}"
const ServiceReadOrganisation = "/v2/service/organisation"
const ServiceReadOrganisationLogoImage = "/v2/service/organisation/logoimage"
const ServiceReadOrganisationCoverImage = "/v2/service/organisation/coverimage"

// Individuals
const ServiceCreateIndividual = "/v2/service/individual"
const ServiceReadIndividual = "/v2/service/individual/{individualId}"
const ServiceUpdateIndividual = "/v2/service/individual/{individualId}"
const ServiceListIndividuals = "/v2/service/individuals"

0 comments on commit 0e07755

Please sign in to comment.