From 34e12860e4f8a70c35e6fb8b3df128c687117a25 Mon Sep 17 00:00:00 2001 From: Daniel Date: Tue, 13 Oct 2020 14:58:27 +0200 Subject: [PATCH] Fix another locking issue --- database/interface.go | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/database/interface.go b/database/interface.go index 04f1830..9c6b4a9 100644 --- a/database/interface.go +++ b/database/interface.go @@ -92,11 +92,28 @@ func (o *Options) Apply(r record.Record) { } } -// HasAllPermissions returns whether the options specify the highest possible permissions for operations. +// HasAllPermissions returns whether the options specify the highest possible +// permissions for operations. func (o *Options) HasAllPermissions() bool { return o.Local && o.Internal } +// hasAccessPermission checks if the interface options permit access to the +// given record, locking the record for accessing it's attributes. +func (o *Options) hasAccessPermission(r record.Record) bool { + // Check if the options specify all permissions, which makes checking the + // record unnecessary. + if o.HasAllPermissions() { + return true + } + + r.Lock() + defer r.Unlock() + + // Check permissions against record. + return r.Meta().CheckPermission(o.Local, o.Internal) +} + // NewInterface returns a new Interface to the database. func NewInterface(opts *Options) *Interface { if opts == nil { @@ -156,13 +173,8 @@ func (i *Interface) getRecord(dbName string, dbKey string, mustBeWriteable bool) r = i.checkCache(dbName + ":" + dbKey) if r != nil { - if !i.options.HasAllPermissions() { - r.Lock() - permitted := r.Meta().CheckPermission(i.options.Local, i.options.Internal) - r.Unlock() - if !permitted { - return nil, db, ErrPermissionDenied - } + if !i.options.hasAccessPermission(r) { + return nil, db, ErrPermissionDenied } return r, db, nil } @@ -172,7 +184,7 @@ func (i *Interface) getRecord(dbName string, dbKey string, mustBeWriteable bool) return nil, db, err } - if !r.Meta().CheckPermission(i.options.Local, i.options.Internal) { + if !i.options.hasAccessPermission(r) { return nil, db, ErrPermissionDenied }