Skip to content
This repository has been archived by the owner on Jan 27, 2021. It is now read-only.

Atomic requests to the accounts service #82

Merged
merged 5 commits into from
Aug 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions changelog/unreleased/atomic-requests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Bugfix: Atomic Requests

Operations on the file system level are now atomic. This happens only on the provisioning API.

https://github.com/owncloud/ocis-accounts/pull/82
21 changes: 11 additions & 10 deletions pkg/service/v0/accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import (
)

// accLock mutually exclude readers from writers on account files
var accLock sync.RWMutex
var accLock sync.Mutex

func (s Service) indexAccounts(path string) (err error) {
var f *os.File
Expand Down Expand Up @@ -80,9 +80,6 @@ var authQuery = regexp.MustCompile(`^login eq '(.*)' and password eq '(.*)'$`) /
func (s Service) loadAccount(id string, a *proto.Account) (err error) {
path := filepath.Join(s.Config.Server.AccountsDataPath, "accounts", id)

accLock.Lock()
defer accLock.Unlock()

var data []byte
if data, err = ioutil.ReadFile(path); err != nil {
return merrors.NotFound(s.id, "could not read account: %v", err.Error())
Expand All @@ -95,7 +92,6 @@ func (s Service) loadAccount(id string, a *proto.Account) (err error) {
}

func (s Service) writeAccount(a *proto.Account) (err error) {

// leave only the group id
s.deflateMemberOf(a)

Expand All @@ -106,8 +102,6 @@ func (s Service) writeAccount(a *proto.Account) (err error) {

path := filepath.Join(s.Config.Server.AccountsDataPath, "accounts", a.Id)

accLock.Lock()
defer accLock.Unlock()
if err = ioutil.WriteFile(path, bytes, 0600); err != nil {
return merrors.InternalServerError(s.id, "could not write account: %v", err.Error())
}
Expand Down Expand Up @@ -164,7 +158,8 @@ func (s Service) passwordIsValid(hash string, pwd string) (ok bool) {
// ListAccounts implements the AccountsServiceHandler interface
// the query contains account properties
func (s Service) ListAccounts(ctx context.Context, in *proto.ListAccountsRequest, out *proto.ListAccountsResponse) (err error) {

accLock.Lock()
defer accLock.Unlock()
var password string

// check if this looks like an auth request
Expand Down Expand Up @@ -253,6 +248,8 @@ func (s Service) ListAccounts(ctx context.Context, in *proto.ListAccountsRequest

// GetAccount implements the AccountsServiceHandler interface
func (s Service) GetAccount(c context.Context, in *proto.GetAccountRequest, out *proto.Account) (err error) {
accLock.Lock()
defer accLock.Unlock()
var id string
if id, err = cleanupID(in.Id); err != nil {
return merrors.InternalServerError(s.id, "could not clean up account id: %v", err.Error())
Expand All @@ -279,6 +276,8 @@ func (s Service) GetAccount(c context.Context, in *proto.GetAccountRequest, out

// CreateAccount implements the AccountsServiceHandler interface
func (s Service) CreateAccount(c context.Context, in *proto.CreateAccountRequest, out *proto.Account) (err error) {
accLock.Lock()
defer accLock.Unlock()
var id string
var acc = in.Account
if acc == nil {
Expand Down Expand Up @@ -347,6 +346,8 @@ func (s Service) CreateAccount(c context.Context, in *proto.CreateAccountRequest
// read only fields are ignored
// TODO how can we unset specific values? using the update mask
func (s Service) UpdateAccount(c context.Context, in *proto.UpdateAccountRequest, out *proto.Account) (err error) {
accLock.Lock()
defer accLock.Unlock()
var id string
if in.Account == nil {
return merrors.BadRequest(s.id, "account missing")
Expand All @@ -366,8 +367,6 @@ func (s Service) UpdateAccount(c context.Context, in *proto.UpdateAccountRequest
return
}

s.debugLogAccount(out).Msg("found account")

t := time.Now()
tsnow := &timestamppb.Timestamp{
Seconds: t.Unix(),
Expand Down Expand Up @@ -456,6 +455,8 @@ var updatableAccountPaths = map[string]struct{}{

// DeleteAccount implements the AccountsServiceHandler interface
func (s Service) DeleteAccount(c context.Context, in *proto.DeleteAccountRequest, out *empty.Empty) (err error) {
accLock.Lock()
defer accLock.Unlock()
var id string
if id, err = cleanupID(in.Id); err != nil {
return merrors.InternalServerError(s.id, "could not clean up account id: %v", err.Error())
Expand Down
2 changes: 1 addition & 1 deletion pkg/service/v0/groups.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func (s Service) indexGroups(path string) (err error) {
}

// accLock mutually exclude readers from writers on group files
var groupLock sync.RWMutex
var groupLock sync.Mutex

func (s Service) indexGroup(id string) error {
g := &proto.BleveGroup{
Expand Down