mirror of
https://github.com/absmach/magistrala.git
synced 2026-08-07 07:14:46 +00:00
NOISSUE - Obtain email host from env (#3098)
Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>
This commit is contained in:
committed by
GitHub
parent
6a27594751
commit
af35396601
+23
-23
@@ -67,28 +67,28 @@ const (
|
||||
)
|
||||
|
||||
type config struct {
|
||||
LogLevel string `env:"SMQ_USERS_LOG_LEVEL" envDefault:"info"`
|
||||
AdminEmail string `env:"SMQ_USERS_ADMIN_EMAIL" envDefault:"admin@example.com"`
|
||||
AdminPassword string `env:"SMQ_USERS_ADMIN_PASSWORD" envDefault:"12345678"`
|
||||
AdminUsername string `env:"SMQ_USERS_ADMIN_USERNAME" envDefault:"admin"`
|
||||
AdminFirstName string `env:"SMQ_USERS_ADMIN_FIRST_NAME" envDefault:"super"`
|
||||
AdminLastName string `env:"SMQ_USERS_ADMIN_LAST_NAME" envDefault:"admin"`
|
||||
PassRegexText string `env:"SMQ_USERS_PASS_REGEX" envDefault:"^.{8,}$"`
|
||||
ResetURL string `env:"SMQ_TOKEN_RESET_ENDPOINT" envDefault:"/reset-request"`
|
||||
JaegerURL url.URL `env:"SMQ_JAEGER_URL" envDefault:"http://localhost:4318/v1/traces"`
|
||||
SendTelemetry bool `env:"SMQ_SEND_TELEMETRY" envDefault:"true"`
|
||||
InstanceID string `env:"SMQ_USERS_INSTANCE_ID" envDefault:""`
|
||||
ESURL string `env:"SMQ_ES_URL" envDefault:"nats://localhost:4222"`
|
||||
TraceRatio float64 `env:"SMQ_JAEGER_TRACE_RATIO" envDefault:"1.0"`
|
||||
SelfRegister bool `env:"SMQ_USERS_ALLOW_SELF_REGISTER" envDefault:"false"`
|
||||
OAuthUIRedirectURL string `env:"SMQ_OAUTH_UI_REDIRECT_URL" envDefault:"http://localhost:9095/domains"`
|
||||
OAuthUIErrorURL string `env:"SMQ_OAUTH_UI_ERROR_URL" envDefault:"http://localhost:9095/error"`
|
||||
DeleteInterval time.Duration `env:"SMQ_USERS_DELETE_INTERVAL" envDefault:"24h"`
|
||||
DeleteAfter time.Duration `env:"SMQ_USERS_DELETE_AFTER" envDefault:"720h"`
|
||||
SpicedbHost string `env:"SMQ_SPICEDB_HOST" envDefault:"localhost"`
|
||||
SpicedbPort string `env:"SMQ_SPICEDB_PORT" envDefault:"50051"`
|
||||
SpicedbPreSharedKey string `env:"SMQ_SPICEDB_PRE_SHARED_KEY" envDefault:"12345678"`
|
||||
PassRegex *regexp.Regexp
|
||||
LogLevel string `env:"SMQ_USERS_LOG_LEVEL" envDefault:"info"`
|
||||
AdminEmail string `env:"SMQ_USERS_ADMIN_EMAIL" envDefault:"admin@example.com"`
|
||||
AdminPassword string `env:"SMQ_USERS_ADMIN_PASSWORD" envDefault:"12345678"`
|
||||
AdminUsername string `env:"SMQ_USERS_ADMIN_USERNAME" envDefault:"admin"`
|
||||
AdminFirstName string `env:"SMQ_USERS_ADMIN_FIRST_NAME" envDefault:"super"`
|
||||
AdminLastName string `env:"SMQ_USERS_ADMIN_LAST_NAME" envDefault:"admin"`
|
||||
PassRegexText string `env:"SMQ_USERS_PASS_REGEX" envDefault:"^.{8,}$"`
|
||||
JaegerURL url.URL `env:"SMQ_JAEGER_URL" envDefault:"http://localhost:4318/v1/traces"`
|
||||
SendTelemetry bool `env:"SMQ_SEND_TELEMETRY" envDefault:"true"`
|
||||
InstanceID string `env:"SMQ_USERS_INSTANCE_ID" envDefault:""`
|
||||
ESURL string `env:"SMQ_ES_URL" envDefault:"nats://localhost:4222"`
|
||||
TraceRatio float64 `env:"SMQ_JAEGER_TRACE_RATIO" envDefault:"1.0"`
|
||||
SelfRegister bool `env:"SMQ_USERS_ALLOW_SELF_REGISTER" envDefault:"false"`
|
||||
OAuthUIRedirectURL string `env:"SMQ_OAUTH_UI_REDIRECT_URL" envDefault:"http://localhost:9095/domains"`
|
||||
OAuthUIErrorURL string `env:"SMQ_OAUTH_UI_ERROR_URL" envDefault:"http://localhost:9095/error"`
|
||||
DeleteInterval time.Duration `env:"SMQ_USERS_DELETE_INTERVAL" envDefault:"24h"`
|
||||
DeleteAfter time.Duration `env:"SMQ_USERS_DELETE_AFTER" envDefault:"720h"`
|
||||
SpicedbHost string `env:"SMQ_SPICEDB_HOST" envDefault:"localhost"`
|
||||
SpicedbPort string `env:"SMQ_SPICEDB_PORT" envDefault:"50051"`
|
||||
SpicedbPreSharedKey string `env:"SMQ_SPICEDB_PRE_SHARED_KEY" envDefault:"12345678"`
|
||||
PasswordResetURLPrefix string `env:"SMQ_PASSWORD_RESET_URL_PREFIX" envDefault:"http://localhost:8080"`
|
||||
PassRegex *regexp.Regexp
|
||||
}
|
||||
|
||||
func main() {
|
||||
@@ -264,7 +264,7 @@ func newService(ctx context.Context, authz smqauthz.Authorization, token grpcTok
|
||||
|
||||
// Creating users service
|
||||
repo := postgres.NewRepository(database)
|
||||
emailerClient, err := emailer.New(c.ResetURL, &ec)
|
||||
emailerClient, err := emailer.New(fmt.Sprintf("%s/reset-request", c.PasswordResetURLPrefix), &ec)
|
||||
if err != nil {
|
||||
logger.Error(fmt.Sprintf("failed to configure e-mailing util: %s", err.Error()))
|
||||
}
|
||||
|
||||
+1
-2
@@ -235,7 +235,6 @@ SMQ_USERS_ADMIN_LAST_NAME=admin
|
||||
SMQ_USERS_PASS_REGEX=^.{8,}$
|
||||
SMQ_USERS_ACCESS_TOKEN_DURATION=15m
|
||||
SMQ_USERS_REFRESH_TOKEN_DURATION=24h
|
||||
SMQ_TOKEN_RESET_ENDPOINT=/reset-request
|
||||
SMQ_USERS_HTTP_HOST=users
|
||||
SMQ_USERS_HTTP_PORT=9002
|
||||
SMQ_USERS_HTTP_SERVER_CERT=
|
||||
@@ -257,12 +256,12 @@ SMQ_USERS_ADMIN_PASSWORD=12345678
|
||||
SMQ_USERS_PASS_REGEX=^.{8,}$
|
||||
SMQ_USERS_ACCESS_TOKEN_DURATION=15m
|
||||
SMQ_USERS_REFRESH_TOKEN_DURATION=24h
|
||||
SMQ_TOKEN_RESET_ENDPOINT=/reset-request
|
||||
SMQ_USERS_ALLOW_SELF_REGISTER=true
|
||||
SMQ_OAUTH_UI_REDIRECT_URL=http://localhost:9095${SMQ_UI_PATH_PREFIX}/tokens/secure
|
||||
SMQ_OAUTH_UI_ERROR_URL=http://localhost:9095${SMQ_UI_PATH_PREFIX}/error
|
||||
SMQ_USERS_DELETE_INTERVAL=24h
|
||||
SMQ_USERS_DELETE_AFTER=720h
|
||||
SMQ_PASSWORD_RESET_URL_PREFIX=http://localhost:9001
|
||||
|
||||
#### Users Client Config
|
||||
SMQ_USERS_URL=users:9002
|
||||
|
||||
@@ -835,7 +835,6 @@ services:
|
||||
SMQ_USERS_PASS_REGEX: ${SMQ_USERS_PASS_REGEX}
|
||||
SMQ_USERS_ACCESS_TOKEN_DURATION: ${SMQ_USERS_ACCESS_TOKEN_DURATION}
|
||||
SMQ_USERS_REFRESH_TOKEN_DURATION: ${SMQ_USERS_REFRESH_TOKEN_DURATION}
|
||||
SMQ_TOKEN_RESET_ENDPOINT: ${SMQ_TOKEN_RESET_ENDPOINT}
|
||||
SMQ_USERS_HTTP_HOST: ${SMQ_USERS_HTTP_HOST}
|
||||
SMQ_USERS_HTTP_PORT: ${SMQ_USERS_HTTP_PORT}
|
||||
SMQ_USERS_HTTP_SERVER_CERT: ${SMQ_USERS_HTTP_SERVER_CERT}
|
||||
@@ -882,6 +881,7 @@ services:
|
||||
SMQ_SPICEDB_PRE_SHARED_KEY: ${SMQ_SPICEDB_PRE_SHARED_KEY}
|
||||
SMQ_SPICEDB_HOST: ${SMQ_SPICEDB_HOST}
|
||||
SMQ_SPICEDB_PORT: ${SMQ_SPICEDB_PORT}
|
||||
SMQ_PASSWORD_RESET_URL_PREFIX: ${SMQ_PASSWORD_RESET_URL_PREFIX}
|
||||
ports:
|
||||
- ${SMQ_USERS_HTTP_PORT}:${SMQ_USERS_HTTP_PORT}
|
||||
networks:
|
||||
|
||||
@@ -1409,16 +1409,14 @@ func TestResetPasswordRequest(t *testing.T) {
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
svcCall := svc.On("GenerateResetToken", mock.Anything, tc.email, defHost).Return(tc.svcErr)
|
||||
svcCall1 := svc.On("SendPasswordReset", mock.Anything, mock.Anything, tc.email, user.Credentials.Username, tc.issueRes.AccessToken).Return(nil)
|
||||
svcCall := svc.On("SendPasswordReset", mock.Anything, tc.email).Return(tc.svcErr)
|
||||
err := mgsdk.ResetPasswordRequest(context.Background(), tc.email)
|
||||
assert.Equal(t, tc.err, err)
|
||||
if tc.err == nil {
|
||||
ok := svcCall.Parent.AssertCalled(t, "GenerateResetToken", mock.Anything, tc.email, defHost)
|
||||
ok := svcCall.Parent.AssertCalled(t, "SendPasswordReset", mock.Anything, tc.email)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
svcCall.Unset()
|
||||
svcCall1.Unset()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ The service is configured using the environment variables presented in the follo
|
||||
| SMQ_USERS_ADMIN_EMAIL | Default user, created on startup | <admin@example.com> |
|
||||
| SMQ_USERS_ADMIN_PASSWORD | Default user password, created on startup | 12345678 |
|
||||
| SMQ_USERS_PASS_REGEX | Password regex | ^.{8,}$ |
|
||||
| SMQ_TOKEN_RESET_ENDPOINT | Password request reset endpoint, for constructing link | /reset-request |
|
||||
| SMQ_USERS_HTTP_HOST | Users service HTTP host | localhost |
|
||||
| SMQ_USERS_HTTP_PORT | Users service HTTP port | 9002 |
|
||||
| SMQ_USERS_HTTP_SERVER_CERT | Path to the PEM encoded server certificate file | "" |
|
||||
@@ -79,7 +78,6 @@ SMQ_USERS_LOG_LEVEL=info \
|
||||
SMQ_USERS_ADMIN_EMAIL=admin@example.com \
|
||||
SMQ_USERS_ADMIN_PASSWORD=12345678 \
|
||||
SMQ_USERS_PASS_REGEX="^.{8,}$" \
|
||||
SMQ_TOKEN_RESET_ENDPOINT="/reset-request" \
|
||||
SMQ_USERS_HTTP_HOST=localhost \
|
||||
SMQ_USERS_HTTP_PORT=9002 \
|
||||
SMQ_USERS_HTTP_SERVER_CERT="" \
|
||||
|
||||
@@ -1695,14 +1695,6 @@ func TestPasswordResetRequest(t *testing.T) {
|
||||
status: http.StatusBadRequest,
|
||||
err: apiutil.ErrValidation,
|
||||
},
|
||||
{
|
||||
desc: "password reset request with empty host",
|
||||
data: fmt.Sprintf(`{"email": "%s", "host": "%s"}`, testemail, ""),
|
||||
contentType: contentType,
|
||||
referer: "",
|
||||
status: http.StatusBadRequest,
|
||||
err: apiutil.ErrValidation,
|
||||
},
|
||||
{
|
||||
desc: "password reset request with invalid email",
|
||||
data: fmt.Sprintf(`{"email": "%s", "host": "%s"}`, "invalid", testhost),
|
||||
@@ -1749,13 +1741,11 @@ func TestPasswordResetRequest(t *testing.T) {
|
||||
referer: tc.referer,
|
||||
body: strings.NewReader(tc.data),
|
||||
}
|
||||
svcCall := svc.On("GenerateResetToken", mock.Anything, mock.Anything, mock.Anything).Return(tc.generateErr)
|
||||
svcCall1 := svc.On("SendPasswordReset", mock.Anything, mock.Anything, mock.Anything, mock.Anything, validToken).Return(tc.err)
|
||||
svcCall := svc.On("SendPasswordReset", mock.Anything, mock.Anything).Return(tc.generateErr)
|
||||
res, err := req.make()
|
||||
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
|
||||
assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode))
|
||||
svcCall.Unset()
|
||||
svcCall1.Unset()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ func passwordResetRequestEndpoint(svc users.Service) endpoint.Endpoint {
|
||||
return nil, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
|
||||
if err := svc.GenerateResetToken(ctx, req.Email, req.Host); err != nil {
|
||||
if err := svc.SendPasswordReset(ctx, req.Email); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
@@ -284,16 +284,12 @@ func (req tokenReq) validate() error {
|
||||
|
||||
type passResetReq struct {
|
||||
Email string `json:"email"`
|
||||
Host string `json:"host"`
|
||||
}
|
||||
|
||||
func (req passResetReq) validate() error {
|
||||
if req.Email == "" {
|
||||
return apiutil.ErrMissingEmail
|
||||
}
|
||||
if req.Host == "" {
|
||||
return apiutil.ErrMissingHost
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -587,7 +587,6 @@ func TestPasswResetReqValidate(t *testing.T) {
|
||||
desc: "valid request",
|
||||
req: passResetReq{
|
||||
Email: "example@example.com",
|
||||
Host: "example.com",
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
@@ -595,18 +594,9 @@ func TestPasswResetReqValidate(t *testing.T) {
|
||||
desc: "empty email",
|
||||
req: passResetReq{
|
||||
Email: "",
|
||||
Host: "example.com",
|
||||
},
|
||||
err: apiutil.ErrMissingEmail,
|
||||
},
|
||||
{
|
||||
desc: "empty host",
|
||||
req: passResetReq{
|
||||
Email: "example@example.com",
|
||||
Host: "",
|
||||
},
|
||||
err: apiutil.ErrMissingHost,
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
err := c.req.validate()
|
||||
|
||||
@@ -441,7 +441,6 @@ func decodePasswordResetRequest(_ context.Context, r *http.Request) (any, error)
|
||||
return nil, errors.Wrap(apiutil.ErrValidation, errors.Wrap(err, errors.ErrMalformedEntity))
|
||||
}
|
||||
|
||||
req.Host = r.Header.Get("Referer")
|
||||
return req, nil
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -6,5 +6,5 @@ package users
|
||||
// Emailer wrapper around the email.
|
||||
type Emailer interface {
|
||||
// SendPasswordReset sends an email to the user with a link to reset the password.
|
||||
SendPasswordReset(To []string, host, user, token string) error
|
||||
SendPasswordReset(To []string, user, token string) error
|
||||
}
|
||||
|
||||
@@ -20,10 +20,13 @@ type emailer struct {
|
||||
// New creates new emailer utility.
|
||||
func New(url string, c *email.Config) (users.Emailer, error) {
|
||||
e, err := email.New(c)
|
||||
return &emailer{resetURL: url, agent: e}, err
|
||||
return &emailer{
|
||||
resetURL: url,
|
||||
agent: e,
|
||||
}, err
|
||||
}
|
||||
|
||||
func (e *emailer) SendPasswordReset(to []string, host, user, token string) error {
|
||||
url := fmt.Sprintf("%s%s?token=%s", host, e.resetURL, token)
|
||||
func (e *emailer) SendPasswordReset(to []string, user, token string) error {
|
||||
url := fmt.Sprintf("%s?token=%s", e.resetURL, token)
|
||||
return e.agent.Send(to, "", "Password Reset Request", "", user, url, "")
|
||||
}
|
||||
|
||||
+4
-20
@@ -304,19 +304,18 @@ func (es *eventStore) Identify(ctx context.Context, session authn.Session) (stri
|
||||
return userID, nil
|
||||
}
|
||||
|
||||
func (es *eventStore) GenerateResetToken(ctx context.Context, email, host string) error {
|
||||
err := es.svc.GenerateResetToken(ctx, email, host)
|
||||
func (es *eventStore) SendPasswordReset(ctx context.Context, email string) error {
|
||||
err := es.svc.SendPasswordReset(ctx, email)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event := generateResetTokenEvent{
|
||||
event := sendPasswordResetEvent{
|
||||
email: email,
|
||||
host: host,
|
||||
requestID: middleware.GetReqID(ctx),
|
||||
}
|
||||
|
||||
return es.Publish(ctx, resetTokenStream, event)
|
||||
return es.Publish(ctx, sendPasswordResetStream, event)
|
||||
}
|
||||
|
||||
func (es *eventStore) IssueToken(ctx context.Context, username, secret string) (*grpcTokenV1.Token, error) {
|
||||
@@ -366,21 +365,6 @@ func (es *eventStore) ResetSecret(ctx context.Context, session authn.Session, se
|
||||
return es.Publish(ctx, resetSecretStream, event)
|
||||
}
|
||||
|
||||
func (es *eventStore) SendPasswordReset(ctx context.Context, host, email, user, token string) error {
|
||||
if err := es.svc.SendPasswordReset(ctx, host, email, user, token); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
event := sendPasswordResetEvent{
|
||||
host: host,
|
||||
email: email,
|
||||
user: user,
|
||||
requestID: middleware.GetReqID(ctx),
|
||||
}
|
||||
|
||||
return es.Publish(ctx, sendPasswordResetStream, event)
|
||||
}
|
||||
|
||||
func (es *eventStore) OAuthCallback(ctx context.Context, user users.User) (users.User, error) {
|
||||
token, err := es.svc.OAuthCallback(ctx, user)
|
||||
if err != nil {
|
||||
|
||||
@@ -200,8 +200,8 @@ func (am *authorizationMiddleware) UpdateProfilePicture(ctx context.Context, ses
|
||||
return am.svc.UpdateProfilePicture(ctx, session, id, usr)
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) GenerateResetToken(ctx context.Context, email, host string) error {
|
||||
return am.svc.GenerateResetToken(ctx, email, host)
|
||||
func (am *authorizationMiddleware) SendPasswordReset(ctx context.Context, email string) error {
|
||||
return am.svc.SendPasswordReset(ctx, email)
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) UpdateSecret(ctx context.Context, session authn.Session, oldSecret, newSecret string) (users.User, error) {
|
||||
@@ -224,10 +224,6 @@ func (am *authorizationMiddleware) ResetSecret(ctx context.Context, session auth
|
||||
return am.svc.ResetSecret(ctx, session, secret)
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) SendPasswordReset(ctx context.Context, host, email, user, token string) error {
|
||||
return am.svc.SendPasswordReset(ctx, host, email, user, token)
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) UpdateRole(ctx context.Context, session authn.Session, user users.User) (users.User, error) {
|
||||
if session.Type == authn.PersonalAccessToken {
|
||||
if err := am.authz.AuthorizePAT(ctx, smqauthz.PatReq{
|
||||
|
||||
@@ -314,23 +314,22 @@ func (lm *loggingMiddleware) UpdateProfilePicture(ctx context.Context, session a
|
||||
return lm.svc.UpdateProfilePicture(ctx, session, id, user)
|
||||
}
|
||||
|
||||
// GenerateResetToken logs the generate_reset_token request. It logs the time it took to complete the request.
|
||||
// SendPasswordReset logs the send_password_reset request. It logs the time it took to complete the request.
|
||||
// If the request fails, it logs the error.
|
||||
func (lm *loggingMiddleware) GenerateResetToken(ctx context.Context, email, host string) (err error) {
|
||||
func (lm *loggingMiddleware) SendPasswordReset(ctx context.Context, email string) (err error) {
|
||||
defer func(begin time.Time) {
|
||||
args := []any{
|
||||
slog.String("duration", time.Since(begin).String()),
|
||||
slog.String("request_id", middleware.GetReqID(ctx)),
|
||||
slog.String("host", host),
|
||||
}
|
||||
if err != nil {
|
||||
args = append(args, slog.String("error", err.Error()))
|
||||
lm.logger.Warn("Generate reset token failed", args...)
|
||||
return
|
||||
}
|
||||
lm.logger.Info("Generate reset token completed successfully", args...)
|
||||
lm.logger.Info("Send password reset completed successfully", args...)
|
||||
}(time.Now())
|
||||
return lm.svc.GenerateResetToken(ctx, email, host)
|
||||
return lm.svc.SendPasswordReset(ctx, email)
|
||||
}
|
||||
|
||||
// ResetSecret logs the reset_secret request. It logs the time it took to complete the request.
|
||||
@@ -351,25 +350,6 @@ func (lm *loggingMiddleware) ResetSecret(ctx context.Context, session authn.Sess
|
||||
return lm.svc.ResetSecret(ctx, session, secret)
|
||||
}
|
||||
|
||||
// SendPasswordReset logs the send_password_reset request. It logs the time it took to complete the request.
|
||||
// If the request fails, it logs the error.
|
||||
func (lm *loggingMiddleware) SendPasswordReset(ctx context.Context, host, email, user, token string) (err error) {
|
||||
defer func(begin time.Time) {
|
||||
args := []any{
|
||||
slog.String("duration", time.Since(begin).String()),
|
||||
slog.String("request_id", middleware.GetReqID(ctx)),
|
||||
slog.String("host", host),
|
||||
}
|
||||
if err != nil {
|
||||
args = append(args, slog.String("error", err.Error()))
|
||||
lm.logger.Warn("Send password reset failed", args...)
|
||||
return
|
||||
}
|
||||
lm.logger.Info("Send password reset completed successfully", args...)
|
||||
}(time.Now())
|
||||
return lm.svc.SendPasswordReset(ctx, host, email, user, token)
|
||||
}
|
||||
|
||||
// UpdateRole logs the update_user_role request. It logs the user id and the time it took to complete the request.
|
||||
// If the request fails, it logs the error.
|
||||
func (lm *loggingMiddleware) UpdateRole(ctx context.Context, session authn.Session, user users.User) (c users.User, err error) {
|
||||
|
||||
@@ -147,13 +147,13 @@ func (ms *metricsMiddleware) UpdateProfilePicture(ctx context.Context, session a
|
||||
return ms.svc.UpdateProfilePicture(ctx, session, id, user)
|
||||
}
|
||||
|
||||
// GenerateResetToken instruments GenerateResetToken method with metrics.
|
||||
func (ms *metricsMiddleware) GenerateResetToken(ctx context.Context, email, host string) error {
|
||||
// SendPasswordReset instruments SendPasswordReset method with metrics.
|
||||
func (ms *metricsMiddleware) SendPasswordReset(ctx context.Context, email string) error {
|
||||
defer func(begin time.Time) {
|
||||
ms.counter.With("method", "generate_reset_token").Add(1)
|
||||
ms.latency.With("method", "generate_reset_token").Observe(time.Since(begin).Seconds())
|
||||
ms.counter.With("method", "send_password_reset").Add(1)
|
||||
ms.latency.With("method", "send_password_reset").Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
return ms.svc.GenerateResetToken(ctx, email, host)
|
||||
return ms.svc.SendPasswordReset(ctx, email)
|
||||
}
|
||||
|
||||
// ResetSecret instruments ResetSecret method with metrics.
|
||||
@@ -165,15 +165,6 @@ func (ms *metricsMiddleware) ResetSecret(ctx context.Context, session authn.Sess
|
||||
return ms.svc.ResetSecret(ctx, session, secret)
|
||||
}
|
||||
|
||||
// SendPasswordReset instruments SendPasswordReset method with metrics.
|
||||
func (ms *metricsMiddleware) SendPasswordReset(ctx context.Context, host, email, user, token string) error {
|
||||
defer func(begin time.Time) {
|
||||
ms.counter.With("method", "send_password_reset").Add(1)
|
||||
ms.latency.With("method", "send_password_reset").Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
return ms.svc.SendPasswordReset(ctx, host, email, user, token)
|
||||
}
|
||||
|
||||
// UpdateRole instruments UpdateRole method with metrics.
|
||||
func (ms *metricsMiddleware) UpdateRole(ctx context.Context, session authn.Session, user users.User) (users.User, error) {
|
||||
defer func(begin time.Time) {
|
||||
|
||||
+8
-14
@@ -39,16 +39,16 @@ func (_m *Emailer) EXPECT() *Emailer_Expecter {
|
||||
}
|
||||
|
||||
// SendPasswordReset provides a mock function for the type Emailer
|
||||
func (_mock *Emailer) SendPasswordReset(To []string, host string, user string, token string) error {
|
||||
ret := _mock.Called(To, host, user, token)
|
||||
func (_mock *Emailer) SendPasswordReset(To []string, user string, token string) error {
|
||||
ret := _mock.Called(To, user, token)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for SendPasswordReset")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if returnFunc, ok := ret.Get(0).(func([]string, string, string, string) error); ok {
|
||||
r0 = returnFunc(To, host, user, token)
|
||||
if returnFunc, ok := ret.Get(0).(func([]string, string, string) error); ok {
|
||||
r0 = returnFunc(To, user, token)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
@@ -62,14 +62,13 @@ type Emailer_SendPasswordReset_Call struct {
|
||||
|
||||
// SendPasswordReset is a helper method to define mock.On call
|
||||
// - To []string
|
||||
// - host string
|
||||
// - user string
|
||||
// - token string
|
||||
func (_e *Emailer_Expecter) SendPasswordReset(To interface{}, host interface{}, user interface{}, token interface{}) *Emailer_SendPasswordReset_Call {
|
||||
return &Emailer_SendPasswordReset_Call{Call: _e.mock.On("SendPasswordReset", To, host, user, token)}
|
||||
func (_e *Emailer_Expecter) SendPasswordReset(To interface{}, user interface{}, token interface{}) *Emailer_SendPasswordReset_Call {
|
||||
return &Emailer_SendPasswordReset_Call{Call: _e.mock.On("SendPasswordReset", To, user, token)}
|
||||
}
|
||||
|
||||
func (_c *Emailer_SendPasswordReset_Call) Run(run func(To []string, host string, user string, token string)) *Emailer_SendPasswordReset_Call {
|
||||
func (_c *Emailer_SendPasswordReset_Call) Run(run func(To []string, user string, token string)) *Emailer_SendPasswordReset_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
var arg0 []string
|
||||
if args[0] != nil {
|
||||
@@ -83,15 +82,10 @@ func (_c *Emailer_SendPasswordReset_Call) Run(run func(To []string, host string,
|
||||
if args[2] != nil {
|
||||
arg2 = args[2].(string)
|
||||
}
|
||||
var arg3 string
|
||||
if args[3] != nil {
|
||||
arg3 = args[3].(string)
|
||||
}
|
||||
run(
|
||||
arg0,
|
||||
arg1,
|
||||
arg2,
|
||||
arg3,
|
||||
)
|
||||
})
|
||||
return _c
|
||||
@@ -102,7 +96,7 @@ func (_c *Emailer_SendPasswordReset_Call) Return(err error) *Emailer_SendPasswor
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Emailer_SendPasswordReset_Call) RunAndReturn(run func(To []string, host string, user string, token string) error) *Emailer_SendPasswordReset_Call {
|
||||
func (_c *Emailer_SendPasswordReset_Call) RunAndReturn(run func(To []string, user string, token string) error) *Emailer_SendPasswordReset_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
+8
-89
@@ -250,69 +250,6 @@ func (_c *Service_Enable_Call) RunAndReturn(run func(ctx context.Context, sessio
|
||||
return _c
|
||||
}
|
||||
|
||||
// GenerateResetToken provides a mock function for the type Service
|
||||
func (_mock *Service) GenerateResetToken(ctx context.Context, email string, host string) error {
|
||||
ret := _mock.Called(ctx, email, host)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GenerateResetToken")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, string, string) error); ok {
|
||||
r0 = returnFunc(ctx, email, host)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
return r0
|
||||
}
|
||||
|
||||
// Service_GenerateResetToken_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GenerateResetToken'
|
||||
type Service_GenerateResetToken_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GenerateResetToken is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - email string
|
||||
// - host string
|
||||
func (_e *Service_Expecter) GenerateResetToken(ctx interface{}, email interface{}, host interface{}) *Service_GenerateResetToken_Call {
|
||||
return &Service_GenerateResetToken_Call{Call: _e.mock.On("GenerateResetToken", ctx, email, host)}
|
||||
}
|
||||
|
||||
func (_c *Service_GenerateResetToken_Call) Run(run func(ctx context.Context, email string, host string)) *Service_GenerateResetToken_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
var arg0 context.Context
|
||||
if args[0] != nil {
|
||||
arg0 = args[0].(context.Context)
|
||||
}
|
||||
var arg1 string
|
||||
if args[1] != nil {
|
||||
arg1 = args[1].(string)
|
||||
}
|
||||
var arg2 string
|
||||
if args[2] != nil {
|
||||
arg2 = args[2].(string)
|
||||
}
|
||||
run(
|
||||
arg0,
|
||||
arg1,
|
||||
arg2,
|
||||
)
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Service_GenerateResetToken_Call) Return(err error) *Service_GenerateResetToken_Call {
|
||||
_c.Call.Return(err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Service_GenerateResetToken_Call) RunAndReturn(run func(ctx context.Context, email string, host string) error) *Service_GenerateResetToken_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Identify provides a mock function for the type Service
|
||||
func (_mock *Service) Identify(ctx context.Context, session authn.Session) (string, error) {
|
||||
ret := _mock.Called(ctx, session)
|
||||
@@ -930,16 +867,16 @@ func (_c *Service_SearchUsers_Call) RunAndReturn(run func(ctx context.Context, p
|
||||
}
|
||||
|
||||
// SendPasswordReset provides a mock function for the type Service
|
||||
func (_mock *Service) SendPasswordReset(ctx context.Context, host string, email string, user string, token string) error {
|
||||
ret := _mock.Called(ctx, host, email, user, token)
|
||||
func (_mock *Service) SendPasswordReset(ctx context.Context, email string) error {
|
||||
ret := _mock.Called(ctx, email)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for SendPasswordReset")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, string, string, string, string) error); ok {
|
||||
r0 = returnFunc(ctx, host, email, user, token)
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, string) error); ok {
|
||||
r0 = returnFunc(ctx, email)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
@@ -953,15 +890,12 @@ type Service_SendPasswordReset_Call struct {
|
||||
|
||||
// SendPasswordReset is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - host string
|
||||
// - email string
|
||||
// - user string
|
||||
// - token string
|
||||
func (_e *Service_Expecter) SendPasswordReset(ctx interface{}, host interface{}, email interface{}, user interface{}, token interface{}) *Service_SendPasswordReset_Call {
|
||||
return &Service_SendPasswordReset_Call{Call: _e.mock.On("SendPasswordReset", ctx, host, email, user, token)}
|
||||
func (_e *Service_Expecter) SendPasswordReset(ctx interface{}, email interface{}) *Service_SendPasswordReset_Call {
|
||||
return &Service_SendPasswordReset_Call{Call: _e.mock.On("SendPasswordReset", ctx, email)}
|
||||
}
|
||||
|
||||
func (_c *Service_SendPasswordReset_Call) Run(run func(ctx context.Context, host string, email string, user string, token string)) *Service_SendPasswordReset_Call {
|
||||
func (_c *Service_SendPasswordReset_Call) Run(run func(ctx context.Context, email string)) *Service_SendPasswordReset_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
var arg0 context.Context
|
||||
if args[0] != nil {
|
||||
@@ -971,24 +905,9 @@ func (_c *Service_SendPasswordReset_Call) Run(run func(ctx context.Context, host
|
||||
if args[1] != nil {
|
||||
arg1 = args[1].(string)
|
||||
}
|
||||
var arg2 string
|
||||
if args[2] != nil {
|
||||
arg2 = args[2].(string)
|
||||
}
|
||||
var arg3 string
|
||||
if args[3] != nil {
|
||||
arg3 = args[3].(string)
|
||||
}
|
||||
var arg4 string
|
||||
if args[4] != nil {
|
||||
arg4 = args[4].(string)
|
||||
}
|
||||
run(
|
||||
arg0,
|
||||
arg1,
|
||||
arg2,
|
||||
arg3,
|
||||
arg4,
|
||||
)
|
||||
})
|
||||
return _c
|
||||
@@ -999,7 +918,7 @@ func (_c *Service_SendPasswordReset_Call) Return(err error) *Service_SendPasswor
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Service_SendPasswordReset_Call) RunAndReturn(run func(ctx context.Context, host string, email string, user string, token string) error) *Service_SendPasswordReset_Call {
|
||||
func (_c *Service_SendPasswordReset_Call) RunAndReturn(run func(ctx context.Context, email string) error) *Service_SendPasswordReset_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
+2
-7
@@ -269,7 +269,7 @@ func (svc service) UpdateEmail(ctx context.Context, session authn.Session, userI
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func (svc service) GenerateResetToken(ctx context.Context, email, host string) error {
|
||||
func (svc service) SendPasswordReset(ctx context.Context, email string) error {
|
||||
user, err := svc.users.RetrieveByEmail(ctx, email)
|
||||
if err != nil {
|
||||
return errors.Wrap(svcerr.ErrViewEntity, err)
|
||||
@@ -284,7 +284,7 @@ func (svc service) GenerateResetToken(ctx context.Context, email, host string) e
|
||||
return errors.Wrap(errRecoveryToken, err)
|
||||
}
|
||||
|
||||
return svc.SendPasswordReset(ctx, host, email, user.Credentials.Username, token.AccessToken)
|
||||
return svc.email.SendPasswordReset([]string{email}, user.Credentials.Username, token.AccessToken)
|
||||
}
|
||||
|
||||
func (svc service) ResetSecret(ctx context.Context, session authn.Session, secret string) error {
|
||||
@@ -358,11 +358,6 @@ func (svc service) UpdateUsername(ctx context.Context, session authn.Session, id
|
||||
return updatedUser, nil
|
||||
}
|
||||
|
||||
func (svc service) SendPasswordReset(_ context.Context, host, email, user, token string) error {
|
||||
to := []string{email}
|
||||
return svc.email.SendPasswordReset(to, host, user, token)
|
||||
}
|
||||
|
||||
func (svc service) UpdateRole(ctx context.Context, session authn.Session, usr User) (User, error) {
|
||||
if err := svc.checkSuperAdmin(ctx, session); err != nil {
|
||||
return User{}, err
|
||||
|
||||
@@ -1526,13 +1526,12 @@ func TestRefreshToken(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateResetToken(t *testing.T) {
|
||||
func TestSendPasswordReset(t *testing.T) {
|
||||
svc, auth, cRepo, _, e := newService()
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
email string
|
||||
host string
|
||||
retrieveByEmailResponse users.User
|
||||
issueResponse *grpcTokenV1.Token
|
||||
retrieveByEmailErr error
|
||||
@@ -1542,7 +1541,6 @@ func TestGenerateResetToken(t *testing.T) {
|
||||
{
|
||||
desc: "generate reset token for existing user",
|
||||
email: "existingemail@example.com",
|
||||
host: "examplehost",
|
||||
retrieveByEmailResponse: user,
|
||||
issueResponse: &grpcTokenV1.Token{AccessToken: validToken, RefreshToken: &validToken, AccessType: "3"},
|
||||
err: nil,
|
||||
@@ -1550,7 +1548,6 @@ func TestGenerateResetToken(t *testing.T) {
|
||||
{
|
||||
desc: "generate reset token for user with non-existing user",
|
||||
email: "example@example.com",
|
||||
host: "examplehost",
|
||||
retrieveByEmailResponse: users.User{
|
||||
ID: testsutil.GenerateUUID(t),
|
||||
Email: "",
|
||||
@@ -1561,7 +1558,6 @@ func TestGenerateResetToken(t *testing.T) {
|
||||
{
|
||||
desc: "generate reset token with failed to issue token",
|
||||
email: "existingemail@example.com",
|
||||
host: "examplehost",
|
||||
retrieveByEmailResponse: user,
|
||||
issueResponse: &grpcTokenV1.Token{},
|
||||
issueErr: svcerr.ErrAuthorization,
|
||||
@@ -1573,8 +1569,8 @@ func TestGenerateResetToken(t *testing.T) {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
repoCall := cRepo.On("RetrieveByEmail", context.Background(), tc.email).Return(tc.retrieveByEmailResponse, tc.retrieveByEmailErr)
|
||||
authCall := auth.On("Issue", context.Background(), mock.Anything).Return(tc.issueResponse, tc.issueErr)
|
||||
svcCall := e.On("SendPasswordReset", []string{tc.email}, tc.host, user.Credentials.Username, validToken).Return(tc.err)
|
||||
err := svc.GenerateResetToken(context.Background(), tc.email, tc.host)
|
||||
svcCall := e.On("SendPasswordReset", []string{tc.email}, user.Credentials.Username, validToken).Return(tc.err)
|
||||
err := svc.SendPasswordReset(context.Background(), tc.email)
|
||||
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
||||
repoCall.Parent.AssertCalled(t, "RetrieveByEmail", context.Background(), tc.email)
|
||||
repoCall.Unset()
|
||||
|
||||
@@ -145,15 +145,14 @@ func (tm *tracingMiddleware) UpdateProfilePicture(ctx context.Context, session a
|
||||
return tm.svc.UpdateProfilePicture(ctx, session, id, usr)
|
||||
}
|
||||
|
||||
// GenerateResetToken traces the "GenerateResetToken" operation of the wrapped users.Service.
|
||||
func (tm *tracingMiddleware) GenerateResetToken(ctx context.Context, email, host string) error {
|
||||
ctx, span := tracing.StartSpan(ctx, tm.tracer, "svc_generate_reset_token", trace.WithAttributes(
|
||||
// SendPasswordReset traces the "SendPasswordReset" operation of the wrapped users.Service.
|
||||
func (tm *tracingMiddleware) SendPasswordReset(ctx context.Context, email string) error {
|
||||
ctx, span := tracing.StartSpan(ctx, tm.tracer, "svc_send_password_reset", trace.WithAttributes(
|
||||
attribute.String("email", email),
|
||||
attribute.String("host", host),
|
||||
))
|
||||
defer span.End()
|
||||
|
||||
return tm.svc.GenerateResetToken(ctx, email, host)
|
||||
return tm.svc.SendPasswordReset(ctx, email)
|
||||
}
|
||||
|
||||
// ResetSecret traces the "ResetSecret" operation of the wrapped users.Service.
|
||||
@@ -164,17 +163,6 @@ func (tm *tracingMiddleware) ResetSecret(ctx context.Context, session authn.Sess
|
||||
return tm.svc.ResetSecret(ctx, session, secret)
|
||||
}
|
||||
|
||||
// SendPasswordReset traces the "SendPasswordReset" operation of the wrapped users.Service.
|
||||
func (tm *tracingMiddleware) SendPasswordReset(ctx context.Context, host, email, user, token string) error {
|
||||
ctx, span := tracing.StartSpan(ctx, tm.tracer, "svc_send_password_reset", trace.WithAttributes(
|
||||
attribute.String("email", email),
|
||||
attribute.String("user", user),
|
||||
))
|
||||
defer span.End()
|
||||
|
||||
return tm.svc.SendPasswordReset(ctx, host, email, user, token)
|
||||
}
|
||||
|
||||
// ViewProfile traces the "ViewProfile" operation of the wrapped users.Service.
|
||||
func (tm *tracingMiddleware) ViewProfile(ctx context.Context, session authn.Session) (users.User, error) {
|
||||
ctx, span := tracing.StartSpan(ctx, tm.tracer, "svc_view_profile")
|
||||
|
||||
+2
-6
@@ -179,9 +179,8 @@ type Service interface {
|
||||
// UpdateProfilePicture updates the user's profile picture.
|
||||
UpdateProfilePicture(ctx context.Context, session authn.Session, id string, usr UserReq) (User, error)
|
||||
|
||||
// GenerateResetToken email where mail will be sent.
|
||||
// host is used for generating reset link.
|
||||
GenerateResetToken(ctx context.Context, email, host string) error
|
||||
// SendPasswordReset generates reset password link and sends it to the user via email.
|
||||
SendPasswordReset(ctx context.Context, email string) error
|
||||
|
||||
// UpdateSecret updates the user's secret.
|
||||
UpdateSecret(ctx context.Context, session authn.Session, oldSecret, newSecret string) (User, error)
|
||||
@@ -190,9 +189,6 @@ type Service interface {
|
||||
// token can be authentication token or secret reset token.
|
||||
ResetSecret(ctx context.Context, session authn.Session, secret string) error
|
||||
|
||||
// SendPasswordReset sends reset password link to email.
|
||||
SendPasswordReset(ctx context.Context, host, email, user, token string) error
|
||||
|
||||
// UpdateRole updates the user's Role.
|
||||
UpdateRole(ctx context.Context, session authn.Session, user User) (User, error)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user