github.com/kaleido-io/firefly@v0.0.0-20210622132723-8b4b6aacb971/internal/database/sqlcommon/organization_sql.go (about)

     1  // Copyright © 2021 Kaleido, Inc.
     2  //
     3  // SPDX-License-Identifier: Apache-2.0
     4  //
     5  // Licensed under the Apache License, Version 2.0 (the "License");
     6  // you may not use this file except in compliance with the License.
     7  // You may obtain a copy of the License at
     8  //
     9  //     http://www.apache.org/licenses/LICENSE-2.0
    10  //
    11  // Unless required by applicable law or agreed to in writing, software
    12  // distributed under the License is distributed on an "AS IS" BASIS,
    13  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  // See the License for the specific language governing permissions and
    15  // limitations under the License.
    16  
    17  package sqlcommon
    18  
    19  import (
    20  	"context"
    21  	"database/sql"
    22  
    23  	sq "github.com/Masterminds/squirrel"
    24  	"github.com/kaleido-io/firefly/internal/i18n"
    25  	"github.com/kaleido-io/firefly/internal/log"
    26  	"github.com/kaleido-io/firefly/pkg/database"
    27  	"github.com/kaleido-io/firefly/pkg/fftypes"
    28  )
    29  
    30  var (
    31  	organizationColumns = []string{
    32  		"id",
    33  		"message_id",
    34  		"name",
    35  		"parent",
    36  		"identity",
    37  		"description",
    38  		"profile",
    39  		"created",
    40  	}
    41  	organizationFilterTypeMap = map[string]string{
    42  		"message": "message_id",
    43  	}
    44  )
    45  
    46  func (s *SQLCommon) UpsertOrganization(ctx context.Context, organization *fftypes.Organization, allowExisting bool) (err error) {
    47  	ctx, tx, autoCommit, err := s.beginOrUseTx(ctx)
    48  	if err != nil {
    49  		return err
    50  	}
    51  	defer s.rollbackTx(ctx, tx, autoCommit)
    52  
    53  	existing := false
    54  	if allowExisting {
    55  		// Do a select within the transaction to detemine if the UUID already exists
    56  		organizationRows, err := s.queryTx(ctx, tx,
    57  			sq.Select("id").
    58  				From("orgs").
    59  				Where(sq.Eq{"identity": organization.Identity}),
    60  		)
    61  		if err != nil {
    62  			return err
    63  		}
    64  		existing = organizationRows.Next()
    65  
    66  		if existing {
    67  			var id fftypes.UUID
    68  			_ = organizationRows.Scan(&id)
    69  			if organization.ID != nil {
    70  				if *organization.ID != id {
    71  					organizationRows.Close()
    72  					return database.IDMismatch
    73  				}
    74  			}
    75  			organization.ID = &id // Update on returned object
    76  		}
    77  		organizationRows.Close()
    78  	}
    79  
    80  	if existing {
    81  		// Update the organization
    82  		if err = s.updateTx(ctx, tx,
    83  			sq.Update("orgs").
    84  				// Note we do not update ID
    85  				Set("message_id", organization.Message).
    86  				Set("parent", organization.Parent).
    87  				Set("identity", organization.Identity).
    88  				Set("description", organization.Description).
    89  				Set("profile", organization.Profile).
    90  				Set("created", organization.Created).
    91  				Where(sq.Eq{"identity": organization.Identity}),
    92  		); err != nil {
    93  			return err
    94  		}
    95  	} else {
    96  		if _, err = s.insertTx(ctx, tx,
    97  			sq.Insert("orgs").
    98  				Columns(organizationColumns...).
    99  				Values(
   100  					organization.ID,
   101  					organization.Message,
   102  					organization.Name,
   103  					organization.Parent,
   104  					organization.Identity,
   105  					organization.Description,
   106  					organization.Profile,
   107  					organization.Created,
   108  				),
   109  		); err != nil {
   110  			return err
   111  		}
   112  	}
   113  
   114  	return s.commitTx(ctx, tx, autoCommit)
   115  }
   116  
   117  func (s *SQLCommon) organizationResult(ctx context.Context, row *sql.Rows) (*fftypes.Organization, error) {
   118  	organization := fftypes.Organization{}
   119  	err := row.Scan(
   120  		&organization.ID,
   121  		&organization.Message,
   122  		&organization.Name,
   123  		&organization.Parent,
   124  		&organization.Identity,
   125  		&organization.Description,
   126  		&organization.Profile,
   127  		&organization.Created,
   128  	)
   129  	if err != nil {
   130  		return nil, i18n.WrapError(ctx, err, i18n.MsgDBReadErr, "orgs")
   131  	}
   132  	return &organization, nil
   133  }
   134  
   135  func (s *SQLCommon) getOrganizationPred(ctx context.Context, desc string, pred interface{}) (message *fftypes.Organization, err error) {
   136  
   137  	rows, err := s.query(ctx,
   138  		sq.Select(organizationColumns...).
   139  			From("orgs").
   140  			Where(pred),
   141  	)
   142  	if err != nil {
   143  		return nil, err
   144  	}
   145  	defer rows.Close()
   146  
   147  	if !rows.Next() {
   148  		log.L(ctx).Debugf("Organization '%s' not found", desc)
   149  		return nil, nil
   150  	}
   151  
   152  	organization, err := s.organizationResult(ctx, rows)
   153  	if err != nil {
   154  		return nil, err
   155  	}
   156  
   157  	return organization, nil
   158  }
   159  
   160  func (s *SQLCommon) GetOrganizationByName(ctx context.Context, name string) (message *fftypes.Organization, err error) {
   161  	return s.getOrganizationPred(ctx, name, sq.Eq{"name": name})
   162  }
   163  
   164  func (s *SQLCommon) GetOrganizationByIdentity(ctx context.Context, identity string) (message *fftypes.Organization, err error) {
   165  	return s.getOrganizationPred(ctx, identity, sq.Eq{"identity": identity})
   166  }
   167  
   168  func (s *SQLCommon) GetOrganizationByID(ctx context.Context, id *fftypes.UUID) (message *fftypes.Organization, err error) {
   169  	return s.getOrganizationPred(ctx, id.String(), sq.Eq{"id": id})
   170  }
   171  
   172  func (s *SQLCommon) GetOrganizations(ctx context.Context, filter database.Filter) (message []*fftypes.Organization, err error) {
   173  
   174  	query, err := s.filterSelect(ctx, "", sq.Select(organizationColumns...).From("orgs"), filter, organizationFilterTypeMap)
   175  	if err != nil {
   176  		return nil, err
   177  	}
   178  
   179  	rows, err := s.query(ctx, query)
   180  	if err != nil {
   181  		return nil, err
   182  	}
   183  	defer rows.Close()
   184  
   185  	organization := []*fftypes.Organization{}
   186  	for rows.Next() {
   187  		d, err := s.organizationResult(ctx, rows)
   188  		if err != nil {
   189  			return nil, err
   190  		}
   191  		organization = append(organization, d)
   192  	}
   193  
   194  	return organization, err
   195  
   196  }
   197  
   198  func (s *SQLCommon) UpdateOrganization(ctx context.Context, id *fftypes.UUID, update database.Update) (err error) {
   199  
   200  	ctx, tx, autoCommit, err := s.beginOrUseTx(ctx)
   201  	if err != nil {
   202  		return err
   203  	}
   204  	defer s.rollbackTx(ctx, tx, autoCommit)
   205  
   206  	query, err := s.buildUpdate(sq.Update("orgs"), update, organizationFilterTypeMap)
   207  	if err != nil {
   208  		return err
   209  	}
   210  	query = query.Where(sq.Eq{"id": id})
   211  
   212  	err = s.updateTx(ctx, tx, query)
   213  	if err != nil {
   214  		return err
   215  	}
   216  
   217  	return s.commitTx(ctx, tx, autoCommit)
   218  }