Work on share tokens
This commit is contained in:
parent
963acf11e8
commit
a3a4dda286
|
@ -1,7 +1,7 @@
|
||||||
CREATE TABLE IF NOT EXISTS user (
|
CREATE TABLE IF NOT EXISTS user (
|
||||||
user_id int NOT NULL AUTO_INCREMENT,
|
user_id int NOT NULL AUTO_INCREMENT,
|
||||||
username varchar(255) NOT NULL UNIQUE,
|
username varchar(256) NOT NULL UNIQUE,
|
||||||
password varchar(255) NOT NULL,
|
password varchar(256) NOT NULL,
|
||||||
root_path varchar(512),
|
root_path varchar(512),
|
||||||
admin boolean NOT NULL DEFAULT 0,
|
admin boolean NOT NULL DEFAULT 0,
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ CREATE TABLE IF NOT EXISTS album (
|
||||||
CREATE TABLE IF NOT EXISTS photo (
|
CREATE TABLE IF NOT EXISTS photo (
|
||||||
photo_id int NOT NULL AUTO_INCREMENT,
|
photo_id int NOT NULL AUTO_INCREMENT,
|
||||||
title varchar(256) NOT NULL,
|
title varchar(256) NOT NULL,
|
||||||
path varchar(512) NOT NULL UNIQUE,
|
path varchar(1024) NOT NULL UNIQUE,
|
||||||
album_id int NOT NULL,
|
album_id int NOT NULL,
|
||||||
exif_id int,
|
exif_id int,
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ CREATE TABLE IF NOT EXISTS photo (
|
||||||
CREATE TABLE IF NOT EXISTS photo_url (
|
CREATE TABLE IF NOT EXISTS photo_url (
|
||||||
url_id int NOT NULL AUTO_INCREMENT,
|
url_id int NOT NULL AUTO_INCREMENT,
|
||||||
photo_id int NOT NULL,
|
photo_id int NOT NULL,
|
||||||
photo_name varchar(256) NOT NULL,
|
photo_name varchar(512) NOT NULL,
|
||||||
width int NOT NULL,
|
width int NOT NULL,
|
||||||
height int NOT NULL,
|
height int NOT NULL,
|
||||||
purpose varchar(64) NOT NULL,
|
purpose varchar(64) NOT NULL,
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS share_token;
|
|
@ -0,0 +1,12 @@
|
||||||
|
CREATE TABLE IF NOT EXISTS share_token (
|
||||||
|
token_id int AUTO_INCREMENT,
|
||||||
|
value char(24) NOT NULL UNIQUE,
|
||||||
|
owner_id int NOT NULL,
|
||||||
|
expire timestamp,
|
||||||
|
password varchar(256) NOT NULL,
|
||||||
|
album_id int,
|
||||||
|
photo_id int,
|
||||||
|
|
||||||
|
PRIMARY KEY (token_id),
|
||||||
|
CHECK (album_id IS NOT NULL OR photo_id IS NOT NULL)
|
||||||
|
);
|
|
@ -28,3 +28,5 @@ models:
|
||||||
model: github.com/viktorstrate/photoview/api/graphql/models.PhotoURL
|
model: github.com/viktorstrate/photoview/api/graphql/models.PhotoURL
|
||||||
Album:
|
Album:
|
||||||
model: github.com/viktorstrate/photoview/api/graphql/models.Album
|
model: github.com/viktorstrate/photoview/api/graphql/models.Album
|
||||||
|
ShareToken:
|
||||||
|
model: github.com/viktorstrate/photoview/api/graphql/models.ShareToken
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,7 +2,6 @@ package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"strconv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Album struct {
|
type Album struct {
|
||||||
|
@ -13,8 +12,8 @@ type Album struct {
|
||||||
Path string
|
Path string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Album) ID() string {
|
func (a *Album) ID() int {
|
||||||
return strconv.Itoa(a.AlbumID)
|
return a.AlbumID
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAlbumFromRow(row *sql.Row) (*Album, error) {
|
func NewAlbumFromRow(row *sql.Row) (*Album, error) {
|
||||||
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"strconv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Photo struct {
|
type Photo struct {
|
||||||
|
@ -16,6 +15,10 @@ type Photo struct {
|
||||||
ExifId *int
|
ExifId *int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Photo) ID() int {
|
||||||
|
return p.PhotoID
|
||||||
|
}
|
||||||
|
|
||||||
type PhotoPurpose string
|
type PhotoPurpose string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -34,10 +37,6 @@ type PhotoURL struct {
|
||||||
ContentType string
|
ContentType string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Photo) ID() string {
|
|
||||||
return strconv.Itoa(p.PhotoID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewPhotoFromRow(row *sql.Row) (*Photo, error) {
|
func NewPhotoFromRow(row *sql.Row) (*Photo, error) {
|
||||||
photo := Photo{}
|
photo := Photo{}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type ShareToken struct {
|
||||||
|
TokenID int
|
||||||
|
Value string
|
||||||
|
OwnerID int
|
||||||
|
Expire *time.Time
|
||||||
|
Password *string
|
||||||
|
AlbumID *int
|
||||||
|
PhotoID *int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (share *ShareToken) Token() string {
|
||||||
|
return share.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (share *ShareToken) ID() int {
|
||||||
|
return share.TokenID
|
||||||
|
}
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"strconv"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
@ -20,8 +19,8 @@ type User struct {
|
||||||
Admin bool
|
Admin bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *User) ID() string {
|
func (u *User) ID() int {
|
||||||
return strconv.Itoa(u.UserID)
|
return u.UserID
|
||||||
}
|
}
|
||||||
|
|
||||||
type AccessToken struct {
|
type AccessToken struct {
|
||||||
|
|
|
@ -33,7 +33,7 @@ func (r *queryResolver) MyAlbums(ctx context.Context, filter *models.Filter) ([]
|
||||||
return albums, nil
|
return albums, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *queryResolver) Album(ctx context.Context, id *string) (*models.Album, error) {
|
func (r *queryResolver) Album(ctx context.Context, id int) (*models.Album, error) {
|
||||||
user := auth.UserFromContext(ctx)
|
user := auth.UserFromContext(ctx)
|
||||||
if user == nil {
|
if user == nil {
|
||||||
return nil, auth.ErrUnauthorized
|
return nil, auth.ErrUnauthorized
|
||||||
|
|
|
@ -28,7 +28,7 @@ func (r *queryResolver) MyPhotos(ctx context.Context, filter *models.Filter) ([]
|
||||||
return models.NewPhotosFromRows(rows)
|
return models.NewPhotosFromRows(rows)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *queryResolver) Photo(ctx context.Context, id string) (*models.Photo, error) {
|
func (r *queryResolver) Photo(ctx context.Context, id int) (*models.Photo, error) {
|
||||||
user := auth.UserFromContext(ctx)
|
user := auth.UserFromContext(ctx)
|
||||||
if user == nil {
|
if user == nil {
|
||||||
return nil, auth.ErrUnauthorized
|
return nil, auth.ErrUnauthorized
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
func (r *mutationResolver) ScanAll(ctx context.Context) (*models.ScannerResult, error) {
|
func (r *mutationResolver) ScanAll(ctx context.Context) (*models.ScannerResult, error) {
|
||||||
panic("Not implemented")
|
panic("Not implemented")
|
||||||
}
|
}
|
||||||
func (r *mutationResolver) ScanUser(ctx context.Context, userID string) (*models.ScannerResult, error) {
|
func (r *mutationResolver) ScanUser(ctx context.Context, userID int) (*models.ScannerResult, error) {
|
||||||
if err := scanner.ScanUser(r.Database, userID); err != nil {
|
if err := scanner.ScanUser(r.Database, userID); err != nil {
|
||||||
errorMessage := fmt.Sprintf("Error scanning user: %s", err.Error())
|
errorMessage := fmt.Sprintf("Error scanning user: %s", err.Error())
|
||||||
return &models.ScannerResult{
|
return &models.ScannerResult{
|
||||||
|
|
|
@ -0,0 +1,120 @@
|
||||||
|
package resolvers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
api "github.com/viktorstrate/photoview/api/graphql"
|
||||||
|
"github.com/viktorstrate/photoview/api/graphql/auth"
|
||||||
|
"github.com/viktorstrate/photoview/api/graphql/models"
|
||||||
|
"github.com/viktorstrate/photoview/api/utils"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type shareTokenResolver struct {
|
||||||
|
*Resolver
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Resolver) ShareToken() api.ShareTokenResolver {
|
||||||
|
return &shareTokenResolver{r}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *shareTokenResolver) Owner(ctx context.Context, obj *models.ShareToken) (*models.User, error) {
|
||||||
|
row := r.Database.QueryRow("SELECT * FROM user WHERE user.user_id = ?", obj.OwnerID)
|
||||||
|
return models.NewUserFromRow(row)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *shareTokenResolver) Album(ctx context.Context, obj *models.ShareToken) (*models.Album, error) {
|
||||||
|
row := r.Database.QueryRow("SELECT * FROM album WHERE album.album_id = ?", obj.AlbumID)
|
||||||
|
album, err := models.NewAlbumFromRow(row)
|
||||||
|
if err != nil {
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return nil, nil
|
||||||
|
} else {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return album, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *shareTokenResolver) Photo(ctx context.Context, obj *models.ShareToken) (*models.Photo, error) {
|
||||||
|
row := r.Database.QueryRow("SELECT * FROM photo WHERE photo.photo_id = ?", obj.PhotoID)
|
||||||
|
photo, err := models.NewPhotoFromRow(row)
|
||||||
|
if err != nil {
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return nil, nil
|
||||||
|
} else {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return photo, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *queryResolver) AlbumShares(ctx context.Context, id int, password *string) ([]*models.ShareToken, error) {
|
||||||
|
log.Println("Query AlbumShares: not implemented")
|
||||||
|
|
||||||
|
tokens := make([]*models.ShareToken, 0)
|
||||||
|
return tokens, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *queryResolver) PhotoShares(ctx context.Context, id int, 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 {
|
||||||
|
return nil, auth.ErrUnauthorized
|
||||||
|
}
|
||||||
|
|
||||||
|
rows, err := r.Database.Query("SELECT owner_id FROM album WHERE album.album_id = ? AND album.owner_id = ?", albumID, 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, album_id) VALUES (?, ?, ?, ?, ?)", token, user.UserID, expire, hashed_password, albumID)
|
||||||
|
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: &albumID,
|
||||||
|
PhotoID: nil,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *mutationResolver) SharePhoto(ctx context.Context, photoID int, expire *time.Time, password *string) (*models.ShareToken, error) {
|
||||||
|
panic("not implemented")
|
||||||
|
}
|
|
@ -74,9 +74,9 @@ type Photo {
|
||||||
|
|
||||||
type ShareToken {
|
type ShareToken {
|
||||||
token: ID!
|
token: ID!
|
||||||
owner: User
|
owner: User!
|
||||||
# Optional expire date
|
# Optional expire date
|
||||||
expire: Time
|
expire: Time!
|
||||||
# Optional password
|
# Optional password
|
||||||
# password: String
|
# password: String
|
||||||
|
|
||||||
|
|
|
@ -25,12 +25,15 @@ type Query {
|
||||||
"List of albums owned by the logged in user"
|
"List of albums owned by the logged in user"
|
||||||
myAlbums(filter: Filter): [Album!]!
|
myAlbums(filter: Filter): [Album!]!
|
||||||
"Get album by id, user must own the album or be admin"
|
"Get album by id, user must own the album or be admin"
|
||||||
album(id: ID): Album!
|
album(id: Int!): Album!
|
||||||
|
|
||||||
"List of photos owned by the logged in user"
|
"List of photos owned by the logged in user"
|
||||||
myPhotos(filter: Filter): [Photo!]!
|
myPhotos(filter: Filter): [Photo!]!
|
||||||
"Get photo by id, user must own the photo or be admin"
|
"Get photo by id, user must own the photo or be admin"
|
||||||
photo(id: ID!): Photo!
|
photo(id: Int!): Photo!
|
||||||
|
|
||||||
|
albumShares(id: Int!, password: String): [ShareToken!]!
|
||||||
|
photoShares(id: Int!, password: String): [ShareToken!]!
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mutation {
|
type Mutation {
|
||||||
|
@ -53,7 +56,12 @@ type Mutation {
|
||||||
"Scan all users for new photos"
|
"Scan all users for new photos"
|
||||||
scanAll: ScannerResult!
|
scanAll: ScannerResult!
|
||||||
"Scan a single user for new photos"
|
"Scan a single user for new photos"
|
||||||
scanUser(userId: ID!): ScannerResult!
|
scanUser(userId: Int!): ScannerResult!
|
||||||
|
|
||||||
|
"Generate share token for album"
|
||||||
|
shareAlbum(albumId: Int!, expire: Time, password: String): ShareToken
|
||||||
|
"Generate share token for photo"
|
||||||
|
sharePhoto(photoId: Int!, expire: Time, password: String): ShareToken
|
||||||
}
|
}
|
||||||
|
|
||||||
type AuthorizeResult {
|
type AuthorizeResult {
|
||||||
|
@ -69,13 +77,28 @@ type ScannerResult {
|
||||||
message: String
|
message: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"A token used to publicly access an album or photo"
|
||||||
|
type ShareToken {
|
||||||
|
id: Int!
|
||||||
|
token: String!
|
||||||
|
"The user who created the token"
|
||||||
|
owner: User!
|
||||||
|
"Optional expire date"
|
||||||
|
expire: Time
|
||||||
|
|
||||||
|
"The album this token shares"
|
||||||
|
album: Album
|
||||||
|
"The photo this token shares"
|
||||||
|
photo: Photo
|
||||||
|
}
|
||||||
|
|
||||||
"General public information about the site"
|
"General public information about the site"
|
||||||
type SiteInfo {
|
type SiteInfo {
|
||||||
initialSetup: Boolean!
|
initialSetup: Boolean!
|
||||||
}
|
}
|
||||||
|
|
||||||
type User {
|
type User {
|
||||||
id: ID!
|
id: Int!
|
||||||
username: String!
|
username: String!
|
||||||
#albums: [Album]
|
#albums: [Album]
|
||||||
"Local filepath for the user's photos"
|
"Local filepath for the user's photos"
|
||||||
|
@ -85,13 +108,19 @@ type User {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Album {
|
type Album {
|
||||||
id: ID!
|
id: Int!
|
||||||
title: String!
|
title: String!
|
||||||
|
"The photos inside this album"
|
||||||
photos(filter: Filter): [Photo!]!
|
photos(filter: Filter): [Photo!]!
|
||||||
|
"The albums contained in this album"
|
||||||
subAlbums(filter: Filter): [Album!]!
|
subAlbums(filter: Filter): [Album!]!
|
||||||
|
"The album witch contains this album"
|
||||||
parentAlbum: Album
|
parentAlbum: Album
|
||||||
|
"The user who owns this album"
|
||||||
owner: User!
|
owner: User!
|
||||||
|
"The path on the filesystem of the server, where this album is located"
|
||||||
path: String!
|
path: String!
|
||||||
|
"An image in this album used for previewing this album"
|
||||||
thumbnail: Photo
|
thumbnail: Photo
|
||||||
|
|
||||||
# shares: [ShareToken]
|
# shares: [ShareToken]
|
||||||
|
@ -107,7 +136,7 @@ type PhotoURL {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Photo {
|
type Photo {
|
||||||
id: ID!
|
id: Int!
|
||||||
title: String!
|
title: String!
|
||||||
"Local filepath for the photo"
|
"Local filepath for the photo"
|
||||||
path: String!
|
path: String!
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"image"
|
"image"
|
||||||
"image/jpeg"
|
"image/jpeg"
|
||||||
"log"
|
"log"
|
||||||
"math/rand"
|
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -14,6 +13,7 @@ import (
|
||||||
|
|
||||||
"github.com/nfnt/resize"
|
"github.com/nfnt/resize"
|
||||||
"github.com/viktorstrate/photoview/api/graphql/models"
|
"github.com/viktorstrate/photoview/api/graphql/models"
|
||||||
|
"github.com/viktorstrate/photoview/api/utils"
|
||||||
|
|
||||||
// Image decoders
|
// Image decoders
|
||||||
_ "golang.org/x/image/bmp"
|
_ "golang.org/x/image/bmp"
|
||||||
|
@ -68,7 +68,7 @@ func ProcessImage(tx *sql.Tx, photoPath string, albumId int, content_type string
|
||||||
photoBaseName := photoName[0 : len(photoName)-len(path.Ext(photoName))]
|
photoBaseName := photoName[0 : len(photoName)-len(path.Ext(photoName))]
|
||||||
photoBaseExt := path.Ext(photoName)
|
photoBaseExt := path.Ext(photoName)
|
||||||
|
|
||||||
original_image_name := fmt.Sprintf("%s_%s", photoBaseName, generateToken())
|
original_image_name := fmt.Sprintf("%s_%s", photoBaseName, utils.GenerateToken())
|
||||||
original_image_name = strings.ReplaceAll(original_image_name, " ", "_") + photoBaseExt
|
original_image_name = strings.ReplaceAll(original_image_name, " ", "_") + photoBaseExt
|
||||||
|
|
||||||
_, err = tx.Exec("INSERT INTO photo_url (photo_id, photo_name, width, height, purpose, content_type) VALUES (?, ?, ?, ?, ?, ?)", photo_id, original_image_name, image.Bounds().Max.X, image.Bounds().Max.Y, models.PhotoOriginal, content_type)
|
_, err = tx.Exec("INSERT INTO photo_url (photo_id, photo_name, width, height, purpose, content_type) VALUES (?, ?, ?, ?, ?, ?)", photo_id, original_image_name, image.Bounds().Max.X, image.Bounds().Max.Y, models.PhotoOriginal, content_type)
|
||||||
|
@ -96,7 +96,7 @@ func ProcessImage(tx *sql.Tx, photoPath string, albumId int, content_type string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save thumbnail as jpg
|
// Save thumbnail as jpg
|
||||||
thumbnail_name := fmt.Sprintf("thumbnail_%s_%s", photoName, generateToken())
|
thumbnail_name := fmt.Sprintf("thumbnail_%s_%s", photoName, utils.GenerateToken())
|
||||||
thumbnail_name = strings.ReplaceAll(thumbnail_name, ".", "_")
|
thumbnail_name = strings.ReplaceAll(thumbnail_name, ".", "_")
|
||||||
thumbnail_name = strings.ReplaceAll(thumbnail_name, " ", "_")
|
thumbnail_name = strings.ReplaceAll(thumbnail_name, " ", "_")
|
||||||
thumbnail_name = thumbnail_name + ".jpg"
|
thumbnail_name = thumbnail_name + ".jpg"
|
||||||
|
@ -118,14 +118,3 @@ func ProcessImage(tx *sql.Tx, photoPath string, albumId int, content_type string
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateToken() string {
|
|
||||||
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
|
||||||
const length = 8
|
|
||||||
|
|
||||||
b := make([]byte, length)
|
|
||||||
for i := range b {
|
|
||||||
b[i] = charset[rand.Intn(len(charset))]
|
|
||||||
}
|
|
||||||
return string(b)
|
|
||||||
}
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ func (cache *scanner_cache) get_photo_type(path string) *string {
|
||||||
return &photo_type
|
return &photo_type
|
||||||
}
|
}
|
||||||
|
|
||||||
func ScanUser(database *sql.DB, userId string) error {
|
func ScanUser(database *sql.DB, userId int) error {
|
||||||
|
|
||||||
row := database.QueryRow("SELECT * FROM user WHERE user_id = ?", userId)
|
row := database.QueryRow("SELECT * FROM user WHERE user_id = ?", userId)
|
||||||
user, err := models.NewUserFromRow(row)
|
user, err := models.NewUserFromRow(row)
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import "math/rand"
|
||||||
|
|
||||||
|
func GenerateToken() string {
|
||||||
|
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||||
|
const length = 8
|
||||||
|
|
||||||
|
b := make([]byte, length)
|
||||||
|
for i := range b {
|
||||||
|
b[i] = charset[rand.Intn(len(charset))]
|
||||||
|
}
|
||||||
|
return string(b)
|
||||||
|
}
|
|
@ -10,7 +10,7 @@ import AlbumTitle from '../../components/AlbumTitle'
|
||||||
import AlbumGallery from '../../components/albumGallery/AlbumGallery'
|
import AlbumGallery from '../../components/albumGallery/AlbumGallery'
|
||||||
|
|
||||||
const albumQuery = gql`
|
const albumQuery = gql`
|
||||||
query albumQuery($id: ID!) {
|
query albumQuery($id: Int!) {
|
||||||
album(id: $id) {
|
album(id: $id) {
|
||||||
id
|
id
|
||||||
title
|
title
|
||||||
|
|
|
@ -14,7 +14,7 @@ import gql from 'graphql-tag'
|
||||||
|
|
||||||
const updateUserMutation = gql`
|
const updateUserMutation = gql`
|
||||||
mutation updateUser(
|
mutation updateUser(
|
||||||
$id: ID!
|
$id: Int!
|
||||||
$username: String
|
$username: String
|
||||||
$rootPath: String
|
$rootPath: String
|
||||||
$admin: Boolean
|
$admin: Boolean
|
||||||
|
@ -34,7 +34,7 @@ const updateUserMutation = gql`
|
||||||
`
|
`
|
||||||
|
|
||||||
const deleteUserMutation = gql`
|
const deleteUserMutation = gql`
|
||||||
mutation deleteUser($id: ID!) {
|
mutation deleteUser($id: Int!) {
|
||||||
deleteUser(id: $id) {
|
deleteUser(id: $id) {
|
||||||
id
|
id
|
||||||
username
|
username
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { Query } from 'react-apollo'
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
const tokenQuery = gql`
|
const tokenQuery = gql`
|
||||||
query SharePageToken($token: ID!) {
|
query SharePageToken($token: Int!) {
|
||||||
shareToken(token: $token) {
|
shareToken(token: $token) {
|
||||||
token
|
token
|
||||||
album {
|
album {
|
||||||
|
|
|
@ -5,7 +5,7 @@ import gql from 'graphql-tag'
|
||||||
import SidebarShare from './Sharing'
|
import SidebarShare from './Sharing'
|
||||||
|
|
||||||
const albumQuery = gql`
|
const albumQuery = gql`
|
||||||
query getAlbumSidebar($id: ID!) {
|
query getAlbumSidebar($id: Int!) {
|
||||||
album(id: $id) {
|
album(id: $id) {
|
||||||
id
|
id
|
||||||
title
|
title
|
||||||
|
|
|
@ -9,7 +9,7 @@ import SidebarShare from './Sharing'
|
||||||
import SidebarDownload from './SidebarDownload'
|
import SidebarDownload from './SidebarDownload'
|
||||||
|
|
||||||
const photoQuery = gql`
|
const photoQuery = gql`
|
||||||
query sidebarPhoto($id: ID!) {
|
query sidebarPhoto($id: Int!) {
|
||||||
photo(id: $id) {
|
photo(id: $id) {
|
||||||
id
|
id
|
||||||
title
|
title
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { Table, Button, Dropdown } from 'semantic-ui-react'
|
||||||
import copy from 'copy-to-clipboard'
|
import copy from 'copy-to-clipboard'
|
||||||
|
|
||||||
const sharePhotoQuery = gql`
|
const sharePhotoQuery = gql`
|
||||||
query sidbarGetPhotoShares($id: ID!) {
|
query sidbarGetPhotoShares($id: Int!) {
|
||||||
photoShares(id: $id) {
|
photoShares(id: $id) {
|
||||||
token
|
token
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ const sharePhotoQuery = gql`
|
||||||
`
|
`
|
||||||
|
|
||||||
const shareAlbumQuery = gql`
|
const shareAlbumQuery = gql`
|
||||||
query sidbarGetAlbumShares($id: ID!) {
|
query sidbarGetAlbumShares($id: Int!) {
|
||||||
albumShares(id: $id) {
|
albumShares(id: $id) {
|
||||||
token
|
token
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ const shareAlbumQuery = gql`
|
||||||
|
|
||||||
const addPhotoShareMutation = gql`
|
const addPhotoShareMutation = gql`
|
||||||
mutation sidebarPhotoAddShare(
|
mutation sidebarPhotoAddShare(
|
||||||
$id: ID!
|
$id: Int!
|
||||||
$password: String
|
$password: String
|
||||||
$expire: _Neo4jDateInput
|
$expire: _Neo4jDateInput
|
||||||
) {
|
) {
|
||||||
|
@ -35,7 +35,7 @@ const addPhotoShareMutation = gql`
|
||||||
|
|
||||||
const addAlbumShareMutation = gql`
|
const addAlbumShareMutation = gql`
|
||||||
mutation sidebarAlbumAddShare(
|
mutation sidebarAlbumAddShare(
|
||||||
$id: ID!
|
$id: Int!
|
||||||
$password: String
|
$password: String
|
||||||
$expire: _Neo4jDateInput
|
$expire: _Neo4jDateInput
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -6,7 +6,7 @@ import gql from 'graphql-tag'
|
||||||
import download from 'downloadjs'
|
import download from 'downloadjs'
|
||||||
|
|
||||||
const downloadQuery = gql`
|
const downloadQuery = gql`
|
||||||
query sidebarDownloadQuery($photoId: ID!) {
|
query sidebarDownloadQuery($photoId: Int!) {
|
||||||
photo(id: $photoId) {
|
photo(id: $photoId) {
|
||||||
id
|
id
|
||||||
downloads {
|
downloads {
|
||||||
|
|
Loading…
Reference in New Issue