refactor(backend): lint graphql (#8473)

This commit is contained in:
Ulf Gebhardt 2026-01-28 14:42:53 +01:00 committed by GitHub
parent 8136ec1aba
commit 524c4caf5e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 1273 additions and 288 deletions

View File

@ -14,7 +14,6 @@ module.exports = {
'plugin:import/recommended',
'plugin:import/typescript',
'plugin:promise/recommended',
'plugin:security/recommended-legacy',
'plugin:@eslint-community/eslint-comments/recommended',
'prettier',
],
@ -175,6 +174,10 @@ module.exports = {
'@eslint-community/eslint-comments/require-description': 'off',
},
overrides: [
{
files: ['*.js', '*.cjs', '*.ts', '*.tsx'],
extends: ['plugin:security/recommended-legacy'],
},
// only for ts files
{
files: ['*.ts', '*.tsx'],
@ -228,5 +231,33 @@ module.exports = {
files: ['*.json', '*.json5', '*.jsonc'],
parser: 'jsonc-eslint-parser',
},
{
files: ['*.graphql', '*.gql'],
parser: '@graphql-eslint/eslint-plugin',
plugins: ['@graphql-eslint'],
extends: ['plugin:@graphql-eslint/schema-recommended'],
rules: {
'@graphql-eslint/description-style': ['error', { style: 'inline' }],
'@graphql-eslint/require-description': 'off',
'@graphql-eslint/naming-convention': 'off',
'@graphql-eslint/strict-id-in-types': 'off',
'@graphql-eslint/no-typename-prefix': 'off',
// incompatible: `depends on a GraphQL validation rule "XXX" but it's not available in the "graphql" version you are using. Skipping…`
'@graphql-eslint/known-directives': 'off',
'@graphql-eslint/known-argument-names': 'off',
'@graphql-eslint/known-type-names': 'off',
'@graphql-eslint/lone-schema-definition': 'off',
'@graphql-eslint/provided-required-arguments': 'off',
'@graphql-eslint/unique-directive-names': 'off',
'@graphql-eslint/unique-directive-names-per-location': 'off',
'@graphql-eslint/unique-field-definition-names': 'off',
'@graphql-eslint/unique-operation-types': 'off',
'@graphql-eslint/unique-type-names': 'off',
},
parserOptions: {
schema: './src/graphql/types/**/*.gql',
assumeValid: true,
},
},
],
}

View File

@ -12,7 +12,7 @@
"build": "tsc && tsc-alias && ./scripts/build.copy.files.sh",
"dev": "nodemon --exec ts-node --require tsconfig-paths/register src/index.ts -e js,ts,gql",
"dev:debug": "nodemon --exec node --inspect=0.0.0.0:9229 build/src/index.js -e js,ts,gql",
"lint": "eslint --max-warnings=0 --report-unused-disable-directives --ext .js,.ts,.cjs,.json,.json5,.jsonc .",
"lint": "eslint --max-warnings=0 --report-unused-disable-directives --ext .js,.ts,.cjs,.json,.json5,.jsonc,.graphql,.gql .",
"test": "cross-env NODE_ENV=test NODE_OPTIONS=--max-old-space-size=8192 jest --runInBand --coverage --forceExit --detectOpenHandles",
"db:reset": "ts-node --require tsconfig-paths/register src/db/reset.ts",
"db:reset:withmigrations": "ts-node --require tsconfig-paths/register src/db/reset-with-migrations.ts",
@ -95,6 +95,7 @@
"devDependencies": {
"@eslint-community/eslint-plugin-eslint-comments": "^4.6.0",
"@faker-js/faker": "9.9.0",
"@graphql-eslint/eslint-plugin": "^3.20.1",
"@types/email-templates": "^10.0.4",
"@types/jest": "^30.0.0",
"@types/jsonwebtoken": "~8.5.1",

View File

@ -0,0 +1,14 @@
# directive @MutationMeta on FIELD_DEFINITION
# directive @isAuthenticated on FIELD_DEFINITION
# directive @hasRole on FIELD_DEFINITION
# directive @hasScope on FIELD_DEFINITION
# directive @additionalLabels on FIELD_DEFINITION
directive @cypher(statement: String) on FIELD_DEFINITION
directive @relation(
name: String
from: String
to: String
direction: String
) on FIELD_DEFINITION | OBJECT
directive @neo4j_ignore on FIELD_DEFINITION

View File

@ -2,4 +2,4 @@ enum EmailNotificationSettingsType {
post
chat
group
}
}

View File

@ -4,4 +4,4 @@ enum Emotion {
happy
angry
funny
}
}

View File

@ -1,4 +1,4 @@
enum ShoutTypeEnum {
Post
Comment
}
}

View File

@ -2,4 +2,4 @@ enum Visibility {
public
friends
private
}
}

View File

@ -50,12 +50,16 @@ type Comment {
isPostObservedByMe: Boolean!
@cypher(
statement: "MATCH (this)-[:COMMENTS]->(:Post)<-[obs:OBSERVES]-(u:User {id: $cypherParams.currentUserId}) WHERE obs.active = true RETURN COUNT(u) >= 1"
)
postObservingUsersCount: Int!
@cypher(statement: "MATCH (this)-[:COMMENTS]->(:Post)<-[obs:OBSERVES]-(u:User) WHERE obs.active = true AND NOT u.disabled = true AND NOT u.deleted = true RETURN COUNT(DISTINCT u)")
)
postObservingUsersCount: Int!
@cypher(
statement: "MATCH (this)-[:COMMENTS]->(:Post)<-[obs:OBSERVES]-(u:User) WHERE obs.active = true AND NOT u.disabled = true AND NOT u.deleted = true RETURN COUNT(DISTINCT u)"
)
shoutedByCurrentUser: Boolean!
@cypher(statement: "MATCH (this) RETURN EXISTS((this)<-[:SHOUTED]-(:User {id: $cypherParams.currentUserId}))")
@cypher(
statement: "MATCH (this) RETURN EXISTS((this)<-[:SHOUTED]-(:User {id: $cypherParams.currentUserId}))"
)
shoutedCount: Int!
@cypher(
@ -77,16 +81,7 @@ type Query {
}
type Mutation {
CreateComment(
id: ID
postId: ID!
content: String!
contentExcerpt: String
): Comment
UpdateComment(
id: ID!
content: String!
contentExcerpt: String
): Comment
CreateComment(id: ID, postId: ID!, content: String!, contentExcerpt: String): Comment
UpdateComment(id: ID!, content: String!, contentExcerpt: String): Comment
DeleteComment(id: ID!): Comment
}

View File

@ -13,4 +13,4 @@ type Query {
type Mutation {
UpdateDonations(showDonations: Boolean, goal: Int, progress: Int): Donations
}
}

View File

@ -9,11 +9,7 @@ type Query {
}
type Mutation {
Signup(
email: String!
locale: String!
inviteCode: String = null
): EmailAddress
Signup(email: String!, locale: String!, inviteCode: String = null): EmailAddress
SignupVerification(
nonce: String!
email: String!
@ -27,8 +23,5 @@ type Mutation {
locationName: String = null
): User
AddEmailAddress(email: String!): EmailAddress
VerifyEmailAddress(
nonce: String!
email: String!
): EmailAddress
VerifyEmailAddress(nonce: String!, email: String!): EmailAddress
}

View File

@ -5,7 +5,7 @@ type FILED {
submitter: User
}
# this list equals the strings of an array in file "webapp/constants/modals.js"
"this list equals the strings of an array in file `webapp/constants/modals.js`"
enum ReasonCategory {
other
discrimination_etc
@ -26,5 +26,9 @@ type FiledReport {
}
type Mutation {
fileReport(resourceId: ID!, reasonCategory: ReasonCategory!, reasonDescription: String!): FiledReport
}
fileReport(
resourceId: ID!
reasonCategory: ReasonCategory!
reasonDescription: String!
): FiledReport
}

View File

@ -1,16 +1,16 @@
type File {
url: ID!,
name: String,
#size: Int,
type: String,
#audio: Boolean,
#duration: Float,
#preview: String,
#progress: Int,
url: ID!
name: String
type: String
# size: Int
# audio: Boolean
# duration: Float
# preview: String
# progress: Int
}
input FileInput {
upload: Upload,
name: String,
type: String,
upload: Upload
name: String
type: String
}

View File

@ -1,19 +1,19 @@
enum _GroupOrdering {
id_asc
id_desc
name_asc
name_desc
slug_asc
slug_desc
locationName_asc
locationName_desc
about_asc
about_desc
createdAt_asc
createdAt_desc
updatedAt_asc
updatedAt_desc
}
# enum _GroupOrdering {
# id_asc
# id_desc
# name_asc
# name_desc
# slug_asc
# slug_desc
# locationName_asc
# locationName_desc
# about_asc
# about_desc
# createdAt_asc
# createdAt_desc
# updatedAt_asc
# updatedAt_desc
# }
type Group {
id: ID!
@ -38,19 +38,21 @@ type Group {
categories: [Category] @relation(name: "CATEGORIZED", direction: "OUT")
membersCount: Int! @cypher(statement: "MATCH (this)<-[:MEMBER_OF]-(r:User) RETURN COUNT(DISTINCT r)")
membersCount: Int!
@cypher(statement: "MATCH (this)<-[:MEMBER_OF]-(r:User) RETURN COUNT(DISTINCT r)")
myRole: GroupMemberRole # if 'null' then the current user is no member
posts: [Post] @relation(name: "IN", direction: "IN")
isMutedByMe: Boolean! @cypher(statement: "MATCH (this) RETURN EXISTS( (this)<-[:MUTED]-(:User {id: $cypherParams.currentUserId}) )")
isMutedByMe: Boolean!
@cypher(
statement: "MATCH (this) RETURN EXISTS( (this)<-[:MUTED]-(:User {id: $cypherParams.currentUserId}) )"
)
"inviteCodes to this group the current user has generated"
inviteCodes: [InviteCode]! @neo4j_ignore
}
input _GroupFilter {
AND: [_GroupFilter!]
OR: [_GroupFilter!]
@ -74,20 +76,16 @@ type Query {
slug: String
first: Int
offset: Int
# orderBy: [_GroupOrdering] # not implemented yet
# filter: _GroupFilter # not implemented yet
): [Group]
# orderBy: [_GroupOrdering] # not implemented yet
# filter: _GroupFilter # not implemented yet
GroupMembers(
id: ID!
first: Int
offset: Int
# orderBy: [_UserOrdering] # not implemented yet
# filter: _UserFilter # not implemented yet
): [User]
GroupMembers(id: ID!, first: Int, offset: Int): [User]
# orderBy: [_UserOrdering] # not implemented yet
# filter: _UserFilter # not implemented yet
GroupCount(isMember: Boolean): Int
# AvailableGroupTypes: [GroupType]!
# AvailableGroupActionRadii: [GroupActionRadius]!
@ -105,7 +103,9 @@ type Mutation {
groupType: GroupType!
actionRadius: GroupActionRadius!
categoryIds: [ID]
# avatar: ImageInput # a group can not be created with an avatar
locationName: String # empty string '' sets it to null
): Group
@ -115,7 +115,9 @@ type Mutation {
slug: String
about: String
description: String
# groupType: GroupType # is not possible at the moment and has to be discussed. may be in the stronger direction: public → closed → hidden
actionRadius: GroupActionRadius
categoryIds: [ID]
avatar: ImageInput # test this as result
@ -124,27 +126,14 @@ type Mutation {
# DeleteGroup(id: ID!): Group
JoinGroup(
groupId: ID!
userId: ID!
): User
JoinGroup(groupId: ID!, userId: ID!): User
LeaveGroup(
groupId: ID!
userId: ID!
): User
LeaveGroup(groupId: ID!, userId: ID!): User
ChangeGroupMemberRole(
groupId: ID!
userId: ID!
roleInGroup: GroupMemberRole!
): User
ChangeGroupMemberRole(groupId: ID!, userId: ID!, roleInGroup: GroupMemberRole!): User
RemoveUserFromGroup(
groupId: ID!
userId: ID!
): User
RemoveUserFromGroup(groupId: ID!, userId: ID!): User
muteGroup(groupId: ID!): Group
unmuteGroup(groupId: ID!): Group
unmuteGroup(groupId: ID!): Group
}

View File

@ -1,21 +1,23 @@
type Image {
url: ID!,
url: ID!
transform(width: Int, height: Int): String
# urlW34: String,
# urlW160: String,
# urlW320: String,
# urlW640: String,
# urlW1024: String,
alt: String,
sensitive: Boolean,
aspectRatio: Float,
type: String,
alt: String
sensitive: Boolean
aspectRatio: Float
type: String
}
input ImageInput {
alt: String,
upload: Upload,
sensitive: Boolean,
aspectRatio: Float,
type: String,
alt: String
upload: Upload
sensitive: Boolean
aspectRatio: Float
type: String
}

View File

@ -19,7 +19,11 @@ type Query {
type Mutation {
generatePersonalInviteCode(expiresAt: String = null, comment: String = null): InviteCode!
generateGroupInviteCode(groupId: ID!, expiresAt: String = null, comment: String = null): InviteCode!
generateGroupInviteCode(
groupId: ID!
expiresAt: String = null
comment: String = null
): InviteCode!
invalidateInviteCode(code: String!): InviteCode
redeemInviteCode(code: String!): Boolean!
}

View File

@ -18,6 +18,7 @@ type Location {
}
# This is not smart - we need one location for everything - use the same type everywhere!
type LocationMapBox {
id: ID!
place_name: String!

View File

@ -19,8 +19,11 @@ type Message {
senderId: String! @cypher(statement: "MATCH (this)<-[:CREATED]-(user:User) RETURN user.id")
username: String! @cypher(statement: "MATCH (this)<-[:CREATED]-(user:User) RETURN user.name")
avatar: String @cypher(statement: "MATCH (this)<-[:CREATED]-(:User)-[:AVATAR_IMAGE]->(image:Image) RETURN image.url")
date: String! @cypher(statement: "RETURN this.createdAt")
avatar: String
@cypher(
statement: "MATCH (this)<-[:CREATED]-(:User)-[:AVATAR_IMAGE]->(image:Image) RETURN image.url"
)
date: String! @cypher(statement: "RETURN this.createdAt")
saved: Boolean
distributed: Boolean
@ -29,22 +32,13 @@ type Message {
}
type Mutation {
CreateMessage(
roomId: ID!
content: String
files: [FileInput]
): Message
CreateMessage(roomId: ID!, content: String, files: [FileInput]): Message
MarkMessagesAsSeen(messageIds: [String!]): Boolean
}
type Query {
Message(
roomId: ID!,
first: Int
offset: Int
orderBy: [_MessageOrdering]
): [Message]
Message(roomId: ID!, first: Int, offset: Int, orderBy: [_MessageOrdering]): [Message]
}
type Subscription {

View File

@ -33,7 +33,7 @@ enum NotificationReason {
type Query {
notifications(read: Boolean, orderBy: NotificationOrdering, first: Int, offset: Int): [NOTIFIED]
}
type Mutation {
markAsRead(id: ID!): NOTIFIED
markAllAsRead: [NOTIFIED]

View File

@ -1,3 +1,7 @@
input _CategoryFilter {
AND: [_CategoryFilter!]
OR: [_CategoryFilter!]
}
input _PostFilter {
AND: [_PostFilter!]
OR: [_PostFilter!]
@ -113,7 +117,6 @@ enum _PostOrdering {
eventStart_desc
}
type Post {
id: ID!
activityId: String
@ -132,10 +135,11 @@ type Post {
updatedAt: String
sortDate: String
language: String
pinnedAt: String @cypher(
pinnedAt: String
@cypher(
statement: "MATCH (this)<-[pinned:PINNED]-(:User) WHERE NOT this.deleted = true AND NOT this.disabled = true RETURN pinned.createdAt"
)
pinnedBy: User @relation(name:"PINNED", direction: "IN")
pinnedBy: User @relation(name: "PINNED", direction: "IN")
relatedContributions: [Post]!
@cypher(
statement: """
@ -160,7 +164,7 @@ type Post {
statement: "MATCH (this)<-[:SHOUTED]-(r:User) WHERE NOT r.deleted = true AND NOT r.disabled = true RETURN COUNT(DISTINCT r)"
)
# Has the currently logged in user shouted that post?
"Has the currently logged in user shouted that post?"
shoutedByCurrentUser: Boolean!
@cypher(
statement: "MATCH (this)<-[:SHOUTED]-(u:User {id: $cypherParams.currentUserId}) RETURN COUNT(u) >= 1"
@ -173,15 +177,14 @@ type Post {
@cypher(
statement: "MATCH (this)<-[:VIEWED_TEASER]-(u:User {id: $cypherParams.currentUserId}) RETURN COUNT(u) >= 1"
)
emotions: [EMOTED]
emotionsCount: Int!
@cypher(statement: "MATCH (this)<-[emoted:EMOTED]-(:User) RETURN COUNT(DISTINCT emoted)")
group: Group @relation(name: "IN", direction: "OUT")
postType: [PostType]
@cypher(statement: "RETURN [l IN labels(this) WHERE NOT l = 'Post']")
postType: [PostType] @cypher(statement: "RETURN [l IN labels(this) WHERE NOT l = 'Post']")
eventLocationName: String
eventLocation: Location @cypher(statement: "MATCH (this)-[:IS_IN]->(l:Location) RETURN l")
@ -193,9 +196,11 @@ type Post {
isObservedByMe: Boolean!
@cypher(
statement: "MATCH (this)<-[obs:OBSERVES]-(u:User {id: $cypherParams.currentUserId}) WHERE obs.active = true RETURN COUNT(u) >= 1"
)
)
observingUsersCount: Int!
@cypher(statement: "MATCH (this)<-[obs:OBSERVES]-(u:User) WHERE obs.active = true AND NOT u.deleted = true AND NOT u.disabled = true RETURN COUNT(DISTINCT u)")
@cypher(
statement: "MATCH (this)<-[obs:OBSERVES]-(u:User) WHERE obs.active = true AND NOT u.deleted = true AND NOT u.disabled = true RETURN COUNT(DISTINCT u)"
)
}
input _PostInput {
@ -216,7 +221,7 @@ type Mutation {
title: String!
slug: String
content: String!
image: ImageInput,
image: ImageInput
visibility: Visibility
language: String
categoryIds: [ID]
@ -231,7 +236,7 @@ type Mutation {
slug: String
content: String!
contentExcerpt: String
image: ImageInput,
image: ImageInput
visibility: Visibility
language: String
categoryIds: [ID]
@ -247,9 +252,9 @@ type Mutation {
pushPost(id: ID!): Post!
unpushPost(id: ID!): Post!
# Shout the given Type and ID
"Shout the given Type and ID"
shout(id: ID!, type: ShoutTypeEnum!): Boolean!
# Unshout the given Type and ID
"Unshout the given Type and ID"
unshout(id: ID!, type: ShoutTypeEnum!): Boolean!
toggleObservePost(id: ID!, value: Boolean!): Post!

View File

@ -17,7 +17,13 @@ enum ReportRule {
}
type Query {
reports(orderBy: ReportOrdering, first: Int, offset: Int, reviewed: Boolean, closed: Boolean): [Report]
reports(
orderBy: ReportOrdering
first: Int
offset: Int
reviewed: Boolean
closed: Boolean
): [Report]
}
enum ReportOrdering {

View File

@ -6,6 +6,7 @@
# }
# TODO change this to last message date
enum _RoomOrdering {
lastMessageAt_desc
createdAt_desc
@ -19,41 +20,48 @@ type Room {
users: [User]! @relation(name: "CHATS_IN", direction: "IN")
roomId: String! @cypher(statement: "RETURN this.id")
roomName: String! @cypher(statement: "MATCH (this)<-[:CHATS_IN]-(user:User) WHERE NOT user.id = $cypherParams.currentUserId RETURN user.name")
avatar: String @cypher(statement: """
MATCH (this)<-[:CHATS_IN]-(user:User)
WHERE NOT user.id = $cypherParams.currentUserId
OPTIONAL MATCH (user)-[:AVATAR_IMAGE]->(image:Image)
RETURN image.url
""")
roomName: String!
@cypher(
statement: "MATCH (this)<-[:CHATS_IN]-(user:User) WHERE NOT user.id = $cypherParams.currentUserId RETURN user.name"
)
avatar: String
@cypher(
statement: """
MATCH (this)<-[:CHATS_IN]-(user:User)
WHERE NOT user.id = $cypherParams.currentUserId
OPTIONAL MATCH (user)-[:AVATAR_IMAGE]->(image:Image)
RETURN image.url
"""
)
lastMessageAt: String
lastMessage: Message @cypher(statement: """
MATCH (this)<-[:INSIDE]-(message:Message)
WITH message ORDER BY message.indexId DESC LIMIT 1
RETURN message
""")
lastMessage: Message
@cypher(
statement: """
MATCH (this)<-[:INSIDE]-(message:Message)
WITH message ORDER BY message.indexId DESC LIMIT 1
RETURN message
"""
)
unreadCount: Int @cypher(statement: """
MATCH (this)<-[:INSIDE]-(message:Message)<-[:CREATED]-(user:User)
WHERE NOT user.id = $cypherParams.currentUserId
AND NOT message.seen
RETURN count(message)
""")
unreadCount: Int
@cypher(
statement: """
MATCH (this)<-[:INSIDE]-(message:Message)<-[:CREATED]-(user:User)
WHERE NOT user.id = $cypherParams.currentUserId
AND NOT message.seen
RETURN count(message)
"""
)
}
type Mutation {
CreateRoom(
userId: ID!
): Room
CreateRoom(userId: ID!): Room
}
type Query {
Room(
id: ID
orderBy: [_RoomOrdering]
): [Room]
Room(id: ID, orderBy: [_RoomOrdering]): [Room]
UnreadRooms: Int
}

View File

@ -25,4 +25,3 @@ type Statistics {
usersVerified: Int!
reports: Int!
}

View File

@ -19,7 +19,8 @@ type Tag {
id: ID!
taggedPosts: [Post]! @relation(name: "TAGGED", direction: "IN")
taggedCount: Int! @cypher(statement: "MATCH (this)<-[:TAGGED]-(p) RETURN COUNT(DISTINCT p)")
taggedCountUnique: Int! @cypher(statement: "MATCH (this)<-[:TAGGED]-(p)<-[:WROTE]-(u:User) RETURN COUNT(DISTINCT u)")
taggedCountUnique: Int!
@cypher(statement: "MATCH (this)<-[:TAGGED]-(p)<-[:WROTE]-(u:User) RETURN COUNT(DISTINCT u)")
deleted: Boolean
disabled: Boolean
}
@ -34,11 +35,5 @@ enum _TagOrdering {
}
type Query {
Tag(
id: ID
first: Int
offset: Int
orderBy: [_TagOrdering]
filter: _TagFilter
): [Tag]
Tag(id: ID, first: Int, offset: Int, orderBy: [_TagOrdering], filter: _TagFilter): [Tag]
}

View File

@ -38,7 +38,8 @@ type User {
id: ID!
actorId: String
name: String
email: String! @cypher(statement: "MATCH (this)-[:PRIMARY_EMAIL]->(e:EmailAddress) RETURN e.email")
email: String!
@cypher(statement: "MATCH (this)-[:PRIMARY_EMAIL]->(e:EmailAddress) RETURN e.email")
slug: String!
avatar: Image @relation(name: "AVATAR_IMAGE", direction: "OUT")
deleted: Boolean
@ -64,65 +65,78 @@ type User {
emailNotificationSettings: [EmailNotificationSettings]! @neo4j_ignore
locale: String
friends: [User]! @relation(name: "FRIENDS", direction: "BOTH")
friendsCount: Int! @cypher(statement: "MATCH (this)<-[:FRIENDS]->(r:User) RETURN COUNT(DISTINCT r)")
friendsCount: Int!
@cypher(statement: "MATCH (this)<-[:FRIENDS]->(r:User) RETURN COUNT(DISTINCT r)")
following: [User]! @relation(name: "FOLLOWS", direction: "OUT")
followingCount: Int! @cypher(statement: "MATCH (this)-[:FOLLOWS]->(r:User) RETURN COUNT(DISTINCT r)")
followingCount: Int!
@cypher(statement: "MATCH (this)-[:FOLLOWS]->(r:User) RETURN COUNT(DISTINCT r)")
followedBy: [User]! @relation(name: "FOLLOWS", direction: "IN")
followedByCount: Int! @cypher(statement: "MATCH (this)<-[:FOLLOWS]-(r:User) RETURN COUNT(DISTINCT r)")
followedByCount: Int!
@cypher(statement: "MATCH (this)<-[:FOLLOWS]-(r:User) RETURN COUNT(DISTINCT r)")
# Is the currently logged in user following that user?
followedByCurrentUser: Boolean! @cypher(
statement: """
MATCH (this)<-[:FOLLOWS]-(u:User { id: $cypherParams.currentUserId})
RETURN COUNT(u) >= 1
"""
)
"Is the currently logged in user following that user?"
followedByCurrentUser: Boolean!
@cypher(
statement: "MATCH (this)<-[:FOLLOWS]-(u:User { id: $cypherParams.currentUserId}) RETURN COUNT(u) >= 1"
)
isBlocked: Boolean! @cypher(
statement: """
MATCH (this)<-[:BLOCKED]-(user:User {id: $cypherParams.currentUserId})
RETURN COUNT(user) >= 1
"""
)
blocked: Boolean! @cypher(
statement: """
MATCH (this)-[:BLOCKED]-(user:User {id: $cypherParams.currentUserId})
RETURN COUNT(user) >= 1
"""
)
isBlocked: Boolean!
@cypher(
statement: """
MATCH (this)<-[:BLOCKED]-(user:User {id: $cypherParams.currentUserId})
RETURN COUNT(user) >= 1
"""
)
blocked: Boolean!
@cypher(
statement: """
MATCH (this)-[:BLOCKED]-(user:User {id: $cypherParams.currentUserId})
RETURN COUNT(user) >= 1
"""
)
isMuted: Boolean!
@cypher(
statement: """
MATCH (this)<-[:MUTED]-(user:User { id: $cypherParams.currentUserId})
RETURN COUNT(user) >= 1
"""
)
isMuted: Boolean! @cypher(
statement: """
MATCH (this)<-[:MUTED]-(user:User { id: $cypherParams.currentUserId})
RETURN COUNT(user) >= 1
"""
)
# contributions: [WrittenPost]!
# contributions2(first: Int = 10, offset: Int = 0): [WrittenPost2]!
# @cypher(
# statement: "MATCH (this)-[w:WROTE]->(p:Post) RETURN p as Post, w.timestamp as timestamp"
# )
contributions: [Post]! @relation(name: "WROTE", direction: "OUT")
contributionsCount: Int! @cypher(
statement: """
MATCH (this)-[:WROTE]->(r:Post)
WHERE NOT r.deleted = true AND NOT r.disabled = true
RETURN COUNT(r)
"""
)
contributionsCount: Int!
@cypher(
statement: """
MATCH (this)-[:WROTE]->(r:Post)
WHERE NOT r.deleted = true AND NOT r.disabled = true
RETURN COUNT(r)
"""
)
comments: [Comment]! @relation(name: "WROTE", direction: "OUT")
commentedCount: Int! @cypher(statement: "MATCH (this)-[:WROTE]->(:Comment)-[:COMMENTS]->(p:Post) WHERE NOT p.deleted = true AND NOT p.disabled = true RETURN COUNT(DISTINCT(p))")
commentedCount: Int!
@cypher(
statement: "MATCH (this)-[:WROTE]->(:Comment)-[:COMMENTS]->(p:Post) WHERE NOT p.deleted = true AND NOT p.disabled = true RETURN COUNT(DISTINCT(p))"
)
shouted: [Post]! @relation(name: "SHOUTED", direction: "OUT")
shoutedCount: Int! @cypher(statement: "MATCH (this)-[:SHOUTED]->(r:Post) WHERE NOT r.deleted = true AND NOT r.disabled = true RETURN COUNT(DISTINCT r)")
shoutedCount: Int!
@cypher(
statement: "MATCH (this)-[:SHOUTED]->(r:Post) WHERE NOT r.deleted = true AND NOT r.disabled = true RETURN COUNT(DISTINCT r)"
)
categories: [Category] @relation(name: "CATEGORIZED", direction: "OUT")
# Badges
badgeVerification: Badge! @neo4j_ignore
badgeTrophies: [Badge]! @relation(name: "REWARDED", direction: "IN")
badgeTrophiesCount: Int! @cypher(statement: "MATCH (this)<-[:REWARDED]-(r:Badge) RETURN COUNT(r)")
@ -133,6 +147,7 @@ type User {
"personal inviteCodes the user has generated"
inviteCodes: [InviteCode]! @neo4j_ignore
# inviteCodes: [InviteCode]! @relation(name: "GENERATED", direction: "OUT")
redeemedInviteCode: InviteCode @relation(name: "REDEEMED", direction: "OUT")
emotions: [EMOTED]
@ -142,7 +157,6 @@ type User {
myRoleInGroup: GroupMemberRole
}
input _UserFilter {
AND: [_UserFilter!]
OR: [_UserFilter!]
@ -197,7 +211,7 @@ type Query {
filter: _UserFilter
): [User]
availableRoles: [UserRole]!
availableRoles: [UserRole]!
mutedUsers: [User]
blockedUsers: [User]
currentUser: User!
@ -209,7 +223,7 @@ enum Deletable {
}
type Mutation {
UpdateUser (
UpdateUser(
id: ID!
name: String
email: String
@ -239,14 +253,14 @@ type Mutation {
switchUserRole(role: UserRole!, id: ID!): User
saveCategorySettings(activeCategories: [String]): Boolean
updateOnlineStatus(status: OnlineStatus!): Boolean!
requestPasswordReset(email: String!, locale: String!): Boolean!
resetPassword(email: String!, nonce: String!, newPassword: String!): Boolean!
changePassword(oldPassword: String!, newPassword: String!): String!
# Get a JWT Token for the given Email and password
"Get a JWT Token for the given Email and password"
login(email: String!, password: String!): String!
setTrophyBadgeSelected(slot: Int!, badgeId: ID): User

View File

@ -4,7 +4,5 @@ type UserData {
}
type Query {
userData(
id: ID
): UserData
userData(id: ID): UserData
}

File diff suppressed because it is too large Load Diff