From 6ad03fc2645f0ffc5deb5add33bb86e58aa4fa7d Mon Sep 17 00:00:00 2001 From: Steven Date: Thu, 5 Sep 2024 15:15:18 +0800 Subject: [PATCH] update: login for upload and delete --- Makefile | 2 +- README.md | 3 +++ README_zh.md | 3 +++ cmd/ipasd/ipasd.go | 20 +++++++++++++++---- cmd/ipasd/service/middleware.go | 12 ++++++++++++ cmd/ipasd/service/transport.go | 14 ++++++++------ docker-entrypoint.sh | 8 ++++++++ public/app/index.html | 6 ++++-- public/js/core.js | 34 ++++++++++++++++++++------------- public/key.html | 28 --------------------------- 10 files changed, 76 insertions(+), 54 deletions(-) delete mode 100644 public/key.html diff --git a/Makefile b/Makefile index f4fcd7d..efbfa9f 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -VERSION := 2.4 +VERSION := 2.5 DOCKER_IMAGE := ineva/ipa-server DOCKER_TARGET := $(DOCKER_IMAGE):$(VERSION) diff --git a/README.md b/README.md index 8c89dae..10b6598 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,9 @@ services: - DELETE_ENABLED="false" # meta data filter, string list, comma separated - META_DATA_FILTER="key1,key2" + # If set, login user for upload and delete Apps. + - LOGIN_USER= + - LOGIN_PASS= volumes: - "/docker/data/ipa-server:/app/upload" caddy: diff --git a/README_zh.md b/README_zh.md index a38ee9c..0f74360 100644 --- a/README_zh.md +++ b/README_zh.md @@ -75,6 +75,9 @@ services: - DELETE_ENABLED="false" # meta data 过滤显示, string list, 使用逗号分隔 - META_DATA_FILTER="key1,key2" + # 如果设置了,使用此用户名密码来上传和删除App + - LOGIN_USER= + - LOGIN_PASS= volumes: - "/docker/data/ipa-server:/app/upload" caddy: diff --git a/cmd/ipasd/ipasd.go b/cmd/ipasd/ipasd.go index 3ff15bd..af4b46b 100644 --- a/cmd/ipasd/ipasd.go +++ b/cmd/ipasd/ipasd.go @@ -34,6 +34,8 @@ func main() { addr := flag.String("addr", "0.0.0.0", "bind addr") port := flag.String("port", "8080", "bind port") debug := flag.Bool("d", false, "enable debug logging") + user := flag.String("user", "", "basic auth username") + pass := flag.String("pass", "", "basic auth password") storageDir := flag.String("dir", "upload", "upload data storage dir") publicURL := flag.String("public-url", "", "server public url") metadataPath := flag.String("meta-path", "appList.json", "metadata storage path, use random secret path to keep your metadata safer") @@ -91,10 +93,12 @@ func main() { } srv := service.New(store, *publicURL, *metadataPath) + basicAuth := service.BasicAuthMiddleware(*user, *pass, "My Realm") listHandler := httptransport.NewServer( - service.LoggingMiddleware(logger, "/api/list", *debug)(service.MakeListEndpoint(srv)), + basicAuth(service.LoggingMiddleware(logger, "/api/list", *debug)(service.MakeListEndpoint(srv))), service.DecodeListRequest, service.EncodeJsonResponse, + httptransport.ServerBefore(httptransport.PopulateRequestContext), ) findHandler := httptransport.NewServer( service.LoggingMiddleware(logger, "/api/info", *debug)(service.MakeFindEndpoint(srv)), @@ -102,14 +106,22 @@ func main() { service.EncodeJsonResponse, ) addHandler := httptransport.NewServer( - service.LoggingMiddleware(logger, "/api/upload", *debug)(service.MakeAddEndpoint(srv)), + basicAuth(service.LoggingMiddleware(logger, "/api/upload", *debug)(service.MakeAddEndpoint(srv))), service.DecodeAddRequest, service.EncodeJsonResponse, + httptransport.ServerBefore(httptransport.PopulateRequestContext), ) deleteHandler := httptransport.NewServer( - service.LoggingMiddleware(logger, "/api/delete", *debug)(service.MakeDeleteEndpoint(srv, *enabledDelete)), + basicAuth(service.LoggingMiddleware(logger, "/api/delete", *debug)(service.MakeDeleteEndpoint(srv, *enabledDelete))), service.DecodeDeleteRequest, service.EncodeJsonResponse, + httptransport.ServerBefore(httptransport.PopulateRequestContext), + ) + deleteGetHandler := httptransport.NewServer( + service.LoggingMiddleware(logger, "/api/delete/get", *debug)(service.MakeGetDeleteEndpoint(srv, *enabledDelete)), + service.DecodeDeleteRequest, + service.EncodeJsonResponse, + httptransport.ServerBefore(httptransport.PopulateRequestContext), ) plistHandler := httptransport.NewServer( service.LoggingMiddleware(logger, "/plist", *debug)(service.MakePlistEndpoint(srv)), @@ -122,6 +134,7 @@ func main() { serve.Handle("/api/info/", findHandler) serve.Handle("/api/upload", addHandler) serve.Handle("/api/delete", deleteHandler) + serve.Handle("/api/delete/get", deleteGetHandler) serve.Handle("/plist/", plistHandler) // static files @@ -131,7 +144,6 @@ func main() { httpfs.NewAferoFS(uploadFS), ) serve.Handle("/", redirect(map[string]string{ - "/key": "/key.html", // random path to block local metadata fmt.Sprintf("/%s", *metadataPath): fmt.Sprintf("/%s", uuid.NewString()), }, http.FileServer(staticFS))) diff --git a/cmd/ipasd/service/middleware.go b/cmd/ipasd/service/middleware.go index 7daedac..440f782 100644 --- a/cmd/ipasd/service/middleware.go +++ b/cmd/ipasd/service/middleware.go @@ -3,8 +3,10 @@ package service import ( "context" "fmt" + stdLog "log" "time" + basic "github.com/go-kit/kit/auth/basic" "github.com/go-kit/kit/endpoint" "github.com/go-kit/kit/log" "github.com/go-kit/kit/log/level" @@ -51,3 +53,13 @@ func LoggingMiddleware(logger log.Logger, name string, debug bool) endpoint.Midd } } } + +func BasicAuthMiddleware(user, pass, realm string) endpoint.Middleware { + if user == "" { + return func(e endpoint.Endpoint) endpoint.Endpoint { + return e + } + } + stdLog.Println(user, pass, realm) + return basic.AuthMiddleware(user, pass, realm) +} diff --git a/cmd/ipasd/service/transport.go b/cmd/ipasd/service/transport.go index 453899b..5b88770 100644 --- a/cmd/ipasd/service/transport.go +++ b/cmd/ipasd/service/transport.go @@ -83,16 +83,11 @@ func MakeAddEndpoint(srv Service) endpoint.Endpoint { func MakeDeleteEndpoint(srv Service, enabledDelete bool) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (interface{}, error) { - p := request.(delParam) - if p.get { - // check is delete enabled - return map[string]interface{}{"delete": enabledDelete}, nil - } - if !enabledDelete { return nil, errors.New("no permission to delete") } + p := request.(delParam) err := srv.Delete(p.id) if err != nil { return nil, err @@ -101,6 +96,13 @@ func MakeDeleteEndpoint(srv Service, enabledDelete bool) endpoint.Endpoint { } } +func MakeGetDeleteEndpoint(srv Service, enabledDelete bool) endpoint.Endpoint { + return func(ctx context.Context, request interface{}) (interface{}, error) { + // check is delete enabled + return map[string]interface{}{"delete": enabledDelete}, nil + } +} + func MakePlistEndpoint(srv Service) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (interface{}, error) { p := request.(param) diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index 595f165..766dd41 100644 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -27,4 +27,12 @@ if [ -n "$META_PATH" ];then ipasd_args=$ipasd_args"-meta-path $META_PATH " fi +if [ -n "$LOGIN_USER" ];then + ipasd_args=$ipasd_args"-user $LOGIN_USER " +fi + +if [ -n "$LOGIN_PASS" ];then + ipasd_args=$ipasd_args"-user $LOGIN_PASS " +fi + /app/ipasd $ipasd_args diff --git a/public/app/index.html b/public/app/index.html index 67c9f91..52036db 100644 --- a/public/app/index.html +++ b/public/app/index.html @@ -126,7 +126,7 @@ const filter = (row.metaDataFilter || []).map(r => `${r}`.toLowerCase()) const meta = Object.keys(row.metaData || {}) .map(k => ({ name: k, value: (row.metaData || {})[k] })) - .filter(r => r.value && filter.indexOf(r.name.toLocaleLowerCase()) !== -1) + .filter(r => r.value && (filter.length === 0 || filter.indexOf(r.name.toLocaleLowerCase()) !== -1)) document.querySelector('#info').innerHTML = `
${row.name}
@@ -150,8 +150,10 @@ }) } function onWindowsLoad() { - IPA.fetch(`/api/delete?v=${parseInt(new Date().getTime() / 1000)}`).then(d => { + IPA.fetch(`/api/delete/get?v=${parseInt(new Date().getTime() / 1000)}`).then(d => { loadInfo(d.delete) + }).catch(e => { + loadInfo(false) }) } diff --git a/public/js/core.js b/public/js/core.js index 64d2c4b..203525f 100644 --- a/public/js/core.js +++ b/public/js/core.js @@ -9,22 +9,29 @@ // fetch with progress function fetch(url, opts = {}, onProgress) { return new Promise((res, rej) => { - var xhr = new XMLHttpRequest() - xhr.open(opts.method || 'get', url) - for (var k in opts.headers || {}) - xhr.setRequestHeader(k, opts.headers[k]) - xhr.onload = e => res(JSON.parse(e.target.responseText)) - xhr.onerror = rej - if (xhr.upload && onProgress) - xhr.upload.onprogress = onProgress - xhr.send(opts.body) + try { + var xhr = new XMLHttpRequest() + xhr.open(opts.method || 'get', url) + for (var k in opts.headers || {}) + xhr.setRequestHeader(k, opts.headers[k]) + xhr.onload = e => { + try { + res(JSON.parse(e.target.responseText)) + } catch (e) { + rej(e) + } + } + xhr.onerror = rej + if (xhr.upload && onProgress) + xhr.upload.onprogress = onProgress + xhr.send(opts.body) + } catch (e) { + rej(e) + } }); } function getApiUrl(path) { - if (window.localStorage.getItem('ACCESS_KEY')) { - return path + '?key=' + window.localStorage.getItem('ACCESS_KEY') + `&v=${parseInt(new Date().getTime() / 1000)}` - } return path } @@ -111,6 +118,7 @@ window.goToLink = function(event, link) { event && event.stopPropagation() + if (!link) return window.location.href = link } @@ -143,7 +151,7 @@ }); icons.sort().reverse() return ` - +
diff --git a/public/key.html b/public/key.html deleted file mode 100644 index a685271..0000000 --- a/public/key.html +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - IPA Server - - - - - - - -