Skip to content

Commit

Permalink
feat: add register app store api in sync (#192)
Browse files Browse the repository at this point in the history
  • Loading branch information
CorrectRoadH authored May 28, 2024
1 parent 4ba67b3 commit 279f570
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 17 deletions.
25 changes: 25 additions & 0 deletions api/app_management/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,31 @@ paths:
"500":
$ref: "#/components/responses/ResponseInternalServerError"

# the endpoint is newer version of POST /appstore for the demand of @ETWang1991
# the old api is dependent by CasaOS. So we can't remove it.
# a good idea is /v3/app-management/appstore. But it is hard to implement in ZimaOS
# So I had to add the endpoint here.
/appstore/sync:
post:
summary: Register an app store in Sync.
description: |
(TODO)
operationId: registerAppStoreSync
tags:
- AppStore methods
parameters:
- $ref: "#/components/parameters/AppStoreURL"
responses:
"200":
$ref: "#/components/responses/AppStoreRegisterOK"
"400":
$ref: "#/components/responses/ResponseBadRequest"
"409":
$ref: "#/components/responses/ResponseConflict"
"500":
$ref: "#/components/responses/ResponseInternalServerError"


/appstore:
get:
summary: Get the list of registered app stores
Expand Down
50 changes: 38 additions & 12 deletions route/v2/appstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,36 +30,62 @@ func (a *AppManagement) AppStoreList(ctx echo.Context) error {
})
}

// the method should be deprecated
// but it be used by CasaOS
func (a *AppManagement) RegisterAppStore(ctx echo.Context, params codegen.RegisterAppStoreParams) error {
if params.Url == nil || *params.Url == "" {
message := "appstore url is required"
return ctx.JSON(http.StatusBadRequest, codegen.ResponseBadRequest{Message: &message})
}

isExist := lo.ContainsBy(service.MyService.AppStoreManagement().AppStoreList(), func(appstore codegen.AppStoreMetadata) bool {
return appstore.URL != nil && strings.EqualFold(*appstore.URL, *params.Url)
backgroundCtx := common.WithProperties(context.Background(), PropertiesFromQueryParams(ctx))

if err := service.MyService.AppStoreManagement().RegisterAppStore(backgroundCtx, *params.Url); err != nil {
message := err.Error()

if err != nil {
switch err {
case service.ErrAppStoreSourceExists:
return ctx.JSON(http.StatusConflict, codegen.ResponseConflict{Message: &message})
case service.ErrNotAppStore:
return ctx.JSON(http.StatusBadRequest, codegen.ResponseBadRequest{Message: &message})
default:
return ctx.JSON(http.StatusInternalServerError, codegen.ResponseInternalServerError{Message: &message})
}
}
}

logFilepath := filepath.Join(config.AppInfo.LogPath, fmt.Sprintf("%s.%s", config.AppInfo.LogSaveName, config.AppInfo.LogFileExt))
message := fmt.Sprintf("trying to register app store asynchronously - see %s for any errors.", logFilepath)
return ctx.JSON(http.StatusOK, codegen.AppStoreRegisterOK{
Message: &message,
})
}

if isExist {
message := "appstore is already registered"
return ctx.JSON(http.StatusConflict, codegen.ResponseConflict{Message: &message})
func (a *AppManagement) RegisterAppStoreSync(ctx echo.Context, params codegen.RegisterAppStoreSyncParams) error {
if params.Url == nil || *params.Url == "" {
message := "appstore url is required"
return ctx.JSON(http.StatusBadRequest, codegen.ResponseBadRequest{Message: &message})
}

backgroundCtx := common.WithProperties(context.Background(), PropertiesFromQueryParams(ctx))

if err := service.MyService.AppStoreManagement().RegisterAppStore(backgroundCtx, *params.Url); err != nil {
err := service.MyService.AppStoreManagement().RegisterAppStoreSync(backgroundCtx, *params.Url)
if err != nil {
message := err.Error()
if err == service.ErrNotAppStore {

switch err {
case service.ErrAppStoreSourceExists:
return ctx.JSON(http.StatusConflict, codegen.ResponseConflict{Message: &message})
case service.ErrNotAppStore:
return ctx.JSON(http.StatusBadRequest, codegen.ResponseBadRequest{Message: &message})
default:
return ctx.JSON(http.StatusInternalServerError, codegen.ResponseInternalServerError{Message: &message})
}

return ctx.JSON(http.StatusInternalServerError, codegen.ResponseInternalServerError{Message: &message})
}

logFilepath := filepath.Join(config.AppInfo.LogPath, fmt.Sprintf("%s.%s", config.AppInfo.LogSaveName, config.AppInfo.LogFileExt))
message := fmt.Sprintf("trying to register app store asynchronously - see %s for any errors.", logFilepath)
return ctx.JSON(http.StatusOK, codegen.AppStoreRegisterOK{
Message: &message,
Message: utils.Ptr("app store is registered."),
})
}

Expand Down
71 changes: 66 additions & 5 deletions service/appstore_management.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@ import (
"go.uber.org/zap"
)

var ErrAppStoreSourceExists = fmt.Errorf("appstore source already exists")

type AppStoreManagement struct {
isAppUpgradable gcache.Cache
defaultAppStore AppStore
isAppUpgrading sync.Map
onAppStoreRegister []func(string) error
onAppStoreUnregister []func(string) error

isAppUpgradable gcache.Cache
isAppUpgrading sync.Map
defaultAppStore AppStore
}

func (a *AppStoreManagement) AppStoreList() []codegen.AppStoreMetadata {
Expand Down Expand Up @@ -99,7 +100,7 @@ func (a *AppStoreManagement) RegisterAppStore(ctx context.Context, appstoreURL s
// check if appstore already exists
for _, url := range config.ServerInfo.AppStoreList {
if strings.EqualFold(url, appstoreURL) {
return nil
return ErrAppStoreSourceExists
}
}

Expand Down Expand Up @@ -158,6 +159,66 @@ func (a *AppStoreManagement) RegisterAppStore(ctx context.Context, appstoreURL s
return nil
}

// TODO: refactor the function and above function
func (a *AppStoreManagement) RegisterAppStoreSync(ctx context.Context, appstoreURL string, callbacks ...func(*codegen.AppStoreMetadata)) error {
// check if appstore already exists
for _, url := range config.ServerInfo.AppStoreList {
if strings.EqualFold(url, appstoreURL) {
return ErrAppStoreSourceExists
}
}

appstore, err := AppStoreByURL(appstoreURL)
if err != nil {
return err
}

go PublishEventWrapper(ctx, common.EventTypeAppStoreRegisterBegin, nil)

defer PublishEventWrapper(ctx, common.EventTypeAppStoreRegisterEnd, nil)

defer func() {
if err == nil {
return
}

PublishEventWrapper(ctx, common.EventTypeAppStoreRegisterError, map[string]string{
common.PropertyTypeMessage.Name: err.Error(),
})
}()

if err = appstore.UpdateCatalog(); err != nil {
logger.Error("failed to update appstore catalog", zap.Error(err), zap.String("appstoreURL", appstoreURL))

return err
}

// if everything is good, add to the list
config.ServerInfo.AppStoreList = append(config.ServerInfo.AppStoreList, appstoreURL)

if err = config.SaveSetup(); err != nil {
logger.Error("failed to save appstore list", zap.Error(err), zap.String("appstoreURL", appstoreURL))
return err
}

for _, fn := range a.onAppStoreRegister {
if err := fn(appstoreURL); err != nil {
logger.Error("failed to run onAppStoreRegister", zap.Error(err), zap.String("appstoreURL", appstoreURL))
}
}

appStoreMetadata := &codegen.AppStoreMetadata{
ID: utils.Ptr(len(config.ServerInfo.AppStoreList) - 1),
URL: &appstoreURL,
}

for _, callback := range callbacks {
callback(appStoreMetadata)
}

return nil
}

func (a *AppStoreManagement) UnregisterAppStore(appStoreID uint) error {
if appStoreID >= uint(len(config.ServerInfo.AppStoreList)) {
return fmt.Errorf("appstore id %d out of range", appStoreID)
Expand Down

0 comments on commit 279f570

Please sign in to comment.