2021-02-02 20:34:10 +00:00
|
|
|
|
|
|
|
# https://gqlgen.com/reference/scalars/
|
|
|
|
scalar Time
|
|
|
|
scalar Upload
|
|
|
|
|
|
|
|
# https://gqlgen.com/reference/directives/
|
2021-02-03 03:55:35 +00:00
|
|
|
directive @hasMinRole(role: Role!) on FIELD_DEFINITION
|
2021-02-04 20:31:07 +00:00
|
|
|
directive @isPrivate on FIELD_DEFINITION | INPUT_FIELD_DEFINITION
|
2021-02-02 20:34:10 +00:00
|
|
|
|
|
|
|
directive @meta(
|
|
|
|
gorm: String,
|
|
|
|
) on OBJECT | FIELD_DEFINITION | ENUM_VALUE | INPUT_FIELD_DEFINITION | ENUM | INPUT_OBJECT | ARGUMENT_DEFINITION
|
|
|
|
|
|
|
|
enum Role {
|
|
|
|
Admin
|
|
|
|
User
|
|
|
|
}
|
|
|
|
|
|
|
|
enum DeviceType {
|
|
|
|
iOS
|
|
|
|
Android
|
|
|
|
Chrome
|
|
|
|
Firefox
|
|
|
|
InternetExplorer
|
|
|
|
Edge
|
|
|
|
Safari
|
|
|
|
Unknown
|
|
|
|
}
|
|
|
|
|
|
|
|
enum AuthType {
|
|
|
|
Local
|
|
|
|
LDAP
|
|
|
|
}
|
|
|
|
|
2021-02-03 03:55:35 +00:00
|
|
|
# ------------------------------------------------------------
|
|
|
|
# ---------------------- Authentication ----------------------
|
|
|
|
# ------------------------------------------------------------
|
|
|
|
|
|
|
|
enum AuthResult {
|
|
|
|
Success
|
|
|
|
Failure
|
|
|
|
}
|
|
|
|
|
|
|
|
type AuthResponse {
|
2021-02-04 20:31:07 +00:00
|
|
|
result: AuthResult!
|
|
|
|
device: Device
|
|
|
|
error: String
|
2021-02-03 03:55:35 +00:00
|
|
|
}
|
|
|
|
|
2021-02-02 20:34:10 +00:00
|
|
|
# ------------------------------------------------------------
|
|
|
|
# ----------------------- Type Filters -----------------------
|
|
|
|
# ------------------------------------------------------------
|
|
|
|
|
|
|
|
input TimeFilter {
|
|
|
|
equalTo: Time
|
|
|
|
notEqualTo: Time
|
|
|
|
lessThan: Time
|
|
|
|
lessThanOrEqualTo: Time
|
|
|
|
moreThan: Time
|
|
|
|
moreThanOrEqualTo: Time
|
|
|
|
}
|
|
|
|
|
|
|
|
input IntFilter {
|
|
|
|
equalTo: Int
|
|
|
|
notEqualTo: Int
|
|
|
|
lessThan: Int
|
|
|
|
lessThanOrEqualTo: Int
|
|
|
|
moreThan: Int
|
|
|
|
moreThanOrEqualTo: Int
|
|
|
|
in: [Int!]
|
|
|
|
notIn: [Int!]
|
|
|
|
}
|
|
|
|
|
|
|
|
input FloatFilter {
|
|
|
|
equalTo: Float
|
|
|
|
notEqualTo: Float
|
|
|
|
lessThan: Float
|
|
|
|
lessThanOrEqualTo: Float
|
|
|
|
moreThan: Float
|
|
|
|
moreThanOrEqualTo: Float
|
|
|
|
in: [Float!]
|
|
|
|
notIn: [Float!]
|
|
|
|
}
|
|
|
|
|
|
|
|
input BooleanFilter {
|
|
|
|
equalTo: Boolean
|
|
|
|
notEqualTo: Boolean
|
|
|
|
}
|
|
|
|
|
|
|
|
input IDFilter {
|
|
|
|
equalTo: ID
|
|
|
|
notEqualTo: ID
|
|
|
|
in: [ID!]
|
|
|
|
notIn: [ID!]
|
|
|
|
}
|
|
|
|
|
|
|
|
input StringFilter {
|
|
|
|
equalTo: String
|
|
|
|
notEqualTo: String
|
|
|
|
startWith: String
|
|
|
|
notStartWith: String
|
|
|
|
endWith: String
|
|
|
|
notEndWith: String
|
|
|
|
contain: String
|
|
|
|
notContain: String
|
|
|
|
in: [String!]
|
|
|
|
notIn: [String!]
|
|
|
|
|
|
|
|
startWithStrict: String
|
|
|
|
notStartWithStrict: String
|
|
|
|
endWithStrict: String
|
|
|
|
notEndWithStrict: String
|
|
|
|
containStrict: String
|
|
|
|
notContainStrict: String
|
|
|
|
}
|
|
|
|
|
|
|
|
input RoleFilter {
|
|
|
|
equalTo: Role
|
|
|
|
notEqualTo: Role
|
|
|
|
in: [Role!]
|
|
|
|
notIn: [Role!]
|
|
|
|
}
|
|
|
|
|
|
|
|
input DeviceTypeFilter {
|
|
|
|
equalTo: DeviceType
|
|
|
|
notEqualTo: DeviceType
|
|
|
|
in: [DeviceType!]
|
|
|
|
notIn: [DeviceType!]
|
|
|
|
}
|
|
|
|
|
|
|
|
input AuthTypeFilter {
|
|
|
|
equalTo: AuthType
|
|
|
|
notEqualTo: AuthType
|
|
|
|
in: [AuthType!]
|
|
|
|
notIn: [AuthType!]
|
|
|
|
}
|
|
|
|
|
|
|
|
# ------------------------------------------------------------
|
|
|
|
# -------------------- Object Definitions --------------------
|
|
|
|
# ------------------------------------------------------------
|
|
|
|
|
2021-02-06 03:01:51 +00:00
|
|
|
type User {
|
|
|
|
id: ID! @meta(gorm: "primaryKey;not null")
|
|
|
|
createdAt: Time
|
|
|
|
updatedAt: Time
|
|
|
|
email: String! @meta(gorm: "not null;unique")
|
|
|
|
username: String! @meta(gorm: "not null;unique")
|
|
|
|
firstName: String
|
|
|
|
lastName: String
|
|
|
|
role: Role! @meta(gorm: "default:User;not null")
|
|
|
|
authType: AuthType! @meta(gorm: "default:Local;not null")
|
|
|
|
password: String @isPrivate
|
|
|
|
devices: [Device!] @meta(gorm: "foreignKey:UserID")
|
|
|
|
mediaItems: [MediaItem!] @meta(gorm: "foreignKey:UserID")
|
|
|
|
}
|
|
|
|
|
2021-02-02 20:34:10 +00:00
|
|
|
type Device {
|
2021-02-04 10:16:13 +00:00
|
|
|
id: ID! @meta(gorm: "primaryKey;not null")
|
2021-02-02 20:34:10 +00:00
|
|
|
createdAt: Time
|
|
|
|
updatedAt: Time
|
|
|
|
name: String! @meta(gorm: "not null")
|
|
|
|
type: DeviceType! @meta(gorm: "default:Unknown;not null")
|
2021-02-04 10:16:13 +00:00
|
|
|
userID: ID! @meta(gorm: "not null")
|
2021-02-04 20:31:07 +00:00
|
|
|
refreshKey: String @isPrivate
|
2021-02-02 20:34:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type MediaItem {
|
2021-02-04 10:16:13 +00:00
|
|
|
id: ID! @meta(gorm: "primaryKey;not null")
|
2021-02-02 20:34:10 +00:00
|
|
|
createdAt: Time
|
|
|
|
updatedAt: Time
|
|
|
|
exifDate: Time
|
|
|
|
latitude: Float
|
|
|
|
longitude: Float
|
|
|
|
isVideo: Boolean! @meta(gorm: "default:false;not null")
|
|
|
|
fileName: String! @meta(gorm: "not null")
|
|
|
|
origName: String! @meta(gorm: "not null")
|
|
|
|
tags: [Tag] @meta(gorm: "many2many:media_tags")
|
|
|
|
albums: [Album] @meta(gorm: "many2many:media_albums")
|
2021-02-04 10:16:13 +00:00
|
|
|
userID: ID! @meta(gorm: "not null")
|
2021-02-02 20:34:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type Tag {
|
2021-02-06 03:01:51 +00:00
|
|
|
id: ID! @meta(gorm: "primaryKey;not null")
|
2021-02-02 20:34:10 +00:00
|
|
|
createdAt: Time
|
|
|
|
updatedAt: Time
|
2021-02-06 03:01:51 +00:00
|
|
|
name: String! @meta(gorm: "unique;not null")
|
2021-02-02 20:34:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type Album {
|
2021-02-07 02:11:44 +00:00
|
|
|
id: ID! @meta(gorm: "primaryKey;not null")
|
2021-02-02 20:34:10 +00:00
|
|
|
createdAt: Time
|
|
|
|
updatedAt: Time
|
2021-02-07 02:11:44 +00:00
|
|
|
name: String! @meta(gorm: "unique;not null")
|
|
|
|
# userID: ID! @meta(gorm: "not null")
|
2021-02-02 20:34:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# ------------------------------------------------------------
|
|
|
|
# ---------------------- Object Filters ----------------------
|
|
|
|
# ------------------------------------------------------------
|
|
|
|
|
|
|
|
input UserFilter {
|
|
|
|
id: IDFilter
|
|
|
|
createdAt: TimeFilter
|
|
|
|
updatedAt: TimeFilter
|
|
|
|
username: StringFilter
|
|
|
|
firstName: StringFilter
|
|
|
|
lastName: StringFilter
|
|
|
|
role: RoleFilter
|
|
|
|
authType: AuthTypeFilter
|
|
|
|
|
|
|
|
and: UserFilter
|
|
|
|
or: UserFilter
|
|
|
|
}
|
|
|
|
|
|
|
|
input MediaItemFilter {
|
|
|
|
id: IDFilter
|
|
|
|
createdAt: TimeFilter
|
|
|
|
updatedAt: TimeFilter
|
|
|
|
exifDate: TimeFilter
|
|
|
|
latitude: FloatFilter
|
|
|
|
longitude: FloatFilter
|
|
|
|
isVideo: BooleanFilter
|
|
|
|
origName: StringFilter
|
|
|
|
tags: TagFilter
|
|
|
|
albums: AlbumFilter
|
|
|
|
|
|
|
|
and: MediaItemFilter
|
|
|
|
or: MediaItemFilter
|
|
|
|
}
|
|
|
|
|
|
|
|
input DeviceFilter {
|
|
|
|
id: IDFilter
|
|
|
|
createdAt: TimeFilter
|
|
|
|
updatedAt: TimeFilter
|
|
|
|
name: StringFilter
|
|
|
|
type: DeviceTypeFilter
|
|
|
|
|
|
|
|
and: MediaItemFilter
|
|
|
|
or: MediaItemFilter
|
|
|
|
}
|
|
|
|
|
|
|
|
input TagFilter {
|
|
|
|
id: IDFilter
|
|
|
|
createdAt: TimeFilter
|
|
|
|
updatedAt: TimeFilter
|
|
|
|
name: StringFilter
|
|
|
|
|
|
|
|
and: MediaItemFilter
|
|
|
|
or: MediaItemFilter
|
|
|
|
}
|
|
|
|
|
|
|
|
input AlbumFilter {
|
|
|
|
id: IDFilter
|
|
|
|
createdAt: TimeFilter
|
|
|
|
updatedAt: TimeFilter
|
|
|
|
name: StringFilter
|
|
|
|
|
|
|
|
and: MediaItemFilter
|
|
|
|
or: MediaItemFilter
|
|
|
|
}
|
|
|
|
|
|
|
|
# ------------------------------------------------------------
|
|
|
|
# -------------------------- Inputs --------------------------
|
|
|
|
# ------------------------------------------------------------
|
|
|
|
|
|
|
|
input NewUser {
|
|
|
|
email: String!
|
|
|
|
username: String!
|
|
|
|
firstName: String
|
|
|
|
lastName: String
|
|
|
|
role: Role!
|
|
|
|
authType: AuthType!
|
|
|
|
password: String
|
|
|
|
}
|
|
|
|
|
|
|
|
input NewMediaItem {
|
|
|
|
file: Upload!
|
|
|
|
tags: [ID!]
|
|
|
|
albums: [ID!]
|
|
|
|
}
|
|
|
|
|
|
|
|
input NewTag {
|
|
|
|
name: String!
|
|
|
|
}
|
|
|
|
|
|
|
|
input NewAlbum {
|
|
|
|
name: String!
|
|
|
|
}
|
|
|
|
|
|
|
|
# ------------------------------------------------------------
|
|
|
|
# ------------------------ Responses -------------------------
|
|
|
|
# ------------------------------------------------------------
|
|
|
|
|
|
|
|
type PageInfo {
|
|
|
|
count: Int!
|
|
|
|
page: Int!
|
|
|
|
total: Int!
|
|
|
|
}
|
|
|
|
|
|
|
|
type MediaItemResponse {
|
|
|
|
data: [MediaItem]
|
|
|
|
pageInfo: PageInfo!
|
|
|
|
}
|
|
|
|
|
|
|
|
type UserResponse {
|
|
|
|
data: [User]
|
|
|
|
pageInfo: PageInfo!
|
|
|
|
}
|
|
|
|
|
|
|
|
type DeviceResponse {
|
|
|
|
data: [Device]
|
|
|
|
pageInfo: PageInfo!
|
|
|
|
}
|
|
|
|
|
|
|
|
type TagResponse {
|
|
|
|
data: [Tag]
|
|
|
|
pageInfo: PageInfo!
|
|
|
|
}
|
|
|
|
|
|
|
|
type AlbumResponse {
|
|
|
|
data: [Album]
|
|
|
|
pageInfo: PageInfo!
|
|
|
|
}
|
|
|
|
|
|
|
|
# ------------------------------------------------------------
|
|
|
|
# --------------------- Query & Mutations --------------------
|
|
|
|
# ------------------------------------------------------------
|
|
|
|
|
|
|
|
type Query {
|
2021-02-03 03:55:35 +00:00
|
|
|
# Authentication
|
|
|
|
login(
|
|
|
|
user: String!
|
|
|
|
password: String!
|
2021-02-04 10:16:13 +00:00
|
|
|
deviceID: ID
|
|
|
|
): AuthResponse!
|
2021-02-07 02:11:44 +00:00
|
|
|
logout: AuthResponse! @hasMinRole(role: User)
|
2021-02-03 03:55:35 +00:00
|
|
|
|
2021-02-02 20:34:10 +00:00
|
|
|
# Single Item
|
2021-02-07 02:11:44 +00:00
|
|
|
mediaItem(
|
|
|
|
id: ID!
|
|
|
|
delete: Boolean
|
|
|
|
): MediaItem! @hasMinRole(role: User)
|
|
|
|
device(
|
|
|
|
id: ID!
|
|
|
|
delete: Boolean
|
|
|
|
): Device! @hasMinRole(role: User)
|
|
|
|
album(
|
|
|
|
id: ID!
|
|
|
|
delete: Boolean
|
|
|
|
): Album! @hasMinRole(role: User)
|
|
|
|
user(
|
|
|
|
id: ID!
|
|
|
|
delete: Boolean
|
|
|
|
): User! @hasMinRole(role: Admin) # TODO: Delete All User Content
|
|
|
|
tag(
|
|
|
|
id: ID!
|
|
|
|
delete: Boolean
|
|
|
|
): Tag! @hasMinRole(role: User)
|
|
|
|
me(delete: Boolean): User! @hasMinRole(role: User)
|
2021-02-02 20:34:10 +00:00
|
|
|
|
|
|
|
# All
|
|
|
|
mediaItems(
|
2021-02-07 02:11:44 +00:00
|
|
|
delete: Boolean
|
2021-02-02 20:34:10 +00:00
|
|
|
filter: MediaItemFilter
|
|
|
|
count: Int
|
|
|
|
page: Int
|
2021-02-03 03:55:35 +00:00
|
|
|
): MediaItemResponse! @hasMinRole(role: User)
|
2021-02-02 20:34:10 +00:00
|
|
|
devices(
|
2021-02-07 02:11:44 +00:00
|
|
|
delete: Boolean
|
2021-02-02 20:34:10 +00:00
|
|
|
filter: DeviceFilter
|
|
|
|
count: Int
|
|
|
|
page: Int
|
2021-02-03 03:55:35 +00:00
|
|
|
): DeviceResponse! @hasMinRole(role: User)
|
2021-02-02 20:34:10 +00:00
|
|
|
albums(
|
2021-02-07 02:11:44 +00:00
|
|
|
delete: Boolean
|
2021-02-02 20:34:10 +00:00
|
|
|
filter: AlbumFilter
|
|
|
|
count: Int
|
|
|
|
page: Int
|
2021-02-03 03:55:35 +00:00
|
|
|
): AlbumResponse! @hasMinRole(role: User)
|
2021-02-02 20:34:10 +00:00
|
|
|
tags(
|
2021-02-07 02:11:44 +00:00
|
|
|
delete: Boolean
|
2021-02-02 20:34:10 +00:00
|
|
|
filter: TagFilter
|
|
|
|
count: Int
|
|
|
|
page: Int
|
2021-02-03 03:55:35 +00:00
|
|
|
): TagResponse! @hasMinRole(role: User)
|
2021-02-02 20:34:10 +00:00
|
|
|
users(
|
2021-02-07 02:11:44 +00:00
|
|
|
delete: Boolean
|
2021-02-02 20:34:10 +00:00
|
|
|
filter: UserFilter
|
|
|
|
count: Int
|
|
|
|
page: Int
|
2021-02-07 02:11:44 +00:00
|
|
|
): UserResponse! @hasMinRole(role: Admin) # TODO: Delete All User Content
|
2021-02-02 20:34:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type Mutation {
|
2021-02-03 03:55:35 +00:00
|
|
|
createMediaItem(input: NewMediaItem!): MediaItem! @hasMinRole(role: User)
|
|
|
|
createAlbum(input: NewAlbum!): Album! @hasMinRole(role: User)
|
|
|
|
createTag(input: NewTag!): Tag! @hasMinRole(role: User)
|
|
|
|
createUser(input: NewUser!): User! @hasMinRole(role: Admin)
|
2021-02-02 20:34:10 +00:00
|
|
|
}
|