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

Task/query #26

Open
wants to merge 2 commits into
base: stage
Choose a base branch
from
Open
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
91 changes: 45 additions & 46 deletions db/migrations/01_up.sql
Original file line number Diff line number Diff line change
@@ -1,81 +1,80 @@
CREATE TABLE IF NOT EXISTS users
CREATE TABLE IF NOT EXISTS "user"
(
id SERIAL PRIMARY KEY, -- Уникальный идентификатор пользователя
email VARCHAR(255) NOT NULL UNIQUE, -- Email пользователя
login VARCHAR(255) NOT NULL UNIQUE, -- Логин пользователя
email TEXT NOT NULL,
password VARCHAR(255) NOT NULL, -- Хэш пароля
id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY, -- Уникальный идентификатор пользователя
login TEXT UNIQUE NOT NULL, -- Логин пользователя
email TEXT NOT NULL, -- Email пользователя
password TEXT NOT NULL, -- Хэш пароля
created_at TIMESTAMP NOT NULL DEFAULT NOW() -- Дата создания пользователя
);

CREATE TABLE IF NOT EXISTS cities
CREATE TABLE IF NOT EXISTS city
(
id SERIAL PRIMARY KEY, -- Уникальный идентификатор города
name VARCHAR(255) NOT NULL, -- Название города
id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY, -- Уникальный идентификатор города
name TEXT NOT NULL, -- Название города
created_at TIMESTAMP NOT NULL DEFAULT NOW() -- Дата создания города
);

CREATE TABLE IF NOT EXISTS places
CREATE TABLE IF NOT EXISTS place
(
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL, -- название места
imagePath VARCHAR(255) NOT NULL, -- путь к картинке
description TEXT NOT NULL, -- описание места
rating INT NOT NULL, -- рейтинг места
numberOfReviews INT NOT NULL, -- количество отзывов
address VARCHAR(255) NOT NULL, -- адрес места
id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name TEXT NOT NULL, -- название места
imagePath TEXT NOT NULL DEFAULT '', -- путь к картинке
description TEXT NOT NULL DEFAULT '', -- описание места
rating INT NOT NULL DEFAULT 0, -- рейтинг места
numberOfReviews INT NOT NULL DEFAULT 0, -- количество отзывов
address TEXT NOT NULL DEFAULT '', -- адрес места
cityId INT NOT NULL, -- город, где находится место
phoneNumber VARCHAR(10), -- номер телефона
FOREIGN KEY (cityId) REFERENCES cities(id) ON DELETE CASCADE
phoneNumber TEXT DEFAULT '', -- номер телефона
FOREIGN KEY (cityId) REFERENCES city(id) ON DELETE CASCADE
);

CREATE TABLE IF NOT EXISTS reviews
CREATE TABLE IF NOT EXISTS review
(
id SERIAL PRIMARY KEY, -- Уникальный идентификатор отзыва
user_id INT REFERENCES users(id), -- Идентификатор пользователя, который оставил отзыв
place_id INT REFERENCES places(id), -- Идентификатор места, к которому относится отзыв
rating INT NOT NULL CHECK (rating BETWEEN 1 AND 5), -- Рейтинг места (от 1 до 5)
review_text TEXT, -- Текст отзыва
id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY, -- Уникальный идентификатор отзыва
user_id INT REFERENCES "user"(id) NOT NULL, -- Идентификатор пользователя, который оставил отзыв
place_id INT REFERENCES place(id) NOT NULL, -- Идентификатор места, к которому относится отзыв
rating INT NOT NULL CHECK (rating BETWEEN 1 AND 5) DEFAULT 0, -- Рейтинг места (от 1 до 5)
review_text TEXT DEFAULT '', -- Текст отзыва
created_at TIMESTAMP NOT NULL DEFAULT NOW(), -- Дата создания отзыва
CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
CONSTRAINT fk_place FOREIGN KEY (place_id) REFERENCES places(id) ON DELETE CASCADE
CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES "user"(id) ON DELETE CASCADE,
CONSTRAINT fk_place FOREIGN KEY (place_id) REFERENCES place(id) ON DELETE CASCADE
);

CREATE TABLE IF NOT EXISTS categories
CREATE TABLE IF NOT EXISTS category
(
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL
id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name TEXT NOT NULL DEFAULT ''
);

CREATE TABLE IF NOT EXISTS places_categories
CREATE TABLE IF NOT EXISTS place_category
(
place_id INT NOT NULL,
category_id INT NOT NULL,
PRIMARY KEY(place_id, category_id),
FOREIGN KEY (place_id) REFERENCES places(id) ON DELETE CASCADE,
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE
FOREIGN KEY (place_id) REFERENCES place(id) ON DELETE CASCADE,
FOREIGN KEY (category_id) REFERENCES category(id) ON DELETE CASCADE
);

CREATE TABLE IF NOT EXISTS trips
CREATE TABLE IF NOT EXISTS trip
(
id SERIAL PRIMARY KEY, -- Уникальный идентификатор поездки
name VARCHAR(255) NOT NULL, -- Название поездки
description VARCHAR(1000), -- Описание поездки
id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY, -- Уникальный идентификатор поездки
name TEXT NOT NULL, -- Название поездки
description TEXT DEFAULT '', -- Описание поездки
city_id INTEGER NOT NULL, -- Направление поездки
start_date DATE, -- Дата начала поездки
end_date DATE, -- Дата окончания поездки
private BOOLEAN DEFAULT TRUE, -- Кому видна поездка (всем или выбранным пользователям)
start_date DATE NOT NULL, -- Дата начала поездки
end_date DATE NOT NULL, -- Дата окончания поездки
private BOOLEAN NOT NULL DEFAULT TRUE, -- Кому видна поездка (всем или выбранным пользователям)
created_at TIMESTAMP NOT NULL DEFAULT NOW(), -- Дата создания поездки
user_id INTEGER NOT NULL, -- Идентификатор пользователя-создателя поездки
CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
CONSTRAINT fk_city FOREIGN KEY (city_id) REFERENCES cities(id) ON DELETE CASCADE
CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES "user"(id) ON DELETE CASCADE,
CONSTRAINT fk_city FOREIGN KEY (city_id) REFERENCES city(id) ON DELETE CASCADE
);

CREATE TABLE IF NOT EXISTS trips_places ( --таблица для сопоставления поездки и достопримечательности, которая в нее входит
id SERIAL PRIMARY KEY,
CREATE TABLE IF NOT EXISTS trip_place ( --таблица для сопоставления поездки и достопримечательности, которая в нее входит
id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
trip_id INT NOT NULL, -- Идентификатор поездки
place_id INT NOT NULL, -- Идентификатор города
created_at TIMESTAMP NOT NULL DEFAULT NOW(), -- Дата создания записи
FOREIGN KEY (trip_id) REFERENCES trips(id) ON DELETE CASCADE,
FOREIGN KEY (place_id) REFERENCES places(id) ON DELETE CASCADE
FOREIGN KEY (trip_id) REFERENCES trip(id) ON DELETE CASCADE,
FOREIGN KEY (place_id) REFERENCES place(id) ON DELETE CASCADE
);
4 changes: 4 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,21 @@ require (

require (
github.com/KyleBanks/depth v1.2.1 // indirect
github.com/Masterminds/squirrel v1.5.4 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference v0.21.0 // indirect
github.com/go-openapi/spec v0.21.0 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/swaggo/files v1.0.1 // indirect
github.com/swaggo/swag v1.16.3 // indirect
golang.org/x/net v0.30.0 // indirect
golang.org/x/tools v0.26.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
github.com/Masterminds/squirrel v1.5.4
)
7 changes: 7 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7Oputl
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM=
github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
Expand All @@ -25,6 +27,10 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw=
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o=
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk=
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
Expand All @@ -33,6 +39,7 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE=
Expand Down
76 changes: 65 additions & 11 deletions internal/pkg/auth/repo/auth_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
"database/sql"
"errors"
"fmt"

"github.com/Masterminds/squirrel"
"github.com/lib/pq"
_ "github.com/lib/pq"
)
Expand All @@ -19,8 +21,18 @@
}

func (r *RepositoryImpl) CreateUser(ctx context.Context, user models.User) error {
query := "INSERT INTO users (login, email, password, created_at) VALUES ($1, $2, $3, NOW())"
_, err := r.db.ExecContext(ctx, query, user.Login, user.Email, user.Password)
query, args, err := squirrel.Insert(`"user"`).
Columns("login", "email", "password", "created_at").
Values(user.Login, user.Email, user.Password, squirrel.Expr("NOW()")).
PlaceholderFormat(squirrel.Dollar).
ToSql()
if err != nil {
return fmt.Errorf("couldn't build query: %w", err)
}

_, err = r.db.ExecContext(ctx, query, args...)
// query := "INSERT INTO user (login, email, password, created_at) VALUES ($1, $2, $3, NOW())"
// _, err := r.db.ExecContext(ctx, query, user.Login, user.Email, user.Password)

if err != nil {
var pqErr *pq.Error
Expand All @@ -34,9 +46,19 @@

func (r *RepositoryImpl) GetUserByEmail(ctx context.Context, email string) (models.User, error) {
var user models.User
query := "SELECT id, login, email, password, created_at FROM users WHERE email = $1"
row := r.db.QueryRowContext(ctx, query, email)
err := row.Scan(&user.ID, &user.Login, &user.Email, &user.Password, &user.CreatedAt)
query, args, err := squirrel.Select("id", "login", "email", "password", "created_at").
From(`"user"`).
Where(squirrel.Eq{"email": email}).
PlaceholderFormat(squirrel.Dollar).
ToSql()
if err != nil {
return models.User{}, fmt.Errorf("couldn't build query: %w", err)
}

row := r.db.QueryRowContext(ctx, query, args...)
// query := "SELECT id, login, email, password, created_at FROM user WHERE email = $1"
// row := r.db.QueryRowContext(ctx, query, email)
err = row.Scan(&user.ID, &user.Login, &user.Email, &user.Password, &user.CreatedAt)
if err != nil {
if err == sql.ErrNoRows {
return models.User{}, fmt.Errorf("user not found with email: %s", email)
Expand All @@ -47,20 +69,52 @@
}

func (r *RepositoryImpl) UpdateUser(ctx context.Context, user models.User) error {
query := "UPDATE users SET login = $1, email=$2, password = $3 WHERE id = $4"
_, err := r.db.ExecContext(ctx, query, user.Login, user.Email, user.Password, user.ID)
query, args, err := squirrel.Update(`"user"`).
Set("login", user.Login).
Set("email", user.Email).
Set("password", user.Password).
Where("id = ?", user.ID).
PlaceholderFormat(squirrel.Dollar).
ToSql()
if err != nil {
return fmt.Errorf("couldn't build query: %w", err)
}

_, err = r.db.ExecContext(ctx, query, args...)
// query := "UPDATE user SET login = $1, email=$2, password = $3 WHERE id = $4"
// _, err := r.db.ExecContext(ctx, query, user.Login, user.Email, user.Password, user.ID)
return err
}

func (r *RepositoryImpl) DeleteUser(ctx context.Context, id string) error {
query := "DELETE FROM users WHERE id = $1"
_, err := r.db.ExecContext(ctx, query, id)
query, args, err := squirrel.Delete(`"user"`).
Where("id = ?", id).
PlaceholderFormat(squirrel.Dollar).
ToSql()
if err != nil {
return fmt.Errorf("couldn't build query: %w", err)
}

_, err = r.db.ExecContext(ctx, query, args...)
// query := "DELETE FROM user WHERE id = $1"
// _, err := r.db.ExecContext(ctx, query, id)
return err
}

func (r *RepositoryImpl) GetUsers(ctx context.Context, count, offset int64) ([]models.User, error) {
query := "SELECT id, login, email, created_at FROM users LIMIT $1 OFFSET $2"
rows, err := r.db.QueryContext(ctx, query, count, offset)
query, args, err := squirrel.Select("id", "login", "email", "created_at").
From(`"user"`).
Limit(uint64(count)).

Check failure on line 107 in internal/pkg/auth/repo/auth_repository.go

View workflow job for this annotation

GitHub Actions / linters

G115: integer overflow conversion int64 -> uint64 (gosec)
Offset(uint64(offset)).

Check failure on line 108 in internal/pkg/auth/repo/auth_repository.go

View workflow job for this annotation

GitHub Actions / linters

G115: integer overflow conversion int64 -> uint64 (gosec)
PlaceholderFormat(squirrel.Dollar).
ToSql()
if err != nil {
return nil, fmt.Errorf("couldn't build query: %w", err)
}

rows, err := r.db.QueryContext(ctx, query, args...)
// query := "SELECT id, login, email, created_at FROM user LIMIT $1 OFFSET $2"
// rows, err := r.db.QueryContext(ctx, query, count, offset)
if err != nil {
return nil, err
}
Expand Down
Loading
Loading