implemented piwigo authentication code with cookiehandling

This commit is contained in:
Philipp Häfelfinger 2019-02-24 00:33:18 +01:00
parent 1adeac1d24
commit 4721c762f1
7 changed files with 226 additions and 28 deletions

View File

@ -9,18 +9,11 @@ import (
func main() { func main() {
flag.Parse() flag.Parse()
root := flag.Arg(0) rootPath := flag.Arg(0)
InitializeLog() InitializeLog()
app.AuthenticateToPiwigo() app.Run(rootPath)
app.ScanLocalDirectories(root)
app.GetAllCategoriesFromServer()
app.FindMissingAlbums()
app.CreateMissingAlbums()
app.FindMissingImages()
app.UploadImages()
} }
func InitializeLog() { func InitializeLog() {

View File

@ -3,15 +3,46 @@ package app
import ( import (
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"haefelfinger.net/piwigo/DirectoriesToAlbums/internal/pkg/localFileStructure" "haefelfinger.net/piwigo/DirectoriesToAlbums/internal/pkg/localFileStructure"
"haefelfinger.net/piwigo/DirectoriesToAlbums/internal/pkg/piwigo/authentication"
) )
func AuthenticateToPiwigo() { func Run(rootPath string) {
logrus.Warnln("Authenticating to piwigo server (NotImplemented)") context := ConfigureContext(rootPath)
loginToPiwigoAndConfigureContext(context)
//ScanLocalDirectories(context)
//GetAllCategoriesFromServer()
//FindMissingAlbums()
//CreateMissingAlbums()
//FindMissingImages()
//UploadImages()
authentication.Logout(context.Piwigo)
} }
func ScanLocalDirectories(root string) { func ConfigureContext(rootPath string) *AppContext {
fileNodes := localFileStructure.ScanLocalFileStructure(root) logrus.Infoln("Preparing application context and configuration")
logrus.Debugln("filepath.Walk() returned %v\n", fileNodes)
context := new(AppContext)
context.LocalRootPath = rootPath
context.Piwigo = new(authentication.PiwigoContext)
//TODO: Move this values to configuration files
//No, these are not real credentials :-P
context.Piwigo.Url = "http://pictures.haefelfinger.net/ws.php?format=json"
context.Piwigo.Username = "admin"
context.Piwigo.Password = "asdf"
return context
}
func ScanLocalDirectories(context *AppContext) {
var fileNodes map[string]localFileStructure.FilesystemNode = localFileStructure.ScanLocalFileStructure(context.LocalRootPath)
for _, node := range fileNodes {
logrus.Debugln("found path entry:", node.Key)
}
} }
func GetAllCategoriesFromServer() { func GetAllCategoriesFromServer() {
@ -35,3 +66,15 @@ func FindMissingImages() {
func UploadImages() { func UploadImages() {
logrus.Warnln("Uploading missing images (NotImplemented)") logrus.Warnln("Uploading missing images (NotImplemented)")
} }
func loginToPiwigoAndConfigureContext(context *AppContext) {
logrus.Infoln("Logging in to piwigo and getting chunk size configuration for uploads")
authentication.Login(context.Piwigo)
initializeUploadChunkSize(context)
}
func initializeUploadChunkSize(context *AppContext) {
userStatus := authentication.GetStatus(context.Piwigo)
context.ChunkSizeBytes = userStatus.Result.UploadFormChunkSize * 1024
logrus.Debugln(context.ChunkSizeBytes)
}

10
internal/app/types.go Normal file
View File

@ -0,0 +1,10 @@
package app
import "haefelfinger.net/piwigo/DirectoriesToAlbums/internal/pkg/piwigo/authentication"
type AppContext struct {
Piwigo *authentication.PiwigoContext
SessionId string
LocalRootPath string
ChunkSizeBytes int
}

View File

@ -5,8 +5,8 @@ import (
"path/filepath" "path/filepath"
) )
func ScanLocalFileStructure(path string) map[string]FileNode { func ScanLocalFileStructure(path string) map[string]FilesystemNode {
fileMap := make(map[string]FileNode) fileMap := make(map[string]FilesystemNode)
err := filepath.Walk(path, func(p string, info os.FileInfo, err error) error { err := filepath.Walk(path, func(p string, info os.FileInfo, err error) error {
if path == p { if path == p {
@ -15,10 +15,10 @@ func ScanLocalFileStructure(path string) map[string]FileNode {
//TODO: Only allow jpg and png files here //TODO: Only allow jpg and png files here
fileMap[p] = FileNode{ fileMap[p] = FilesystemNode{
key: p, Key: p,
name: info.Name(), Name: info.Name(),
isDir: info.IsDir(), IsDir: info.IsDir(),
} }
return nil return nil
}) })

View File

@ -1,7 +1,13 @@
package localFileStructure package localFileStructure
type FileNode struct { import "fmt"
key string
name string type FilesystemNode struct {
isDir bool Key string
Name string
IsDir bool
}
func (n *FilesystemNode) String() string {
return fmt.Sprintf("FilesystemNode: %s", n.Key)
} }

View File

@ -0,0 +1,114 @@
package authentication
import (
"encoding/json"
"fmt"
"github.com/sirupsen/logrus"
"net/http"
"net/http/cookiejar"
"net/url"
"strings"
)
func Login(context *PiwigoContext) {
logrus.Debugf("Logging in to %s using user %s", context.Url, context.Username)
if !strings.HasPrefix(context.Url,"https") {
logrus.Warnf("The server url %s does not use https! Credentials are not encrypted!", context.Url)
}
initializeCookieJarIfRequired(context)
formData := url.Values{}
formData.Set("method", "pwg.session.login")
formData.Set("username", context.Username)
formData.Set("password", context.Password)
client := http.Client{Jar: context.Cookies}
response, err := client.PostForm(context.Url, formData)
if err == nil {
var loginResponse LoginResponse
if err := json.NewDecoder(response.Body).Decode(&loginResponse); err != nil {
logrus.Errorln(err)
}
if loginResponse.Status != "ok" {
errorMessage := fmt.Sprintf("Login failed: %d - %s", loginResponse.ErrorNumber, loginResponse.Message)
logrus.Errorf(errorMessage)
panic(errorMessage)
}
logrus.Infof("Login succeeded: %s", loginResponse.Status)
} else {
logrus.Errorln("The HTTP request failed with error %s", err)
}
}
func Logout(context *PiwigoContext) {
logrus.Debugf("Logging out from %s", context.Url)
initializeCookieJarIfRequired(context)
formData := url.Values{}
formData.Set("method", "pwg.session.logout")
client := http.Client{Jar: context.Cookies}
response, err := client.PostForm(context.Url, formData)
if err == nil {
var statusResponse LogoutResponse
if err := json.NewDecoder(response.Body).Decode(&statusResponse); err != nil {
logrus.Errorln(err)
}
if statusResponse.Status == "ok" {
logrus.Infof("Successfully logged out from %s", context.Url)
} else {
logrus.Errorf("Logout from %s failed", context.Url)
}
} else {
logrus.Errorln("The HTTP request failed with error %s", err)
}
}
func GetStatus(context *PiwigoContext) *GetStatusResponse {
logrus.Debugln("Getting current login state...")
initializeCookieJarIfRequired(context)
formData := url.Values{}
formData.Set("method", "pwg.session.getStatus")
client := http.Client{Jar: context.Cookies}
response, err := client.PostForm(context.Url, formData)
if err == nil {
var statusResponse GetStatusResponse
if err := json.NewDecoder(response.Body).Decode(&statusResponse); err != nil {
logrus.Errorln(err)
}
if statusResponse.Status != "ok" {
logrus.Errorf("Could not get session state from %s", context.Url)
}
return &statusResponse
} else {
logrus.Errorln("The HTTP request failed with error %s\n", err)
}
return nil
}
func initializeCookieJarIfRequired(context *PiwigoContext) {
if context.Cookies != nil {
return
}
options := cookiejar.Options{}
jar, _ := cookiejar.New(&options)
context.Cookies = jar
}

View File

@ -1,7 +1,39 @@
package authentication package authentication
type PiwigoConfig struct { import "net/http/cookiejar"
url string
username string type PiwigoContext struct {
password string Url string
Username string
Password string
Cookies *cookiejar.Jar
}
type LoginResponse struct {
Status string `json:"stat"`
Result bool `json:"result"`
ErrorNumber int `json:"err"`
Message string `json:"message"`
}
type GetStatusResponse struct {
Status string `json:"stat"`
Result struct {
Username string `json:"username"`
Status string `json:"status"`
Theme string `json:"theme"`
Language string `json:"language"`
PwgToken string `json:"pwg_token"`
Charset string `json:"charset"`
CurrentDatetime string `json:"current_datetime"`
Version string `json:"version"`
AvailableSizes []string `json:"available_sizes"`
UploadFileTypes string `json:"upload_file_types"`
UploadFormChunkSize int `json:"upload_form_chunk_size"`
} `json:"result"`
}
type LogoutResponse struct {
Status string `json:"stat"`
Result bool `json:"result"`
} }