Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
d193b79
migration: add quest_settings and quest_characters tables
the-medo Nov 17, 2024
0855c22
feat: add queries for quest_settings and quest_characters tables
the-medo Nov 18, 2024
76c8a7c
feat: extend view_quests for new properties from quest_settings table
the-medo Nov 18, 2024
111e33b
feat: remove quest_settings table, move its columns to quests table
the-medo Nov 19, 2024
9033e0f
feat: protobuf for quest_characters
the-medo Nov 19, 2024
f3d8929
feat: add new properties to rpc_update_quest.go
the-medo Nov 20, 2024
f218b63
feat: add CreateQuestCharacter
the-medo Nov 21, 2024
72090aa
feat: add UpdateQuestCharacter
the-medo Nov 21, 2024
b3b8682
feat: more validations to rpc_update_quest_character
the-medo Nov 22, 2024
b6a8ebb
feat: add rpc_delete_quest_character
the-medo Nov 22, 2024
47f7d29
feat: add GetQuestCharacters
the-medo Nov 25, 2024
2e900f3
feat: add GetCharacterQuests
the-medo Nov 28, 2024
1541208
feat: add status and can_join to PbQuest
the-medo Nov 29, 2024
7bec1f2
feat: upsert into user module when module admin is approved
the-medo Dec 1, 2024
8f32f77
fix: make get_quests arguments optional
the-medo Dec 3, 2024
aedd384
fix: fix counter of get_quests endpoint
the-medo Dec 21, 2024
aa93def
fix: increase version of golang-migrate-objects to fix bug when migra…
the-medo Dec 21, 2024
5aa40c4
feat: add filter by status and can_join properties to get_quests func…
the-medo Dec 21, 2024
af7d711
feat: add filter by status and can_join properties to GetQuests endpoint
the-medo Dec 21, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions api/services/characters/rpc_get_character_quests.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package characters

import (
"context"
"encoding/json"
"github.com/the-medo/talebound-backend/api/apihelpers"
"github.com/the-medo/talebound-backend/converters"
"github.com/the-medo/talebound-backend/e"
"github.com/the-medo/talebound-backend/pb"
"github.com/the-medo/talebound-backend/validator"
"google.golang.org/genproto/googleapis/rpc/errdetails"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
)

func (server *ServiceCharacters) GetCharacterQuests(ctx context.Context, req *pb.GetCharacterQuestsRequest) (*pb.GetQuestCharactersResponse, error) {
violations := validateGetCharacterQuests(req)

if violations != nil {
return nil, e.InvalidArgumentError(violations)
}

questCharacters, err := server.Store.GetQuestCharactersByCharacterID(ctx, req.GetCharacterId())
if err != nil {
return nil, err
}

rsp := &pb.GetQuestCharactersResponse{
QuestCharacters: make([]*pb.QuestCharacter, len(questCharacters)),
}

questIds := make([]int32, len(questCharacters))

for i, qc := range questCharacters {
rsp.QuestCharacters[i] = converters.ConvertQuestCharacter(qc)
questIds[i] = qc.QuestID
}

fetchInterface := &apihelpers.FetchInterface{
QuestIds: questIds,
}

fetchIdsHeader, err := json.Marshal(fetchInterface)

md := metadata.Pairs(
"X-Fetch-Ids", string(fetchIdsHeader),
)
err = grpc.SendHeader(ctx, md)
if err != nil {
return nil, err
}

return rsp, nil
}

func validateGetCharacterQuests(req *pb.GetCharacterQuestsRequest) (violations []*errdetails.BadRequest_FieldViolation) {

if err := validator.ValidateUniversalId(req.GetCharacterId()); err != nil {
violations = append(violations, e.FieldViolation("character_id", err))
}

return violations
}
22 changes: 22 additions & 0 deletions api/services/modules/rpc_update_module_admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,28 @@ func (server *ServiceModules) UpdateModuleAdmin(ctx context.Context, req *pb.Upd
}
}

if req.GetApproved() == 1 {
_, err := server.Store.UpsertUserModule(ctx, db.UpsertUserModuleParams{
ModuleID: req.GetModuleId(),
UserID: req.GetUserId(),
Admin: sql.NullBool{
Bool: true,
Valid: true,
},
Favorite: sql.NullBool{
Bool: true,
Valid: true,
},
Following: sql.NullBool{
Bool: true,
Valid: true,
},
})
if err != nil {
return nil, err
}
}

moduleAdmin, err := server.Store.UpdateModuleAdmin(ctx, arg)
if err != nil {
return nil, err
Expand Down
71 changes: 71 additions & 0 deletions api/services/quests/rpc_create_quest_character.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package quests

import (
"context"
"github.com/the-medo/talebound-backend/api/servicecore"
"github.com/the-medo/talebound-backend/converters"
db "github.com/the-medo/talebound-backend/db/sqlc"
"github.com/the-medo/talebound-backend/e"
"github.com/the-medo/talebound-backend/pb"
"github.com/the-medo/talebound-backend/validator"
"google.golang.org/genproto/googleapis/rpc/errdetails"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)

func (server *ServiceQuests) CreateQuestCharacter(ctx context.Context, request *pb.CreateQuestCharacterRequest) (*pb.QuestCharacter, error) {
violations := validateCreateQuestCharacter(request)
if violations != nil {
return nil, e.InvalidArgumentError(violations)
}

//only character owner can add it to quest
_, _, err := server.CheckModuleTypePermissions(ctx, db.ModuleTypeCharacter, request.GetCharacterId(), &servicecore.ModulePermission{
NeedsSuperAdmin: true,
})
if err != nil {
return nil, err
}

quest, err := server.Store.GetQuestByID(ctx, request.GetQuestId())
if err != nil {
return nil, err
}
character, err := server.Store.GetQuestByID(ctx, request.GetCharacterId())
if err != nil {
return nil, err
}
if quest.SystemID != character.SystemID {
return nil, status.Errorf(codes.Internal, "failed to create quest character: quest and character systems do not match")
}
if quest.WorldID != character.WorldID {
return nil, status.Errorf(codes.Internal, "failed to create quest character: quest and character worlds do not match")
}

argQuestCharacter := db.CreateQuestCharacterParams{
QuestID: request.GetQuestId(),
CharacterID: request.GetCharacterId(),
Approved: 2, //Pending
MotivationalLetter: request.GetMotivationalLetter(),
}

newQuestCharacter, err := server.Store.CreateQuestCharacter(ctx, argQuestCharacter)
if err != nil {
return nil, err
}

rsp := converters.ConvertQuestCharacter(newQuestCharacter)

return rsp, nil
}

func validateCreateQuestCharacter(req *pb.CreateQuestCharacterRequest) (violations []*errdetails.BadRequest_FieldViolation) {
if err := validator.ValidateUniversalId(req.GetQuestId()); err != nil {
violations = append(violations, e.FieldViolation("quest_id", err))
}

if err := validator.ValidateUniversalId(req.GetCharacterId()); err != nil {
violations = append(violations, e.FieldViolation("character_id", err))
}
return violations
}
58 changes: 58 additions & 0 deletions api/services/quests/rpc_delete_quest_character.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package quests

import (
"context"
"github.com/the-medo/talebound-backend/api/servicecore"
db "github.com/the-medo/talebound-backend/db/sqlc"
"github.com/the-medo/talebound-backend/e"
"github.com/the-medo/talebound-backend/pb"
"github.com/the-medo/talebound-backend/validator"
"google.golang.org/genproto/googleapis/rpc/errdetails"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/emptypb"
)

func (server *ServiceQuests) DeleteQuestCharacter(ctx context.Context, req *pb.DeleteQuestCharacterRequest) (*emptypb.Empty, error) {
violations := validateDeleteQuestCharacterRequest(req)
if violations != nil {
return nil, e.InvalidArgumentError(violations)
}

//Only quest or character owner can delete it
_, _, err := server.CheckModuleTypePermissions(ctx, db.ModuleTypeQuest, req.GetQuestId(), &servicecore.ModulePermission{
NeedsSuperAdmin: true,
})
if err != nil {
_, _, err := server.CheckModuleTypePermissions(ctx, db.ModuleTypeCharacter, req.GetCharacterId(), &servicecore.ModulePermission{
NeedsSuperAdmin: true,
})
if err != nil {
return nil, err
}
}

arg := db.DeleteQuestCharacterParams{
QuestID: req.GetQuestId(),
CharacterID: req.GetCharacterId(),
}

err = server.Store.DeleteQuestCharacter(ctx, arg)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to delete quest character: %s", err)
}

return &emptypb.Empty{}, nil
}

func validateDeleteQuestCharacterRequest(req *pb.DeleteQuestCharacterRequest) (violations []*errdetails.BadRequest_FieldViolation) {
if err := validator.ValidateModuleId(req.GetQuestId()); err != nil {
violations = append(violations, e.FieldViolation("quest_id", err))
}

if err := validator.ValidateModuleId(req.GetCharacterId()); err != nil {
violations = append(violations, e.FieldViolation("character_id", err))
}

return violations
}
63 changes: 63 additions & 0 deletions api/services/quests/rpc_get_quest_characters.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package quests

import (
"context"
"encoding/json"
"github.com/the-medo/talebound-backend/api/apihelpers"
"github.com/the-medo/talebound-backend/converters"
"github.com/the-medo/talebound-backend/e"
"github.com/the-medo/talebound-backend/pb"
"github.com/the-medo/talebound-backend/validator"
"google.golang.org/genproto/googleapis/rpc/errdetails"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
)

func (server *ServiceQuests) GetQuestCharacters(ctx context.Context, req *pb.GetQuestCharactersRequest) (*pb.GetQuestCharactersResponse, error) {
violations := validateGetQuestCharacters(req)

if violations != nil {
return nil, e.InvalidArgumentError(violations)
}

questCharacters, err := server.Store.GetQuestCharactersByQuestID(ctx, req.GetQuestId())
if err != nil {
return nil, err
}

rsp := &pb.GetQuestCharactersResponse{
QuestCharacters: make([]*pb.QuestCharacter, len(questCharacters)),
}

characterIds := make([]int32, len(questCharacters))

for i, qc := range questCharacters {
rsp.QuestCharacters[i] = converters.ConvertQuestCharacter(qc)
characterIds[i] = qc.CharacterID
}

fetchInterface := &apihelpers.FetchInterface{
CharacterIds: characterIds,
}

fetchIdsHeader, err := json.Marshal(fetchInterface)

md := metadata.Pairs(
"X-Fetch-Ids", string(fetchIdsHeader),
)
err = grpc.SendHeader(ctx, md)
if err != nil {
return nil, err
}

return rsp, nil
}

func validateGetQuestCharacters(req *pb.GetQuestCharactersRequest) (violations []*errdetails.BadRequest_FieldViolation) {

if err := validator.ValidateUniversalId(req.GetQuestId()); err != nil {
violations = append(violations, e.FieldViolation("quest_id", err))
}

return violations
}
48 changes: 36 additions & 12 deletions api/services/quests/rpc_get_quests.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package quests

import (
"context"
"database/sql"
"encoding/json"
"fmt"
"github.com/the-medo/talebound-backend/api/apihelpers"
"github.com/the-medo/talebound-backend/converters"
db "github.com/the-medo/talebound-backend/db/sqlc"
"github.com/the-medo/talebound-backend/e"
"github.com/the-medo/talebound-backend/pb"
Expand All @@ -24,32 +26,54 @@ func (server *ServiceQuests) GetQuests(ctx context.Context, req *pb.GetQuestsReq
limit, offset := apihelpers.GetDefaultQueryBoundaries(req.GetLimit(), req.GetOffset())

arg := db.GetQuestsParams{
PageLimit: limit,
PageOffset: offset,
PageLimit: sql.NullInt32{Int32: limit, Valid: true},
PageOffset: sql.NullInt32{Int32: offset, Valid: true},
Tags: req.GetTags(),
OrderBy: "created_at",
OrderBy: sql.NullString{String: "created_at", Valid: true},
WorldID: sql.NullInt32{
Int32: req.GetWorldId(),
Valid: req.WorldId != nil,
},
SystemID: sql.NullInt32{
Int32: req.GetSystemId(),
Valid: req.SystemId != nil,
},
CanJoin: sql.NullBool{
Bool: req.GetCanJoin(),
Valid: req.CanJoin != nil,
},
Status: db.NullQuestStatus{
QuestStatus: converters.ConvertQuestStatusToDB(req.GetStatus()),
Valid: req.Status != nil,
},
}

countArg := db.GetQuestsCountParams{
IsPublic: sql.NullBool{},
Tags: req.GetTags(),
WorldID: arg.WorldID,
SystemID: arg.SystemID,
CanJoin: arg.CanJoin,
Status: arg.Status,
}

if req.Public != nil {
arg.IsPublic = req.GetPublic()
} else {
arg.IsPublic = true
arg.IsPublic = sql.NullBool{Bool: req.GetPublic(), Valid: true}
countArg.IsPublic = sql.NullBool{
Bool: req.GetPublic(),
Valid: true,
}
}

if req.OrderBy != nil {
arg.OrderBy = req.GetOrderBy()
arg.OrderBy.String = req.GetOrderBy()
}

quests, err := server.Store.GetQuests(ctx, arg)
if err != nil {
return nil, err
}

countArg := db.GetQuestsCountParams{
IsPublic: arg.IsPublic,
Tags: req.GetTags(),
}

totalCount, err := server.Store.GetQuestsCount(ctx, countArg)
if err != nil {
return nil, err
Expand Down
Loading
Loading