aboutsummaryrefslogtreecommitdiffstats
path: root/modern.go
diff options
context:
space:
mode:
Diffstat (limited to 'modern.go')
-rw-r--r--modern.go109
1 files changed, 77 insertions, 32 deletions
diff --git a/modern.go b/modern.go
index cbfbcd3..83feb5d 100644
--- a/modern.go
+++ b/modern.go
@@ -4,15 +4,17 @@ import (
"database/sql/driver"
"encoding/json"
"encoding/xml"
+ "errors"
"fmt"
"net/http"
"strings"
+ "time"
)
type Api interface {
- AuthGetToken(*http.Request) ApiResponse
- AuthGetSession(*http.Request) ApiResponse
- AuthGetMobileSession(*http.Request) ApiResponse
+ AuthGetToken(*http.Request) (ApiResponse, error)
+ AuthGetSession(*http.Request) (ApiResponse, error)
+ AuthGetMobileSession(*http.Request) (ApiResponse, error)
TrackScrobble(*http.Request) (ApiResponse, error)
}
@@ -27,17 +29,15 @@ func (s Scrobbles) MarshalJSON() ([]byte, error) {
}{Tag: SuspendScrobbles(s)})
}
-func (s *Session) MarshalJSON() ([]byte, error) {
- return json.Marshal(s)
-}
-
type Name struct {
XMLName xml.Name
}
type Token struct {
- XMLName xml.Name `xml:"token" json:"-"`
- Val string `xml:",innerxml" json:"token"`
+ XMLName xml.Name `xml:"token" json:"-"`
+ Val string `xml:",innerxml" json:"token"`
+ Created time.Time `xml:"-" json:"-"`
+ UserId int `xml:"-" json:"-"`
}
type LFMResponse struct {
@@ -80,34 +80,76 @@ func (n Name) getName() string {
return n.XMLName.Local
}
-func (store *SqlStore) AuthGetToken(r *http.Request) ApiResponse {
- token := Token{Val: randomToken(16)}
- return token
+func (store *SqlStore) AuthGetToken(r *http.Request) (ApiResponse, error) {
+ if token, err := store.NewToken(); err != nil {
+ return nil, err
+ } else {
+ return Token{Val: token}, nil
+ }
}
-func (store *SqlStore) AuthGetMobileSession(r *http.Request) ApiResponse {
- return struct{}{}
+func (store *SqlStore) AuthGetMobileSession(r *http.Request) (ApiResponse, error) {
+ return nil, nil
}
-func (store *SqlStore) AuthGetSession(r *http.Request) ApiResponse {
- var response struct {
- Session *Session `json:"session"`
+func (store *SqlStore) VerifySig(r *http.Request) error {
+ key := r.FormValue("api_key")
+ token := r.FormValue("token")
+ sig := r.FormValue("api_sig")
+ method := r.FormValue("method")
+ if c, err := store.GetClient(key); err != nil {
+ return errors.New("Invalid API key")
+ } else {
+ to_hash := fmt.Sprintf("api_key%smethod%stoken%s%s",
+ key, method, token, c.Secret)
+ if md5hex(to_hash) == sig {
+ return nil
+ } else {
+ return errors.New("Invalid method signature supplied")
+ }
}
- session := &Session{
- User: "thibauthorel",
- Client: r.FormValue("api_key"),
- Protocol: "2.0",
- Key: randomToken(16),
+}
+
+func (store *SqlStore) AuthGetSession(r *http.Request) (ApiResponse, error) {
+ if err := store.VerifySig(r); err == nil {
+ if token, err := store.GetToken(r.FormValue("token")); err != nil {
+ // FIXME: error 4
+ return nil, errors.New("Invalid authentication token supplied")
+ } else {
+ if time.Since(token.Created) > 5*time.Minute {
+ // FIXME: error 15
+ return nil, errors.New("This token has expired")
+ } else {
+ if token.UserId != 0 {
+ user := &User{Id: token.UserId}
+ if err := store.GetUser(user); err != nil {
+ return nil, err
+ } else {
+ session := &Session{
+ User: user.Name,
+ Key: randomToken(16),
+ Client: r.FormValue("api_key"),
+ UserId: user.Id,
+ Protocol: "2.0",
+ }
+ store.PutSession(session)
+ return session, nil
+ }
+ } else {
+ //FIXME: error 14
+ return nil, errors.New("This token has not been authorized")
+ }
+ }
+ }
+ } else {
+ return nil, err
}
- store.PutSession(session)
- response.Session = session
- return response
}
func (store *SqlStore) TrackScrobble(r *http.Request) (ApiResponse, error) {
if session, err := store.GetSession(r.FormValue("sk")); err != nil {
fmt.Printf("%v\n", err)
- return struct{}{}, err
+ return nil, err
} else {
scrobbles, ignored := parseScrobbles(r.Form, session)
store.PutScrobbles(scrobbles)
@@ -119,18 +161,21 @@ func (store *SqlStore) TrackScrobble(r *http.Request) (ApiResponse, error) {
func (app *App) ApiHandler(w http.ResponseWriter, r *http.Request) {
method := r.FormValue("method")
var response ApiResponse
+ var err error
switch strings.ToLower(method) {
case "auth.gettoken":
- response = app.AuthGetToken(r)
+ response, err = app.AuthGetToken(r)
+ if err != nil {
+ fmt.Printf("%v\n", err)
+ }
case "auth.getsession":
- response = app.AuthGetSession(r)
+ response, err = app.AuthGetSession(r)
case "auth.getmobilesession":
- response = app.AuthGetSession(r)
+ response, err = app.AuthGetMobileSession(r)
case "track.scrobble":
- if r, err := app.DataStore.TrackScrobble(r); err != nil {
+ response, err = app.TrackScrobble(r)
+ if err != nil {
fmt.Printf("%v\n", err)
- } else {
- response = r
}
}
var text []byte