mirror of https://github.com/writeas/writefreely
parent
af601d7b0c
commit
62abc11142
@ -0,0 +1,11 @@ |
||||
package writefreely |
||||
|
||||
import ( |
||||
"github.com/writeas/impart" |
||||
"net/http" |
||||
) |
||||
|
||||
// Commonly returned HTTP errors
|
||||
var ( |
||||
ErrInternalCookieSession = impart.HTTPError{http.StatusInternalServerError, "Could not get cookie session."} |
||||
) |
@ -0,0 +1,126 @@ |
||||
package writefreely |
||||
|
||||
import ( |
||||
"encoding/gob" |
||||
"github.com/gorilla/sessions" |
||||
"github.com/writeas/web-core/log" |
||||
"net/http" |
||||
"strings" |
||||
) |
||||
|
||||
const ( |
||||
day = 86400 |
||||
sessionLength = 180 * day |
||||
cookieName = "wfu" |
||||
cookieUserVal = "u" |
||||
) |
||||
|
||||
// initSession creates the cookie store. It depends on the keychain already
|
||||
// being loaded.
|
||||
func initSession(app *app) *sessions.CookieStore { |
||||
// Register complex data types we'll be storing in cookies
|
||||
gob.Register(&User{}) |
||||
|
||||
// Create the cookie store
|
||||
store := sessions.NewCookieStore(app.keys.cookieAuthKey, app.keys.cookieKey) |
||||
store.Options = &sessions.Options{ |
||||
Path: "/", |
||||
MaxAge: sessionLength, |
||||
HttpOnly: true, |
||||
Secure: strings.HasPrefix(app.cfg.Server.Host, "https://"), |
||||
} |
||||
return store |
||||
} |
||||
|
||||
func getSessionFlashes(app *app, w http.ResponseWriter, r *http.Request, session *sessions.Session) ([]string, error) { |
||||
var err error |
||||
if session == nil { |
||||
session, err = app.sessionStore.Get(r, cookieName) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
} |
||||
|
||||
f := []string{} |
||||
if flashes := session.Flashes(); len(flashes) > 0 { |
||||
for _, flash := range flashes { |
||||
if str, ok := flash.(string); ok { |
||||
f = append(f, str) |
||||
} |
||||
} |
||||
} |
||||
saveUserSession(app, r, w) |
||||
|
||||
return f, nil |
||||
} |
||||
|
||||
func addSessionFlash(app *app, w http.ResponseWriter, r *http.Request, m string, session *sessions.Session) error { |
||||
var err error |
||||
if session == nil { |
||||
session, err = app.sessionStore.Get(r, cookieName) |
||||
} |
||||
|
||||
if err != nil { |
||||
log.Error("Unable to add flash '%s': %v", m, err) |
||||
return err |
||||
} |
||||
|
||||
session.AddFlash(m) |
||||
saveUserSession(app, r, w) |
||||
return nil |
||||
} |
||||
|
||||
func getUserAndSession(app *app, r *http.Request) (*User, *sessions.Session) { |
||||
session, err := app.sessionStore.Get(r, cookieName) |
||||
if err == nil { |
||||
// Got the currently logged-in user
|
||||
val := session.Values[cookieUserVal] |
||||
var u = &User{} |
||||
var ok bool |
||||
if u, ok = val.(*User); ok { |
||||
return u, session |
||||
} |
||||
} |
||||
|
||||
return nil, nil |
||||
} |
||||
|
||||
func getUserSession(app *app, r *http.Request) *User { |
||||
u, _ := getUserAndSession(app, r) |
||||
return u |
||||
} |
||||
|
||||
func saveUserSession(app *app, r *http.Request, w http.ResponseWriter) error { |
||||
session, err := app.sessionStore.Get(r, cookieName) |
||||
if err != nil { |
||||
return ErrInternalCookieSession |
||||
} |
||||
|
||||
// Extend the session
|
||||
session.Options.MaxAge = int(sessionLength) |
||||
|
||||
// Remove any information that accidentally got added
|
||||
// FIXME: find where Plan information is getting saved to cookie.
|
||||
val := session.Values[cookieUserVal] |
||||
var u = &User{} |
||||
var ok bool |
||||
if u, ok = val.(*User); ok { |
||||
session.Values[cookieUserVal] = u.Cookie() |
||||
} |
||||
|
||||
err = session.Save(r, w) |
||||
if err != nil { |
||||
log.Error("Couldn't saveUserSession: %v", err) |
||||
} |
||||
return err |
||||
} |
||||
|
||||
func getFullUserSession(app *app, r *http.Request) *User { |
||||
u := getUserSession(app, r) |
||||
if u == nil { |
||||
return nil |
||||
} |
||||
|
||||
u, _ = app.db.GetUserByID(u.ID) |
||||
return u |
||||
} |
@ -0,0 +1,51 @@ |
||||
package writefreely |
||||
|
||||
import ( |
||||
"time" |
||||
|
||||
"github.com/guregu/null/zero" |
||||
"github.com/writeas/web-core/data" |
||||
"github.com/writeas/web-core/log" |
||||
) |
||||
|
||||
type ( |
||||
// User is a consistent user object in the database and all contexts (auth
|
||||
// and non-auth) in the API.
|
||||
User struct { |
||||
ID int64 `json:"-"` |
||||
Username string `json:"username"` |
||||
HashedPass []byte `json:"-"` |
||||
HasPass bool `json:"has_pass"` |
||||
Email zero.String `json:"email"` |
||||
Created time.Time `json:"created"` |
||||
|
||||
clearEmail string `json:"email"` |
||||
} |
||||
) |
||||
|
||||
// EmailClear decrypts and returns the user's email, caching it in the user
|
||||
// object.
|
||||
func (u *User) EmailClear(keys *keychain) string { |
||||
if u.clearEmail != "" { |
||||
return u.clearEmail |
||||
} |
||||
|
||||
if u.Email.Valid && u.Email.String != "" { |
||||
email, err := data.Decrypt(keys.emailKey, []byte(u.Email.String)) |
||||
if err != nil { |
||||
log.Error("Error decrypting user email: %v", err) |
||||
} else { |
||||
u.clearEmail = string(email) |
||||
return u.clearEmail |
||||
} |
||||
} |
||||
return "" |
||||
} |
||||
|
||||
// Cookie strips down an AuthUser to contain only information necessary for
|
||||
// cookies.
|
||||
func (u User) Cookie() *User { |
||||
u.HashedPass = []byte{} |
||||
|
||||
return &u |
||||
} |
Loading…
Reference in new issue