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

metaprotocol labeling: mappings and protobufs #4987

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
12,851 changes: 6,536 additions & 6,315 deletions distributor-node/src/services/networking/query-node/schema.graphql

Large diffs are not rendered by default.

81 changes: 81 additions & 0 deletions metadata-protobuf/proto/WorkingGroups.proto
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,91 @@ message ModeratePost {
required string rationale = 2;
}

message CreateTag {
// Name of new Tag, e.g : roadmap
required string name = 1;

// Description of new Tag, e.g : Roadmap covering the Joystream ecosystem
required string description = 2;

// Type of new Tag : e.g : roadmap
required string type = 3;

// Visibility of new Tag : e.g : true
required bool visibility = 4;
}

message UpdateTag {
// ID of tag
required string tag_id = 1;

// name of tag
optional string name = 2;

// Updated Description of Tag
optional string description = 3;

// Updated Type of Tag
optional string type = 4;

// Updated Visibility of Tag
optional bool visibility = 5;
}

message AssignTagsToThread {
// ID of tag
repeated string tag_ids = 1;

// ID of thread
required string thread_id = 2;
}

message UnassignTagsFromThread {
// ID of tag
repeated string tag_ids = 1;

// ID of thread
required string thread_id = 2;
}

message AssignTagsToProposal {
// ID of tag
repeated string tag_ids = 1;

// ID of proposal
required string proposal_id = 2;
}

message UnassignTagsFromProposal {
// ID of tag
repeated string tag_ids = 1;

// ID of proposal
required string proposal_id = 2;
}

message AllowTagToWorker {
// ID of worker
required uint64 worker_id = 1;
}

message DisallowTagToWorker {
// ID of worker
required uint64 worker_id = 1;
}

message RemarkMetadataAction {
oneof action {
ModeratePost moderate_post = 1;
VerifyValidator verify_validator = 2;
CreateTag create_tag = 3;
UpdateTag update_tag = 4;
AssignTagsToThread assign_tags_to_thread = 5;
UnassignTagsFromThread unassign_tags_from_thread = 6;
AssignTagsToProposal assign_tags_to_proposal = 7;
UnassignTagsFromProposal unassign_tags_from_proposal = 8;
AllowTagToWorker allow_tag_to_worker = 9;
DisallowTagToWorker disallow_tag_to_worker = 10;
}
}

Expand Down
2 changes: 1 addition & 1 deletion query-node/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

- Refactor of mappings for more better handling of error cases. [#4856](https://github.com/Joystream/joystream/pull/4856)
- Bug fix [#4855](https://github.com/Joystream/joystream/issues/4855)
- Add support for UpdateGlobalNftLimit proposal.
- Add support for UpdateGlobalNftLimit proposal.

### 1.6.0

Expand Down
8 changes: 8 additions & 0 deletions query-node/mappings/src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -434,4 +434,12 @@ export enum MetaprotocolTxError {

// Channel errors
InvalidChannelRewardAccount = 'InvalidChannelRewardAccount',

// Tag errors
TagAlreadyExists = 'TagAlreadyExists',
TagIsNotLead = 'TagIsNotLead',
TagNotFound = 'TagNotFound',
TagPermNotAllowed = 'TagPermNotAllowed',
TagInvalidThreadId = 'TagInvalidThreadId',
TagInvalidProposalId = 'TagInvalidProposalId',
}
252 changes: 252 additions & 0 deletions query-node/mappings/src/label/tag.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
import _ from 'lodash'
import { DatabaseManager } from '@joystream/hydra-common'
import {
ICreateTag,
IUpdateTag,
IAssignTagsToThread,
IAssignTagsToProposal,
IUnassignTagsFromThread,
IUnassignTagsFromProposal,
IAllowTagToWorker,
IDisallowTagToWorker,
} from '@joystream/metadata-protobuf'
import { DecodedMetadataObject } from '@joystream/metadata-protobuf/types'
import { Tag, TagPermittedWorker, ForumThread, Proposal } from 'query-node/dist/model'
import { MetaprotocolTxError, getOneBy, getById, logger } from 'src/common'

export async function processCreateTag(
store: DatabaseManager,
metadata: DecodedMetadataObject<ICreateTag>,
isLead: boolean
): Promise<any> {
const { name, description, type, visibility } = metadata

if (isLead === false) {
return MetaprotocolTxError.TagPermNotAllowed
}

const isTagExists = await getOneBy(store, Tag, { name: name })
if (isTagExists) {
return MetaprotocolTxError.TagAlreadyExists
}

const newTag = new Tag({
name: name,
description: description,
type: type,
visibility: visibility,
})

await store.save<Tag>(newTag)
logger.info('Tag has been created', { name })

return newTag
}

export async function processUpdateTag(
store: DatabaseManager,
metadata: DecodedMetadataObject<IUpdateTag>,
isLead: boolean
): Promise<any> {
const { tagId, name, description, type, visibility } = metadata

if (isLead === false) {
return MetaprotocolTxError.TagPermNotAllowed
}

const tag: Tag | undefined = await getById(store, Tag, tagId)
if (!tag) {
return MetaprotocolTxError.TagNotFound
}

if (name) {
const isTagExists = await getOneBy(store, Tag, { name: name })
if (isTagExists) {
return MetaprotocolTxError.TagAlreadyExists
}

tag.name = name
}

if (description) {
tag.description = description
}

if (type) {
tag.type = type
}

if (visibility) {
tag.visibility = visibility
}

await store.save<Tag>(tag)

logger.info('Tag has been created', { name })
kdembler marked this conversation as resolved.
Show resolved Hide resolved
return tag
}

export async function processAssignTagsToThread(
store: DatabaseManager,
metadata: DecodedMetadataObject<IAssignTagsToThread>,
isLead: boolean,
workerId: number
): Promise<any> {
const { tagIds, threadId } = metadata

if (!isLead) {
const tagPermittedWorker: TagPermittedWorker | undefined = await getOneBy(store, TagPermittedWorker, {
workerId: workerId.toString(),
})
if (!tagPermittedWorker) {
return MetaprotocolTxError.TagPermNotAllowed
}
}

const forumThread: ForumThread | undefined = await getById(store, ForumThread, threadId)
if (!forumThread) {
return MetaprotocolTxError.TagInvalidThreadId
}

const currentTagIds = (forumThread.newTags || []).map((t) => t.id)
const tagIdsToSet = _.union(currentTagIds, tagIds)
if (tagIdsToSet) {
kdembler marked this conversation as resolved.
Show resolved Hide resolved
const tags = await Promise.all(tagIdsToSet.map(async (tagId: string) => await getById(store, Tag, tagId)))
forumThread.newTags = tags.filter((t): t is Tag => !!t)
await store.save<ForumThread>(forumThread)
}

logger.info('new Tag is assigned to ForumThread', { tagIds, threadId })
kdembler marked this conversation as resolved.
Show resolved Hide resolved
return forumThread
}

export async function processAssignTagsToProposal(
store: DatabaseManager,
metadata: DecodedMetadataObject<IAssignTagsToProposal>,
isLead: boolean,
workerId: number
): Promise<any> {
const { tagIds, proposalId } = metadata

if (!isLead) {
const tagPermittedWorker: TagPermittedWorker | undefined = await getOneBy(store, TagPermittedWorker, {
workerId: workerId.toString(),
})
if (!tagPermittedWorker) {
return MetaprotocolTxError.TagPermNotAllowed
}
}

const proposal: Proposal | undefined = await getById(store, Proposal, proposalId)
if (!proposal) {
return MetaprotocolTxError.TagInvalidProposalId
}

const currentTagIds = (proposal.tags || []).map((t) => t.id)
const tagIdsToSet = _.union(currentTagIds, tagIds)
if (tagIdsToSet) {
kdembler marked this conversation as resolved.
Show resolved Hide resolved
const tags = await Promise.all(tagIdsToSet.map(async (tagId: string) => await getById(store, Tag, tagId)))
proposal.tags = tags.filter((t): t is Tag => !!t)
await store.save<Proposal>(proposal)
}

logger.info('new Tag is assigned to proposal', { tagIds, proposalId })
kdembler marked this conversation as resolved.
Show resolved Hide resolved
return proposal
}

export async function processUnassignTagsFromThread(
store: DatabaseManager,
metadata: DecodedMetadataObject<IUnassignTagsFromThread>,
isLead: boolean,
workerId: number
): Promise<any> {
const { tagIds, threadId } = metadata

if (!isLead) {
const tagPermittedWorker: TagPermittedWorker | undefined = await getOneBy(store, TagPermittedWorker, {
workerId: workerId.toString(),
})
if (!tagPermittedWorker) {
return MetaprotocolTxError.TagPermNotAllowed
}
}

const forumThread: ForumThread | undefined = await getById(store, ForumThread, threadId)
if (!forumThread) {
return MetaprotocolTxError.TagInvalidThreadId
}

const remainedTags = (forumThread.newTags || []).filter((t) => !(tagIds || []).includes(t.id))
kdembler marked this conversation as resolved.
Show resolved Hide resolved
forumThread.newTags = remainedTags
await store.save<ForumThread>(forumThread)

logger.info('tag is unassigned from forumThread', { tagIds, threadId })
kdembler marked this conversation as resolved.
Show resolved Hide resolved
return forumThread
}

export async function processUnassignTagsFromProposal(
store: DatabaseManager,
metadata: DecodedMetadataObject<IUnassignTagsFromProposal>,
isLead: boolean,
workerId: number
): Promise<any> {
const { tagIds, proposalId } = metadata

if (!isLead) {
const tagPermittedWorker: TagPermittedWorker | undefined = await getOneBy(store, TagPermittedWorker, {
workerId: workerId.toString(),
})
if (!tagPermittedWorker) {
return MetaprotocolTxError.TagPermNotAllowed
}
}

const proposal: Proposal | undefined = await getById(store, Proposal, proposalId)
if (!proposal) {
return MetaprotocolTxError.TagInvalidProposalId
}

const remainedTags = (proposal.tags || []).filter((t) => !(tagIds || []).includes(t.id))
kdembler marked this conversation as resolved.
Show resolved Hide resolved
proposal.tags = remainedTags
await store.save<Proposal>(proposal)

logger.info('tag is unassigned from proposal', { tagIds, proposalId })
kdembler marked this conversation as resolved.
Show resolved Hide resolved
return proposal
}

export async function processAllowTagToWorker(
store: DatabaseManager,
metadata: DecodedMetadataObject<IAllowTagToWorker>
): Promise<any> {
const { workerId: assigneeId } = metadata

const tagPermittedWorker: TagPermittedWorker | undefined = await getOneBy(store, TagPermittedWorker, {
workerId: assigneeId.toString(),
})

if (!tagPermittedWorker) {
const newTagToWorker = new TagPermittedWorker({
workerId: assigneeId,
})
await store.save<TagPermittedWorker>(newTagToWorker)
}

logger.info('TagPermittedWorker has been allowed', { assigneeId })
kdembler marked this conversation as resolved.
Show resolved Hide resolved
}

export async function processDisallowTagToWorker(
store: DatabaseManager,
metadata: DecodedMetadataObject<IDisallowTagToWorker>
): Promise<any> {
const { workerId: assigneeId } = metadata

const tagPermittedWorker: TagPermittedWorker | undefined = await getOneBy(store, TagPermittedWorker, {
workerId: assigneeId.toString(),
})

if (tagPermittedWorker) {
await store.remove<TagPermittedWorker>(tagPermittedWorker)
}

logger.info('TagToWorker has been disallowed', { assigneeId })
}
Loading
Loading