Detect if share token is password protected
This commit is contained in:
parent
f6f6eb8bfa
commit
79be996985
|
@ -137,15 +137,16 @@ type ComplexityRoot struct {
|
|||
}
|
||||
|
||||
Query struct {
|
||||
Album func(childComplexity int, id int) int
|
||||
MyAlbums func(childComplexity int, filter *models.Filter, onlyRoot *bool, showEmpty *bool) int
|
||||
MyPhotos func(childComplexity int, filter *models.Filter) int
|
||||
MyUser func(childComplexity int) int
|
||||
Photo func(childComplexity int, id int) int
|
||||
Search func(childComplexity int, query string, limitPhotos *int, limitAlbums *int) int
|
||||
ShareToken func(childComplexity int, token string, password *string) int
|
||||
SiteInfo func(childComplexity int) int
|
||||
User func(childComplexity int, filter *models.Filter) int
|
||||
Album func(childComplexity int, id int) int
|
||||
MyAlbums func(childComplexity int, filter *models.Filter, onlyRoot *bool, showEmpty *bool) int
|
||||
MyPhotos func(childComplexity int, filter *models.Filter) int
|
||||
MyUser func(childComplexity int) int
|
||||
Photo func(childComplexity int, id int) int
|
||||
Search func(childComplexity int, query string, limitPhotos *int, limitAlbums *int) int
|
||||
ShareToken func(childComplexity int, token string, password *string) int
|
||||
ShareTokenRequiresPassword func(childComplexity int, token string) int
|
||||
SiteInfo func(childComplexity int) int
|
||||
User func(childComplexity int, filter *models.Filter) int
|
||||
}
|
||||
|
||||
ScannerResult struct {
|
||||
|
@ -228,6 +229,7 @@ type QueryResolver interface {
|
|||
MyPhotos(ctx context.Context, filter *models.Filter) ([]*models.Photo, error)
|
||||
Photo(ctx context.Context, id int) (*models.Photo, error)
|
||||
ShareToken(ctx context.Context, token string, password *string) (*models.ShareToken, error)
|
||||
ShareTokenRequiresPassword(ctx context.Context, token string) (bool, error)
|
||||
Search(ctx context.Context, query string, limitPhotos *int, limitAlbums *int) (*models.SearchResult, error)
|
||||
}
|
||||
type ShareTokenResolver interface {
|
||||
|
@ -827,6 +829,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
|||
|
||||
return e.complexity.Query.ShareToken(childComplexity, args["token"].(string), args["password"].(*string)), true
|
||||
|
||||
case "Query.shareTokenRequiresPassword":
|
||||
if e.complexity.Query.ShareTokenRequiresPassword == nil {
|
||||
break
|
||||
}
|
||||
|
||||
args, err := ec.field_Query_shareTokenRequiresPassword_args(context.TODO(), rawArgs)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
return e.complexity.Query.ShareTokenRequiresPassword(childComplexity, args["token"].(string)), true
|
||||
|
||||
case "Query.siteInfo":
|
||||
if e.complexity.Query.SiteInfo == nil {
|
||||
break
|
||||
|
@ -1108,6 +1122,7 @@ type Query {
|
|||
photo(id: Int!): Photo!
|
||||
|
||||
shareToken(token: String!, password: String): ShareToken!
|
||||
shareTokenRequiresPassword(token: String!): Boolean!
|
||||
|
||||
search(query: String!, limitPhotos: Int, limitAlbums: Int): SearchResult!
|
||||
}
|
||||
|
@ -1752,6 +1767,20 @@ func (ec *executionContext) field_Query_search_args(ctx context.Context, rawArgs
|
|||
return args, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) field_Query_shareTokenRequiresPassword_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_Query_shareToken_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
||||
var err error
|
||||
args := map[string]interface{}{}
|
||||
|
@ -4325,6 +4354,47 @@ func (ec *executionContext) _Query_shareToken(ctx context.Context, field graphql
|
|||
return ec.marshalNShareToken2ᚖgithubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐShareToken(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Query_shareTokenRequiresPassword(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "Query",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: true,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
rawArgs := field.ArgumentMap(ec.Variables)
|
||||
args, err := ec.field_Query_shareTokenRequiresPassword_args(ctx, rawArgs)
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
fc.Args = args
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return ec.resolvers.Query().ShareTokenRequiresPassword(rctx, args["token"].(string))
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(bool)
|
||||
fc.Result = res
|
||||
return ec.marshalNBoolean2bool(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Query_search(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
|
@ -6880,6 +6950,20 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr
|
|||
}
|
||||
return res
|
||||
})
|
||||
case "shareTokenRequiresPassword":
|
||||
field := field
|
||||
out.Concurrently(i, func() (res graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
}
|
||||
}()
|
||||
res = ec._Query_shareTokenRequiresPassword(ctx, field)
|
||||
if res == graphql.Null {
|
||||
atomic.AddUint32(&invalids, 1)
|
||||
}
|
||||
return res
|
||||
})
|
||||
case "search":
|
||||
field := field
|
||||
out.Concurrently(i, func() (res graphql.Marshaler) {
|
||||
|
|
|
@ -84,6 +84,21 @@ func (r *queryResolver) ShareToken(ctx context.Context, tokenValue string, passw
|
|||
return token, nil
|
||||
}
|
||||
|
||||
func (r *queryResolver) ShareTokenRequiresPassword(ctx context.Context, tokenValue string) (bool, error) {
|
||||
row := r.Database.QueryRow("SELECT * FROM share_token WHERE value = ?", tokenValue)
|
||||
token, err := models.NewShareTokenFromRow(row)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return false, errors.New("share not found")
|
||||
} else {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
requiresPassword := token.Password != nil
|
||||
return requiresPassword, 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 {
|
||||
|
|
|
@ -39,6 +39,7 @@ type Query {
|
|||
photo(id: Int!): Photo!
|
||||
|
||||
shareToken(token: String!, password: String): ShareToken!
|
||||
shareTokenRequiresPassword(token: String!): Boolean!
|
||||
|
||||
search(query: String!, limitPhotos: Int, limitAlbums: Int): SearchResult!
|
||||
}
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import RouterProps from 'react-router-prop-types'
|
||||
import { Route, Switch } from 'react-router-dom'
|
||||
import AlbumSharePage from './AlbumSharePage'
|
||||
import PhotoSharePage from './PhotoSharePage'
|
||||
import { Query } from 'react-apollo'
|
||||
import { useQuery } from 'react-apollo'
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
const tokenQuery = gql`
|
||||
query SharePageToken($token: String!) {
|
||||
shareToken(token: $token) {
|
||||
query SharePageToken($token: String!, $password: String) {
|
||||
shareToken(token: $token, password: $password) {
|
||||
token
|
||||
album {
|
||||
...AlbumProps
|
||||
|
@ -70,30 +71,60 @@ const tokenQuery = gql`
|
|||
}
|
||||
`
|
||||
|
||||
const tokenPasswordProtectedQuery = gql`
|
||||
query ShareTokenRequiresPassword($token: String!) {
|
||||
shareTokenRequiresPassword(token: $token)
|
||||
}
|
||||
`
|
||||
|
||||
const AuthorizedTokenRoute = ({ match, password }) => {
|
||||
const { loading, error, data } = useQuery(tokenQuery, {
|
||||
variables: { token: match.params.token, password },
|
||||
})
|
||||
|
||||
if (error) return error.message
|
||||
if (loading) return 'Loading...'
|
||||
|
||||
if (data.shareToken.album) {
|
||||
return <AlbumSharePage album={data.shareToken.album} match={match} />
|
||||
}
|
||||
|
||||
if (data.shareToken.photo) {
|
||||
return <PhotoSharePage photo={data.shareToken.photo} />
|
||||
}
|
||||
|
||||
return <h1>Share not found</h1>
|
||||
}
|
||||
|
||||
AuthorizedTokenRoute.propTypes = {
|
||||
match: PropTypes.object.isRequired,
|
||||
password: PropTypes.string,
|
||||
}
|
||||
|
||||
const TokenRoute = ({ match }) => {
|
||||
const { loading, error, data } = useQuery(tokenPasswordProtectedQuery, {
|
||||
variables: { token: match.params.token },
|
||||
})
|
||||
|
||||
if (error) return error.message
|
||||
if (loading) return 'Loading...'
|
||||
|
||||
if (data.shareTokenRequiresPassword == true) {
|
||||
return 'Please provide password'
|
||||
}
|
||||
|
||||
return <AuthorizedTokenRoute match={match} />
|
||||
}
|
||||
|
||||
TokenRoute.propTypes = {
|
||||
match: PropTypes.object.isRequired,
|
||||
}
|
||||
|
||||
const SharePage = ({ match }) => {
|
||||
return (
|
||||
<Switch>
|
||||
<Route path={`${match.url}/:token`}>
|
||||
{({ match }) => (
|
||||
<Query query={tokenQuery} variables={{ token: match.params.token }}>
|
||||
{({ loading, error, data }) => {
|
||||
if (error) return error.message
|
||||
if (loading) return 'Loading...'
|
||||
|
||||
if (data.shareToken.album) {
|
||||
return (
|
||||
<AlbumSharePage album={data.shareToken.album} match={match} />
|
||||
)
|
||||
}
|
||||
|
||||
if (data.shareToken.photo) {
|
||||
return <PhotoSharePage photo={data.shareToken.photo} />
|
||||
}
|
||||
|
||||
return <h1>Share not found</h1>
|
||||
}}
|
||||
</Query>
|
||||
)}
|
||||
{({ match }) => <TokenRoute match={match} />}
|
||||
</Route>
|
||||
<Route path="/">Share not found</Route>
|
||||
</Switch>
|
||||
|
|
Loading…
Reference in New Issue