Skip to content

Commit

Permalink
finish context switcher
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanfaerman committed Feb 12, 2024
1 parent d649d1d commit 59adfc9
Show file tree
Hide file tree
Showing 21 changed files with 501 additions and 199 deletions.
2 changes: 1 addition & 1 deletion internal/handlers/memberships.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func (h Membership) Create(w http.ResponseWriter, r *http.Request) {
if errs, ok := err.(services.ValidationError); ok {
for field, e := range errs {
switch field {
case "Account.Name":
case "Account.Settings.ProfileSettings.Name":
viewErr.Name = e
case "Account.Slug":
viewErr.Slug = e
Expand Down
34 changes: 34 additions & 0 deletions internal/handlers/navigation.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/go-chi/chi"
"github.com/ryanfaerman/netctl/internal/middleware"
"github.com/ryanfaerman/netctl/internal/models"
"github.com/ryanfaerman/netctl/internal/services"
"github.com/ryanfaerman/netctl/internal/views"
"github.com/ryanfaerman/netctl/web/named"
Expand All @@ -21,6 +22,9 @@ func (h Navigation) Routes(r chi.Router) {
r.Use(middleware.HTMXOnly)
r.Get(named.Route("slide-over-show", "/-/slide-over/show/{side}"), h.SlideOverShow)
r.Get(named.Route("slide-over-hide", "/-/slide-over/hide"), h.SlideOverHide)

r.Get(named.Route("modal-show", "/-/modal/show/{name}"), h.ModalShow)
r.Get(named.Route("modal-hide", "/-/modal/hide"), h.ModalHide)
}

func (h Navigation) SlideOverShow(w http.ResponseWriter, r *http.Request) {
Expand All @@ -38,3 +42,33 @@ func (h Navigation) SlideOverShow(w http.ResponseWriter, r *http.Request) {
func (h Navigation) SlideOverHide(w http.ResponseWriter, r *http.Request) {
views.SlideOverTarget().Render(r.Context(), w)
}

func (h Navigation) ModalShow(w http.ResponseWriter, r *http.Request) {
name := chi.URLParam(r, "name")
v := views.Modal{
Name: name,
}

switch name {
default:
h.ModalHide(w, r)
return
case "settings-context-switcher":
currentUser := services.Session.GetAccount(r.Context())
accounts := []*models.Account{currentUser}
delegates, err := currentUser.Delegated(r.Context())
if err != nil {
ErrorHandler(err)(w, r)
return
}
for _, d := range delegates {
target := d.Target(r.Context())
accounts = append(accounts, target)
}
v.SettingsContextSwitcher(accounts).Render(r.Context(), w)
}
}

func (h Navigation) ModalHide(w http.ResponseWriter, r *http.Request) {
views.ModalOverlay(false).Render(r.Context(), w)
}
2 changes: 1 addition & 1 deletion internal/handlers/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func (h settings) Settings(w http.ResponseWriter, r *http.Request) {
account = currentUser
}

if err := services.Authorization.Can(r.Context(), currentUser, "edit", account); err != nil {
if err := services.Authorization.Can(ctx, currentUser, "edit", account); err != nil {
ErrorHandler(err)(w, r)
return
}
Expand Down
8 changes: 6 additions & 2 deletions internal/models/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,12 +182,16 @@ func (m *Account) PrimaryEmail() (Email, error) {
return Email{}, errors.New("no primary email")
}

func (m *Account) Delegated(ctx context.Context) ([]*Membership, error) {
return Find[Membership](ctx, ByAccount(m.ID))
}

func (m *Account) Clubs(ctx context.Context) ([]*Membership, error) {
return FindMemberships(ctx, m, AccountKindClub)
return Find[Membership](ctx, ByAccount(m.ID), ByKind(int(AccountKindClub)))
}

func (m *Account) Organizations(ctx context.Context) ([]*Membership, error) {
return FindMemberships(ctx, m, AccountKindOrganization)
return Find[Membership](ctx, ByAccount(m.ID), ByKind(int(AccountKindOrganization)))
}

func FindAccountByID(ctx context.Context, id int64) (*Account, error) {
Expand Down
4 changes: 0 additions & 4 deletions internal/models/account_finder.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,6 @@ func (m Account) Find(ctx context.Context, queries finders.QuerySet) (any, error
for i, raw := range raws {
a := Account{
ID: raw.ID,
Name: raw.Name,
About: raw.About,
Kind: AccountKind(raw.Kind),
CreatedAt: raw.Createdat,
Settings: DefaultSettings,
Expand Down Expand Up @@ -197,12 +195,10 @@ func callsignsWithinRange(ctx context.Context, arg callsignsWithinRangeParams) (

err := rows.Scan(
&raw.ID,
&raw.Name,
&raw.Createdat,
&raw.Updatedat,
&raw.Deletedat,
&raw.Kind,
&raw.About,
&raw.Settings,
&raw.Slug,
&distance,
Expand Down
89 changes: 37 additions & 52 deletions internal/models/membership.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,77 +2,62 @@ package models

import (
"context"
"encoding/json"
"fmt"
"runtime"
"time"

"dario.cat/mergo"
"github.com/ryanfaerman/netctl/internal/dao"
"github.com/ryanfaerman/netctl/internal/models/finders"
)

type Membership struct {
Account *Account `json:"account"`
Target *Account `json:"target"`
Role *Role `json:"role" validate:"required"`
AccountID int64

TargetID int64
RoleID int64

CreatedAt time.Time
ID int64
}

func (m *Membership) Can(ctx context.Context, account *Account, action string) error {
p := ParsePermission(action)
func (m *Membership) Account(ctx context.Context) (*Account, error) {
return finders.FindOne[Account](ctx, finders.ByID(m.AccountID))
}

if !m.Role.Permissions.Has(p) {
return fmt.Errorf("account %s does not have permission %s", m.Account.Name, p)
func (m *Membership) Target(ctx context.Context) *Account {
a, err := finders.FindOne[Account](ctx, finders.ByID(m.TargetID))
if err != nil {
global.log.Error("error finding account", "error", err)
return AccountAnonymous
}

return nil
return a
}

func FindMemberships(ctx context.Context, account *Account, kind AccountKind) ([]*Membership, error) {
var memberships []*Membership
raws, err := global.dao.GetAccountKindMemberships(ctx, dao.GetAccountKindMembershipsParams{
AccountID: account.ID,
Kind: int64(kind),
})
func (m *Membership) Role(ctx context.Context) *Role {
r, err := finders.FindOne[Role](ctx, finders.ByID(m.RoleID))
if err != nil {
return memberships, err
return RoleNone
}
for _, raw := range raws {
target := &Account{
ID: raw.ID,
Name: raw.Name,
About: raw.About,
CreatedAt: raw.Createdat,
Kind: AccountKind(raw.Kind),
}
if err := json.Unmarshal([]byte(raw.Settings), &target.Settings); err != nil {
return memberships, err
}
return r
}

if err := mergo.Merge(&target.Settings, DefaultSettings); err != nil {
return memberships, err
}
func (m *Membership) Can(ctx context.Context, account *Account, action string) error {
p := ParsePermission(action)

if raw.Deletedat.Valid {
target.DeletedAt = raw.Deletedat.Time
target.Deleted = true
}
if !m.Role(ctx).Permissions.Has(p) {
return fmt.Errorf("account %d does not have permission %s", m.AccountID, p)
}

role := &Role{
ID: raw.RoleID,
Name: raw.RoleName,
Permissions: Permission(raw.RolePermissions),
Ranking: raw.RoleRanking,
}
return nil
}

memberships = append(memberships, &Membership{
Account: account,
Target: target,
Role: role,
CreatedAt: raw.MembershipCreatedAt,
ID: raw.ID,
})
}
return memberships, nil
func FindMemberships(ctx context.Context, account *Account, kind AccountKind) ([]*Membership, error) {
_, file, line, _ := runtime.Caller(1)
global.log.Warn(
"DEPRECATED FUNCTION",
"func", "FindMemberships",
"use", "Find[Membership](ctx, ByAccount(ID)",
"file", file,
"line", line,
)
return finders.Find[Membership](ctx, finders.ByAccount(account.ID), finders.ByKind(int(kind)))
}
52 changes: 34 additions & 18 deletions internal/models/membership_finder.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,17 @@ func (m Membership) Find(ctx context.Context, queries finders.QuerySet) (any, er
default:
return nil, finders.ErrInvalidWhere
case queries.HasWhere("account_id", "member_of") && queries.HasField("permission"):
memberOf, err := finders.EnforceValue[int64](queries, "member_of")
if err != nil {
return nil, err
memberOf, ok := finders.EnforceValue[int64](queries, "member_of")
if ok != nil {
return nil, ok
}
accountID, err := finders.EnforceValue[int64](queries, "account_id")
if err != nil {
return nil, err
accountID, ok := finders.EnforceValue[int64](queries, "account_id")
if ok != nil {
return nil, ok
}
permission, err := finders.EnforceValue[int64](queries, "permission")
if err != nil {
return nil, err
permission, ok := finders.EnforceValue[int64](queries, "permission")
if ok != nil {
return nil, ok
}

raw, err = global.dao.HasPermissionOnAccount(ctx, dao.HasPermissionOnAccountParams{
Expand All @@ -39,23 +39,39 @@ func (m Membership) Find(ctx context.Context, queries finders.QuerySet) (any, er
Permission: permission,
})
raws = append(raws, raw)
case queries.HasWhere("account_id", "kind"):
accountID, ok := finders.EnforceValue[int64](queries, "account_id")
if ok != nil {
return nil, ok
}
kind, ok := finders.EnforceValue[int](queries, "kind")
if ok != nil {
return nil, ok
}

raws, err = global.dao.GetMembershipsForAccountAndKind(ctx, dao.GetMembershipsForAccountAndKindParams{
AccountID: accountID,
Kind: int64(kind),
})
case queries.HasWhere("account_id"):
accountID, ok := finders.EnforceValue[int64](queries, "account_id")
if ok != nil {
return nil, ok
}
raws, err = global.dao.GetMembershipsForAccount(ctx, accountID)

}

if err != nil {
return nil, err
}

found = make([]*Membership, len(raws))
for i, raw := range raws {
found[i] = &Membership{
Account: &Account{
ID: raw.AccountID,
},
Target: &Account{
ID: raw.MemberOf,
},
Role: &Role{
ID: raw.RoleID,
},
AccountID: raw.AccountID,
TargetID: raw.MemberOf,
RoleID: raw.RoleID,
CreatedAt: raw.CreatedAt,
ID: raw.ID,
}
Expand Down
7 changes: 7 additions & 0 deletions internal/models/role.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,10 @@ type Role struct {
Permissions Permission `form:"permissions" json:"permissions" validate:"required"`
Ranking int64 `form:"ranking" json:"ranking"`
}

var RoleNone = &Role{
Name: "None",
ID: -1,
Permissions: PermissionNone,
Ranking: -1,
}
46 changes: 46 additions & 0 deletions internal/models/role_finder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package models

import (
"context"

"github.com/ryanfaerman/netctl/internal/dao"
"github.com/ryanfaerman/netctl/internal/models/finders"
)

func (m Role) Find(ctx context.Context, queries finders.QuerySet) (any, error) {
var (
raw dao.Role
raws []dao.Role
err error
found []*Role
)
switch {
default:
return nil, finders.ErrInvalidWhere
case queries.HasWhere("id"):
id, ok := finders.EnforceValue[int64](queries, "id")
if ok != nil {
return nil, ok
}

raw, err = global.dao.GetRole(ctx, id)
raws = append(raws, raw)
}

if err != nil {
return nil, err
}

found = make([]*Role, len(raws))

for i, raw := range raws {
found[i] = &Role{
ID: raw.ID,
Name: raw.Name,
Permissions: Permission(raw.Permissions),
Ranking: raw.Ranking,
}
}

return found, nil
}
Loading

0 comments on commit 59adfc9

Please sign in to comment.