Skip to main content

Sync a user with the Go SDK

Permit.Api.Users.SyncUser() saves a user's identity and attributes to Permit.io. If no user with the key exists, SyncUser creates the user. If the user exists, SyncUser updates it. This reference is for Go developers who sync users from their authentication flow, for example when a user signs up or signs in. After the sync, the policy decision point (PDP) can evaluate permission checks for that user.

SyncUser doesn't assign roles. To give the synced user a role, call Users.AssignRole.

Users.SyncUser signature

func (u *Users) SyncUser(ctx context.Context, user models.UserCreate) (*models.UserRead, error)

Users.SyncUser parameters

ParameterTypeRequiredDescription
ctxcontext.ContextYesThe context of the request.
usermodels.UserCreateYesThe user to sync. Build it with models.NewUserCreate(key).

UserCreate fields for Users.SyncUser

Users.SyncUser takes the same UserCreate struct as Users.Create:

FieldTypeRequiredDescription
KeystringYesA unique ID by which Permit identifies the user. You pass the same key as the user in Permit.Check().
Email*stringNoThe email of the user. Set it with SetEmail().
FirstName*stringNoThe first name of the user. Set it with SetFirstName().
LastName*stringNoThe last name of the user. Set it with SetLastName().
Attributesmap[string]interface{}NoUser attributes that attribute-based access control (ABAC) policies evaluate. Set them with SetAttributes().

How Users.SyncUser decides between create and update

  1. SyncUser calls Users.Get with the key of the user.
  2. If the Permit API returns NotFound, SyncUser calls Users.Create with the struct you passed.
  3. If the user exists, SyncUser calls Users.Update. The update copies Email, FirstName, and LastName when they aren't empty, and copies Attributes when you set them.
warning

When the user exists and you set Attributes, the update replaces all the user's stored attributes with the map you pass. Attribute keys that aren't in the map are removed from the user, and ABAC policies no longer see them.

Example: sync a user with Users.SyncUser

The example uses a client named Permit, created with permit.NewPermit() as shown in Check permissions with the Go SDK, and a ctx of type context.Context.

Build the UserCreate struct with the key user-key, an email, a first and last name, and an age attribute:

user := models.NewUserCreate("user-key")
user.SetEmail("john@doe.com")
user.SetFirstName("John")
user.SetLastName("Doe")
user.SetAttributes(map[string]interface{}{
"age": "26",
})

Pass the struct to Users.SyncUser:

newUser, err := Permit.Api.Users.SyncUser(ctx, *user)

Users.SyncUser return value and errors

On success, Users.SyncUser returns a *models.UserRead for the created or updated user.

If the call fails, err holds an errors.PermitError from the github.com/permitio/permit-golang/pkg/errors package. Its StatusCode field has the HTTP status, and its ErrorCode field has one of these codes:

ErrorCodeCause
UnprocessableEntityErrorHTTP 422: a field failed validation.
Unauthorized, ForbiddenAccessHTTP 401 or 403: the API key is invalid or has no access to the environment.
UnexpectedErrorA server error (HTTP 5xx) or a network error.