dictyBase/modware-user

View on GitHub
server/permission.go

Summary

Maintainability
D
1 day
Test Coverage
package server

import (
    "context"
    "fmt"

    "github.com/dictyBase/apihelpers/aphgrpc"
    "github.com/dictyBase/go-genproto/dictybaseapis/api/jsonapi"
    "github.com/dictyBase/go-genproto/dictybaseapis/user"
    "github.com/golang/protobuf/ptypes"
    "github.com/golang/protobuf/ptypes/any"
    "github.com/golang/protobuf/ptypes/empty"
    "google.golang.org/grpc"
    "google.golang.org/grpc/codes"
    "google.golang.org/grpc/metadata"
    "google.golang.org/grpc/status"
    dat "gopkg.in/mgutz/dat.v2/dat"
    runner "gopkg.in/mgutz/dat.v2/sqlx-runner"
)

const (
    permDbTable = "auth_permission"
    permDbAlias = "auth_permission perm"
)

var permissionCols = []string{
    "permission",
    "description",
    "created_at",
    "updated_at",
    "resource",
}

type dbPermission struct {
    AuthPermissionId dat.NullInt64  `db:"auth_permission_id"`
    Permission       string         `db:"permission"`
    Resource         string         `db:"resource"`
    Description      dat.NullString `db:"description"`
    CreatedAt        dat.NullTime   `db:"created_at"`
    UpdatedAt        dat.NullTime   `db:"updated_at"`
}

type PermissionService struct {
    *aphgrpc.Service
}

func permissionServiceOptions() *aphgrpc.ServiceOptions {
    return &aphgrpc.ServiceOptions{
        Resource:   "permissions",
        PathPrefix: "permissions",
        FilToColumns: map[string]string{
            "permission":  fmt.Sprintf("%s.permission", permDbTable),
            "resource":    fmt.Sprintf("%s.resource", permDbTable),
            "description": fmt.Sprintf("%s.description", permDbTable),
        },
        FieldsToColumns: map[string]string{
            "permission":  fmt.Sprintf("%s.permission", permDbTable),
            "resource":    fmt.Sprintf("%s.resource", permDbTable),
            "description": fmt.Sprintf("%s.description", permDbTable),
            "created_at":  fmt.Sprintf("%s.created_at", permDbTable),
            "updated_at":  fmt.Sprintf("%s.updated_at", permDbTable),
        },
        ReqAttrs: []string{"Permission", "Resource"},
    }
}

func NewPermissionService(dbh *runner.DB, opt ...aphgrpc.Option) *PermissionService {
    so := permissionServiceOptions()
    for _, optfn := range opt {
        optfn(so)
    }
    srv := &aphgrpc.Service{Dbh: dbh}
    aphgrpc.AssignFieldsToStructs(so, srv)
    return &PermissionService{srv}
}

func (s *PermissionService) GetPermission(ctx context.Context, r *jsonapi.GetRequestWithFields) (*user.Permission, error) {
    getReq := &jsonapi.GetRequest{
        Id:     r.Id,
        Fields: r.Fields,
    }
    params, md, err := aphgrpc.ValidateAndParseGetParams(s, getReq)
    if err != nil {
        grpc.SetTrailer(ctx, md)
        return &user.Permission{}, status.Error(codes.InvalidArgument, err.Error())
    }
    gctx := aphgrpc.GetReqCtx(params, getReq)
    switch {
    case params.HasFields:
        perm, err := s.getResourceWithSelectedAttr(gctx, r.Id)
        if err != nil {
            return &user.Permission{}, aphgrpc.HandleError(ctx, err)
        }
        return perm, nil
    default:
        perm, err := s.getResource(gctx, r.Id)
        if err != nil {
            return &user.Permission{}, aphgrpc.HandleError(ctx, err)
        }
        return perm, nil
    }
}

func (s *PermissionService) ListPermissions(ctx context.Context, r *jsonapi.SimpleListRequest) (*user.PermissionCollection, error) {
    params, md, err := aphgrpc.ValidateAndParseSimpleListParams(s, r)
    if err != nil {
        grpc.SetTrailer(ctx, md)
        return &user.PermissionCollection{}, status.Error(codes.InvalidArgument, err.Error())
    }
    lctx := aphgrpc.ListReqCtx(
        params,
        &jsonapi.ListRequest{
            Fields:  r.Fields,
            Filter:  r.Filter,
            Include: r.Include,
        })
    // request without any pagination query parameters
    switch {
    case params.HasFields && params.HasFilter:
        dbrows, err := s.getAllSelectedFilteredRows(lctx)
        if err != nil {
            return &user.PermissionCollection{}, aphgrpc.HandleError(ctx, err)
        }
        return s.dbToCollResource(lctx, dbrows), nil
    case params.HasFields:
        dbrows, err := s.getAllSelectedRows(lctx)
        if err != nil {
            return &user.PermissionCollection{}, aphgrpc.HandleError(ctx, err)
        }
        return s.dbToCollResource(lctx, dbrows), nil
    case params.HasFilter:
        dbrows, err := s.getAllFilteredRows(lctx)
        if err != nil {
            return &user.PermissionCollection{}, aphgrpc.HandleError(ctx, err)
        }
        return s.dbToCollResource(lctx, dbrows), nil
    default:
        dbrows, err := s.getAllRows(lctx)
        if err != nil {
            return &user.PermissionCollection{}, aphgrpc.HandleError(ctx, err)
        }
        return s.dbToCollResource(lctx, dbrows), nil
    }
}

func (s *PermissionService) CreatePermission(ctx context.Context, r *user.CreatePermissionRequest) (*user.Permission, error) {
    dbperm := s.attrTodbPermission(r.Data.Attributes)
    pcolumns := aphgrpc.GetDefinedTags(dbperm, "db")
    allcolumns := append(permissionCols, "auth_permission_id")
    newdbPerm := &dbPermission{}
    if len(pcolumns) > 0 {
        err := s.Dbh.InsertInto(permDbTable).
            Columns(pcolumns...).
            Record(dbperm).
            Returning(allcolumns...).
            QueryStruct(newdbPerm)
        if err != nil {
            grpc.SetTrailer(ctx, aphgrpc.ErrDatabaseInsert)
            return &user.Permission{}, status.Error(codes.Internal, err.Error())
        }
    }
    grpc.SetTrailer(ctx, metadata.Pairs("method", "POST"))
    return s.buildResource(
        context.TODO(),
        aphgrpc.NullToInt64(newdbPerm.AuthPermissionId),
        s.dbToResourceAttributes(newdbPerm),
    ), nil
}

func (s *PermissionService) UpdatePermission(ctx context.Context, r *user.UpdatePermissionRequest) (*user.Permission, error) {
    result, err := s.existsResource(r.Id)
    if err != nil {
        return &user.Permission{}, aphgrpc.HandleError(ctx, err)
    }
    if !result {
        grpc.SetTrailer(ctx, aphgrpc.ErrNotFound)
        return &user.Permission{}, status.Error(codes.NotFound, fmt.Sprintf("id %d not found", r.Id))
    }
    dbperm := s.attrTodbPermission(r.Data.Attributes)
    permMap := aphgrpc.GetDefinedTagsWithValue(dbperm, "db")
    if len(permMap) > 0 {
        _, err := s.Dbh.Update("auth_permission").SetMap(permMap).
            Where("auth_permission_id = $1", r.Data.Id).Exec()
        if err != nil {
            grpc.SetTrailer(ctx, aphgrpc.ErrDatabaseUpdate)
            return &user.Permission{}, status.Error(codes.Internal, err.Error())
        }
    }
    return s.buildResource(context.TODO(), r.Data.Id, r.Data.Attributes), nil
}

func (s *PermissionService) DeletePermission(ctx context.Context, r *jsonapi.DeleteRequest) (*empty.Empty, error) {
    result, err := s.existsResource(r.Id)
    if err != nil {
        return &empty.Empty{}, aphgrpc.HandleError(ctx, err)
    }
    if !result {
        grpc.SetTrailer(ctx, aphgrpc.ErrNotFound)
        return &empty.Empty{}, status.Error(codes.NotFound, fmt.Sprintf("id %d not found", r.Id))
    }
    _, err = s.Dbh.DeleteFrom("auth_permission").Where("auth_permission_id = $1", r.Id).Exec()
    if err != nil {
        grpc.SetTrailer(ctx, aphgrpc.ErrDatabaseDelete)
        return &empty.Empty{}, status.Error(codes.Internal, err.Error())
    }
    return &empty.Empty{}, nil
}

// All helper functions

func (s *PermissionService) existsResource(id int64) (bool, error) {
    r, err := s.Dbh.Select("auth_permission_id").From("auth_permission").
        Where("auth_permission_id = $1", id).Exec()
    if err != nil {
        return false, err
    }
    if r.RowsAffected != 1 {
        return false, nil
    }
    return true, nil
}

func (s *PermissionService) getResourceWithSelectedAttr(ctx context.Context, id int64) (*user.Permission, error) {
    dperm := &dbPermission{}
    params, ok := ctx.Value(aphgrpc.ContextKeyParams).(*aphgrpc.JSONAPIParams)
    if !ok {
        return &user.Permission{}, fmt.Errorf("no params object found in context")
    }
    columns := s.MapFieldsToColumns(params.Fields)
    err := s.Dbh.Select(columns...).
        From(permDbTable).
        Where("auth_permission_id = $1", id).QueryStruct(dperm)
    if err != nil {
        return &user.Permission{}, err
    }
    return s.buildResource(ctx, id, s.dbToResourceAttributes(dperm)), nil
}

func (s *PermissionService) getResource(ctx context.Context, id int64) (*user.Permission, error) {
    dperm := &dbPermission{}
    err := s.Dbh.Select(fmt.Sprintf("%s.*", permDbTable)).From(permDbTable).
        Where("auth_permission_id = $1", id).QueryStruct(dperm)
    if err != nil {
        return &user.Permission{}, err
    }
    return s.buildResource(ctx, id, s.dbToResourceAttributes(dperm)), nil
}

func (s *PermissionService) getAllRows(ctx context.Context) ([]*dbPermission, error) {
    var dbrows []*dbPermission
    err := s.Dbh.Select(fmt.Sprintf("%s.*", permDbTable)).
        From(permDbTable).
        QueryStructs(&dbrows)
    return dbrows, err
}

func (s *PermissionService) getAllSelectedRows(ctx context.Context) ([]*dbPermission, error) {
    var dbrows []*dbPermission
    params, ok := ctx.Value(aphgrpc.ContextKeyParams).(*aphgrpc.JSONAPIParams)
    if !ok {
        return dbrows, fmt.Errorf("no params object found in context")
    }
    columns := s.MapFieldsToColumns(params.Fields)
    err := s.Dbh.Select(columns...).
        From(permDbTable).
        QueryStructs(&dbrows)
    return dbrows, err
}

func (s *PermissionService) getAllFilteredRows(ctx context.Context) ([]*dbPermission, error) {
    var dbrows []*dbPermission
    params, ok := ctx.Value(aphgrpc.ContextKeyParams).(*aphgrpc.JSONAPIParams)
    if !ok {
        return dbrows, fmt.Errorf("no params object found in context")
    }
    err := s.Dbh.Select(fmt.Sprintf("%s.*", permDbTable)).
        From(permDbTable).
        Scope(
            aphgrpc.FilterToWhereClause(s, params.Filters),
            aphgrpc.FilterToBindValue(params.Filters)...,
        ).
        QueryStructs(&dbrows)
    return dbrows, err
}

func (s *PermissionService) getAllSelectedFilteredRows(ctx context.Context) ([]*dbPermission, error) {
    var dbrows []*dbPermission
    params, ok := ctx.Value(aphgrpc.ContextKeyParams).(*aphgrpc.JSONAPIParams)
    if !ok {
        return dbrows, fmt.Errorf("no params object found in context")
    }
    columns := s.MapFieldsToColumns(params.Fields)
    err := s.Dbh.Select(columns...).
        From(permDbTable).
        Scope(
            aphgrpc.FilterToWhereClause(s, params.Filters),
            aphgrpc.FilterToBindValue(params.Filters)...,
        ).
        QueryStructs(&dbrows)
    return dbrows, err
}

func (s *PermissionService) buildResourceData(ctx context.Context, id int64, attr *user.PermissionAttributes) *user.PermissionData {
    return &user.PermissionData{
        Type:       s.GetResourceName(),
        Id:         id,
        Attributes: attr,
        Links: &jsonapi.Links{
            Self: s.GenResourceSelfLink(ctx, id),
        },
    }
}

func (s *PermissionService) buildResource(ctx context.Context, id int64, attr *user.PermissionAttributes) *user.Permission {
    return &user.Permission{
        Data: s.buildResourceData(ctx, id, attr),
        Links: &jsonapi.Links{
            Self: s.GenResourceSelfLink(ctx, id),
        },
    }
}

func (s *PermissionService) dbToResourceAttributes(dperm *dbPermission) *user.PermissionAttributes {
    return &user.PermissionAttributes{
        Permission:  dperm.Permission,
        Resource:    dperm.Resource,
        Description: aphgrpc.NullToString(dperm.Description),
        CreatedAt:   aphgrpc.NullToTime(dperm.CreatedAt),
        UpdatedAt:   aphgrpc.NullToTime(dperm.UpdatedAt),
    }
}

func (s *PermissionService) attrTodbPermission(attr *user.PermissionAttributes) *dbPermission {
    return &dbPermission{
        Permission:  attr.Permission,
        Resource:    attr.Resource,
        Description: dat.NullStringFrom(attr.Description),
        CreatedAt:   dat.NullTimeFrom(aphgrpc.ProtoTimeStamp(attr.CreatedAt)),
        UpdatedAt:   dat.NullTimeFrom(aphgrpc.ProtoTimeStamp(attr.UpdatedAt)),
    }
}

func (s *PermissionService) dbToCollResourceData(ctx context.Context, dbrows []*dbPermission) []*user.PermissionData {
    var pdata []*user.PermissionData
    for _, dperm := range dbrows {
        pdata = append(
            pdata,
            s.buildResourceData(
                ctx,
                aphgrpc.NullToInt64(dperm.AuthPermissionId),
                s.dbToResourceAttributes(dperm),
            ))
    }
    return pdata
}

func (s *PermissionService) dbToCollResource(ctx context.Context, dbrows []*dbPermission) *user.PermissionCollection {
    return &user.PermissionCollection{
        Data: s.dbToCollResourceData(ctx, dbrows),
        Links: &jsonapi.Links{
            Self: s.GenCollResourceSelfLink(ctx),
        },
    }
}

func (s *PermissionService) convertAllToAny(perms []*user.PermissionData) ([]*any.Any, error) {
    aslice := make([]*any.Any, len(perms))
    for i, p := range perms {
        pkg, err := ptypes.MarshalAny(p)
        if err != nil {
            return aslice, err
        }
        aslice[i] = pkg
    }
    return aslice, nil
}