122 lines
3.8 KiB
Go
122 lines
3.8 KiB
Go
package invitationdb
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/tech/sendico/pkg/db/repository"
|
|
"github.com/tech/sendico/pkg/merrors"
|
|
"github.com/tech/sendico/pkg/model"
|
|
"github.com/tech/sendico/pkg/mservice"
|
|
"github.com/tech/sendico/pkg/mutil/mzap"
|
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
|
"go.mongodb.org/mongo-driver/mongo"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
func (db *InvitationDB) GetPublic(ctx context.Context, invitationRef primitive.ObjectID) (*model.PublicInvitation, error) {
|
|
roleField := repository.Field("role")
|
|
orgField := repository.Field("organization")
|
|
accField := repository.Field("account")
|
|
empField := repository.Field("employee")
|
|
regField := repository.Field("registrationAcc")
|
|
descEmailField := repository.Field("description").Dot("email")
|
|
pipeline := repository.Pipeline().
|
|
// 0) Filter to exactly the invitation(s) you want
|
|
Match(repository.IDFilter(invitationRef).And(repository.Filter("status", model.InvitationCreated))).
|
|
// 1) Lookup the role document
|
|
Lookup(
|
|
mservice.Roles,
|
|
repository.Field("roleRef"),
|
|
repository.IDField(),
|
|
roleField,
|
|
).
|
|
Unwind(repository.Ref(roleField)).
|
|
// 2) Lookup the organization document
|
|
Lookup(
|
|
mservice.Organizations,
|
|
repository.Field("organizationRef"),
|
|
repository.IDField(),
|
|
orgField,
|
|
).
|
|
Unwind(repository.Ref(orgField)).
|
|
// 3) Lookup the account document
|
|
Lookup(
|
|
mservice.Accounts,
|
|
repository.Field("inviterRef"),
|
|
repository.IDField(),
|
|
accField,
|
|
).
|
|
Unwind(repository.Ref(accField)).
|
|
/* 4) do we already have an account whose login == invitation.description ? */
|
|
Lookup(
|
|
mservice.Accounts,
|
|
descEmailField, // local field (invitation.description.email)
|
|
repository.Field("login"), // foreign field (account.login)
|
|
regField, // array: 0-length or ≥1
|
|
).
|
|
// 5) Projection
|
|
Project(
|
|
repository.SimpleAlias(
|
|
empField.Dot("description"),
|
|
repository.Ref(accField),
|
|
),
|
|
repository.SimpleAlias(
|
|
empField.Dot("avatarUrl"),
|
|
repository.Ref(accField.Dot("avatarUrl")),
|
|
),
|
|
repository.SimpleAlias(
|
|
orgField.Dot("description"),
|
|
repository.Ref(orgField),
|
|
),
|
|
repository.SimpleAlias(
|
|
orgField.Dot("logoUrl"),
|
|
repository.Ref(orgField.Dot("logoUrl")),
|
|
),
|
|
repository.SimpleAlias(
|
|
roleField,
|
|
repository.Ref(roleField),
|
|
),
|
|
repository.SimpleAlias(
|
|
repository.Field("invitation"), // ← left-hand side
|
|
repository.Ref(repository.Field("description")), // ← right-hand side (“$description”)
|
|
),
|
|
repository.SimpleAlias(
|
|
repository.Field("storable"), // ← left-hand side
|
|
repository.RootRef(), // ← right-hand side (“$description”)
|
|
),
|
|
repository.ProjectionExpr(
|
|
repository.Field("registrationRequired"),
|
|
repository.Eq(
|
|
repository.Size(repository.Value(repository.Ref(regField).Build())),
|
|
repository.Literal(0),
|
|
),
|
|
),
|
|
)
|
|
|
|
var res model.PublicInvitation
|
|
haveResult := false
|
|
decoder := func(cur *mongo.Cursor) error {
|
|
if haveResult {
|
|
// should never get here
|
|
db.DBImp.Logger.Warn("Unexpected extra invitation", mzap.ObjRef("invitation_ref", invitationRef))
|
|
return merrors.Internal("Unexpected extra invitation found by reference")
|
|
}
|
|
if e := cur.Decode(&res); e != nil {
|
|
db.DBImp.Logger.Warn("Failed to decode entity", zap.Error(e), zap.Any("data", cur.Current.String()))
|
|
return e
|
|
}
|
|
haveResult = true
|
|
return nil
|
|
}
|
|
if err := db.DBImp.Repository.Aggregate(ctx, pipeline, decoder); err != nil {
|
|
db.DBImp.Logger.Warn("Failed to execute aggregation pipeline", zap.Error(err), mzap.ObjRef("invitation_ref", invitationRef))
|
|
return nil, err
|
|
}
|
|
if !haveResult {
|
|
db.DBImp.Logger.Warn("No results fetched", mzap.ObjRef("invitation_ref", invitationRef))
|
|
return nil, merrors.NoData(fmt.Sprintf("Invitation %s not found", invitationRef.Hex()))
|
|
}
|
|
return &res, nil
|
|
}
|