From d4971cda89308525603a595ca9e6f440f1e5b1e8 Mon Sep 17 00:00:00 2001 From: ston1th Date: Sun, 23 Sep 2018 23:56:12 +0200 Subject: [PATCH] single db with prefixes, dump/restore, blacklisting on user deletion --- go.mod | 2 +- go.sum | 4 +- pkg/cmd/cmd.go | 5 ++ pkg/core/types.go | 1 + pkg/db/blacklist.go | 36 ++++++++ pkg/db/db.go | 18 +--- pkg/db/helper.go | 8 ++ pkg/db/lockout.go | 11 +++ pkg/db/page.go | 39 ++++---- pkg/db/user.go | 64 ++++++++++--- pkg/log/log.go | 19 +++- pkg/server/context.go | 10 ++- pkg/server/handler.go | 10 ++- pkg/server/server.go | 4 +- pkg/store/boltstore.go | 74 ++++++++++++--- pkg/store/dump.go | 89 +------------------ pkg/store/store.go | 8 +- .../ston1th/jwt/v3/blacklist.go | 14 +-- vendor/git.giftfish.de/ston1th/jwt/v3/jwt.go | 9 +- vendor/modules.txt | 2 +- 20 files changed, 264 insertions(+), 163 deletions(-) create mode 100644 pkg/db/blacklist.go create mode 100644 pkg/db/lockout.go diff --git a/go.mod b/go.mod index 2aa66ea..43aa597 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,7 @@ module git.giftfish.de/ston1th/gowiki require ( git.giftfish.de/ston1th/godrop/v2 v2.0.1 - git.giftfish.de/ston1th/jwt/v3 v3.0.0 + git.giftfish.de/ston1th/jwt/v3 v3.1.0 github.com/RoaringBitmap/roaring v0.4.16 // indirect github.com/Smerity/govarint v0.0.0-20150407073650-7265e41f48f1 // indirect github.com/blevesearch/bleve v0.7.0 diff --git a/go.sum b/go.sum index a09fe86..ae9926a 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ git.giftfish.de/ston1th/godrop/v2 v2.0.1 h1:Ka7P1VcC11n4mDXhCA/qaM1Bi6IBhcGFk6J9OO6c2vs= git.giftfish.de/ston1th/godrop/v2 v2.0.1/go.mod h1:QPMNHbTi2clDHyq8Chie49wFG78LkwKnw5lkx/RBkKQ= -git.giftfish.de/ston1th/jwt/v3 v3.0.0 h1:zywHtrYmEpU+osig6ujvHdettLuuDC4K7HHaiGigD/k= -git.giftfish.de/ston1th/jwt/v3 v3.0.0/go.mod h1:jDALrW7OKeIaqYuMxs3GWyPRnQZmk/R+Lu9p/Em3Ziw= +git.giftfish.de/ston1th/jwt/v3 v3.1.0 h1:SaSpVyl98iqnsRIh9tA8/XJpU6nCYIGa4L85rLvQWC0= +git.giftfish.de/ston1th/jwt/v3 v3.1.0/go.mod h1:jDALrW7OKeIaqYuMxs3GWyPRnQZmk/R+Lu9p/Em3Ziw= github.com/RoaringBitmap/roaring v0.4.16 h1:NholfewybRLOwACgfqfzn/N5xa6keKNs4fP00t0cwLo= github.com/RoaringBitmap/roaring v0.4.16/go.mod h1:8khRDP4HmeXns4xIj9oGrKSz7XTQiJx2zgh7AcNke4w= github.com/Smerity/govarint v0.0.0-20150407073650-7265e41f48f1 h1:G/NOANWMQev0CftoyxQwtRakdyNNNMB3qxkt/tj1HGs= diff --git a/pkg/cmd/cmd.go b/pkg/cmd/cmd.go index c12a445..059839b 100644 --- a/pkg/cmd/cmd.go +++ b/pkg/cmd/cmd.go @@ -168,6 +168,11 @@ func serverFlags() []cli.Flag { Usage: "enable secure cookie", Destination: &conf.SecureCookie, }, + cli.BoolFlag{ + Name: "debug", + Usage: "enable debugging", + Destination: &log.DebugEnabled, + }, } } diff --git a/pkg/core/types.go b/pkg/core/types.go index 714e145..59ecfd4 100644 --- a/pkg/core/types.go +++ b/pkg/core/types.go @@ -25,6 +25,7 @@ func (p Pages) Less(i, j int) bool { return p[i].StoreTitle < p[j].StoreTitle } type User struct { Username string Password string + Created string Admin bool Locked int } diff --git a/pkg/db/blacklist.go b/pkg/db/blacklist.go new file mode 100644 index 0000000..e7160ae --- /dev/null +++ b/pkg/db/blacklist.go @@ -0,0 +1,36 @@ +package db + +import "git.giftfish.de/ston1th/jwt/v3" + +const blacklistPrefix = "blacklist/" + +func (db *DB) Add(sig string, exp int64) error { + return db.store.Set(blacklistPrefix+sig, exp) +} + +func (db *DB) Remove(sig string) error { + return db.store.Delete(blacklistPrefix + sig) +} + +func (db *DB) Check(sig string) (ok bool) { + if db.store.Get(blacklistPrefix+sig, nil) == nil { + return true + } + return false +} + +func (db *DB) Map() (list jwt.BlacklistMap, err error) { + list = make(jwt.BlacklistMap) + err = db.store.ForEach(func(k string, v []byte) error { + if trim, ok := hasTrimPrefix(k, blacklistPrefix); ok { + var exp int64 + err := db.store.Unmarshal(v, &exp) + if err != nil { + return err + } + list[trim] = exp + } + return nil + }) + return +} diff --git a/pkg/db/db.go b/pkg/db/db.go index 8137bed..937f07d 100644 --- a/pkg/db/db.go +++ b/pkg/db/db.go @@ -13,8 +13,7 @@ import ( const ( defUser = "admin" defPassword = "gowiki" - usersFile = "users.db" - pagesFile = "pages.db" + storeFile = "store.db" bcryptCost = 13 welcome = `# Welcome to GoWiki This is the [Index](/wiki/Index) page. @@ -28,8 +27,7 @@ func dbErr(i interface{}) error { } type DB struct { - pages store.Store - users store.Store + store store.Store cache *cache.Cache Index *index.Index } @@ -41,7 +39,7 @@ func New(datadir string) (db *DB, err error) { return } - db.users, err = store.NewBoltStore(usersFile, nil) + db.store, err = store.NewBoltStore(storeFile, nil) if err != nil { return } @@ -56,10 +54,6 @@ func New(datadir string) (db *DB, err error) { return } - db.pages, err = store.NewBoltStore(pagesFile, nil) - if err != nil { - return - } _, err = db.CreatePage(core.IndexPage, core.WikiSection, welcome, defUser, core.Public) if err != nil && err != store.ErrKeyNotFound { return @@ -68,11 +62,7 @@ func New(datadir string) (db *DB, err error) { } func (db *DB) Close() error { - err := db.pages.Close() - if err != nil { - return err - } - err = db.users.Close() + err := db.store.Close() if err != nil { return err } diff --git a/pkg/db/helper.go b/pkg/db/helper.go index 2ebe1b5..a8b87ab 100644 --- a/pkg/db/helper.go +++ b/pkg/db/helper.go @@ -19,6 +19,14 @@ var reservedUsers = []string{ "wiki", } +// Parts taken from strings.TrimPrefix +func hasTrimPrefix(s, prefix string) (string, bool) { + if len(s) >= len(prefix) && s[0:len(prefix)] == prefix { + return s[len(prefix):], true + } + return s, false +} + func reservedUser(username string) bool { for _, v := range reservedUsers { if username == v { diff --git a/pkg/db/lockout.go b/pkg/db/lockout.go new file mode 100644 index 0000000..249b7e8 --- /dev/null +++ b/pkg/db/lockout.go @@ -0,0 +1,11 @@ +package db + +const lockoutPrefix = "lockout/" + +func (db *DB) lockout(username, created string) error { + return db.store.Set(lockoutPrefix+username+created, nil) +} + +func (db *DB) LockedOut(username, created string) bool { + return db.store.Get(lockoutPrefix+username+created, nil) == nil +} diff --git a/pkg/db/page.go b/pkg/db/page.go index a985064..1ef130d 100644 --- a/pkg/db/page.go +++ b/pkg/db/page.go @@ -9,6 +9,8 @@ import ( "sort" ) +const pagePrefix = "page/" + var ( errPageNotFound = store.ErrKeyNotFound errPermissionDenied = dbErr("permission denied") @@ -18,13 +20,15 @@ var ( ) func (db *DB) GetAllPages(username string) (pages core.Pages) { - db.pages.ForEach(func(title string, _ []byte) error { - if title == core.IndexURI { - return nil - } - p, err := db.GetPage(title, username) - if err == nil { - pages = append(pages, *p) + db.store.ForEach(func(k string, _ []byte) error { + if trim, ok := hasTrimPrefix(k, pagePrefix); ok { + if trim == core.IndexURI { + return nil + } + p, err := db.GetPage(trim, username) + if err == nil { + pages = append(pages, *p) + } } return nil }) @@ -47,7 +51,7 @@ func (db *DB) GetPage(title, username string) (p *core.Page, err error) { func (db *DB) getPage(title, username string) (p *core.Page, err error) { p = new(core.Page) - err = db.pages.Get(title, p) + err = db.store.Get(pagePrefix+title, p) if err != nil { return } @@ -85,7 +89,7 @@ func (db *DB) CreatePage(title, section, markdown, username string, p core.Permi } search := render.Render(page) - err = db.pages.Set(st, page) + err = db.store.Set(pagePrefix+st, page) if err != nil { return } @@ -121,7 +125,7 @@ func (db *DB) UpdatePage(title, section, markdown, username string, p core.Permi page.Perm = p search := render.Render(page) - err = db.pages.Set(st, page) + err = db.store.Set(pagePrefix+st, page) if err != nil { return } @@ -134,6 +138,14 @@ func (db *DB) UpdatePage(title, section, markdown, username string, p core.Permi return } +func (db *DB) deletePage(st string) (err error) { + if err = db.store.Delete(pagePrefix + st); err != nil { + return + } + db.cache.Delete(st) + return db.Index.Delete(st) +} + func (db *DB) DeletePage(title, section, username string) (err error) { var page *core.Page if section == core.WikiSection && title == core.IndexPage { @@ -147,10 +159,5 @@ func (db *DB) DeletePage(title, section, username string) (err error) { if !core.WritePerm(username, section, page) { return errPermissionDenied } - - if err = db.pages.Delete(st); err != nil { - return - } - db.cache.Delete(st) - return db.Index.Delete(st) + return db.deletePage(st) } diff --git a/pkg/db/user.go b/pkg/db/user.go index 98522a0..97e0f4b 100644 --- a/pkg/db/user.go +++ b/pkg/db/user.go @@ -5,10 +5,16 @@ package db import ( "errors" "git.giftfish.de/ston1th/gowiki/pkg/core" + "git.giftfish.de/ston1th/gowiki/pkg/log" + "git.giftfish.de/ston1th/jwt/v3" "golang.org/x/crypto/bcrypt" "sort" + "strconv" + "strings" ) +const userPrefix = "user/" + var ( errUserNotFound = dbErr("user not found") errUserExists = dbErr("user already exist") @@ -16,10 +22,12 @@ var ( ) func (db *DB) DumpUsers() (users core.Users, err error) { - db.users.ForEach(func(username string, _ []byte) error { - u, err := db.GetUser(username) - if err == nil { - users = append(users, u) + db.store.ForEach(func(k string, _ []byte) error { + if trim, ok := hasTrimPrefix(k, userPrefix); ok { + u, err := db.GetUser(trim) + if err == nil { + users = append(users, u) + } } return nil }) @@ -42,12 +50,12 @@ func (db *DB) GetUserWithoutPassword(username string) (u core.User, err error) { } func (db *DB) GetUser(username string) (u core.User, err error) { - err = db.users.Get(username, &u) + err = db.store.Get(userPrefix+username, &u) return } func (db *DB) UserExists(username string) error { - return db.users.Get(username, nil) + return db.store.Get(userPrefix+username, nil) } // TODO @@ -85,9 +93,10 @@ func (db *DB) CreateUser(username, password string, admin bool) error { if err != nil { return err } - return db.users.Set(username, &core.User{ + return db.store.Set(userPrefix+username, &core.User{ Username: username, Password: string(hash), + Created: strconv.Itoa(int(jwt.Now())), Admin: admin, }) } @@ -103,7 +112,7 @@ func (db *DB) Login(username, password string) (u core.User, err error) { } if err = bcrypt.CompareHashAndPassword([]byte(u.Password), validatePassword(password)); err != nil { u.Locked++ - err = db.users.Set(username, u) + err = db.store.Set(userPrefix+username, u) if err != nil { return } @@ -112,7 +121,7 @@ func (db *DB) Login(username, password string) (u core.User, err error) { } if u.Locked > 0 { u.Locked = 0 - err = db.users.Set(username, u) + err = db.store.Set(userPrefix+username, u) if err != nil { return } @@ -128,7 +137,7 @@ func (db *DB) UnlockUser(username string) (err error) { } if u.Locked > 0 { u.Locked = 0 - err = db.users.Set(username, u) + err = db.store.Set(userPrefix+username, u) if err != nil { return } @@ -146,7 +155,7 @@ func (db *DB) UpdateUserPassword(username, password string) error { return err } u.Password = string(hash) - return db.users.Set(username, u) + return db.store.Set(userPrefix+username, u) } func (db *DB) AdminUpdateUser(username, password string, admin bool) error { @@ -165,13 +174,40 @@ func (db *DB) AdminUpdateUser(username, password string, admin bool) error { } u.Password = string(hash) } - return db.users.Set(username, u) + return db.store.Set(userPrefix+username, u) } -//TODO delete all user owned pages func (db *DB) DeleteUser(username string) error { if username == defUser { return errors.New("user '" + defUser + "' cannot be deleted") } - return db.users.Delete(username) + u, err := db.GetUser(username) + if err != nil { + return err + } + err = db.store.Delete(userPrefix + username) + if err != nil { + return err + } + err = db.lockout(username, u.Created) + if err != nil { + return err + } + username += "/" + var pages []string + db.store.ForEach(func(k string, _ []byte) error { + if trim, ok := hasTrimPrefix(k, pagePrefix); ok { + if strings.HasPrefix(trim, username) { + pages = append(pages, trim) + } + } + return nil + }) + for _, p := range pages { + err := db.deletePage(p) + if err != nil { + log.Debugf("DeleteUser %s, %s", username, err) + } + } + return nil } diff --git a/pkg/log/log.go b/pkg/log/log.go index 4640c78..0f6be5b 100644 --- a/pkg/log/log.go +++ b/pkg/log/log.go @@ -7,7 +7,12 @@ import ( "os" ) -var log *stdlog.Logger +const debug = "debug: " + +var ( + log *stdlog.Logger + DebugEnabled = false +) func NewLogger(file string) { if file == "" { @@ -33,3 +38,15 @@ func Printf(fmt string, v ...interface{}) { func Fatal(v ...interface{}) { log.Fatal(v...) } + +func Debug(v ...interface{}) { + if DebugEnabled { + log.Println(append([]interface{}{debug}, v...)) + } +} + +func Debugf(fmt string, v ...interface{}) { + if DebugEnabled { + log.Printf(debug+fmt, v...) + } +} diff --git a/pkg/server/context.go b/pkg/server/context.go index 7954df6..5e0be49 100644 --- a/pkg/server/context.go +++ b/pkg/server/context.go @@ -15,6 +15,7 @@ import ( const ( userClaim = "user" adminClaim = "admin" + createdClaim = "created" sharedClaim = "shared" sectionClaim = "section" titleClaim = "title" @@ -40,8 +41,13 @@ func newContext(w http.ResponseWriter, r *http.Request, s *HTTPServer) (ctx *Con if err = s.JWT.Verify(t); err != nil { log.Println("VerifyToken:", err) } else { - ctx.Token = *t - return + if !s.DB.LockedOut(t.Claims.GetString(userClaim), t.Claims.GetString(createdClaim)) { + ctx.Token = *t + return + } + if err = s.JWT.Invalidate(t); err != nil { + log.Println("Invalidate:", err) + } } } } diff --git a/pkg/server/handler.go b/pkg/server/handler.go index e122055..9fce088 100644 --- a/pkg/server/handler.go +++ b/pkg/server/handler.go @@ -100,7 +100,7 @@ func loginHandler(ctx *Context) { ctx.Error(err) return } - ctx.SetCookie(jwt.Claims{userClaim: u.Username, adminClaim: u.Admin}) + ctx.SetCookie(jwt.Claims{userClaim: u.Username, createdClaim: u.Created, adminClaim: u.Admin}) ctx.Redirect(core.IndexURI, 302) } } @@ -195,6 +195,13 @@ func pageHandler(ctx *Context) { return } user = t.Claims.GetString(sharedClaim) + if ctx.Srv.DB.LockedOut(user, t.Claims.GetString(createdClaim)) { + if err = ctx.Srv.JWT.Invalidate(t); err != nil { + log.Println("Invalidate:", err) + } + ctx.NotFound() + return + } section = t.Claims.GetString(sectionClaim) title = t.Claims.GetString(titleClaim) ctx.Data.Key = key @@ -259,6 +266,7 @@ func pageShareHandler(ctx *Context) { } t := jwt.NewToken(map[string]interface{}{ sharedClaim: user, + createdClaim: ctx.Token.Claims.GetString(createdClaim), sectionClaim: section, titleClaim: title, jwt.ExpClaim: jwt.NewExp(d), diff --git a/pkg/server/server.go b/pkg/server/server.go index 634a3ae..c64d1c8 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -56,11 +56,11 @@ func (s *HTTPServer) Start() (err error) { if s.Secret != "" { buf = bytes.NewBufferString(s.Secret) } - s.JWT, err = jwt.New(jwt.DefaultExpiry, jwt.NewMemBlacklist(), buf) + s.DB, err = db.New(s.DataDir) if err != nil { return } - s.DB, err = db.New(s.DataDir) + s.JWT, err = jwt.New(jwt.DefaultExpiry, s.DB, buf) if err != nil { return } diff --git a/pkg/store/boltstore.go b/pkg/store/boltstore.go index 2137e68..c7f6432 100644 --- a/pkg/store/boltstore.go +++ b/pkg/store/boltstore.go @@ -2,7 +2,11 @@ package store -import "github.com/boltdb/bolt" +import ( + "encoding/json" + "github.com/boltdb/bolt" + "io" +) const defaultBoltBucket = "default" @@ -15,15 +19,13 @@ func NewBoltStore(file string, m Marshaler) (bs *BoltStore, err error) { if m == nil { m = NewGOB() } - db, err := bolt.Open(file, 0666, nil) + db, err := bolt.Open(file, 0640, nil) if err != nil { return } - if err = db.Update(func(tx *bolt.Tx) error { - if _, err := tx.CreateBucketIfNotExists([]byte(defaultBoltBucket)); err != nil { - return err - } - return nil + if err = db.Update(func(tx *bolt.Tx) (err error) { + _, err = tx.CreateBucketIfNotExists([]byte(defaultBoltBucket)) + return }); err != nil { return } @@ -31,6 +33,53 @@ func NewBoltStore(file string, m Marshaler) (bs *BoltStore, err error) { return } +type dump struct { + k string `json:"k"` + v []byte `json:"v"` +} + +func (bs *BoltStore) Dump(w io.Writer) (err error) { + if w == nil { + return ErrWriterIsNil + } + var d []dump + err = bs.ForEach(func(k string, v []byte) error { + d = append(d, dump{k, v}) + return nil + }) + if err != nil { + return + } + return json.NewEncoder(w).Encode(d) +} + +func (bs *BoltStore) Restore(r io.Reader) (err error) { + if r == nil { + return ErrReaderIsNil + } + var d []dump + err = json.NewDecoder(r).Decode(&d) + if err != nil { + return + } + if err = bs.db.Update(func(tx *bolt.Tx) (err error) { + if err = tx.DeleteBucket([]byte(defaultBoltBucket)); err != nil { + return + } + _, err = tx.CreateBucket([]byte(defaultBoltBucket)) + return + }); err != nil { + return + } + return bs.db.Update(func(tx *bolt.Tx) (err error) { + b := tx.Bucket([]byte(defaultBoltBucket)) + for _, v := range d { + b.Put([]byte(v.k), v.v) + } + return nil + }) +} + func (bs *BoltStore) Get(key string, v interface{}) (err error) { err = bs.db.View(func(tx *bolt.Tx) error { b := tx.Bucket([]byte(defaultBoltBucket)).Get([]byte(key)) @@ -46,10 +95,13 @@ func (bs *BoltStore) Get(key string, v interface{}) (err error) { } func (bs *BoltStore) Set(key string, v interface{}) error { - return bs.db.Update(func(tx *bolt.Tx) error { - b, err := bs.Marshal(v) - if err != nil { - return err + return bs.db.Update(func(tx *bolt.Tx) (err error) { + var b []byte + if v != nil { + b, err = bs.Marshal(v) + if err != nil { + return + } } return tx.Bucket([]byte(defaultBoltBucket)).Put([]byte(key), b) }) diff --git a/pkg/store/dump.go b/pkg/store/dump.go index d4081d0..043e84c 100644 --- a/pkg/store/dump.go +++ b/pkg/store/dump.go @@ -2,12 +2,7 @@ package store -/*import ( - "encoding/json" - "fmt" - "io" - "os" -) +import "io" type Dumper interface { Dump(io.Writer) error @@ -16,85 +11,3 @@ type Dumper interface { type Restorer interface { Restore(io.Reader) error } - -type DBDump struct { - Pages []DumpPage `json:"pages"` - Snippets []Snippet `json:"snippets"` - Users []User `json:"users"` -} - -type DumpPage struct { - Title string `json:"title"` - LinkTitle string `json:"link_title"` - MD string `json:"md"` - Created string `json:"created"` - Updated string `json:"updated"` - Public bool `json:"public"` -} - -func verboseLog(prefix, title string, v bool) { - if v { - fmt.Fprintln(os.Stderr, prefix, title) - } -} - -func Dump(path string, v bool) (err error) { - bs, err := NewBoltStore() - if err != nil { - return - } - var dump DBDump - //TODO bs.GetAllPages - var pages []*core.Page - for _, p := range pages { - if err != nil { - return - } - verboseLog("dump:", p.Title, v) - dump.Pages = append(dump.Pages, DumpPage{ - Title: p.Title, - LinkTitle: p.LinkTitle, - MD: p.MD, - Created: p.Created, - Updated: p.Updated, - Public: p.Public, - }) - } - //TODO snippets - //verboseLog("dump:", "snippets", v) - verboseLog("dump:", "users", v) - dump.Users, err = bs.DumpUsers() - if err != nil { - return - } - return json.NewEncoder(os.Stdout).Encode(dump) -} - -func Restore(path string, v bool) (err error) { - i, err := NewIndex(path) - if err != nil { - return - } - defer i.Close() - bs, err := NewBoltStore() - if err != nil { - return - } - var dump DBDump - err = json.NewDecoder(os.Stdin).Decode(&dump) - if err != nil { - return - } - for _, art := range dump.Articles { - verboseLog("restore:", art.Title, v) - err = i.Restore(&art) - if err != nil { - return - } - } - //TODO snippets - //verboseLog("restore:", "snippets", v) - verboseLog("restore:", "users", v) - err = bs.RestoreUsers(dump.Users) - return -}*/ diff --git a/pkg/store/store.go b/pkg/store/store.go index fac86b7..66fdd0a 100644 --- a/pkg/store/store.go +++ b/pkg/store/store.go @@ -8,10 +8,16 @@ func storeErr(i interface{}) error { return fmt.Errorf("store: %s", i) } -var ErrKeyNotFound = storeErr("key not found") +var ( + ErrKeyNotFound = storeErr("key not found") + ErrWriterIsNil = storeErr("writer is nil") + ErrReaderIsNil = storeErr("reader is nil") +) type Store interface { Marshaler + Dumper + Restorer Get(string, interface{}) error Set(string, interface{}) error ForEach(func(string, []byte) error) error diff --git a/vendor/git.giftfish.de/ston1th/jwt/v3/blacklist.go b/vendor/git.giftfish.de/ston1th/jwt/v3/blacklist.go index 9ecf662..b60a928 100644 --- a/vendor/git.giftfish.de/ston1th/jwt/v3/blacklist.go +++ b/vendor/git.giftfish.de/ston1th/jwt/v3/blacklist.go @@ -6,10 +6,10 @@ import "sync" // Blacklist is the blacklisting storage interface type Blacklist interface { - Add(string, int64) - Remove(string) + Add(string, int64) error + Remove(string) error Check(string) bool - Map() BlacklistMap + Map() (BlacklistMap, error) } // BlacklistMap is the blacklist map structure @@ -28,17 +28,19 @@ func NewMemBlacklist() *MemBlacklist { } // Add adds a new token signature with expiration time to the blacklist -func (mb *MemBlacklist) Add(sig string, exp int64) { +func (mb *MemBlacklist) Add(sig string, exp int64) error { mb.Lock() mb.list[sig] = exp mb.Unlock() + return nil } // Remove deletes a token signature from the blacklist -func (mb *MemBlacklist) Remove(sig string) { +func (mb *MemBlacklist) Remove(sig string) error { mb.Lock() delete(mb.list, sig) mb.Unlock() + return nil } // Check returns true if a token signature is blacklisted and false otherwise @@ -50,7 +52,7 @@ func (mb *MemBlacklist) Check(sig string) (ok bool) { } // Map returns the blacklist in the form of a iterable map structure for cleanup -func (mb *MemBlacklist) Map() (list BlacklistMap) { +func (mb *MemBlacklist) Map() (list BlacklistMap, err error) { list = make(BlacklistMap) mb.RLock() for k, v := range mb.list { diff --git a/vendor/git.giftfish.de/ston1th/jwt/v3/jwt.go b/vendor/git.giftfish.de/ston1th/jwt/v3/jwt.go index 76217f4..d77c7dd 100644 --- a/vendor/git.giftfish.de/ston1th/jwt/v3/jwt.go +++ b/vendor/git.giftfish.de/ston1th/jwt/v3/jwt.go @@ -143,8 +143,7 @@ func (jwt *JWT) Invalidate(t *Token) error { if !hmac.Equal(jwt.sum(t.Data(), h), t.RawSig()) { return ErrInvalid } - jwt.blacklist.Add(t.Sig(), exp) - return nil + return jwt.blacklist.Add(t.Sig(), exp) } // blacklisted checks if a token is blacklisted @@ -169,7 +168,11 @@ func (jwt *JWT) clean() { return } now := Now() - for k, v := range jwt.blacklist.Map() { + m, err := jwt.blacklist.Map() + if err != nil { + continue + } + for k, v := range m { if now > v { jwt.blacklist.Remove(k) } diff --git a/vendor/modules.txt b/vendor/modules.txt index f0749e0..4b0da97 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,6 +1,6 @@ # git.giftfish.de/ston1th/godrop/v2 v2.0.1 git.giftfish.de/ston1th/godrop/v2 -# git.giftfish.de/ston1th/jwt/v3 v3.0.0 +# git.giftfish.de/ston1th/jwt/v3 v3.1.0 git.giftfish.de/ston1th/jwt/v3 # github.com/RoaringBitmap/roaring v0.4.16 github.com/RoaringBitmap/roaring