Skip to content
This repository has been archived by the owner on Aug 11, 2023. It is now read-only.

feat: Forums CRUD #27

Open
wants to merge 19 commits into
base: main
Choose a base branch
from
48 changes: 48 additions & 0 deletions internal/entity/forumpost/forumpost.go
Copy link
Contributor Author

@tan-yun-e tan-yun-e Jul 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WIP did not mean to stage files on forumpost

Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package forumpost

import "errors"

type Role string

func (Role) Values() (kinds []string) {
for _, s := range Roles {
kinds = append(kinds, string(s))
}
return
}

func (fr Role) Validate() error {
switch fr {
case RoleOwner, RoleEducator, RoleMember:
return nil
default:
return errors.New("group role is not valid")
}
}

var (
Roles = []Role{RoleOwner, RoleEducator, RoleMember}

RoleOwner Role = "owner"
RoleEducator Role = "educator"
RoleMember Role = "member"
)

type Options struct {
Title string
Content string
}

type Option func(*Options)

func Name(n string) Option {
return func(opts *Options) {
opts.Title = n
}
}

func ShortName(n string) Option {
return func(opts *Options) {
opts.Content = n
}
}
4 changes: 2 additions & 2 deletions internal/group/forum/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func mapDomainErr(err error) render.Renderer {
return &apperror.ErrResponse{
Err: err,
HTTPStatusCode: http.StatusNotFound,
AppErrCode: 40401,
AppErrCode: 40402,
AppErrMessage: "The group specified does not exist",
}
}
Expand All @@ -28,7 +28,7 @@ func mapDomainErr(err error) render.Renderer {
return &apperror.ErrResponse{
Err: err,
HTTPStatusCode: http.StatusConflict,
AppErrCode: 40901,
AppErrCode: 40902,
AppErrMessage: "This forum short name is unavailable",
}
}
Expand Down
24 changes: 24 additions & 0 deletions internal/group/forum/forumpost/repository.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package forumpost

import (
"context"

"github.com/np-inprove/server/internal/entity"
"github.com/np-inprove/server/internal/entity/forumpost"
)

type Reader interface {
FindForumPostsByUser() ([]*entity.ForumPost, error)
FindForumPost() (*entity.ForumPost, error)

FindGroupUser(ctx context.Context, principal, shortName string) (*entity.GroupUser, error)
}

type Writer interface {
CreateForumPost(ctx context.Context, forumID int, opts ...forumpost.Option) (*entity.ForumPost, error)
}

type Repository interface {
Reader
Writer
}
2 changes: 1 addition & 1 deletion internal/group/forum/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
)

type Reader interface {
FindForumsByUser(ctx context.Context, principal string) ([]*entity.Forum, error)
FindForumsByGroup(ctx context.Context, principal string) ([]*entity.Forum, error)
FindForumByGroupIDAndShortName(ctx context.Context, groupID int, shortName string) (*entity.Forum, error)
FindForum(ctx context.Context, shortName string) (*entity.Forum, error)

Expand Down
2 changes: 1 addition & 1 deletion internal/group/forum/repository_ent.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func NewEntRepository(e *ent.Client) Repository {
return &entRepository{client: e}
}

func (e entRepository) FindForumsByUser(ctx context.Context, principal string) ([]*entity.Forum, error) {
func (e entRepository) FindForumsByGroup(ctx context.Context, principal string) ([]*entity.Forum, error) {
forum, err := e.client.Forum.Query().
Where(
entforum.HasGroupWith(
Expand Down
37 changes: 19 additions & 18 deletions internal/group/forum/usecase.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,17 @@ import (
)

type UseCase interface {
ListPrincipalForums(ctx context.Context, principal string) ([]*entity.Forum, error)
// groupShortName is the shortname used by groups, shortName us the shortname used by forums
ListForums(ctx context.Context, principal string, groupShortName string) ([]*entity.Forum, error)

// CreateGroup should be an admin only function
CreateForum(ctx context.Context, principal, name, shortName, description string) (*entity.Forum, error)
// CreateGroup should be an educator + owner only function
CreateForum(ctx context.Context, principal, groupShortName, name, shortName, description string) (*entity.Forum, error)

// DeleteGroup should be an admin only function
DeleteForum(ctx context.Context, principal string, shortName string) error
// DeleteGroup should be an educator + owner only function
DeleteForum(ctx context.Context, principal string, groupShortName string) error

// UpdateForum should be an admin only function
UpdateForum(ctx context.Context, principal string, name, shortName, description string) (*entity.Forum, error)
// UpdateForum should be an educator + owner only function
UpdateForum(ctx context.Context, principal string, groupShortName, name, shortName, description string) (*entity.Forum, error)
}

type useCase struct {
Expand All @@ -30,12 +31,12 @@ func NewUseCase(r Repository) UseCase {
return useCase{repo: r}
}

func (u useCase) ListPrincipalForums(ctx context.Context, principal string) ([]*entity.Forum, error) {
return u.repo.FindForumsByUser(ctx, principal)
func (u useCase) ListForums(ctx context.Context, principal string, groupShortName string) ([]*entity.Forum, error) {
return u.repo.FindForumsByGroup(ctx, principal)
}

func (u useCase) CreateForum(ctx context.Context, principal, name, shortName, description string) (*entity.Forum, error) {
usr, err := u.repo.FindGroupUser(ctx, principal, shortName)
func (u useCase) CreateForum(ctx context.Context, principal, groupShortName, name, shortName, description string) (*entity.Forum, error) {
usr, err := u.repo.FindGroupUser(ctx, principal, groupShortName)
if err != nil {
return nil, fmt.Errorf("failed to find user: %w", err)
}
Expand All @@ -44,7 +45,7 @@ func (u useCase) CreateForum(ctx context.Context, principal, name, shortName, de
return nil, fmt.Errorf("user edges not loaded")
}

if usr.Role == group.RoleMember {
if usr.Role != group.RoleEducator || usr.Role != group.RoleOwner {
return nil, ErrUnauthorized
}

Expand All @@ -61,13 +62,13 @@ func (u useCase) CreateForum(ctx context.Context, principal, name, shortName, de
return forum, nil
}

func (u useCase) DeleteForum(ctx context.Context, principal string, shortName string) error {
usr, err := u.repo.FindGroupUser(ctx, principal, shortName)
func (u useCase) DeleteForum(ctx context.Context, principal string, groupShortName string) error {
usr, err := u.repo.FindGroupUser(ctx, principal, groupShortName)
if err != nil {
return fmt.Errorf("failed to find user: %w", err)
}

if usr.Role == group.RoleMember {
if usr.Role != group.RoleEducator || usr.Role != group.RoleOwner {
return ErrUnauthorized
}

Expand All @@ -78,8 +79,8 @@ func (u useCase) DeleteForum(ctx context.Context, principal string, shortName st
return nil
}

func (u useCase) UpdateForum(ctx context.Context, principal string, name, shortName, description string) (*entity.Forum, error) {
usr, err := u.repo.FindGroupUser(ctx, principal, shortName)
func (u useCase) UpdateForum(ctx context.Context, principal string, groupShortName, name, shortName, description string) (*entity.Forum, error) {
usr, err := u.repo.FindGroupUser(ctx, principal, groupShortName)
if err != nil {
return nil, fmt.Errorf("failed to find user: %w", err)
}
Expand All @@ -88,7 +89,7 @@ func (u useCase) UpdateForum(ctx context.Context, principal string, name, shortN
return nil, fmt.Errorf("user edges not loaded")
}

if usr.Role == group.RoleMember {
if usr.Role != group.RoleEducator || usr.Role != group.RoleOwner {
return nil, ErrUnauthorized
}

Expand Down
3 changes: 2 additions & 1 deletion internal/payload/forum.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import (
)

type Forum struct {
ID int `json:"id,omitempty"`
GroupID int `json:"groupid,omitempty"`
tan-yun-e marked this conversation as resolved.
Show resolved Hide resolved
ID int `json:"forumid,omitempty"`
Name string `json:"name,omitempty"`
ShortName string `json:"shortName,omitempty"`
Description string `json:"description,omitempty"`
Expand Down
38 changes: 38 additions & 0 deletions internal/payload/forumpost.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package payload

import (
"net/http"

"github.com/gookit/validate"
)

type ForumPost struct {
ID int `json:"id,omitempty"`
Title string `json:"title,omitempty"`
Content string `json:"content,omitempty"`
TimeDate string `json:"description,omitempty"`
}

func (fp ForumPost) Render(_ http.ResponseWriter, _ *http.Request) error {
return nil
}

type CreateForumPostRequest struct {
Name string `json:"name,omitempty" validate:"required|minLen:3"`
ShortName string `json:"shortName,omitempty" validate:"required|alphaDash"`
Description string `json:"description,omitempty"`
}

func (c CreateForumPostRequest) Validate() *validate.Validation {
return validate.Struct(c)
}

type UpdateForumPostRequest struct {
Name string `json:"name,omitempty" validate:"required|minLen:3"`
ShortName string `json:"shortName,omitempty" validate:"required|alphaDash"`
Description string `json:"description,omitempty"`
}

func (u UpdateForumPostRequest) Validate() *validate.Validation {
return validate.Struct(u)
}