-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* copy User and related types from go-server-sdk * lint * lint * rm references to obsolete function
- Loading branch information
1 parent
871db18
commit 576fd88
Showing
3 changed files
with
978 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,291 @@ | ||
package lduser | ||
|
||
import ( | ||
"encoding/json" | ||
"time" | ||
|
||
"gopkg.in/launchdarkly/go-sdk-common.v2/ldvalue" | ||
) | ||
|
||
// A User contains specific attributes of a user browsing your site. The only mandatory property is the Key, | ||
// which must uniquely identify each user. For authenticated users, this may be a username or e-mail address. | ||
// For anonymous users, this could be an IP address or session ID. | ||
// | ||
// Besides the mandatory Key, User supports two kinds of optional attributes: interpreted attributes (e.g. | ||
// Ip and Country) and custom attributes. LaunchDarkly can parse interpreted attributes and attach meaning | ||
// to them. For example, from an IP address, LaunchDarkly can do a geo IP lookup and determine the user's | ||
// country. | ||
// | ||
// Custom attributes are not parsed by LaunchDarkly. They can be used in custom rules-- for example, a custom | ||
// attribute such as "customer_ranking" can be used to launch a feature to the top 10% of users on a site. | ||
// | ||
// User fields will be made private in the future, accessible only via getter methods, to prevent unsafe | ||
// modification of users after they are created. The preferred method of constructing a User is to use either | ||
// a simple constructor (NewUser, NewAnonymousUser) or the builder pattern with NewUserBuilder. If you do set | ||
// the User fields directly, it is important not to change any map/slice elements, and not change a string | ||
// that is pointed to by an existing pointer, after the User has been passed to any SDK methods; otherwise, | ||
// flag evaluations and analytics events may refer to the wrong user properties (or, in the case of a map, | ||
// you may even cause a concurrent modification panic). | ||
type User struct { | ||
// Key is the unique key of the user. | ||
// | ||
// Deprecated: Direct access to User fields is now deprecated in favor of UserBuilder. In a future version, | ||
// User fields will be private and only accessible via getter methods. | ||
Key *string `json:"key,omitempty" bson:"key,omitempty"` | ||
// SecondaryKey is the secondary key of the user. | ||
// | ||
// This affects feature flag targeting | ||
// (https://docs.launchdarkly.com/docs/targeting-users#section-targeting-rules-based-on-user-attributes) | ||
// as follows: if you have chosen to bucket users by a specific attribute, the secondary key (if set) | ||
// is used to further distinguish between users who are otherwise identical according to that attribute. | ||
// | ||
// Deprecated: Direct access to User fields is now deprecated in favor of UserBuilder. In a future version, | ||
// User fields will be private and only accessible via getter methods. | ||
Secondary *string `json:"secondary,omitempty" bson:"secondary,omitempty"` | ||
// Ip is the IP address attribute of the user. | ||
// | ||
// Deprecated: Direct access to User fields is now deprecated in favor of UserBuilder. In a future version, | ||
// User fields will be private and only accessible via getter methods. | ||
Ip *string `json:"ip,omitempty" bson:"ip,omitempty"` //nolint (nonstandard capitalization) | ||
// Country is the country attribute of the user. | ||
// | ||
// Deprecated: Direct access to User fields is now deprecated in favor of UserBuilder. In a future version, | ||
// User fields will be private and only accessible via getter methods. | ||
Country *string `json:"country,omitempty" bson:"country,omitempty"` | ||
// Email is the email address attribute of the user. | ||
// | ||
// Deprecated: Direct access to User fields is now deprecated in favor of UserBuilder. In a future version, | ||
// User fields will be private and only accessible via getter methods. | ||
Email *string `json:"email,omitempty" bson:"email,omitempty"` | ||
// FirstName is the first name attribute of the user. | ||
// | ||
// Deprecated: Direct access to User fields is now deprecated in favor of UserBuilder. In a future version, | ||
// User fields will be private and only accessible via getter methods. | ||
FirstName *string `json:"firstName,omitempty" bson:"firstName,omitempty"` | ||
// LastName is the last name attribute of the user. | ||
// | ||
// Deprecated: Direct access to User fields is now deprecated in favor of UserBuilder. In a future version, | ||
// User fields will be private and only accessible via getter methods. | ||
LastName *string `json:"lastName,omitempty" bson:"lastName,omitempty"` | ||
// Avatar is the avatar URL attribute of the user. | ||
// | ||
// Deprecated: Direct access to User fields is now deprecated in favor of UserBuilder. In a future version, | ||
// User fields will be private and only accessible via getter methods. | ||
Avatar *string `json:"avatar,omitempty" bson:"avatar,omitempty"` | ||
// Name is the name attribute of the user. | ||
// | ||
// Deprecated: Direct access to User fields is now deprecated in favor of UserBuilder. In a future version, | ||
// User fields will be private and only accessible via getter methods. | ||
Name *string `json:"name,omitempty" bson:"name,omitempty"` | ||
// Anonymous indicates whether the user is anonymous. | ||
// | ||
// If a user is anonymous, the user key will not appear on your LaunchDarkly dashboard. | ||
// | ||
// Deprecated: Direct access to User fields is now deprecated in favor of UserBuilder. In a future version, | ||
// User fields will be private and only accessible via getter methods. | ||
Anonymous *bool `json:"anonymous,omitempty" bson:"anonymous,omitempty"` | ||
// Custom is the user's map of custom attribute names and values. | ||
// | ||
// Deprecated: Direct access to User fields is now deprecated in favor of UserBuilder. In a future version, | ||
// User fields will be private and only accessible via getter methods. | ||
Custom *map[string]interface{} `json:"custom,omitempty" bson:"custom,omitempty"` | ||
// Derived is used internally by the SDK. | ||
// | ||
// Deprecated: Direct access to User fields is now deprecated in favor of UserBuilder. In a future version, | ||
// User fields will be private and only accessible via getter methods. | ||
Derived map[string]*DerivedAttribute `json:"derived,omitempty" bson:"derived,omitempty"` | ||
|
||
// PrivateAttributes contains a list of attribute names that were included in the user, | ||
// but were marked as private. As such, these attributes are not included in the fields above. | ||
// | ||
// Deprecated: Direct access to User fields is now deprecated in favor of UserBuilder. In a future version, | ||
// User fields will be private and only accessible via getter methods. | ||
PrivateAttributes []string `json:"privateAttrs,omitempty" bson:"privateAttrs,omitempty"` | ||
|
||
// This contains list of attributes to keep private, whether they appear at the top-level or Custom | ||
// The attribute "key" is always sent regardless of whether it is in this list, and "custom" cannot be used to | ||
// eliminate all custom attributes | ||
// | ||
// Deprecated: Direct access to User fields is now deprecated in favor of UserBuilder. In a future version, | ||
// User fields will be private and only accessible via getter methods. | ||
PrivateAttributeNames []string `json:"-" bson:"-"` | ||
} | ||
|
||
// GetKey gets the unique key of the user. | ||
func (u User) GetKey() string { | ||
// Key is only nullable for historical reasons - all users should have a key | ||
if u.Key == nil { | ||
return "" | ||
} | ||
return *u.Key | ||
} | ||
|
||
// GetSecondaryKey returns the secondary key of the user, if any. | ||
// | ||
// This affects feature flag targeting | ||
// (https://docs.launchdarkly.com/docs/targeting-users#section-targeting-rules-based-on-user-attributes) | ||
// as follows: if you have chosen to bucket users by a specific attribute, the secondary key (if set) | ||
// is used to further distinguish between users who are otherwise identical according to that attribute. | ||
func (u User) GetSecondaryKey() ldvalue.OptionalString { | ||
return ldvalue.NewOptionalStringFromPointer(u.Secondary) | ||
} | ||
|
||
// GetIP returns the IP address attribute of the user, if any. | ||
func (u User) GetIP() ldvalue.OptionalString { | ||
return ldvalue.NewOptionalStringFromPointer(u.Ip) | ||
} | ||
|
||
// GetCountry returns the country attribute of the user, if any. | ||
func (u User) GetCountry() ldvalue.OptionalString { | ||
return ldvalue.NewOptionalStringFromPointer(u.Country) | ||
} | ||
|
||
// GetEmail returns the email address attribute of the user, if any. | ||
func (u User) GetEmail() ldvalue.OptionalString { | ||
return ldvalue.NewOptionalStringFromPointer(u.Email) | ||
} | ||
|
||
// GetFirstName returns the first name attribute of the user, if any. | ||
func (u User) GetFirstName() ldvalue.OptionalString { | ||
return ldvalue.NewOptionalStringFromPointer(u.FirstName) | ||
} | ||
|
||
// GetLastName returns the last name attribute of the user, if any. | ||
func (u User) GetLastName() ldvalue.OptionalString { | ||
return ldvalue.NewOptionalStringFromPointer(u.LastName) | ||
} | ||
|
||
// GetAvatar returns the avatar URL attribute of the user, if any. | ||
func (u User) GetAvatar() ldvalue.OptionalString { | ||
return ldvalue.NewOptionalStringFromPointer(u.Avatar) | ||
} | ||
|
||
// GetName returns the full name attribute of the user, if any. | ||
func (u User) GetName() ldvalue.OptionalString { | ||
return ldvalue.NewOptionalStringFromPointer(u.Name) | ||
} | ||
|
||
// GetAnonymous returns the anonymous attribute of the user. | ||
// | ||
// If a user is anonymous, the user key will not appear on your LaunchDarkly dashboard. | ||
func (u User) GetAnonymous() bool { | ||
return u.Anonymous != nil && *u.Anonymous | ||
} | ||
|
||
// GetAnonymousOptional returns the anonymous attribute of the user, with a second value indicating | ||
// whether that attribute was defined for the user or not. | ||
func (u User) GetAnonymousOptional() (bool, bool) { | ||
return u.GetAnonymous(), u.Anonymous != nil | ||
} | ||
|
||
// GetCustom returns a custom attribute of the user by name. The boolean second return value indicates | ||
// whether any value was set for this attribute or not. | ||
// | ||
// The value is returned using the ldvalue.Value type, which can contain any type supported by JSON: | ||
// boolean, number, string, array (slice), or object (map). Use Value methods to access the value as | ||
// the desired type, rather than casting it. If the attribute did not exist, the value will be | ||
// ldvalue.Null() and the second return value will be false. | ||
func (u User) GetCustom(attrName string) (ldvalue.Value, bool) { | ||
if u.Custom == nil { | ||
return ldvalue.Null(), false | ||
} | ||
value, found := (*u.Custom)[attrName] | ||
// Note: since the value is currently represented internally as interface{}, we are using a | ||
// method that wraps the same interface{} in a Value, to avoid the overhead of a deep copy. | ||
// This is designated as Unsafe because it is possible (using another Unsafe method) to access | ||
// the interface{} value directly and, if it contains a slice or map, modify it. In a future | ||
// version when the User fields are no longer exposed and backward compatibility is no longer | ||
// necessary, a custom attribute will be stored as a completely immutable Value. | ||
return ldvalue.UnsafeUseArbitraryValue(value), found //nolint (using deprecated method) | ||
} | ||
|
||
// GetCustomKeys returns the keys of all custom attributes that have been set on this user. | ||
func (u User) GetCustomKeys() []string { | ||
if u.Custom == nil || len(*u.Custom) == 0 { | ||
return nil | ||
} | ||
keys := make([]string, 0, len(*u.Custom)) | ||
for key := range *u.Custom { | ||
keys = append(keys, key) | ||
} | ||
return keys | ||
} | ||
|
||
// Equal tests whether two users have equal attributes. | ||
// | ||
// Regular struct equality comparison is not allowed for User because it can contain slices and | ||
// maps. This method is faster than using reflect.DeepEqual(), and also correctly ignores | ||
// insignificant differences in the internal representation of the attributes. | ||
func (u User) Equal(other User) bool { | ||
if u.GetKey() != other.GetKey() || | ||
u.GetSecondaryKey() != other.GetSecondaryKey() || | ||
u.GetIP() != other.GetIP() || | ||
u.GetCountry() != other.GetCountry() || | ||
u.GetEmail() != other.GetEmail() || | ||
u.GetFirstName() != other.GetFirstName() || | ||
u.GetLastName() != other.GetLastName() || | ||
u.GetAvatar() != other.GetAvatar() || | ||
u.GetName() != other.GetName() || | ||
u.GetAnonymous() != other.GetAnonymous() { | ||
return false | ||
} | ||
if (u.Anonymous == nil) != (other.Anonymous == nil) || | ||
u.Anonymous != nil && *u.Anonymous != *other.Anonymous { | ||
return false | ||
} | ||
if (u.Custom == nil) != (other.Custom == nil) || | ||
u.Custom != nil && len(*u.Custom) != len(*other.Custom) { | ||
return false | ||
} | ||
if u.Custom != nil { | ||
for k, v := range *u.Custom { | ||
v1, ok := (*other.Custom)[k] | ||
if !ok || v != v1 { | ||
return false | ||
} | ||
} | ||
} | ||
if !stringSlicesEqual(u.PrivateAttributeNames, other.PrivateAttributeNames) { | ||
return false | ||
} | ||
if !stringSlicesEqual(u.PrivateAttributes, other.PrivateAttributes) { | ||
return false | ||
} | ||
return true | ||
} | ||
|
||
// String returns a simple string representation of a user. | ||
func (u User) String() string { | ||
if bytes, err := json.Marshal(u); err == nil { | ||
return string(bytes) | ||
} | ||
return "" | ||
} | ||
|
||
// DerivedAttribute is an entry in a Derived attribute map and is for internal use by LaunchDarkly only.' | ||
// Derived attributes sent to LaunchDarkly are ignored. | ||
// | ||
// Deprecated: this type is for internal use and will be removed in a future version. | ||
type DerivedAttribute struct { | ||
Value interface{} `json:"value" bson:"value"` | ||
LastDerived time.Time `json:"lastDerived" bson:"lastDerived"` | ||
} | ||
|
||
func stringSlicesEqual(a []string, b []string) bool { | ||
if len(a) != len(b) { | ||
return false | ||
} | ||
for _, n0 := range a { | ||
ok := false | ||
for _, n1 := range b { | ||
if n1 == n0 { | ||
ok = true | ||
break | ||
} | ||
} | ||
if !ok { | ||
return false | ||
} | ||
} | ||
return true | ||
} |
Oops, something went wrong.