generated from VLADIMIR/template
add actions and auth
This commit is contained in:
@@ -25,3 +25,10 @@ func mapProtoTeamsToTeam(team *proto.Team) *models.Team {
|
||||
Name: team.Name,
|
||||
}
|
||||
}
|
||||
|
||||
func mapActionToProtoAction(action *models.Action) *proto.Action {
|
||||
return &proto.Action{
|
||||
Id: action.ID,
|
||||
Place: action.Place,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package services
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"evening_detective/internal/models"
|
||||
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
@@ -21,6 +22,15 @@ func NewRepository() (*Repository, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = db.Exec("CREATE TABLE IF NOT EXISTS actions (id INTEGER PRIMARY KEY AUTOINCREMENT, place TEXT, teamId INTEGER);")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// for tests
|
||||
// _, err = db.Exec("insert into teams (id, name, password) values (1, \"name\", \"pass\");")
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
return &Repository{db: db}, nil
|
||||
}
|
||||
|
||||
@@ -56,3 +66,54 @@ func (r *Repository) AddTeams(ctx context.Context, teams []*models.Team) ([]*mod
|
||||
}
|
||||
return teams, nil
|
||||
}
|
||||
|
||||
func (r *Repository) GetActions(ctx context.Context, teamId int64) ([]*models.Action, error) {
|
||||
rows, err := r.db.Query("select id, place from actions where teamId = $1", teamId)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer rows.Close()
|
||||
actions := []*models.Action{}
|
||||
|
||||
for rows.Next() {
|
||||
team := &models.Action{}
|
||||
err := rows.Scan(&team.ID, &team.Place)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
actions = append(actions, team)
|
||||
}
|
||||
return actions, nil
|
||||
}
|
||||
|
||||
func (r *Repository) AddActions(ctx context.Context, actions []*models.Action) error {
|
||||
for _, action := range actions {
|
||||
_, err := r.db.Exec("insert into actions (place, teamId) values ($1, $2)", action.Place, action.TeamID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Repository) GetTeam(ctx context.Context, teamId any, password any) (*models.Team, error) {
|
||||
rows, err := r.db.Query("select id, name from teams where id = $1 and password = $2", teamId, password)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
teams := []*models.Team{}
|
||||
|
||||
for rows.Next() {
|
||||
team := &models.Team{}
|
||||
err := rows.Scan(&team.ID, &team.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
teams = append(teams, team)
|
||||
}
|
||||
if len(teams) != 1 {
|
||||
return nil, errors.New("bad result")
|
||||
}
|
||||
return teams[0], nil
|
||||
}
|
||||
|
||||
@@ -4,19 +4,27 @@ import (
|
||||
"context"
|
||||
"evening_detective/internal/models"
|
||||
"evening_detective/internal/modules/password"
|
||||
"evening_detective/internal/services/story_service"
|
||||
"evening_detective/proto"
|
||||
"strconv"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
type Services struct {
|
||||
repository *Repository
|
||||
repository *Repository
|
||||
storyService *story_service.StoryService
|
||||
}
|
||||
|
||||
func NewServices(repository *Repository) *Services {
|
||||
func NewServices(
|
||||
repository *Repository,
|
||||
storyService *story_service.StoryService,
|
||||
) *Services {
|
||||
return &Services{
|
||||
repository: repository,
|
||||
repository: repository,
|
||||
storyService: storyService,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +41,20 @@ func (s *Services) GameStart(ctx context.Context, req *proto.GameStartReq) (*pro
|
||||
}
|
||||
|
||||
func (s *Services) AddAction(ctx context.Context, req *proto.AddActionReq) (*proto.AddActionRsp, error) {
|
||||
panic("unimplemented")
|
||||
team, err := s.getTeam(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
actions := []*models.Action{
|
||||
{
|
||||
Place: req.Place,
|
||||
TeamID: team.ID,
|
||||
},
|
||||
}
|
||||
if err := s.repository.AddActions(ctx, actions); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, err.Error())
|
||||
}
|
||||
return &proto.AddActionRsp{}, nil
|
||||
}
|
||||
|
||||
func (s *Services) DeleteTeams(ctx context.Context, req *proto.DeleteTeamsReq) (*proto.DeleteTeamsRsp, error) {
|
||||
@@ -41,7 +62,26 @@ func (s *Services) DeleteTeams(ctx context.Context, req *proto.DeleteTeamsReq) (
|
||||
}
|
||||
|
||||
func (s *Services) GetTeam(ctx context.Context, req *proto.GetTeamReq) (*proto.GetTeamRsp, error) {
|
||||
panic("unimplemented")
|
||||
team, err := s.getTeam(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
actions, err := s.repository.GetActions(ctx, team.ID)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, err.Error())
|
||||
}
|
||||
res := make([]*proto.Action, 0, len(actions))
|
||||
for _, action := range actions {
|
||||
newAction := mapActionToProtoAction(action)
|
||||
place, err := s.storyService.GetPlace(action.Place)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newAction.Text = place.Text
|
||||
res = append(res, newAction)
|
||||
}
|
||||
return &proto.GetTeamRsp{Actions: res}, err
|
||||
}
|
||||
|
||||
func (s *Services) GetTeamsCSV(ctx context.Context, req *proto.GetTeamsCSVReq) (*proto.GetTeamsCSVRsp, error) {
|
||||
@@ -77,3 +117,31 @@ func (s *Services) AddTeams(ctx context.Context, req *proto.AddTeamsReq) (*proto
|
||||
}
|
||||
return &proto.AddTeamsRsp{Teams: res}, err
|
||||
}
|
||||
|
||||
func (s *Services) getTeam(ctx context.Context) (*models.Team, error) {
|
||||
md, ok := metadata.FromIncomingContext(ctx)
|
||||
if !ok {
|
||||
return nil, status.Errorf(codes.Unauthenticated, "error creds")
|
||||
}
|
||||
|
||||
teamIdArr, ok := md["team-id"]
|
||||
if !ok {
|
||||
return nil, status.Errorf(codes.Unauthenticated, "error creds")
|
||||
}
|
||||
teamId, err := strconv.Atoi(teamIdArr[0])
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Unauthenticated, "error creds")
|
||||
}
|
||||
|
||||
passwordArr, ok := md["password"]
|
||||
if !ok {
|
||||
return nil, status.Errorf(codes.Unauthenticated, "error creds")
|
||||
}
|
||||
password := passwordArr[0]
|
||||
|
||||
team, err := s.repository.GetTeam(ctx, teamId, password)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Unauthenticated, err.Error())
|
||||
}
|
||||
return team, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package story_service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"os"
|
||||
)
|
||||
|
||||
type Story struct {
|
||||
Places []*Place `json:"places"`
|
||||
}
|
||||
|
||||
type Place struct {
|
||||
Code string `json:"code"`
|
||||
Text string `json:"text"`
|
||||
}
|
||||
|
||||
type StoryService struct {
|
||||
story *Story
|
||||
}
|
||||
|
||||
func NewStoryService() (*StoryService, error) {
|
||||
data, err := os.ReadFile("./story/story.json")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
story := &Story{}
|
||||
if err := json.Unmarshal(data, story); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &StoryService{story: story}, nil
|
||||
}
|
||||
|
||||
func (s *StoryService) GetPlace(code string) (*Place, error) {
|
||||
for _, place := range s.story.Places {
|
||||
if place.Code == code {
|
||||
return place, nil
|
||||
}
|
||||
}
|
||||
return nil, errors.New("place not found")
|
||||
}
|
||||
Reference in New Issue
Block a user