Enable GraphQL! #1
File diff suppressed because it is too large
Load Diff
@ -1,15 +1,61 @@
|
|||||||
package graph
|
package graph
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/dsoprea/go-exif/v3"
|
"github.com/dsoprea/go-exif/v3"
|
||||||
exifcommon "github.com/dsoprea/go-exif/v3/common"
|
exifcommon "github.com/dsoprea/go-exif/v3/common"
|
||||||
|
"github.com/google/uuid"
|
||||||
"reichard.io/imagini/graph/model"
|
"reichard.io/imagini/graph/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func getContextHTTP(ctx context.Context) (*http.ResponseWriter, *http.Request, error) {
|
||||||
|
authContext := ctx.Value("auth").(*model.AuthContext)
|
||||||
|
|
||||||
|
resp := authContext.AuthResponse
|
||||||
|
if resp == nil {
|
||||||
|
return nil, nil, errors.New("Context Error")
|
||||||
|
}
|
||||||
|
|
||||||
|
req := authContext.AuthRequest
|
||||||
|
if resp == nil {
|
||||||
|
return nil, nil, errors.New("Context Error")
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, req, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getContextIDs(ctx context.Context) (string, string, error) {
|
||||||
|
authContext := ctx.Value("auth").(*model.AuthContext)
|
||||||
|
accessToken := *authContext.AccessToken
|
||||||
|
|
||||||
|
uid, ok := accessToken.Get("sub")
|
||||||
|
if !ok {
|
||||||
|
return "", "", errors.New("Context Error")
|
||||||
|
}
|
||||||
|
|
||||||
|
did, ok := accessToken.Get("sub")
|
||||||
|
if !ok {
|
||||||
|
return "", "", errors.New("Context Error")
|
||||||
|
}
|
||||||
|
|
||||||
|
userID, err := uuid.Parse(uid.(string))
|
||||||
|
if err != nil {
|
||||||
|
return "", "", errors.New("Context Error")
|
||||||
|
}
|
||||||
|
|
||||||
|
deviceID, err := uuid.Parse(did.(string))
|
||||||
|
if err != nil {
|
||||||
|
return "", "", errors.New("Context Error")
|
||||||
|
}
|
||||||
|
|
||||||
|
return userID.String(), deviceID.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
func deriveDeviceType(r *http.Request) model.DeviceType {
|
func deriveDeviceType(r *http.Request) model.DeviceType {
|
||||||
userAgent := strings.ToLower(r.Header.Get("User-Agent"))
|
userAgent := strings.ToLower(r.Header.Get("User-Agent"))
|
||||||
if strings.Contains(userAgent, "ios-imagini") {
|
if strings.Contains(userAgent, "ios-imagini") {
|
||||||
|
@ -28,7 +28,7 @@ type AlbumFilter struct {
|
|||||||
|
|
||||||
type AlbumResponse struct {
|
type AlbumResponse struct {
|
||||||
Data []*Album `json:"data" `
|
Data []*Album `json:"data" `
|
||||||
PageInfo *PageInfo `json:"pageInfo" `
|
Page *PageResponse `json:"page" `
|
||||||
}
|
}
|
||||||
|
|
||||||
type AuthResponse struct {
|
type AuthResponse struct {
|
||||||
@ -67,7 +67,7 @@ type DeviceFilter struct {
|
|||||||
|
|
||||||
type DeviceResponse struct {
|
type DeviceResponse struct {
|
||||||
Data []*Device `json:"data" `
|
Data []*Device `json:"data" `
|
||||||
PageInfo *PageInfo `json:"pageInfo" `
|
Page *PageResponse `json:"page" `
|
||||||
}
|
}
|
||||||
|
|
||||||
type DeviceTypeFilter struct {
|
type DeviceTypeFilter struct {
|
||||||
@ -128,7 +128,7 @@ type MediaItemFilter struct {
|
|||||||
|
|
||||||
type MediaItemResponse struct {
|
type MediaItemResponse struct {
|
||||||
Data []*MediaItem `json:"data" `
|
Data []*MediaItem `json:"data" `
|
||||||
PageInfo *PageInfo `json:"pageInfo" `
|
Page *PageResponse `json:"page" `
|
||||||
}
|
}
|
||||||
|
|
||||||
type NewAlbum struct {
|
type NewAlbum struct {
|
||||||
@ -155,8 +155,18 @@ type NewUser struct {
|
|||||||
Password *string `json:"password" `
|
Password *string `json:"password" `
|
||||||
}
|
}
|
||||||
|
|
||||||
type PageInfo struct {
|
type Order struct {
|
||||||
Count int `json:"count" `
|
By *string `json:"by" `
|
||||||
|
Direction *OrderDirection `json:"direction" `
|
||||||
|
}
|
||||||
|
|
||||||
|
type Page struct {
|
||||||
|
Size *int `json:"size" `
|
||||||
|
Page *int `json:"page" `
|
||||||
|
}
|
||||||
|
|
||||||
|
type PageResponse struct {
|
||||||
|
Size int `json:"size" `
|
||||||
Page int `json:"page" `
|
Page int `json:"page" `
|
||||||
Total int `json:"total" `
|
Total int `json:"total" `
|
||||||
}
|
}
|
||||||
@ -194,7 +204,7 @@ type TagFilter struct {
|
|||||||
|
|
||||||
type TagResponse struct {
|
type TagResponse struct {
|
||||||
Data []*Tag `json:"data" `
|
Data []*Tag `json:"data" `
|
||||||
PageInfo *PageInfo `json:"pageInfo" `
|
Page *PageResponse `json:"page" `
|
||||||
}
|
}
|
||||||
|
|
||||||
type TimeFilter struct {
|
type TimeFilter struct {
|
||||||
@ -234,7 +244,7 @@ type UserFilter struct {
|
|||||||
|
|
||||||
type UserResponse struct {
|
type UserResponse struct {
|
||||||
Data []*User `json:"data" `
|
Data []*User `json:"data" `
|
||||||
PageInfo *PageInfo `json:"pageInfo" `
|
Page *PageResponse `json:"page" `
|
||||||
}
|
}
|
||||||
|
|
||||||
type AuthResult string
|
type AuthResult string
|
||||||
@ -372,6 +382,47 @@ func (e DeviceType) MarshalGQL(w io.Writer) {
|
|||||||
fmt.Fprint(w, strconv.Quote(e.String()))
|
fmt.Fprint(w, strconv.Quote(e.String()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type OrderDirection string
|
||||||
|
|
||||||
|
const (
|
||||||
|
OrderDirectionAsc OrderDirection = "ASC"
|
||||||
|
OrderDirectionDesc OrderDirection = "DESC"
|
||||||
|
)
|
||||||
|
|
||||||
|
var AllOrderDirection = []OrderDirection{
|
||||||
|
OrderDirectionAsc,
|
||||||
|
OrderDirectionDesc,
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e OrderDirection) IsValid() bool {
|
||||||
|
switch e {
|
||||||
|
case OrderDirectionAsc, OrderDirectionDesc:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e OrderDirection) String() string {
|
||||||
|
return string(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *OrderDirection) UnmarshalGQL(v interface{}) error {
|
||||||
|
str, ok := v.(string)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("enums must be strings")
|
||||||
|
}
|
||||||
|
|
||||||
|
*e = OrderDirection(str)
|
||||||
|
if !e.IsValid() {
|
||||||
|
return fmt.Errorf("%s is not a valid OrderDirection", str)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e OrderDirection) MarshalGQL(w io.Writer) {
|
||||||
|
fmt.Fprint(w, strconv.Quote(e.String()))
|
||||||
|
}
|
||||||
|
|
||||||
type Role string
|
type Role string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -32,6 +32,11 @@ enum AuthType {
|
|||||||
LDAP
|
LDAP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum OrderDirection {
|
||||||
|
ASC
|
||||||
|
DESC
|
||||||
|
}
|
||||||
|
|
||||||
# ------------------------------------------------------------
|
# ------------------------------------------------------------
|
||||||
# ---------------------- Authentication ----------------------
|
# ---------------------- Authentication ----------------------
|
||||||
# ------------------------------------------------------------
|
# ------------------------------------------------------------
|
||||||
@ -267,39 +272,49 @@ input NewAlbum {
|
|||||||
name: String!
|
name: String!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input Page {
|
||||||
|
size: Int
|
||||||
|
page: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
input Order {
|
||||||
|
by: String
|
||||||
|
direction: OrderDirection
|
||||||
|
}
|
||||||
|
|
||||||
# ------------------------------------------------------------
|
# ------------------------------------------------------------
|
||||||
# ------------------------ Responses -------------------------
|
# ------------------------ Responses -------------------------
|
||||||
# ------------------------------------------------------------
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
type PageInfo {
|
type PageResponse {
|
||||||
count: Int!
|
size: Int!
|
||||||
page: Int!
|
page: Int!
|
||||||
total: Int!
|
total: Int!
|
||||||
}
|
}
|
||||||
|
|
||||||
type MediaItemResponse {
|
type MediaItemResponse {
|
||||||
data: [MediaItem]
|
data: [MediaItem]
|
||||||
pageInfo: PageInfo!
|
page: PageResponse!
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserResponse {
|
type UserResponse {
|
||||||
data: [User]
|
data: [User]
|
||||||
pageInfo: PageInfo!
|
page: PageResponse!
|
||||||
}
|
}
|
||||||
|
|
||||||
type DeviceResponse {
|
type DeviceResponse {
|
||||||
data: [Device]
|
data: [Device]
|
||||||
pageInfo: PageInfo!
|
page: PageResponse!
|
||||||
}
|
}
|
||||||
|
|
||||||
type TagResponse {
|
type TagResponse {
|
||||||
data: [Tag]
|
data: [Tag]
|
||||||
pageInfo: PageInfo!
|
page: PageResponse!
|
||||||
}
|
}
|
||||||
|
|
||||||
type AlbumResponse {
|
type AlbumResponse {
|
||||||
data: [Album]
|
data: [Album]
|
||||||
pageInfo: PageInfo!
|
page: PageResponse!
|
||||||
}
|
}
|
||||||
|
|
||||||
# ------------------------------------------------------------
|
# ------------------------------------------------------------
|
||||||
@ -318,57 +333,47 @@ type Query {
|
|||||||
# Single Item
|
# Single Item
|
||||||
mediaItem(
|
mediaItem(
|
||||||
id: ID!
|
id: ID!
|
||||||
delete: Boolean
|
|
||||||
): MediaItem! @hasMinRole(role: User)
|
): MediaItem! @hasMinRole(role: User)
|
||||||
device(
|
device(
|
||||||
id: ID!
|
id: ID!
|
||||||
delete: Boolean
|
|
||||||
): Device! @hasMinRole(role: User)
|
): Device! @hasMinRole(role: User)
|
||||||
album(
|
album(
|
||||||
id: ID!
|
id: ID!
|
||||||
delete: Boolean
|
|
||||||
): Album! @hasMinRole(role: User)
|
): Album! @hasMinRole(role: User)
|
||||||
user(
|
user(
|
||||||
id: ID!
|
id: ID!
|
||||||
delete: Boolean
|
): User! @hasMinRole(role: Admin)
|
||||||
): User! @hasMinRole(role: Admin) # TODO: Delete All User Content
|
|
||||||
tag(
|
tag(
|
||||||
id: ID!
|
id: ID!
|
||||||
delete: Boolean
|
|
||||||
): Tag! @hasMinRole(role: User)
|
): Tag! @hasMinRole(role: User)
|
||||||
me(delete: Boolean): User! @hasMinRole(role: User)
|
me: User! @hasMinRole(role: User)
|
||||||
|
|
||||||
# All
|
# All
|
||||||
mediaItems(
|
mediaItems(
|
||||||
delete: Boolean
|
|
||||||
filter: MediaItemFilter
|
filter: MediaItemFilter
|
||||||
count: Int
|
page: Page
|
||||||
page: Int
|
order: Order
|
||||||
): MediaItemResponse! @hasMinRole(role: User)
|
): MediaItemResponse! @hasMinRole(role: User)
|
||||||
devices(
|
devices(
|
||||||
delete: Boolean
|
|
||||||
filter: DeviceFilter
|
filter: DeviceFilter
|
||||||
count: Int
|
page: Page
|
||||||
page: Int
|
order: Order
|
||||||
): DeviceResponse! @hasMinRole(role: User)
|
): DeviceResponse! @hasMinRole(role: User)
|
||||||
albums(
|
albums(
|
||||||
delete: Boolean
|
|
||||||
filter: AlbumFilter
|
filter: AlbumFilter
|
||||||
count: Int
|
page: Page
|
||||||
page: Int
|
order: Order
|
||||||
): AlbumResponse! @hasMinRole(role: User)
|
): AlbumResponse! @hasMinRole(role: User)
|
||||||
tags(
|
tags(
|
||||||
delete: Boolean
|
|
||||||
filter: TagFilter
|
filter: TagFilter
|
||||||
count: Int
|
page: Page
|
||||||
page: Int
|
order: Order
|
||||||
): TagResponse! @hasMinRole(role: User)
|
): TagResponse! @hasMinRole(role: User)
|
||||||
users(
|
users(
|
||||||
delete: Boolean
|
|
||||||
filter: UserFilter
|
filter: UserFilter
|
||||||
count: Int
|
page: Page
|
||||||
page: Int
|
order: Order
|
||||||
): UserResponse! @hasMinRole(role: Admin) # TODO: Delete All User Content
|
): UserResponse! @hasMinRole(role: Admin)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mutation {
|
type Mutation {
|
||||||
|
@ -21,12 +21,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (r *mutationResolver) CreateMediaItem(ctx context.Context, input model.NewMediaItem) (*model.MediaItem, error) {
|
func (r *mutationResolver) CreateMediaItem(ctx context.Context, input model.NewMediaItem) (*model.MediaItem, error) {
|
||||||
// Get Context
|
// Acquire Context
|
||||||
authContext := ctx.Value("auth").(*model.AuthContext)
|
userID, _, err := getContextIDs(ctx)
|
||||||
accessToken := *authContext.AccessToken
|
if err != nil {
|
||||||
userID, ok := accessToken.Get("sub")
|
return nil, err
|
||||||
if !ok {
|
|
||||||
return nil, errors.New("Upload Failed")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// File header placeholder
|
// File header placeholder
|
||||||
@ -52,7 +50,7 @@ func (r *mutationResolver) CreateMediaItem(ctx context.Context, input model.NewM
|
|||||||
// Derive Folder & File Path
|
// Derive Folder & File Path
|
||||||
mediaItemID := uuid.New().String()
|
mediaItemID := uuid.New().String()
|
||||||
fileName := mediaItemID + fileMime.Extension()
|
fileName := mediaItemID + fileMime.Extension()
|
||||||
folderPath := path.Join("/" + r.Config.DataPath + "/media/" + userID.(string))
|
folderPath := path.Join("/" + r.Config.DataPath + "/media/" + userID)
|
||||||
os.MkdirAll(folderPath, 0700)
|
os.MkdirAll(folderPath, 0700)
|
||||||
filePath := path.Join(folderPath + "/" + fileName)
|
filePath := path.Join(folderPath + "/" + fileName)
|
||||||
|
|
||||||
@ -83,7 +81,7 @@ func (r *mutationResolver) CreateMediaItem(ctx context.Context, input model.NewM
|
|||||||
|
|
||||||
// Add Additional MediaItem Fields
|
// Add Additional MediaItem Fields
|
||||||
mediaItem.ID = mediaItemID
|
mediaItem.ID = mediaItemID
|
||||||
mediaItem.UserID = userID.(string)
|
mediaItem.UserID = userID
|
||||||
mediaItem.IsVideo = isVideo
|
mediaItem.IsVideo = isVideo
|
||||||
mediaItem.FileName = fileName
|
mediaItem.FileName = fileName
|
||||||
mediaItem.OrigName = input.File.Filename
|
mediaItem.OrigName = input.File.Filename
|
||||||
@ -99,20 +97,18 @@ func (r *mutationResolver) CreateMediaItem(ctx context.Context, input model.NewM
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *mutationResolver) CreateAlbum(ctx context.Context, input model.NewAlbum) (*model.Album, error) {
|
func (r *mutationResolver) CreateAlbum(ctx context.Context, input model.NewAlbum) (*model.Album, error) {
|
||||||
// Get Context
|
// Acquire Context
|
||||||
authContext := ctx.Value("auth").(*model.AuthContext)
|
userID, _, err := getContextIDs(ctx)
|
||||||
accessToken := *authContext.AccessToken
|
if err != nil {
|
||||||
userID, ok := accessToken.Get("sub")
|
return nil, err
|
||||||
if !ok {
|
|
||||||
return nil, errors.New("Upload Failed")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
album := &model.Album{
|
album := &model.Album{
|
||||||
Name: input.Name,
|
Name: input.Name,
|
||||||
UserID: userID.(string),
|
UserID: userID,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := r.DB.CreateAlbum(album)
|
err = r.DB.CreateAlbum(album)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -121,20 +117,18 @@ func (r *mutationResolver) CreateAlbum(ctx context.Context, input model.NewAlbum
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *mutationResolver) CreateTag(ctx context.Context, input model.NewTag) (*model.Tag, error) {
|
func (r *mutationResolver) CreateTag(ctx context.Context, input model.NewTag) (*model.Tag, error) {
|
||||||
// Get Context
|
// Acquire Context
|
||||||
authContext := ctx.Value("auth").(*model.AuthContext)
|
userID, _, err := getContextIDs(ctx)
|
||||||
accessToken := *authContext.AccessToken
|
if err != nil {
|
||||||
userID, ok := accessToken.Get("sub")
|
return nil, err
|
||||||
if !ok {
|
|
||||||
return nil, errors.New("Upload Failed")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tag := &model.Tag{
|
tag := &model.Tag{
|
||||||
Name: input.Name,
|
Name: input.Name,
|
||||||
UserID: userID.(string),
|
UserID: userID,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := r.DB.CreateTag(tag)
|
err = r.DB.CreateTag(tag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -162,10 +156,11 @@ func (r *mutationResolver) CreateUser(ctx context.Context, input model.NewUser)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *queryResolver) Login(ctx context.Context, user string, password string, deviceID *string) (*model.AuthResponse, error) {
|
func (r *queryResolver) Login(ctx context.Context, user string, password string, deviceID *string) (*model.AuthResponse, error) {
|
||||||
// Get Context
|
// Acquire Context
|
||||||
authContext := ctx.Value("auth").(*model.AuthContext)
|
resp, req, err := getContextHTTP(ctx)
|
||||||
resp := authContext.AuthResponse
|
if err != nil {
|
||||||
req := authContext.AuthRequest
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// Clear All Cookies By Default
|
// Clear All Cookies By Default
|
||||||
accessCookie := http.Cookie{Name: "AccessToken", Path: "/", HttpOnly: true, MaxAge: -1, Expires: time.Now().Add(-100 * time.Hour)}
|
accessCookie := http.Cookie{Name: "AccessToken", Path: "/", HttpOnly: true, MaxAge: -1, Expires: time.Now().Add(-100 * time.Hour)}
|
||||||
@ -219,9 +214,11 @@ func (r *queryResolver) Login(ctx context.Context, user string, password string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *queryResolver) Logout(ctx context.Context) (*model.AuthResponse, error) {
|
func (r *queryResolver) Logout(ctx context.Context) (*model.AuthResponse, error) {
|
||||||
// Set Cookie From Context
|
// Acquire Context
|
||||||
authContext := ctx.Value("auth").(*model.AuthContext)
|
resp, _, err := getContextHTTP(ctx)
|
||||||
resp := authContext.AuthResponse
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// Clear All Cookies
|
// Clear All Cookies
|
||||||
accessCookie := http.Cookie{Name: "AccessToken", Path: "/", HttpOnly: true, MaxAge: -1, Expires: time.Now().Add(-100 * time.Hour)}
|
accessCookie := http.Cookie{Name: "AccessToken", Path: "/", HttpOnly: true, MaxAge: -1, Expires: time.Now().Add(-100 * time.Hour)}
|
||||||
@ -232,13 +229,11 @@ func (r *queryResolver) Logout(ctx context.Context) (*model.AuthResponse, error)
|
|||||||
return &model.AuthResponse{Result: model.AuthResultSuccess}, nil
|
return &model.AuthResponse{Result: model.AuthResultSuccess}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *queryResolver) MediaItem(ctx context.Context, id string, delete *bool) (*model.MediaItem, error) {
|
func (r *queryResolver) MediaItem(ctx context.Context, id string) (*model.MediaItem, error) {
|
||||||
// Get Context
|
// Acquire Context
|
||||||
authContext := ctx.Value("auth").(*model.AuthContext)
|
userID, _, err := getContextIDs(ctx)
|
||||||
accessToken := *authContext.AccessToken
|
if err != nil {
|
||||||
userID, ok := accessToken.Get("sub")
|
return nil, err
|
||||||
if !ok {
|
|
||||||
return nil, errors.New("Context Error")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mediaItemID, err := uuid.Parse(id)
|
mediaItemID, err := uuid.Parse(id)
|
||||||
@ -246,7 +241,7 @@ func (r *queryResolver) MediaItem(ctx context.Context, id string, delete *bool)
|
|||||||
return nil, errors.New("Invalid ID Format")
|
return nil, errors.New("Invalid ID Format")
|
||||||
}
|
}
|
||||||
|
|
||||||
foundMediaItem := &model.MediaItem{ID: mediaItemID.String(), UserID: userID.(string)}
|
foundMediaItem := &model.MediaItem{ID: mediaItemID.String(), UserID: userID}
|
||||||
count, err := r.DB.MediaItem(foundMediaItem)
|
count, err := r.DB.MediaItem(foundMediaItem)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("DB Error")
|
return nil, errors.New("DB Error")
|
||||||
@ -256,13 +251,11 @@ func (r *queryResolver) MediaItem(ctx context.Context, id string, delete *bool)
|
|||||||
return foundMediaItem, nil
|
return foundMediaItem, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *queryResolver) Device(ctx context.Context, id string, delete *bool) (*model.Device, error) {
|
func (r *queryResolver) Device(ctx context.Context, id string) (*model.Device, error) {
|
||||||
// Get Context
|
// Acquire Context
|
||||||
authContext := ctx.Value("auth").(*model.AuthContext)
|
userID, _, err := getContextIDs(ctx)
|
||||||
accessToken := *authContext.AccessToken
|
if err != nil {
|
||||||
userID, ok := accessToken.Get("sub")
|
return nil, err
|
||||||
if !ok {
|
|
||||||
return nil, errors.New("Context Error")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
deviceID, err := uuid.Parse(id)
|
deviceID, err := uuid.Parse(id)
|
||||||
@ -270,7 +263,7 @@ func (r *queryResolver) Device(ctx context.Context, id string, delete *bool) (*m
|
|||||||
return nil, errors.New("Invalid ID Format")
|
return nil, errors.New("Invalid ID Format")
|
||||||
}
|
}
|
||||||
|
|
||||||
foundDevice := &model.Device{ID: deviceID.String(), UserID: userID.(string)}
|
foundDevice := &model.Device{ID: deviceID.String(), UserID: userID}
|
||||||
count, err := r.DB.Device(foundDevice)
|
count, err := r.DB.Device(foundDevice)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("DB Error")
|
return nil, errors.New("DB Error")
|
||||||
@ -280,13 +273,11 @@ func (r *queryResolver) Device(ctx context.Context, id string, delete *bool) (*m
|
|||||||
return foundDevice, nil
|
return foundDevice, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *queryResolver) Album(ctx context.Context, id string, delete *bool) (*model.Album, error) {
|
func (r *queryResolver) Album(ctx context.Context, id string) (*model.Album, error) {
|
||||||
// Get Context
|
// Acquire Context
|
||||||
authContext := ctx.Value("auth").(*model.AuthContext)
|
userID, _, err := getContextIDs(ctx)
|
||||||
accessToken := *authContext.AccessToken
|
if err != nil {
|
||||||
userID, ok := accessToken.Get("sub")
|
return nil, err
|
||||||
if !ok {
|
|
||||||
return nil, errors.New("Context Error")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
albumID, err := uuid.Parse(id)
|
albumID, err := uuid.Parse(id)
|
||||||
@ -294,7 +285,7 @@ func (r *queryResolver) Album(ctx context.Context, id string, delete *bool) (*mo
|
|||||||
return nil, errors.New("Invalid ID Format")
|
return nil, errors.New("Invalid ID Format")
|
||||||
}
|
}
|
||||||
|
|
||||||
foundAlbum := &model.Album{ID: albumID.String(), UserID: userID.(string)}
|
foundAlbum := &model.Album{ID: albumID.String(), UserID: userID}
|
||||||
count, err := r.DB.Album(foundAlbum)
|
count, err := r.DB.Album(foundAlbum)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("DB Error")
|
return nil, errors.New("DB Error")
|
||||||
@ -304,7 +295,7 @@ func (r *queryResolver) Album(ctx context.Context, id string, delete *bool) (*mo
|
|||||||
return foundAlbum, nil
|
return foundAlbum, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *queryResolver) User(ctx context.Context, id string, delete *bool) (*model.User, error) {
|
func (r *queryResolver) User(ctx context.Context, id string) (*model.User, error) {
|
||||||
userID, err := uuid.Parse(id)
|
userID, err := uuid.Parse(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("Invalid ID Format")
|
return nil, errors.New("Invalid ID Format")
|
||||||
@ -320,13 +311,19 @@ func (r *queryResolver) User(ctx context.Context, id string, delete *bool) (*mod
|
|||||||
return foundUser, nil
|
return foundUser, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *queryResolver) Tag(ctx context.Context, id string, delete *bool) (*model.Tag, error) {
|
func (r *queryResolver) Tag(ctx context.Context, id string) (*model.Tag, error) {
|
||||||
|
// Acquire Context
|
||||||
|
userID, _, err := getContextIDs(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
tagID, err := uuid.Parse(id)
|
tagID, err := uuid.Parse(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("Invalid ID Format")
|
return nil, errors.New("Invalid ID Format")
|
||||||
}
|
}
|
||||||
|
|
||||||
foundTag := &model.Tag{ID: tagID.String()}
|
foundTag := &model.Tag{ID: tagID.String(), UserID: userID}
|
||||||
count, err := r.DB.Tag(foundTag)
|
count, err := r.DB.Tag(foundTag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("DB Error")
|
return nil, errors.New("DB Error")
|
||||||
@ -336,16 +333,14 @@ func (r *queryResolver) Tag(ctx context.Context, id string, delete *bool) (*mode
|
|||||||
return foundTag, nil
|
return foundTag, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *queryResolver) Me(ctx context.Context, delete *bool) (*model.User, error) {
|
func (r *queryResolver) Me(ctx context.Context) (*model.User, error) {
|
||||||
// Get Context
|
// Acquire Context
|
||||||
authContext := ctx.Value("auth").(*model.AuthContext)
|
userID, _, err := getContextIDs(ctx)
|
||||||
accessToken := *authContext.AccessToken
|
if err != nil {
|
||||||
userID, ok := accessToken.Get("sub")
|
return nil, err
|
||||||
if !ok {
|
|
||||||
return nil, errors.New("Context Error")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foundUser := &model.User{ID: userID.(string)}
|
foundUser := &model.User{ID: userID}
|
||||||
count, err := r.DB.User(foundUser)
|
count, err := r.DB.User(foundUser)
|
||||||
if err != nil || count != 1 {
|
if err != nil || count != 1 {
|
||||||
return nil, errors.New("DB Error")
|
return nil, errors.New("DB Error")
|
||||||
@ -353,88 +348,82 @@ func (r *queryResolver) Me(ctx context.Context, delete *bool) (*model.User, erro
|
|||||||
return foundUser, nil
|
return foundUser, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *queryResolver) MediaItems(ctx context.Context, delete *bool, filter *model.MediaItemFilter, count *int, page *int) (*model.MediaItemResponse, error) {
|
func (r *queryResolver) MediaItems(ctx context.Context, filter *model.MediaItemFilter, page *model.Page, order *model.Order) (*model.MediaItemResponse, error) {
|
||||||
resp, totalCount, err := r.DB.MediaItems(filter)
|
// Acquire Context
|
||||||
|
userID, _, err := getContextIDs(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("Context Error")
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, pageResponse, err := r.DB.MediaItems(userID, filter, page, order)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("DB Error")
|
||||||
}
|
}
|
||||||
return &model.MediaItemResponse{
|
return &model.MediaItemResponse{
|
||||||
Data: resp,
|
Data: resp,
|
||||||
PageInfo: &model.PageInfo{
|
Page: &pageResponse,
|
||||||
Count: int(totalCount),
|
|
||||||
Page: 0,
|
|
||||||
Total: int(totalCount),
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *queryResolver) Devices(ctx context.Context, delete *bool, filter *model.DeviceFilter, count *int, page *int) (*model.DeviceResponse, error) {
|
func (r *queryResolver) Devices(ctx context.Context, filter *model.DeviceFilter, page *model.Page, order *model.Order) (*model.DeviceResponse, error) {
|
||||||
// Get Context
|
// Acquire Context
|
||||||
authContext := ctx.Value("auth").(*model.AuthContext)
|
userID, _, err := getContextIDs(ctx)
|
||||||
accessToken := *authContext.AccessToken
|
if err != nil {
|
||||||
userID, ok := accessToken.Get("sub")
|
return nil, err
|
||||||
if !ok {
|
|
||||||
return nil, errors.New("Context Error")
|
|
||||||
}
|
}
|
||||||
_ = userID
|
|
||||||
|
|
||||||
resp, totalCount, err := r.DB.Devices()
|
resp, pageResponse, err := r.DB.Devices(userID, filter, page, order)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("DB Error")
|
return nil, errors.New("DB Error")
|
||||||
}
|
}
|
||||||
return &model.DeviceResponse{
|
return &model.DeviceResponse{
|
||||||
Data: resp,
|
Data: resp,
|
||||||
PageInfo: &model.PageInfo{
|
Page: &pageResponse,
|
||||||
Count: int(totalCount),
|
|
||||||
Page: 0,
|
|
||||||
Total: int(totalCount),
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *queryResolver) Albums(ctx context.Context, delete *bool, filter *model.AlbumFilter, count *int, page *int) (*model.AlbumResponse, error) {
|
func (r *queryResolver) Albums(ctx context.Context, filter *model.AlbumFilter, page *model.Page, order *model.Order) (*model.AlbumResponse, error) {
|
||||||
// TODO: User Specific
|
// Acquire Context
|
||||||
resp, totalCount, err := r.DB.Albums()
|
userID, _, err := getContextIDs(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, pageResponse, err := r.DB.Albums(userID, filter, page, order)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("Context Error")
|
return nil, errors.New("Context Error")
|
||||||
}
|
}
|
||||||
return &model.AlbumResponse{
|
return &model.AlbumResponse{
|
||||||
Data: resp,
|
Data: resp,
|
||||||
PageInfo: &model.PageInfo{
|
Page: &pageResponse,
|
||||||
Count: int(totalCount),
|
|
||||||
Page: 0,
|
|
||||||
Total: int(totalCount),
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *queryResolver) Tags(ctx context.Context, delete *bool, filter *model.TagFilter, count *int, page *int) (*model.TagResponse, error) {
|
func (r *queryResolver) Tags(ctx context.Context, filter *model.TagFilter, page *model.Page, order *model.Order) (*model.TagResponse, error) {
|
||||||
resp, totalCount, err := r.DB.Tags()
|
// Acquire Context
|
||||||
|
userID, _, err := getContextIDs(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, pageResponse, err := r.DB.Tags(userID, filter, page, order)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("Context Error")
|
return nil, errors.New("Context Error")
|
||||||
}
|
}
|
||||||
return &model.TagResponse{
|
return &model.TagResponse{
|
||||||
Data: resp,
|
Data: resp,
|
||||||
PageInfo: &model.PageInfo{
|
Page: &pageResponse,
|
||||||
Count: int(totalCount),
|
|
||||||
Page: 0,
|
|
||||||
Total: int(totalCount),
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *queryResolver) Users(ctx context.Context, delete *bool, filter *model.UserFilter, count *int, page *int) (*model.UserResponse, error) {
|
func (r *queryResolver) Users(ctx context.Context, filter *model.UserFilter, page *model.Page, order *model.Order) (*model.UserResponse, error) {
|
||||||
resp, totalCount, err := r.DB.Users()
|
resp, pageResponse, err := r.DB.Users(filter, page, order)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("Context Error")
|
return nil, errors.New("Context Error")
|
||||||
}
|
}
|
||||||
return &model.UserResponse{
|
return &model.UserResponse{
|
||||||
Data: resp,
|
Data: resp,
|
||||||
PageInfo: &model.PageInfo{
|
Page: &pageResponse,
|
||||||
Count: int(totalCount),
|
|
||||||
Page: 0,
|
|
||||||
Total: int(totalCount),
|
|
||||||
},
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package db
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
|
||||||
"reichard.io/imagini/graph/model"
|
"reichard.io/imagini/graph/model"
|
||||||
)
|
)
|
||||||
@ -18,11 +19,17 @@ func (dbm *DBManager) Album(album *model.Album) (int64, error) {
|
|||||||
return count, err
|
return count, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dbm *DBManager) Albums() ([]*model.Album, int64, error) {
|
func (dbm *DBManager) Albums(userID string, filters *model.AlbumFilter, page *model.Page, order *model.Order) ([]*model.Album, model.PageResponse, error) {
|
||||||
|
// Initial User Filter
|
||||||
|
tx := dbm.db.Session(&gorm.Session{}).Model(&model.Album{}).Where("user_id == ?", userID)
|
||||||
|
|
||||||
|
// Dynamically Generate Base Query
|
||||||
|
tx, pageResponse := dbm.generateBaseQuery(tx, filters, page, order)
|
||||||
|
|
||||||
|
// Acquire Results
|
||||||
var foundAlbums []*model.Album
|
var foundAlbums []*model.Album
|
||||||
var count int64
|
err := tx.Find(&foundAlbums).Error
|
||||||
err := dbm.db.Find(&foundAlbums).Count(&count).Error
|
return foundAlbums, pageResponse, err
|
||||||
return foundAlbums, count, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dbm *DBManager) DeleteAlbum(album *model.Album) error {
|
func (dbm *DBManager) DeleteAlbum(album *model.Album) error {
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
package db
|
package db
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"path"
|
"path"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/iancoleman/strcase"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
// "gorm.io/gorm/logger"
|
// "gorm.io/gorm/logger"
|
||||||
"gorm.io/driver/sqlite"
|
"gorm.io/driver/sqlite"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
@ -30,6 +32,7 @@ func NewMgr(c *config.Config) *DBManager {
|
|||||||
if c.DBType == "SQLite" {
|
if c.DBType == "SQLite" {
|
||||||
dbLocation := path.Join(c.ConfigPath, "imagini.db")
|
dbLocation := path.Join(c.ConfigPath, "imagini.db")
|
||||||
dbm.db, _ = gorm.Open(sqlite.Open(dbLocation), gormConfig)
|
dbm.db, _ = gorm.Open(sqlite.Open(dbLocation), gormConfig)
|
||||||
|
dbm.db = dbm.db.Debug()
|
||||||
} else {
|
} else {
|
||||||
log.Fatal("Unsupported Database")
|
log.Fatal("Unsupported Database")
|
||||||
}
|
}
|
||||||
@ -48,28 +51,9 @@ func NewMgr(c *config.Config) *DBManager {
|
|||||||
dbm.bootstrapDatabase()
|
dbm.bootstrapDatabase()
|
||||||
}
|
}
|
||||||
|
|
||||||
dbm.testFeatures()
|
|
||||||
|
|
||||||
return dbm
|
return dbm
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dbm *DBManager) testFeatures() {
|
|
||||||
|
|
||||||
// Get Devices By UserID
|
|
||||||
// var myDevices []model.Device
|
|
||||||
// dbm.db.Debug().Where(&model.Device{UserID: "97589354-cd42-40e2-bc5e-7ba6badf89fa"}).Find(&myDevices)
|
|
||||||
// fmt.Printf("Devices: %+v\n", myDevices)
|
|
||||||
|
|
||||||
// Get User by DeviceID
|
|
||||||
// var myUser []model.User
|
|
||||||
// dbm.db.Debug().Model(&model.User{}).
|
|
||||||
// Select("users.*").
|
|
||||||
// Joins("left join devices on users.id = devices.user_id").
|
|
||||||
// Where("devices.id = ?", "4e9aa851-f25b-4330-91dc-c0f975e56fa1").
|
|
||||||
// Find(&myUser)
|
|
||||||
// fmt.Printf("User: %+v\n", myUser)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dbm *DBManager) bootstrapDatabase() {
|
func (dbm *DBManager) bootstrapDatabase() {
|
||||||
log.Info("[query] Bootstrapping database.")
|
log.Info("[query] Bootstrapping database.")
|
||||||
|
|
||||||
@ -88,46 +72,84 @@ func (dbm *DBManager) bootstrapDatabase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
func (dbm *DBManager) generateBaseQuery(tx *gorm.DB, filter interface{}, page *model.Page, order *model.Order) (*gorm.DB, model.PageResponse) {
|
||||||
func (dbm *DBManager) QueryBuilder(dest interface{}, params []byte) (int64, error) {
|
tx = dbm.generateFilter(tx, filter)
|
||||||
// TODO:
|
tx = dbm.generateOrder(tx, order, filter)
|
||||||
// - Where Filters
|
tx, pageResponse := dbm.generatePage(tx, page)
|
||||||
// - Sort Filters
|
return tx, pageResponse
|
||||||
// - Paging Filters
|
}
|
||||||
|
|
||||||
objType := fmt.Sprintf("%T", dest)
|
func (dbm *DBManager) generateOrder(tx *gorm.DB, order *model.Order, filter interface{}) *gorm.DB {
|
||||||
if objType == "*[]model.MediaItem" {
|
// Set Defaults
|
||||||
// TODO: Validate MediaItem Type
|
orderBy := "created_at"
|
||||||
} else {
|
orderDirection := model.OrderDirectionDesc
|
||||||
// Return Error
|
|
||||||
return 0, errors.New("Invalid type")
|
if order == nil {
|
||||||
|
order = &model.Order{
|
||||||
|
By: &orderBy,
|
||||||
|
Direction: &orderDirection,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var count int64
|
if order.By == nil {
|
||||||
err := dbm.db.Find(dest).Count(&count).Error
|
order.By = &orderBy
|
||||||
return count, err
|
}
|
||||||
|
|
||||||
// Paging:
|
if order.Direction == nil {
|
||||||
// - Regular Pagination:
|
order.Direction = &orderDirection
|
||||||
// - /api/v1/MediaItems?page[limit]=50&page=2
|
}
|
||||||
// - Meta Count Only
|
|
||||||
// - /api/v1/MediaItems?page[limit]=0
|
|
||||||
|
|
||||||
// Sorting:
|
// Get Possible Values
|
||||||
// - Ascending Sort:
|
ptr := reflect.New(reflect.TypeOf(filter).Elem())
|
||||||
// - /api/v1/MediaItems?sort=created_at
|
v := reflect.Indirect(ptr)
|
||||||
// - Descending Sort:
|
|
||||||
// - /api/v1/MediaItems?sort=-created_at
|
|
||||||
|
|
||||||
// Filters:
|
isValid := false
|
||||||
// - Greater Than / Less Than (created_at, updated_at, exif_date)
|
for i := 0; i < v.NumField(); i++ {
|
||||||
// - /api/v1/MediaItems?filter[created_at]>=2020-01-01&filter[created_at]<=2021-01-01
|
fieldName := v.Type().Field(i).Name
|
||||||
// - Long / Lat Range (latitude, longitude)
|
if strcase.ToSnake(*order.By) == strcase.ToSnake(fieldName) {
|
||||||
// - /api/v1/MediaItems?filter[latitude]>=71.1827&filter[latitude]<=72.0000&filter[longitude]>=100.000&filter[longitude]<=101.0000
|
isValid = true
|
||||||
// - Image / Video (media_type)
|
break
|
||||||
// - /api/v1/MediaItems?filter[media_type]=Image
|
}
|
||||||
// - Tags (tags)
|
}
|
||||||
// - /api/v1/MediaItems?filter[tags]=id1,id2,id3
|
|
||||||
// - Albums (albums)
|
if isValid {
|
||||||
// - /api/v1/MediaItems?filter[albums]=id1
|
tx = tx.Order(fmt.Sprintf("%s %s", strcase.ToSnake(*order.By), order.Direction.String()))
|
||||||
|
}
|
||||||
|
|
||||||
|
return tx
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dbm *DBManager) generatePage(tx *gorm.DB, page *model.Page) (*gorm.DB, model.PageResponse) {
|
||||||
|
// Set Defaults
|
||||||
|
var count int64
|
||||||
|
pageSize := 50
|
||||||
|
pageNum := 1
|
||||||
|
|
||||||
|
if page == nil {
|
||||||
|
page = &model.Page{
|
||||||
|
Size: &pageSize,
|
||||||
|
Page: &pageNum,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if page.Size == nil {
|
||||||
|
page.Size = &pageSize
|
||||||
|
}
|
||||||
|
|
||||||
|
if page.Page == nil {
|
||||||
|
page.Page = &pageNum
|
||||||
|
}
|
||||||
|
|
||||||
|
// Acquire Counts Before Pagination
|
||||||
|
tx.Count(&count)
|
||||||
|
|
||||||
|
// Calculate Offset
|
||||||
|
calculatedOffset := (*page.Page - 1) * *page.Size
|
||||||
|
tx = tx.Limit(*page.Size).Offset(calculatedOffset)
|
||||||
|
|
||||||
|
return tx, model.PageResponse{
|
||||||
|
Page: *page.Page,
|
||||||
|
Size: *page.Size,
|
||||||
|
Total: int(count),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package db
|
|||||||
import (
|
import (
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
|
||||||
"reichard.io/imagini/graph/model"
|
"reichard.io/imagini/graph/model"
|
||||||
)
|
)
|
||||||
@ -21,11 +22,17 @@ func (dbm *DBManager) Device(device *model.Device) (int64, error) {
|
|||||||
return count, err
|
return count, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dbm *DBManager) Devices() ([]*model.Device, int64, error) {
|
func (dbm *DBManager) Devices(userID string, filters *model.DeviceFilter, page *model.Page, order *model.Order) ([]*model.Device, model.PageResponse, error) {
|
||||||
|
// Initial User Filter
|
||||||
|
tx := dbm.db.Session(&gorm.Session{}).Model(&model.Device{}).Where("user_id == ?", userID)
|
||||||
|
|
||||||
|
// Dynamically Generate Base Query
|
||||||
|
tx, pageResponse := dbm.generateBaseQuery(tx, filters, page, order)
|
||||||
|
|
||||||
|
// Acquire Results
|
||||||
var foundDevices []*model.Device
|
var foundDevices []*model.Device
|
||||||
var count int64
|
err := tx.Find(&foundDevices).Error
|
||||||
err := dbm.db.Find(&foundDevices).Count(&count).Error
|
return foundDevices, pageResponse, err
|
||||||
return foundDevices, count, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dbm *DBManager) DeleteDevice(user *model.Device) error {
|
func (dbm *DBManager) DeleteDevice(user *model.Device) error {
|
||||||
|
@ -10,10 +10,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Generic function used to generate filters for the DB
|
// Generic function used to generate filters for the DB
|
||||||
func (dbm *DBManager) generateFilters(filter interface{}) (*gorm.DB, error) {
|
func (dbm *DBManager) generateFilter(tx *gorm.DB, filter interface{}) *gorm.DB {
|
||||||
tx := dbm.db.Session(&gorm.Session{}).Debug()
|
ptr := reflect.ValueOf(filter)
|
||||||
|
v := reflect.Indirect(ptr)
|
||||||
|
|
||||||
v := reflect.ValueOf(filter)
|
if v == reflect.ValueOf(nil) {
|
||||||
|
return tx
|
||||||
|
}
|
||||||
|
|
||||||
for i := 0; i < v.NumField(); i++ {
|
for i := 0; i < v.NumField(); i++ {
|
||||||
fieldName := strcase.ToSnake(v.Type().Field(i).Name)
|
fieldName := strcase.ToSnake(v.Type().Field(i).Name)
|
||||||
@ -45,7 +48,7 @@ func (dbm *DBManager) generateFilters(filter interface{}) (*gorm.DB, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tx, nil
|
return tx
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateStringFilter(tx *gorm.DB, fieldName string, filter *model.StringFilter) *gorm.DB {
|
func generateStringFilter(tx *gorm.DB, fieldName string, filter *model.StringFilter) *gorm.DB {
|
||||||
|
@ -2,6 +2,7 @@ package db
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
|
||||||
"reichard.io/imagini/graph/model"
|
"reichard.io/imagini/graph/model"
|
||||||
)
|
)
|
||||||
@ -18,14 +19,16 @@ func (dbm *DBManager) MediaItem(mediaItem *model.MediaItem) (int64, error) {
|
|||||||
return count, err
|
return count, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dbm *DBManager) MediaItems(filters *model.MediaItemFilter) ([]*model.MediaItem, int64, error) {
|
// UserID, Filters, Sort, Page, Delete
|
||||||
// Perform Filters
|
func (dbm *DBManager) MediaItems(userID string, filters *model.MediaItemFilter, page *model.Page, order *model.Order) ([]*model.MediaItem, model.PageResponse, error) {
|
||||||
tx, err := dbm.generateFilters(*filters)
|
// Initial User Filter
|
||||||
if err != nil {
|
tx := dbm.db.Session(&gorm.Session{}).Model(&model.MediaItem{}).Where("user_id == ?", userID)
|
||||||
return nil, 0, err
|
|
||||||
}
|
// Dynamically Generate Base Query
|
||||||
|
tx, pageResponse := dbm.generateBaseQuery(tx, filters, page, order)
|
||||||
|
|
||||||
|
// Acquire Results
|
||||||
var mediaItems []*model.MediaItem
|
var mediaItems []*model.MediaItem
|
||||||
var count int64
|
err := tx.Find(&mediaItems).Error
|
||||||
err = tx.Find(&mediaItems).Count(&count).Error
|
return mediaItems, pageResponse, err
|
||||||
return mediaItems, count, err
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package db
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
|
||||||
"reichard.io/imagini/graph/model"
|
"reichard.io/imagini/graph/model"
|
||||||
)
|
)
|
||||||
@ -18,11 +19,17 @@ func (dbm *DBManager) Tag(tag *model.Tag) (int64, error) {
|
|||||||
return count, err
|
return count, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dbm *DBManager) Tags() ([]*model.Tag, int64, error) {
|
func (dbm *DBManager) Tags(userID string, filters *model.TagFilter, page *model.Page, order *model.Order) ([]*model.Tag, model.PageResponse, error) {
|
||||||
|
// Initial User Filter
|
||||||
|
tx := dbm.db.Session(&gorm.Session{}).Model(&model.Tag{}).Where("user_id == ?", userID)
|
||||||
|
|
||||||
|
// Dynamically Generate Base Query
|
||||||
|
tx, pageResponse := dbm.generateBaseQuery(tx, filters, page, order)
|
||||||
|
|
||||||
|
// Acquire Results
|
||||||
var foundTags []*model.Tag
|
var foundTags []*model.Tag
|
||||||
var count int64
|
err := tx.Find(&foundTags).Error
|
||||||
err := dbm.db.Find(&foundTags).Count(&count).Error
|
return foundTags, pageResponse, err
|
||||||
return foundTags, count, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dbm *DBManager) DeleteTag(tag *model.Tag) error {
|
func (dbm *DBManager) DeleteTag(tag *model.Tag) error {
|
||||||
|
@ -3,6 +3,7 @@ package db
|
|||||||
import (
|
import (
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
|
||||||
"reichard.io/imagini/graph/model"
|
"reichard.io/imagini/graph/model"
|
||||||
)
|
)
|
||||||
@ -25,11 +26,17 @@ func (dbm *DBManager) User(user *model.User) (int64, error) {
|
|||||||
return count, err
|
return count, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dbm *DBManager) Users() ([]*model.User, int64, error) {
|
func (dbm *DBManager) Users(filters *model.UserFilter, page *model.Page, order *model.Order) ([]*model.User, model.PageResponse, error) {
|
||||||
|
// Initial User Filter
|
||||||
|
tx := dbm.db.Session(&gorm.Session{}).Model(&model.Tag{})
|
||||||
|
|
||||||
|
// Dynamically Generate Base Query
|
||||||
|
tx, pageResponse := dbm.generateBaseQuery(tx, filters, page, order)
|
||||||
|
|
||||||
|
// Acquire Results
|
||||||
var foundUsers []*model.User
|
var foundUsers []*model.User
|
||||||
var count int64
|
err := tx.Find(&foundUsers).Error
|
||||||
err := dbm.db.Find(&foundUsers).Count(&count).Error
|
return foundUsers, pageResponse, err
|
||||||
return foundUsers, count, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dbm *DBManager) DeleteUser(user model.User) error {
|
func (dbm *DBManager) DeleteUser(user model.User) error {
|
||||||
|
Reference in New Issue
Block a user