Beispiel #1
0
func TestCreateAndGetGroup(t *testing.T) {
	db := modeltesthelper.NewMongoDB(t)
	defer db.Close()

	g, err := createGroup()
	if err != nil {
		t.Fatalf(err.Error())
	}

	g2, err := modelhelper.GetGroup(g.Slug)
	if err != nil {
		t.Errorf(err.Error())
	}

	if g2 == nil {
		t.Errorf("couldnt fetch group by its slug. Got nil, expected: %+v", g)
	}

	if g2.Id.Hex() != g.Id.Hex() {
		t.Errorf("groups are not same: expected: %+v, got: %+v ", g.Id.Hex(), g2.Id.Hex())
	}

	randomName := bson.NewObjectId().Hex()
	_, err = modelhelper.GetGroup(randomName)
	if err == nil {
		t.Errorf("we should not be able to find the group")
	}
}
Beispiel #2
0
// HandleParticipant handles participant operations
func (c *Controller) HandleParticipant(cp *models.ChannelParticipant) error {
	channel, err := models.Cache.Channel.ById(cp.ChannelId)
	if err != nil {
		c.log.Error("Channel: %d is not found", cp.ChannelId)
		return nil
	}

	if channel.TypeConstant != models.Channel_TYPE_GROUP {
		return nil // following logic ensures that channel is a group channel
	}

	group, err := modelhelper.GetGroup(channel.GroupName)
	if err != nil && err != mgo.ErrNotFound {
		return err
	}

	if err == mgo.ErrNotFound {
		c.log.Error("Group: %s is not found in mongo", channel.GroupName)
		return nil
	}

	if err := c.handleDefaultChannels(group.DefaultChannels, cp); err != nil {
		return err
	}

	if err := c.handleParticipantRemove(cp); err != nil {
		return err
	}

	return nil
}
Beispiel #3
0
// UpdateCustomerForGroup updates customer data of a group
func UpdateCustomerForGroup(username, groupName string, params *stripe.CustomerParams) (*stripe.Customer, error) {
	if _, err := EnsureCustomerForGroup(username, groupName, params); err != nil {
		return nil, err
	}

	group, err := modelhelper.GetGroup(groupName)
	if err != nil {
		return nil, err
	}

	if group.Payment.Customer.ID == "" {
		return nil, ErrCustomerNotExists
	}

	params, err = populateCustomerParams(username, groupName, params)
	if err != nil {
		return nil, err
	}

	// if the update request has a new CC, delete old ones.
	if params != nil && params.Source != nil && params.Source.Token != "" {
		if err := DeleteCreditCardForGroup(groupName); err != nil {
			return nil, err
		}
	}

	return customer.Update(group.Payment.Customer.ID, params)
}
Beispiel #4
0
func getGroupBySlug(slug string) bool {
	if isIn(slug, "koding", "guests", "team") {
		return true
	}

	if _, err := existingGroupBySlug.Get(slug); err == nil {
		return true
	}

	if _, err := deletedGroupBySlug.Get(slug); err == nil {
		return false
	}

	_, err := helper.GetGroup(slug)
	if err == mgo.ErrNotFound {
		deletedGroupBySlug.Set(slug, struct{}{})
		return false
	}

	// treat them as existing on random errors
	if err != nil {
		fmt.Printf("err while getting group by slug %q, %s\n", slug, err)
		return true
	}

	existingGroupBySlug.Set(slug, struct{}{})

	return true
}
Beispiel #5
0
// HasCreditCard returns the existance status of group's credit card
func HasCreditCard(u *url.URL, h http.Header, _ interface{}, context *models.Context) (int, http.Header, interface{}, error) {
	if !context.IsLoggedIn() {
		return response.NewBadRequest(models.ErrNotLoggedIn)
	}

	group, err := modelhelper.GetGroup(context.GroupName)
	if err != nil {
		return response.NewBadRequest(err)
	}

	if group.Payment.Customer.ID == "" {
		return response.NewNotFound()
	}

	err = payment.CheckCustomerHasSource(group.Payment.Customer.ID)
	if err == payment.ErrCustomerSourceNotExists {
		return response.NewNotFound()
	}

	if err != nil {
		return response.NewBadRequest(err)
	}

	return response.NewDefaultOK()
}
Beispiel #6
0
// ListInvoicesForGroup lists invoices of a group
func ListInvoicesForGroup(groupName string, startingAfter string, limit int) ([]*stripe.Invoice, error) {
	group, err := modelhelper.GetGroup(groupName)
	if err != nil {
		return nil, err
	}

	if group.Payment.Customer.ID == "" {
		return nil, ErrCustomerNotExists
	}

	var invoices []*stripe.Invoice

	params := &stripe.InvoiceListParams{}
	params.Customer = group.Payment.Customer.ID
	params.Limit = limit
	params.Start = startingAfter
	i := invoice.List(params)
	for i.Next() {
		invoices = append(invoices, i.Invoice())
	}

	if err := i.Err(); err != nil {
		return nil, err
	}

	return invoices, nil
}
Beispiel #7
0
func (cmd *GroupStack) details(username string) (*modelhelper.StackDetails, error) {
	user, err := modelhelper.GetUser(username)
	if err != nil {
		return nil, fmt.Errorf("unable to find a user %q: %s", username, err)
	}

	group, err := modelhelper.GetGroup(cmd.groupSlug)
	if err != nil {
		return nil, fmt.Errorf("unable to find a group %q: %s", cmd.groupSlug, err)
	}

	machine, err := modelhelper.GetMachineBySlug(user.ObjectId, cmd.machineSlug)
	if err != nil {
		return nil, fmt.Errorf("unable to find a machine slug=%q, userID=%q: %s", cmd.machineSlug, user.ObjectId.Hex(), err)
	}

	account, err := modelhelper.GetAccount(username)
	if err != nil {
		return nil, fmt.Errorf("unable to find an account for %q: %s", username, err)
	}

	sd := &modelhelper.StackDetails{
		UserID:    user.ObjectId,
		AccountID: account.Id,
		GroupID:   group.Id,

		UserName:  user.Name,
		GroupSlug: group.Slug,

		MachineID: machine.ObjectId,
		BaseID:    bson.ObjectIdHex(cmd.baseID),
	}

	return sd, nil
}
Beispiel #8
0
// EnsureCustomerForGroup registers a customer for a group if it does not exist,
// returns the existing one if created previously
func EnsureCustomerForGroup(username string, groupName string, req *stripe.CustomerParams) (*stripe.Customer, error) {
	group, err := modelhelper.GetGroup(groupName)
	if err != nil {
		return nil, err
	}

	// if we already have the customer, return it.
	if group.Payment.Customer.ID != "" {
		return customer.Get(group.Payment.Customer.ID, nil)
	}

	req, err = populateCustomerParams(username, group.Slug, req)
	if err != nil {
		return nil, err
	}

	cus, err := customer.New(req)
	if err != nil {
		return nil, err
	}

	if err := modelhelper.UpdateGroupPartial(
		modelhelper.Selector{"_id": group.Id},
		modelhelper.Selector{
			"$set": modelhelper.Selector{
				"payment.customer.id": cus.ID,
			},
		},
	); err != nil {
		return nil, err
	}

	return cus, nil
}
Beispiel #9
0
func getGroupPaymentStatusFromCache(groupName string) (string, error) {
	data, err := groupCache.Get(groupName)
	if err != nil && err != cache.ErrNotFound {
		return "", err
	}

	if err == nil {
		status, ok := data.(string)
		if ok {
			return status, nil
		}
	}

	group, err := modelhelper.GetGroup(groupName)
	if err != nil {
		return "", err
	}

	status := group.Payment.Subscription.Status
	// set defaul payment status
	if status != mongomodels.SubStatusActive {
		status = "invalid"
	}

	if err := groupCache.Set(groupName, status); err != nil {
		return "", err
	}
	return string(status), nil
}
Beispiel #10
0
func withSubscription(endpoint, groupName, sessionID, planID string, f func(subscriptionID string)) {
	createURL := endpoint + EndpointSubscriptionCreate
	deleteURL := endpoint + EndpointSubscriptionCancel

	group, err := modelhelper.GetGroup(groupName)
	tests.ResultedWithNoErrorCheck(group, err)

	Convey("We should be able to create a subscription", func() {
		req, err := json.Marshal(&stripe.SubParams{
			Customer: group.Payment.Customer.ID,
			Plan:     planID,
		})
		tests.ResultedWithNoErrorCheck(req, err)

		res, err := rest.DoRequestWithAuth("POST", createURL, req, sessionID)
		tests.ResultedWithNoErrorCheck(res, err)

		v := &stripe.Sub{}
		err = json.Unmarshal(res, v)
		So(err, ShouldBeNil)

		f(v.ID)

		Convey("We should be able to cancel the subscription", func() {
			res, err = rest.DoRequestWithAuth("DELETE", deleteURL, req, sessionID)
			tests.ResultedWithNoErrorCheck(res, err)

			v = &stripe.Sub{}
			err = json.Unmarshal(res, v)
			So(err, ShouldBeNil)
			So(v.Status, ShouldEqual, "canceled")
		})
	})
}
Beispiel #11
0
func (mwc *Controller) createGroupChannel(groupName string) (*models.Channel, error) {
	c := models.NewChannel()
	c.Name = groupName
	if groupName == models.Channel_KODING_NAME {
		c.Name = "public"
	}
	c.GroupName = groupName
	c.TypeConstant = models.Channel_TYPE_GROUP

	group, err := modelhelper.GetGroup(groupName)
	if err != nil {
		return nil, err
	}

	if group.Visibility == "visible" {
		c.PrivacyConstant = models.Channel_PRIVACY_PUBLIC
	} else {
		c.PrivacyConstant = models.Channel_PRIVACY_PRIVATE
	}

	// find group owner
	creatorId, err := mwc.fetchGroupOwnerId(group)
	if err != nil {
		return nil, err
	}

	c.CreatorId = creatorId
	// create channel
	if err := c.Create(); err != nil {
		return nil, err
	}

	return c, nil
}
Beispiel #12
0
// DeleteSubscriptionForGroup deletes the subscription of a group
func DeleteSubscriptionForGroup(groupName string) (*stripe.Sub, error) {
	group, err := modelhelper.GetGroup(groupName)
	if err != nil {
		return nil, err
	}

	if group.Payment.Subscription.ID == "" {
		return nil, ErrCustomerNotSubscribedToAnyPlans
	}

	if group.Payment.Customer.ID == "" {
		return nil, ErrCustomerNotExists
	}

	sub, err := deleteSubscription(group.Payment.Subscription.ID, group.Payment.Customer.ID)
	if err != nil {
		return nil, err
	}

	if err := syncGroupWithCustomerID(group.Payment.Customer.ID); err != nil {
		return nil, err
	}

	return sub, nil
}
Beispiel #13
0
func TestCreditCardInfoNotSubscribingMember(t *testing.T) {
	Convey("When a non subscribed user request to get CC", t, func() {
		withTestServer(t, func(endpoint string) {
			withStubData(endpoint, func(username, groupName, sessionID string) {
				group, err := modelhelper.GetGroup(groupName)
				tests.ResultedWithNoErrorCheck(group, err)

				err = modelhelper.UpdateGroupPartial(
					modelhelper.Selector{"_id": group.Id},
					modelhelper.Selector{
						"$unset": modelhelper.Selector{"payment.customer.id": ""},
					},
				)
				So(err, ShouldBeNil)

				Convey("Endpoint should return error", func() {
					_, err := rest.DoRequestWithAuth("GET", endpoint+EndpointCreditCardHas, nil, sessionID)
					So(err, ShouldNotBeNil)

					// set the customer id back becase test data callback requires it.
					err = modelhelper.UpdateGroupPartial(
						modelhelper.Selector{"_id": group.Id},
						modelhelper.Selector{
							"$set": modelhelper.Selector{"payment.customer.id": group.Payment.Customer.ID},
						},
					)
					So(err, ShouldBeNil)
				})
			})
		})
	})
}
Beispiel #14
0
func TestInvoiceList(t *testing.T) {
	Convey("Given stub data", t, func() {
		withTestServer(t, func(endpoint string) {
			withStubData(endpoint, func(username, groupName, sessionID string) {
				withTestPlan(func(planID string) {
					createURL := endpoint + EndpointSubscriptionCreate
					deleteURL := endpoint + EndpointSubscriptionCancel

					group, err := modelhelper.GetGroup(groupName)
					tests.ResultedWithNoErrorCheck(group, err)

					addCreditCardToUserWithChecks(endpoint, sessionID)

					Convey("We should be able to create a subscription", func() {
						req, err := json.Marshal(&stripe.SubParams{
							Customer: group.Payment.Customer.ID,
							Plan:     planID,
						})
						tests.ResultedWithNoErrorCheck(req, err)

						res, err := rest.DoRequestWithAuth("POST", createURL, req, sessionID)
						tests.ResultedWithNoErrorCheck(res, err)

						v := &stripe.Sub{}
						err = json.Unmarshal(res, v)
						So(err, ShouldBeNil)
						So(v.Status, ShouldEqual, "active")

						Convey("We should be able to list invoices", func() {
							listInvoicesURL := endpoint + EndpointInvoiceList
							res, err = rest.DoRequestWithAuth("GET", listInvoicesURL, nil, sessionID)
							tests.ResultedWithNoErrorCheck(res, err)

							var invoices []*stripe.Invoice
							err = json.Unmarshal(res, &invoices)
							So(err, ShouldBeNil)
							So(len(invoices), ShouldBeGreaterThan, 0)
							Convey("We should be able to list invoices with startingAfter query param", func() {
								listInvoicesURLWithQuery := fmt.Sprintf("%s%s?startingAfter=%s", endpoint, EndpointInvoiceList, invoices[0].ID)
								res, err = rest.DoRequestWithAuth("GET", listInvoicesURLWithQuery, nil, sessionID)
								tests.ResultedWithNoErrorCheck(res, err)

								var invoices []*stripe.Invoice
								err = json.Unmarshal(res, &invoices)
								So(err, ShouldBeNil)
								So(len(invoices), ShouldEqual, 0) // because we only have one invoice

								Convey("We should be able to cancel the subscription", func() {
									res, err = rest.DoRequestWithAuth("DELETE", deleteURL, req, sessionID)
									tests.ResultedWithNoErrorCheck(res, err)
								})
							})
						})
					})
				})
			})
		})
	})
}
Beispiel #15
0
// BuildTeam fetches team details from MongoDB.
//
// When it returns with nil error, the b.Team field is
// guranteed to be non-nil.
func (b *Builder) BuildTeam(team string) error {
	g, err := modelhelper.GetGroup(team)
	if err != nil {
		return err
	}

	b.Team = g

	return nil
}
Beispiel #16
0
// make sure we can subscribe to 7 days-free plan with more trial period
func TestSubscribingToPaidPlanWithWithDifferentTrialPeriodThanDefault(t *testing.T) {
	Convey("Given stub data", t, func() {
		withTestServer(t, func(endpoint string) {
			withStubData(endpoint, func(username, groupName, sessionID string) {
				pp := &stripe.PlanParams{
					Amount:        12345,
					Interval:      stripeplan.Month,
					IntervalCount: 1,
					TrialPeriod:   1, // trial for one day
					Name:          fmt.Sprintf("plan for %s", username),
					Currency:      currency.USD,
					ID:            fmt.Sprintf("plan_for_%s", username),
					Statement:     "NAN-FREE",
				}

				plan, err := stripeplan.New(pp)
				So(err, ShouldBeNil)

				addCreditCardToUserWithChecks(endpoint, sessionID)

				createURL := endpoint + EndpointSubscriptionCreate
				deleteURL := endpoint + EndpointSubscriptionCancel
				group, err := modelhelper.GetGroup(groupName)
				tests.ResultedWithNoErrorCheck(group, err)

				req, err := json.Marshal(&stripe.SubParams{
					Customer: group.Payment.Customer.ID,
					Plan:     plan.ID,
					TrialEnd: time.Now().Add(time.Hour * 48).Unix(),
				})
				tests.ResultedWithNoErrorCheck(req, err)

				sub, err := rest.DoRequestWithAuth("POST", createURL, req, sessionID)
				tests.ResultedWithNoErrorCheck(sub, err)

				v := &stripe.Sub{}
				err = json.Unmarshal(sub, v)
				So(err, ShouldBeNil)

				So(v.TrialEnd, ShouldBeGreaterThan, time.Now().Add(time.Hour*24*time.Duration(pp.TrialPeriod)).Unix())

				Convey("We should be able to cancel the subscription", func() {
					res, err := rest.DoRequestWithAuth("DELETE", deleteURL, req, sessionID)
					tests.ResultedWithNoErrorCheck(res, err)

					v := &stripe.Sub{}
					err = json.Unmarshal(res, v)
					So(err, ShouldBeNil)
					So(v.Status, ShouldEqual, "canceled")
				})
			})
		})
	})
}
Beispiel #17
0
// GetCustomerForGroup get the registered customer info of a group if exists
func GetCustomerForGroup(groupName string) (*stripe.Customer, error) {
	group, err := modelhelper.GetGroup(groupName)
	if err != nil {
		return nil, err
	}

	if group.Payment.Customer.ID == "" {
		return nil, ErrCustomerNotExists
	}

	return customer.Get(group.Payment.Customer.ID, nil)
}
Beispiel #18
0
// GetSubscriptionForGroup gets the subscription of a group
func GetSubscriptionForGroup(groupName string) (*stripe.Sub, error) {
	group, err := modelhelper.GetGroup(groupName)
	if err != nil {
		return nil, err
	}

	if group.Payment.Subscription.ID == "" {
		return nil, ErrCustomerNotSubscribedToAnyPlans
	}

	return sub.Get(group.Payment.Subscription.ID, nil)
}
Beispiel #19
0
// DeleteCreditCardForGroup deletes credit card of the group, if customer is not
// registered yet for the group, returns error. Credit card operations hanled by
// Stripe.
func DeleteCreditCardForGroup(groupName string) error {
	group, err := modelhelper.GetGroup(groupName)
	if err != nil {
		return err
	}

	if group.Payment.Customer.ID == "" {
		return ErrCustomerNotExists
	}

	return deleteCreditCard(group.Payment.Customer.ID)
}
Beispiel #20
0
func setDefaults(log logging.Logger) {
	group, err := modelhelper.GetGroup(models.Channel_KODING_NAME)
	if err != nil {
		log.Error("err while fetching koding group: %s", err.Error())
		return
	}

	log.Debug("mongo group found")

	setPublicChannel(log, group)
	setChangeLogChannel(log, group)
	log.Info("socialApi defaults are created")
}
Beispiel #21
0
func withStubData(endpoint string, f func(username string, groupName string, sessionID string)) {
	acc, _, groupName := models.CreateRandomGroupDataWithChecks()

	group, err := modelhelper.GetGroup(groupName)
	tests.ResultedWithNoErrorCheck(group, err)

	err = modelhelper.MakeAdmin(bson.ObjectIdHex(acc.OldId), group.Id)
	So(err, ShouldBeNil)

	ses, err := modelhelper.FetchOrCreateSession(acc.Nick, groupName)
	tests.ResultedWithNoErrorCheck(ses, err)

	f(acc.Nick, groupName, ses.ClientId)
}
Beispiel #22
0
// Info return usage info for a group
func Info(u *url.URL, h http.Header, _ interface{}, context *models.Context) (int, http.Header, interface{}, error) {
	if err := context.IsGroupAdmin(); err != nil {
		return response.NewBadRequest(err)
	}

	group, err := modelhelper.GetGroup(context.GroupName)
	if err != nil {
		return response.NewBadRequest(err)
	}

	return response.HandleResultAndError(
		payment.EnsureInfoForGroup(group, context.Client.Account.Nick),
	)
}
Beispiel #23
0
func TestCustomer(t *testing.T) {
	Convey("Given a user", t, func() {
		withTestServer(t, func(endpoint string) {
			withStubData(endpoint, func(username, groupName, sessionID string) {
				Convey("Then Group should have customer id", func() {
					group, err := modelhelper.GetGroup(groupName)
					tests.ResultedWithNoErrorCheck(group, err)

					So(group.Payment.Customer.ID, ShouldNotBeBlank)
					Convey("We should be able to get the customer", func() {
						getURL := endpoint + EndpointCustomerGet

						res, err := rest.DoRequestWithAuth("GET", getURL, nil, sessionID)
						So(err, ShouldBeNil)
						So(res, ShouldNotBeNil)

						v := &stripe.Customer{}
						err = json.Unmarshal(res, v)
						So(err, ShouldBeNil)

						So(v.Deleted, ShouldEqual, false)
						So(v.Desc, ShouldContainSubstring, groupName)
						So(len(v.Meta), ShouldBeGreaterThanOrEqualTo, 2)
						So(v.Meta["groupName"], ShouldEqual, groupName)
						So(v.Meta["username"], ShouldEqual, username)

						Convey("After adding credit card to the user", func() {
							addCreditCardToUserWithChecks(endpoint, sessionID)

							res, err = rest.DoRequestWithAuth("GET", getURL, nil, sessionID)
							So(err, ShouldBeNil)
							So(res, ShouldNotBeNil)

							Convey("Customer should have CC assigned", func() {
								v = &stripe.Customer{}
								err = json.Unmarshal(res, v)
								So(err, ShouldBeNil)

								So(v.DefaultSource, ShouldNotBeNil)
								So(v.DefaultSource.Deleted, ShouldBeFalse)
								So(v.DefaultSource.ID, ShouldNotBeEmpty)
							})
						})
					})
				})
			})
		})
	})
}
Beispiel #24
0
func TestInvoiceHandlers(t *testing.T) {
	testData := `
{
    "id": "in_00000000000000",
    "object": "invoice",
    "amount_due": 100,
    "currency": "usd",
    "customer": %q
}`

	tests.WithConfiguration(t, func(c *config.Config) {
		stripe.Key = c.Stripe.SecretToken

		Convey("Given stub data", t, func() {
			withStubData(func(username, groupName, sessionID string) {
				Convey("Then Group should have customer id", func() {
					group, err := modelhelper.GetGroup(groupName)
					tests.ResultedWithNoErrorCheck(group, err)
					Convey("When invoice handlers are triggered", func() {
						var invoice *stripe.Invoice
						raw := fmt.Sprintf(testData, group.Payment.Customer.ID)
						err := json.Unmarshal([]byte(raw), &invoice)
						So(err, ShouldBeNil)

						var capturedMails []*emailsender.Mail

						realMailSender := mailSender
						mailSender = func(m *emailsender.Mail) error {
							capturedMails = append(capturedMails, m)
							return nil
						}

						eventName := "test event name"
						err = sendInvoiceEvent(invoice, eventName)
						So(err, ShouldBeNil)
						mailSender = realMailSender
						Convey("properties of event should be set accordingly", func() {
							So(len(capturedMails), ShouldEqual, 1)
							So(capturedMails[0].Subject, ShouldEqual, eventName)
						})
					})
				})
			})
		})
	})
}
Beispiel #25
0
func handleInvoiceStateChange(invoice *stripe.Invoice) error {
	cus, err := customer.Get(invoice.Customer.ID, nil)
	if err != nil {
		return err
	}

	if err := syncGroupWithCustomerID(invoice.Customer.ID); err != nil {
		return err
	}

	group, err := modelhelper.GetGroup(cus.Meta["groupName"])
	// we might get events from other environments where we might not have the
	// group in this env.
	if err == mgo.ErrNotFound {
		return nil
	}

	if err != nil {
		return err
	}

	status := group.Payment.Subscription.Status

	// if sub is in cancelled state within 2 months send an event
	if stripe.SubStatus(status) == SubStatusCanceled {
		// if group has been created in last 2 months (1 month trial + 1 month free)
		totalTrialTime := time.Now().UTC().Add(-time.Hour * 24 * 60)
		if group.Id.Time().After(totalTrialTime) {
			eventName := "trial ended without payment"
			sendEventForCustomer(invoice.Customer.ID, eventName, nil)
		}
	}

	// send instance notification to group
	go realtimehelper.NotifyGroup(
		group.Slug,
		"payment_status_changed",
		map[string]string{
			"oldStatus": string(group.Payment.Subscription.Status),
			"newStatus": string(status),
		},
	)

	eventName := fmt.Sprintf("subscription status %s", status)
	return sendEventForCustomer(invoice.Customer.ID, eventName, nil)
}
Beispiel #26
0
// CancelSubscriptionForGroup cancels the subscription for a team. In order to
// achive that, first deletes the current subscription then subscribes to new
// plan with new quantity, ( reasoning behind that is subscribing to a new plan
// charges immediately ) Then deletes the current subscription again. All these
// reqiured because we charge our users at the end of the month based  on the
// usage. So while cancelling group subscription, charge for the due usage
// amount immediately then cancel subscription
func CancelSubscriptionForGroup(groupName string) (*stripe.Sub, error) {
	group, err := modelhelper.GetGroup(groupName)
	if err != nil {
		return nil, err
	}

	info, err := GetInfoForGroup(group)
	if err != nil {
		return nil, err
	}

	if err := switchToNewSub(info); err != nil {
		return nil, err
	}

	return DeleteSubscriptionForGroup(groupName)
}
Beispiel #27
0
func syncGroupWithCustomerID(cusID string) error {
	cus, err := customer.Get(cusID, nil)
	if err != nil {
		return err
	}

	group, err := modelhelper.GetGroup(cus.Meta["groupName"])
	if err == mgo.ErrNotFound {
		return nil
	}

	if err != nil {
		return err
	}

	// here sub count might be 0, but should not be gt 1
	if cus.Subs.Count > 1 {
		return errors.New("customer should only have one subscription")
	}

	subID := ""
	subStatus := SubStatusCanceled

	// if we dont have any sub, set it as canceled
	if cus.Subs.Count == 1 {
		subID = cus.Subs.Values[0].ID
		subStatus = cus.Subs.Values[0].Status
	}

	// if subID and subStatus are same, update not needed
	if group.Payment.Subscription.ID == subID &&
		stripe.SubStatus(group.Payment.Subscription.Status) == subStatus {
		return nil
	}

	return modelhelper.UpdateGroupPartial(
		modelhelper.Selector{"_id": group.Id},
		modelhelper.Selector{
			"$set": modelhelper.Selector{
				"payment.subscription.id":     subID,
				"payment.subscription.status": string(subStatus),
			},
		},
	)
}
Beispiel #28
0
func withStubData(f func(username string, groupName string, sessionID string)) {
	acc, _, groupName := models.CreateRandomGroupDataWithChecks()
	group, err := modelhelper.GetGroup(groupName)
	tests.ResultedWithNoErrorCheck(group, err)

	err = modelhelper.MakeAdmin(bson.ObjectIdHex(acc.OldId), group.Id)
	So(err, ShouldBeNil)

	ses, err := modelhelper.FetchOrCreateSession(acc.Nick, groupName)
	tests.ResultedWithNoErrorCheck(ses, err)

	cus, err := EnsureCustomerForGroup(acc.Nick, groupName, &stripe.CustomerParams{})
	tests.ResultedWithNoErrorCheck(cus, err)

	f(acc.Nick, groupName, ses.ClientId)

	err = DeleteCustomerForGroup(groupName)
	So(err, ShouldBeNil)
}
Beispiel #29
0
func TestCheckCustomerHasSource(t *testing.T) {
	tests.WithConfiguration(t, func(c *config.Config) {
		stripe.Key = c.Stripe.SecretToken

		Convey("Given a customer", t, func() {
			withStubData(func(username, groupName, sessionID string) {
				group, err := modelhelper.GetGroup(groupName)
				tests.ResultedWithNoErrorCheck(group, err)

				So(group.Payment.Customer.ID, ShouldNotBeBlank)

				Convey("When customer does not have card", func() {
					err := CheckCustomerHasSource(group.Payment.Customer.ID)
					Convey("CheckCustomerHasSource should return false", func() {
						So(err, ShouldEqual, ErrCustomerSourceNotExists)

						Convey("When customer does have card", func() {
							// add credit card to the user
							withTestCreditCardToken(func(token string) {
								// attach payment source
								cp := &stripe.CustomerParams{
									Source: &stripe.SourceParams{
										Token: token,
									},
								}
								c, err := UpdateCustomerForGroup(username, groupName, cp)
								tests.ResultedWithNoErrorCheck(c, err)
								Convey("CheckCustomerHasSource should return true", func() {
									err := CheckCustomerHasSource(group.Payment.Customer.ID)
									So(err, ShouldBeNil)
								})
							})
						})
					})
				})
			})
		})
	})
}
Beispiel #30
0
// DeleteCustomerForGroup deletes the customer for a given group. If customer is
// not registered, returns error. If customer is already deleted, returns success.
// Not necessarily should be used. Call with care.
func DeleteCustomerForGroup(groupName string) error {
	group, err := modelhelper.GetGroup(groupName)
	if err != nil {
		return err
	}

	if group.Payment.Customer.ID == "" {
		return nil
	}

	if err := deleteCustomer(group.Payment.Customer.ID); err != nil {
		return err
	}

	return modelhelper.UpdateGroupPartial(
		modelhelper.Selector{"_id": group.Id},
		modelhelper.Selector{
			// deleting customer deletes everything belong to that customer in stripe,
			// so say we all
			"$unset": modelhelper.Selector{"payment": ""},
		},
	)
}