github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/core/description/user.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package description
     5  
     6  import (
     7  	"time"
     8  
     9  	"github.com/juju/errors"
    10  	"github.com/juju/schema"
    11  	"gopkg.in/juju/names.v2"
    12  )
    13  
    14  type users struct {
    15  	Version int     `yaml:"version"`
    16  	Users_  []*user `yaml:"users"`
    17  }
    18  
    19  type UserArgs struct {
    20  	Name           names.UserTag
    21  	DisplayName    string
    22  	CreatedBy      names.UserTag
    23  	DateCreated    time.Time
    24  	LastConnection time.Time
    25  	Access         string
    26  }
    27  
    28  func newUser(args UserArgs) *user {
    29  	u := &user{
    30  		Name_:        args.Name.Id(),
    31  		DisplayName_: args.DisplayName,
    32  		CreatedBy_:   args.CreatedBy.Id(),
    33  		DateCreated_: args.DateCreated,
    34  		Access_:      args.Access,
    35  	}
    36  	if !args.LastConnection.IsZero() {
    37  		value := args.LastConnection
    38  		u.LastConnection_ = &value
    39  	}
    40  	return u
    41  }
    42  
    43  type user struct {
    44  	Name_        string    `yaml:"name"`
    45  	DisplayName_ string    `yaml:"display-name,omitempty"`
    46  	CreatedBy_   string    `yaml:"created-by"`
    47  	DateCreated_ time.Time `yaml:"date-created"`
    48  	Access_      string    `yaml:"access"`
    49  	// Can't use omitempty with time.Time, it just doesn't work,
    50  	// so use a pointer in the struct.
    51  	LastConnection_ *time.Time `yaml:"last-connection,omitempty"`
    52  }
    53  
    54  // Name implements User.
    55  func (u *user) Name() names.UserTag {
    56  	return names.NewUserTag(u.Name_)
    57  }
    58  
    59  // DisplayName implements User.
    60  func (u *user) DisplayName() string {
    61  	return u.DisplayName_
    62  }
    63  
    64  // CreatedBy implements User.
    65  func (u *user) CreatedBy() names.UserTag {
    66  	return names.NewUserTag(u.CreatedBy_)
    67  }
    68  
    69  // DateCreated implements User.
    70  func (u *user) DateCreated() time.Time {
    71  	return u.DateCreated_
    72  }
    73  
    74  // LastConnection implements User.
    75  func (u *user) LastConnection() time.Time {
    76  	var zero time.Time
    77  	if u.LastConnection_ == nil {
    78  		return zero
    79  	}
    80  	return *u.LastConnection_
    81  }
    82  
    83  // Access implements User.
    84  func (u *user) Access() string {
    85  	return u.Access_
    86  }
    87  
    88  func importUsers(source map[string]interface{}) ([]*user, error) {
    89  	checker := versionedChecker("users")
    90  	coerced, err := checker.Coerce(source, nil)
    91  	if err != nil {
    92  		return nil, errors.Annotatef(err, "users version schema check failed")
    93  	}
    94  	valid := coerced.(map[string]interface{})
    95  
    96  	version := int(valid["version"].(int64))
    97  	importFunc, ok := userDeserializationFuncs[version]
    98  	if !ok {
    99  		return nil, errors.NotValidf("version %d", version)
   100  	}
   101  	sourceList := valid["users"].([]interface{})
   102  	return importUserList(sourceList, importFunc)
   103  }
   104  
   105  func importUserList(sourceList []interface{}, importFunc userDeserializationFunc) ([]*user, error) {
   106  	result := make([]*user, 0, len(sourceList))
   107  	for i, value := range sourceList {
   108  		source, ok := value.(map[string]interface{})
   109  		if !ok {
   110  			return nil, errors.Errorf("unexpected value for user %d, %T", i, value)
   111  		}
   112  		user, err := importFunc(source)
   113  		if err != nil {
   114  			return nil, errors.Annotatef(err, "user %d", i)
   115  		}
   116  		result = append(result, user)
   117  	}
   118  	return result, nil
   119  }
   120  
   121  type userDeserializationFunc func(map[string]interface{}) (*user, error)
   122  
   123  var userDeserializationFuncs = map[int]userDeserializationFunc{
   124  	1: importUserV1,
   125  }
   126  
   127  func importUserV1(source map[string]interface{}) (*user, error) {
   128  	fields := schema.Fields{
   129  		"name":            schema.String(),
   130  		"display-name":    schema.String(),
   131  		"created-by":      schema.String(),
   132  		"read-only":       schema.Bool(),
   133  		"date-created":    schema.Time(),
   134  		"last-connection": schema.Time(),
   135  		"access":          schema.String(),
   136  	}
   137  
   138  	// Some values don't have to be there.
   139  	defaults := schema.Defaults{
   140  		"display-name":    "",
   141  		"last-connection": time.Time{},
   142  		"read-only":       false,
   143  	}
   144  	checker := schema.FieldMap(fields, defaults)
   145  	coerced, err := checker.Coerce(source, nil)
   146  	if err != nil {
   147  		return nil, errors.Annotatef(err, "user v1 schema check failed")
   148  	}
   149  	valid := coerced.(map[string]interface{})
   150  	// From here we know that the map returned from the schema coercion
   151  	// contains fields of the right type.
   152  
   153  	result := &user{
   154  		Name_:        valid["name"].(string),
   155  		DisplayName_: valid["display-name"].(string),
   156  		CreatedBy_:   valid["created-by"].(string),
   157  		DateCreated_: valid["date-created"].(time.Time),
   158  		Access_:      valid["access"].(string),
   159  	}
   160  
   161  	lastConn := valid["last-connection"].(time.Time)
   162  	if !lastConn.IsZero() {
   163  		result.LastConnection_ = &lastConn
   164  	}
   165  
   166  	return result, nil
   167  
   168  }