Add vendor risk assement
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
This commit is contained in:
3
pkg/coredata/migrations/20250422T004000Z.sql
Normal file
3
pkg/coredata/migrations/20250422T004000Z.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE risk_assessments RENAME TO vendor_risk_assessments;
|
||||
|
||||
ALTER TABLE vendor_risk_assessments ADD COLUMN assessed_at TIMESTAMP WITH TIME ZONE NOT NULL;
|
||||
1
pkg/coredata/migrations/20250422T004300Z.sql
Normal file
1
pkg/coredata/migrations/20250422T004300Z.sql
Normal file
@@ -0,0 +1 @@
|
||||
ALTER TABLE vendor_risk_assessments ADD COLUMN assessed_by TEXT NOT NULL;
|
||||
@@ -90,7 +90,7 @@ func (r VendorRiskAssessment) Insert(
|
||||
) error {
|
||||
q := `
|
||||
INSERT INTO
|
||||
risk_assessments (
|
||||
vendor_risk_assessments (
|
||||
tenant_id,
|
||||
id,
|
||||
vendor_id,
|
||||
@@ -165,7 +165,7 @@ SELECT
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
risk_assessments
|
||||
vendor_risk_assessments
|
||||
WHERE
|
||||
%s
|
||||
AND id = @id
|
||||
@@ -216,7 +216,7 @@ SELECT
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
risk_assessments
|
||||
vendor_risk_assessments
|
||||
WHERE
|
||||
%s
|
||||
AND vendor_id = @vendor_id
|
||||
@@ -270,7 +270,7 @@ SELECT
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
risk_assessments
|
||||
vendor_risk_assessments
|
||||
WHERE
|
||||
%s
|
||||
AND vendor_id = @vendor_id
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/getprobo/probo/pkg/probo"
|
||||
"github.com/getprobo/probo/pkg/usrmgr"
|
||||
"go.gearno.de/kit/httpserver"
|
||||
)
|
||||
@@ -33,7 +34,7 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
func InvitationConfirmationHandler(usrmgrSvc *usrmgr.Service, authCfg AuthConfig) http.HandlerFunc {
|
||||
func InvitationConfirmationHandler(usrmgrSvc *usrmgr.Service, proboSvc *probo.Service, authCfg AuthConfig) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req InvitationConfirmationRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
@@ -41,7 +42,7 @@ func InvitationConfirmationHandler(usrmgrSvc *usrmgr.Service, authCfg AuthConfig
|
||||
return
|
||||
}
|
||||
|
||||
err := usrmgrSvc.ConfirmInvitation(r.Context(), req.Token, req.Password)
|
||||
_, err := usrmgrSvc.ConfirmInvitation(r.Context(), req.Token, req.Password)
|
||||
if err != nil {
|
||||
httpserver.RenderError(w, http.StatusInternalServerError, err)
|
||||
return
|
||||
|
||||
@@ -80,7 +80,7 @@ func NewMux(proboSvc *probo.Service, usrmgrSvc *usrmgr.Service, authCfg AuthConf
|
||||
r.Post("/auth/register", SignUpHandler(usrmgrSvc, authCfg))
|
||||
r.Post("/auth/login", SignInHandler(usrmgrSvc, authCfg))
|
||||
r.Delete("/auth/logout", SignOutHandler(usrmgrSvc, authCfg))
|
||||
r.Post("/auth/invitation", InvitationConfirmationHandler(usrmgrSvc, authCfg))
|
||||
r.Post("/auth/invitation", InvitationConfirmationHandler(usrmgrSvc, proboSvc, authCfg))
|
||||
r.Post("/auth/forget-password", ForgetPasswordHandler(usrmgrSvc, authCfg))
|
||||
r.Post("/auth/reset-password", ResetPasswordHandler(usrmgrSvc, authCfg))
|
||||
|
||||
|
||||
@@ -1585,7 +1585,27 @@ func (r *vendorResolver) ComplianceReports(ctx context.Context, obj *types.Vendo
|
||||
|
||||
// RiskAssessments is the resolver for the riskAssessments field.
|
||||
func (r *vendorResolver) RiskAssessments(ctx context.Context, obj *types.Vendor, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.VendorRiskAssessmentOrder) (*types.VendorRiskAssessmentConnection, error) {
|
||||
panic(fmt.Errorf("not implemented: RiskAssessments - riskAssessments"))
|
||||
svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID())
|
||||
|
||||
pageOrderBy := page.OrderBy[coredata.VendorRiskAssessmentOrderField]{
|
||||
Field: coredata.VendorRiskAssessmentOrderFieldCreatedAt,
|
||||
Direction: page.OrderDirectionDesc,
|
||||
}
|
||||
if orderBy != nil {
|
||||
pageOrderBy = page.OrderBy[coredata.VendorRiskAssessmentOrderField]{
|
||||
Field: orderBy.Field,
|
||||
Direction: orderBy.Direction,
|
||||
}
|
||||
}
|
||||
|
||||
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
|
||||
|
||||
page, err := svc.Vendors.ListRiskAssessments(ctx, obj.ID, cursor)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("failed to list vendor risk assessments: %w", err))
|
||||
}
|
||||
|
||||
return types.NewVendorRiskAssessmentConnection(page), nil
|
||||
}
|
||||
|
||||
// BusinessOwner is the resolver for the businessOwner field.
|
||||
|
||||
@@ -710,31 +710,32 @@ func (s Service) InviteUser(
|
||||
)
|
||||
}
|
||||
|
||||
func (s Service) ConfirmInvitation(ctx context.Context, tokenString string, password string) error {
|
||||
func (s Service) ConfirmInvitation(ctx context.Context, tokenString string, password string) (*coredata.User, error) {
|
||||
token, err := statelesstoken.ValidateToken[InvitationData](
|
||||
s.tokenSecret,
|
||||
TokenTypeOrganizationInvitation,
|
||||
tokenString,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot validate organization invitation token: %w", err)
|
||||
return nil, fmt.Errorf("cannot validate organization invitation token: %w", err)
|
||||
}
|
||||
|
||||
if len(password) < 8 {
|
||||
return &ErrInvalidPassword{len(password)}
|
||||
return nil, &ErrInvalidPassword{len(password)}
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
|
||||
hashedPassword, err := s.hp.HashPassword([]byte(password))
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot hash password: %w", err)
|
||||
return nil, fmt.Errorf("cannot hash password: %w", err)
|
||||
}
|
||||
|
||||
return s.pg.WithTx(
|
||||
user := &coredata.User{}
|
||||
|
||||
err = s.pg.WithTx(
|
||||
ctx,
|
||||
func(tx pg.Conn) error {
|
||||
user := &coredata.User{}
|
||||
|
||||
if err := user.LoadByEmail(ctx, tx, token.Data.Email); err != nil {
|
||||
var errUserNotFound *coredata.ErrUserNotFound
|
||||
@@ -766,9 +767,31 @@ func (s Service) ConfirmInvitation(ctx context.Context, tokenString string, pass
|
||||
return fmt.Errorf("cannot insert user organization: %w", err)
|
||||
}
|
||||
|
||||
people := coredata.People{
|
||||
OrganizationID: token.Data.OrganizationID,
|
||||
UserID: &user.ID,
|
||||
FullName: token.Data.FullName,
|
||||
PrimaryEmailAddress: token.Data.Email,
|
||||
Kind: coredata.PeopleKindEmployee,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
scope := coredata.NewScope(token.Data.OrganizationID.TenantID())
|
||||
|
||||
if err := people.Insert(ctx, tx, scope); err != nil {
|
||||
return fmt.Errorf("cannot insert people: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func (s Service) RemoveUser(ctx context.Context, organizationID gid.GID, userID gid.GID) error {
|
||||
|
||||
Reference in New Issue
Block a user