Further work on shares
This commit is contained in:
parent
687b4f4f7f
commit
0f7f703982
|
@ -69,6 +69,7 @@ type ComplexityRoot struct {
|
|||
|
||||
Mutation struct {
|
||||
AuthorizeUser func(childComplexity int, username string, password string) int
|
||||
DeleteShareToken func(childComplexity int, token string) int
|
||||
InitialSetupWizard func(childComplexity int, username string, password string, rootPath string) int
|
||||
RegisterUser func(childComplexity int, username string, password string, rootPath string) int
|
||||
ScanAll func(childComplexity int) int
|
||||
|
@ -170,6 +171,7 @@ type MutationResolver interface {
|
|||
ScanUser(ctx context.Context, userID int) (*models.ScannerResult, error)
|
||||
ShareAlbum(ctx context.Context, albumID int, expire *time.Time, password *string) (*models.ShareToken, error)
|
||||
SharePhoto(ctx context.Context, photoID int, expire *time.Time, password *string) (*models.ShareToken, error)
|
||||
DeleteShareToken(ctx context.Context, token string) (*models.ShareToken, error)
|
||||
}
|
||||
type PhotoResolver interface {
|
||||
Thumbnail(ctx context.Context, obj *models.Photo) (*models.PhotoURL, error)
|
||||
|
@ -317,6 +319,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
|||
|
||||
return e.complexity.Mutation.AuthorizeUser(childComplexity, args["username"].(string), args["password"].(string)), true
|
||||
|
||||
case "Mutation.deleteShareToken":
|
||||
if e.complexity.Mutation.DeleteShareToken == nil {
|
||||
break
|
||||
}
|
||||
|
||||
args, err := ec.field_Mutation_deleteShareToken_args(context.TODO(), rawArgs)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
return e.complexity.Mutation.DeleteShareToken(childComplexity, args["token"].(string)), true
|
||||
|
||||
case "Mutation.initialSetupWizard":
|
||||
if e.complexity.Mutation.InitialSetupWizard == nil {
|
||||
break
|
||||
|
@ -875,6 +889,8 @@ type Mutation {
|
|||
shareAlbum(albumId: Int!, expire: Time, password: String): ShareToken
|
||||
"Generate share token for photo"
|
||||
sharePhoto(photoId: Int!, expire: Time, password: String): ShareToken
|
||||
"Delete a share token by it's token value"
|
||||
deleteShareToken(token: String!): ShareToken
|
||||
}
|
||||
|
||||
type AuthorizeResult {
|
||||
|
@ -1050,6 +1066,20 @@ func (ec *executionContext) field_Mutation_authorizeUser_args(ctx context.Contex
|
|||
return args, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) field_Mutation_deleteShareToken_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
||||
var err error
|
||||
args := map[string]interface{}{}
|
||||
var arg0 string
|
||||
if tmp, ok := rawArgs["token"]; ok {
|
||||
arg0, err = ec.unmarshalNString2string(ctx, tmp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
args["token"] = arg0
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) field_Mutation_initialSetupWizard_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
||||
var err error
|
||||
args := map[string]interface{}{}
|
||||
|
@ -2064,6 +2094,47 @@ func (ec *executionContext) _Mutation_sharePhoto(ctx context.Context, field grap
|
|||
return ec.marshalOShareToken2ᚖgithubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐShareToken(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Mutation_deleteShareToken(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||
ctx = ec.Tracer.StartFieldExecution(ctx, field)
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
ec.Tracer.EndFieldExecution(ctx)
|
||||
}()
|
||||
rctx := &graphql.ResolverContext{
|
||||
Object: "Mutation",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: true,
|
||||
}
|
||||
ctx = graphql.WithResolverContext(ctx, rctx)
|
||||
rawArgs := field.ArgumentMap(ec.Variables)
|
||||
args, err := ec.field_Mutation_deleteShareToken_args(ctx, rawArgs)
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
rctx.Args = args
|
||||
ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return ec.resolvers.Mutation().DeleteShareToken(rctx, args["token"].(string))
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*models.ShareToken)
|
||||
rctx.Result = res
|
||||
ctx = ec.Tracer.StartFieldChildExecution(ctx)
|
||||
return ec.marshalOShareToken2ᚖgithubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐShareToken(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Photo_id(ctx context.Context, field graphql.CollectedField, obj *models.Photo) (ret graphql.Marshaler) {
|
||||
ctx = ec.Tracer.StartFieldExecution(ctx, field)
|
||||
defer func() {
|
||||
|
@ -5328,6 +5399,8 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet)
|
|||
out.Values[i] = ec._Mutation_shareAlbum(ctx, field)
|
||||
case "sharePhoto":
|
||||
out.Values[i] = ec._Mutation_sharePhoto(ctx, field)
|
||||
case "deleteShareToken":
|
||||
out.Values[i] = ec._Mutation_deleteShareToken(ctx, field)
|
||||
default:
|
||||
panic("unknown field " + strconv.Quote(field.Name))
|
||||
}
|
||||
|
|
|
@ -58,9 +58,12 @@ func (r *Resolver) Photo() api.PhotoResolver {
|
|||
}
|
||||
|
||||
func (r *photoResolver) Shares(ctx context.Context, obj *models.Photo) ([]*models.ShareToken, error) {
|
||||
log.Println("Photo: shares not implemented")
|
||||
shares := make([]*models.ShareToken, 0)
|
||||
return shares, nil
|
||||
rows, err := r.Database.Query("SELECT * FROM share_token WHERE photo_id = ?", obj.PhotoID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return models.NewShareTokensFromRows(rows)
|
||||
}
|
||||
|
||||
func (r *photoResolver) Downloads(ctx context.Context, obj *models.Photo) ([]*models.PhotoDownload, error) {
|
||||
|
|
|
@ -3,7 +3,7 @@ package resolvers
|
|||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"log"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
api "github.com/viktorstrate/photoview/api/graphql"
|
||||
|
@ -60,7 +60,7 @@ func (r *queryResolver) ShareToken(ctx context.Context, token string, password *
|
|||
result, err := models.NewShareTokenFromRow(row)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, nil
|
||||
return nil, errors.New("share not found")
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -69,13 +69,6 @@ func (r *queryResolver) ShareToken(ctx context.Context, token string, password *
|
|||
return result, nil
|
||||
}
|
||||
|
||||
func (r *queryResolver) PhotoShares(ctx context.Context, token string, password *string) ([]*models.ShareToken, error) {
|
||||
log.Println("Query PhotoShares: not implemented")
|
||||
|
||||
tokens := make([]*models.ShareToken, 0)
|
||||
return tokens, nil
|
||||
}
|
||||
|
||||
func (r *mutationResolver) ShareAlbum(ctx context.Context, albumID int, expire *time.Time, password *string) (*models.ShareToken, error) {
|
||||
user := auth.UserFromContext(ctx)
|
||||
if user == nil {
|
||||
|
@ -124,5 +117,73 @@ func (r *mutationResolver) ShareAlbum(ctx context.Context, albumID int, expire *
|
|||
}
|
||||
|
||||
func (r *mutationResolver) SharePhoto(ctx context.Context, photoID int, expire *time.Time, password *string) (*models.ShareToken, error) {
|
||||
panic("not implemented")
|
||||
user := auth.UserFromContext(ctx)
|
||||
if user == nil {
|
||||
return nil, auth.ErrUnauthorized
|
||||
}
|
||||
|
||||
rows, err := r.Database.Query("SELECT owner_id FROM album, photo WHERE photo.photo_id = ? AND photo.album_id = album.album_id AND album.owner_id = ?", photoID, user.UserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if rows.Next() == false {
|
||||
return nil, auth.ErrUnauthorized
|
||||
}
|
||||
rows.Close()
|
||||
|
||||
var hashed_password *string = nil
|
||||
if password != nil {
|
||||
hashedPassBytes, err := bcrypt.GenerateFromPassword([]byte(*password), 12)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hashed_str := string(hashedPassBytes)
|
||||
hashed_password = &hashed_str
|
||||
}
|
||||
|
||||
token := utils.GenerateToken()
|
||||
res, err := r.Database.Exec("INSERT INTO share_token (value, owner_id, expire, password, photo_id) VALUES (?, ?, ?, ?, ?)", token, user.UserID, expire, hashed_password, photoID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
token_id, err := res.LastInsertId()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &models.ShareToken{
|
||||
TokenID: int(token_id),
|
||||
Value: token,
|
||||
OwnerID: user.UserID,
|
||||
Expire: expire,
|
||||
Password: password,
|
||||
AlbumID: nil,
|
||||
PhotoID: &photoID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *mutationResolver) DeleteShareToken(ctx context.Context, tokenValue string) (*models.ShareToken, error) {
|
||||
user := auth.UserFromContext(ctx)
|
||||
if user == nil {
|
||||
return nil, auth.ErrUnauthorized
|
||||
}
|
||||
|
||||
row := r.Database.QueryRow(`
|
||||
SELECT share_token.* FROM share_token, user WHERE
|
||||
share_token.value = ? AND
|
||||
share_token.owner_id = user.user_id AND
|
||||
(user.user_id = ? OR user.admin = TRUE)
|
||||
`, tokenValue, user.UserID)
|
||||
|
||||
token, err := models.NewShareTokenFromRow(row)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err := r.Database.Exec("DELETE FROM share_token WHERE token_id = ?", token.TokenID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return token, nil
|
||||
}
|
||||
|
|
|
@ -61,6 +61,8 @@ type Mutation {
|
|||
shareAlbum(albumId: Int!, expire: Time, password: String): ShareToken
|
||||
"Generate share token for photo"
|
||||
sharePhoto(photoId: Int!, expire: Time, password: String): ShareToken
|
||||
"Delete a share token by it's token value"
|
||||
deleteShareToken(token: String!): ShareToken
|
||||
}
|
||||
|
||||
type AuthorizeResult {
|
||||
|
|
|
@ -20,7 +20,7 @@ const AlbumSharePage = ({ photo }) => {
|
|||
<>
|
||||
<h1>{photo.title}</h1>
|
||||
<DisplayPhoto
|
||||
src={photo.original.url}
|
||||
src={photo.highRes.url}
|
||||
onLoad={() => {
|
||||
updateSidebar(<PhotoSidebar photo={photo} hidePreview />)
|
||||
}}
|
||||
|
|
|
@ -44,7 +44,7 @@ const addAlbumShareMutation = gql`
|
|||
`
|
||||
|
||||
const deleteShareMutation = gql`
|
||||
mutation sidebareDeleteShare($token: ID!) {
|
||||
mutation sidebareDeleteShare($token: String!) {
|
||||
deleteShareToken(token: $token) {
|
||||
token
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue