package core import ( "crypto/rand" "encoding/base64" "errors" "gorm.io/gorm" ) func GetPlan(orm *gorm.DB, user User, id uint) (*Plan, error) { var plan Plan = Plan{ ID: id, } result := orm.Take(&plan) if errors.Is(result.Error, gorm.ErrRecordNotFound) { return nil, ErrNotFound } else if result.Error != nil { return nil, result.Error } if plan.Owner == user.Username { return &plan, nil } isMember, err := plan.IsMember(orm, &user) if !isMember || err != nil { return nil, err } return &plan, nil } func (p *Plan) GetAllUsers(orm *gorm.DB) ([]Member, error) { var members []Member err := orm.Model(p).Association("Members").Find(&members) return members, err } func (p *Plan) IsMember(orm *gorm.DB, u *User) (bool, error) { var member_count int64 result := orm. Table("members"). Where("user_id=? AND plan_id=?", u.Username, p.ID). Count(&member_count).Error if result != nil { return false, ErrNotMember } return member_count == 1, nil } func (p *Plan) GetMember(orm *gorm.DB, u *User) (*Member, error) { var m Member result := orm. Table("members"). Where("user_id=? AND plan_id=?", u.Username, p.ID). Take(&m).Error if result != nil { return nil, ErrNotMember } return &m, nil } func (p *Plan) HasNonUser(orm *gorm.DB, name string) (bool, error) { var member_count int64 result := orm. Table("members"). Where("plan_id=? AND name=?", p.ID, name). Count(&member_count).Error if result != nil { return false, result } return member_count == 1, nil } func (p *Plan) AddMember(orm *gorm.DB, new_member *Member) error { if new_member == nil { return errors.New("Member is nil") } new_member.PlanID = p.ID if new_member.Type == "non-user" { found, err := p.HasNonUser(orm, new_member.Name) if err != nil { return nil } if found { return errors.New("Non user name taken") } new_member.Status = "ready" return orm.Create(&new_member).Error } else if new_member.Type == "user" { user, err := GetUser(orm, new_member.UserID) if err != nil { return err } found, err := p.IsMember(orm, &user) if err != nil { return nil } if found { return errors.New("User already is member") } new_member.Status = "pending" var res error for retries := 3; retries >= 0; retries -= 1 { join_code := make([]byte, 32) _, err = rand.Read(join_code) if err != nil { return err } new_member.JoinCode = base64.URLEncoding.EncodeToString(join_code) res = orm.Create(&new_member).Error if res == nil { break } else if !errors.Is(res, gorm.ErrDuplicatedKey) { return res } } return res } else { return errors.New("Invalid type for user") } }