The /enroll wait UI polled device state via node(), which requires an assumed org session, so confirmation never succeeded for unassumed viewers. Expose viewer.enrolledDevice behind itam:employee-device:get (own-device, skip assumption) and point the poller at it. Signed-off-by: Ludovic Vielle <ludovic@probo.com>
268 lines
8.7 KiB
Go
268 lines
8.7 KiB
Go
package console_v1
|
|
|
|
// This file will be automatically regenerated based on the schema, any resolver
|
|
// implementations
|
|
// will be copied through when generating and any unknown code will be moved to the end.
|
|
// Code generated by github.com/99designs/gqlgen version v0.17.94
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
|
|
"go.gearno.de/kit/log"
|
|
"go.probo.inc/probo/pkg/coredata"
|
|
"go.probo.inc/probo/pkg/gid"
|
|
"go.probo.inc/probo/pkg/iam"
|
|
"go.probo.inc/probo/pkg/itam"
|
|
"go.probo.inc/probo/pkg/page"
|
|
"go.probo.inc/probo/pkg/probo"
|
|
"go.probo.inc/probo/pkg/server/api/authn"
|
|
"go.probo.inc/probo/pkg/server/api/authz"
|
|
"go.probo.inc/probo/pkg/server/api/console/v1/schema"
|
|
"go.probo.inc/probo/pkg/server/api/console/v1/types"
|
|
"go.probo.inc/probo/pkg/server/gqlutils"
|
|
)
|
|
|
|
// SignableDocuments is the resolver for the signableDocuments field.
|
|
func (r *viewerResolver) SignableDocuments(ctx context.Context, obj *types.Viewer, organizationID gid.GID, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentOrderBy) (*types.EmployeeDocumentConnection, error) {
|
|
scope, err := r.authorize(ctx, organizationID, probo.ActionEmployeeDocumentList)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
pageOrderBy := page.OrderBy[coredata.DocumentOrderField]{
|
|
Field: coredata.DocumentOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if orderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.DocumentOrderField]{
|
|
Field: orderBy.Field,
|
|
Direction: orderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
|
|
|
|
identity := authn.IdentityFromContext(ctx)
|
|
|
|
documentFilter := coredata.NewDocumentFilter(nil).WithEmployeeIdentityID(&identity.ID, coredata.EmployeeFilterModeSignature)
|
|
|
|
documentsPage, err := r.probo.Documents.ListByOrganizationID(ctx, scope, organizationID, cursor, documentFilter)
|
|
if err != nil {
|
|
r.logger.ErrorCtx(ctx, "cannot list organization signable documents", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
employeeDocuments := make([]*types.EmployeeDocument, len(documentsPage.Data))
|
|
for i, doc := range documentsPage.Data {
|
|
employeeDocuments[i] = &types.EmployeeDocument{
|
|
ID: doc.ID,
|
|
Title: doc.Title,
|
|
DocumentType: doc.DocumentType,
|
|
CreatedAt: doc.CreatedAt,
|
|
UpdatedAt: doc.UpdatedAt,
|
|
FilterMode: types.EmployeeDocumentFilterModeSignature,
|
|
}
|
|
}
|
|
|
|
page := page.NewPage(employeeDocuments, documentsPage.Cursor)
|
|
|
|
return types.NewEmployeeDocumentConnection(page), nil
|
|
}
|
|
|
|
// SignableDocument is the resolver for the signableDocument field.
|
|
func (r *viewerResolver) SignableDocument(ctx context.Context, obj *types.Viewer, id gid.GID) (*types.EmployeeDocument, error) {
|
|
scope, err := r.authorize(ctx, id, probo.ActionEmployeeDocumentGet)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
identity := authn.IdentityFromContext(ctx)
|
|
|
|
documentFilter := coredata.NewDocumentFilter(nil).WithEmployeeIdentityID(&identity.ID, coredata.EmployeeFilterModeSignature)
|
|
|
|
document, err := r.probo.Documents.GetWithFilter(ctx, scope, id, documentFilter)
|
|
if err != nil {
|
|
if errors.Is(err, coredata.ErrResourceNotFound) {
|
|
return nil, gqlutils.NotFound(ctx, err)
|
|
}
|
|
|
|
r.logger.ErrorCtx(ctx, "cannot get signable document", log.Error(err))
|
|
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
return &types.EmployeeDocument{
|
|
ID: document.ID,
|
|
Title: document.Title,
|
|
DocumentType: document.DocumentType,
|
|
CreatedAt: document.CreatedAt,
|
|
UpdatedAt: document.UpdatedAt,
|
|
FilterMode: types.EmployeeDocumentFilterModeSignature,
|
|
}, nil
|
|
}
|
|
|
|
// ApprovableDocuments is the resolver for the approvableDocuments field.
|
|
func (r *viewerResolver) ApprovableDocuments(ctx context.Context, obj *types.Viewer, organizationID gid.GID, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentOrderBy) (*types.EmployeeDocumentConnection, error) {
|
|
scope, err := r.authorize(ctx, organizationID, probo.ActionEmployeeDocumentList)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
pageOrderBy := page.OrderBy[coredata.DocumentOrderField]{
|
|
Field: coredata.DocumentOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
|
|
if orderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.DocumentOrderField]{
|
|
Field: orderBy.Field,
|
|
Direction: orderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
|
|
|
|
identity := authn.IdentityFromContext(ctx)
|
|
|
|
documentFilter := coredata.NewDocumentFilter(nil).WithEmployeeIdentityID(&identity.ID, coredata.EmployeeFilterModeApproval)
|
|
|
|
documentsPage, err := r.probo.Documents.ListByOrganizationID(ctx, scope, organizationID, cursor, documentFilter)
|
|
if err != nil {
|
|
r.logger.ErrorCtx(ctx, "cannot list organization approvable documents", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
employeeDocuments := make([]*types.EmployeeDocument, len(documentsPage.Data))
|
|
for i, doc := range documentsPage.Data {
|
|
employeeDocuments[i] = &types.EmployeeDocument{
|
|
ID: doc.ID,
|
|
Title: doc.Title,
|
|
DocumentType: doc.DocumentType,
|
|
CreatedAt: doc.CreatedAt,
|
|
UpdatedAt: doc.UpdatedAt,
|
|
FilterMode: types.EmployeeDocumentFilterModeApproval,
|
|
}
|
|
}
|
|
|
|
page := page.NewPage(employeeDocuments, documentsPage.Cursor)
|
|
|
|
return types.NewEmployeeDocumentConnection(page), nil
|
|
}
|
|
|
|
// ApprovableDocument is the resolver for the approvableDocument field.
|
|
func (r *viewerResolver) ApprovableDocument(ctx context.Context, obj *types.Viewer, id gid.GID) (*types.EmployeeDocument, error) {
|
|
scope, err := r.authorize(ctx, id, probo.ActionEmployeeDocumentGet)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
identity := authn.IdentityFromContext(ctx)
|
|
|
|
documentFilter := coredata.NewDocumentFilter(nil).WithEmployeeIdentityID(&identity.ID, coredata.EmployeeFilterModeApproval)
|
|
|
|
document, err := r.probo.Documents.GetWithFilter(ctx, scope, id, documentFilter)
|
|
if err != nil {
|
|
if errors.Is(err, coredata.ErrResourceNotFound) {
|
|
return nil, gqlutils.NotFound(ctx, err)
|
|
}
|
|
|
|
r.logger.ErrorCtx(ctx, "cannot get approvable document", log.Error(err))
|
|
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
return &types.EmployeeDocument{
|
|
ID: document.ID,
|
|
Title: document.Title,
|
|
DocumentType: document.DocumentType,
|
|
CreatedAt: document.CreatedAt,
|
|
UpdatedAt: document.UpdatedAt,
|
|
FilterMode: types.EmployeeDocumentFilterModeApproval,
|
|
}, nil
|
|
}
|
|
|
|
// EnrolledDevices is the resolver for the enrolledDevices field.
|
|
func (r *viewerResolver) EnrolledDevices(ctx context.Context, obj *types.Viewer, organizationID gid.GID, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DeviceOrderBy) (*types.DeviceConnection, error) {
|
|
scope, err := r.authorize(ctx, organizationID, itam.ActionEmployeeDeviceList)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
pageOrderBy := page.OrderBy[coredata.DeviceOrderField]{
|
|
Field: coredata.DeviceOrderFieldCreatedAt,
|
|
Direction: page.OrderDirectionDesc,
|
|
}
|
|
if orderBy != nil {
|
|
pageOrderBy = page.OrderBy[coredata.DeviceOrderField]{
|
|
Field: orderBy.Field,
|
|
Direction: orderBy.Direction,
|
|
}
|
|
}
|
|
|
|
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
|
|
|
|
identity := authn.IdentityFromContext(ctx)
|
|
|
|
profile, err := r.iam.OrganizationService.GetProfileForIdentityAndOrganization(
|
|
ctx,
|
|
identity.ID,
|
|
organizationID,
|
|
)
|
|
if err != nil {
|
|
if _, ok := errors.AsType[*iam.ErrProfileNotFound](err); ok {
|
|
return nil, gqlutils.NotFound(ctx, err)
|
|
}
|
|
|
|
r.logger.ErrorCtx(ctx, "cannot get enrolled devices owner profile", log.Error(err))
|
|
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
devicesPage, err := r.itam.ListForOrganizationIDAndOwnerID(
|
|
ctx, scope, organizationID, profile.ID, cursor,
|
|
)
|
|
if err != nil {
|
|
r.logger.ErrorCtx(ctx, "cannot list enrolled devices", log.Error(err))
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
return types.NewOwnedDeviceConnection(devicesPage, r, organizationID, profile.ID), nil
|
|
}
|
|
|
|
// EnrolledDevice is the resolver for the enrolledDevice field.
|
|
func (r *viewerResolver) EnrolledDevice(ctx context.Context, obj *types.Viewer, id gid.GID) (*types.Device, error) {
|
|
scope, err := r.authorize(
|
|
ctx,
|
|
id,
|
|
itam.ActionEmployeeDeviceGet,
|
|
authz.WithSkipAssumptionCheck(),
|
|
)
|
|
if err != nil {
|
|
if gqlutils.IsForbidden(err) {
|
|
return nil, gqlutils.NotFoundf(ctx, "resource not found")
|
|
}
|
|
|
|
return nil, err
|
|
}
|
|
|
|
device, err := r.itam.GetDevice(ctx, scope, id)
|
|
if err != nil {
|
|
if errors.Is(err, coredata.ErrResourceNotFound) {
|
|
return nil, gqlutils.NotFound(ctx, err)
|
|
}
|
|
|
|
r.logger.ErrorCtx(ctx, "cannot get enrolled device", log.Error(err))
|
|
|
|
return nil, gqlutils.Internal(ctx)
|
|
}
|
|
|
|
return types.NewDevice(device), nil
|
|
}
|
|
|
|
// Viewer returns schema.ViewerResolver implementation.
|
|
func (r *Resolver) Viewer() schema.ViewerResolver { return &viewerResolver{r} }
|
|
|
|
type viewerResolver struct{ *Resolver }
|