Пример #1
1
func TestRediStore(t *testing.T) {
	var req *http.Request
	var rsp *ResponseRecorder
	var hdr http.Header
	var err error
	var ok bool
	var cookies []string
	var session *sessions.Session
	var flashes []interface{}

	// Copyright 2012 The Gorilla Authors. All rights reserved.
	// Use of this source code is governed by a BSD-style
	// license that can be found in the LICENSE file.

	// Round 1 ----------------------------------------------------------------

	// RedisStore
	store := NewRediStore(10, "tcp", ":6379", "", []byte("secret-key"))
	defer store.Close()

	req, _ = http.NewRequest("GET", "http://localhost:8080/", nil)
	rsp = NewRecorder()
	// Get a session.
	if session, err = store.Get(req, "session-key"); err != nil {
		t.Fatalf("Error getting session: %v", err)
	}
	// Get a flash.
	flashes = session.Flashes()
	if len(flashes) != 0 {
		t.Errorf("Expected empty flashes; Got %v", flashes)
	}
	// Add some flashes.
	session.AddFlash("foo")
	session.AddFlash("bar")
	// Custom key.
	session.AddFlash("baz", "custom_key")
	// Save.
	if err = sessions.Save(req, rsp); err != nil {
		t.Fatalf("Error saving session: %v", err)
	}
	hdr = rsp.Header()
	cookies, ok = hdr["Set-Cookie"]
	if !ok || len(cookies) != 1 {
		t.Fatalf("No cookies. Header:", hdr)
	}

	// Round 2 ----------------------------------------------------------------

	req, _ = http.NewRequest("GET", "http://localhost:8080/", nil)
	req.Header.Add("Cookie", cookies[0])
	rsp = NewRecorder()
	// Get a session.
	if session, err = store.Get(req, "session-key"); err != nil {
		t.Fatalf("Error getting session: %v", err)
	}
	// Check all saved values.
	flashes = session.Flashes()
	if len(flashes) != 2 {
		t.Fatalf("Expected flashes; Got %v", flashes)
	}
	if flashes[0] != "foo" || flashes[1] != "bar" {
		t.Errorf("Expected foo,bar; Got %v", flashes)
	}
	flashes = session.Flashes()
	if len(flashes) != 0 {
		t.Errorf("Expected dumped flashes; Got %v", flashes)
	}
	// Custom key.
	flashes = session.Flashes("custom_key")
	if len(flashes) != 1 {
		t.Errorf("Expected flashes; Got %v", flashes)
	} else if flashes[0] != "baz" {
		t.Errorf("Expected baz; Got %v", flashes)
	}
	flashes = session.Flashes("custom_key")
	if len(flashes) != 0 {
		t.Errorf("Expected dumped flashes; Got %v", flashes)
	}

	// RediStore specific
	// Set MaxAge to -1 to mark for deletion.
	session.Options.MaxAge = -1
	// Save.
	if err = sessions.Save(req, rsp); err != nil {
		t.Fatalf("Error saving session: %v", err)
	}

	// Round 3 ----------------------------------------------------------------
	// Custom type

	// RedisStore
	store = NewRediStore(10, "tcp", ":6379", "", []byte("secret-key"))
	defer store.Close()

	req, _ = http.NewRequest("GET", "http://localhost:8080/", nil)
	rsp = NewRecorder()
	// Get a session.
	if session, err = store.Get(req, "session-key"); err != nil {
		t.Fatalf("Error getting session: %v", err)
	}
	// Get a flash.
	flashes = session.Flashes()
	if len(flashes) != 0 {
		t.Errorf("Expected empty flashes; Got %v", flashes)
	}
	// Add some flashes.
	session.AddFlash(&FlashMessage{42, "foo"})
	// Save.
	if err = sessions.Save(req, rsp); err != nil {
		t.Fatalf("Error saving session: %v", err)
	}
	hdr = rsp.Header()
	cookies, ok = hdr["Set-Cookie"]
	if !ok || len(cookies) != 1 {
		t.Fatalf("No cookies. Header:", hdr)
	}

	// Round 4 ----------------------------------------------------------------
	// Custom type

	req, _ = http.NewRequest("GET", "http://localhost:8080/", nil)
	req.Header.Add("Cookie", cookies[0])
	rsp = NewRecorder()
	// Get a session.
	if session, err = store.Get(req, "session-key"); err != nil {
		t.Fatalf("Error getting session: %v", err)
	}
	// Check all saved values.
	flashes = session.Flashes()
	if len(flashes) != 1 {
		t.Fatalf("Expected flashes; Got %v", flashes)
	}
	custom := flashes[0].(FlashMessage)
	if custom.Type != 42 || custom.Message != "foo" {
		t.Errorf("Expected %#v, got %#v", FlashMessage{42, "foo"}, custom)
	}

	// RediStore specific
	// Set MaxAge to -1 to mark for deletion.
	session.Options.MaxAge = -1
	// Save.
	if err = sessions.Save(req, rsp); err != nil {
		t.Fatalf("Error saving session: %v", err)
	}

	// Round 5 ----------------------------------------------------------------
	// RediStore Delete session (deprecated)

	//req, _ = http.NewRequest("GET", "http://localhost:8080/", nil)
	//req.Header.Add("Cookie", cookies[0])
	//rsp = NewRecorder()
	//// Get a session.
	//if session, err = store.Get(req, "session-key"); err != nil {
	//	t.Fatalf("Error getting session: %v", err)
	//}
	//// Delete session.
	//if err = store.Delete(req, rsp, session); err != nil {
	//	t.Fatalf("Error deleting session: %v", err)
	//}
	//// Get a flash.
	//flashes = session.Flashes()
	//if len(flashes) != 0 {
	//	t.Errorf("Expected empty flashes; Got %v", flashes)
	//}
	//hdr = rsp.Header()
	//cookies, ok = hdr["Set-Cookie"]
	//if !ok || len(cookies) != 1 {
	//	t.Fatalf("No cookies. Header:", hdr)
	//}

	// Round 6 ----------------------------------------------------------------
	// RediStore change MaxLength of session

	store = NewRediStore(10, "tcp", ":6379", "", []byte("secret-key"))
	req, err = http.NewRequest("GET", "http://www.example.com", nil)
	if err != nil {
		t.Fatal("failed to create request", err)
	}
	w := httptest.NewRecorder()

	session, err = store.New(req, "my session")
	session.Values["big"] = make([]byte, base64.StdEncoding.DecodedLen(4096*2))
	err = session.Save(req, w)
	if err == nil {
		t.Fatal("expected an error, got nil")
	}

	store.MaxLength(4096 * 3) // A bit more than the value size to account for encoding overhead.
	err = session.Save(req, w)
	if err != nil {
		t.Fatal("failed to Save:", err)
	}
}
Пример #2
0
// Clear will remove all the tokens. Call after a permission change.
func Clear(w http.ResponseWriter, r *http.Request, sess *sessions.Session) {
	// Delete the map if it doesn't exist
	if _, ok := sess.Values[TokenName]; ok {
		delete(sess.Values, TokenName)
		sess.Save(r, w)
	}
}
Пример #3
0
func fakeCookies(req *http.Request, email, userid, token, csrftoken string) error {
	var err error
	var session *sessions.Session
	resp := httptest.NewRecorder()
	session, err = sessionStore.Get(req, SESSION_NAME)
	if len(email) > 0 {
		session.Values[SESSION_EMAIL] = email
	}
	if len(userid) > 0 {
		session.Values[SESSION_USERID] = userid
	}
	if len(token) > 0 {
		session.Values[SESSION_TOKEN] = token
	}
	if len(csrftoken) > 0 {
		session.Values[SESSION_CSRFTOKEN] = csrftoken
	}

	if err = session.Save(req, resp); err != nil {
		return fmt.Errorf("Could not set cookie! %s", err.Error())
	}
	fcookies, ok := resp.HeaderMap["Set-Cookie"]
	if !ok {
		return fmt.Errorf("Cookie not set in header")
	}
	req.Header.Add("Cookie", strings.Split(fcookies[0], ";")[0])
	return nil
}
Пример #4
0
// Token will return a token. If SingleToken = true, it will return the same token for every page.
func Token(w http.ResponseWriter, r *http.Request, sess *sessions.Session) string {
	// Generate the map if it doesn't exist
	if _, ok := sess.Values[TokenName]; !ok {
		sess.Values[TokenName] = make(StringMap)
	}

	path := r.URL.Path

	if SingleToken {
		path = "/"
	}

	sessMap := sess.Values[TokenName].(StringMap)
	if _, ok := sessMap[path]; !ok {

		if len(sessMap) >= MaxTokens {
			for i, _ := range sessMap {
				delete(sessMap, i)
			}
		}

		sessMap[path] = generate(TokenLength)
		sess.Save(r, w)
	}

	return sessMap[path]
}
Пример #5
0
func googleDisconnect(w http.ResponseWriter, r *http.Request, session *sessions.Session) *appError {

	token := session.Values["accessToken"]
	if token == nil {
		m := "Current user not connected"
		return &appError{errors.New(m), m, 401}
	}

	// Execute HTTP GET request to revoke current token
	url := "https://accounts.google.com/o/oauth2/revoke?token=" + token.(string)
	resp, err := http.Get(url)
	if err != nil {
		m := "Failed to revoke token for a given user"
		return &appError{errors.New(m), m, 400}
	}
	defer resp.Body.Close()

	// Reset the user's session
	session.Values["accessToken"] = nil
	session.Values["userId"] = nil
	session.Values["gplusID"] = nil

	session.Save(r, w)
	return nil
}
Пример #6
0
func createSession(w http.ResponseWriter, r *http.Request, session *sessions.Session) *ServerSession {

	// Each session needs a unique ID in order to be saved.
	if session.ID == "" {
		session.ID = tokens.NewSessionID()
	}

	ss := &ServerSession{
		CSRFToken: tokens.NewCSRFToken(session.ID),
	}

	// Attempt to store the session. Remove the session if it's not stored
	// correctly.
	if err := ss.StoreSession(session.ID); err != nil {
		RemoveSession(session.ID)
		glog.Fatalln(err)
	}

	// Similarly, save it in our FS storage and set the user's cookie.
	if err := session.Save(r, w); err != nil {
		RemoveSession(session.ID)
		glog.Fatalln(err)
	}

	return ss
}
Пример #7
0
// ValidateAuth validates that the user cookie is set up before calling the
// handler passed as parameter.
func ValidateAuth(h httputils.ContextHandler) httputils.ContextHandler {
	return func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
		var (
			sessionData *httputils.SessionData
			err         error
			ok          bool
			cookieStore *sessions.CookieStore
			session     *sessions.Session
			cfg         = ctx.Value("config").(*config.Config)
		)

		cookieStore, ok = ctx.Value("cookieStore").(*sessions.CookieStore)

		if !ok {
			httputils.WriteError(w, http.StatusInternalServerError, "")
			return fmt.Errorf("validate auth: could not cast value as cookie store: %s", ctx.Value("cookieStore"))
		}

		session, err = cookieStore.Get(r, cfg.SessionCookieName)

		if err != nil {
			log.Println(err)
			http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
			return nil
		}

		sessionData, ok = session.Values["data"].(*httputils.SessionData)

		if !ok || sessionData.IsInvalid() {
			http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
			return nil
		} else if time.Now().After(sessionData.ExpiresAt) {
			session.Options.MaxAge = -1
			session.Save(r, w)
			http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)

			return nil
		}

		// Extend the session's lifetime.
		cfg, ok = ctx.Value("config").(*config.Config)

		if !ok {
			httputils.WriteError(w, http.StatusInternalServerError, "")
			return fmt.Errorf("validate auth: error casting config object: %s", ctx.Value("config"))
		}

		// Save session only if the session was extended.
		if extendSessionLifetime(sessionData, cfg.SessionLifeTime) {
			sessionData.ExpiresAt = time.Now().Add(cfg.SessionLifeTime)
			session.Save(r, w)
		}

		authenticatedContext := context.WithValue(ctx, "sessionData", sessionData)
		return h(authenticatedContext, w, r)
	}
}
Пример #8
0
func saveUserToSessionAndSendHome(w http.ResponseWriter, r *http.Request,
	session *sessions.Session, userName string, id int) {

	session.Values["UserName"] = userName
	session.Values["Id"] = id
	err := session.Save(r, w)
	if err != nil {
		log.Fatal(err)
	}
	http.Redirect(w, r, "/", http.StatusFound)
}
Пример #9
0
// Remove all current user information from the session object
func (c *CAS) removeCurrentUserFromSession(w http.ResponseWriter, req *http.Request, session *sessions.Session) *CASServerError {
	// Delete current user from session
	delete(session.Values, "currentUser")

	// Save the modified session
	err := session.Save(req, w)
	if err != nil {
		return &FailedToDeleteSessionError
	}

	return nil
}
Пример #10
0
// Token will return a token for the specified URL. SingleToken is ignored.
func TokenWithPath(w http.ResponseWriter, r *http.Request, sess *sessions.Session, urlPath string) string {
	// Generate the map if it doesn't exist
	if _, ok := sess.Values[TokenName]; !ok {
		sess.Values[TokenName] = make(StringMap)
	}

	sessMap := sess.Values[TokenName].(StringMap)
	if _, ok := sessMap[urlPath]; !ok {
		sessMap[urlPath] = generate(TokenLength)
		sess.Save(r, w)
	}

	return sessMap[urlPath]
}
Пример #11
0
func loginHandler(res http.ResponseWriter, r *http.Request, session *sessions.Session, ctx *pongo2.Context) (*string, error) {
	var (
		username = strings.ToLower(r.FormValue("username"))
		password = fmt.Sprintf("%x", sha1.Sum([]byte(cfg.PasswordSalt+r.FormValue("password"))))
	)

	if !storage.IsPresent(createUserFilename(username)) {
		(*ctx)["error"] = true
		return stringPointer("login.html"), nil
	}

	userFileRaw, err := storage.Read(createUserFilename(username))
	if err != nil {
		fmt.Printf("ERR: Unable to read user file: %s\n", err)
		(*ctx)["error"] = true
		return stringPointer("login.html"), nil
	}

	userFile, _ := readDataObject(userFileRaw)

	if userFile.MetaData.Password != password {
		(*ctx)["error"] = true
		return stringPointer("login.html"), nil
	}

	auth, ok := session.Values["authorizedAccounts"].(authorizedAccounts)
	if !ok {
		auth = authorizedAccounts{}
	}

	for i, v := range auth {
		if v.Name == username {
			http.Redirect(res, r, fmt.Sprintf("u/%d/overview", i), http.StatusFound)
			return nil, nil
		}
	}

	auth = append(auth, authorizedAccount{
		Name:     username,
		UserFile: createUserFilename(username),
	})

	session.Values["authorizedAccounts"] = auth
	if err := session.Save(r, res); err != nil {
		return nil, err
	}

	http.Redirect(res, r, fmt.Sprintf("u/%d/overview", len(auth)-1), http.StatusFound)
	return nil, nil
}
Пример #12
0
func HomeHandler(w http.ResponseWriter, r *http.Request) {
	var session *sessions.Session
	s, err := store.Get(r, "session-name")
	if err != nil {
		log.Println("error fetching session:", err)
		s, _ := store.New(r, "session-name")
		session = s
	} else {
		session = s
	}
	state := randomString(64)
	session.Values["state"] = state
	session.Save(r, w)

	if err := Views.Lookup("home.ghtml").Execute(w, struct{}{}); err != nil {
		log.Printf("error executing view template: %v", err)
	}
}
Пример #13
0
func (sc SessionController) SaveSession(w http.ResponseWriter, r *http.Request, s *sessions.Session) {
	err := s.Save(r, w)
	if err != nil {
		log.Println("ERROR: SessionController: SaveSession: " + err.Error())
	}
}
//ExtendExpiration pushes out the expiration of the session cookie to a further time
//this is done to keep a user logged in automatically if they use the app frequently
func ExtendExpiration(session *sessions.Session, w http.ResponseWriter, r *http.Request) {
	session.Options = options
	session.Save(r, w)
	return
}
//Save saves any new session data to an existing session
//write the new values to it (after using AddValue)
func Save(session *sessions.Session, w http.ResponseWriter, r *http.Request) {
	session.Save(r, w)
	return
}
Пример #16
0
func endSession(s *sessions.Session, w http.ResponseWriter, r *http.Request) {
	s.Options = &sessions.Options{MaxAge: -1}
	s.Save(r, w)
}
Пример #17
0
func loginHandler(w http.ResponseWriter, r *http.Request) error {
	ctx := context.Get(r, TemplateContext).(map[string]interface{})
	ctx["Title"] = "Login"
	if r.Method == "GET" {
		return renderTemplate(w, "login", ctx)
	}

	session, err := store.Get(r, "flashes")
	if err != nil {
		return err
	}

	if err := r.ParseForm(); err != nil {
		return err
	}

	lschema := &LoginSchema{}
	decoder := schema.NewDecoder()

	if err := decoder.Decode(lschema, r.PostForm); err != nil {
		return err
	}

	formErrors := []string{}

	if !govalidator.IsEmail(lschema.Email) {
		if lschema.Email == "" {
			formErrors = append(formErrors, "Email cannot be blank")
		} else {
			formErrors = append(formErrors, fmt.Sprintf("%s is not a valid email address", lschema.Email))
		}
	}
	if lschema.Password == "" {
		formErrors = append(formErrors, "Password cannot be blank")
	}
	if len(formErrors) > 0 {
		for _, msg := range formErrors {
			session.AddFlash(msg, "danger")
		}
		session.Save(r, w)
		http.Redirect(w, r, reverse("login"), http.StatusSeeOther)
		return nil
	}

	userbytes, err := database.Get(uint64(1), config.BucketNameUser)
	if err != nil {
		formErrors = append(formErrors, "Email and password did not match")
	}

	user := DeserializeUser(userbytes)

	if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(lschema.Password)); err != nil {
		formErrors = append(formErrors, "Email and password did not match")
	}

	if len(formErrors) > 0 {
		for _, msg := range formErrors {
			session.AddFlash(msg, "danger")
		}
		session.Save(r, w)
		http.Redirect(w, r, reverse("login"), http.StatusSeeOther)
		return nil
	}

	var authsession *sessions.Session
	authsession, err = store.Get(r, "auth")
	if err != nil {
		return err
	}

	authsession.Values["userID"] = user.ID
	authsession.Save(r, w)

	http.Redirect(w, r, reverse("url-index"), http.StatusSeeOther)
	return nil
}
Пример #18
0
func deleteSession(session *sessions.Session, w http.ResponseWriter, r *http.Request) {
	session.Options = &sessions.Options{MaxAge: -1}
	session.Save(r, w)
}
Пример #19
0
func logoutHandler(res http.ResponseWriter, r *http.Request, session *sessions.Session, ctx *pongo2.Context) (*string, error) {
	session.Values["authorizedAccounts"] = authorizedAccounts{}
	session.Save(r, res)
	http.Redirect(res, r, "overview", http.StatusFound)
	return nil, nil
}
Пример #20
0
func (u *User) saveSession(session *sessions.Session, w http.ResponseWriter, r *http.Request) error {
	session.Values["nickname"] = u.Nickname
	session.Values["email"] = u.Email
	return session.Save(r, w)

}