0

Good afternoon I need to implement user verification email and I am using mongo driver, as below I have User entity and ConfirmationToken Embeddable.

I want ConfirmationToken to die after some period of time, as in redis ttl I use Index https://www.mongodb.com/docs/manual/core/index-ttl/#timing-of-the-delete-operation - documentation. But I have a problem, the token stays, even after time, how can I make the ConfirmationToken die after say an hour?

User entity

type User struct {
    ID         string                 `json:"id" bson:"id"`

    VerifyEmail   ConfirmationToken `json:"verifyemail,omitempty" bson:"verifyemail"`
    ConfirmedMail bool              `json:"confirmedMail" json:"confirmedMail"`
}

type ConfirmationToken struct {
    Value     string    `json:"value,omitempty" bson:"value"`
    CreatedAt time.Time `json:"created_at" bson:"created_at"`
    ExpireOn  int64     `json:"expireon,omitempty" bson:"expires"`
}

My request to mongodb

init repository

func NewMongo(client *mongo.Client) *Mongo {
    m := &Mongo{
        col: client.Database("data").Collection("user"),
    }

    // create ttl index
    _, _ = m.col.Indexes().CreateOne(context.Background(), mongo.IndexModel{
        Keys: bson.D{{
            Key:   "verifyemail.created_at",
            Value: 1,
        }},
        Options: options.Index().SetExpireAfterSeconds(int32(time.Now().Add(time.Minute * 4).Unix())),
    })

    return m
}
func (r *Mongo) CreateVerifyEmailToken(ctx context.Context, user *domain.User) (*domain.User, error) {
    oid, err := primitive.ObjectIDFromHex(user.ID)
    if err != nil {
        return user, err
    }

    data := bson.M{
        "verifyemail": user.VerifyEmail,
    }

    u := &domain.User{}
    err = r.col.FindOneAndUpdate(
        ctx,
        bson.M{"_id": oid},
        bson.M{"$set": data},
        options.FindOneAndUpdate().SetReturnDocument(options.After),
    ).Decode(u)

    fmt.Print(u)
    return u, err
}

Again I repeat my question: How can I make the ConfirmationToken live for a while and then automatically delete it?

alex
  • 524
  • 2
  • 11
  • I cannot fully grasp the question. To automatically do something you have to automate doing that something. IoW, if your database engine provides for this, use that feature (AFAIK, MongoDB does not), otherwise program this yourself. An exact approach to implementing this feature is out of the scope of the `go` tag but if I were you, I'd roll like this: 1) after fetching a token, verify whether it's already expired (given the current time on the server), and if it is, drop it and behave as if it never existed; … – kostix Jul 06 '22 at 14:14
  • … 2) Either implement a periodic scan for expired tokens, or make each or each Nth scan for a token also scan the table with the tokens to nuke those which expired. – kostix Jul 06 '22 at 14:16
  • Oh, it seems MongoDB actually has the auto-expiration feature for its records, cool! – kostix Jul 06 '22 at 14:17
  • `SetExpireAfterSeconds()` expects the lifetime of the documents, relative to the `verifyemail.expiresverifytoken` property. So `verifyemail.expiresverifytoken` must hold the creation timestmap, and you must pass `SetExpireAfterSeconds()` `2` if you want the documents to auto-delete after 2 seconds. But as the marked duplicate states, the auto-delete "granularity" is much bigger than this. – icza Jul 06 '22 at 14:17
  • MongoDB's auto-delete feature is to automatically / conveniently get rid of "garbage", and not to time events to the seconds. Timing may be a minute off! – icza Jul 06 '22 at 14:18
  • And always check errors in Go! And you only need to create an index once! Not in every handler invocation! Put the index check / creation to the initialization code to ensure the index exists, but certainly don't call it every time! – icza Jul 06 '22 at 14:19

0 Answers0