Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added update token command #22

Merged
merged 3 commits into from
Dec 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions internal/storage/postgres/company/company.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const (
addCompany = "INSERT INTO companies (token, owner_id, name, email) VALUES ($1, $2, $3, $4) RETURNING id, token, owner_id, name, email"
getCompanyByOwnerId = "SELECT c.id, c.token, c.owner_id, c.name, c.email FROM companies AS c INNER JOIN owners As o ON o.id = c.owner_id WHERE o.telegram_id=$1"
getCompanyIdByName = "SELECT id FROM companies WHERE name=$1"
updateToken = "UPDATE companies SET token=$1 WHERE id=$2"
)

// AddCompany adds a new company to the database and returns the newly created company.
Expand Down Expand Up @@ -61,3 +62,15 @@ func (s *CompanyStorage) GetCompanyByOwnerTelegramId(ctx context.Context, ownerI

return company, nil
}

// UpdateToken updates the company's token.
func (s *CompanyStorage) UpdateToken(ctx context.Context, companyId int64, token string) error {
const op = "storage.postgres.UpdateToken"

_, err := s.db.ExecContext(ctx, updateToken, token, companyId)
if err != nil {
return fmt.Errorf("%s: execute query: %w", op, err)
}

return nil
}
69 changes: 69 additions & 0 deletions internal/storage/postgres/company/company_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,3 +148,72 @@ func TestCompanyStorage_GetCompanyByOwnerTelegramId(t *testing.T) {
assert.Equal(t, entities.Company{}, company)
})
}

func TestCompanyStorage_UpdateToken(t *testing.T) {
t.Run("with company", func(t *testing.T) {
// Arrange
t.Parallel()
f := database.NewFixture(t)
defer f.Teardown()

var companyID int64 = 12
var token = "bguFFFTF&32r23r23t"

f.Mock.ExpectExec(regexp.QuoteMeta("UPDATE companies SET token=$1 WHERE id=$2")).
WithArgs(token, companyID).
WillReturnResult(sqlmock.NewResult(1, 1))

repo := New(f.DB)

// Act
err := repo.UpdateToken(context.Background(), companyID, token)

// Assert
assert.NoError(t, err)
})

t.Run("without company", func(t *testing.T) {
// Arrange
t.Parallel()
f := database.NewFixture(t)
defer f.Teardown()

var companyID int64 = 12
var token = "bguFFFTF&32r23r23t"

f.Mock.ExpectExec(regexp.QuoteMeta("UPDATE companies SET token=$1 WHERE id=$2")).
WithArgs(token, companyID).
WillReturnResult(sqlmock.NewResult(0, 0))

repo := New(f.DB)

// Act
err := repo.UpdateToken(context.Background(), companyID, token)

// Assert
assert.NoError(t, err)
})

t.Run("with error", func(t *testing.T) {
// Arrange
t.Parallel()
f := database.NewFixture(t)
defer f.Teardown()

expectErr := errors.New("test error")

var companyID int64 = 12
var token = "bguFFFTF&32r23r23t"

f.Mock.ExpectExec(regexp.QuoteMeta("UPDATE companies SET token=$1 WHERE id=$2")).
WithArgs(token, companyID).
WillReturnError(expectErr)
repo := New(f.DB)

// Act
err := repo.UpdateToken(context.Background(), companyID, token)

// Assert
assert.ErrorIs(t, err, expectErr)
})
}
28 changes: 28 additions & 0 deletions internal/transport/telegram/commands/company.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

type companyUsesaces interface {
GetCompanyByOwnerTelegramId(ctx context.Context, ownerId int64) (entities.CompanyInfo, error)
UpdateToken(ctx context.Context, ownerId int64) error
}

// CompanyCommands represents a set of commands related to companies.
Expand Down Expand Up @@ -67,3 +68,30 @@ func (c *CompanyCommands) GetMyCompanies(m *tgbotapi.Message) (tgbotapi.MessageC

return msg, nil
}

// UpdateToken updates the token of the company owned by the user who sent the message.
// If the user does not own any companies, the message will indicate that they have no companies and provide a command to register a new one.
// If an error occurs while retrieving the company information, an error message will be returned.
func (c *CompanyCommands) UpdateToken(m *tgbotapi.Message) (tgbotapi.MessageConfig, error) {
const op = "CompanyCommands.UpdateToken"

msg := tgbotapi.NewMessage(m.Chat.ID, "")
msg.ParseMode = tgbotapi.ModeHTML

err := c.cu.UpdateToken(context.Background(), m.From.ID)
if err != nil {
if errors.Is(err, usecases.ErrCompanyNotFound) {
msg.Text = `
<b>You have no companies</b>

You can register new company with <b>/register</b> command
`
return msg, nil
}
msg.Text = "Something went wrong. Lets try again"
return msg, fmt.Errorf("%s: update token: %w", op, err)
}

msg.Text = "Token updated successfully"
return msg, nil
}
1 change: 1 addition & 0 deletions internal/transport/telegram/commands/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ func GetHelpMessage(m *tgbotapi.Message) tgbotapi.MessageConfig {
/getchatid - show chat ID
/register - register new company
/getcompany - show registered company
/updatetoken - update company token
/addchat {chat_id} - add chat to company, for example: /addchat 123456789
/deletechat {chat_id} - delete chat from company, for example: /deletechat 123456789
`)
Expand Down
24 changes: 17 additions & 7 deletions internal/transport/telegram/telegram.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@ import (
)

const (
rigesterCommand = "register"
getChatIdCommand = "getchatid"
getCompanyCommand = "getcompany"
addChatCommand = "addchat"
helpCommand = "help"
deleteChatCommand = "deletechat"
startCommand = "start"
rigesterCommand = "register"
getChatIdCommand = "getchatid"
getCompanyCommand = "getcompany"
addChatCommand = "addchat"
helpCommand = "help"
deleteChatCommand = "deletechat"
startCommand = "start"
updateTokenCommand = "updatetoken"
)

type registrator interface {
Expand All @@ -29,6 +30,7 @@ type registrator interface {

type companyCommands interface {
GetMyCompanies(m *tgbotapi.Message) (tgbotapi.MessageConfig, error)
UpdateToken(m *tgbotapi.Message) (tgbotapi.MessageConfig, error)
}

type chatCommands interface {
Expand Down Expand Up @@ -124,6 +126,14 @@ func (b *TelegramBot) Run() {
}
b.sendMessage(msg)
continue

case updateTokenCommand:
msg, err := b.cc.UpdateToken(update.Message)
if err != nil {
b.logger.Error("cannot update token", sl.Err(err))
}
b.sendMessage(msg)
continue
case addChatCommand:
msg, err := b.chc.AddChat(update.Message)
if err != nil {
Expand Down
24 changes: 24 additions & 0 deletions internal/usecases/company.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ import (
"fmt"

"github.com/testit-tms/webhook-bot/internal/entities"
"github.com/testit-tms/webhook-bot/internal/lib/random"
"github.com/testit-tms/webhook-bot/internal/storage"
)

//go:generate mockgen -source=$GOFILE -destination=$PWD/mocks/${GOFILE} -package=mocks
type companyStorage interface {
GetCompanyByOwnerTelegramId(ctx context.Context, ownerId int64) (entities.Company, error)
UpdateToken(ctx context.Context, companyId int64, token string) error
}

//go:generate mockgen -source=$GOFILE -destination=$PWD/mocks/${GOFILE} -package=mocks
Expand Down Expand Up @@ -72,3 +74,25 @@ func (u *companyUsecases) GetCompanyByOwnerTelegramId(ctx context.Context, owner

return ci, nil
}

// UpdateToken updates the company token.
// It returns an error if the company is not found.
func (u *companyUsecases) UpdateToken(ctx context.Context, ownerId int64) error {
const op = "usecases.UpdateToken"

company, err := u.cs.GetCompanyByOwnerTelegramId(ctx, ownerId)
if err != nil {
if errors.Is(err, storage.ErrNotFound) {
return fmt.Errorf("%s: %w", op, ErrCompanyNotFound)
}
return fmt.Errorf("%s: get company by owner id: %w", op, err)
}

token := random.NewRandomString(30)

if err := u.cs.UpdateToken(ctx, company.ID, token); err != nil {
return fmt.Errorf("%s: update token: %w", op, err)
}

return nil
}
81 changes: 81 additions & 0 deletions internal/usecases/company_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,84 @@ func Test_companyUsecases_GetCompanyByOwnerId(t *testing.T) {
})
}
}

func Test_companyUsecases_UpdateToken(t *testing.T) {
tests := []struct {
name string
ownerId int64
wantErr bool
mockCompEntities entities.Company
mockCompError error
mockCompTimes int
mockUpdateTokenError error
mockUpdateTokenTimes int
}{
{
name: "success",
ownerId: 1,
wantErr: false,
mockCompEntities: entities.Company{
ID: 12,
OwnerID: 21,
Token: "token",
Name: "Yandex",
Email: "",
},
mockCompError: nil,
mockCompTimes: 1,
mockUpdateTokenError: nil,
mockUpdateTokenTimes: 1,
},
{
name: "company with ErrNotFound",
ownerId: 1,
wantErr: true,
mockCompEntities: entities.Company{},
mockCompError: storage.ErrNotFound,
mockCompTimes: 1,
},
{
name: "company with other error",
ownerId: 1,
wantErr: true,
mockCompEntities: entities.Company{},
mockCompError: errors.New("test error"),
mockCompTimes: 1,
},
{
name: "update token with error",
wantErr: true,
mockCompEntities: entities.Company{
ID: 12,
OwnerID: 21,
Token: "token",
Name: "Yandex",
Email: "",
},
mockCompError: nil,
mockCompTimes: 1,
mockUpdateTokenError: errors.New("test error"),
mockUpdateTokenTimes: 1,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mockCtrl := gomock.NewController(t)
companyMock := mocks.NewMockcompanyStorage(mockCtrl)
companyMock.EXPECT().GetCompanyByOwnerTelegramId(gomock.Any(), tt.ownerId).Return(tt.mockCompEntities, tt.mockCompError).Times(tt.mockCompTimes)
if tt.mockCompError == nil {
companyMock.EXPECT().UpdateToken(gomock.Any(), tt.mockCompEntities.ID, gomock.Any()).Return(tt.mockUpdateTokenError).Times(tt.mockUpdateTokenTimes)
}

u := NewCompanyUsecases(companyMock, nil)

err := u.UpdateToken(context.Background(), tt.ownerId)
if err != nil {
if !tt.wantErr {
t.Errorf("companyUsecases.UpdateToken() error = %v, wantErr %v", err, tt.wantErr)
return
}
}
})
}
}
14 changes: 14 additions & 0 deletions internal/usecases/mocks/company.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions makefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ test:
coverage:
go test -v ./... -coverprofile=coverage.out
go tool cover -func ./coverage.out
go tool cover -html ./coverage.out

.PHONY: lint
lint:
Expand Down
Loading