Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update #63

Merged
merged 24 commits into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
# builder
FROM golang:1.16 AS builder
FROM golang:1.22.6 AS builder
WORKDIR /src/
COPY go.mod /src/
COPY go.sum /src/
RUN cd /src && go mod download
RUN --mount=type=cache,id=gomod,target=/go/pkg/mod \
--mount=type=cache,id=gobuild,target=/root/.cache/go-build \
go mod download && \
go mod tidy
COPY . /src/
RUN cd /src && go build -ldflags '-linkmode "external" --extldflags "-static"' cmd/ipasd/ipasd.go
RUN --mount=type=cache,id=gomod,target=/go/pkg/mod \
--mount=type=cache,id=gobuild,target=/root/.cache/go-build \
CGO_ENABLED=1 go build -ldflags '-linkmode "external" --extldflags "-static"' cmd/ipasd/ipasd.go

# runtime
FROM ineva/alpine:3.10.3
Expand Down
9 changes: 9 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
VERSION := 2.5
DOCKER_IMAGE := ineva/ipa-server
DOCKER_TARGET := $(DOCKER_IMAGE):$(VERSION)

all:: web

Expand All @@ -12,3 +15,9 @@ build::

test::
go test ./...

image::
docker build --platform linux/amd64 -t $(DOCKER_TARGET) .

push::
docker push $(DOCKER_TARGET)
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ services:
- META_PATH=appList.json
# delete app enabled, true/false
- 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:
Expand Down
5 changes: 5 additions & 0 deletions README_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ services:
- META_PATH=appList.json
# 是否开启删除APP功能, true/false
- 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:
Expand Down
3 changes: 2 additions & 1 deletion cmd/ipasd/doc.go
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
// Package ipa-server's web servie
// Package ipa-server's web servie
package main
20 changes: 16 additions & 4 deletions cmd/ipasd/ipasd.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -91,25 +93,35 @@ 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)),
service.DecodeFindRequest,
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)),
Expand All @@ -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
Expand All @@ -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)))
Expand Down
13 changes: 8 additions & 5 deletions cmd/ipasd/service/appinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ type AppInfo struct {
Size int64 `json:"size"`
NoneIcon bool `json:"noneIcon"`
Type AppInfoType `json:"type"`
// Metadata plist.Plist `json:"metadata"` // metadata from Info.plist
// Metadata
MetaData map[string]interface{} `json:"metaData"`
}

const (
Expand All @@ -34,9 +35,9 @@ const (
func (t AppInfoType) StorageName() string {
switch t {
case AppInfoTypeIpa:
return "ipa.ipa"
return ".ipa"
case AppInfoTypeApk:
return "apk.apk"
return ".apk"
default:
return "unknown"
}
Expand Down Expand Up @@ -66,6 +67,7 @@ type Package interface {
Identifier() string
Build() string
Channel() string
MetaData() map[string]interface{}
Icon() image.Image
Size() int64
}
Expand All @@ -78,6 +80,7 @@ func NewAppInfo(i Package, t AppInfoType) *AppInfo {
Identifier: i.Identifier(),
Build: i.Build(),
Channel: i.Channel(),
MetaData: i.MetaData(),
Date: time.Now(),
Size: i.Size(),
Type: t,
Expand All @@ -89,9 +92,9 @@ func (a *AppInfo) IconStorageName() string {
if a.NoneIcon {
return ""
}
return filepath.Join(a.Identifier, a.ID, "icon.png")
return filepath.Join(a.Identifier, a.ID+".png")
}

func (a *AppInfo) PackageStorageName() string {
return filepath.Join(a.Identifier, a.ID, a.Type.StorageName())
return filepath.Join(a.Identifier, a.ID+a.Type.StorageName())
}
12 changes: 12 additions & 0 deletions cmd/ipasd/service/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
}
27 changes: 20 additions & 7 deletions cmd/ipasd/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import (
"io"
"io/ioutil"
"net/url"
"os"
"path/filepath"
"sort"
"strings"
"sync"
"time"

Expand Down Expand Up @@ -40,6 +42,9 @@ type Item struct {
Version string `json:"version"`
Identifier string `json:"identifier"`

MetaData map[string]interface{} `json:"metaData"`
MetaDataFilter []string `json:"metaDataFilter"`

// package download link
Pkg string `json:"pkg"`
// Icon to display on iOS desktop
Expand All @@ -64,7 +69,7 @@ type Service interface {
Find(id string, publicURL string) (*Item, error)
History(id string, publicURL string) ([]*Item, error)
Delete(id string) error
Add(r Reader, t AppInfoType) error
Add(r Reader, t AppInfoType) (*AppInfo, error)
Plist(id, publicURL string) ([]byte, error)
}

Expand Down Expand Up @@ -171,19 +176,19 @@ func (s *service) Delete(id string) error {
return nil
}

func (s *service) Add(r Reader, t AppInfoType) error {
func (s *service) Add(r Reader, t AppInfoType) (*AppInfo, error) {

app, err := s.addPackage(r, t)
if err != nil {
return err
return nil, err
}

// update list
s.lock.Lock()
s.list = append([]*AppInfo{app}, s.list...)
s.lock.Unlock()

return s.saveMetadata()
return app, s.saveMetadata()
}

func (s *service) addPackage(r Reader, t AppInfoType) (*AppInfo, error) {
Expand All @@ -208,9 +213,6 @@ func (s *service) addPackage(r Reader, t AppInfoType) (*AppInfo, error) {

// new AppInfo
app := NewAppInfo(pkg, t)
if err != nil {
return nil, err
}
// move temp package file to target location
err = s.store.Move(pkgTempFileName, app.PackageStorageName())
if err != nil {
Expand Down Expand Up @@ -320,6 +322,14 @@ func (s *service) itemInfo(row *AppInfo, publicURL string) *Item {
plist = s.servicePublicURL(publicURL, fmt.Sprintf("plist/%v.plist", row.ID))
}

metaDataFilter := []string{}
for _, v := range strings.Split(os.Getenv("META_DATA_FILTER"), ",") {
key := strings.TrimSpace(v)
if len(key) > 0 {
metaDataFilter = append(metaDataFilter, key)
}
}

return &Item{
// from AppInfo
ID: row.ID,
Expand All @@ -332,6 +342,9 @@ func (s *service) itemInfo(row *AppInfo, publicURL string) *Item {
Channel: row.Channel,
Type: row.Type,

MetaData: row.MetaData,
MetaDataFilter: metaDataFilter,

Pkg: s.storagerPublicURL(publicURL, row.PackageStorageName()),
Plist: plist,
Icon: s.iconPublicURL(publicURL, row),
Expand Down
19 changes: 11 additions & 8 deletions cmd/ipasd/service/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,25 +73,21 @@ func MakeAddEndpoint(srv Service) endpoint.Endpoint {
return nil, fmt.Errorf("do not support %s file", path.Ext(p.file.FileName()))
}

if err := srv.Add(buf, t); err != nil {
app, err := srv.Add(buf, t)
if err != nil {
return nil, err
}
return map[string]string{"msg": "ok"}, nil
return map[string]interface{}{"msg": "ok", "data": app}, nil
}
}

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
Expand All @@ -100,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)
Expand Down
8 changes: 8 additions & 0 deletions docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
16 changes: 16 additions & 0 deletions pkg/apk/package_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,22 @@ func (a *APK) Channel() string {
return ""
}

func (a *APK) MetaData() map[string]interface{} {
d := map[string]interface{}{}
for _, r := range a.manifest.App.MetaData {
name, err := r.Name.String()
if err != nil {
continue
}
value, err := r.Value.String()
if err != nil {
continue
}
d[name] = value
}
return d
}

func (a *APK) Icon() image.Image {
return a.icon
}
Expand Down
23 changes: 23 additions & 0 deletions pkg/apk/package_info_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package apk

import (
"fmt"
"testing"

"github.com/shogo82148/androidbinary/apk"
)

func TestApkInfo(t *testing.T) {

a, err := apk.OpenFile("./test.apk")
if err != nil {
t.Fatal(err)
}

for _, m := range a.Manifest().App.MetaData {
name, _ := m.Name.String()
value, _ := m.Value.String()
fmt.Printf("%s: %s\n", name, value)
}

}
Loading
Loading