Beispiel #1
0
// Respond performs an API response, adding some additional data to
// the context's CodecOptions to support our custom codecs.  This
// particular function is very specifically for use with the
// github.com/stretchr/goweb web framework.
//
// TODO: Move the with={} parameter to options in the mimetypes in the
// Accept header.
func Respond(ctx context.Context, status int, notifications MessageMap, data interface{}, useFullDomain ...bool) error {
	body, err := web_request_readers.ParseBody(ctx)
	if err != nil {
		return err
	}
	if ctx.QueryParams().Has("joins") {
		if m, ok := body.(objx.Map); ok {
			m.Set("joins", ctx.QueryValue("joins"))
		}
	}

	protocol := "http"
	if ctx.HttpRequest().TLS != nil {
		protocol += "s"
	}

	host := ctx.HttpRequest().Host

	requestDomain := fmt.Sprintf("%s://%s", protocol, host)
	if status == http.StatusOK {
		location := "Error: no location present"
		if locationer, ok := data.(Locationer); ok {
			location = fmt.Sprintf("%s%s", requestDomain, locationer.Location())
		}
		ctx.HttpResponseWriter().Header().Set("Location", location)

		if linker, ok := data.(RelatedLinker); ok {
			linkMap := linker.RelatedLinks()
			links := make([]string, 0, len(linkMap)+1)
			links = append(links, fmt.Sprintf(`<%s>; rel="location"`, location))
			for rel, link := range linkMap {
				link := fmt.Sprintf(`<%s%s>; rel="%s"`, requestDomain, link, rel)
				links = append(links, link)
			}
			ctx.HttpResponseWriter().Header().Set("Link", strings.Join(links, ", "))
		}
	}
	// Transitionary period - don't pass the domain to the codec
	// unless it's requested in the responder
	if len(useFullDomain) == 0 || useFullDomain[0] == false {
		requestDomain = ""
	}

	options := ctx.CodecOptions()
	options.MergeHere(objx.Map{
		"status":        status,
		"input_params":  body,
		"notifications": notifications,
		"domain":        requestDomain,
	})

	// Right now, this line is commented out to support our joins
	// logic.  Unfortunately, that means that codecs other than our
	// custom codecs from this package will not work.  Whoops.
	// data = CreateResponse(data)

	return goweb.API.WriteResponseObject(ctx, status, data)
}
Beispiel #2
0
func Callback(ctx context.Context) error {
	provider_type := ctx.PathValue("provider")
	provider, err := gomniauth.Provider(provider_type)
	if err != nil {
		log.Error("Error on getting provider: " + err.Error())
		return goweb.API.Respond(ctx, 200, nil, []string{"An error has occured."})
	}
	creds, err := provider.CompleteAuth(ctx.QueryParams())
	if err != nil {
		log.Error("Error on completing auth: " + err.Error())
		return goweb.API.Respond(ctx, 200, nil, []string{"An error has occured."})
	}
	// load the user
	// https://github.com/stretchr/gomniauth/blob/master/common/user.go
	user, userErr := provider.GetUser(creds)
	if userErr != nil {
		log.Error("Error on getting user: "******"An error has occured."})
	}

	passport := m.Passport{}
	err = m.GetDB("Passport").
		Find(bson.M{"provider": provider_type,
			"identifier": user.IDForProvider(provider_type)}).
		One(&passport)
	if err != nil {
		if err.Error() == "not found" {
			var currentUser, ok = ctx.Data()["user"].(m.User)
			if ok {
				err = m.GetDB("Passport").
					Insert(&m.Passport{bson.NewObjectId(), currentUser.Id, "", provider_type,
						user.IDForProvider(provider_type), fmt.Sprintf("%v", creds.Map.Get("access_token").Data()),
						fmt.Sprintf("%v", creds.Map.Get("refresh_token").Data())})
				if err != nil {
					log.Error("Error on registration with provider " + provider_type + ", new passport: " + err.Error())
					return goweb.API.Respond(ctx, 200, nil, []string{"Could not create your new authorization."})
				}
				log.Info("Connecting user")
				url, _ := url.Parse(utils.EnvUrl() + "/#/fblogin/?token=" + currentUser.Token)
				return goweb.Respond.WithRedirect(ctx, url)
			} else {
				// No user, create user, create passport
				var token = nonce.NewToken()
				nonce.MarkToken(token)
				newUser := m.User{bson.NewObjectId(), user.Nickname(), user.Email(), true, token, time.Now()}
				err = m.GetDB("User").Insert(&newUser)
				if err != nil {
					log.Error("Error on registration with provider " + provider_type + ", new user: "******"Failed to register."})
				}
				err = m.GetDB("Passport").
					Insert(&m.Passport{bson.NewObjectId(), newUser.Id, "", provider_type,
						user.IDForProvider(provider_type), fmt.Sprintf("%v", creds.Map.Get("access_token").Data()),
						fmt.Sprintf("%v", creds.Map.Get("refresh_token").Data())})
				if err != nil {
					log.Error("Error on registration with provider " + provider_type + ", new user passport: " + err.Error())
					return goweb.API.Respond(ctx, 200, nil, []string{"Failed to create your new passport."})
				}
				log.Info("New user registered")
				url, _ := url.Parse(utils.EnvUrl() + "/#/fblogin/?token=" + newUser.Token)
				return goweb.Respond.WithRedirect(ctx, url)
			}
		} else {
			log.Error("Error on registration with provider " + provider_type + ", new passport: " + err.Error())
			return goweb.API.Respond(ctx, 200, nil, []string{"Could not find your authorization."})
		}
	} else {
		// login the user
		var user = m.User{}
		fmt.Println(passport)
		err = m.GetDB("User").Find(bson.M{"_id": passport.User}).One(&user)
		if err != nil {
			log.Error("Error on login with provider " + provider_type + ", user query: " + err.Error())
			return goweb.API.Respond(ctx, 200, nil, []string{"Could not find you on the database."})
		}
		log.Info("Found user returning id")
		url, _ := url.Parse(utils.EnvUrl() + "/#/fblogin/?token=" + user.Token)
		return goweb.Respond.WithRedirect(ctx, url)
	}
}