Files
Quic/api/graphql/resolvers/share_token.go
T

168 lines
5.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package resolvers
// This file will be automatically regenerated based on the schema, any resolver
// implementations
// will be copied through when generating and any unknown code will be moved to the end.
// Code generated by github.com/99designs/gqlgen version v0.17.90
import (
"context"
"errors"
"fmt"
"time"
api "github.com/photoview/photoview/api/graphql"
"github.com/photoview/photoview/api/graphql/auth"
"github.com/photoview/photoview/api/graphql/models"
"github.com/photoview/photoview/api/graphql/models/actions"
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
// ShareAlbum is the resolver for the shareAlbum field.
func (r *mutationResolver) ShareAlbum(ctx context.Context, albumID int, expire *time.Time, password *string) (*models.ShareToken, error) {
user := auth.UserFromContext(ctx)
if user == nil {
return nil, auth.ErrUnauthorized
}
return actions.AddAlbumShare(r.DB(ctx), user, albumID, expire, password)
}
// ShareMedia is the resolver for the shareMedia field.
func (r *mutationResolver) ShareMedia(ctx context.Context, mediaID int, expire *time.Time, password *string) (*models.ShareToken, error) {
user := auth.UserFromContext(ctx)
if user == nil {
return nil, auth.ErrUnauthorized
}
return actions.AddMediaShare(r.DB(ctx), user, mediaID, expire, password)
}
// DeleteShareToken is the resolver for the deleteShareToken field.
func (r *mutationResolver) DeleteShareToken(ctx context.Context, token string) (*models.ShareToken, error) {
user := auth.UserFromContext(ctx)
if user == nil {
return nil, auth.ErrUnauthorized
}
return actions.DeleteShareToken(r.DB(ctx), user.ID, token)
}
// ProtectShareToken is the resolver for the protectShareToken field.
func (r *mutationResolver) ProtectShareToken(ctx context.Context, token string, password *string) (*models.ShareToken, error) {
user := auth.UserFromContext(ctx)
if user == nil {
return nil, auth.ErrUnauthorized
}
return actions.ProtectShareToken(r.DB(ctx), user.ID, token, password)
}
// SetExpireShareToken is the resolver for the setExpireShareToken field.
func (r *mutationResolver) SetExpireShareToken(ctx context.Context, token string, expire *time.Time) (*models.ShareToken, error) {
user := auth.UserFromContext(ctx)
if user == nil {
return nil, auth.ErrUnauthorized
}
return actions.SetExpireShareToken(r.DB(ctx), user.ID, token, expire)
}
// ShareToken is the resolver for the shareToken field.
func (r *queryResolver) ShareToken(ctx context.Context, credentials models.ShareTokenCredentials) (*models.ShareToken, error) {
var token models.ShareToken
if err := r.DB(ctx).Preload(clause.Associations).Where("value = ?", credentials.Token).First(&token).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, errors.New("share not found")
} else {
return nil, fmt.Errorf("failed to get share token from database: %w", err)
}
}
now := time.Now()
fakeTime := time.Date(
now.Year(),
now.Month(),
now.Day(),
now.Hour(),
now.Minute(),
now.Second(),
0,
time.UTC,
)
if token.Expire != nil && fakeTime.After(*token.Expire) {
return nil, errors.New("share expired")
}
if token.Password != nil {
if err := bcrypt.CompareHashAndPassword([]byte(*token.Password), []byte(*credentials.Password)); err != nil {
if err == bcrypt.ErrMismatchedHashAndPassword {
return nil, errors.New("unauthorized")
} else {
return nil, fmt.Errorf("failed to compare token password hashes: %w", err)
}
}
}
return &token, nil
}
// ShareTokenValidatePassword is the resolver for the shareTokenValidatePassword field.
func (r *queryResolver) ShareTokenValidatePassword(ctx context.Context, credentials models.ShareTokenCredentials) (bool, error) {
var token models.ShareToken
if err := r.DB(ctx).Where("value = ?", credentials.Token).First(&token).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return false, errors.New("share not found")
} else {
return false, fmt.Errorf("failed to get share token from database: %w", err)
}
}
now := time.Now()
fakeTime := time.Date(
now.Year(),
now.Month(),
now.Day(),
now.Hour(),
now.Minute(),
now.Second(),
0,
time.UTC,
)
//Assume the client’s local time is UTC, without applying any timezone conversion.
if token.Expire != nil && fakeTime.After(*token.Expire) {
return false, errors.New("share expired")
}
if token.Password == nil {
return true, nil
}
if credentials.Password == nil {
return false, nil
}
if err := bcrypt.CompareHashAndPassword([]byte(*token.Password), []byte(*credentials.Password)); err != nil {
if err == bcrypt.ErrMismatchedHashAndPassword {
return false, nil
} else {
return false, fmt.Errorf("could not compare token password hashes: %w", err)
}
}
return true, nil
}
// HasPassword is the resolver for the hasPassword field.
func (r *shareTokenResolver) HasPassword(ctx context.Context, obj *models.ShareToken) (bool, error) {
hasPassword := obj.Password != nil
return hasPassword, nil
}
// ShareToken returns api.ShareTokenResolver implementation.
func (r *Resolver) ShareToken() api.ShareTokenResolver { return &shareTokenResolver{r} }
type shareTokenResolver struct{ *Resolver }