Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: add fields createdByMe and iamInvolved of Network API #33

Merged
merged 1 commit into from
Feb 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 68 additions & 2 deletions src/channel/channel.resolver.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
import { Args, Mutation, Resolver } from '@nestjs/graphql';
import {
Args,
Mutation,
Parent,
ResolveField,
Resolver,
} from '@nestjs/graphql';
import DataLoader from 'dataloader';
import { Loader } from 'src/common/dataloader';
import { Auth } from 'src/common/decorators/auth.decorator';
import { Organization } from 'src/organization/models/organization.model';
import { OrganizationLoader } from 'src/organization/organization.loader';
import { JwtAuth } from 'src/types';
import { ChannelService } from './channel.service';
import { NewChannel } from './dto/new-channel.input';
import { UpdateChannel } from './dto/update-channel.input';
import { Channel } from './models/channel.model';

@Resolver()
@Resolver(() => Channel)
export class ChannelResolver {
constructor(private readonly channelService: ChannelService) {}

Expand All @@ -27,4 +37,60 @@ export class ChannelResolver {
): Promise<Channel> {
return this.channelService.updateChannel(auth, name, channel);
}

@ResolveField(() => Boolean, {
description: '是否为我创建的',
})
async createdByMe(
@Auth() auth: JwtAuth,
@Parent() channel: Channel,
@Loader(OrganizationLoader)
orgLoader: DataLoader<Organization['name'], Organization>,
): Promise<boolean> {
const { preferred_username } = auth;
const { members } = channel;
if (!members) return;
const orgs = await orgLoader.loadMany(members.map((m) => m.name));
const orgMap = new Map(
(orgs as Organization[]).map((org) => [org.name, org]),
);
let iCreated = false;
members.forEach((m) => {
if (orgMap.has(m.name)) {
const v = orgMap.get(m.name);
if (m.initiator && v.admin === preferred_username) {
iCreated = true;
}
}
});
return iCreated;
}

@ResolveField(() => Boolean, {
description: '是否为我参与的',
})
async iamInvolved(
@Auth() auth: JwtAuth,
@Parent() channel: Channel,
@Loader(OrganizationLoader)
orgLoader: DataLoader<Organization['name'], Organization>,
): Promise<boolean> {
const { preferred_username } = auth;
const { members } = channel;
if (!members) return;
const orgs = await orgLoader.loadMany(members.map((m) => m.name));
const orgMap = new Map(
(orgs as Organization[]).map((org) => [org.name, org]),
);
let involved = false;
members.forEach((m) => {
if (orgMap.has(m.name)) {
const v = orgMap.get(m.name);
if (v.clients?.includes(preferred_username)) {
involved = true;
}
}
});
return involved;
}
}
2 changes: 1 addition & 1 deletion src/channel/channel.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export class ChannelService {
channel;
const members = (organizations || [])
.concat(initiator)
.map((d) => ({ name: d }));
.map((d) => ({ name: d, initiator: d === initiator }));
const k8s = await this.k8sService.getClient(auth);
const { body } = await k8s.channel.create({
metadata: {
Expand Down
6 changes: 6 additions & 0 deletions src/channel/models/channel.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,10 @@ export class Channel {
/** 状态 */
@Field(() => ChannelStatus, { description: '状态' })
status?: string;

/** 我创建的 */
createdByMe?: boolean;

/** 我参与的 */
iamInvolved?: boolean;
}
12 changes: 12 additions & 0 deletions src/ibppeer/ibppeer.resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,16 @@ export class IbppeerResolver {
?.filter((net) => find(net.channelNames, (o) => joinedChans.includes(o)))
?.map((net) => net.name);
}

@ResolveField(() => Boolean, {
description: '是否为我创建的',
})
async createdByMe(
@Auth() auth: JwtAuth,
@Parent() ibppeer: Ibppeer,
): Promise<boolean> {
const { preferred_username } = auth;
const { enrolluser } = ibppeer;
return enrolluser === preferred_username;
}
}
7 changes: 7 additions & 0 deletions src/ibppeer/ibppeer.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export class IbppeerService {
limits: ibppeer.spec?.resources?.peer?.limits,
status: ibppeer.status?.type,
namespace: ibppeer.metadata?.namespace,
enrolluser: ibppeer.spec?.secret?.enrollment?.component?.enrolluser,
};
}

Expand All @@ -45,6 +46,12 @@ export class IbppeerService {
return body.items.map((item) => this.format(item));
}

async getIbppeer(auth: JwtAuth, org: string, name: string): Promise<Ibppeer> {
const k8s = await this.k8sService.getClient(auth);
const { body } = await k8s.ibppeer.read(name, org);
return this.format(body);
}

async createIbppeer(auth: JwtAuth, org: string): Promise<Ibppeer> {
const { token, preferred_username } = auth;
const { binaryData } = await this.cmService.getConfigmap(
Expand Down
6 changes: 6 additions & 0 deletions src/ibppeer/models/ibppeer.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,10 @@ export class Ibppeer {
/** 运行状态 */
@Field(() => IbppeerStatus, { description: '运行状态' })
status?: string;

@HideField()
enrolluser?: string;

/** 我创建的 */
createdByMe?: boolean;
}
9 changes: 9 additions & 0 deletions src/network/models/network.model.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { Field, HideField, ID, ObjectType } from '@nestjs/graphql';
import { Channel } from 'src/channel/models/channel.model';
import { SpecResource } from 'src/common/models/spec-resource.model';
import { Ibppeer } from 'src/ibppeer/models/ibppeer.model';
import { Organization } from 'src/organization/models/organization.model';
import { StatusType } from 'src/organization/models/status-type.enum';
import { AnyObj } from 'src/types';
import { OrderVersion } from '../dto/order-version.enum';

@ObjectType({ description: '网络' })
export class Network {
Expand Down Expand Up @@ -61,6 +63,13 @@ export class Network {

/** 节点存储 */
storage?: string;

/** 节点版本 */
@Field(() => OrderVersion, { description: '节点版本' })
version?: string;

/** 网络中的所有节点 */
peers?: Ibppeer[];
}

@ObjectType({ description: '成员' })
Expand Down
20 changes: 20 additions & 0 deletions src/network/network.gql
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ query getNetworks{
status
channels {
name
createdByMe
iamInvolved
}
peers {
name
createdByMe
}
}
}
Expand All @@ -42,13 +48,25 @@ query getNetwork($name: String!) {
}
organizations {
name
displayName
admin
creationTimestamp
lastHeartbeatTime
status
reason
ibppeers {
name
}
}
initiator {
name
admin
}
status
peers {
name
createdByMe
}
channels {
name
members{
Expand All @@ -60,6 +78,8 @@ query getNetwork($name: String!) {
}
creationTimestamp
status
createdByMe
iamInvolved
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/network/network.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import { ProposalModule } from 'src/proposal/proposal.module';
import { NetworkLoader } from './network.loader';
import { FederationModule } from 'src/federation/federation.module';
import { ChannelModule } from 'src/channel/channel.module';
import { IbppeerModule } from 'src/ibppeer/ibppeer.module';

@Module({
providers: [NetworkService, NetworkResolver, NetworkLoader],
exports: [NetworkLoader],
imports: [ProposalModule, FederationModule, ChannelModule], // TODO: 使用ChannelLoader后,去掉ChannelModule
imports: [ProposalModule, FederationModule, ChannelModule, IbppeerModule], // TODO: 使用ChannelLoader后,去掉ChannelModule, IbppeerModule
})
export class NetworkModule {}
31 changes: 31 additions & 0 deletions src/network/network.resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@ import {
Resolver,
} from '@nestjs/graphql';
import DataLoader from 'dataloader';
import { isEqual, uniqWith } from 'lodash';
// import { ChannelLoader } from 'src/channel/channel.loader';
import { ChannelService } from 'src/channel/channel.service';
import { Channel } from 'src/channel/models/channel.model';
import { Loader } from 'src/common/dataloader';
import { Auth } from 'src/common/decorators/auth.decorator';
import { NETWORK_VERSION_RESOURCES } from 'src/common/utils';
import { IbppeerService } from 'src/ibppeer/ibppeer.service';
import { Ibppeer } from 'src/ibppeer/models/ibppeer.model';
import { Organization } from 'src/organization/models/organization.model';
import { OrganizationLoader } from 'src/organization/organization.loader';
import { JwtAuth } from 'src/types';
Expand All @@ -26,6 +29,7 @@ export class NetworkResolver {
constructor(
private readonly networkService: NetworkService,
private readonly channelService: ChannelService,
private readonly peerService: IbppeerService,
) {}

@Query(() => [Network], { description: '网络列表' })
Expand Down Expand Up @@ -124,4 +128,31 @@ export class NetworkResolver {
// const cs = await channelLoader.loadMany(channelNames);
// return cs;
}

@ResolveField(() => [Ibppeer], {
nullable: true,
description: '网络中的所有节点',
})
async peers(
@Auth() auth: JwtAuth,
@Parent() network: Network,
): Promise<Ibppeer[]> {
const { channelNames } = network;
if (!channelNames || channelNames.length === 0) return;
// TODO: channelLoader
const channels = await this.channelService.getChannelsByNames(
auth,
channelNames,
);
const peerses = channels?.map((channel) => channel.peers);
const peers = uniqWith(peerses.flat(), isEqual);
// TODO: IbppeerLoader, 以namespace/name为key
return Promise.all(
peers?.map((peer) =>
this.peerService
.getIbppeer(auth, peer.namespace, peer.name)
.catch(() => peer),
),
);
}
}
2 changes: 1 addition & 1 deletion src/organization/models/organization.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export class Organization {
@Field(() => StatusType)
status?: string;

/** 原因(状态为非Deplyed时) */
/** 原因 */
reason?: string;

/** 加入时间(只在联盟中使用) */
Expand Down
16 changes: 14 additions & 2 deletions src/schema.gql
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,15 @@
# ------------------------------------------------------

type Channel {
"""我创建的"""
createdByMe: Boolean

"""合约数量"""
creationTimestamp: String

"""我参与的"""
iamInvolved: Boolean

"""组织数量"""
members: [SpecMember!]

Expand Down Expand Up @@ -91,6 +97,9 @@ type Ibppeer {
"""加入的通道"""
channels: [String!]

"""我创建的"""
createdByMe: Boolean

"""创建时间"""
creationTimestamp: String!

Expand Down Expand Up @@ -250,13 +259,16 @@ type Network {
"""网络中组织"""
organizations: [Organization!]

"""网络中的所有节点"""
peers: [Ibppeer!]

"""状态"""
status: StatusType

"""节点存储"""
storage: String

"""配置版本"""
"""节点版本"""
version: OrderVersion
}

Expand Down Expand Up @@ -393,7 +405,7 @@ type Organization {
"""所在网络"""
networks: [Network!]

"""原因(状态为非Deplyed时)"""
"""原因"""
reason: String

"""状态"""
Expand Down