list members of organization (#537)

This commit is contained in:
Michael Quigley 2024-12-09 16:42:30 -05:00
parent 52333ddb69
commit 917a4d3f22
No known key found for this signature in database
GPG Key ID: 9B60314A9DD20A62
15 changed files with 283 additions and 12 deletions

View File

@ -0,0 +1,61 @@
package main
import (
"fmt"
"github.com/jedib0t/go-pretty/v6/table"
"github.com/openziti/zrok/environment"
"github.com/openziti/zrok/rest_client_zrok/admin"
"github.com/spf13/cobra"
"os"
)
func init() {
adminListCmd.AddCommand(newAdminListOrgMembersCommand().cmd)
}
type adminListOrgMembersCommand struct {
cmd *cobra.Command
}
func newAdminListOrgMembersCommand() *adminListOrgMembersCommand {
cmd := &cobra.Command{
Use: "org-members <organizationToken>",
Aliases: []string{"members"},
Short: "List the members of the specified organization",
Args: cobra.ExactArgs(1),
}
command := &adminListOrgMembersCommand{cmd: cmd}
cmd.Run = command.run
return command
}
func (cmd *adminListOrgMembersCommand) run(_ *cobra.Command, args []string) {
env, err := environment.LoadRoot()
if err != nil {
panic(err)
}
zrok, err := env.Client()
if err != nil {
panic(err)
}
req := admin.NewListOrganizationMembersParams()
req.Body.Token = args[0]
resp, err := zrok.Admin.ListOrganizationMembers(req, mustGetAdminAuth())
if err != nil {
panic(err)
}
fmt.Println()
t := table.NewWriter()
t.SetOutputMirror(os.Stdout)
t.SetStyle(table.StyleColoredDark)
t.AppendHeader(table.Row{"Account Email", "Admin?"})
for _, member := range resp.Payload.Members {
t.AppendRow(table.Row{member.Email, member.Admin})
}
t.Render()
fmt.Println()
}

View File

@ -29,22 +29,22 @@ func (h *listOrganizationMembersHandler) Handle(params admin.ListOrganizationMem
org, err := str.FindOrganizationByToken(params.Body.Token, trx)
if err != nil {
logrus.Errorf("error finding organization by token: %v", err)
return admin.NewListOrganizationMembersInternalServerError()
return admin.NewListOrganizationMembersNotFound()
}
if org == nil {
logrus.Errorf("organization '%v' not found", params.Body.Token)
return admin.NewListOrganizationMembersNotFound()
}
emails, err := str.FindAccountsForOrganization(org.Id, trx)
oms, err := str.FindAccountsForOrganization(org.Id, trx)
if err != nil {
logrus.Errorf("error finding accounts for organization: %v", err)
return admin.NewListOrganizationMembersInternalServerError()
}
var members []*admin.ListOrganizationMembersOKBodyMembersItems0
for _, email := range emails {
members = append(members, &admin.ListOrganizationMembersOKBodyMembersItems0{Email: email})
for _, om := range oms {
members = append(members, &admin.ListOrganizationMembersOKBodyMembersItems0{Email: om.Email, Admin: om.Admin})
}
return admin.NewListOrganizationMembersOK().WithPayload(&admin.ListOrganizationMembersOKBody{Members: members})
}

View File

@ -17,8 +17,25 @@ func (str *Store) AddAccountToOrganization(acctId, orgId int, admin bool, trx *s
return nil
}
func (str *Store) FindAccountsForOrganization(orgId int, trx *sqlx.Tx) ([]string, error) {
return nil, nil
type OrganizationMember struct {
Email string
Admin bool
}
func (str *Store) FindAccountsForOrganization(orgId int, trx *sqlx.Tx) ([]*OrganizationMember, error) {
rows, err := trx.Queryx("select organization_members.admin, accounts.email from organization_members, accounts where organization_members.organization_id = $1 and organization_members.account_id = accounts.id", orgId)
if err != nil {
return nil, errors.Wrap(err, "error querying organization members")
}
var members []*OrganizationMember
for rows.Next() {
om := &OrganizationMember{}
if err := rows.StructScan(&om); err != nil {
return nil, errors.Wrap(err, "error scanning account email")
}
members = append(members, om)
}
return members, nil
}
func (str *Store) IsAccountInOrganization(acctId, orgId int, trx *sqlx.Tx) (bool, error) {

View File

@ -441,6 +441,9 @@ swagger:model ListOrganizationMembersOKBodyMembersItems0
*/
type ListOrganizationMembersOKBodyMembersItems0 struct {
// admin
Admin bool `json:"admin,omitempty"`
// email
Email string `json:"email,omitempty"`
}

View File

@ -992,6 +992,9 @@ func init() {
"type": "array",
"items": {
"properties": {
"admin": {
"type": "boolean"
},
"email": {
"type": "string"
}
@ -3512,6 +3515,9 @@ func init() {
"definitions": {
"MembersItems0": {
"properties": {
"admin": {
"type": "boolean"
},
"email": {
"type": "string"
}

View File

@ -223,6 +223,9 @@ func (o *ListOrganizationMembersOKBody) UnmarshalBinary(b []byte) error {
// swagger:model ListOrganizationMembersOKBodyMembersItems0
type ListOrganizationMembersOKBodyMembersItems0 struct {
// admin
Admin bool `json:"admin,omitempty"`
// email
Email string `json:"email,omitempty"`
}

View File

@ -29,6 +29,7 @@ model/grantsRequest.ts
model/inviteRequest.ts
model/inviteTokenGenerateRequest.ts
model/listOrganizationMembers200Response.ts
model/listOrganizationMembers200ResponseMembersInner.ts
model/loginRequest.ts
model/metrics.ts
model/metricsSample.ts

View File

@ -11,10 +11,10 @@
*/
import { RequestFile } from './models';
import { GrantsRequest } from './grantsRequest';
import { ListOrganizationMembers200ResponseMembersInner } from './listOrganizationMembers200ResponseMembersInner';
export class ListOrganizationMembers200Response {
'members'?: Array<GrantsRequest>;
'members'?: Array<ListOrganizationMembers200ResponseMembersInner>;
static discriminator: string | undefined = undefined;
@ -22,7 +22,7 @@ export class ListOrganizationMembers200Response {
{
"name": "members",
"baseName": "members",
"type": "Array<GrantsRequest>"
"type": "Array<ListOrganizationMembers200ResponseMembersInner>"
} ];
static getAttributeTypeMap() {

View File

@ -0,0 +1,37 @@
/**
* zrok
* zrok client access
*
* The version of the OpenAPI document: 0.3.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { RequestFile } from './models';
export class ListOrganizationMembers200ResponseMembersInner {
'email'?: string;
'admin'?: boolean;
static discriminator: string | undefined = undefined;
static attributeTypeMap: Array<{name: string, baseName: string, type: string}> = [
{
"name": "email",
"baseName": "email",
"type": "string"
},
{
"name": "admin",
"baseName": "admin",
"type": "boolean"
} ];
static getAttributeTypeMap() {
return ListOrganizationMembers200ResponseMembersInner.attributeTypeMap;
}
}

View File

@ -23,6 +23,7 @@ export * from './grantsRequest';
export * from './inviteRequest';
export * from './inviteTokenGenerateRequest';
export * from './listOrganizationMembers200Response';
export * from './listOrganizationMembers200ResponseMembersInner';
export * from './loginRequest';
export * from './metrics';
export * from './metricsSample';
@ -83,6 +84,7 @@ import { GrantsRequest } from './grantsRequest';
import { InviteRequest } from './inviteRequest';
import { InviteTokenGenerateRequest } from './inviteTokenGenerateRequest';
import { ListOrganizationMembers200Response } from './listOrganizationMembers200Response';
import { ListOrganizationMembers200ResponseMembersInner } from './listOrganizationMembers200ResponseMembersInner';
import { LoginRequest } from './loginRequest';
import { Metrics } from './metrics';
import { MetricsSample } from './metricsSample';
@ -151,6 +153,7 @@ let typeMap: {[index: string]: any} = {
"InviteRequest": InviteRequest,
"InviteTokenGenerateRequest": InviteTokenGenerateRequest,
"ListOrganizationMembers200Response": ListOrganizationMembers200Response,
"ListOrganizationMembers200ResponseMembersInner": ListOrganizationMembers200ResponseMembersInner,
"LoginRequest": LoginRequest,
"Metrics": Metrics,
"MetricsSample": MetricsSample,

View File

@ -46,6 +46,7 @@ from zrok_api.models.grants_body import GrantsBody
from zrok_api.models.identity_body import IdentityBody
from zrok_api.models.inline_response200 import InlineResponse200
from zrok_api.models.inline_response2001 import InlineResponse2001
from zrok_api.models.inline_response2001_members import InlineResponse2001Members
from zrok_api.models.inline_response201 import InlineResponse201
from zrok_api.models.invite_request import InviteRequest
from zrok_api.models.invite_token_generate_request import InviteTokenGenerateRequest

View File

@ -36,6 +36,7 @@ from zrok_api.models.grants_body import GrantsBody
from zrok_api.models.identity_body import IdentityBody
from zrok_api.models.inline_response200 import InlineResponse200
from zrok_api.models.inline_response2001 import InlineResponse2001
from zrok_api.models.inline_response2001_members import InlineResponse2001Members
from zrok_api.models.inline_response201 import InlineResponse201
from zrok_api.models.invite_request import InviteRequest
from zrok_api.models.invite_token_generate_request import InviteTokenGenerateRequest

View File

@ -28,7 +28,7 @@ class InlineResponse2001(object):
and the value is json key in definition.
"""
swagger_types = {
'members': 'list[GrantsBody]'
'members': 'list[InlineResponse2001Members]'
}
attribute_map = {
@ -48,7 +48,7 @@ class InlineResponse2001(object):
:return: The members of this InlineResponse2001. # noqa: E501
:rtype: list[GrantsBody]
:rtype: list[InlineResponse2001Members]
"""
return self._members
@ -58,7 +58,7 @@ class InlineResponse2001(object):
:param members: The members of this InlineResponse2001. # noqa: E501
:type: list[GrantsBody]
:type: list[InlineResponse2001Members]
"""
self._members = members

View File

@ -0,0 +1,136 @@
# coding: utf-8
"""
zrok
zrok client access # noqa: E501
OpenAPI spec version: 0.3.0
Generated by: https://github.com/swagger-api/swagger-codegen.git
"""
import pprint
import re # noqa: F401
import six
class InlineResponse2001Members(object):
"""NOTE: This class is auto generated by the swagger code generator program.
Do not edit the class manually.
"""
"""
Attributes:
swagger_types (dict): The key is attribute name
and the value is attribute type.
attribute_map (dict): The key is attribute name
and the value is json key in definition.
"""
swagger_types = {
'email': 'str',
'admin': 'bool'
}
attribute_map = {
'email': 'email',
'admin': 'admin'
}
def __init__(self, email=None, admin=None): # noqa: E501
"""InlineResponse2001Members - a model defined in Swagger""" # noqa: E501
self._email = None
self._admin = None
self.discriminator = None
if email is not None:
self.email = email
if admin is not None:
self.admin = admin
@property
def email(self):
"""Gets the email of this InlineResponse2001Members. # noqa: E501
:return: The email of this InlineResponse2001Members. # noqa: E501
:rtype: str
"""
return self._email
@email.setter
def email(self, email):
"""Sets the email of this InlineResponse2001Members.
:param email: The email of this InlineResponse2001Members. # noqa: E501
:type: str
"""
self._email = email
@property
def admin(self):
"""Gets the admin of this InlineResponse2001Members. # noqa: E501
:return: The admin of this InlineResponse2001Members. # noqa: E501
:rtype: bool
"""
return self._admin
@admin.setter
def admin(self, admin):
"""Sets the admin of this InlineResponse2001Members.
:param admin: The admin of this InlineResponse2001Members. # noqa: E501
:type: bool
"""
self._admin = admin
def to_dict(self):
"""Returns the model properties as a dict"""
result = {}
for attr, _ in six.iteritems(self.swagger_types):
value = getattr(self, attr)
if isinstance(value, list):
result[attr] = list(map(
lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
value
))
elif hasattr(value, "to_dict"):
result[attr] = value.to_dict()
elif isinstance(value, dict):
result[attr] = dict(map(
lambda item: (item[0], item[1].to_dict())
if hasattr(item[1], "to_dict") else item,
value.items()
))
else:
result[attr] = value
if issubclass(InlineResponse2001Members, dict):
for key, value in self.items():
result[key] = value
return result
def to_str(self):
"""Returns the string representation of the model"""
return pprint.pformat(self.to_dict())
def __repr__(self):
"""For `print` and `pprint`"""
return self.to_str()
def __eq__(self, other):
"""Returns true if both objects are equal"""
if not isinstance(other, InlineResponse2001Members):
return False
return self.__dict__ == other.__dict__
def __ne__(self, other):
"""Returns true if both objects are not equal"""
return not self == other

View File

@ -483,6 +483,8 @@ paths:
properties:
email:
type: string
admin:
type: boolean
401:
description: unauthorized
404: