// 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) }
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) } }