diff --git a/api/Invitation.go b/api/Invitation.go index 9c485f72..4c134a62 100644 --- a/api/Invitation.go +++ b/api/Invitation.go @@ -195,7 +195,7 @@ func (a *API) VerifyInvitation(w http.ResponseWriter, r *http.Request) error { defer itr.Close() var invitation models.Invitation for itr.Next(&invitation) { - if invitation.Code == params.Code && time.Now().UnixMilli() <= invitation.ExpirationTime && invitation.Status == InvitationStatusPending { + if invitation.Code == params.Code && time.Now().UnixMilli() <= (invitation.ExpirationTime+int64(a.config.InvitationConfig.LeewaySecond)*1000) && invitation.Status == InvitationStatusPending { // mark invitation as accepted, if not dry if !params.Dry { invitation.Status = InvitationStatusAccepted diff --git a/api/admin.go b/api/admin.go index 332f72a6..e13f9c84 100644 --- a/api/admin.go +++ b/api/admin.go @@ -202,16 +202,13 @@ func (a *API) adminUserCreate(w http.ResponseWriter, r *http.Request) error { return terr } - _, terr := tigris.GetCollection[models.User](a.db).Insert(ctx, user) - if terr != nil { - return terr - } - role := config.JWT.DefaultGroupName if params.Role != "" { role = params.Role } - if terr := user.SetRole(ctx, a.db, role); terr != nil { + user.Role = role + _, terr := tigris.GetCollection[models.User](a.db).Insert(ctx, user) + if terr != nil { return terr } diff --git a/api/admin_test.go b/api/admin_test.go index fc108cc0..6c987119 100644 --- a/api/admin_test.go +++ b/api/admin_test.go @@ -212,7 +212,7 @@ func (ts *AdminTestSuite) TestAdminUsers_SortAsc() { func (ts *AdminTestSuite) TestAdminUsers_SortDesc() { // enable test once sorting is implemented ts.T().Skip() - u, err := models.NewUserWithAppData(ts.instanceID, "test1@example.com", "test", ts.Config.JWT.Aud, nil, models.UserAppMetadata{ + u, err := models.NewUserWithAppData(ts.instanceID, "test1@example.com", "test", ts.Config.JWT.Aud, "test_role", nil, models.UserAppMetadata{ TigrisNamespace: "test", TigrisProject: "test", Name: "test", @@ -248,7 +248,7 @@ func (ts *AdminTestSuite) TestAdminUsers_SortDesc() { // TestAdminUsers tests API /admin/users route func (ts *AdminTestSuite) TestAdminUsers_FilterEmail() { - u, err := models.NewUserWithAppData(ts.instanceID, "test1@example.com", "test", ts.Config.JWT.Aud, nil, models.UserAppMetadata{ + u, err := models.NewUserWithAppData(ts.instanceID, "test1@example.com", "test", ts.Config.JWT.Aud, "test_role", nil, models.UserAppMetadata{ TigrisNamespace: "test", TigrisProject: "test", Name: "test", @@ -280,7 +280,7 @@ func (ts *AdminTestSuite) TestAdminUsers_FilterEmail() { // TestAdminUsers tests API /admin/users route func (ts *AdminTestSuite) TestAdminUsers_FilterName() { - u, err := models.NewUserWithAppData(ts.instanceID, "test1@example.com", "test", ts.Config.JWT.Aud, nil, models.UserAppMetadata{ + u, err := models.NewUserWithAppData(ts.instanceID, "test1@example.com", "test", ts.Config.JWT.Aud, "test_role", nil, models.UserAppMetadata{ TigrisNamespace: "test", TigrisProject: "test", Name: "test", @@ -313,7 +313,7 @@ func (ts *AdminTestSuite) TestAdminUsers_FilterName() { // TestAdminUsers_FilterTigrisProject tests API /admin/users route - creates 3 users for a test_namespace with different projects and queries them by tigris_project func (ts *AdminTestSuite) TestAdminUsers_FilterTigrisProject() { // first user - u, err := models.NewUserWithAppData(ts.instanceID, "test1@example.com", "test", ts.Config.JWT.Aud, nil, models.UserAppMetadata{ + u, err := models.NewUserWithAppData(ts.instanceID, "test1@example.com", "test", ts.Config.JWT.Aud, "test_role", nil, models.UserAppMetadata{ TigrisNamespace: "test_namespace", TigrisProject: "test2", Name: "test", @@ -325,7 +325,7 @@ func (ts *AdminTestSuite) TestAdminUsers_FilterTigrisProject() { require.NoError(ts.T(), err, "Error creating user") // second user - u2, err := models.NewUserWithAppData(ts.instanceID, "test2@example.com", "test", ts.Config.JWT.Aud, nil, models.UserAppMetadata{ + u2, err := models.NewUserWithAppData(ts.instanceID, "test2@example.com", "test", ts.Config.JWT.Aud, "test_role", nil, models.UserAppMetadata{ TigrisNamespace: "test_namespace", TigrisProject: "test3", Name: "test", @@ -336,7 +336,7 @@ func (ts *AdminTestSuite) TestAdminUsers_FilterTigrisProject() { require.NoError(ts.T(), err, "Error creating user") // third user without project field - u3, err := models.NewUserWithAppData(ts.instanceID, "test3@example.com", "test", ts.Config.JWT.Aud, nil, models.UserAppMetadata{ + u3, err := models.NewUserWithAppData(ts.instanceID, "test3@example.com", "test", ts.Config.JWT.Aud, "test_role", nil, models.UserAppMetadata{ TigrisNamespace: "test_namespace", Name: "test", Provider: "email", diff --git a/api/signup.go b/api/signup.go index a5021893..35dbdea9 100644 --- a/api/signup.go +++ b/api/signup.go @@ -14,6 +14,7 @@ import ( type SignupParams struct { Email string `json:"email"` Password string `json:"password"` + Role string `json:"role"` Data map[string]interface{} `json:"data"` AppData models.UserAppMetadata `json:"app_data"` Provider string `json:"-"` @@ -100,7 +101,7 @@ func (a *API) signupNewUser(ctx context.Context, params *SignupParams) (*models. instanceID := getInstanceID(ctx) config := a.getConfig(ctx) - user, err := models.NewUserWithAppData(instanceID, params.Email, params.Password, params.Aud, params.Data, params.AppData, a.encrypter) + user, err := models.NewUserWithAppData(instanceID, params.Email, params.Password, params.Aud, params.Role, params.Data, params.AppData, a.encrypter) if err != nil { return nil, internalServerError("Database error creating user").WithInternalError(err) } diff --git a/conf/configuration.go b/conf/configuration.go index 65a46fc1..b633c67c 100644 --- a/conf/configuration.go +++ b/conf/configuration.go @@ -85,9 +85,11 @@ type GlobalConfiguration struct { } type InvitationConfiguration struct { - CodeLength int `json:"code_length" default:"30"` - CodePrefix string `json:"code_prefix" default:"ti_"` - HideCode bool `json:"hide_code" default:"false"` + CodeLength int `json:"code_length" default:"30"` + // allows the delay of leeway seconds in expiration of the invitation code + LeewaySecond int `json:"leeway_second" default:"300"` + CodePrefix string `json:"code_prefix" default:"ti_"` + HideCode bool `json:"hide_code" default:"false"` } // EmailContentConfiguration holds the configuration for emails, both subjects and template URLs. diff --git a/models/user.go b/models/user.go index 7cf87283..801bd8ab 100644 --- a/models/user.go +++ b/models/user.go @@ -88,7 +88,7 @@ func NewUser(instanceID uuid.UUID, email, password, aud string, userData map[str } // NewUserWithAppData initializes a new user from an email, password and user data. -func NewUserWithAppData(instanceID uuid.UUID, email, password, aud string, userData map[string]interface{}, appData UserAppMetadata, encrypter *crypto.AESBlockEncrypter) (*User, error) { +func NewUserWithAppData(instanceID uuid.UUID, email, password, aud string, role string, userData map[string]interface{}, appData UserAppMetadata, encrypter *crypto.AESBlockEncrypter) (*User, error) { id, err := uuid.NewRandom() if err != nil { return nil, errors.Wrap(err, "Error generating unique id") @@ -175,7 +175,7 @@ func (u *User) IsConfirmed() bool { func (u *User) SetRole(ctx context.Context, database *tigris.Database, roleName string) error { u.Role = strings.TrimSpace(roleName) - _, err := tigris.GetCollection[User](database).Update(ctx, filter.Eq("id", u.ID.String()), fields.Set("role", u.Role)) + _, err := tigris.GetCollection[User](database).Update(ctx, filter.Eq("email", u.Email), fields.Set("role", u.Role)) return err } diff --git a/models/user_test.go b/models/user_test.go index 18178cc3..c1b2abc2 100644 --- a/models/user_test.go +++ b/models/user_test.go @@ -206,7 +206,7 @@ func (ts *UserTestSuite) createUser() *User { } func (ts *UserTestSuite) createUserWithEmail(email string) *User { - user, err := NewUserWithAppData(uuid.Nil, email, "secret", "test", nil, UserAppMetadata{ + user, err := NewUserWithAppData(uuid.Nil, email, "secret", "test", "test_role", nil, UserAppMetadata{ Name: "test", Description: "test", Provider: "email",