everywhere: use different session cookie names

If the user is hosting the dashboard in the same domain as
their blog (with a nginx suburi, for example), the two session
cookies clash; logging into one service logs you out of the other.
With this patch, both have separate names.

Fixes https://gitlab.com/commento/commento-ce/issues/49
This commit is contained in:
Adhityaa 2018-06-20 08:59:55 +05:30
parent 76a286d884
commit ef0f45527a
45 changed files with 189 additions and 282 deletions

View File

@ -26,7 +26,7 @@ func commentApprove(commentHex string) error {
func commentApproveHandler(w http.ResponseWriter, r *http.Request) {
type request struct {
Session *string `json:"session"`
CommenterToken *string `json:"commenterToken"`
CommentHex *string `json:"commentHex"`
}
@ -36,7 +36,7 @@ func commentApproveHandler(w http.ResponseWriter, r *http.Request) {
return
}
c, err := commenterGetBySession(*x.Session)
c, err := commenterGetByCommenterToken(*x.CommenterToken)
if err != nil {
writeBody(w, response{"success": false, "message": err.Error()})
return

View File

@ -25,7 +25,7 @@ func commentDelete(commentHex string) error {
func commentDeleteHandler(w http.ResponseWriter, r *http.Request) {
type request struct {
Session *string `json:"session"`
CommenterToken *string `json:"commenterToken"`
CommentHex *string `json:"commentHex"`
}
@ -35,7 +35,7 @@ func commentDeleteHandler(w http.ResponseWriter, r *http.Request) {
return
}
c, err := commenterGetBySession(*x.Session)
c, err := commenterGetByCommenterToken(*x.CommenterToken)
if err != nil {
writeBody(w, response{"success": false, "message": err.Error()})
return

View File

@ -91,7 +91,7 @@ func commentList(commenterHex string, domain string, path string, includeUnappro
func commentListHandler(w http.ResponseWriter, r *http.Request) {
type request struct {
Session *string `json:"session"`
CommenterToken *string `json:"CommenterToken"`
Domain *string `json:"domain"`
Path *string `json:"path"`
}
@ -113,10 +113,10 @@ func commentListHandler(w http.ResponseWriter, r *http.Request) {
commenterHex := "anonymous"
isModerator := false
if *x.Session != "anonymous" {
c, err := commenterGetBySession(*x.Session)
if *x.CommenterToken != "anonymous" {
c, err := commenterGetByCommenterToken(*x.CommenterToken)
if err != nil {
if err == errorNoSuchSession {
if err == errorNoSuchToken {
commenterHex = "anonymous"
} else {
writeBody(w, response{"success": false, "message": err.Error()})

View File

@ -36,7 +36,7 @@ func commentNew(commenterHex string, domain string, path string, parentHex strin
func commentNewHandler(w http.ResponseWriter, r *http.Request) {
type request struct {
Session *string `json:"session"`
CommenterToken *string `json:"commenterToken"`
Domain *string `json:"domain"`
Path *string `json:"path"`
ParentHex *string `json:"parentHex"`
@ -74,11 +74,11 @@ func commentNewHandler(w http.ResponseWriter, r *http.Request) {
var commenterHex string
var state string
if *x.Session == "anonymous" {
if *x.CommenterToken == "anonymous" {
state = "unapproved"
commenterHex = "anonymous"
} else {
c, err := commenterGetBySession(*x.Session)
c, err := commenterGetByCommenterToken(*x.CommenterToken)
if err != nil {
writeBody(w, response{"success": false, "message": err.Error()})
return

View File

@ -45,7 +45,7 @@ func commentVote(commenterHex string, commentHex string, direction int) error {
func commentVoteHandler(w http.ResponseWriter, r *http.Request) {
type request struct {
Session *string `json:"session"`
CommenterToken *string `json:"commenterToken"`
CommentHex *string `json:"commentHex"`
Direction *int `json:"direction"`
}
@ -56,12 +56,12 @@ func commentVoteHandler(w http.ResponseWriter, r *http.Request) {
return
}
if *x.Session == "anonymous" {
if *x.CommenterToken == "anonymous" {
writeBody(w, response{"success": false, "message": errorUnauthorisedVote.Error()})
return
}
c, err := commenterGetBySession(*x.Session)
c, err := commenterGetByCommenterToken(*x.CommenterToken)
if err != nil {
writeBody(w, response{"success": false, "message": err.Error()})
return

View File

@ -44,26 +44,26 @@ func commenterGetByEmail(provider string, email string) (commenter, error) {
return c, nil
}
func commenterGetBySession(session string) (commenter, error) {
if session == "" {
func commenterGetByCommenterToken(commenterToken string) (commenter, error) {
if commenterToken == "" {
return commenter{}, errorMissingField
}
statement := `
SELECT commenterHex
FROM commenterSessions
WHERE session = $1;
WHERE commenterToken = $1;
`
row := db.QueryRow(statement, session)
row := db.QueryRow(statement, commenterToken)
var commenterHex string
if err := row.Scan(&commenterHex); err != nil {
// TODO: is the only error?
return commenter{}, errorNoSuchSession
return commenter{}, errorNoSuchToken
}
if commenterHex == "none" {
return commenter{}, errorNoSuchSession
return commenter{}, errorNoSuchToken
}
return commenterGetByHex(commenterHex)

View File

@ -30,16 +30,16 @@ func TestCommenterGetByHexEmpty(t *testing.T) {
}
}
func TestCommenterGetBySession(t *testing.T) {
func TestCommenterGetByCommenterToken(t *testing.T) {
failTestOnError(t, setupTestEnv())
commenterHex, _ := commenterNew("test@example.com", "Test", "undefined", "https://example.com/photo.jpg", "google", "")
session, _ := commenterSessionNew()
commenterToken, _ := commenterTokenNew()
commenterSessionUpdate(session, commenterHex)
commenterSessionUpdate(commenterToken, commenterHex)
c, err := commenterGetBySession(session)
c, err := commenterGetByCommenterToken(commenterToken)
if err != nil {
t.Errorf("unexpected error getting commenter by hex: %v", err)
return
@ -51,11 +51,11 @@ func TestCommenterGetBySession(t *testing.T) {
}
}
func TestCommenterGetBySessionEmpty(t *testing.T) {
func TestCommenterGetByCommenterTokenEmpty(t *testing.T) {
failTestOnError(t, setupTestEnv())
if _, err := commenterGetBySession(""); err == nil {
t.Errorf("expected error not found getting commenter with empty session")
if _, err := commenterGetByCommenterToken(""); err == nil {
t.Errorf("expected error not found getting commenter with empty commenterToken")
return
}
}
@ -65,9 +65,9 @@ func TestCommenterGetByName(t *testing.T) {
commenterHex, _ := commenterNew("test@example.com", "Test", "undefined", "https://example.com/photo.jpg", "google", "")
session, _ := commenterSessionNew()
commenterToken, _ := commenterTokenNew()
commenterSessionUpdate(session, commenterHex)
commenterSessionUpdate(commenterToken, commenterHex)
c, err := commenterGetByEmail("google", "test@example.com")
if err != nil {

View File

@ -29,24 +29,24 @@ func commenterLogin(email string, password string) (string, error) {
return "", errorInvalidEmailPassword
}
session, err := randomHex(32)
commenterToken, err := randomHex(32)
if err != nil {
logger.Errorf("cannot create session hex: %v", err)
logger.Errorf("cannot create commenterToken: %v", err)
return "", errorInternal
}
statement = `
INSERT INTO
commenterSessions (session, commenterHex, creationDate)
VALUES ($1, $2, $3 );
commenterSessions (commenterToken, commenterHex, creationDate)
VALUES ($1, $2, $3 );
`
_, err = db.Exec(statement, session, commenterHex, time.Now().UTC())
_, err = db.Exec(statement, commenterToken, commenterHex, time.Now().UTC())
if err != nil {
logger.Errorf("cannot insert session token: %v\n", err)
logger.Errorf("cannot insert commenterToken token: %v\n", err)
return "", errorInternal
}
return session, nil
return commenterToken, nil
}
func commenterLoginHandler(w http.ResponseWriter, r *http.Request) {
@ -61,11 +61,11 @@ func commenterLoginHandler(w http.ResponseWriter, r *http.Request) {
return
}
session, err := commenterLogin(*x.Email, *x.Password)
commenterToken, err := commenterLogin(*x.Email, *x.Password)
if err != nil {
writeBody(w, response{"success": false, "message": err.Error()})
return
}
writeBody(w, response{"success": true, "session": session})
writeBody(w, response{"success": true, "commenterToken": commenterToken})
}

View File

@ -24,8 +24,8 @@ func TestCommenterLoginBasics(t *testing.T) {
return
}
if session, err := commenterLogin("test@example.com", "hunter2"); session == "" {
t.Errorf("empty session on successful login: %v", err)
if commenterToken, err := commenterLogin("test@example.com", "hunter2"); commenterToken == "" {
t.Errorf("empty comenterToken on successful login: %v", err)
return
}
}

View File

@ -6,7 +6,7 @@ import (
func commenterSelfHandler(w http.ResponseWriter, r *http.Request) {
type request struct {
Session *string `json:"session"`
CommenterToken *string `json:"commenterToken"`
}
var x request
@ -15,7 +15,7 @@ func commenterSelfHandler(w http.ResponseWriter, r *http.Request) {
return
}
c, err := commenterGetBySession(*x.Session)
c, err := commenterGetByCommenterToken(*x.CommenterToken)
if err != nil {
writeBody(w, response{"success": false, "message": err.Error()})
return

View File

@ -4,8 +4,11 @@ import (
"time"
)
// A session is a 3-field entry of a token, a hex, and a creation date. Do
// not confuse session and token; the token is just an identifying string,
// while the session contains more information.
type commenterSession struct {
Session string `json:"session"`
CommenterToken string `json:"commenterToken"`
CommenterHex string `json:"commenterHex"`
CreationDate time.Time `json:"creationDate"`
}

View File

@ -1,25 +0,0 @@
package main
import ()
func commenterSessionGet(session string) (commenterSession, error) {
if session == "" {
return commenterSession{}, errorMissingField
}
statement := `
SELECT commenterHex, creationDate
FROM commenterSessions
WHERE session=$1;
`
row := db.QueryRow(statement, session)
cs := commenterSession{}
if err := row.Scan(&cs.CommenterHex, &cs.CreationDate); err != nil {
return commenterSession{}, errorNoSuchSession
}
cs.Session = session
return cs, nil
}

View File

@ -1,46 +0,0 @@
package main
import (
"testing"
)
func TestCommenterSessionGetBasics(t *testing.T) {
failTestOnError(t, setupTestEnv())
commenterHex, _ := commenterNew("test@example.com", "Test", "undefined", "https://example.com/photo.jpg", "google", "")
session, _ := commenterSessionNew()
commenterSessionUpdate(session, commenterHex)
cs, err := commenterSessionGet(session)
if err != nil {
t.Errorf("unexpected error found when getting session information: %v", err)
return
}
if cs.CommenterHex != commenterHex {
t.Errorf("expected commenterHex=%s got commenterHex=%s", commenterHex, cs.CommenterHex)
return
}
}
func TestCommenterSessionGetDNE(t *testing.T) {
failTestOnError(t, setupTestEnv())
_, err := commenterSessionGet("does-not-exist")
if err == nil {
t.Errorf("expected error not found when invalid session")
return
}
}
func TestCommenterSessionGetEmpty(t *testing.T) {
failTestOnError(t, setupTestEnv())
_, err := commenterSessionGet("")
if err == nil {
t.Errorf("expected error not found with empty session")
return
}
}

View File

@ -5,33 +5,33 @@ import (
"time"
)
func commenterSessionNew() (string, error) {
session, err := randomHex(32)
func commenterTokenNew() (string, error) {
commenterToken, err := randomHex(32)
if err != nil {
logger.Errorf("cannot create session hex: %v", err)
logger.Errorf("cannot create commenterToken: %v", err)
return "", errorInternal
}
statement := `
INSERT INTO
commenterSessions (session, creationDate)
VALUES ($1, $2 );
commenterSessions (commenterToken, creationDate)
VALUES ($1, $2 );
`
_, err = db.Exec(statement, session, time.Now().UTC())
_, err = db.Exec(statement, commenterToken, time.Now().UTC())
if err != nil {
logger.Errorf("cannot insert new session: %v", err)
logger.Errorf("cannot insert new commenterToken: %v", err)
return "", errorInternal
}
return session, nil
return commenterToken, nil
}
func commenterSessionNewHandler(w http.ResponseWriter, r *http.Request) {
session, err := commenterSessionNew()
func commenterTokenNewHandler(w http.ResponseWriter, r *http.Request) {
commenterToken, err := commenterTokenNew()
if err != nil {
writeBody(w, response{"success": false, "message": err.Error()})
return
}
writeBody(w, response{"success": true, "session": session})
writeBody(w, response{"success": true, "commenterToken": commenterToken})
}

View File

@ -4,11 +4,11 @@ import (
"testing"
)
func TestCommenterSessionNewBasics(t *testing.T) {
func TestCommenterTokenNewBasics(t *testing.T) {
failTestOnError(t, setupTestEnv())
if _, err := commenterSessionNew(); err != nil {
t.Errorf("unexpected error creating new session: %v", err)
if _, err := commenterTokenNew(); err != nil {
t.Errorf("unexpected error creating new commenterToken: %v", err)
return
}
}

View File

@ -2,19 +2,19 @@ package main
import ()
func commenterSessionUpdate(session string, commenterHex string) error {
if session == "" || commenterHex == "" {
func commenterSessionUpdate(commenterToken string, commenterHex string) error {
if commenterToken == "" || commenterHex == "" {
return errorMissingField
}
statement := `
UPDATE commenterSessions
SET commenterHex=$2
WHERE session=$1;
SET commenterHex = $2
WHERE commenterToken = $1;
`
_, err := db.Exec(statement, session, commenterHex)
_, err := db.Exec(statement, commenterToken, commenterHex)
if err != nil {
logger.Errorf("error updating commenterHex in commenterSessions: %v", err)
logger.Errorf("error updating commenterHex: %v", err)
return errorInternal
}

View File

@ -7,10 +7,10 @@ import (
func TestCommenterSessionUpdateBasics(t *testing.T) {
failTestOnError(t, setupTestEnv())
session, _ := commenterSessionNew()
commenterToken, _ := commenterTokenNew()
if err := commenterSessionUpdate(session, "temp-commenter-hex"); err != nil {
t.Errorf("unexpected error updating session to commenterHex: %v", err)
if err := commenterSessionUpdate(commenterToken, "temp-commenter-hex"); err != nil {
t.Errorf("unexpected error updating commenter session: %v", err)
return
}
}
@ -19,7 +19,7 @@ func TestCommenterSessionUpdateEmpty(t *testing.T) {
failTestOnError(t, setupTestEnv())
if err := commenterSessionUpdate("", "temp-commenter-hex"); err == nil {
t.Errorf("expected error not found when updating with empty session")
t.Errorf("expected error not found when updating with empty commenterToken")
return
}
}

View File

@ -40,6 +40,8 @@ func performMigrationsFromDir(dir string) error {
filenames[filename] = true
}
logger.Infof("%d migrations already installed, looking for more", len(filenames))
completed := 0
for _, file := range files {
if strings.HasSuffix(file.Name(), ".sql") {
@ -73,7 +75,9 @@ func performMigrationsFromDir(dir string) error {
}
if completed > 0 {
logger.Infof("%d migrations found, %d new migrations completed (%d total)", len(filenames), completed, len(filenames)+completed)
logger.Infof("%d new migrations completed (%d total)", completed, len(filenames)+completed)
} else {
logger.Infof("none found")
}
return nil

View File

@ -65,7 +65,7 @@ func domainDelete(domain string) error {
func domainDeleteHandler(w http.ResponseWriter, r *http.Request) {
type request struct {
Session *string `json:"session"`
OwnerToken *string `json:"ownerToken"`
Domain *string `json:"domain"`
}
@ -75,7 +75,7 @@ func domainDeleteHandler(w http.ResponseWriter, r *http.Request) {
return
}
o, err := ownerGetBySession(*x.Session)
o, err := ownerGetByOwnerToken(*x.OwnerToken)
if err != nil {
writeBody(w, response{"success": false, "message": err.Error()})
return

View File

@ -168,7 +168,7 @@ func domainImportDisqus(domain string, url string) (int, error) {
func domainImportDisqusHandler(w http.ResponseWriter, r *http.Request) {
type request struct {
Session *string `json:"session"`
OwnerToken *string `json:"ownerToken"`
Domain *string `json:"domain"`
URL *string `json:"url"`
}
@ -179,7 +179,7 @@ func domainImportDisqusHandler(w http.ResponseWriter, r *http.Request) {
return
}
o, err := ownerGetBySession(*x.Session)
o, err := ownerGetByOwnerToken(*x.OwnerToken)
if err != nil {
writeBody(w, response{"success": false, "message": err.Error()})
return

View File

@ -42,7 +42,7 @@ func domainList(ownerHex string) ([]domain, error) {
func domainListHandler(w http.ResponseWriter, r *http.Request) {
type request struct {
Session *string `json:"session"`
OwnerToken *string `json:"ownerToken"`
}
var x request
@ -51,7 +51,7 @@ func domainListHandler(w http.ResponseWriter, r *http.Request) {
return
}
o, err := ownerGetBySession(*x.Session)
o, err := ownerGetByOwnerToken(*x.OwnerToken)
if err != nil {
writeBody(w, response{"success": false, "message": err.Error()})
return

View File

@ -24,7 +24,7 @@ func domainModeratorDelete(domain string, email string) error {
func domainModeratorDeleteHandler(w http.ResponseWriter, r *http.Request) {
type request struct {
Session *string `json:"session"`
OwnerToken *string `json:"ownerToken"`
Domain *string `json:"domain"`
Email *string `json:"email"`
}
@ -35,7 +35,7 @@ func domainModeratorDeleteHandler(w http.ResponseWriter, r *http.Request) {
return
}
o, err := ownerGetBySession(*x.Session)
o, err := ownerGetByOwnerToken(*x.OwnerToken)
if err != nil {
writeBody(w, response{"success": false, "message": err.Error()})
return

View File

@ -26,7 +26,7 @@ func domainModeratorNew(domain string, email string) error {
func domainModeratorNewHandler(w http.ResponseWriter, r *http.Request) {
type request struct {
Session *string `json:"session"`
OwnerToken *string `json:"ownerToken"`
Domain *string `json:"domain"`
Email *string `json:"email"`
}
@ -37,7 +37,7 @@ func domainModeratorNewHandler(w http.ResponseWriter, r *http.Request) {
return
}
o, err := ownerGetBySession(*x.Session)
o, err := ownerGetByOwnerToken(*x.OwnerToken)
if err != nil {
writeBody(w, response{"success": false, "message": err.Error()})
return

View File

@ -26,7 +26,7 @@ func domainNew(ownerHex string, name string, domain string) error {
func domainNewHandler(w http.ResponseWriter, r *http.Request) {
type request struct {
Session *string `json:"session"`
OwnerToken *string `json:"ownerToken"`
Name *string `json:"name"`
Domain *string `json:"domain"`
}
@ -37,7 +37,7 @@ func domainNewHandler(w http.ResponseWriter, r *http.Request) {
return
}
o, err := ownerGetBySession(*x.Session)
o, err := ownerGetByOwnerToken(*x.OwnerToken)
if err != nil {
writeBody(w, response{"success": false, "message": err.Error()})
return

View File

@ -39,7 +39,7 @@ func domainStatistics(domain string) ([]int64, error) {
func domainStatisticsHandler(w http.ResponseWriter, r *http.Request) {
type request struct {
Session *string `json:"session"`
OwnerToken *string `json:"ownerToken"`
Domain *string `json:"domain"`
}
@ -49,7 +49,7 @@ func domainStatisticsHandler(w http.ResponseWriter, r *http.Request) {
return
}
o, err := ownerGetBySession(*x.Session)
o, err := ownerGetByOwnerToken(*x.OwnerToken)
if err != nil {
writeBody(w, response{"success": false, "message": err.Error()})
return

View File

@ -22,7 +22,7 @@ func domainUpdate(d domain) error {
func domainUpdateHandler(w http.ResponseWriter, r *http.Request) {
type request struct {
Session *string `json:"session"`
OwnerToken *string `json:"ownerToken"`
D *domain `json:"domain"`
}
@ -32,7 +32,7 @@ func domainUpdateHandler(w http.ResponseWriter, r *http.Request) {
return
}
o, err := ownerGetBySession(*x.Session)
o, err := ownerGetByOwnerToken(*x.OwnerToken)
if err != nil {
writeBody(w, response{"success": false, "message": err.Error()})
return

View File

@ -17,7 +17,7 @@ var errorNoSuchConfirmationToken = errors.New("This email confirmation link has
var errorNoSuchResetToken = errors.New("This password reset link has expired.")
var errorNotAuthorised = errors.New("You're not authorised to access that.")
var errorEmailAlreadyExists = errors.New("That email address has already been registered.")
var errorNoSuchSession = errors.New("No such session/state.")
var errorNoSuchToken = errors.New("No such session token.")
var errorNoSuchCommenter = errors.New("No such commenter.")
var errorAlreadyUpvoted = errors.New("You have already upvoted that comment.")
var errorNoSuchDomain = errors.New("This domain is not registered with Commento.")
@ -32,8 +32,6 @@ var errorForbiddenEdit = errors.New("You cannot edit someone else's comment.")
var errorMissingSmtpAddress = errors.New("Missing SMTP_FROM_ADDRESS")
var errorSmtpNotConfigured = errors.New("SMTP is not configured.")
var errorOauthMisconfigured = errors.New("OAuth is misconfigured.")
var errorUnassociatedSession = errors.New("No user associated with that session.")
var errorSessionAlreadyInUse = errors.New("Session is already in use.")
var errorCannotReadResponse = errors.New("Cannot read response.")
var errorNotModerator = errors.New("You need to be a moderator to do that.")
var errorNotADirectory = errors.New("The given path is not a directory.")

View File

@ -9,11 +9,11 @@ import (
)
func googleCallbackHandler(w http.ResponseWriter, r *http.Request) {
session := r.FormValue("state")
commenterToken := r.FormValue("state")
code := r.FormValue("code")
_, err := commenterSessionGet(session)
if err != nil && err != errorNoSuchSession {
_, err := commenterGetByCommenterToken(commenterToken)
if err != nil && err != errorNoSuchToken {
fmt.Fprintf(w, "Error: %s\n", err.Error())
return
}
@ -73,7 +73,7 @@ func googleCallbackHandler(w http.ResponseWriter, r *http.Request) {
commenterHex = c.CommenterHex
}
if err := commenterSessionUpdate(session, commenterHex); err != nil {
if err := commenterSessionUpdate(commenterToken, commenterHex); err != nil {
fmt.Fprintf(w, "Error: %s", err.Error())
return
}

View File

@ -12,14 +12,14 @@ func googleRedirectHandler(w http.ResponseWriter, r *http.Request) {
return
}
session := r.FormValue("session")
commenterToken := r.FormValue("commenterToken")
_, err := commenterGetBySession(session)
if err != nil && err != errorNoSuchSession {
_, err := commenterGetByCommenterToken(commenterToken)
if err != nil && err != errorNoSuchToken {
fmt.Fprintf(w, "error: %s\n", err.Error())
return
}
url := googleConfig.AuthCodeURL(session)
url := googleConfig.AuthCodeURL(commenterToken)
http.Redirect(w, r, url, http.StatusFound)
}

View File

@ -23,8 +23,8 @@ func ownerGetByEmail(email string) (owner, error) {
return o, nil
}
func ownerGetBySession(session string) (owner, error) {
if session == "" {
func ownerGetByOwnerToken(ownerToken string) (owner, error) {
if ownerToken == "" {
return owner{}, errorMissingField
}
@ -33,10 +33,10 @@ func ownerGetBySession(session string) (owner, error) {
FROM owners
WHERE email IN (
SELECT email FROM ownerSessions
WHERE session=$1
WHERE ownerToken = $1
);
`
row := db.QueryRow(statement, session)
row := db.QueryRow(statement, ownerToken)
var o owner
if err := row.Scan(&o.OwnerHex, &o.Email, &o.Name, &o.ConfirmedEmail, &o.JoinDate); err != nil {

View File

@ -30,16 +30,16 @@ func TestOwnerGetByEmailDNE(t *testing.T) {
}
}
func TestOwnerGetBySessionBasics(t *testing.T) {
func TestOwnerGetByOwnerTokenBasics(t *testing.T) {
failTestOnError(t, setupTestEnv())
ownerHex, _ := ownerNew("test@example.com", "Test", "hunter2")
session, _ := ownerLogin("test@example.com", "hunter2")
ownerToken, _ := ownerLogin("test@example.com", "hunter2")
o, err := ownerGetBySession(session)
o, err := ownerGetByOwnerToken(ownerToken)
if err != nil {
t.Errorf("unexpected error on ownerGetBySession: %v", err)
t.Errorf("unexpected error on ownerGetByOwnerToken: %v", err)
return
}
@ -49,11 +49,11 @@ func TestOwnerGetBySessionBasics(t *testing.T) {
}
}
func TestOwnerGetBySessionDNE(t *testing.T) {
func TestOwnerGetByOwnerTokenDNE(t *testing.T) {
failTestOnError(t, setupTestEnv())
if _, err := ownerGetBySession("does-not-exist"); err == nil {
t.Errorf("expected error not found on ownerGetBySession before creating an account")
if _, err := ownerGetByOwnerToken("does-not-exist"); err == nil {
t.Errorf("expected error not found on ownerGetByOwnerToken before creating an account")
return
}
}

View File

@ -34,24 +34,24 @@ func ownerLogin(email string, password string) (string, error) {
return "", errorInvalidEmailPassword
}
session, err := randomHex(32)
ownerToken, err := randomHex(32)
if err != nil {
logger.Errorf("cannot create session hex: %v", err)
logger.Errorf("cannot create ownerToken: %v", err)
return "", errorInternal
}
statement = `
INSERT INTO
ownerSessions (session, ownerHex, loginDate)
VALUES ($1, $2, $3 );
ownerSessions (ownerToken, ownerHex, loginDate)
VALUES ($1, $2, $3 );
`
_, err = db.Exec(statement, session, ownerHex, time.Now().UTC())
_, err = db.Exec(statement, ownerToken, ownerHex, time.Now().UTC())
if err != nil {
logger.Errorf("cannot insert session token: %v\n", err)
logger.Errorf("cannot insert ownerSession: %v\n", err)
return "", errorInternal
}
return session, nil
return ownerToken, nil
}
func ownerLoginHandler(w http.ResponseWriter, r *http.Request) {
@ -66,11 +66,11 @@ func ownerLoginHandler(w http.ResponseWriter, r *http.Request) {
return
}
session, err := ownerLogin(*x.Email, *x.Password)
ownerToken, err := ownerLogin(*x.Email, *x.Password)
if err != nil {
writeBody(w, response{"success": false, "message": err.Error()})
return
}
writeBody(w, response{"success": true, "session": session})
writeBody(w, response{"success": true, "ownerToken": ownerToken})
}

View File

@ -24,8 +24,8 @@ func TestOwnerLoginBasics(t *testing.T) {
return
}
if session, err := ownerLogin("test@example.com", "hunter2"); session == "" {
t.Errorf("empty session on successful login: %v", err)
if ownerToken, err := ownerLogin("test@example.com", "hunter2"); ownerToken == "" {
t.Errorf("empty token on successful login: %v", err)
return
}
}

View File

@ -4,18 +4,9 @@ import (
"net/http"
)
func ownerSelf(session string) (bool, owner) {
o, err := ownerGetBySession(session)
if err != nil {
return false, owner{}
}
return true, o
}
func ownerSelfHandler(w http.ResponseWriter, r *http.Request) {
type request struct {
Session *string `json:"session"`
OwnerToken *string `json:"ownerToken"`
}
var x request
@ -24,7 +15,16 @@ func ownerSelfHandler(w http.ResponseWriter, r *http.Request) {
return
}
loggedIn, o := ownerSelf(*x.Session)
o, err := ownerGetByOwnerToken(*x.OwnerToken)
if err == errorNoSuchToken {
writeBody(w, response{"success": true, "loggedIn": false})
return
}
writeBody(w, response{"success": true, "loggedIn": loggedIn, "owner": o})
if err != nil {
writeBody(w, response{"success": false, "message": err.Error()})
return
}
writeBody(w, response{"success": true, "loggedIn": true, "owner": o})
}

View File

@ -1,32 +0,0 @@
package main
import (
"testing"
)
func TestOwnerSelfBasics(t *testing.T) {
failTestOnError(t, setupTestEnv())
ownerNew("test@example.com", "Test", "hunter2")
session, _ := ownerLogin("test@example.com", "hunter2")
loggedIn, o := ownerSelf(session)
if !loggedIn {
t.Errorf("expected loggedIn=true got loggedIn=false")
return
}
if o.Name != "Test" {
t.Errorf("expected name=Test got name=%s", o.Name)
return
}
}
func TestOwnerSelfNotLoggedIn(t *testing.T) {
failTestOnError(t, setupTestEnv())
if loggedIn, _ := ownerSelf("does-not-exist"); loggedIn {
t.Errorf("expected loggedIn=false got loggedIn=true")
return
}
}

View File

@ -21,7 +21,7 @@ func initAPIRouter(router *mux.Router) error {
router.HandleFunc("/api/domain/statistics", domainStatisticsHandler).Methods("POST")
router.HandleFunc("/api/domain/import/disqus", domainImportDisqusHandler).Methods("POST")
router.HandleFunc("/api/commenter/session/new", commenterSessionNewHandler).Methods("GET")
router.HandleFunc("/api/commenter/token/new", commenterTokenNewHandler).Methods("GET")
router.HandleFunc("/api/commenter/new", commenterNewHandler).Methods("POST")
router.HandleFunc("/api/commenter/login", commenterLoginHandler).Methods("POST")
router.HandleFunc("/api/commenter/self", commenterSelfHandler).Methods("POST")

View File

@ -0,0 +1,5 @@
ALTER TABLE ownerSessions
RENAME COLUMN session TO ownerToken;
ALTER TABLE commenterSessions
RENAME COLUMN session TO commenterToken

View File

@ -192,36 +192,36 @@
}
function sessionGet() {
var session = cookieGet("session");
if (session === undefined)
function commenterTokenGet() {
var commenterToken = cookieGet("commenterToken");
if (commenterToken === undefined)
return "anonymous";
return session;
return commenterToken;
}
global.logout = function() {
cookieSet("session", "anonymous");
cookieSet("commenterToken", "anonymous");
refreshAll();
}
function selfGet(callback) {
var session = sessionGet();
if (session == "anonymous") {
var commenterToken = commenterTokenGet();
if (commenterToken == "anonymous") {
isAuthenticated = false;
call(callback);
return;
}
var json = {
session: sessionGet(),
"commenterToken": commenterTokenGet(),
};
post(origin + "/api/commenter/self", json, function(resp) {
if (!resp.success) {
cookieSet("session", "anonymous");
cookieSet("commenterToken", "anonymous");
call(callback);
return;
}
@ -344,9 +344,9 @@
function commentsGet(callback) {
var json = {
session: sessionGet(),
domain: location.host,
path: location.pathname,
"commenterToken": commenterTokenGet(),
"domain": location.host,
"path": location.pathname,
};
post(origin + "/api/comment/list", json, function(resp) {
@ -487,7 +487,7 @@
}
var json = {
"session": sessionGet(),
"commenterToken": commenterTokenGet(),
"domain": location.host,
"path": location.pathname,
"parentHex": id,
@ -773,7 +773,7 @@
global.commentApprove = function(commentHex) {
var json = {
"session": sessionGet(),
"commenterToken": commenterTokenGet(),
"commentHex": commentHex,
}
@ -796,7 +796,7 @@
global.commentDelete = function(commentHex) {
var json = {
"session": sessionGet(),
"commenterToken": commenterTokenGet(),
"commentHex": commentHex,
}
@ -826,7 +826,7 @@
var score = $(ID_SCORE + commentHex);
var json = {
"session": sessionGet(),
"commenterToken": commenterTokenGet(),
"commentHex": commentHex,
"direction": direction,
};
@ -970,7 +970,7 @@
global.commentoAuth = function(provider) {
if (provider == "anonymous") {
cookieSet("session", "anonymous");
cookieSet("commenterToken", "anonymous");
chosenAnonymous = true;
refreshAll();
return;
@ -978,15 +978,15 @@
var popup = window.open("", "_blank");
get(origin + "/api/commenter/session/new", function(resp) {
get(origin + "/api/commenter/token/new", function(resp) {
if (!resp.success) {
errorShow(resp.message);
return;
}
cookieSet("session", resp.session);
cookieSet("commenterToken", resp.commenterToken);
popup.location = origin + "/api/oauth/" + provider + "/redirect?session=" + resp.session;
popup.location = origin + "/api/oauth/" + provider + "/redirect?commenterToken=" + resp.commenterToken;
var interval = setInterval(function() {
if (popup.closed) {
@ -1144,8 +1144,8 @@
function loginUP(username, password) {
var json = {
email: username,
password: password,
"email": username,
"password": password,
};
post(origin + "/api/commenter/login", json, function(resp) {
@ -1155,7 +1155,7 @@
return
}
cookieSet("session", resp.session);
cookieSet("commenterToken", resp.commenterToken);
refreshAll();
});
}
@ -1176,10 +1176,10 @@
var password = $(ID_LOGIN_BOX_PASSWORD_INPUT);
var json = {
email: email.value,
name: name.value,
website: website.value,
password: password.value,
"email": email.value,
"name": name.value,
"website": website.value,
"password": password.value,
};
post(origin + "/api/commenter/new", json, function(resp) {

View File

@ -36,9 +36,9 @@
// Creates a new domain.
global.domainNewHandler = function() {
var json = {
session: global.cookieGet("session"),
name: $("#new-domain-name").val(),
domain: $("#new-domain-domain").val(),
"ownerToken": global.cookieGet("ownerToken"),
"name": $("#new-domain-name").val(),
"domain": $("#new-domain-domain").val(),
}
global.buttonDisable("#add-site-button");
@ -66,7 +66,7 @@
// Refreshes the list of domains.
global.domainRefresh = function(callback) {
var json = {
session: global.cookieGet("session"),
ownerToken: global.cookieGet("ownerToken"),
};
global.post(global.commentoOrigin + "/api/domain/list", json, function(resp) {
@ -107,8 +107,8 @@
// Updates a domain with the backend.
global.domainUpdate = function(domain, callback) {
var json = {
session: global.cookieGet("session"),
domain: domain,
"ownerToken": global.cookieGet("ownerToken"),
"domain": domain,
};
global.post(global.commentoOrigin + "/api/domain/update", json, function(resp) {
@ -126,8 +126,8 @@
// Deletes a domain.
global.domainDelete = function(domain, callback) {
var json = {
session: global.cookieGet("session"),
domain: domain,
"ownerToken": global.cookieGet("ownerToken"),
"domain": domain,
};
global.post(global.commentoOrigin + "/api/domain/delete", json, function(resp) {

View File

@ -12,9 +12,9 @@
var data = global.dashboard.$data;
var json = {
session: global.cookieGet("session"),
domain: data.domains[data.cd].domain,
url: url,
"ownerToken": global.cookieGet("ownerToken"),
"domain": data.domains[data.cd].domain,
"url": url,
}
global.buttonDisable("#disqus-import-button");

View File

@ -13,9 +13,9 @@
var email = $("#new-mod").val();
var json = {
session: global.cookieGet("session"),
domain: data.domains[data.cd].domain,
email: email,
"ownerToken": global.cookieGet("ownerToken"),
"domain": data.domains[data.cd].domain,
"email": email,
}
var idx = -1;
@ -53,9 +53,9 @@
var data = global.dashboard.$data;
var json = {
session: global.cookieGet("session"),
domain: data.domains[data.cd].domain,
email: email,
"ownerToken": global.cookieGet("ownerToken"),
"domain": data.domains[data.cd].domain,
"email": email,
}
var idx = -1;

View File

@ -38,8 +38,8 @@
var data = global.dashboard.$data;
var json = {
session: global.cookieGet("session"),
domain: data.domains[data.cd].domain,
"ownerToken": global.cookieGet("ownerToken"),
"domain": data.domains[data.cd].domain,
}
$(".view").hide();

View File

@ -65,7 +65,7 @@
return;
}
global.cookieSet("session", resp.session);
global.cookieSet("ownerToken", resp.ownerToken);
document.location = "/dashboard";
});
};

View File

@ -1,7 +1,7 @@
(function (global, document) {
global.logout = function() {
global.cookieSet("session", "");
global.cookieSet("ownerToken", "");
document.location = "/login";
}

View File

@ -3,7 +3,7 @@
// Get self details.
global.selfGet = function(callback) {
var json = {
"session": global.cookieGet("session"),
"ownerToken": global.cookieGet("ownerToken"),
};
global.post(global.commentoOrigin + "/api/owner/self", json, function(resp) {