func (hooks UserResourceHooks) AllowUpdate(res kit.Resource, obj kit.Model, old kit.Model, user kit.User) bool { if user == nil { return false } if user.HasRole("admin") || user.HasPermission("users.update") { return true } return obj.GetId() == user.GetId() }
func (UserResource) AllowDelete(res kit.Resource, obj kit.Model, user kit.User) bool { if user == nil { return false } if obj.(kit.UserModel).GetUserId() == user.GetId() { return true } return user.HasRole("admin") || user.HasPermission(res.Collection()+".delete") }
func (m *StrUserModel) SetUser(u kit.User) { if u == nil { m.User = nil m.UserId = "" } else { m.User = u.(*UserStrId) m.SetUserId(u.GetId()) } }
func (UserResource) AllowFind(res kit.Resource, model kit.Model, user kit.User) bool { if user == nil { return false } if model.(kit.UserModel).GetUserId() == user.GetId() { return true } return user.HasRole("admin") }
func (m *IntUserModel) SetUser(u kit.User) { if u == nil { m.User = nil m.UserId = 0 } else { m.User = u.(*UserIntId) m.SetUserId(u.GetId()) } }
func (PageResource) AllowFind(res kit.Resource, obj kit.Model, user kit.User) bool { if p, ok := obj.(*PageIntId); ok && p.Published { return true } else if p, ok := obj.(*PageStrId); ok && p.Published { return true } u := obj.(kit.UserModel) return user != nil && (u.GetUserId() == user.GetId() || user.HasRole("admin")) }
func (a *AuthAdaptorPassword) RegisterUser(user kit.User, data map[string]interface{}) (kit.AuthItem, apperror.Error) { if data == nil { return nil, apperror.New("invalid_nil_data") } pw, _ := GetStringFromMap(data, "password") if pw == "" { return nil, apperror.New("invalid_data_no_password") } hash, err := bcrypt.GenerateFromPassword([]byte(pw), 10) if err != nil { return nil, apperror.Wrap(err, "hash_errr", "") } item := &AuthItemPassword{ Hash: string(hash), } item.SetId(user.GetId()) return item, nil }
func (res *Resource) Create(obj kit.Model, user kit.User) apperror.Error { if hook, ok := res.hooks.(CreateHook); ok { return hook.Create(res, obj, user) } // This has to be done before tthe AllowCreate hook to allow the hook to // compare UserId value. if userModel, ok := obj.(kit.UserModel); ok && user != nil { if reflector.R(userModel.GetUserId()).IsZero() { userModel.SetUserId(user.GetId()) } } if allowCreate, ok := res.hooks.(AllowCreateHook); ok { if !allowCreate.AllowCreate(res, obj, user) { return apperror.New("permission_denied") } } if beforeCreate, ok := res.hooks.(BeforeCreateHook); ok { if err := beforeCreate.BeforeCreate(res, obj, user); err != nil { return err } } if err := res.backend.Create(obj); err != nil { return err } if afterCreate, ok := res.hooks.(AfterCreateHook); ok { if err := afterCreate.AfterCreate(res, obj, user); err != nil { return err } } return nil }
func (s Service) StartSession(user kit.User, sessionType string) (kit.Session, apperror.Error) { token := randomToken() if token == "" { return nil, apperror.New("token_creation_failed") } session := s.Sessions.CreateModel().(kit.Session) session.SetType(sessionType) session.SetToken(token) session.SetStartedAt(time.Now()) session.SetValidUntil(time.Now().Add(time.Hour * 12)) if user != nil { session.SetUserId(user.GetId()) } err := s.Sessions.Create(session, nil) if err != nil { return nil, err } return session, nil }
func (item *AuthItemPassword) SetUser(u kit.User) { item.SetUserId(u.GetId()) }
func (p IntIdUserProfile) SetUser(user kit.User) { p.SetUserId(user.GetId()) }
}) It("Should resend confirmation email", func() { if skipUser { Skip("Previous error") } js := `{"data": {}}` status, _, err := client.PostJson("/api/method/users.send-confirmation-email", js) Expect(err).ToNot(HaveOccurred()) Expect(status).To(Equal(200)) // Check that confirmation email was sent. logEntry := logMessages[len(logMessages)-2] Expect(logEntry.Data["action"]).To(Equal("users.email_confirmation_mail_sent")) Expect(logEntry.Data["user_id"]).To(Equal(currentUser.GetId())) Expect(logEntry.Data["email"]).To(Equal(currentUser.GetEmail())) currentToken = logEntry.Data["token"].(string) }) It("Should confirm email", func() { if skipUser || currentToken == "" { Skip("Previous error") } js := fmt.Sprintf(`{"data": {"token": "%v"}}`, currentToken) status, _, err := client.PostJson("/api/method/users.confirm-email", js) Expect(err).ToNot(HaveOccurred()) Expect(status).To(Equal(200))
func (s *Service) SendPasswordResetEmail(user kit.User) apperror.Error { // Check that an email service is configured. mailService := s.registry.EmailService() if mailService == nil { return apperror.New("no_email_service") } hoursValid := 48 // Generate a token. expiresAt := time.Now().Add(time.Hour * time.Duration(hoursValid)) tokenItem, err := s.BuildToken("password_reset", user.GetStrId(), expiresAt) if err != nil { return err } token := tokenItem.GetToken() conf := s.registry.Config() // Build the confirmation url. url := conf.UString("url") if url == "" { return &apperror.Err{ Code: "no_url_set", Message: "Config must specify url", } } resetPath := conf.UString("users.passwordResetPath") if resetPath == "" { return &apperror.Err{ Code: "no_password_reset_path", Message: "Config must specify users.passwordResetPath", } } if !strings.Contains(resetPath, "{token}") { return &apperror.Err{ Code: "invalid_password_reset_path", Message: "users.passwordResetPath does not contain {token} placeholder", } } resetUrl := url + "/" + strings.Replace(resetPath, "{token}", token, -1) // Render email. subject := conf.UString("users.passwordResetSubject", "Password reset") var txtContent, htmlContent []byte txtTpl := conf.UString("users.passwordResetTextTpl") htmlTpl := conf.UString("users.passwordResetHtmlTpl") if txtTpl != "" && htmlTpl != "" { // Check that a template engine is configured. engine := s.registry.TemplateEngine() if engine == nil { return apperror.New("no_template_engine") } data := map[string]interface{}{ "user": user, "token": token, "hours_valid": hoursValid, } var err apperror.Error txtContent, err = s.registry.TemplateEngine().BuildFileAndRender(txtTpl, data) if err != nil { return apperror.Wrap(err, "password_reset_tpl_error", "Could not render password reset tpl") } htmlContent, err = s.registry.TemplateEngine().BuildFileAndRender(htmlTpl, data) if err != nil { return apperror.Wrap(err, "password_reset_tpl_error", "Could not render password reset tpl") } } else { tpl := `Password reset To reset your password, please visit %v. The link will be valid for %v hours. ` htmlTpl := `Password Reset<br><br> To reset your password, please visit <a href="%v">this link</a>.<br> The link will be valid for %v hours. ` txtContent = []byte(fmt.Sprintf(tpl, resetUrl, hoursValid)) htmlContent = []byte(fmt.Sprintf(htmlTpl, resetUrl, hoursValid)) } // Now build the email and send it. email := email.NewMail() email.SetSubject(subject) email.AddBody("text/plain", txtContent) email.AddBody("text/html", htmlContent) email.AddTo(user.GetEmail(), "") if err := mailService.Send(email); err != nil { return err } s.registry.Logger().WithFields(logrus.Fields{ "action": "users.password_reset_requested", "email": user.GetEmail(), "user_id": user.GetId(), "token": token, }).Debugf("Password reset email sent to %v for user %v", user.GetEmail(), user.GetId()) return nil }
func (s *Service) SendConfirmationEmail(user kit.User) apperror.Error { // Check that an email service is configured. mailService := s.registry.EmailService() if mailService == nil { return apperror.New("no_email_service") } conf := s.registry.Config() // Check that sending is enabled. if !conf.UBool("users.sendEmailConfirmationEmail", true) { return nil } // Generate a token. tokenItem, err := s.BuildToken("email_confirmation", user.GetStrId(), time.Time{}) if err != nil { return err } token := tokenItem.GetToken() // Build the confirmation url. confirmationPath := conf.UString("users.emailConfirmationPath") if confirmationPath == "" { return &apperror.Err{ Code: "no_email_confirmation_path", Message: "Config must specify users.emailConfirmationPath", } } if !strings.Contains(confirmationPath, "{token}") { return &apperror.Err{ Code: "invalid_email_confirmation_path", Message: "users.emailConfirmationPath does not contain {token} placeholder", } } confirmationUrl := conf.UString("url") + "/" + strings.Replace(confirmationPath, "{token}", token, -1) // Render email. subject := conf.UString("users.emailConfirmationSubject", "Confirm your Email") var txtContent, htmlContent []byte txtTpl := conf.UString("users.emailConfirmationEmailTextTpl") htmlTpl := conf.UString("users.emailConfirmationEmailHtmlTpl") if txtTpl != "" && htmlTpl != "" { // Check that a template engine is configured. engine := s.registry.TemplateEngine() if engine == nil { return apperror.New("no_template_engine") } data := map[string]interface{}{ "user": user, "token": token, } var err apperror.Error txtContent, err = s.registry.TemplateEngine().BuildFileAndRender(txtTpl, data) if err != nil { return apperror.Wrap(err, "email_confirmation_tpl_error", "Could not render email confirmation tpl") } htmlContent, err = s.registry.TemplateEngine().BuildFileAndRender(htmlTpl, data) if err != nil { return apperror.Wrap(err, "email_confirmation_tpl_error", "Could not render email confirmation tpl") } } else { tpl := `Welcome to Appkit To confirm your email address, please visit %v. ` htmlTpl := `Welcome to Appkit<br><br> To confirm your email address, please visit <a href="%v">this link</a>. ` txtContent = []byte(fmt.Sprintf(tpl, confirmationUrl)) htmlContent = []byte(fmt.Sprintf(htmlTpl, confirmationUrl)) } // Now build the email and send it. email := email.NewMail() email.SetSubject(subject) email.AddBody("text/plain", txtContent) email.AddBody("text/html", htmlContent) email.AddTo(user.GetEmail(), "") if err := mailService.Send(email); err != nil { return err } s.registry.Logger().WithFields(logrus.Fields{ "action": "users.email_confirmation_mail_sent", "email": user.GetEmail(), "user_id": user.GetId(), "token": token, }).Debugf("Password reset email sent to %v for user %v", user.GetEmail(), user.GetId()) return nil }
func (s *Service) CreateUser(user kit.User, adaptorName string, authData map[string]interface{}) apperror.Error { adaptor := s.AuthAdaptor(adaptorName) if adaptor == nil { return &apperror.Err{ Code: "unknown_auth_adaptor", Message: fmt.Sprintf("Auth adaptor %v was not registered with user service", adaptorName), Public: true, } } authItem, err := adaptor.RegisterUser(user, authData) if err != nil { return apperror.Wrap(err, "adaptor_error", "") } if user.GetUsername() == "" { user.SetUsername(user.GetEmail()) } // Check if user with same username or email exists. oldUser, err2 := s.Users.Q(). Filter("email", user.GetEmail()).Or("username", user.GetUsername()).First() if err2 != nil { return err2 } else if oldUser != nil { return &apperror.Err{ Code: "user_exists", Message: "A user with the username or email already exists", Public: true, } } user.SetIsActive(true) profile := user.GetProfile() // If a profile is configured, and the user does not have a profile yet, // create a new one. if s.Profiles != nil && profile == nil { profile = s.Profiles.CreateModel().(kit.UserProfile) user.SetProfile(profile) } if err := s.Users.Create(user, nil); err != nil { return err } // Create profile if one exists. if profile != nil { profile.SetUser(user) if err := s.Profiles.Create(profile, user); err != nil { s.Users.Backend().Delete(user) return apperror.Wrap(err, "user_profile_create_error", "Could not create the user profile") } } // Persist auth item. if authItemUserId, ok := authItem.(kit.UserModel); ok { authItemUserId.SetUserId(user.GetId()) } if err := s.Users.Backend().Create(authItem); err != nil { s.Users.Backend().Delete(user) if profile != nil { s.Profiles.Backend().Delete(profile) } return apperror.Wrap(err, "auth_item_create_error", "") } if err := s.SendConfirmationEmail(user); err != nil { s.registry.Logger().Errorf("Could not send confirmation email: %v", err) } return nil }
func (item *AuthItemOauth) SetUser(u kit.User) { item.SetUserId(u.GetId()) }