package store import ( "context" "errors" "time" "go.mongodb.org/mongo-driver/v2/bson" "go.mongodb.org/mongo-driver/v2/mongo" "go.mongodb.org/mongo-driver/v2/mongo/options" ) type TokenRecord struct { LocationID string `bson:"location_id"` CompanyID string `bson:"company_id"` AccessToken string `bson:"access_token"` RefreshToken string `bson:"refresh_token"` ExpiresAt time.Time `bson:"expires_at"` InstalledAt time.Time `bson:"installed_at"` UpdatedAt time.Time `bson:"updated_at"` } type Store struct { client *mongo.Client collection *mongo.Collection } func NewStore(ctx context.Context, uri string) (*Store, error) { ctx, cancel := context.WithTimeout(ctx, 10*time.Second) defer cancel() client, err := mongo.Connect(options.Client().ApplyURI(uri)) if err != nil { return nil, err } if err := client.Ping(ctx, nil); err != nil { return nil, err } col := client.Database("cast-ghl").Collection("oauth_tokens") indexModel := mongo.IndexModel{ Keys: bson.D{{Key: "location_id", Value: 1}}, Options: options.Index().SetUnique(true), } if _, err := col.Indexes().CreateOne(ctx, indexModel); err != nil { return nil, err } return &Store{client: client, collection: col}, nil } func (s *Store) SaveToken(ctx context.Context, record *TokenRecord) error { record.UpdatedAt = time.Now() filter := bson.D{{Key: "location_id", Value: record.LocationID}} opts := options.Replace().SetUpsert(true) _, err := s.collection.ReplaceOne(ctx, filter, record, opts) return err } func (s *Store) GetToken(ctx context.Context, locationID string) (*TokenRecord, error) { filter := bson.D{{Key: "location_id", Value: locationID}} var record TokenRecord err := s.collection.FindOne(ctx, filter).Decode(&record) if errors.Is(err, mongo.ErrNoDocuments) { return nil, nil } if err != nil { return nil, err } return &record, nil } func (s *Store) UpdateToken(ctx context.Context, locationID, accessToken, refreshToken string, expiresAt time.Time) error { filter := bson.D{{Key: "location_id", Value: locationID}} update := bson.D{{Key: "$set", Value: bson.D{ {Key: "access_token", Value: accessToken}, {Key: "refresh_token", Value: refreshToken}, {Key: "expires_at", Value: expiresAt}, {Key: "updated_at", Value: time.Now()}, }}} _, err := s.collection.UpdateOne(ctx, filter, update) return err } func (s *Store) DeleteToken(ctx context.Context, locationID string) error { filter := bson.D{{Key: "location_id", Value: locationID}} _, err := s.collection.DeleteOne(ctx, filter) return err } func (s *Store) Close(ctx context.Context) error { return s.client.Disconnect(ctx) }