From 3f42e63c4999eaade140c3474090a877789530f9 Mon Sep 17 00:00:00 2001 From: pai0id Date: Mon, 15 Jul 2024 17:43:44 +0300 Subject: [PATCH 01/21] db for new event logic --- migrations/001_init_database.sql | 5 ++-- migrations/002_new_structures_sql.sql | 1 + migrations/004_insert_feed_test_data.sql | 6 ++--- migrations/017_initmember_event.sql | 31 ++++++++++++++++++++++++ 4 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 migrations/017_initmember_event.sql diff --git a/migrations/001_init_database.sql b/migrations/001_init_database.sql index 5eaa3ab..c02d78d 100644 --- a/migrations/001_init_database.sql +++ b/migrations/001_init_database.sql @@ -51,7 +51,8 @@ create table IF NOT EXISTS event date timestamp not null, approved boolean default false, created_at timestamp not null, - created_by int not null, + club_id int not null, + main_org int not null, reg_url text default '', reg_open_date timestamp not null, feedback_url text default '' @@ -64,7 +65,7 @@ alter table feed add foreign key (media_id) references mediafile(id); alter table feed add foreign key (created_by) references member(id); alter table event add foreign key (media_id) references mediafile(id); -alter table event add foreign key (created_by) references member(id); +alter table event add foreign key (main_org) references member(id); -- +goose StatementEnd diff --git a/migrations/002_new_structures_sql.sql b/migrations/002_new_structures_sql.sql index fc887f5..b771370 100644 --- a/migrations/002_new_structures_sql.sql +++ b/migrations/002_new_structures_sql.sql @@ -38,6 +38,7 @@ create table if not exists club_org ( alter table encounter add foreign key (club_id) references club(id); alter table club add FOREIGN KEY (logo) REFERENCES mediafile(id); +alter table event add foreign key (club_id) references club(id); alter table club_photo add FOREIGN KEY (media_id) REFERENCES mediafile(id); alter table club_photo add FOREIGN KEY (club_id) REFERENCES club(id); diff --git a/migrations/004_insert_feed_test_data.sql b/migrations/004_insert_feed_test_data.sql index 3e10b7c..92a0487 100644 --- a/migrations/004_insert_feed_test_data.sql +++ b/migrations/004_insert_feed_test_data.sql @@ -23,10 +23,10 @@ VALUES ('2', 'sllab', 1), ('22', 'sllab', 2); -INSERT INTO event (title, description, prompt, media_id, date, approved, created_at, created_by, reg_url, reg_open_date, feedback_url) +INSERT INTO event (title, description, prompt, media_id, date, approved, created_at, main_org, reg_url, reg_open_date, feedback_url, club_id) VALUES -('kcoc', 'sllab', 'kcid', 1, '2005-11-19 10:23:54', true, '2005-11-19 10:23:54', 1, 'ahh', '2005-11-19 10:23:54', '123'), -('sinep', 'stun', 'nibor', 1, '2005-11-19 10:23:54', true, '2005-11-19 10:23:54', 2, 'ahh', '2005-11-19 10:23:54', '123'); +('kcoc', 'sllab', 'kcid', 1, '2005-11-19 10:23:54', true, '2005-11-19 10:23:54', 1, 'ahh', '2005-11-19 10:23:54', '123', 1), +('sinep', 'stun', 'nibor', 1, '2005-11-19 10:23:54', true, '2005-11-19 10:23:54', 2, 'ahh', '2005-11-19 10:23:54', '123', 0); -- +goose StatementEnd diff --git a/migrations/017_initmember_event.sql b/migrations/017_initmember_event.sql new file mode 100644 index 0000000..e0256bd --- /dev/null +++ b/migrations/017_initmember_event.sql @@ -0,0 +1,31 @@ +-- +goose Up +-- +goose StatementBegin + +create table IF NOT EXISTS member_event +( + id serial primary key, + event_id int not null, + member_id int not null, + role_id int not null, + division text default '' +); + +create table IF NOT EXISTS member_event_role +( + id serial primary key, + name text not null +); + +alter table member_event add foreign key (event_id) references event(id); +alter table member_event add foreign key (member_id) references member(id); +alter table member_event add foreign key (role_id) references member_event_role(id); + +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin + +drop table IF EXISTS member_event_role CASCADE; +drop table IF EXISTS member_event CASCADE; + +-- +goose StatementEnd From 9a5a187637fbf96fd37a125834b313d946b29c77 Mon Sep 17 00:00:00 2001 From: Impervguin Date: Mon, 15 Jul 2024 18:10:21 +0300 Subject: [PATCH 02/21] Refactored club except delete and update --- internal/app/mapper/members.go | 5 -- internal/domain/member.go | 1 - internal/infrastructure/postgres/club.go | 90 ++++++++++++++++----- internal/infrastructure/postgres/members.go | 20 ++--- migrations/001_init_database.sql | 1 - migrations/006_add_orgs_to_clubs.sql | 16 ++-- migrations/015_insert_default_media.sql | 2 +- migrations/016_init_role_table.sql | 42 ++++++++++ 8 files changed, 126 insertions(+), 51 deletions(-) create mode 100644 migrations/016_init_role_table.sql diff --git a/internal/app/mapper/members.go b/internal/app/mapper/members.go index 9e4f0bb..5960956 100644 --- a/internal/app/mapper/members.go +++ b/internal/app/mapper/members.go @@ -24,7 +24,6 @@ func MakeResponseAllMembers(f []domain.Member, membersMediaFiles map[int]domain. Telegram: v.Telegram, Vk: v.Vk, Name: v.Name, - RoleID: v.RoleID, IsAdmin: v.IsAdmin, }) } @@ -41,7 +40,6 @@ func MakeResponseMember(f *domain.Member, membersMediaFile *domain.MediaFile) (* Telegram: f.Telegram, Vk: f.Vk, Name: f.Name, - RoleID: f.RoleID, IsAdmin: f.IsAdmin, }, nil } @@ -62,7 +60,6 @@ func MakeResponseMembersByName(f []domain.Member, membersMediaFiles map[int]doma Telegram: v.Telegram, Vk: v.Vk, Name: v.Name, - RoleID: v.RoleID, IsAdmin: v.IsAdmin, }) } @@ -78,7 +75,6 @@ func MakeRequestPostMember(f *requests.PostMember) *domain.Member { Telegram: f.Telegram, Vk: f.Vk, Name: f.Name, - RoleID: f.RoleID, IsAdmin: f.IsAdmin, } } @@ -92,7 +88,6 @@ func MakeRequestUpdateMember(f *requests.UpdateMember) *domain.Member { Telegram: f.Telegram, Vk: f.Vk, Name: f.Name, - RoleID: f.RoleID, IsAdmin: f.IsAdmin, } } diff --git a/internal/domain/member.go b/internal/domain/member.go index 7a17e20..4887bb1 100644 --- a/internal/domain/member.go +++ b/internal/domain/member.go @@ -8,6 +8,5 @@ type Member struct { Telegram string `json:"telegram"` Vk string `json:"vk"` Name string `json:"name"` - RoleID int `json:"role_id"` IsAdmin bool `json:"isAdmin"` } diff --git a/internal/infrastructure/postgres/club.go b/internal/infrastructure/postgres/club.go index 826ef28..1659ab0 100644 --- a/internal/infrastructure/postgres/club.go +++ b/internal/infrastructure/postgres/club.go @@ -182,8 +182,8 @@ func (s *Postgres) GetClubsByType(_ context.Context, type_ string) ([]domain.Clu const getClubOrgs = ` SELECT - role_name, - role_spec, + orgs.role_name, + orgs.role_spec, mem.id, mem.hash_password, mem.login, @@ -191,7 +191,6 @@ SELECT mem.telegram, mem.vk, mem.name, - mem.role_id, mem.is_admin, clubs.name as club_name FROM club_org @@ -205,7 +204,6 @@ JOIN telegram, vk, name, - role_id, is_admin FROM member ) mem @@ -218,6 +216,16 @@ JOIN FROM club ) as clubs ON (club_org.club_id = clubs.id) +JOIN +( + SELECT + id, + role_name, + role_spec + FROM club_role + WHERE role_clearance = 2 +) as orgs +ON orgs.id = club_org.role_id WHERE club_id = $1 AND club_id > 0 ` @@ -239,7 +247,6 @@ func (s *Postgres) GetClubOrgs(_ context.Context, clubID int) ([]domain.ClubOrg, &c.Telegram, &c.Vk, &c.Name, - &c.RoleID, &c.IsAdmin, &c.ClubName, ) @@ -256,8 +263,8 @@ func (s *Postgres) GetClubOrgs(_ context.Context, clubID int) ([]domain.ClubOrg, const getClubsOrgs = ` SELECT - role_name, - role_spec, + orgs.role_name, + orgs.role_spec, mem.id, mem.hash_password, mem.login, @@ -265,7 +272,6 @@ SELECT mem.telegram, mem.vk, mem.name, - mem.role_id, mem.is_admin, clubs.name as club_name, clubs.id as club_id @@ -293,6 +299,16 @@ JOIN FROM club ) as clubs ON (club_org.club_id = clubs.id) +JOIN +( + SELECT + id, + role_name, + role_spec + FROM club_role + WHERE role_clearance = 2 +) as orgs +ON orgs.id = club_org.role_id WHERE club_id = ANY($1) AND club_id > 0 ` @@ -314,7 +330,6 @@ func (s *Postgres) GetClubsOrgs(_ context.Context, clubIDs []int) ([]domain.Club &c.Telegram, &c.Vk, &c.Name, - &c.RoleID, &c.IsAdmin, &c.ClubName, &c.ClubID, @@ -332,8 +347,8 @@ func (s *Postgres) GetClubsOrgs(_ context.Context, clubIDs []int) ([]domain.Club const getClubSubOrgs = ` SELECT - role_name, - role_spec, + orgs.role_name, + orgs.role_spec, mem.id, mem.hash_password, mem.login, @@ -341,7 +356,6 @@ SELECT mem.telegram, mem.vk, mem.name, - mem.role_id, mem.is_admin, clubs.name as club_name FROM club_org @@ -369,6 +383,16 @@ JOIN WHERE id > 0 ) as clubs ON (club_org.club_id = clubs.id) +JOIN +( + SELECT + id, + role_name, + role_spec + FROM club_role + WHERE role_clearance = 2 +) as orgs +ON orgs.id = club_org.role_id WHERE club_id = ANY((SELECT id FROM club WHERE parent_id = $1)) AND club_id > 0 ` @@ -390,7 +414,6 @@ func (s *Postgres) GetClubSubOrgs(_ context.Context, clubID int) ([]domain.ClubO &c.Telegram, &c.Vk, &c.Name, - &c.RoleID, &c.IsAdmin, &c.ClubName, ) @@ -408,8 +431,8 @@ func (s *Postgres) GetClubSubOrgs(_ context.Context, clubID int) ([]domain.ClubO const getAllClubOrgs = ` SELECT - role_name, - role_spec, + orgs.role_name, + orgs.role_spec, member_id, club_id, mem.hash_password, @@ -418,7 +441,6 @@ SELECT mem.telegram, mem.vk, mem.name, - mem.role_id, mem.is_admin, clubs.name as club_name FROM club_org @@ -445,6 +467,16 @@ JOIN FROM club WHERE id > 0 ) as clubs +JOIN +( + SELECT + id, + role_name, + role_spec + FROM club_role + WHERE role_clearance = 2 +) as orgs +ON orgs.id = club_org.role_id ON (club_org.club_id = clubs.id) ` @@ -467,7 +499,6 @@ func (s *Postgres) GetAllClubOrgs(_ context.Context) ([]domain.ClubOrg, error) { &c.Telegram, &c.Vk, &c.Name, - &c.RoleID, &c.IsAdmin, &c.ClubName, ) @@ -516,13 +547,21 @@ func (s *Postgres) AddClub(_ context.Context, c *domain.Club) (int, error) { return id, nil } +const addOrgRole = ` +INSERT INTO club_role ( + role_name, + role_spec, + role_clearance +) VALUES ($1, $2, 2) +RETURNING id +` + const addOrgs = ` INSERT INTO club_org ( - role_name, - role_spec, + role_id, member_id, - club_id -) VALUES ($1, $2, $3, $4) + club_id, +) VALUES ($1, $2, $3) ` func (s *Postgres) AddOrgs(_ context.Context, orgs []domain.ClubOrg) error { @@ -532,7 +571,13 @@ func (s *Postgres) AddOrgs(_ context.Context, orgs []domain.ClubOrg) error { } for _, org := range orgs { - _, err = tx.Exec(addOrgs, org.RoleName, org.RoleSpec, org.ID, org.ClubID) + var id int + err := s.db.QueryRow(addOrgRole, org.RoleName, org.RoleSpec).Scan(&id) + if err != nil { + tx.Rollback() + return wrapPostgresError(err) + } + _, err = tx.Exec(addOrgs, id, org.ID, org.ClubID) if err != nil { tx.Rollback() return wrapPostgresError(err) @@ -576,6 +621,7 @@ func (s *Postgres) GetClubMediaFiles(clubID int) ([]domain.ClubPhoto, error) { const deleteClub = "DELETE FROM club WHERE id = $1" const deleteClubOrgs = "DELETE FROM club_org WHERE club_id = $1" +const deleteClubMembers = "DELETE FROM member WHERE club_id = $1" const deleteClubPhotos = "DELETE FROM club_photo WHERE club_id = $1" const deleteClubEncounters = "DELETE FROM encounter WHERE club_id = $1" const deleteClubDocuments = "DELETE FROM document WHERE club_id = $1" diff --git a/internal/infrastructure/postgres/members.go b/internal/infrastructure/postgres/members.go index 33960dc..881e414 100644 --- a/internal/infrastructure/postgres/members.go +++ b/internal/infrastructure/postgres/members.go @@ -6,7 +6,7 @@ import ( "github.com/STUD-IT-team/bmstu-stud-web-backend/internal/domain" ) -const getAllMembersQuery = "SELECT id, hash_password, login, media_id, telegram, vk, name, role_id, is_admin FROM member" +const getAllMembersQuery = "SELECT id, hash_password, login, media_id, telegram, vk, name, is_admin FROM member" func (p *Postgres) GetAllMembers(_ context.Context) ([]domain.Member, error) { var members []domain.Member @@ -27,7 +27,6 @@ func (p *Postgres) GetAllMembers(_ context.Context) ([]domain.Member, error) { &member.Telegram, &member.Vk, &member.Name, - &member.RoleID, &member.IsAdmin, ) @@ -45,7 +44,7 @@ func (p *Postgres) GetAllMembers(_ context.Context) ([]domain.Member, error) { return members, nil } -const getMemberQuery = "SELECT id, hash_password, login, media_id, telegram, vk, name, role_id, is_admin FROM member WHERE id=$1" +const getMemberQuery = "SELECT id, hash_password, login, media_id, telegram, vk, name, is_admin FROM member WHERE id=$1" func (p *Postgres) GetMember(ctx context.Context, id int) (*domain.Member, error) { var member domain.Member @@ -61,7 +60,6 @@ func (p *Postgres) GetMember(ctx context.Context, id int) (*domain.Member, error &member.Telegram, &member.Vk, &member.Name, - &member.RoleID, &member.IsAdmin, ) @@ -72,7 +70,7 @@ func (p *Postgres) GetMember(ctx context.Context, id int) (*domain.Member, error return &member, nil } -const getMembersByNameQuery = "SELECT id, hash_password, login, media_id, telegram, vk, name, role_id, is_admin FROM member WHERE name ILIKE $1" +const getMembersByNameQuery = "SELECT id, hash_password, login, media_id, telegram, vk, name, is_admin FROM member WHERE name ILIKE $1" func (p *Postgres) GetMembersByName(_ context.Context, name string) ([]domain.Member, error) { var members []domain.Member @@ -93,7 +91,6 @@ func (p *Postgres) GetMembersByName(_ context.Context, name string) ([]domain.Me &member.Telegram, &member.Vk, &member.Name, - &member.RoleID, &member.IsAdmin, ) @@ -112,8 +109,8 @@ func (p *Postgres) GetMembersByName(_ context.Context, name string) ([]domain.Me } const postMemberQuery = `INSERT INTO member - (hash_password, login, media_id, telegram, vk, name, role_id, is_admin) - VALUES ($1, $2, $3, $4, $5, $6, $7, $8)` + (hash_password, login, media_id, telegram, vk, name, is_admin) + VALUES ($1, $2, $3, $4, $5, $6, $7)` func (p *Postgres) PostMember(ctx context.Context, member *domain.Member) error { _, err := p.db.Exec( @@ -124,7 +121,6 @@ func (p *Postgres) PostMember(ctx context.Context, member *domain.Member) error member.Telegram, member.Vk, member.Name, - member.RoleID, member.IsAdmin, ) @@ -160,9 +156,8 @@ media_id=$3, telegram=$4, vk=$5, name=$6, -role_id=$7, -is_admin=$8 -WHERE id=$9` +is_admin=$7 +WHERE id=$8` func (p *Postgres) UpdateMember(ctx context.Context, member *domain.Member) error { tag, err := p.db.Exec( @@ -173,7 +168,6 @@ func (p *Postgres) UpdateMember(ctx context.Context, member *domain.Member) erro member.Telegram, member.Vk, member.Name, - member.RoleID, member.IsAdmin, member.ID, ) diff --git a/migrations/001_init_database.sql b/migrations/001_init_database.sql index 5eaa3ab..6e8eff0 100644 --- a/migrations/001_init_database.sql +++ b/migrations/001_init_database.sql @@ -58,7 +58,6 @@ create table IF NOT EXISTS event ); alter table member add foreign key (media_id) references mediafile(id); -alter table member add foreign key (role_id) references member_role(role_id); alter table feed add foreign key (media_id) references mediafile(id); alter table feed add foreign key (created_by) references member(id); diff --git a/migrations/006_add_orgs_to_clubs.sql b/migrations/006_add_orgs_to_clubs.sql index 429e0d6..0052fd6 100644 --- a/migrations/006_add_orgs_to_clubs.sql +++ b/migrations/006_add_orgs_to_clubs.sql @@ -1,15 +1,15 @@ -- +goose Up -- +goose StatementBegin -INSERT INTO member (hash_password, login, media_id, telegram, vk, name, role_id, is_admin) +INSERT INTO member (hash_password, login, media_id, telegram, vk, name, is_admin) VALUES -('test', 'toha', 1, '@toha', 'vk.com/toha', 'Антон Павленко', 1, true), -('$2a$10$kj0GwI3q1H0PgOzuLqK5uOhPPvA42upL8CdIm/4luikQBYNKVxXay', 'imp', 1, '@imp', 'vk.com/imp', 'Дмитрий Шахнович', 1, true), -('test', 'dasha', 1, '@dasha', 'vk.com/dasha', 'Дарья Серышева', 1, true), -('test', 'paioid', 1, '@paioid', 'vk.com/paioid', 'Андрей Поляков', 1, true), -('test', 'admin', 1, '@admin', 'vk.com/admin', 'Админ', 1, true), -('test', 'user', 1, '@user', 'vk.com/user', 'Юзер', 1, true), -('test', 'user2', 1, '@user2', 'vk.com/user2', 'Юзер2', 1, true); +('test', 'toha', 1, '@toha', 'vk.com/toha', 'Антон Павленко', true), +('$2a$10$kj0GwI3q1H0PgOzuLqK5uOhPPvA42upL8CdIm/4luikQBYNKVxXay', 'imp', 1, '@imp', 'vk.com/imp', 'Дмитрий Шахнович', true), +('test', 'dasha', 1, '@dasha', 'vk.com/dasha', 'Дарья Серышева', true), +('test', 'paioid', 1, '@paioid', 'vk.com/paioid', 'Андрей Поляков', true), +('test', 'admin', 1, '@admin', 'vk.com/admin', 'Админ', true), +('test', 'user', 1, '@user', 'vk.com/user', 'Юзер', true), +('test', 'user2', 1, '@user2', 'vk.com/user2', 'Юзер2', true); INSERT INTO club_org (club_id, member_id, role_name, role_spec) diff --git a/migrations/015_insert_default_media.sql b/migrations/015_insert_default_media.sql index a83c4e3..eecedb1 100644 --- a/migrations/015_insert_default_media.sql +++ b/migrations/015_insert_default_media.sql @@ -15,5 +15,5 @@ VALUES -- +goose Down -- +goose StatementBegin -DELETE FROM default_media +DELETE FROM default_media; -- +goose StatementEnd diff --git a/migrations/016_init_role_table.sql b/migrations/016_init_role_table.sql new file mode 100644 index 0000000..b081622 --- /dev/null +++ b/migrations/016_init_role_table.sql @@ -0,0 +1,42 @@ +-- +goose Up +-- +goose StatementBegin + + +ALTER TABLE member_role RENAME TO club_role; +ALTER TABLE member DROP COLUMN role_id; +ALTER TABLE club_org DROP COLUMN role_spec; +ALTER TABLE club_org DROP COLUMN role_name; +ALTER TABLE club_role RENAME COLUMN role_id TO id; +ALTER TABLE club_org ADD COLUMN role_id int references club_role(id); + +-- 0 - гость +-- 1 - участник +-- 2 - руководитель +-- 3 - админ +ALTER TABLE club_role ADD COLUMN role_clearance int; + + +INSERT INTO club_role (role_name, role_spec, role_clearance) +VALUES +('IT бог', 'Глава ИТЭ', 2), +('Программист', 'Программист', 2), +('Тестировщик', 'Тестировщик', 2), +('Бухгалтер', 'Бухгалтер', 2), +('Старший участник', 'Старший участник', 2), +('Младший участник', 'Младший участник', 2), +('Гость', 'Гость', 2); + +UPDATE club_org SET role_id = 1 WHERE id = 1; +UPDATE club_org SET role_id = 2 WHERE id = 2; +UPDATE club_org SET role_id = 3 WHERE id = 3; +UPDATE club_org SET role_id = 4 WHERE id = 4; +UPDATE club_org SET role_id = 5 WHERE id = 5; +UPDATE club_org SET role_id = 6 WHERE id = 6; +UPDATE club_org SET role_id = 7 WHERE id = 7; + +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin +ALTER TABLE member Add COLUMN role_id int; +-- +goose StatementEnd From 3ae549310a236b74fc05644aa27a6ef663c350df Mon Sep 17 00:00:00 2001 From: pai0id Date: Tue, 16 Jul 2024 11:08:43 +0300 Subject: [PATCH 03/21] prune member hash --- internal/app/mapper/members.go | 83 +++++++++----------- internal/domain/requests/post-member.go | 48 +++++------ internal/domain/requests/update-member.go | 50 ++++++------ internal/domain/responses/get-all-members.go | 17 ++-- internal/domain/responses/get-member.go | 17 ++-- internal/infrastructure/postgres/members.go | 34 ++++---- 6 files changed, 112 insertions(+), 137 deletions(-) diff --git a/internal/app/mapper/members.go b/internal/app/mapper/members.go index 9e4f0bb..810d15c 100644 --- a/internal/app/mapper/members.go +++ b/internal/app/mapper/members.go @@ -17,15 +17,14 @@ func MakeResponseAllMembers(f []domain.Member, membersMediaFiles map[int]domain. } members = append(members, responses.Member{ - ID: v.ID, - HashPassword: v.HashPassword, - Login: v.Login, - Media: media, - Telegram: v.Telegram, - Vk: v.Vk, - Name: v.Name, - RoleID: v.RoleID, - IsAdmin: v.IsAdmin, + ID: v.ID, + Login: v.Login, + Media: media, + Telegram: v.Telegram, + Vk: v.Vk, + Name: v.Name, + RoleID: v.RoleID, + IsAdmin: v.IsAdmin, }) } @@ -34,15 +33,14 @@ func MakeResponseAllMembers(f []domain.Member, membersMediaFiles map[int]domain. func MakeResponseMember(f *domain.Member, membersMediaFile *domain.MediaFile) (*responses.GetMember, error) { return &responses.GetMember{ - ID: f.ID, - HashPassword: f.HashPassword, - Login: f.Login, - Media: *membersMediaFile, - Telegram: f.Telegram, - Vk: f.Vk, - Name: f.Name, - RoleID: f.RoleID, - IsAdmin: f.IsAdmin, + ID: f.ID, + Login: f.Login, + Media: *membersMediaFile, + Telegram: f.Telegram, + Vk: f.Vk, + Name: f.Name, + RoleID: f.RoleID, + IsAdmin: f.IsAdmin, }, nil } @@ -55,15 +53,14 @@ func MakeResponseMembersByName(f []domain.Member, membersMediaFiles map[int]doma } members = append(members, responses.Member{ - ID: v.ID, - HashPassword: v.HashPassword, - Login: v.Login, - Media: media, - Telegram: v.Telegram, - Vk: v.Vk, - Name: v.Name, - RoleID: v.RoleID, - IsAdmin: v.IsAdmin, + ID: v.ID, + Login: v.Login, + Media: media, + Telegram: v.Telegram, + Vk: v.Vk, + Name: v.Name, + RoleID: v.RoleID, + IsAdmin: v.IsAdmin, }) } @@ -72,27 +69,25 @@ func MakeResponseMembersByName(f []domain.Member, membersMediaFiles map[int]doma func MakeRequestPostMember(f *requests.PostMember) *domain.Member { return &domain.Member{ - HashPassword: f.HashPassword, - Login: f.Login, - MediaID: f.MediaID, - Telegram: f.Telegram, - Vk: f.Vk, - Name: f.Name, - RoleID: f.RoleID, - IsAdmin: f.IsAdmin, + Login: f.Login, + MediaID: f.MediaID, + Telegram: f.Telegram, + Vk: f.Vk, + Name: f.Name, + RoleID: f.RoleID, + IsAdmin: f.IsAdmin, } } func MakeRequestUpdateMember(f *requests.UpdateMember) *domain.Member { return &domain.Member{ - ID: f.ID, - HashPassword: f.HashPassword, - Login: f.Login, - MediaID: f.MediaID, - Telegram: f.Telegram, - Vk: f.Vk, - Name: f.Name, - RoleID: f.RoleID, - IsAdmin: f.IsAdmin, + ID: f.ID, + Login: f.Login, + MediaID: f.MediaID, + Telegram: f.Telegram, + Vk: f.Vk, + Name: f.Name, + RoleID: f.RoleID, + IsAdmin: f.IsAdmin, } } diff --git a/internal/domain/requests/post-member.go b/internal/domain/requests/post-member.go index 2ea1fa3..c74021a 100644 --- a/internal/domain/requests/post-member.go +++ b/internal/domain/requests/post-member.go @@ -9,25 +9,23 @@ import ( ) type PostMember struct { - HashPassword []byte `json:"hash_password"` - Login string `json:"login"` - MediaID int `json:"media_id"` - Telegram string `json:"telegram"` - Vk string `json:"vk"` - Name string `json:"name"` - RoleID int `json:"role_id"` - IsAdmin bool `json:"isAdmin"` + Login string `json:"login"` + MediaID int `json:"media_id"` + Telegram string `json:"telegram"` + Vk string `json:"vk"` + Name string `json:"name"` + RoleID int `json:"role_id"` + IsAdmin bool `json:"isAdmin"` } type PostMemberPointer struct { - HashPassword *[]byte `json:"hash_password"` - Login *string `json:"login"` - MediaID *int `json:"media_id"` - Telegram *string `json:"telegram"` - Vk *string `json:"vk"` - Name *string `json:"name"` - RoleID *int `json:"role_id"` - IsAdmin *bool `json:"isAdmin"` + Login *string `json:"login"` + MediaID *int `json:"media_id"` + Telegram *string `json:"telegram"` + Vk *string `json:"vk"` + Name *string `json:"name"` + RoleID *int `json:"role_id"` + IsAdmin *bool `json:"isAdmin"` } func (f *PostMember) Bind(req *http.Request) error { @@ -50,14 +48,13 @@ func (f *PostMember) Bind(req *http.Request) error { } *f = PostMember{ - HashPassword: *pf.HashPassword, - Login: *pf.Login, - MediaID: *pf.MediaID, - Telegram: *pf.Telegram, - Vk: *pf.Vk, - Name: *pf.Name, - RoleID: *pf.RoleID, - IsAdmin: *pf.IsAdmin, + Login: *pf.Login, + MediaID: *pf.MediaID, + Telegram: *pf.Telegram, + Vk: *pf.Vk, + Name: *pf.Name, + RoleID: *pf.RoleID, + IsAdmin: *pf.IsAdmin, } return f.validate() @@ -68,9 +65,6 @@ func (f *PostMember) validate() error { } func (pf *PostMemberPointer) validate() error { - if pf.HashPassword == nil { - return fmt.Errorf("require: HashPassword") - } if pf.Login == nil { return fmt.Errorf("require: Login") } diff --git a/internal/domain/requests/update-member.go b/internal/domain/requests/update-member.go index f709fc0..4a08b5c 100644 --- a/internal/domain/requests/update-member.go +++ b/internal/domain/requests/update-member.go @@ -11,26 +11,24 @@ import ( ) type UpdateMember struct { - ID int `json:"id"` - HashPassword []byte `json:"hash_password"` - Login string `json:"login"` - MediaID int `json:"media_id"` - Telegram string `json:"telegram"` - Vk string `json:"vk"` - Name string `json:"name"` - RoleID int `json:"role_id"` - IsAdmin bool `json:"isAdmin"` + ID int `json:"id"` + Login string `json:"login"` + MediaID int `json:"media_id"` + Telegram string `json:"telegram"` + Vk string `json:"vk"` + Name string `json:"name"` + RoleID int `json:"role_id"` + IsAdmin bool `json:"isAdmin"` } type UpdateMemberPointer struct { - HashPassword *[]byte `json:"hash_password"` - Login *string `json:"login"` - MediaID *int `json:"media_id"` - Telegram *string `json:"telegram"` - Vk *string `json:"vk"` - Name *string `json:"name"` - RoleID *int `json:"role_id"` - IsAdmin *bool `json:"isAdmin"` + Login *string `json:"login"` + MediaID *int `json:"media_id"` + Telegram *string `json:"telegram"` + Vk *string `json:"vk"` + Name *string `json:"name"` + RoleID *int `json:"role_id"` + IsAdmin *bool `json:"isAdmin"` } func (f *UpdateMember) Bind(req *http.Request) error { @@ -53,14 +51,13 @@ func (f *UpdateMember) Bind(req *http.Request) error { } *f = UpdateMember{ - HashPassword: *pf.HashPassword, - Login: *pf.Login, - MediaID: *pf.MediaID, - Telegram: *pf.Telegram, - Vk: *pf.Vk, - Name: *pf.Name, - RoleID: *pf.RoleID, - IsAdmin: *pf.IsAdmin, + Login: *pf.Login, + MediaID: *pf.MediaID, + Telegram: *pf.Telegram, + Vk: *pf.Vk, + Name: *pf.Name, + RoleID: *pf.RoleID, + IsAdmin: *pf.IsAdmin, } id, err := strconv.Atoi(chi.URLParam(req, "id")) @@ -81,9 +78,6 @@ func (f *UpdateMember) validate() error { } func (pf *UpdateMemberPointer) validate() error { - if pf.HashPassword == nil { - return fmt.Errorf("require: HashPassword") - } if pf.Login == nil { return fmt.Errorf("require: Login") } diff --git a/internal/domain/responses/get-all-members.go b/internal/domain/responses/get-all-members.go index b50a06b..a073d85 100644 --- a/internal/domain/responses/get-all-members.go +++ b/internal/domain/responses/get-all-members.go @@ -7,13 +7,12 @@ type GetAllMembers struct { } type Member struct { - ID int `json:"id"` - HashPassword []byte `json:"hash_password"` - Login string `json:"login"` - Media domain.MediaFile `json:"media"` - Telegram string `json:"telegram"` - Vk string `json:"vk"` - Name string `json:"name"` - RoleID int `json:"role_id"` - IsAdmin bool `json:"isAdmin"` + ID int `json:"id"` + Login string `json:"login"` + Media domain.MediaFile `json:"media"` + Telegram string `json:"telegram"` + Vk string `json:"vk"` + Name string `json:"name"` + RoleID int `json:"role_id"` + IsAdmin bool `json:"isAdmin"` } diff --git a/internal/domain/responses/get-member.go b/internal/domain/responses/get-member.go index 0288e92..e2f2173 100644 --- a/internal/domain/responses/get-member.go +++ b/internal/domain/responses/get-member.go @@ -3,13 +3,12 @@ package responses import "github.com/STUD-IT-team/bmstu-stud-web-backend/internal/domain" type GetMember struct { - ID int `json:"id"` - HashPassword []byte `json:"hash_password"` - Login string `json:"login"` - Media domain.MediaFile `json:"media"` - Telegram string `json:"telegram"` - Vk string `json:"vk"` - Name string `json:"name"` - RoleID int `json:"role_id"` - IsAdmin bool `json:"isAdmin"` + ID int `json:"id"` + Login string `json:"login"` + Media domain.MediaFile `json:"media"` + Telegram string `json:"telegram"` + Vk string `json:"vk"` + Name string `json:"name"` + RoleID int `json:"role_id"` + IsAdmin bool `json:"isAdmin"` } diff --git a/internal/infrastructure/postgres/members.go b/internal/infrastructure/postgres/members.go index 33960dc..d33ef10 100644 --- a/internal/infrastructure/postgres/members.go +++ b/internal/infrastructure/postgres/members.go @@ -6,7 +6,7 @@ import ( "github.com/STUD-IT-team/bmstu-stud-web-backend/internal/domain" ) -const getAllMembersQuery = "SELECT id, hash_password, login, media_id, telegram, vk, name, role_id, is_admin FROM member" +const getAllMembersQuery = "SELECT id, login, media_id, telegram, vk, name, role_id, is_admin FROM member" func (p *Postgres) GetAllMembers(_ context.Context) ([]domain.Member, error) { var members []domain.Member @@ -21,7 +21,6 @@ func (p *Postgres) GetAllMembers(_ context.Context) ([]domain.Member, error) { err = rows.Scan( &member.ID, - &member.HashPassword, &member.Login, &member.MediaID, &member.Telegram, @@ -45,7 +44,7 @@ func (p *Postgres) GetAllMembers(_ context.Context) ([]domain.Member, error) { return members, nil } -const getMemberQuery = "SELECT id, hash_password, login, media_id, telegram, vk, name, role_id, is_admin FROM member WHERE id=$1" +const getMemberQuery = "SELECT id, login, media_id, telegram, vk, name, role_id, is_admin FROM member WHERE id=$1" func (p *Postgres) GetMember(ctx context.Context, id int) (*domain.Member, error) { var member domain.Member @@ -55,7 +54,6 @@ func (p *Postgres) GetMember(ctx context.Context, id int) (*domain.Member, error id, ).Scan( &member.ID, - &member.HashPassword, &member.Login, &member.MediaID, &member.Telegram, @@ -72,7 +70,7 @@ func (p *Postgres) GetMember(ctx context.Context, id int) (*domain.Member, error return &member, nil } -const getMembersByNameQuery = "SELECT id, hash_password, login, media_id, telegram, vk, name, role_id, is_admin FROM member WHERE name ILIKE $1" +const getMembersByNameQuery = "SELECT id, login, media_id, telegram, vk, name, role_id, is_admin FROM member WHERE name ILIKE $1" func (p *Postgres) GetMembersByName(_ context.Context, name string) ([]domain.Member, error) { var members []domain.Member @@ -87,7 +85,6 @@ func (p *Postgres) GetMembersByName(_ context.Context, name string) ([]domain.Me err = rows.Scan( &member.ID, - &member.HashPassword, &member.Login, &member.MediaID, &member.Telegram, @@ -112,13 +109,12 @@ func (p *Postgres) GetMembersByName(_ context.Context, name string) ([]domain.Me } const postMemberQuery = `INSERT INTO member - (hash_password, login, media_id, telegram, vk, name, role_id, is_admin) + (login, media_id, telegram, vk, name, role_id, is_admin) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)` func (p *Postgres) PostMember(ctx context.Context, member *domain.Member) error { _, err := p.db.Exec( postMemberQuery, - member.HashPassword, member.Login, member.MediaID, member.Telegram, @@ -154,20 +150,18 @@ func (p *Postgres) DeleteMember(ctx context.Context, id int) error { const updateMemberQuery = ` UPDATE member SET -hash_password=$1, -login=$2, -media_id=$3, -telegram=$4, -vk=$5, -name=$6, -role_id=$7, -is_admin=$8 -WHERE id=$9` +login=$1, +media_id=$2, +telegram=$3, +vk=$4, +name=$5, +role_id=$6, +is_admin=$7 +WHERE id=$8` func (p *Postgres) UpdateMember(ctx context.Context, member *domain.Member) error { tag, err := p.db.Exec( updateMemberQuery, - member.HashPassword, member.Login, member.MediaID, member.Telegram, @@ -187,12 +181,12 @@ func (p *Postgres) UpdateMember(ctx context.Context, member *domain.Member) erro return nil } -const getMemberByLoginQuery = "SELECT id, login, hash_password FROM member WHERE login=$1;" +const getMemberByLoginQuery = "SELECT id, login FROM member WHERE login=$1;" func (p *Postgres) GetMemberByLogin(_ context.Context, login string) (*domain.Member, error) { var user domain.Member - err := p.db.QueryRow(getMemberByLoginQuery, login).Scan(&user.ID, &user.Login, &user.HashPassword) + err := p.db.QueryRow(getMemberByLoginQuery, login).Scan(&user.ID, &user.Login) if err != nil { return nil, wrapPostgresError(err) } From 3921691f3a09118c3f4d1ffad03bcc6857640e4a Mon Sep 17 00:00:00 2001 From: pai0id Date: Tue, 16 Jul 2024 11:49:34 +0300 Subject: [PATCH 04/21] event structure --- internal/ports/events.go | 7 +++++++ ...tmember_event.sql => 017_init_event_member.sql} | 14 +++++++------- 2 files changed, 14 insertions(+), 7 deletions(-) rename migrations/{017_initmember_event.sql => 017_init_event_member.sql} (50%) diff --git a/internal/ports/events.go b/internal/ports/events.go index 89ed179..c8ff31b 100644 --- a/internal/ports/events.go +++ b/internal/ports/events.go @@ -42,9 +42,16 @@ func (h *EventsHandler) Routes() chi.Router { r.Get("/", h.r.Wrap(h.GetAllEvents)) r.Get("/{id}", h.r.Wrap(h.GetEvent)) r.Get("/range/", h.r.Wrap(h.GetEventsByRange)) + // r.Get("/members/roles/", h.r.Wrap(h.GetEventMemberRoles)) + // r.Get("/members/", h.r.Wrap(h.GetAllEventMembers)) + // r.Get("/members/search_by_event/{event_id}", h.r.Wrap(h.GetEventMembersByEvent)) + // r.Get("/members/{member_id}", h.r.Wrap(h.GetEventMember)) r.Post("/", h.r.Wrap(h.PostEvent)) r.Delete("/{id}", h.r.Wrap(h.DeleteEvent)) r.Put("/{id}", h.r.Wrap(h.UpdateEvent)) + // r.Post("/members/", h.r.Wrap(h.PostEventMember)) + // r.Delete("/members/{id}", h.r.Wrap(h.DeleteEventMember)) + // r.Put("/members/{id}", h.r.Wrap(h.UpdateEventMember)) return r } diff --git a/migrations/017_initmember_event.sql b/migrations/017_init_event_member.sql similarity index 50% rename from migrations/017_initmember_event.sql rename to migrations/017_init_event_member.sql index e0256bd..18329e0 100644 --- a/migrations/017_initmember_event.sql +++ b/migrations/017_init_event_member.sql @@ -1,7 +1,7 @@ -- +goose Up -- +goose StatementBegin -create table IF NOT EXISTS member_event +create table IF NOT EXISTS event_member ( id serial primary key, event_id int not null, @@ -10,22 +10,22 @@ create table IF NOT EXISTS member_event division text default '' ); -create table IF NOT EXISTS member_event_role +create table IF NOT EXISTS event_member_role ( id serial primary key, name text not null ); -alter table member_event add foreign key (event_id) references event(id); -alter table member_event add foreign key (member_id) references member(id); -alter table member_event add foreign key (role_id) references member_event_role(id); +alter table event_member add foreign key (event_id) references event(id); +alter table event_member add foreign key (member_id) references member(id); +alter table event_member add foreign key (role_id) references event_member_role(id); -- +goose StatementEnd -- +goose Down -- +goose StatementBegin -drop table IF EXISTS member_event_role CASCADE; -drop table IF EXISTS member_event CASCADE; +drop table IF EXISTS event_member_role CASCADE; +drop table IF EXISTS event_member CASCADE; -- +goose StatementEnd From 8ff10a8fbbd710c56dd0f8da0fd36ca4bb8b4e37 Mon Sep 17 00:00:00 2001 From: pai0id Date: Tue, 16 Jul 2024 13:04:10 +0300 Subject: [PATCH 05/21] migrations refactor init files done --- migrations/001_init_database.sql | 177 ++++++++++++++++-- migrations/002_init_clubs.sql | 95 ++++++++++ migrations/002_new_structures_sql.sql | 57 ------ ...ments_table.sql => 003_init_documents.sql} | 7 +- migrations/003_insert_club_test_data.sql | 34 ---- ...ideo_table.sql => 004_init_main_video.sql} | 5 +- migrations/004_insert_feed_test_data.sql | 40 ---- .../005_added_tree_structure_to_clubs.sql | 14 -- ...a_table.sql => 005_init_default_media.sql} | 7 +- migrations/006_add_orgs_to_clubs.sql | 36 ---- ...t_member.sql => 006_init_event_member.sql} | 2 +- migrations/007_add_club_photo_for_test.sql | 32 ---- migrations/008_alter_media_tbl.sql | 13 -- migrations/009_insert_mediafile_test_data.sql | 26 --- migrations/012_insert_documents_test_data.sql | 22 --- migrations/015_insert_default_media.sql | 19 -- migrations/016_init_role_table.sql | 42 ----- 17 files changed, 271 insertions(+), 357 deletions(-) create mode 100644 migrations/002_init_clubs.sql delete mode 100644 migrations/002_new_structures_sql.sql rename migrations/{011_init_documents_table.sql => 003_init_documents.sql} (90%) delete mode 100644 migrations/003_insert_club_test_data.sql rename migrations/{013_init_video_table.sql => 004_init_main_video.sql} (94%) delete mode 100644 migrations/004_insert_feed_test_data.sql delete mode 100644 migrations/005_added_tree_structure_to_clubs.sql rename migrations/{014_init_default_media_table.sql => 005_init_default_media.sql} (79%) delete mode 100644 migrations/006_add_orgs_to_clubs.sql rename migrations/{017_init_event_member.sql => 006_init_event_member.sql} (97%) delete mode 100644 migrations/007_add_club_photo_for_test.sql delete mode 100644 migrations/008_alter_media_tbl.sql delete mode 100644 migrations/009_insert_mediafile_test_data.sql delete mode 100644 migrations/012_insert_documents_test_data.sql delete mode 100644 migrations/015_insert_default_media.sql delete mode 100644 migrations/016_init_role_table.sql diff --git a/migrations/001_init_database.sql b/migrations/001_init_database.sql index 0c02fb7..749294e 100644 --- a/migrations/001_init_database.sql +++ b/migrations/001_init_database.sql @@ -1,5 +1,6 @@ -- +goose Up -- +goose StatementBegin + create table IF NOT EXISTS member ( id serial primary key, @@ -9,17 +10,9 @@ create table IF NOT EXISTS member telegram text default '', vk text default '', name text default '', - role_id int default 0, is_admin boolean default false ); -create table IF NOT EXISTS member_role -( - role_id serial primary key, - role_name text not null, - role_spec text not null -); - CREATE table IF NOT EXISTS feed ( id serial primary key, @@ -38,7 +31,21 @@ CREATE table IF NOT EXISTS feed create table if not exists mediafile ( id serial primary key, name text default '', - image text default '' + key text not null unique +); + +alter table member add foreign key (media_id) references mediafile(id); + +alter table feed add foreign key (media_id) references mediafile(id); +alter table feed add foreign key (created_by) references member(id); + +----------------------------------------------------- + +create table if not exists encounter ( + id serial primary key, + count text default '', + description text default '', + club_id int not null ); create table IF NOT EXISTS event @@ -58,21 +65,159 @@ create table IF NOT EXISTS event feedback_url text default '' ); -alter table member add foreign key (media_id) references mediafile(id); +create table if not exists club ( + id serial primary key, + name text default '' unique, + short_name text default '', + description text default '', + type text default '', + logo int not null, + vk_url text default '', + tg_url text default '', + parent_id int default null +); -alter table feed add foreign key (media_id) references mediafile(id); -alter table feed add foreign key (created_by) references member(id); +create table IF NOT EXISTS club_role +( + id serial primary key, + role_name text not null, + role_spec text not null, + role_clearance int default 0 +); +-- 0 - гость +-- 1 - участник +-- 2 - руководитель +-- 3 - админ + +-- TODO in domain +create table if not exists club_photo ( + id serial primary key, + ref_num int default 0, + media_id int not null, + club_id int not null +); + +create table if not exists club_org ( + id serial primary key, + club_id int not null, + member_id int not null, + role_id int not null +); + +alter table encounter add foreign key (club_id) references club(id); +alter table club add FOREIGN KEY (logo) REFERENCES mediafile(id); +alter table club add FOREIGN KEY (parent_id) REFERENCES club(id); + +alter table event add foreign key (club_id) references club(id); alter table event add foreign key (media_id) references mediafile(id); alter table event add foreign key (main_org) references member(id); +alter table club_photo add FOREIGN KEY (media_id) REFERENCES mediafile(id); +alter table club_photo add FOREIGN KEY (club_id) REFERENCES club(id); + +alter table club_org add FOREIGN KEY (club_id) REFERENCES club(id); +alter table club_org add FOREIGN KEY (member_id) REFERENCES member(id); +alter table club_org add FOREIGN KEY (role_id) REFERENCES club_role(id); + +----------------------------------------------------- + +create table IF NOT EXISTS document +( + id serial primary key, + name text default '', + key text default '' unique, + club_id int not null, + category_id int not null +); + +create table IF NOT EXISTS category +( + id serial primary key, + name text default '' unique +); + +alter table document add foreign key (category_id) references category(id); +alter table document add foreign key (club_id) references club(id); + +----------------------------------------------------- + +create table IF NOT EXISTS main_video +( + id serial PRIMARY KEY, + name text DEFAULT '', + key text DEFAULT '', + club_id int NOT NULL, + current boolean default NULL, + FOREIGN KEY (club_id) REFERENCES club(id), + CONSTRAINT true_1_per_club UNIQUE (club_id, current) +); + +----------------------------------------------------- + +create table IF NOT EXISTS default_media +( + id serial PRIMARY KEY, + media_id int not null, + FOREIGN KEY (media_id) REFERENCES mediafile(id) +); + +----------------------------------------------------- + +create table IF NOT EXISTS event_member +( + id serial primary key, + event_id int not null, + member_id int not null, + role_id int not null, + division text default '' +); + +create table IF NOT EXISTS event_member_role +( + id serial primary key, + name text not null +); + +alter table event_member add foreign key (event_id) references event(id); +alter table event_member add foreign key (member_id) references member(id); +alter table event_member add foreign key (role_id) references event_member_role(id); + -- +goose StatementEnd -- +goose Down -- +goose StatementBegin -drop table IF EXISTS member_role CASCADE; -drop table IF EXISTS member CASCADE; -drop table IF EXISTS feed CASCADE; + +drop table IF EXISTS event_member_role CASCADE; +drop table IF EXISTS event_member CASCADE; + +---------------------- + +drop table IF EXISTS default_media CASCADE; + +---------------------- + +drop table IF EXISTS main_video CASCADE; + +---------------------- + +drop table IF EXISTS category CASCADE; +drop table IF EXISTS document CASCADE; + +---------------------- + +drop table IF EXISTS club_org CASCADE; +drop table IF EXISTS club_photo CASCADE; +drop table IF EXISTS club_role CASCADE; +drop table IF EXISTS club CASCADE; drop table IF EXISTS event CASCADE; +drop table IF EXISTS encounter CASCADE; + + +----------------------- + drop table IF EXISTS mediafile CASCADE; --- +goose StatementEnd +drop table IF EXISTS feed CASCADE; +drop table IF EXISTS member CASCADE; + +-- +goose StatementEnd \ No newline at end of file diff --git a/migrations/002_init_clubs.sql b/migrations/002_init_clubs.sql new file mode 100644 index 0000000..562f0ac --- /dev/null +++ b/migrations/002_init_clubs.sql @@ -0,0 +1,95 @@ +-- +goose Up +-- +goose StatementBegin + +create table if not exists encounter ( + id serial primary key, + count text default '', + description text default '', + club_id int not null +); + +create table IF NOT EXISTS event +( + id serial primary key, + title text not null, + description text not null, + prompt text not null, + media_id int not null, + date timestamp not null, + approved boolean default false, + created_at timestamp not null, + club_id int not null, + main_org int not null, + reg_url text default '', + reg_open_date timestamp not null, + feedback_url text default '' +); + +create table if not exists club ( + id serial primary key, + name text default '' unique, + short_name text default '', + description text default '', + type text default '', + logo int not null, + vk_url text default '', + tg_url text default '', + parent_id int default null +); + +create table IF NOT EXISTS club_role +( + id serial primary key, + role_name text not null, + role_spec text not null, + role_clearance int default 0 +); +-- 0 - гость +-- 1 - участник +-- 2 - руководитель +-- 3 - админ + +-- TODO in domain +create table if not exists club_photo ( + id serial primary key, + ref_num int default 0, + media_id int not null, + club_id int not null +); + +create table if not exists club_org ( + id serial primary key, + club_id int not null, + member_id int not null, + role_id int not null +); + +alter table encounter add foreign key (club_id) references club(id); + +alter table club add FOREIGN KEY (logo) REFERENCES mediafile(id); +alter table club add FOREIGN KEY (parent_id) REFERENCES club(id); + +alter table event add foreign key (club_id) references club(id); +alter table event add foreign key (media_id) references mediafile(id); +alter table event add foreign key (main_org) references member(id); + +alter table club_photo add FOREIGN KEY (media_id) REFERENCES mediafile(id); +alter table club_photo add FOREIGN KEY (club_id) REFERENCES club(id); + +alter table club_org add FOREIGN KEY (club_id) REFERENCES club(id); +alter table club_org add FOREIGN KEY (member_id) REFERENCES member(id); +alter table club_org add FOREIGN KEY (role_id) REFERENCES club_role(id); + +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin + +drop table IF EXISTS club_org CASCADE; +drop table IF EXISTS club_photo CASCADE; +drop table IF EXISTS club_role CASCADE; +drop table IF EXISTS club CASCADE; +drop table IF EXISTS event CASCADE; +drop table IF EXISTS encounter CASCADE; + +-- +goose StatementEnd \ No newline at end of file diff --git a/migrations/002_new_structures_sql.sql b/migrations/002_new_structures_sql.sql deleted file mode 100644 index b771370..0000000 --- a/migrations/002_new_structures_sql.sql +++ /dev/null @@ -1,57 +0,0 @@ --- +goose Up --- +goose StatementBegin - -create table if not exists encounter ( - id serial primary key, - count text default '', - description text default '', - club_id int not null -); - -create table if not exists club ( - id serial primary key, - name text default '' unique, - short_name text default '', - description text default '', - type text default '', - logo int not null, - vk_url text default '', - tg_url text default '' -); - --- TODO in domain -create table if not exists club_photo ( - id serial primary key, - ref_num int default 0, - media_id int not null, - club_id int not null -); - -create table if not exists club_org ( - id serial primary key, - club_id int not null, - member_id int not null, - role_name text default '', - role_spec text default '' -); - -alter table encounter add foreign key (club_id) references club(id); - -alter table club add FOREIGN KEY (logo) REFERENCES mediafile(id); -alter table event add foreign key (club_id) references club(id); - -alter table club_photo add FOREIGN KEY (media_id) REFERENCES mediafile(id); -alter table club_photo add FOREIGN KEY (club_id) REFERENCES club(id); - -alter table club_org add FOREIGN KEY (club_id) REFERENCES club(id); -alter table club_org add FOREIGN KEY (member_id) REFERENCES member(id); - --- +goose StatementEnd - --- +goose Down --- +goose StatementBegin -drop table if exists encounter CASCADE; -drop table if exists club_photo CASCADE; -drop table if exists club_org CASCADE; -drop table if exists club CASCADE; --- +goose StatementEnd diff --git a/migrations/011_init_documents_table.sql b/migrations/003_init_documents.sql similarity index 90% rename from migrations/011_init_documents_table.sql rename to migrations/003_init_documents.sql index 79933bc..e7e1ba7 100644 --- a/migrations/011_init_documents_table.sql +++ b/migrations/003_init_documents.sql @@ -1,5 +1,6 @@ -- +goose Up -- +goose StatementBegin + create table IF NOT EXISTS document ( id serial primary key, @@ -22,6 +23,8 @@ alter table document add foreign key (club_id) references club(id); -- +goose Down -- +goose StatementBegin + +drop table IF EXISTS category CASCADE; drop table IF EXISTS document CASCADE; -drop table IF EXISTS category CASCADE; --- +goose StatementEnd + +-- +goose StatementEnd \ No newline at end of file diff --git a/migrations/003_insert_club_test_data.sql b/migrations/003_insert_club_test_data.sql deleted file mode 100644 index 6441d91..0000000 --- a/migrations/003_insert_club_test_data.sql +++ /dev/null @@ -1,34 +0,0 @@ --- +goose Up --- +goose StatementBegin - -INSERT INTO mediafile (id, name, image) -VALUES -(0, 'default', 'default'); -- Important, do not remove - -INSERT INTO mediafile (name, image) -VALUES -('IT-dep.jpg', 'image1.jpg'), -('NIT-dep.jpg', 'image2.jpg'), -('Finance-dep.jpg', 'image3.jpg'); - -INSERT INTO club (id, logo) VALUES (0, 0); -- Important, do not remove -INSERT INTO club (name, short_name, description, type, logo, vk_url, tg_url) -VALUES -('IT-department', 'IT-dep', 'Typo iT', 'IT', 1, 'vk.com', 'tg.me'), -('Not IT-department', 'NIT-dep', 'Typo Ne iT', 'IT', 1, 'vk.com', 'tg.me'), -('Finance-department', 'Finance-dep', 'Typo Fin', 'Finance', 2, 'vk.com', 'tg.me'), -('HR-department', 'HR-dep', 'Typo Hr', 'HR', 2, 'vk.com', 'tg.me'), -('Marketing-department', 'Marketing-dep', 'Typo Mark', 'Marketing' , 3, 'vk.com', 'tg.me'), -('Sales-department', 'Sales-dep', 'Typo Sa', 'Sales', 3, 'vk.com', 'tg.me'), -('Engineering-department', 'Engineering-dep', 'Typo Eng', 'Engineering', 3, 'vk.com', 'tg.me'); - - --- +goose StatementEnd - --- +goose Down --- +goose StatementBegin - -DELETE FROM club; -DELETE FROM mediafile; - --- +goose StatementEnd \ No newline at end of file diff --git a/migrations/013_init_video_table.sql b/migrations/004_init_main_video.sql similarity index 94% rename from migrations/013_init_video_table.sql rename to migrations/004_init_main_video.sql index 149b7b8..d55bf3e 100644 --- a/migrations/013_init_video_table.sql +++ b/migrations/004_init_main_video.sql @@ -1,5 +1,6 @@ -- +goose Up -- +goose StatementBegin + create table IF NOT EXISTS main_video ( id serial PRIMARY KEY, @@ -15,5 +16,7 @@ create table IF NOT EXISTS main_video -- +goose Down -- +goose StatementBegin + drop table IF EXISTS main_video CASCADE; --- +goose StatementEnd + +-- +goose StatementEnd \ No newline at end of file diff --git a/migrations/004_insert_feed_test_data.sql b/migrations/004_insert_feed_test_data.sql deleted file mode 100644 index 92a0487..0000000 --- a/migrations/004_insert_feed_test_data.sql +++ /dev/null @@ -1,40 +0,0 @@ --- +goose Up --- +goose StatementBegin - -INSERT INTO member_role (role_name, role_spec) VALUES -('admin', 'admin'), -('user', 'user'); - -INSERT INTO member (hash_password, login, media_id, role_id) -VALUES -('1234', '1234', 1, 1), -('1', '1', 2, 2); - -INSERT INTO feed (title, approved, description, media_id, vk_post_url, updated_at, created_at, views, created_by) -VALUES -('11', true, '33', 1, '132', '2004-10-19 10:23:54', '2004-10-19 10:23:54', 13, 1), -('1', true, '33', 2, '132', '2004-10-19 10:23:54', '2004-10-19 10:23:54', 13, 1), -('22', false, '44', 3, '321', '2005-11-19 10:23:54', '1900-10-19 10:23:54', 14, 2); - -INSERT INTO encounter (count, description, club_id) -VALUES -('1', 'kcoc', 0), -('11', 'kcoc', 0), -('2', 'sllab', 1), -('22', 'sllab', 2); - -INSERT INTO event (title, description, prompt, media_id, date, approved, created_at, main_org, reg_url, reg_open_date, feedback_url, club_id) -VALUES -('kcoc', 'sllab', 'kcid', 1, '2005-11-19 10:23:54', true, '2005-11-19 10:23:54', 1, 'ahh', '2005-11-19 10:23:54', '123', 1), -('sinep', 'stun', 'nibor', 1, '2005-11-19 10:23:54', true, '2005-11-19 10:23:54', 2, 'ahh', '2005-11-19 10:23:54', '123', 0); - --- +goose StatementEnd - --- +goose Down --- +goose StatementBegin -DELETE FROM encounter; -DELETE FROM feed; -DELETE FROM event; -DELETE FROM member; -DELETE FROM member_role; --- +goose StatementEnd \ No newline at end of file diff --git a/migrations/005_added_tree_structure_to_clubs.sql b/migrations/005_added_tree_structure_to_clubs.sql deleted file mode 100644 index 452ead4..0000000 --- a/migrations/005_added_tree_structure_to_clubs.sql +++ /dev/null @@ -1,14 +0,0 @@ --- +goose Up --- +goose StatementBegin - -ALTER TABLE club ADD COLUMN parent_id int default null; -alter table club add FOREIGN KEY (parent_id) REFERENCES club(id); - --- +goose StatementEnd - --- +goose Down --- +goose StatementBegin - -ALTER TABLE club DROP COLUMN parent_id; - --- +goose StatementEnd \ No newline at end of file diff --git a/migrations/014_init_default_media_table.sql b/migrations/005_init_default_media.sql similarity index 79% rename from migrations/014_init_default_media_table.sql rename to migrations/005_init_default_media.sql index edb19f2..9ddd31b 100644 --- a/migrations/014_init_default_media_table.sql +++ b/migrations/005_init_default_media.sql @@ -1,5 +1,6 @@ -- +goose Up -- +goose StatementBegin + create table IF NOT EXISTS default_media ( id serial PRIMARY KEY, @@ -11,5 +12,7 @@ create table IF NOT EXISTS default_media -- +goose Down -- +goose StatementBegin -drop table IF EXISTS default_media; --- +goose StatementEnd + +drop table IF EXISTS default_media CASCADE; + +-- +goose StatementEnd \ No newline at end of file diff --git a/migrations/006_add_orgs_to_clubs.sql b/migrations/006_add_orgs_to_clubs.sql deleted file mode 100644 index 0052fd6..0000000 --- a/migrations/006_add_orgs_to_clubs.sql +++ /dev/null @@ -1,36 +0,0 @@ --- +goose Up --- +goose StatementBegin - -INSERT INTO member (hash_password, login, media_id, telegram, vk, name, is_admin) -VALUES -('test', 'toha', 1, '@toha', 'vk.com/toha', 'Антон Павленко', true), -('$2a$10$kj0GwI3q1H0PgOzuLqK5uOhPPvA42upL8CdIm/4luikQBYNKVxXay', 'imp', 1, '@imp', 'vk.com/imp', 'Дмитрий Шахнович', true), -('test', 'dasha', 1, '@dasha', 'vk.com/dasha', 'Дарья Серышева', true), -('test', 'paioid', 1, '@paioid', 'vk.com/paioid', 'Андрей Поляков', true), -('test', 'admin', 1, '@admin', 'vk.com/admin', 'Админ', true), -('test', 'user', 1, '@user', 'vk.com/user', 'Юзер', true), -('test', 'user2', 1, '@user2', 'vk.com/user2', 'Юзер2', true); - - -INSERT INTO club_org (club_id, member_id, role_name, role_spec) -VALUES -(1, 1, 'Молодец', 'IT'), -(1, 1, 'Красава', 'NIT'), -(1, 2, 'Веселый', 'Finance'), -(1, 2, 'Хорошо', 'HR'), -(1, 3, 'Богатый', 'Marketing'), -(1, 3, 'Молодец', 'Sales'), -(2, 4, 'Умный', 'Engineering'); - -UPDATE club -SET parent_id = 1 -WHERE id = 2; - --- +goose StatementEnd - --- +goose Down --- +goose StatementBegin - -DELETE FROM club_org; - --- +goose StatementEnd \ No newline at end of file diff --git a/migrations/017_init_event_member.sql b/migrations/006_init_event_member.sql similarity index 97% rename from migrations/017_init_event_member.sql rename to migrations/006_init_event_member.sql index 18329e0..57dcf7e 100644 --- a/migrations/017_init_event_member.sql +++ b/migrations/006_init_event_member.sql @@ -28,4 +28,4 @@ alter table event_member add foreign key (role_id) references event_member_role( drop table IF EXISTS event_member_role CASCADE; drop table IF EXISTS event_member CASCADE; --- +goose StatementEnd +-- +goose StatementEnd \ No newline at end of file diff --git a/migrations/007_add_club_photo_for_test.sql b/migrations/007_add_club_photo_for_test.sql deleted file mode 100644 index cd19850..0000000 --- a/migrations/007_add_club_photo_for_test.sql +++ /dev/null @@ -1,32 +0,0 @@ --- +goose Up --- +goose StatementBegin - -INSERT INTO mediafile (name, image) -VALUES -('4.jpg', 'image4.jpg'), -('5.jpg', 'image5.jpg'), -('6.jpg', 'image6.jpg'), -('7.jpg', 'image7.jpg'), -('8.jpg', 'image8.jpg'), -('9.jpg', 'image9.jpg'); - -INSERT INTO club_photo (club_id, media_id, ref_num) -VALUES -(1, 1, 1), -(1, 1, 2), -(2, 1, 1), -(2, 1, 2), -(3, 1, 1), -(3, 1, 2), -(3, 1, 3), -(3, 1, 4), -(3, 1, 5); - --- +goose StatementEnd - --- +goose Down --- +goose StatementBegin - -DELETE FROM club_photo; - --- +goose StatementEnd \ No newline at end of file diff --git a/migrations/008_alter_media_tbl.sql b/migrations/008_alter_media_tbl.sql deleted file mode 100644 index 48e6111..0000000 --- a/migrations/008_alter_media_tbl.sql +++ /dev/null @@ -1,13 +0,0 @@ --- +goose Up --- +goose StatementBegin -ALTER table mediafile rename column image to image_url; - -ALTER table mediafile ALTER column image_url type TEXT; -update mediafile set image_url = 'localhost:5000/about/arch.png'; - --- +goose StatementEnd - --- +goose Down --- +goose StatementBegin - --- +goose StatementEnd diff --git a/migrations/009_insert_mediafile_test_data.sql b/migrations/009_insert_mediafile_test_data.sql deleted file mode 100644 index 8a9ba2c..0000000 --- a/migrations/009_insert_mediafile_test_data.sql +++ /dev/null @@ -1,26 +0,0 @@ --- +goose Up --- +goose StatementBegin - -ALTER TABLE mediafile RENAME column image_url TO key; - -UPDATE mediafile set key = 'arch.png' where id=1; -UPDATE mediafile set key = '2.jpg' where id=2; -UPDATE mediafile set key = '3.jpg' where id=3; -UPDATE mediafile set key = '4.jpg' where id=4; -UPDATE mediafile set key = '5.jpg' where id=5; -UPDATE mediafile set key = '6.jpg' where id=6; -UPDATE mediafile set key = '7.jpg' where id=7; -UPDATE mediafile set key = '8.jpg' where id=8; -UPDATE mediafile set key = '9.jpg' where id=9; -INSERT INTO mediafile (key, name) VALUES -('10.jpg', 'image10.jpg'), -('11.jpg', 'image11.jpg'), -('12.jpg', 'image12.jpg'); - -ALTER TABLE mediafile ADD CONSTRAINT key_unique UNIQUE (key) --- +goose StatementEnd - --- +goose Down --- +goose StatementBegin - --- +goose StatementEnd \ No newline at end of file diff --git a/migrations/012_insert_documents_test_data.sql b/migrations/012_insert_documents_test_data.sql deleted file mode 100644 index e2aca5f..0000000 --- a/migrations/012_insert_documents_test_data.sql +++ /dev/null @@ -1,22 +0,0 @@ --- +goose Up --- +goose StatementBegin - -INSERT INTO category (name) -VALUES -('first'), -('second'), -('third'); - -INSERT INTO document (name, key, club_id, category_id) -VALUES -('admin', 'admin', 0, 1), -('user', 'user', 1, 1), -('manager','manager', 1, 2); - --- +goose StatementEnd - --- +goose Down --- +goose StatementBegin -DELETE FROM document; -DELETE FROM category; --- +goose StatementEnd \ No newline at end of file diff --git a/migrations/015_insert_default_media.sql b/migrations/015_insert_default_media.sql deleted file mode 100644 index eecedb1..0000000 --- a/migrations/015_insert_default_media.sql +++ /dev/null @@ -1,19 +0,0 @@ --- +goose Up --- +goose StatementBegin -INSERT INTO default_media (media_id) -VALUES -(1), -(1), -(1), -(1), -(1), -(1), -(1), -(1); - --- +goose StatementEnd - --- +goose Down --- +goose StatementBegin -DELETE FROM default_media; --- +goose StatementEnd diff --git a/migrations/016_init_role_table.sql b/migrations/016_init_role_table.sql deleted file mode 100644 index b081622..0000000 --- a/migrations/016_init_role_table.sql +++ /dev/null @@ -1,42 +0,0 @@ --- +goose Up --- +goose StatementBegin - - -ALTER TABLE member_role RENAME TO club_role; -ALTER TABLE member DROP COLUMN role_id; -ALTER TABLE club_org DROP COLUMN role_spec; -ALTER TABLE club_org DROP COLUMN role_name; -ALTER TABLE club_role RENAME COLUMN role_id TO id; -ALTER TABLE club_org ADD COLUMN role_id int references club_role(id); - --- 0 - гость --- 1 - участник --- 2 - руководитель --- 3 - админ -ALTER TABLE club_role ADD COLUMN role_clearance int; - - -INSERT INTO club_role (role_name, role_spec, role_clearance) -VALUES -('IT бог', 'Глава ИТЭ', 2), -('Программист', 'Программист', 2), -('Тестировщик', 'Тестировщик', 2), -('Бухгалтер', 'Бухгалтер', 2), -('Старший участник', 'Старший участник', 2), -('Младший участник', 'Младший участник', 2), -('Гость', 'Гость', 2); - -UPDATE club_org SET role_id = 1 WHERE id = 1; -UPDATE club_org SET role_id = 2 WHERE id = 2; -UPDATE club_org SET role_id = 3 WHERE id = 3; -UPDATE club_org SET role_id = 4 WHERE id = 4; -UPDATE club_org SET role_id = 5 WHERE id = 5; -UPDATE club_org SET role_id = 6 WHERE id = 6; -UPDATE club_org SET role_id = 7 WHERE id = 7; - --- +goose StatementEnd - --- +goose Down --- +goose StatementBegin -ALTER TABLE member Add COLUMN role_id int; --- +goose StatementEnd From b39c3a64167339fe2282e982c414aff681399524 Mon Sep 17 00:00:00 2001 From: pai0id Date: Tue, 16 Jul 2024 13:20:34 +0300 Subject: [PATCH 06/21] doc path now category --- internal/app/documents.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/app/documents.go b/internal/app/documents.go index 5703e50..c658b11 100644 --- a/internal/app/documents.go +++ b/internal/app/documents.go @@ -63,7 +63,7 @@ func (s *DocumentsService) GetDocumentsByClubID(ctx context.Context, clubID int) } func (s *DocumentsService) PostDocument(ctx context.Context, doc *requests.PostDocument) (*responses.PostDocument, error) { - var key = fmt.Sprintf("%d/%s", doc.ClubID, doc.Name) + var key = fmt.Sprintf("%d/%s", doc.CategoryID, doc.Name) err := s.storage.PostDocument(ctx, doc.Name, key, doc.Data, doc.ClubID, doc.CategoryID) if err != nil { @@ -83,7 +83,7 @@ func (s *DocumentsService) DeleteDocument(ctx context.Context, id int) error { } func (s *DocumentsService) UpdateDocument(ctx context.Context, doc *requests.UpdateDocument) (*responses.UpdateDocument, error) { - var key = fmt.Sprintf("%d/%s", doc.ClubID, doc.Name) + var key = fmt.Sprintf("%d/%s", doc.CategoryID, doc.Name) err := s.storage.UpdateDocument(ctx, doc.ID, doc.Name, key, doc.Data, doc.ClubID, doc.CategoryID) if err != nil { From 28f60eaa4032bae33354460351d59d7b04af6dd2 Mon Sep 17 00:00:00 2001 From: pai0id Date: Tue, 16 Jul 2024 13:31:05 +0300 Subject: [PATCH 07/21] 001 cleanup --- migrations/001_init_database.sql | 172 ------------------------------- 1 file changed, 172 deletions(-) diff --git a/migrations/001_init_database.sql b/migrations/001_init_database.sql index 749294e..e9fa1f8 100644 --- a/migrations/001_init_database.sql +++ b/migrations/001_init_database.sql @@ -39,183 +39,11 @@ alter table member add foreign key (media_id) references mediafile(id); alter table feed add foreign key (media_id) references mediafile(id); alter table feed add foreign key (created_by) references member(id); ------------------------------------------------------ - -create table if not exists encounter ( - id serial primary key, - count text default '', - description text default '', - club_id int not null -); - -create table IF NOT EXISTS event -( - id serial primary key, - title text not null, - description text not null, - prompt text not null, - media_id int not null, - date timestamp not null, - approved boolean default false, - created_at timestamp not null, - club_id int not null, - main_org int not null, - reg_url text default '', - reg_open_date timestamp not null, - feedback_url text default '' -); - -create table if not exists club ( - id serial primary key, - name text default '' unique, - short_name text default '', - description text default '', - type text default '', - logo int not null, - vk_url text default '', - tg_url text default '', - parent_id int default null -); - -create table IF NOT EXISTS club_role -( - id serial primary key, - role_name text not null, - role_spec text not null, - role_clearance int default 0 -); --- 0 - гость --- 1 - участник --- 2 - руководитель --- 3 - админ - --- TODO in domain -create table if not exists club_photo ( - id serial primary key, - ref_num int default 0, - media_id int not null, - club_id int not null -); - -create table if not exists club_org ( - id serial primary key, - club_id int not null, - member_id int not null, - role_id int not null -); - -alter table encounter add foreign key (club_id) references club(id); - -alter table club add FOREIGN KEY (logo) REFERENCES mediafile(id); -alter table club add FOREIGN KEY (parent_id) REFERENCES club(id); - -alter table event add foreign key (club_id) references club(id); -alter table event add foreign key (media_id) references mediafile(id); -alter table event add foreign key (main_org) references member(id); - -alter table club_photo add FOREIGN KEY (media_id) REFERENCES mediafile(id); -alter table club_photo add FOREIGN KEY (club_id) REFERENCES club(id); - -alter table club_org add FOREIGN KEY (club_id) REFERENCES club(id); -alter table club_org add FOREIGN KEY (member_id) REFERENCES member(id); -alter table club_org add FOREIGN KEY (role_id) REFERENCES club_role(id); - ------------------------------------------------------ - -create table IF NOT EXISTS document -( - id serial primary key, - name text default '', - key text default '' unique, - club_id int not null, - category_id int not null -); - -create table IF NOT EXISTS category -( - id serial primary key, - name text default '' unique -); - -alter table document add foreign key (category_id) references category(id); -alter table document add foreign key (club_id) references club(id); - ------------------------------------------------------ - -create table IF NOT EXISTS main_video -( - id serial PRIMARY KEY, - name text DEFAULT '', - key text DEFAULT '', - club_id int NOT NULL, - current boolean default NULL, - FOREIGN KEY (club_id) REFERENCES club(id), - CONSTRAINT true_1_per_club UNIQUE (club_id, current) -); - ------------------------------------------------------ - -create table IF NOT EXISTS default_media -( - id serial PRIMARY KEY, - media_id int not null, - FOREIGN KEY (media_id) REFERENCES mediafile(id) -); - ------------------------------------------------------ - -create table IF NOT EXISTS event_member -( - id serial primary key, - event_id int not null, - member_id int not null, - role_id int not null, - division text default '' -); - -create table IF NOT EXISTS event_member_role -( - id serial primary key, - name text not null -); - -alter table event_member add foreign key (event_id) references event(id); -alter table event_member add foreign key (member_id) references member(id); -alter table event_member add foreign key (role_id) references event_member_role(id); - -- +goose StatementEnd -- +goose Down -- +goose StatementBegin -drop table IF EXISTS event_member_role CASCADE; -drop table IF EXISTS event_member CASCADE; - ----------------------- - -drop table IF EXISTS default_media CASCADE; - ----------------------- - -drop table IF EXISTS main_video CASCADE; - ----------------------- - -drop table IF EXISTS category CASCADE; -drop table IF EXISTS document CASCADE; - ----------------------- - -drop table IF EXISTS club_org CASCADE; -drop table IF EXISTS club_photo CASCADE; -drop table IF EXISTS club_role CASCADE; -drop table IF EXISTS club CASCADE; -drop table IF EXISTS event CASCADE; -drop table IF EXISTS encounter CASCADE; - - ------------------------ - drop table IF EXISTS mediafile CASCADE; drop table IF EXISTS feed CASCADE; drop table IF EXISTS member CASCADE; From ec9041e480387df8c22745eb16c42505cacce51c Mon Sep 17 00:00:00 2001 From: Impervguin Date: Tue, 16 Jul 2024 14:56:03 +0300 Subject: [PATCH 08/21] fixed bcrypt too short password error --- internal/infrastructure/postgres/guard.go | 11 +++++++++++ internal/infrastructure/postgres/members.go | 4 ++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/internal/infrastructure/postgres/guard.go b/internal/infrastructure/postgres/guard.go index 7a34541..7c0c7f0 100644 --- a/internal/infrastructure/postgres/guard.go +++ b/internal/infrastructure/postgres/guard.go @@ -16,3 +16,14 @@ func (p *Postgres) AddMember(ctx context.Context, mem *domain.Member) (int, erro } return id, nil } + +const getMemberHash = `SELECT hash_password FROM member WHERE login = $1` + +func (p *Postgres) GetMemberHash(_ context.Context, login string) (string, error) { + var hash string + err := p.db.QueryRow(getMemberHash, login).Scan(&hash) + if err != nil { + return "", wrapPostgresError(err) + } + return hash, nil +} diff --git a/internal/infrastructure/postgres/members.go b/internal/infrastructure/postgres/members.go index 18a4390..9c9325e 100644 --- a/internal/infrastructure/postgres/members.go +++ b/internal/infrastructure/postgres/members.go @@ -175,12 +175,12 @@ func (p *Postgres) UpdateMember(ctx context.Context, member *domain.Member) erro return nil } -const getMemberByLoginQuery = "SELECT id, login FROM member WHERE login=$1;" +const getMemberByLoginQuery = "SELECT id, login, hash_password, media_id, telegram, vk, name, is_admin FROM member WHERE login=$1;" func (p *Postgres) GetMemberByLogin(_ context.Context, login string) (*domain.Member, error) { var user domain.Member - err := p.db.QueryRow(getMemberByLoginQuery, login).Scan(&user.ID, &user.Login) + err := p.db.QueryRow(getMemberByLoginQuery, login).Scan(&user.ID, &user.Login, &user.HashPassword, &user.MediaID, &user.Telegram, &user.Vk, &user.Name, &user.IsAdmin) if err != nil { return nil, wrapPostgresError(err) } From f0add50f82e8432457ea19ea334bc1bf9feeb8e0 Mon Sep 17 00:00:00 2001 From: Impervguin Date: Tue, 16 Jul 2024 15:39:13 +0300 Subject: [PATCH 09/21] Tested and fixed club after adding club roles --- internal/app/club.go | 42 +++++++++++++----- internal/app/mapper/club.go | 43 ++++++++++++------- ...t-categories.go => document-categories.go} | 0 internal/app/media.go | 4 +- internal/infrastructure/postgres/club.go | 20 +++++---- internal/storage/guard.go | 3 +- migrations/004_insert_feed_test_data.sql | 5 --- migrations/006_add_orgs_to_clubs.sql | 1 + migrations/016_init_role_table.sql | 1 + 9 files changed, 77 insertions(+), 42 deletions(-) rename internal/app/mapper/{dcoument-categories.go => document-categories.go} (100%) diff --git a/internal/app/club.go b/internal/app/club.go index a0a543d..d6aaf41 100644 --- a/internal/app/club.go +++ b/internal/app/club.go @@ -8,6 +8,7 @@ import ( "github.com/STUD-IT-team/bmstu-stud-web-backend/internal/domain" "github.com/STUD-IT-team/bmstu-stud-web-backend/internal/domain/requests" "github.com/STUD-IT-team/bmstu-stud-web-backend/internal/domain/responses" + "github.com/STUD-IT-team/bmstu-stud-web-backend/internal/infrastructure/postgres" ) type clubStorage interface { @@ -47,14 +48,22 @@ func (s *ClubService) GetClub(ctx context.Context, id int) (*responses.GetClub, mainOrgs, err := s.storage.GetClubOrgs(ctx, id) if err != nil { - err = fmt.Errorf("can't storage.GetClubOrgs: %w", err) - return nil, err + if err == postgres.ErrPostgresNotFoundError { + mainOrgs = []domain.ClubOrg{} + } else { + err = fmt.Errorf("can't storage.GetClubOrgs: %w", err) + return nil, err + } } subOrgs, err := s.storage.GetClubSubOrgs(ctx, id) if err != nil { - err = fmt.Errorf("can't storage.GetClubSubOrgs: %w", err) - return nil, err + if err == postgres.ErrPostgresNotFoundError { + subOrgs = []domain.ClubOrg{} + } else { + err = fmt.Errorf("can't storage.GetClubSubOrgs: %w", err) + return nil, err + } } ids := make([]int, 0, len(mainOrgs)+len(subOrgs)+1) @@ -72,7 +81,7 @@ func (s *ClubService) GetClub(ctx context.Context, id int) (*responses.GetClub, return nil, err } - return mapper.MakeResponseClub(club, &mainOrgs, &subOrgs, &ims) + return mapper.MakeResponseClub(club, mainOrgs, subOrgs, ims) } func (s *ClubService) GetClubsByName(ctx context.Context, name string) (*responses.GetClubsByName, error) { @@ -173,12 +182,22 @@ func (s *ClubService) GetAllClubs(ctx context.Context) (*responses.GetAllClubs, func (s *ClubService) GetClubMembers(ctx context.Context, clubID int) (*responses.GetClubMembers, error) { orgs, err := s.storage.GetClubOrgs(ctx, clubID) if err != nil { - return nil, fmt.Errorf("can't storage.GetClubOrgs: %w", err) + if err == postgres.ErrPostgresNotFoundError { + orgs = []domain.ClubOrg{} + } else { + err = fmt.Errorf("can't storage.GetClubOrgs: %w", err) + return nil, err + } } subOrgs, err := s.storage.GetClubSubOrgs(ctx, clubID) if err != nil { - return nil, fmt.Errorf("can't storage.GetClubSubOrgs: %w", err) + if err == postgres.ErrPostgresNotFoundError { + subOrgs = []domain.ClubOrg{} + } else { + err = fmt.Errorf("can't storage.GetClubSubOrgs: %w", err) + return nil, err + } } if len(orgs)+len(subOrgs) == 0 { @@ -247,12 +266,13 @@ func (s *ClubService) UpdateClub(ctx context.Context, req *requests.UpdateClub) func (s *ClubService) GetClubMediaFiles(ctx context.Context, clubID int) (*responses.GetClubMedia, error) { clubPhotos, err := s.storage.GetClubMediaFiles(ctx, clubID) if err != nil { - return nil, fmt.Errorf("can't storage.GetClubMediaFiles: %w", err) + if err == postgres.ErrPostgresNotFoundError { + clubPhotos = []domain.ClubPhoto{} + } else { + return nil, fmt.Errorf("can't storage.GetClubMediaFiles: %w", err) + } } - if len(clubPhotos) == 0 { - return nil, fmt.Errorf("no club photo found") - } ids := make([]int, 0, len(clubPhotos)) for _, photo := range clubPhotos { ids = append(ids, photo.MediaID) diff --git a/internal/app/mapper/club.go b/internal/app/mapper/club.go index 70298c8..612673b 100644 --- a/internal/app/mapper/club.go +++ b/internal/app/mapper/club.go @@ -8,8 +8,8 @@ import ( "github.com/STUD-IT-team/bmstu-stud-web-backend/internal/domain/responses" ) -func MakeMainOrg(org *domain.ClubOrg, images *map[int]domain.MediaFile) (*responses.MainOrg, error) { - if _, ok := (*images)[org.MediaID]; !ok { +func MakeMainOrg(org *domain.ClubOrg, images map[int]domain.MediaFile) (*responses.MainOrg, error) { + if _, ok := images[org.MediaID]; !ok { return &responses.MainOrg{}, fmt.Errorf("can't find image for org id: %v", org.MediaID) } @@ -20,12 +20,12 @@ func MakeMainOrg(org *domain.ClubOrg, images *map[int]domain.MediaFile) (*respon TgUrl: org.Telegram, Spec: org.RoleSpec, RoleName: org.RoleName, - Image: (*images)[org.MediaID], + Image: images[org.MediaID], }, nil } -func MakeSubOrg(org *domain.ClubOrg, images *map[int]domain.MediaFile) (*responses.SubClubOrg, error) { - if _, ok := (*images)[org.MediaID]; !ok { +func MakeSubOrg(org *domain.ClubOrg, images map[int]domain.MediaFile) (*responses.SubClubOrg, error) { + if _, ok := images[org.MediaID]; !ok { return &responses.SubClubOrg{}, fmt.Errorf("can't find image for org id: %v", org.MediaID) } @@ -36,13 +36,13 @@ func MakeSubOrg(org *domain.ClubOrg, images *map[int]domain.MediaFile) (*respons VkUrl: org.Vk, TgUrl: org.Telegram, Spec: org.RoleSpec, - Image: (*images)[org.MediaID], + Image: images[org.MediaID], }, nil } -func MakeResponseClub(club *domain.Club, mainOrgs *[]domain.ClubOrg, subOrgs *[]domain.ClubOrg, images *map[int]domain.MediaFile) (*responses.GetClub, error) { - if _, ok := (*images)[club.LogoId]; !ok { +func MakeResponseClub(club *domain.Club, mainOrgs []domain.ClubOrg, subOrgs []domain.ClubOrg, images map[int]domain.MediaFile) (*responses.GetClub, error) { + if _, ok := images[club.LogoId]; !ok { return &responses.GetClub{}, fmt.Errorf("can't get logo media for club id: %v", club.LogoId) } @@ -50,14 +50,16 @@ func MakeResponseClub(club *domain.Club, mainOrgs *[]domain.ClubOrg, subOrgs *[] ID: club.ID, Name: club.Name, ShortName: club.ShortName, - Logo: (*images)[club.LogoId], + Logo: images[club.LogoId], Description: club.Description, Type: club.Type, VkUrl: club.VkUrl, TgUrl: club.TgUrl, + MainOrgs: make([]responses.MainOrg, 0), + SubOrgs: make([]responses.SubClubOrg, 0), } - for _, org := range *mainOrgs { + for _, org := range mainOrgs { m, err := MakeMainOrg(&org, images) if err != nil { return nil, err @@ -65,7 +67,7 @@ func MakeResponseClub(club *domain.Club, mainOrgs *[]domain.ClubOrg, subOrgs *[] r.MainOrgs = append(r.MainOrgs, *m) } - for _, org := range *subOrgs { + for _, org := range subOrgs { s, err := MakeSubOrg(&org, images) if err != nil { return nil, err @@ -89,6 +91,12 @@ func MakeResponseAllClub(clubs []domain.Club, logos map[int]domain.MediaFile, or orgMap[org.ClubID] = append(orgMap[org.ClubID], o) } + for _, club := range clubs { + if _, ok := orgMap[club.ID]; !ok { + orgMap[club.ID] = []responses.ClubOrg{} + } + } + for _, club := range clubs { if _, ok := logos[club.LogoId]; !ok { return nil, fmt.Errorf("can't find logo for club id %v", logos) @@ -111,11 +119,13 @@ func MakeResponseAllClub(clubs []domain.Club, logos map[int]domain.MediaFile, or func MakeResponseClubMembers(clubID int, mainOrgs []domain.ClubOrg, subOrgs []domain.ClubOrg, images map[int]domain.MediaFile) (*responses.GetClubMembers, error) { r := &responses.GetClubMembers{ - ID: clubID, + ID: clubID, + MainOrgs: []responses.MainOrg{}, + SubOrgs: []responses.SubClubOrg{}, } for _, org := range mainOrgs { - m, err := MakeMainOrg(&org, &images) + m, err := MakeMainOrg(&org, images) if err != nil { return nil, err } @@ -123,7 +133,7 @@ func MakeResponseClubMembers(clubID int, mainOrgs []domain.ClubOrg, subOrgs []do } for _, org := range subOrgs { - s, err := MakeSubOrg(&org, &images) + s, err := MakeSubOrg(&org, images) if err != nil { return nil, err } @@ -160,7 +170,10 @@ func ParsePostClub(req *requests.PostClub) (*domain.Club, []domain.ClubOrg, erro } func MakeResponseClubMediaFiles(clubID int, clubPhotos []domain.ClubPhoto, media map[int]domain.MediaFile) (*responses.GetClubMedia, error) { - r := &responses.GetClubMedia{ID: clubID} + r := &responses.GetClubMedia{ + ID: clubID, + Media: []responses.ClubMedia{}, + } for _, f := range clubPhotos { media, ok := media[f.MediaID] if !ok { diff --git a/internal/app/mapper/dcoument-categories.go b/internal/app/mapper/document-categories.go similarity index 100% rename from internal/app/mapper/dcoument-categories.go rename to internal/app/mapper/document-categories.go diff --git a/internal/app/media.go b/internal/app/media.go index ee3afbf..fc87ae9 100644 --- a/internal/app/media.go +++ b/internal/app/media.go @@ -40,7 +40,7 @@ func (s *MediaService) PostMedia(ctx context.Context, req *requests.PostMedia) ( return &responses.PostMedia{}, fmt.Errorf("can't storage.PutMedia: %v", err) } - return mapper.MakeResponsePostMedia(id), err + return mapper.MakeResponsePostMedia(id), nil } const bcryptCost = 12 @@ -56,7 +56,7 @@ func (s *MediaService) PostMediaBcrypt(ctx context.Context, req *requests.PostMe return &responses.PostMedia{}, fmt.Errorf("can't storage.PutMedia: %v", err) } - return mapper.MakeResponsePostMedia(id), fmt.Errorf("can't storage.UploadObject: %v", err) + return mapper.MakeResponsePostMedia(id), nil } func (s *MediaService) ClearUpMedia(ctx context.Context, logger *logrus.Logger) error { diff --git a/internal/infrastructure/postgres/club.go b/internal/infrastructure/postgres/club.go index 1659ab0..f26db80 100644 --- a/internal/infrastructure/postgres/club.go +++ b/internal/infrastructure/postgres/club.go @@ -369,7 +369,6 @@ JOIN telegram, vk, name, - role_id, is_admin FROM member ) mem @@ -454,7 +453,6 @@ JOIN telegram, vk, name, - role_id, is_admin FROM member ) mem @@ -467,6 +465,7 @@ JOIN FROM club WHERE id > 0 ) as clubs +ON (club_org.club_id = clubs.id) JOIN ( SELECT @@ -477,7 +476,6 @@ JOIN WHERE role_clearance = 2 ) as orgs ON orgs.id = club_org.role_id -ON (club_org.club_id = clubs.id) ` func (s *Postgres) GetAllClubOrgs(_ context.Context) ([]domain.ClubOrg, error) { @@ -560,7 +558,7 @@ const addOrgs = ` INSERT INTO club_org ( role_id, member_id, - club_id, + club_id ) VALUES ($1, $2, $3) ` @@ -620,8 +618,8 @@ func (s *Postgres) GetClubMediaFiles(clubID int) ([]domain.ClubPhoto, error) { } const deleteClub = "DELETE FROM club WHERE id = $1" -const deleteClubOrgs = "DELETE FROM club_org WHERE club_id = $1" -const deleteClubMembers = "DELETE FROM member WHERE club_id = $1" +const deleteClubOrgs = "DELETE FROM club_org using club_role WHERE club_id = $1 and club_role.id = club_org.role_id and club_role.role_clearance = 2" +const deleteClubMembers = "DELETE FROM club_org WHERE club_id = $1" const deleteClubPhotos = "DELETE FROM club_photo WHERE club_id = $1" const deleteClubEncounters = "DELETE FROM encounter WHERE club_id = $1" const deleteClubDocuments = "DELETE FROM document WHERE club_id = $1" @@ -633,7 +631,7 @@ func (s *Postgres) DeleteClubWithOrgs(_ context.Context, clubID int) error { return wrapPostgresError(err) } - _, err = tx.Exec(deleteClubOrgs, clubID) + _, err = tx.Exec(deleteClubMembers, clubID) if err != nil { tx.Rollback() return wrapPostgresError(err) @@ -721,7 +719,13 @@ func (s *Postgres) UpdateClub(_ context.Context, c *domain.Club, o []domain.Club } for _, org := range o { - _, err = tx.Exec(addOrgs, org.RoleName, org.RoleSpec, org.ID, c.ID) + var id int + err := s.db.QueryRow(addOrgRole, org.RoleName, org.RoleSpec).Scan(&id) + if err != nil { + tx.Rollback() + return wrapPostgresError(err) + } + _, err = tx.Exec(addOrgs, id, org.ID, org.ClubID) if err != nil { tx.Rollback() return wrapPostgresError(err) diff --git a/internal/storage/guard.go b/internal/storage/guard.go index 3b95f3a..1e8deb9 100644 --- a/internal/storage/guard.go +++ b/internal/storage/guard.go @@ -2,6 +2,7 @@ package storage import ( "context" + "fmt" "time" "github.com/STUD-IT-team/bmstu-stud-web-backend/internal/domain" @@ -36,7 +37,7 @@ func (s *storage) GetMemberAndValidatePassword(ctx context.Context, login string err = hasher.CompareHashAndPassword(user.HashPassword, []byte(password)) if err != nil { - return domain.Member{}, err + return domain.Member{}, fmt.Errorf("%w, size: %v", err, len(user.HashPassword)) } return *user, nil diff --git a/migrations/004_insert_feed_test_data.sql b/migrations/004_insert_feed_test_data.sql index 92a0487..53d62d1 100644 --- a/migrations/004_insert_feed_test_data.sql +++ b/migrations/004_insert_feed_test_data.sql @@ -1,10 +1,6 @@ -- +goose Up -- +goose StatementBegin -INSERT INTO member_role (role_name, role_spec) VALUES -('admin', 'admin'), -('user', 'user'); - INSERT INTO member (hash_password, login, media_id, role_id) VALUES ('1234', '1234', 1, 1), @@ -36,5 +32,4 @@ DELETE FROM encounter; DELETE FROM feed; DELETE FROM event; DELETE FROM member; -DELETE FROM member_role; -- +goose StatementEnd \ No newline at end of file diff --git a/migrations/006_add_orgs_to_clubs.sql b/migrations/006_add_orgs_to_clubs.sql index 0052fd6..b896ab7 100644 --- a/migrations/006_add_orgs_to_clubs.sql +++ b/migrations/006_add_orgs_to_clubs.sql @@ -32,5 +32,6 @@ WHERE id = 2; -- +goose StatementBegin DELETE FROM club_org; +DELETE FROM member; -- +goose StatementEnd \ No newline at end of file diff --git a/migrations/016_init_role_table.sql b/migrations/016_init_role_table.sql index b081622..c56b30b 100644 --- a/migrations/016_init_role_table.sql +++ b/migrations/016_init_role_table.sql @@ -39,4 +39,5 @@ UPDATE club_org SET role_id = 7 WHERE id = 7; -- +goose Down -- +goose StatementBegin ALTER TABLE member Add COLUMN role_id int; +DROP TABLE club_role; -- +goose StatementEnd From 66cd44dd6c7dcda42b314eae20f88b1ac4dd871f Mon Sep 17 00:00:00 2001 From: Impervguin Date: Tue, 16 Jul 2024 15:41:25 +0300 Subject: [PATCH 10/21] Deleted empty result checks in service --- internal/app/club.go | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/internal/app/club.go b/internal/app/club.go index d6aaf41..da23ca4 100644 --- a/internal/app/club.go +++ b/internal/app/club.go @@ -91,10 +91,6 @@ func (s *ClubService) GetClubsByName(ctx context.Context, name string) (*respons return nil, err } - if len(res) == 0 { - return nil, fmt.Errorf("no club found") - } - ids := make([]int, 0, len(res)) for _, club := range res { ids = append(ids, club.LogoId) @@ -123,10 +119,6 @@ func (s *ClubService) GetClubsByType(ctx context.Context, type_ string) (*respon return nil, err } - if len(res) == 0 { - return nil, fmt.Errorf("no club found") - } - ids := make([]int, 0, len(res)) for _, club := range res { ids = append(ids, club.LogoId) @@ -156,10 +148,6 @@ func (s *ClubService) GetAllClubs(ctx context.Context) (*responses.GetAllClubs, return nil, err } - if len(res) == 0 { - return nil, fmt.Errorf("no club found") - } - ids := make([]int, 0, len(res)) for _, club := range res { ids = append(ids, club.LogoId) From 9abf1473bede14b3476963fe9eafcb1aed787d6a Mon Sep 17 00:00:00 2001 From: Impervguin Date: Tue, 16 Jul 2024 16:46:54 +0300 Subject: [PATCH 11/21] Added clearance handler for post in clubs --- internal/app/club.go | 7 ++++++ internal/domain/responses/get-clearance.go | 6 +++++ internal/ports/clubs.go | 27 ++++++++++++++++++++++ pkg/handler/response.go | 4 ++++ 4 files changed, 44 insertions(+) create mode 100644 internal/domain/responses/get-clearance.go diff --git a/internal/app/club.go b/internal/app/club.go index da23ca4..4aff3e6 100644 --- a/internal/app/club.go +++ b/internal/app/club.go @@ -272,3 +272,10 @@ func (s *ClubService) GetClubMediaFiles(ctx context.Context, clubID int) (*respo return mapper.MakeResponseClubMediaFiles(clubID, clubPhotos, media) } + +func (s *ClubService) GetClearancePost(ctx context.Context, resp *responses.CheckResponse) (*responses.GetClearance, error) { + if resp.IsAdmin { + return &responses.GetClearance{Access: true, Comment: ""}, nil + } + return &responses.GetClearance{Access: false, Comment: "only admins"}, nil +} diff --git a/internal/domain/responses/get-clearance.go b/internal/domain/responses/get-clearance.go new file mode 100644 index 0000000..c1c36ca --- /dev/null +++ b/internal/domain/responses/get-clearance.go @@ -0,0 +1,6 @@ +package responses + +type GetClearance struct { + Access bool `json:"access"` + Comment string `json:"Comment"` +} diff --git a/internal/ports/clubs.go b/internal/ports/clubs.go index 8af3638..2f469b8 100644 --- a/internal/ports/clubs.go +++ b/internal/ports/clubs.go @@ -46,10 +46,37 @@ func (h *ClubsHandler) Routes() chi.Router { r.Post("/", h.r.Wrap(h.PostClub)) r.Delete("/{club_id}", h.r.Wrap(h.DeleteClub)) r.Put("/{club_id}", h.r.Wrap(h.UpdateClub)) + r.Get("/clearance/post", h.r.Wrap(h.GetClearancePost)) return r } +func (h *ClubsHandler) GetClearancePost(w http.ResponseWriter, req *http.Request) handler.Response { + h.logger.Info("ClubsHandler: got PostClub request") + + access, err := getAccessToken(req) + if err != nil { + h.logger.Warnf("can't get access token: %v", err) + return handler.UnauthorizedResponse() + } + + resp, err := h.guard.Check(context.Background(), &requests.CheckRequest{AccessToken: access}) + if err != nil || !resp.Valid { + h.logger.Warnf("Unauthorized request: %v", err) + return handler.UnauthorizedResponse() + } + + h.logger.Infof("ClubsHandler: GetClearancePost Authenticated: %v", resp.MemberID) + + response, err := h.clubs.GetClearancePost(context.Background(), resp) + if err != nil { + h.logger.Warnf("can't clubs.GetClearancePost GetClearancePost: %v", err) + return handler.InternalServerErrorResponse() + } + + return handler.OkResponse(response) +} + // GetAllClubs // // @Summary Возвращает все клубы из БД diff --git a/pkg/handler/response.go b/pkg/handler/response.go index d4ba5aa..474544d 100644 --- a/pkg/handler/response.go +++ b/pkg/handler/response.go @@ -49,6 +49,10 @@ func UnauthorizedResponse() Response { return &response{head: map[string]string{}, body: nil, code: http.StatusUnauthorized} } +func ForbiddenResponse() Response { + return &response{head: map[string]string{}, body: nil, code: http.StatusForbidden} +} + func ConflictResponse() Response { return &response{head: map[string]string{}, body: nil, code: http.StatusConflict} } From 9d3f4d59eaaaca12ea2a102127894d0913c53ce7 Mon Sep 17 00:00:00 2001 From: Impervguin Date: Tue, 16 Jul 2024 18:09:02 +0300 Subject: [PATCH 12/21] Add post handler for club photo --- internal/app/club.go | 19 ++++++ internal/domain/requests/post-club-photo.go | 68 +++++++++++++++++++++ internal/domain/requests/post-club.go | 20 +++--- internal/domain/requests/update-club.go | 2 +- internal/infrastructure/postgres/club.go | 17 ++++++ internal/ports/clubs.go | 51 ++++++++++++++++ internal/storage/club.go | 5 ++ 7 files changed, 171 insertions(+), 11 deletions(-) create mode 100644 internal/domain/requests/post-club-photo.go diff --git a/internal/app/club.go b/internal/app/club.go index 4aff3e6..a8c3da8 100644 --- a/internal/app/club.go +++ b/internal/app/club.go @@ -27,6 +27,7 @@ type clubStorage interface { AddOrgs(ctx context.Context, orgs []domain.ClubOrg) error DeleteClubWithOrgs(ctx context.Context, clubID int) error UpdateClub(ctx context.Context, c *domain.Club, o []domain.ClubOrg) error + AddClubPhotos(ctx context.Context, p []domain.ClubPhoto) error } type ClubService struct { @@ -273,6 +274,24 @@ func (s *ClubService) GetClubMediaFiles(ctx context.Context, clubID int) (*respo return mapper.MakeResponseClubMediaFiles(clubID, clubPhotos, media) } +func (s *ClubService) PostClubPhoto(ctx context.Context, req *requests.PostClubPhoto) error { + photos := make([]domain.ClubPhoto, 0, len(req.Photos)) + for _, p := range req.Photos { + photos = append(photos, domain.ClubPhoto{ + ClubID: req.ClubID, + MediaID: p.MediaID, + RefNumber: p.RefNumber, + ID: 0, + }) + } + + err := s.storage.AddClubPhotos(ctx, photos) + if err != nil { + return fmt.Errorf("can't storage.AddClubPhotos: %w", err) + } + return nil +} + func (s *ClubService) GetClearancePost(ctx context.Context, resp *responses.CheckResponse) (*responses.GetClearance, error) { if resp.IsAdmin { return &responses.GetClearance{Access: true, Comment: ""}, nil diff --git a/internal/domain/requests/post-club-photo.go b/internal/domain/requests/post-club-photo.go new file mode 100644 index 0000000..21c805d --- /dev/null +++ b/internal/domain/requests/post-club-photo.go @@ -0,0 +1,68 @@ +package requests + +import ( + "encoding/json" + "fmt" + "net/http" + "strconv" + + "github.com/STUD-IT-team/bmstu-stud-web-backend/internal/domain" + "github.com/go-chi/chi" +) + +type PostClubPhoto struct { + ClubID int `json:"club_id"` + Photos []ClubPhoto `json:"photos"` +} + +type PostClubPhotoPointer struct { + ClubID int `json:"club_id"` + Photos []ClubPhoto `json:"photos"` +} + +type ClubPhoto struct { + MediaID int `json:"media_id"` + RefNumber int `json:"ref_number"` +} + +func (c *PostClubPhoto) Bind(req *http.Request) error { + id, err := strconv.Atoi(chi.URLParam(req, "club_id")) + if err != nil { + return fmt.Errorf("can't Atoi on club_id in request: %w", err) + } + pc := PostClubPhotoPointer{} + + decoder := json.NewDecoder(req.Body) + decoder.DisallowUnknownFields() + err = decoder.Decode(&pc) + + if err != nil { + return fmt.Errorf("can't json decoder on PostClub: %v", err) + } + + if decoder.More() { + return fmt.Errorf("postClub Bind: extraneous data after JSON object") + } + + err = pc.validate() + if err != nil { + return fmt.Errorf("%v: %v", domain.ErrIncorrectRequest, err) + } + *c = PostClubPhoto{ + ClubID: id, + Photos: pc.Photos, + } + return c.validate() + +} + +func (c *PostClubPhoto) validate() error { + return nil +} + +func (pc *PostClubPhotoPointer) validate() error { + if pc.Photos == nil { + return fmt.Errorf("require: photos") + } + return nil +} diff --git a/internal/domain/requests/post-club.go b/internal/domain/requests/post-club.go index 322880f..0bad638 100644 --- a/internal/domain/requests/post-club.go +++ b/internal/domain/requests/post-club.go @@ -21,15 +21,15 @@ type PostClub struct { } type PostClubPointer struct { - Name *string `json:"name"` - ShortName *string `json:"short_name"` - Description *string `json:"description"` - Type *string `json:"type"` - LogoId *int `json:"logo_id"` - VkUrl *string `json:"vk_url"` - TgUrl *string `json:"tg_url"` - ParentID *int `json:"parent_id"` - Orgs *[]ClubOrg `json:"orgs"` + Name *string `json:"name"` + ShortName *string `json:"short_name"` + Description *string `json:"description"` + Type *string `json:"type"` + LogoId *int `json:"logo_id"` + VkUrl *string `json:"vk_url"` + TgUrl *string `json:"tg_url"` + ParentID *int `json:"parent_id"` + Orgs []ClubOrg `json:"orgs"` } type ClubOrg struct { MemberID int `json:"member_id"` @@ -66,7 +66,7 @@ func (c *PostClub) Bind(req *http.Request) error { VkUrl: *pc.VkUrl, TgUrl: *pc.TgUrl, ParentID: *pc.ParentID, - Orgs: *pc.Orgs, + Orgs: pc.Orgs, } return c.validate() diff --git a/internal/domain/requests/update-club.go b/internal/domain/requests/update-club.go index 66e193e..b15e98d 100644 --- a/internal/domain/requests/update-club.go +++ b/internal/domain/requests/update-club.go @@ -55,7 +55,7 @@ func (p *UpdateClub) Bind(req *http.Request) error { VkUrl: *pf.VkUrl, TgUrl: *pf.TgUrl, ParentID: *pf.ParentID, - Orgs: *pf.Orgs, + Orgs: pf.Orgs, }, } diff --git a/internal/infrastructure/postgres/club.go b/internal/infrastructure/postgres/club.go index f26db80..1a2b39e 100644 --- a/internal/infrastructure/postgres/club.go +++ b/internal/infrastructure/postgres/club.go @@ -734,3 +734,20 @@ func (s *Postgres) UpdateClub(_ context.Context, c *domain.Club, o []domain.Club err = tx.Commit() return wrapPostgresError(err) } + +const addClubPhoto = "INSERT INTO club_photo (ref_num, club_id, media_id) VALUES ($1, $2, $3)" + +func (s *Postgres) AddClubPhotos(_ context.Context, p []domain.ClubPhoto) error { + tx, err := s.db.Begin() + if err != nil { + return wrapPostgresError(err) + } + for _, photo := range p { + _, err = tx.Exec(addClubPhoto, photo.RefNumber, photo.ClubID, photo.MediaID) + if err != nil { + tx.Rollback() + return wrapPostgresError(err) + } + } + return wrapPostgresError(tx.Commit()) +} diff --git a/internal/ports/clubs.go b/internal/ports/clubs.go index 2f469b8..662f4a3 100644 --- a/internal/ports/clubs.go +++ b/internal/ports/clubs.go @@ -46,6 +46,9 @@ func (h *ClubsHandler) Routes() chi.Router { r.Post("/", h.r.Wrap(h.PostClub)) r.Delete("/{club_id}", h.r.Wrap(h.DeleteClub)) r.Put("/{club_id}", h.r.Wrap(h.UpdateClub)) + r.Post("/media/{club_id}", h.r.Wrap(h.PostClubMedia)) + r.Delete("/media/{club_id}/{media_id}", h.r.Wrap(h.DeleteClubMedia)) + r.Put("/media/{club_id}", h.r.Wrap(h.UpdateClubMedia)) r.Get("/clearance/post", h.r.Wrap(h.GetClearancePost)) return r @@ -485,3 +488,51 @@ func (h *ClubsHandler) UpdateClub(w http.ResponseWriter, req *http.Request) hand return handler.OkResponse(nil) } + +func (h *ClubsHandler) PostClubMedia(w http.ResponseWriter, req *http.Request) handler.Response { + h.logger.Info("ClubsHandler: got PostClubMedia request") + + access, err := getAccessToken(req) + if err != nil { + h.logger.Warnf("can't get access token: %v", err) + return handler.UnauthorizedResponse() + } + + resp, err := h.guard.Check(context.Background(), &requests.CheckRequest{AccessToken: access}) + if err != nil || !resp.Valid { + h.logger.Warnf("Unauthorized request: %v", err) + return handler.UnauthorizedResponse() + } + + h.logger.Infof("ClubsHandler: PostClubMedia Authenticated: %v", resp.MemberID) + + photo := &requests.PostClubPhoto{} + err = photo.Bind(req) + if err != nil { + h.logger.Warnf("can't service.PostClubMedia %v", err) + return handler.BadRequestResponse() + } + + h.logger.Infof("ClubsHandler: parse request.") + + err = h.clubs.PostClubPhoto(context.Background(), photo) + if err != nil { + h.logger.Warnf("can't service.PostClubMedia %v", err) + if errors.Is(err, postgres.ErrPostgresUniqueConstraintViolation) { + return handler.ConflictResponse() + } else if errors.Is(err, postgres.ErrPostgresForeignKeyViolation) { + return handler.BadRequestResponse() + } + return handler.InternalServerErrorResponse() + } + + return handler.OkResponse(nil) +} + +func (h *ClubsHandler) DeleteClubMedia(w http.ResponseWriter, req *http.Request) handler.Response { + return handler.OkResponse(nil) +} + +func (h *ClubsHandler) UpdateClubMedia(w http.ResponseWriter, req *http.Request) handler.Response { + return handler.OkResponse(nil) +} diff --git a/internal/storage/club.go b/internal/storage/club.go index 912a2e2..f677706 100644 --- a/internal/storage/club.go +++ b/internal/storage/club.go @@ -20,6 +20,7 @@ type clubStorage interface { AddOrgs(ctx context.Context, orgs []domain.ClubOrg) error DeleteClubWithOrgs(ctx context.Context, clubID int) error UpdateClub(ctx context.Context, c *domain.Club, o []domain.ClubOrg) error + AddClubPhotos(ctx context.Context, p []domain.ClubPhoto) error } func (s *storage) GetClub(ctx context.Context, id int) (*domain.Club, error) { @@ -73,3 +74,7 @@ func (s *storage) DeleteClubWithOrgs(ctx context.Context, clubID int) error { func (s *storage) UpdateClub(ctx context.Context, c *domain.Club, o []domain.ClubOrg) error { return s.postgres.UpdateClub(ctx, c, o) } + +func (s *storage) AddClubPhotos(ctx context.Context, p []domain.ClubPhoto) error { + return s.postgres.AddClubPhotos(ctx, p) +} From 67b2dae2e5b42f1ddc649a54a99e46fa733eb93f Mon Sep 17 00:00:00 2001 From: Impervguin Date: Wed, 17 Jul 2024 12:02:37 +0300 Subject: [PATCH 13/21] Done DeleteClubPhoto handler --- internal/app/club.go | 20 ++++++ internal/domain/requests/delete-club-photo.go | 63 +++++++++++++++++++ .../domain/responses/delete-club-photo.go | 5 ++ internal/infrastructure/postgres/club.go | 23 +++++++ internal/ports/clubs.go | 37 ++++++++++- internal/storage/club.go | 10 +++ 6 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 internal/domain/requests/delete-club-photo.go create mode 100644 internal/domain/responses/delete-club-photo.go diff --git a/internal/app/club.go b/internal/app/club.go index a8c3da8..6f4eb7e 100644 --- a/internal/app/club.go +++ b/internal/app/club.go @@ -28,6 +28,8 @@ type clubStorage interface { DeleteClubWithOrgs(ctx context.Context, clubID int) error UpdateClub(ctx context.Context, c *domain.Club, o []domain.ClubOrg) error AddClubPhotos(ctx context.Context, p []domain.ClubPhoto) error + DeleteClubPhoto(ctx context.Context, ids int) error + GetPhotoClubID(ctx context.Context, photoID int) (int, error) } type ClubService struct { @@ -292,6 +294,24 @@ func (s *ClubService) PostClubPhoto(ctx context.Context, req *requests.PostClubP return nil } +func (s *ClubService) DeleteClubPhoto(ctx context.Context, req *requests.DeleteClubPhoto) error { + clubID, err := s.storage.GetPhotoClubID(ctx, req.PhotoID) + if err != nil { + if err == postgres.ErrPostgresNotFoundError { + return fmt.Errorf("photo not found") + } + return fmt.Errorf("can't storage.GetPhotoClubID: %w", err) + } + if clubID != req.ClubID { + return fmt.Errorf("photo is not from the specified club") + } + err = s.storage.DeleteClubPhoto(ctx, req.PhotoID) + if err != nil { + return fmt.Errorf("can't storage.DeleteClubPhoto: %w", err) + } + return nil +} + func (s *ClubService) GetClearancePost(ctx context.Context, resp *responses.CheckResponse) (*responses.GetClearance, error) { if resp.IsAdmin { return &responses.GetClearance{Access: true, Comment: ""}, nil diff --git a/internal/domain/requests/delete-club-photo.go b/internal/domain/requests/delete-club-photo.go new file mode 100644 index 0000000..9b7ad2e --- /dev/null +++ b/internal/domain/requests/delete-club-photo.go @@ -0,0 +1,63 @@ +package requests + +import ( + "encoding/json" + "fmt" + "net/http" + "strconv" + + "github.com/STUD-IT-team/bmstu-stud-web-backend/internal/domain" + "github.com/go-chi/chi" +) + +type DeleteClubPhoto struct { + PhotoID int `json:"photo_id"` + ClubID int `json:"club_id"` +} + +type DeleteClubPhotoPointer struct { + ClubID int `json:"club_id"` + PhotoID *int `json:"photo_id"` +} + +func (c *DeleteClubPhoto) Bind(req *http.Request) error { + clubID, err := strconv.Atoi(chi.URLParam(req, "club_id")) + if err != nil { + return fmt.Errorf("can't Atoi on club_id in request: %w", err) + } + + pc := DeleteClubPhotoPointer{} + + decoder := json.NewDecoder(req.Body) + decoder.DisallowUnknownFields() + err = decoder.Decode(&pc) + if err != nil { + return fmt.Errorf("can't json decoder on DeleteClubPhoto: %v", err) + } + if decoder.More() { + return fmt.Errorf("extraneous data after JSON object on DeleteClubPhoto") + } + + err = pc.validate() + if err != nil { + return fmt.Errorf("%v: %v", domain.ErrIncorrectRequest, err) + } + + c.ClubID = clubID + c.PhotoID = *pc.PhotoID + return c.validate() +} + +func (c *DeleteClubPhoto) validate() error { + if c.ClubID == 0 { + return fmt.Errorf("require: id") + } + return nil +} + +func (pc *DeleteClubPhotoPointer) validate() error { + if pc.PhotoID == nil { + return fmt.Errorf("require: photo_id") + } + return nil +} diff --git a/internal/domain/responses/delete-club-photo.go b/internal/domain/responses/delete-club-photo.go new file mode 100644 index 0000000..687e7a9 --- /dev/null +++ b/internal/domain/responses/delete-club-photo.go @@ -0,0 +1,5 @@ +package responses + +type DeleteClubPhoto struct { + Ids []int `json:"ids"` +} diff --git a/internal/infrastructure/postgres/club.go b/internal/infrastructure/postgres/club.go index 1a2b39e..6671280 100644 --- a/internal/infrastructure/postgres/club.go +++ b/internal/infrastructure/postgres/club.go @@ -751,3 +751,26 @@ func (s *Postgres) AddClubPhotos(_ context.Context, p []domain.ClubPhoto) error } return wrapPostgresError(tx.Commit()) } + +const deleteClubPhoto = "DELETE FROM club_photo WHERE id = $1" + +func (s *Postgres) DeleteClubPhoto(_ context.Context, id int) error { + tx, err := s.db.Begin() + if err != nil { + return wrapPostgresError(err) + } + _, err = tx.Exec(deleteClubPhoto, id) + if err != nil { + tx.Rollback() + return wrapPostgresError(err) + } + return wrapPostgresError(tx.Commit()) +} + +const getPhotoClubID = "SELECT club_id FROM club_photo WHERE id = $1" + +func (s *Postgres) GetPhotoClubID(_ context.Context, photoID int) (int, error) { + var clubID int + err := s.db.QueryRow(getPhotoClubID, photoID).Scan(&clubID) + return clubID, wrapPostgresError(err) +} diff --git a/internal/ports/clubs.go b/internal/ports/clubs.go index 662f4a3..e3f231d 100644 --- a/internal/ports/clubs.go +++ b/internal/ports/clubs.go @@ -47,7 +47,7 @@ func (h *ClubsHandler) Routes() chi.Router { r.Delete("/{club_id}", h.r.Wrap(h.DeleteClub)) r.Put("/{club_id}", h.r.Wrap(h.UpdateClub)) r.Post("/media/{club_id}", h.r.Wrap(h.PostClubMedia)) - r.Delete("/media/{club_id}/{media_id}", h.r.Wrap(h.DeleteClubMedia)) + r.Delete("/media/{club_id}", h.r.Wrap(h.DeleteClubMedia)) r.Put("/media/{club_id}", h.r.Wrap(h.UpdateClubMedia)) r.Get("/clearance/post", h.r.Wrap(h.GetClearancePost)) @@ -530,6 +530,41 @@ func (h *ClubsHandler) PostClubMedia(w http.ResponseWriter, req *http.Request) h } func (h *ClubsHandler) DeleteClubMedia(w http.ResponseWriter, req *http.Request) handler.Response { + h.logger.Info("ClubsHandler: got DeleteClubMedia request") + + access, err := getAccessToken(req) + if err != nil { + h.logger.Warnf("can't get access token: %v", err) + return handler.UnauthorizedResponse() + } + + resp, err := h.guard.Check(context.Background(), &requests.CheckRequest{AccessToken: access}) + if err != nil || !resp.Valid { + h.logger.Warnf("Unauthorized request: %v", err) + return handler.UnauthorizedResponse() + } + + h.logger.Infof("ClubsHandler: DeleteClubMedia Authenticated: %v", resp.MemberID) + + photo := &requests.DeleteClubPhoto{} + err = photo.Bind(req) + if err != nil { + h.logger.Warnf("can't parse DeleteClubMedia %v", err) + return handler.BadRequestResponse() + } + h.logger.Infof("ClubsHandler: parse request.") + + err = h.clubs.DeleteClubPhoto(context.Background(), photo) + if err != nil { + h.logger.Warnf("can't service.DeleteClubMedia %v", err) + if errors.Is(err, postgres.ErrPostgresForeignKeyViolation) { + return handler.BadRequestResponse() + } else if errors.Is(err, postgres.ErrPostgresNotFoundError) { + return handler.NotFoundResponse() + } + return handler.InternalServerErrorResponse() + } + return handler.OkResponse(nil) } diff --git a/internal/storage/club.go b/internal/storage/club.go index f677706..3a516ff 100644 --- a/internal/storage/club.go +++ b/internal/storage/club.go @@ -21,6 +21,8 @@ type clubStorage interface { DeleteClubWithOrgs(ctx context.Context, clubID int) error UpdateClub(ctx context.Context, c *domain.Club, o []domain.ClubOrg) error AddClubPhotos(ctx context.Context, p []domain.ClubPhoto) error + DeleteClubPhoto(ctx context.Context, id int) error + GetPhotoClubID(ctx context.Context, photoID int) (int, error) } func (s *storage) GetClub(ctx context.Context, id int) (*domain.Club, error) { @@ -78,3 +80,11 @@ func (s *storage) UpdateClub(ctx context.Context, c *domain.Club, o []domain.Clu func (s *storage) AddClubPhotos(ctx context.Context, p []domain.ClubPhoto) error { return s.postgres.AddClubPhotos(ctx, p) } + +func (s *storage) DeleteClubPhoto(ctx context.Context, id int) error { + return s.postgres.DeleteClubPhoto(ctx, id) +} + +func (s *storage) GetPhotoClubID(ctx context.Context, photoID int) (int, error) { + return s.postgres.GetPhotoClubID(ctx, photoID) +} From 996815cf986662f05eb065b2576693db1a7d50c3 Mon Sep 17 00:00:00 2001 From: pai0id Date: Wed, 17 Jul 2024 12:11:45 +0300 Subject: [PATCH 14/21] migrations refactored --- internal/app/events.go | 5 ++ internal/infrastructure/postgres/members.go | 4 +- internal/ports/events.go | 49 +++++++++++++- migrations/002_init_clubs.sql | 4 +- migrations/008_insert_media.sql | 28 ++++++++ migrations/009_insert_member.sql | 19 ++++++ migrations/010_insert_feed.sql | 17 +++++ migrations/011_insert_club.sql | 72 +++++++++++++++++++++ migrations/012_insert_event.sql | 17 +++++ migrations/013_insert_document.sql | 24 +++++++ pkg/minio/Dockerfile | 4 +- scripts/minio_migration.sh | 19 +++++- 12 files changed, 250 insertions(+), 12 deletions(-) create mode 100644 migrations/008_insert_media.sql create mode 100644 migrations/009_insert_member.sql create mode 100644 migrations/010_insert_feed.sql create mode 100644 migrations/011_insert_club.sql create mode 100644 migrations/012_insert_event.sql create mode 100644 migrations/013_insert_document.sql diff --git a/internal/app/events.go b/internal/app/events.go index 6b1373d..653d58f 100644 --- a/internal/app/events.go +++ b/internal/app/events.go @@ -84,6 +84,11 @@ func (s *EventsService) GetEventsByRange(ctx context.Context, from, to time.Time return mapper.MakeResponseEventsByRange(res, eventMediaFiles) } +// func (s *EventsService) GetEventMemberRoles(ctx context.Context, id int) (*responses.GetEventMemberRoles, error) { +// // TODO: Implement this method +// return nil, nil +// } + func (s *EventsService) PostEvent(ctx context.Context, event *domain.Event) error { err := s.storage.PostEvent(ctx, event) if err != nil { diff --git a/internal/infrastructure/postgres/members.go b/internal/infrastructure/postgres/members.go index 18a4390..6b12add 100644 --- a/internal/infrastructure/postgres/members.go +++ b/internal/infrastructure/postgres/members.go @@ -175,12 +175,12 @@ func (p *Postgres) UpdateMember(ctx context.Context, member *domain.Member) erro return nil } -const getMemberByLoginQuery = "SELECT id, login FROM member WHERE login=$1;" +const getMemberByLoginQuery = "SELECT id, hash_password, login FROM member WHERE login=$1;" func (p *Postgres) GetMemberByLogin(_ context.Context, login string) (*domain.Member, error) { var user domain.Member - err := p.db.QueryRow(getMemberByLoginQuery, login).Scan(&user.ID, &user.Login) + err := p.db.QueryRow(getMemberByLoginQuery, login).Scan(&user.ID, &user.HashPassword, &user.Login) if err != nil { return nil, wrapPostgresError(err) } diff --git a/internal/ports/events.go b/internal/ports/events.go index c8ff31b..ea1fd2d 100644 --- a/internal/ports/events.go +++ b/internal/ports/events.go @@ -168,6 +168,51 @@ func (h *EventsHandler) GetEventsByRange(w http.ResponseWriter, req *http.Reques return handler.OkResponse(res) } +// // GetEventMemberRoles get all roles for members of events +// // +// // @Summary Retrieve all event roles +// // @Description Get a list of all roles for members of events +// // @Tags auth.events +// // @Produce json +// // @Success 200 {object} responses.GetEventMemberRoles +// // @Failure 404 +// // @Failure 500 +// // @Router /events/members/roles/ [get] +// // @Security Authorised +// func (h *EventsHandler) GetEventMemberRoles(w http.ResponseWriter, req *http.Request) handler.Response { +// h.logger.Info("EventsHandler: got GetEventMemberRoles request") + +// accessToken, err := getAccessToken(req) +// if err != nil { +// h.logger.Warnf("can't get access token GetEventMemberRoles: %v", err) +// return handler.UnauthorizedResponse() +// } + +// resp, err := h.guard.Check(context.Background(), &requests.CheckRequest{AccessToken: accessToken}) +// if err != nil || !resp.Valid { +// h.logger.Warnf("can't GuardService.Check on GetEventMemberRoles: %v", err) +// return handler.UnauthorizedResponse() +// } + +// h.logger.Infof("EventsHandler: GetEventMemberRoles Authenticated: %v", resp.MemberID) + +// res, err := h.events.GetEventMemberRoles(context.Background(), resp.MemberID) +// if err != nil { +// h.logger.Warnf("can't EventsService.GetEventMemberRoles: %v", err) +// if errors.Is(err, postgres.ErrPostgresNotFoundError) { +// return handler.NotFoundResponse() +// } else if errors.Is(err, app.ErrInvalidCredentials) { +// return handler.UnauthorizedResponse() +// } else { +// return handler.InternalServerErrorResponse() +// } +// } + +// h.logger.Info("EventsHandler: request GetEventMemberRoles done") + +// return handler.OkResponse(res) +// } + // PostEvent creates a new event item // // @Summary Create a new event item @@ -192,7 +237,7 @@ func (h *EventsHandler) PostEvent(w http.ResponseWriter, req *http.Request) hand resp, err := h.guard.Check(context.Background(), &requests.CheckRequest{AccessToken: accessToken}) if err != nil || !resp.Valid { - h.logger.Warnf("can't GuardService.Check on DeleteEvent: %v", err) + h.logger.Warnf("can't GuardService.Check on PostEvent: %v", err) return handler.UnauthorizedResponse() } @@ -306,7 +351,7 @@ func (h *EventsHandler) UpdateEvent(w http.ResponseWriter, req *http.Request) ha resp, err := h.guard.Check(context.Background(), &requests.CheckRequest{AccessToken: accessToken}) if err != nil || !resp.Valid { - h.logger.Warnf("can't GuardService.Check on DeleteEvent: %v", err) + h.logger.Warnf("can't GuardService.Check on UpdateEvent: %v", err) return handler.UnauthorizedResponse() } diff --git a/migrations/002_init_clubs.sql b/migrations/002_init_clubs.sql index 562f0ac..01cd19c 100644 --- a/migrations/002_init_clubs.sql +++ b/migrations/002_init_clubs.sql @@ -85,11 +85,11 @@ alter table club_org add FOREIGN KEY (role_id) REFERENCES club_role(id); -- +goose Down -- +goose StatementBegin +drop table IF EXISTS club_role CASCADE; drop table IF EXISTS club_org CASCADE; drop table IF EXISTS club_photo CASCADE; -drop table IF EXISTS club_role CASCADE; -drop table IF EXISTS club CASCADE; drop table IF EXISTS event CASCADE; drop table IF EXISTS encounter CASCADE; +drop table IF EXISTS club CASCADE; -- +goose StatementEnd \ No newline at end of file diff --git a/migrations/008_insert_media.sql b/migrations/008_insert_media.sql new file mode 100644 index 0000000..cecff60 --- /dev/null +++ b/migrations/008_insert_media.sql @@ -0,0 +1,28 @@ +-- +goose Up +-- +goose StatementBegin + +insert into mediafile (name, key) +values +('1.jpg', '1.jpg'), +('2.jpg', '2.jpg'), +('3.jpg', '3.jpg'), +('4.jpg', '4.jpg'), +('5.jpg', '5.jpg'), +('6.jpg', '6.jpg'), +('7.jpg', '7.jpg'), +('8.jpg', '8.jpg'), +('9.jpg', '9.jpg'), +('10.jpg', '10.jpg'), +('11.jpg', '11.jpg'); + +insert into default_media (media_id) +VALUES (1), (2), (3); + +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin + +truncate table mediafile CASCADE; + +-- +goose StatementEnd \ No newline at end of file diff --git a/migrations/009_insert_member.sql b/migrations/009_insert_member.sql new file mode 100644 index 0000000..ee388c4 --- /dev/null +++ b/migrations/009_insert_member.sql @@ -0,0 +1,19 @@ +-- +goose Up +-- +goose StatementBegin + +insert into member (hash_password, login, media_id, telegram, vk, name, is_admin) +values +('12345678', 'TestHeadMaster', 1, '@testHeadTelegram', 'TestHeadTelegram', 'Антон Успенский', true), +('12345678', 'TestTPmaster', 2, '@TestTPmaster', 'TestTPmasterTelegram', 'Максим Демьянов', false), +('12345678', 'TestHeadMissis', 3, '@TestHeadMissis', 'TestHeadMissisTelegram', 'Екатерина Донскова', false), +('12345678', '@testHeadGather', 4, '@testHeadGatherTelegram', 'testHeadGather', 'Ольга Вакулина', false), +('12345678', 'TestHeadMedia', 5, '@testHeadMediaTelegram', 'testHeadMediaTelegram', 'Егор Федорук', false); + +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin + +truncate table member CASCADE; + +-- +goose StatementEnd \ No newline at end of file diff --git a/migrations/010_insert_feed.sql b/migrations/010_insert_feed.sql new file mode 100644 index 0000000..057a693 --- /dev/null +++ b/migrations/010_insert_feed.sql @@ -0,0 +1,17 @@ +-- +goose Up +-- +goose StatementBegin + +insert into feed (title, approved, description, media_id, vk_post_url, updated_at, created_at, views, created_by) +values +('РЕГИСТРАЦИЯ НА СОПК', true, '🔥 Сегодня стартовала приемная кампания 2024 года, и МГТУ им. Н.Э. Баумана радушно распахнул свои двери для будущих студентов. В мае прошло несколько этапов отбора сотрудников, и сегодня они уже помогают абитуриентам с подачей документов, выбором направлений и консультациями. Ректор — Михаил Валерьевич Гордин и и.о. проректора по молодежной работе и воспитательной деятельности — Дмитрий Андреевич Сулегин (https://t.me/sulegin_bmstu) обратились к сотрудникам с напутственными словами и зарядили ребят на продуктивную работу этим летом!🫶 Сотрудники СОПК хорошо понимают все страхи абитуриентов, ведь сами проходили через этап поступления. Ребята ждут вас в Университете, чтобы помочь и ответить на все вопросы. До скорой встречи в МГТУ им. Н.Э. Баумана!', 6, 'https://vk.com/wall-26724538_19086', current_date, current_date, 10, 1), +('РЕГИСТРАЦИЯ НА ШПШ', true, 'На ШМБ приезжают Бауманцы, которые превращают это мероприятие в незабываемое событие для всех первокурсников. Их работа начинается на «Школе Перед Школой», где они не просто знакомятся, но и становятся крепкой командой. Каждая роль здесь важна, и каждый участник вносит неоценимый вклад, выкладываясь на все 100%, чтобы ШМБ стало ярким и запоминающимся мероприятием для всех!',7, 'https://vk.com/wall-26724538_19086', current_date, current_date, 10, 1), +('РЕГИСТРАЦИЯ В СТРОЙ ОТРЯД!', true, '🔥 Сегодня стартовал набор в стройотряд ДрУжБа', 8, 'https://vk.com/wall-26724538_19086', current_date, current_date, 10, 1); + +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin + +truncate table feed CASCADE; + +-- +goose StatementEnd \ No newline at end of file diff --git a/migrations/011_insert_club.sql b/migrations/011_insert_club.sql new file mode 100644 index 0000000..2344101 --- /dev/null +++ b/migrations/011_insert_club.sql @@ -0,0 +1,72 @@ +-- +goose Up +-- +goose StatementBegin + +INSERT INTO club (name, short_name, description, type, logo, vk_url, tg_url) +VALUES + ('SSU IT-department', 'IT-dep', 'Тувинский блогер, не отягощённый интеллектом, решил искупаться в аквариуме с рыбами в гипермаркете "О’кей" в Красноярске. Свой поступок он объяснил фразой "Жарко было на улице, хотел купаться". Теперь "О’кей" хочет засудить молодого человека. Предварительно в магазине подсчитали сумму ущерба – чуть меньше 10 тысяч рублей. В эту стоимость входит изъятая рыба (более десяти голов различной породы) и дезинфекция аквариума.', 'отдел', 6, 'vk.com', 'tg.me'), + ('Техническая поддержка', 'ТП', 'Новые версии операционных систем Apple научились автоматически обнаруживать утерянные или повреждённые фотографии и видео, которые можно будет восстановить и перенести в библиотеку «Фото» или удалить навсегда. Фотографии и видео могут быть утеряны по ряду причин: от повреждения базы данных до ошибок при сохранении фото после съёмки.', 'отдел', 5, 'vk.com', 'tg.me'), + ('Bauman Active Sport', 'BAS', '• несмотря на весь скепсис, сам геймплей оставляет положительное впечатление. Получилась некая смесь Destiny 2 и Overwatch 2, что уже неплохо; +• в игре 16 героев, каждый из которых, якобы, обладает уникальными способностями. Но это не так. Все они повторяют навыки из Overwatch и других схожих проектов; +• вторичны не только навыки, но и сами герои: стрелок с револьвером, танк-щитовик, ракетомётчик с джетпаком и так далее. Складывается чувство, что это китайский клон, а не крупный проект от Sony; +• игровые режимы также не предлагают ничего нового — сражения 5х5 со сбором жетонов или простым уничтожением. Но самое главное, не ощущается командной работы; +• сюжет подаётся через дорогие катсцены, но смотреть их просто невозможно, из-за карикатурных и стереотипных персонажей; +• за опыт, полученный во время матчей, открываются различные косметические предметы, которые можно повесить на героев и оружие.', 'клуб', 7, 'vk.com', 'tg.me'), + ('HR-department', 'HR-dep', 'Аналитическая компания Circana сообщает, что PlayStation Portal возглавила рейтинг продаж игровых аксессуаров в США. Успех стриминговой портативки объясняется общим спадом на рынке и отсутствием аналогов. В США и Великобритании консоль распродали за два дня, а в Испании устройство в три раза популярнее Xbox Series X/S. ', 'HR', 4, 'vk.com', 'tg.me'), + ('КаФеДрА ЮмОрА', 'раш на минималках', 'Собираются пацыки на сходке. Самый главный по автозвуку зовет трех корешей и говорит: +-Кентафарик, попробуй дешево установить автозвук. +Кентафарик тужится, пыжится. +-Никак не получается, товарищ главарь. +-Шлягер, помогай Кентафарику. +Вдвоем пытаются. +-Никак не получается, товарищ главарь. +-Дружище, ну-ка покажи как надо. +Втроем пытаются что-то сделать, та же ситуация. +-А хули вы хотели 18 миллионов', 'Marketing' , 1, 'vk.com', 'tg.me'), + ('Sales-department', 'Sales-dep', 'Typo Sa', 'Sales', 2, 'vk.com', 'tg.me'), + ('Engineering-department', 'Engineering-dep', 'Typo Eng', 'Engineering', 3, 'vk.com', 'tg.me'); + +INSERT INTO club_role (role_name, role_spec, role_clearance) +VALUES +('Бэкендер', 'spec', 1), +('Фронтендер', 'spec', 2), +('Мидлендер', 'spec', 2); + +INSERT INTO club_photo (media_id, club_id) +VALUES +(1, 1), +(1, 2), +(2, 2), +(3, 3), +(4, 4), +(5, 5), +(6, 6), +(7, 7); + +INSERT INTO club_org (club_id, member_id, role_id) +VALUES +(1, 1, 1), +(1, 2, 2), +(1, 3, 3), +(2, 4, 1), +(2, 5, 2), +(2, 1, 3), +(3, 2, 1); + +INSERT INTO encounter (count, description, club_id) +VALUES +('100', 'First encounter', 1), +('200', 'Second encounter', 2), +('300', 'Third encounter', 3); + +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin + +truncate table club_role CASCADE; +truncate table club_photo CASCADE; +truncate table club_org CASCADE; +truncate table encounter CASCADE; +truncate table club CASCADE; + +-- +goose StatementEnd \ No newline at end of file diff --git a/migrations/012_insert_event.sql b/migrations/012_insert_event.sql new file mode 100644 index 0000000..6abeac5 --- /dev/null +++ b/migrations/012_insert_event.sql @@ -0,0 +1,17 @@ +-- +goose Up +-- +goose StatementBegin + +INSERT INTO event (title, description, prompt, media_id, date, approved, created_at, club_id, main_org, reg_url, reg_open_date, feedback_url) +VALUES +('Event 1', 'Description of Event 1', 'Prompt for Event 1', 1, '2022-01-01 10:00:00', true, '2022-01-01 09:00:00', 1, 1, 'https://example.com/register1', '2022-01-01 08:00:00', 'https://example.com/feedback1'), +('Event 2', 'Description of Event 2', 'Prompt for Event 2', 2, '2022-02-01 10:00:00', false, '2022-02-01 09:00:00', 2, 2, 'https://example.com/register2', '2022-02-01 08:00:00', 'https://example.com/feedback2'), +('Event 3', 'Description of Event 3', 'Prompt for Event 3', 3, '2022-03-01 10:00:00', true, '2022-03-01 09:00:00', 3, 3, 'https://example.com/register3', '2022-03-01 08:00:00', 'https://example.com/feedback3'); + +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin + +truncate table event CASCADE; + +-- +goose StatementEnd \ No newline at end of file diff --git a/migrations/013_insert_document.sql b/migrations/013_insert_document.sql new file mode 100644 index 0000000..f9682eb --- /dev/null +++ b/migrations/013_insert_document.sql @@ -0,0 +1,24 @@ +-- +goose Up +-- +goose StatementBegin + +INSERT INTO category (name) +VALUES +('Category 1'), +('Category 2'), +('Category 3'); + +INSERT INTO document (name, key, club_id, category_id) +VALUES +('1.pdf', '1/1.pdf', 1, 1), +('2.pdf', '2/2.pdf', 2, 2), +('3.pdf', '3/3.pdf', 3, 3); + +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin + +truncate table document CASCADE; +truncate table category CASCADE; + +-- +goose StatementEnd \ No newline at end of file diff --git a/pkg/minio/Dockerfile b/pkg/minio/Dockerfile index c42fa71..c7fa8d0 100644 --- a/pkg/minio/Dockerfile +++ b/pkg/minio/Dockerfile @@ -33,9 +33,7 @@ RUN \ COPY ./scripts/minio_migration.sh . RUN mkdir /data -COPY ./data/main_vid.mp4 ./data -COPY ./about/arch.png ./data -COPY ./about/arch.puml ./data +COPY ./data/* ./data RUN chmod 777 minio_migration.sh diff --git a/scripts/minio_migration.sh b/scripts/minio_migration.sh index ec2d950..a607cb7 100644 --- a/scripts/minio_migration.sh +++ b/scripts/minio_migration.sh @@ -7,6 +7,19 @@ mc mb --ignore-existing minio/"$IMAGE_BUCKET" mc anonymous set public minio/"$IMAGE_BUCKET" mc mb --ignore-existing minio/"$DOCUMENT_BUCKET" mc anonymous set public minio/"$DOCUMENT_BUCKET" -mc put data/main_vid.mp4 minio/"$VIDEO_BUCKET" -mc put data/arch.png minio/"$IMAGE_BUCKET" -mc put data/arch.puml minio/"$DOCUMENT_BUCKET" \ No newline at end of file + +for file in data/*.jpg; do + if [ -f "$file" ]; then + mc put "$file" minio/"$IMAGE_BUCKET" + fi +done + +for file in data/*.mp4; do + if [ -f "$file" ]; then + mc put "$file" minio/"$VIDEO_BUCKET" + fi +done + +mc put data/1.pdf minio/"$DOCUMENT_BUCKET"/1 +mc put data/2.pdf minio/"$DOCUMENT_BUCKET"/2 +mc put data/3.pdf minio/"$DOCUMENT_BUCKET"/3 \ No newline at end of file From 78c4aa5a00c1308f445f4b02ae3924cba678d511 Mon Sep 17 00:00:00 2001 From: pai0id Date: Wed, 17 Jul 2024 12:20:43 +0300 Subject: [PATCH 15/21] del mig --- migrations/004_insert_feed_test_data.sql | 35 ------------------- migrations/006_add_orgs_to_clubs.sql | 37 -------------------- migrations/016_init_role_table.sql | 44 ------------------------ 3 files changed, 116 deletions(-) delete mode 100644 migrations/004_insert_feed_test_data.sql delete mode 100644 migrations/006_add_orgs_to_clubs.sql delete mode 100644 migrations/016_init_role_table.sql diff --git a/migrations/004_insert_feed_test_data.sql b/migrations/004_insert_feed_test_data.sql deleted file mode 100644 index 979e9c2..0000000 --- a/migrations/004_insert_feed_test_data.sql +++ /dev/null @@ -1,35 +0,0 @@ --- +goose Up --- +goose StatementBegin - -INSERT INTO member (hash_password, login, media_id, role_id) -VALUES -('1234', '1234', 1, 1), -('1', '1', 2, 2); - -INSERT INTO feed (title, approved, description, media_id, vk_post_url, updated_at, created_at, views, created_by) -VALUES -('11', true, '33', 1, '132', '2004-10-19 10:23:54', '2004-10-19 10:23:54', 13, 1), -('1', true, '33', 2, '132', '2004-10-19 10:23:54', '2004-10-19 10:23:54', 13, 1), -('22', false, '44', 3, '321', '2005-11-19 10:23:54', '1900-10-19 10:23:54', 14, 2); - -INSERT INTO encounter (count, description, club_id) -VALUES -('1', 'kcoc', 0), -('11', 'kcoc', 0), -('2', 'sllab', 1), -('22', 'sllab', 2); - -INSERT INTO event (title, description, prompt, media_id, date, approved, created_at, main_org, reg_url, reg_open_date, feedback_url, club_id) -VALUES -('kcoc', 'sllab', 'kcid', 1, '2005-11-19 10:23:54', true, '2005-11-19 10:23:54', 1, 'ahh', '2005-11-19 10:23:54', '123', 1), -('sinep', 'stun', 'nibor', 1, '2005-11-19 10:23:54', true, '2005-11-19 10:23:54', 2, 'ahh', '2005-11-19 10:23:54', '123', 0); - --- +goose StatementEnd - --- +goose Down --- +goose StatementBegin -DELETE FROM encounter; -DELETE FROM feed; -DELETE FROM event; -DELETE FROM member; --- +goose StatementEnd diff --git a/migrations/006_add_orgs_to_clubs.sql b/migrations/006_add_orgs_to_clubs.sql deleted file mode 100644 index 7bf92d6..0000000 --- a/migrations/006_add_orgs_to_clubs.sql +++ /dev/null @@ -1,37 +0,0 @@ --- +goose Up --- +goose StatementBegin - -INSERT INTO member (hash_password, login, media_id, telegram, vk, name, is_admin) -VALUES -('test', 'toha', 1, '@toha', 'vk.com/toha', 'Антон Павленко', true), -('$2a$10$kj0GwI3q1H0PgOzuLqK5uOhPPvA42upL8CdIm/4luikQBYNKVxXay', 'imp', 1, '@imp', 'vk.com/imp', 'Дмитрий Шахнович', true), -('test', 'dasha', 1, '@dasha', 'vk.com/dasha', 'Дарья Серышева', true), -('test', 'paioid', 1, '@paioid', 'vk.com/paioid', 'Андрей Поляков', true), -('test', 'admin', 1, '@admin', 'vk.com/admin', 'Админ', true), -('test', 'user', 1, '@user', 'vk.com/user', 'Юзер', true), -('test', 'user2', 1, '@user2', 'vk.com/user2', 'Юзер2', true); - - -INSERT INTO club_org (club_id, member_id, role_name, role_spec) -VALUES -(1, 1, 'Молодец', 'IT'), -(1, 1, 'Красава', 'NIT'), -(1, 2, 'Веселый', 'Finance'), -(1, 2, 'Хорошо', 'HR'), -(1, 3, 'Богатый', 'Marketing'), -(1, 3, 'Молодец', 'Sales'), -(2, 4, 'Умный', 'Engineering'); - -UPDATE club -SET parent_id = 1 -WHERE id = 2; - --- +goose StatementEnd - --- +goose Down --- +goose StatementBegin - -DELETE FROM club_org; -DELETE FROM member; - --- +goose StatementEnd diff --git a/migrations/016_init_role_table.sql b/migrations/016_init_role_table.sql deleted file mode 100644 index cce61f0..0000000 --- a/migrations/016_init_role_table.sql +++ /dev/null @@ -1,44 +0,0 @@ --- +goose Up --- +goose StatementBegin - - -ALTER TABLE member_role RENAME TO club_role; -ALTER TABLE member DROP COLUMN role_id; -ALTER TABLE club_org DROP COLUMN role_spec; -ALTER TABLE club_org DROP COLUMN role_name; -ALTER TABLE club_role RENAME COLUMN role_id TO id; -ALTER TABLE club_org ADD COLUMN role_id int references club_role(id); - --- 0 - гость --- 1 - участник --- 2 - руководитель --- 3 - админ -ALTER TABLE club_role ADD COLUMN role_clearance int; - - -INSERT INTO club_role (role_name, role_spec, role_clearance) -VALUES -('IT бог', 'Глава ИТЭ', 2), -('Программист', 'Программист', 2), -('Тестировщик', 'Тестировщик', 2), -('Бухгалтер', 'Бухгалтер', 2), -('Старший участник', 'Старший участник', 2), -('Младший участник', 'Младший участник', 2), -('Гость', 'Гость', 2); - -UPDATE club_org SET role_id = 1 WHERE id = 1; -UPDATE club_org SET role_id = 2 WHERE id = 2; -UPDATE club_org SET role_id = 3 WHERE id = 3; -UPDATE club_org SET role_id = 4 WHERE id = 4; -UPDATE club_org SET role_id = 5 WHERE id = 5; -UPDATE club_org SET role_id = 6 WHERE id = 6; -UPDATE club_org SET role_id = 7 WHERE id = 7; - --- +goose StatementEnd - --- +goose Down --- +goose StatementBegin -ALTER TABLE member Add COLUMN role_id int; -DROP TABLE club_role; --- +goose StatementEnd - From 4fde8494396d0c33ce23edb962a561b923bbefdb Mon Sep 17 00:00:00 2001 From: pai0id Date: Wed, 17 Jul 2024 13:02:21 +0300 Subject: [PATCH 16/21] json fixup --- internal/app/events.go | 4 ++-- internal/domain/event-member-role.go | 6 ++++++ internal/domain/member.go | 2 +- internal/domain/requests/update-member.go | 4 ++-- .../domain/responses/get-all-event-member-roles.go | 10 ++++++++++ internal/domain/responses/get-all-events.go | 2 +- internal/domain/responses/get-clearance.go | 2 +- internal/domain/responses/get-member.go | 2 +- internal/ports/events.go | 1 + 9 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 internal/domain/event-member-role.go create mode 100644 internal/domain/responses/get-all-event-member-roles.go diff --git a/internal/app/events.go b/internal/app/events.go index 653d58f..ce4d336 100644 --- a/internal/app/events.go +++ b/internal/app/events.go @@ -85,8 +85,8 @@ func (s *EventsService) GetEventsByRange(ctx context.Context, from, to time.Time } // func (s *EventsService) GetEventMemberRoles(ctx context.Context, id int) (*responses.GetEventMemberRoles, error) { -// // TODO: Implement this method -// return nil, nil + +// return mapper.MakeResponseEventMemberRoles(res) // } func (s *EventsService) PostEvent(ctx context.Context, event *domain.Event) error { diff --git a/internal/domain/event-member-role.go b/internal/domain/event-member-role.go new file mode 100644 index 0000000..d0703af --- /dev/null +++ b/internal/domain/event-member-role.go @@ -0,0 +1,6 @@ +package domain + +type EventMemberRole struct { + ID int `json:"id"` + Name string `json:"name"` +} diff --git a/internal/domain/member.go b/internal/domain/member.go index 0b89897..a1ee798 100644 --- a/internal/domain/member.go +++ b/internal/domain/member.go @@ -9,5 +9,5 @@ type Member struct { Telegram string `json:"telegram"` Vk string `json:"vk"` Name string `json:"name"` - IsAdmin bool `json:"isAdmin"` + IsAdmin bool `json:"is_admin"` } diff --git a/internal/domain/requests/update-member.go b/internal/domain/requests/update-member.go index 29856ed..d8daae8 100644 --- a/internal/domain/requests/update-member.go +++ b/internal/domain/requests/update-member.go @@ -17,7 +17,7 @@ type UpdateMember struct { Telegram string `json:"telegram"` Vk string `json:"vk"` Name string `json:"name"` - IsAdmin bool `json:"isAdmin"` + IsAdmin bool `json:"is_admin"` } type UpdateMemberPointer struct { @@ -26,7 +26,7 @@ type UpdateMemberPointer struct { Telegram *string `json:"telegram"` Vk *string `json:"vk"` Name *string `json:"name"` - IsAdmin *bool `json:"isAdmin"` + IsAdmin *bool `json:"is_admin"` } func (f *UpdateMember) Bind(req *http.Request) error { diff --git a/internal/domain/responses/get-all-event-member-roles.go b/internal/domain/responses/get-all-event-member-roles.go new file mode 100644 index 0000000..ad9a5c0 --- /dev/null +++ b/internal/domain/responses/get-all-event-member-roles.go @@ -0,0 +1,10 @@ +package responses + +type GetAllEventMemberRoles struct { + EventMemberRole []EventMemberRole `json:"roles"` +} + +type EventMemberRole struct { + ID int `json:"id"` + Name string `json:"name"` +} diff --git a/internal/domain/responses/get-all-events.go b/internal/domain/responses/get-all-events.go index 58023af..a6d1edf 100644 --- a/internal/domain/responses/get-all-events.go +++ b/internal/domain/responses/get-all-events.go @@ -7,7 +7,7 @@ import ( ) type GetAllEvents struct { - Event []Event `json:"event"` + Event []Event `json:"events"` } type Event struct { diff --git a/internal/domain/responses/get-clearance.go b/internal/domain/responses/get-clearance.go index c1c36ca..cf1d4bf 100644 --- a/internal/domain/responses/get-clearance.go +++ b/internal/domain/responses/get-clearance.go @@ -2,5 +2,5 @@ package responses type GetClearance struct { Access bool `json:"access"` - Comment string `json:"Comment"` + Comment string `json:"comment"` } diff --git a/internal/domain/responses/get-member.go b/internal/domain/responses/get-member.go index 9f1993f..f2788c5 100644 --- a/internal/domain/responses/get-member.go +++ b/internal/domain/responses/get-member.go @@ -9,5 +9,5 @@ type GetMember struct { Telegram string `json:"telegram"` Vk string `json:"vk"` Name string `json:"name"` - IsAdmin bool `json:"isAdmin"` + IsAdmin bool `json:"is_admin"` } diff --git a/internal/ports/events.go b/internal/ports/events.go index ea1fd2d..7779b9e 100644 --- a/internal/ports/events.go +++ b/internal/ports/events.go @@ -176,6 +176,7 @@ func (h *EventsHandler) GetEventsByRange(w http.ResponseWriter, req *http.Reques // // @Produce json // // @Success 200 {object} responses.GetEventMemberRoles // // @Failure 404 +// // @Failure 401 // // @Failure 500 // // @Router /events/members/roles/ [get] // // @Security Authorised From 20e696299ae8f09c7d4fd2e8f7fbf1c1c15e9bc7 Mon Sep 17 00:00:00 2001 From: Impervguin Date: Wed, 17 Jul 2024 13:21:33 +0300 Subject: [PATCH 17/21] changes in migrations --- migrations/002_init_clubs.sql | 59 ++++++++++++++++---------------- migrations/009_insert_member.sql | 10 +++--- 2 files changed, 35 insertions(+), 34 deletions(-) diff --git a/migrations/002_init_clubs.sql b/migrations/002_init_clubs.sql index 01cd19c..f6d2113 100644 --- a/migrations/002_init_clubs.sql +++ b/migrations/002_init_clubs.sql @@ -1,16 +1,16 @@ -- +goose Up -- +goose StatementBegin -create table if not exists encounter ( - id serial primary key, +create TABLE if not exists encounter ( + id serial primary KEY, count text default '', description text default '', club_id int not null ); -create table IF NOT EXISTS event +create TABLE IF NOT EXISTS event ( - id serial primary key, + id serial primary KEY, title text not null, description text not null, prompt text not null, @@ -25,8 +25,8 @@ create table IF NOT EXISTS event feedback_url text default '' ); -create table if not exists club ( - id serial primary key, +create TABLE if not exists club ( + id serial primary KEY, name text default '' unique, short_name text default '', description text default '', @@ -37,9 +37,9 @@ create table if not exists club ( parent_id int default null ); -create table IF NOT EXISTS club_role +create TABLE IF NOT EXISTS club_role ( - id serial primary key, + id serial primary KEY, role_name text not null, role_spec text not null, role_clearance int default 0 @@ -50,46 +50,47 @@ create table IF NOT EXISTS club_role -- 3 - админ -- TODO in domain -create table if not exists club_photo ( - id serial primary key, +create TABLE if not exists club_photo ( + id serial primary KEY, ref_num int default 0, media_id int not null, club_id int not null ); -create table if not exists club_org ( - id serial primary key, +create TABLE if not exists club_org ( + id serial primary KEY, club_id int not null, member_id int not null, role_id int not null ); -alter table encounter add foreign key (club_id) references club(id); +ALTER TABLE encounter ADD FOREIGN KEY (club_id) REFERENCES club(id); -alter table club add FOREIGN KEY (logo) REFERENCES mediafile(id); -alter table club add FOREIGN KEY (parent_id) REFERENCES club(id); +ALTER TABLE club ADD FOREIGN KEY (logo) REFERENCES mediafile(id); +ALTER TABLE club ADD FOREIGN KEY (parent_id) REFERENCES club(id); -alter table event add foreign key (club_id) references club(id); -alter table event add foreign key (media_id) references mediafile(id); -alter table event add foreign key (main_org) references member(id); +ALTER TABLE event ADD FOREIGN KEY (club_id) REFERENCES club(id); +ALTER TABLE event ADD FOREIGN KEY (media_id) REFERENCES mediafile(id); +ALTER TABLE event ADD FOREIGN KEY (main_org) REFERENCES member(id); -alter table club_photo add FOREIGN KEY (media_id) REFERENCES mediafile(id); -alter table club_photo add FOREIGN KEY (club_id) REFERENCES club(id); +ALTER TABLE club_photo ADD FOREIGN KEY (media_id) REFERENCES mediafile(id); +ALTER TABLE club_photo ADD FOREIGN KEY (club_id) REFERENCES club(id); +ALTER TABLE club_photo ADD CONSTRAINT media_club_ids_unique UNIQUE (club_id, media_id); -alter table club_org add FOREIGN KEY (club_id) REFERENCES club(id); -alter table club_org add FOREIGN KEY (member_id) REFERENCES member(id); -alter table club_org add FOREIGN KEY (role_id) REFERENCES club_role(id); +ALTER TABLE club_org ADD FOREIGN KEY (club_id) REFERENCES club(id); +ALTER TABLE club_org ADD FOREIGN KEY (member_id) REFERENCES member(id); +ALTER TABLE club_org ADD FOREIGN KEY (role_id) REFERENCES club_role(id); -- +goose StatementEnd -- +goose Down -- +goose StatementBegin -drop table IF EXISTS club_role CASCADE; -drop table IF EXISTS club_org CASCADE; -drop table IF EXISTS club_photo CASCADE; -drop table IF EXISTS event CASCADE; -drop table IF EXISTS encounter CASCADE; -drop table IF EXISTS club CASCADE; +DROP TABLE IF EXISTS club_role CASCADE; +DROP TABLE IF EXISTS club_org CASCADE; +DROP TABLE IF EXISTS club_photo CASCADE; +DROP TABLE IF EXISTS event CASCADE; +DROP TABLE IF EXISTS encounter CASCADE; +DROP TABLE IF EXISTS club CASCADE; -- +goose StatementEnd \ No newline at end of file diff --git a/migrations/009_insert_member.sql b/migrations/009_insert_member.sql index ee388c4..916a834 100644 --- a/migrations/009_insert_member.sql +++ b/migrations/009_insert_member.sql @@ -3,11 +3,11 @@ insert into member (hash_password, login, media_id, telegram, vk, name, is_admin) values -('12345678', 'TestHeadMaster', 1, '@testHeadTelegram', 'TestHeadTelegram', 'Антон Успенский', true), -('12345678', 'TestTPmaster', 2, '@TestTPmaster', 'TestTPmasterTelegram', 'Максим Демьянов', false), -('12345678', 'TestHeadMissis', 3, '@TestHeadMissis', 'TestHeadMissisTelegram', 'Екатерина Донскова', false), -('12345678', '@testHeadGather', 4, '@testHeadGatherTelegram', 'testHeadGather', 'Ольга Вакулина', false), -('12345678', 'TestHeadMedia', 5, '@testHeadMediaTelegram', 'testHeadMediaTelegram', 'Егор Федорук', false); +('$2y$10$GvW6IPLIAda8K7cIVeQ02.Sh/s5hPi2QHXZRSxkwG0kZiG00qOyQi', 'TestHeadMaster', 1, '@testHeadTelegram', 'TestHeadTelegram', 'Антон Успенский', true), +('$2y$10$GvW6IPLIAda8K7cIVeQ02.Sh/s5hPi2QHXZRSxkwG0kZiG00qOyQi', 'TestTPmaster', 2, '@TestTPmaster', 'TestTPmasterTelegram', 'Максим Демьянов', false), +('$2y$10$GvW6IPLIAda8K7cIVeQ02.Sh/s5hPi2QHXZRSxkwG0kZiG00qOyQi', 'TestHeadMissis', 3, '@TestHeadMissis', 'TestHeadMissisTelegram', 'Екатерина Донскова', false), +('$2y$10$GvW6IPLIAda8K7cIVeQ02.Sh/s5hPi2QHXZRSxkwG0kZiG00qOyQi', '@testHeadGather', 4, '@testHeadGatherTelegram', 'testHeadGather', 'Ольга Вакулина', false), +('$2y$10$GvW6IPLIAda8K7cIVeQ02.Sh/s5hPi2QHXZRSxkwG0kZiG00qOyQi', 'TestHeadMedia', 5, '@testHeadMediaTelegram', 'testHeadMediaTelegram', 'Егор Федорук', false); -- +goose StatementEnd From 0553e112abeb6eececf97c51a7ceff973f74821a Mon Sep 17 00:00:00 2001 From: pai0id Date: Wed, 17 Jul 2024 13:28:16 +0300 Subject: [PATCH 18/21] root / guard --- internal/ports/guard.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/ports/guard.go b/internal/ports/guard.go index a5b4200..e1a39b0 100644 --- a/internal/ports/guard.go +++ b/internal/ports/guard.go @@ -36,9 +36,9 @@ func (h *GuardHandler) BasePrefix() string { func (h *GuardHandler) Routes() chi.Router { r := chi.NewRouter() - r.Post("/login", h.r.Wrap(h.LoginUser)) - r.Post("/logout", h.r.Wrap(h.LogoutUser)) - r.Post("/register", h.r.Wrap(h.RegisterUser)) + r.Post("/login/", h.r.Wrap(h.LoginUser)) + r.Post("/logout/", h.r.Wrap(h.LogoutUser)) + r.Post("/register/", h.r.Wrap(h.RegisterUser)) return r } From c5d0b89551650693e793903bbfff07eca871738c Mon Sep 17 00:00:00 2001 From: pai0id Date: Wed, 17 Jul 2024 13:30:21 +0300 Subject: [PATCH 19/21] ports / clubs && media --- internal/ports/clubs.go | 2 +- internal/ports/media.go | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/ports/clubs.go b/internal/ports/clubs.go index e3f231d..13b464e 100644 --- a/internal/ports/clubs.go +++ b/internal/ports/clubs.go @@ -49,7 +49,7 @@ func (h *ClubsHandler) Routes() chi.Router { r.Post("/media/{club_id}", h.r.Wrap(h.PostClubMedia)) r.Delete("/media/{club_id}", h.r.Wrap(h.DeleteClubMedia)) r.Put("/media/{club_id}", h.r.Wrap(h.UpdateClubMedia)) - r.Get("/clearance/post", h.r.Wrap(h.GetClearancePost)) + r.Get("/clearance/post/", h.r.Wrap(h.GetClearancePost)) return r } diff --git a/internal/ports/media.go b/internal/ports/media.go index 80ea305..fabfc0d 100644 --- a/internal/ports/media.go +++ b/internal/ports/media.go @@ -38,11 +38,11 @@ func (h *MediaHandler) BasePrefix() string { func (h *MediaHandler) Routes() chi.Router { r := chi.NewRouter() - r.Post("/public", h.r.Wrap(h.PostMediaPublic)) - r.Post("/private", h.r.Wrap(h.PostMediaPrivate)) - r.Get("/default", h.r.Wrap(h.GetMediaDefault)) + r.Post("/public/", h.r.Wrap(h.PostMediaPublic)) + r.Post("/private/", h.r.Wrap(h.PostMediaPrivate)) + r.Get("/default/", h.r.Wrap(h.GetMediaDefault)) r.Get("/default/{id}", h.r.Wrap(h.GetMediaDefaultByID)) - r.Post("/default", h.r.Wrap(h.PostMediaDefault)) + r.Post("/default/", h.r.Wrap(h.PostMediaDefault)) r.Delete("/default/{id}", h.r.Wrap(h.DeleteMediaDefault)) r.Put("/default/{id}", h.r.Wrap(h.UpdateMediaDefault)) From d24c51a410e3042096cf90e5403531840ef2f6da Mon Sep 17 00:00:00 2001 From: Impervguin Date: Wed, 17 Jul 2024 13:39:26 +0300 Subject: [PATCH 20/21] Done update club photo handler --- internal/app/club.go | 19 ++++++ internal/domain/requests/post-club-photo.go | 1 - internal/domain/requests/update-club-photo.go | 48 +++++++++++++++ .../domain/responses/delete-club-photo.go | 5 -- internal/infrastructure/postgres/club.go | 61 +++++++++++++++++++ internal/ports/clubs.go | 37 +++++++++++ internal/storage/club.go | 5 ++ 7 files changed, 170 insertions(+), 6 deletions(-) create mode 100644 internal/domain/requests/update-club-photo.go delete mode 100644 internal/domain/responses/delete-club-photo.go diff --git a/internal/app/club.go b/internal/app/club.go index 6f4eb7e..36ff85c 100644 --- a/internal/app/club.go +++ b/internal/app/club.go @@ -30,6 +30,7 @@ type clubStorage interface { AddClubPhotos(ctx context.Context, p []domain.ClubPhoto) error DeleteClubPhoto(ctx context.Context, ids int) error GetPhotoClubID(ctx context.Context, photoID int) (int, error) + UpdateClubPhotos(ctx context.Context, clubID int, photos []domain.ClubPhoto) error } type ClubService struct { @@ -312,6 +313,24 @@ func (s *ClubService) DeleteClubPhoto(ctx context.Context, req *requests.DeleteC return nil } +func (s *ClubService) UpdateClubPhoto(ctx context.Context, req *requests.UpdateClubPhoto) error { + clubID := req.ClubID + photos := make([]domain.ClubPhoto, 0, len(req.Photos)) + for _, p := range req.Photos { + photos = append(photos, domain.ClubPhoto{ + ClubID: clubID, + MediaID: p.MediaID, + RefNumber: p.RefNumber, + }) + } + err := s.storage.UpdateClubPhotos(ctx, clubID, photos) + if err != nil { + return fmt.Errorf("can't storage.UpdateClubPhotos: %w", err) + } + return err + +} + func (s *ClubService) GetClearancePost(ctx context.Context, resp *responses.CheckResponse) (*responses.GetClearance, error) { if resp.IsAdmin { return &responses.GetClearance{Access: true, Comment: ""}, nil diff --git a/internal/domain/requests/post-club-photo.go b/internal/domain/requests/post-club-photo.go index 21c805d..b3cc148 100644 --- a/internal/domain/requests/post-club-photo.go +++ b/internal/domain/requests/post-club-photo.go @@ -53,7 +53,6 @@ func (c *PostClubPhoto) Bind(req *http.Request) error { Photos: pc.Photos, } return c.validate() - } func (c *PostClubPhoto) validate() error { diff --git a/internal/domain/requests/update-club-photo.go b/internal/domain/requests/update-club-photo.go new file mode 100644 index 0000000..7e85999 --- /dev/null +++ b/internal/domain/requests/update-club-photo.go @@ -0,0 +1,48 @@ +package requests + +import ( + "encoding/json" + "fmt" + "net/http" + "strconv" + + "github.com/STUD-IT-team/bmstu-stud-web-backend/internal/domain" + "github.com/go-chi/chi" +) + +type UpdateClubPhoto struct { + PostClubPhoto +} + +type UpdateClubPhotoPointer struct { + PostClubPhotoPointer +} + +func (c *UpdateClubPhoto) Bind(req *http.Request) error { + id, err := strconv.Atoi(chi.URLParam(req, "club_id")) + if err != nil { + return fmt.Errorf("can't Atoi on club_id in request: %w", err) + } + pc := PostClubPhotoPointer{} + + decoder := json.NewDecoder(req.Body) + decoder.DisallowUnknownFields() + err = decoder.Decode(&pc) + + if err != nil { + return fmt.Errorf("can't json decoder on updateClubPhoto: %v", err) + } + + if decoder.More() { + return fmt.Errorf("updateClubPhoto Bind: extraneous data after JSON object") + } + + err = pc.validate() + if err != nil { + return fmt.Errorf("%v: %v", domain.ErrIncorrectRequest, err) + } + c.ClubID = id + c.Photos = pc.Photos + + return c.validate() +} diff --git a/internal/domain/responses/delete-club-photo.go b/internal/domain/responses/delete-club-photo.go deleted file mode 100644 index 687e7a9..0000000 --- a/internal/domain/responses/delete-club-photo.go +++ /dev/null @@ -1,5 +0,0 @@ -package responses - -type DeleteClubPhoto struct { - Ids []int `json:"ids"` -} diff --git a/internal/infrastructure/postgres/club.go b/internal/infrastructure/postgres/club.go index 6671280..2814f9d 100644 --- a/internal/infrastructure/postgres/club.go +++ b/internal/infrastructure/postgres/club.go @@ -752,6 +752,67 @@ func (s *Postgres) AddClubPhotos(_ context.Context, p []domain.ClubPhoto) error return wrapPostgresError(tx.Commit()) } +const getClubPhoto = "SELECT id, ref_num, club_id, media_id FROM club_photo WHERE club_id = $1" +const upsertClubPhoto = ` +INSERT INTO club_photo (ref_num, club_id, media_id) VALUES ($1, $2, $3) +ON CONFLICT (media_id, club_id) DO UPDATE SET ref_num=$1 +` + +func (s *Postgres) UpdateClubPhotos(_ context.Context, clubID int, p []domain.ClubPhoto) error { + tx, err := s.db.Begin() + if err != nil { + return wrapPostgresError(err) + } + + dbPhotos := []domain.ClubPhoto{} + rows, err := tx.Query(getClubPhoto, p[0].ClubID) + if err != nil { + tx.Rollback() + return wrapPostgresError(err) + } + for rows.Next() { + dbPhoto := domain.ClubPhoto{} + err := rows.Scan(&dbPhoto.ID, &dbPhoto.RefNumber, &dbPhoto.ClubID, &dbPhoto.MediaID) + if err != nil { + tx.Rollback() + return wrapPostgresError(err) + } + dbPhotos = append(dbPhotos, dbPhoto) + } + + toDelete := make([]int, 0, len(dbPhotos)) + + for _, dbPhoto := range dbPhotos { + found := false + for _, photo := range p { + if dbPhoto.MediaID == photo.MediaID { + found = true + break + } + } + if !found { + toDelete = append(toDelete, dbPhoto.ID) + } + } + + for _, id := range toDelete { + _, err := tx.Exec(deleteClubPhoto, id) + if err != nil { + tx.Rollback() + return wrapPostgresError(err) + } + } + + for _, photo := range p { + _, err := tx.Exec(upsertClubPhoto, photo.RefNumber, clubID, photo.MediaID) + if err != nil { + tx.Rollback() + return wrapPostgresError(err) + } + } + return wrapPostgresError(tx.Commit()) +} + const deleteClubPhoto = "DELETE FROM club_photo WHERE id = $1" func (s *Postgres) DeleteClubPhoto(_ context.Context, id int) error { diff --git a/internal/ports/clubs.go b/internal/ports/clubs.go index 13b464e..d33e9bd 100644 --- a/internal/ports/clubs.go +++ b/internal/ports/clubs.go @@ -569,5 +569,42 @@ func (h *ClubsHandler) DeleteClubMedia(w http.ResponseWriter, req *http.Request) } func (h *ClubsHandler) UpdateClubMedia(w http.ResponseWriter, req *http.Request) handler.Response { + h.logger.Info("ClubsHandler: got UpdateClubMedia request") + + access, err := getAccessToken(req) + if err != nil { + h.logger.Warnf("can't get access token: %v", err) + return handler.UnauthorizedResponse() + } + + resp, err := h.guard.Check(context.Background(), &requests.CheckRequest{AccessToken: access}) + if err != nil || !resp.Valid { + h.logger.Warnf("Unauthorized request: %v", err) + return handler.UnauthorizedResponse() + } + + h.logger.Infof("ClubsHandler: UpdateClubMedia Authenticated: %v", resp.MemberID) + + photo := &requests.UpdateClubPhoto{} + + err = photo.Bind(req) + + if err != nil { + h.logger.Warnf("can't parse UpdateClubMedia %v", err) + return handler.BadRequestResponse() + } + h.logger.Infof("ClubsHandler: parse request.") + + err = h.clubs.UpdateClubPhoto(context.Background(), photo) + if err != nil { + h.logger.Warnf("can't service.UpdateClubMedia %v", err) + if errors.Is(err, postgres.ErrPostgresForeignKeyViolation) { + return handler.BadRequestResponse() + } else if errors.Is(err, postgres.ErrPostgresNotFoundError) { + return handler.NotFoundResponse() + } + return handler.InternalServerErrorResponse() + } + return handler.OkResponse(nil) } diff --git a/internal/storage/club.go b/internal/storage/club.go index 3a516ff..9b2617e 100644 --- a/internal/storage/club.go +++ b/internal/storage/club.go @@ -23,6 +23,7 @@ type clubStorage interface { AddClubPhotos(ctx context.Context, p []domain.ClubPhoto) error DeleteClubPhoto(ctx context.Context, id int) error GetPhotoClubID(ctx context.Context, photoID int) (int, error) + UpdateClubPhotos(ctx context.Context, clubID int, photos []domain.ClubPhoto) error } func (s *storage) GetClub(ctx context.Context, id int) (*domain.Club, error) { @@ -88,3 +89,7 @@ func (s *storage) DeleteClubPhoto(ctx context.Context, id int) error { func (s *storage) GetPhotoClubID(ctx context.Context, photoID int) (int, error) { return s.postgres.GetPhotoClubID(ctx, photoID) } + +func (s *storage) UpdateClubPhotos(ctx context.Context, clubID int, photos []domain.ClubPhoto) error { + return s.postgres.UpdateClubPhotos(ctx, clubID, photos) +} From c350ab8bb0d4d00495fa24c72f7936b1df8dd3b6 Mon Sep 17 00:00:00 2001 From: Impervguin Date: Wed, 17 Jul 2024 13:48:29 +0300 Subject: [PATCH 21/21] Added swagger to clubs photos --- internal/ports/clubs.go | 45 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/internal/ports/clubs.go b/internal/ports/clubs.go index d33e9bd..2900dee 100644 --- a/internal/ports/clubs.go +++ b/internal/ports/clubs.go @@ -489,6 +489,21 @@ func (h *ClubsHandler) UpdateClub(w http.ResponseWriter, req *http.Request) hand return handler.OkResponse(nil) } +// PostClubPhoto +// +// @Summary Добавляет в клуб фотографии клуба в базу данных +// @Description Добавляет в клуб фотографии клуба в базу данных +// @Tags auth.club +// @Produce json +// @Param club_id path int true "club id" +// @Param request body requests.PostClubPhoto true "post club photo data" +// @Success 200 +// @Failure 400 +// @Failure 401 +// @Failure 409 +// @Failure 500 +// @Router /clubs/media/{club_id} [post] +// @Security Authorized func (h *ClubsHandler) PostClubMedia(w http.ResponseWriter, req *http.Request) handler.Response { h.logger.Info("ClubsHandler: got PostClubMedia request") @@ -529,6 +544,21 @@ func (h *ClubsHandler) PostClubMedia(w http.ResponseWriter, req *http.Request) h return handler.OkResponse(nil) } +// DeleteClubPhoto +// +// @Summary Удаляет фотографию из фотографий клуба +// @Description Удаляет фотографию из фотографий клуба +// @Tags auth.club +// @Produce json +// @Param club_id path int true "club id" +// @Param request body requests.DeleteClubPhoto true "post club photo data" +// @Success 200 +// @Failure 400 +// @Failure 401 +// @Failure 404 +// @Failure 500 +// @Router /clubs/media/{club_id} [delete] +// @Security Authorized func (h *ClubsHandler) DeleteClubMedia(w http.ResponseWriter, req *http.Request) handler.Response { h.logger.Info("ClubsHandler: got DeleteClubMedia request") @@ -568,6 +598,21 @@ func (h *ClubsHandler) DeleteClubMedia(w http.ResponseWriter, req *http.Request) return handler.OkResponse(nil) } +// UpdateClubPhoto +// +// @Summary Обновляет все фотографии клуба +// @Description Обновляет все фотографии клуба +// @Tags auth.club +// @Produce json +// @Param club_id path int true "club id" +// @Param request body requests.UpdateClubPhoto true "post club photo data" +// @Success 200 +// @Failure 400 +// @Failure 401 +// @Failure 409 +// @Failure 500 +// @Router /clubs/media/{club_id} [put] +// @Security Authorized func (h *ClubsHandler) UpdateClubMedia(w http.ResponseWriter, req *http.Request) handler.Response { h.logger.Info("ClubsHandler: got UpdateClubMedia request")