update last_updated when calling the API with a token
This commit is contained in:
		@@ -74,6 +74,9 @@ func Start(conf common.Conf, dbO *sqlx.DB) *gin.Engine {
 | 
			
		||||
		DB:       conf.RedisDB,
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	// token updater
 | 
			
		||||
	go tokenUpdater(db)
 | 
			
		||||
 | 
			
		||||
	api := r.Group("/api")
 | 
			
		||||
	{
 | 
			
		||||
		p := api.Group("/")
 | 
			
		||||
 
 | 
			
		||||
@@ -4,20 +4,20 @@ import (
 | 
			
		||||
	"crypto/md5"
 | 
			
		||||
	"database/sql"
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/jmoiron/sqlx"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"git.zxq.co/ripple/rippleapi/common"
 | 
			
		||||
	"github.com/jmoiron/sqlx"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// GetTokenFull retrieves an user ID and their token privileges knowing their API token.
 | 
			
		||||
func GetTokenFull(token string, db *sqlx.DB) (common.Token, bool) {
 | 
			
		||||
	var t common.Token
 | 
			
		||||
	var (
 | 
			
		||||
		t             common.Token
 | 
			
		||||
		tokenPrivsRaw uint64
 | 
			
		||||
		userPrivsRaw  uint64
 | 
			
		||||
		priv8         bool
 | 
			
		||||
	)
 | 
			
		||||
	var priv8 bool
 | 
			
		||||
	err := db.QueryRow(`SELECT 
 | 
			
		||||
	t.id, t.user, t.privileges, t.private, u.privileges
 | 
			
		||||
FROM tokens t
 | 
			
		||||
@@ -27,6 +27,7 @@ WHERE token = ? LIMIT 1`,
 | 
			
		||||
		Scan(
 | 
			
		||||
			&t.ID, &t.UserID, &tokenPrivsRaw, &priv8, &userPrivsRaw,
 | 
			
		||||
		)
 | 
			
		||||
	updateTokens <- t.ID
 | 
			
		||||
	if priv8 {
 | 
			
		||||
		tokenPrivsRaw = common.PrivilegeReadConfidential | common.PrivilegeWrite
 | 
			
		||||
	}
 | 
			
		||||
@@ -42,3 +43,43 @@ WHERE token = ? LIMIT 1`,
 | 
			
		||||
		return t, true
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var updateTokens = make(chan int, 100)
 | 
			
		||||
 | 
			
		||||
func tokenUpdater(db *sqlx.DB) {
 | 
			
		||||
	for {
 | 
			
		||||
		// prepare a queue of tokens to update.
 | 
			
		||||
		tokensToUpdate := make([]int, 0, 50)
 | 
			
		||||
	AwaitLoop:
 | 
			
		||||
		for {
 | 
			
		||||
			// if we got ten, move on and update
 | 
			
		||||
			if len(tokensToUpdate) >= 50 {
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
			// if we ain't got any, add what we get straight from updateTokens
 | 
			
		||||
			if len(tokensToUpdate) == 0 {
 | 
			
		||||
				x := <-updateTokens
 | 
			
		||||
				tokensToUpdate = append(tokensToUpdate, x)
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// otherwise, wait from updateTokens with a timeout of 10 seconds
 | 
			
		||||
			select {
 | 
			
		||||
			case x := <-updateTokens:
 | 
			
		||||
				tokensToUpdate = append(tokensToUpdate, x)
 | 
			
		||||
			case <-time.After(10 * time.Second):
 | 
			
		||||
				// wondering what this means?
 | 
			
		||||
				// https://golang.org/ref/spec#Break_statements
 | 
			
		||||
				break AwaitLoop
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		q, a, _ := sqlx.In("UPDATE tokens SET last_updated = ? WHERE id IN (?)", time.Now().Unix(), tokensToUpdate)
 | 
			
		||||
 | 
			
		||||
		q = db.Rebind(q)
 | 
			
		||||
		_, err := db.Exec(q, a...)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			fmt.Println(err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@ import (
 | 
			
		||||
	"crypto/md5"
 | 
			
		||||
	"database/sql"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/jmoiron/sqlx"
 | 
			
		||||
 | 
			
		||||
@@ -121,7 +122,8 @@ func TokenNewPOST(md common.MethodData) common.CodeMessager {
 | 
			
		||||
			return Err500
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	_, err = md.DB.Exec("INSERT INTO tokens(user, privileges, description, token, private) VALUES (?, ?, ?, ?, '0')", r.ID, r.Privileges, data.Description, tokenMD5)
 | 
			
		||||
	_, err = md.DB.Exec("INSERT INTO tokens(user, privileges, description, token, private, last_updated) VALUES (?, ?, ?, ?, '0', ?)",
 | 
			
		||||
		r.ID, r.Privileges, data.Description, tokenMD5, time.Now().Unix())
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		md.Err(err)
 | 
			
		||||
		return Err500
 | 
			
		||||
@@ -146,9 +148,10 @@ func TokenSelfDeletePOST(md common.MethodData) common.CodeMessager {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type token struct {
 | 
			
		||||
	ID          int    `json:"id"`
 | 
			
		||||
	Privileges  uint64 `json:"privileges"`
 | 
			
		||||
	Description string `json:"description"`
 | 
			
		||||
	ID          int                  `json:"id"`
 | 
			
		||||
	Privileges  uint64               `json:"privileges"`
 | 
			
		||||
	Description string               `json:"description"`
 | 
			
		||||
	LastUpdated common.UnixTimestamp `json:"last_updated"`
 | 
			
		||||
}
 | 
			
		||||
type tokenResponse struct {
 | 
			
		||||
	common.ResponseBase
 | 
			
		||||
@@ -157,14 +160,14 @@ type tokenResponse struct {
 | 
			
		||||
 | 
			
		||||
// TokenGET retrieves a list listing all the user's public tokens.
 | 
			
		||||
func TokenGET(md common.MethodData) common.CodeMessager {
 | 
			
		||||
	rows, err := md.DB.Query("SELECT id, privileges, description FROM tokens WHERE user = ? AND private = '0'", md.ID())
 | 
			
		||||
	rows, err := md.DB.Query("SELECT id, privileges, description, last_updated FROM tokens WHERE user = ? AND private = '0'", md.ID())
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return Err500
 | 
			
		||||
	}
 | 
			
		||||
	var r tokenResponse
 | 
			
		||||
	for rows.Next() {
 | 
			
		||||
		var t token
 | 
			
		||||
		err = rows.Scan(&t.ID, &t.Privileges, &t.Description)
 | 
			
		||||
		err = rows.Scan(&t.ID, &t.Privileges, &t.Description, &t.LastUpdated)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			md.Err(err)
 | 
			
		||||
			continue
 | 
			
		||||
@@ -187,9 +190,9 @@ func TokenSelfGET(md common.MethodData) common.CodeMessager {
 | 
			
		||||
	}
 | 
			
		||||
	var r tokenSingleResponse
 | 
			
		||||
	// md.User.ID = token id, userid would have been md.User.UserID. what a clusterfuck
 | 
			
		||||
	err := md.DB.QueryRow("SELECT id, privileges, description FROM tokens WHERE id = ? "+
 | 
			
		||||
	err := md.DB.QueryRow("SELECT id, privileges, description, last_updated FROM tokens WHERE id = ? "+
 | 
			
		||||
		common.Paginate(md.Query("p"), md.Query("l"), 50), md.User.ID).Scan(
 | 
			
		||||
		&r.ID, &r.Privileges, &r.Description,
 | 
			
		||||
		&r.ID, &r.Privileges, &r.Description, &r.LastUpdated,
 | 
			
		||||
	)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		md.Err(err)
 | 
			
		||||
@@ -220,7 +223,7 @@ func fixPrivileges(user int, db *sqlx.DB) {
 | 
			
		||||
	}
 | 
			
		||||
	rows, err := db.Query(`
 | 
			
		||||
SELECT
 | 
			
		||||
	tokens.id, tokens.privileges, users.privileges
 | 
			
		||||
	tokens.id, tokens.privileges, users.privileges 
 | 
			
		||||
FROM tokens
 | 
			
		||||
LEFT JOIN users ON users.id = tokens.user
 | 
			
		||||
`+wc, params...)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user