Skip to content

Commit

Permalink
Merge pull request #344 from libsgh/dev
Browse files Browse the repository at this point in the history
v3.0.9-part2
  • Loading branch information
libsgh authored Aug 23, 2022
2 parents ab6e642 + 1e5067f commit 83fcfef
Show file tree
Hide file tree
Showing 34 changed files with 1,019 additions and 166 deletions.
14 changes: 9 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,21 @@
- [x] 防盗链
- [x] 短链、分享
- [x] 访问控制
- [x] 分流
- [x] WebDav

## 目前支持的网盘
- 本地目录
- 天翼云网盘
- Teambition(国内、国外)
- 阿里云盘
- [天翼云网盘](https://cloud.189.cn/)
- [Teambition(国内、国外)](https://www.teambition.com/)
- [阿里云盘](https://www.aliyundrive.com/)
- OneDrive(国际版、世纪互联)
- 和彩云
- 谷歌云盘
- [和彩云](https://yun.139.com/)
- [谷歌云盘](https://drive.google.com/)
- WebDav
- FTP
- S3(对象存储)
- [PikPak](https://mypikpak.com "https://mypikpak.com")

## 示例
- [在线演示](https://t1.noki.icu "https://t1.noki.icu")
Expand Down
1 change: 1 addition & 0 deletions boot/boot.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ func InitDb(config BootConfig) {
if config.Dsn != "" {
dsn = config.Dsn
}
dao.DB_TYPE = driver
d, _ := dao.GetDb(driver)
d.CreateDb(dsn)
}
Expand Down
6 changes: 4 additions & 2 deletions control/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,10 @@ func UpdateCache(c *gin.Context) {
}

// admin update all cache
func UpdateAllCache(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"status": 0, "msg": service.UpdateAllCache()})
func BatchUpdateCache(c *gin.Context) {
ids := []string{}
c.BindJSON(&ids)
c.JSON(http.StatusOK, gin.H{"status": 0, "msg": service.BatchUpdateCache(ids)})
}

// admin refresh login status
Expand Down
53 changes: 27 additions & 26 deletions control/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
"strings"
)

func index(c *gin.Context) {
func index(c *gin.Context, isAdminLogin bool) {
var fns []module.FileNode
var isFile bool
tmpFile := strings.Join([]string{"templates/pan/", "/index.html"}, util.GetCurrentTheme(module.GloablConfig.Theme))
Expand All @@ -34,7 +34,7 @@ func index(c *gin.Context) {
status := http.StatusOK
if isSearch {
fns = service.Search(searchKey)
t := Redirect404(c, false)
t := Redirect404(c, false, isAdminLogin)
if t != "" {
tmpFile = t
}
Expand All @@ -45,7 +45,7 @@ func index(c *gin.Context) {
} else {
fns, isFile, lastFile, nextFile = service.Index(ac, path, fullPath, sortColumn, sortOrder, isView)
}
t := Redirect404(c, isFile)
t := Redirect404(c, isFile, isAdminLogin)
if t != "" {
tmpFile = t
}
Expand All @@ -61,30 +61,31 @@ func index(c *gin.Context) {
}
hasParent, parentPath := service.HasParent(fullPath)
c.HTML(status, tmpFile, gin.H{
"title": CurrentTitle(ac, module.GloablConfig, bypassName),
"path": path,
"full_path": fullPath,
"account": ac,
"accounts": service.GetAccounts(),
"config": module.GloablConfig,
"pwd_err_msg": c.GetString("pwd_err_msg"),
"has_pwd": c.GetBool("has_pwd"),
"pwd_path": pwdPath,
"has_parent": hasParent,
"parent_path": parentPath,
"account_path": CurrentAccountPath(ac.Name, bypassName),
"search_key": searchKey,
"pre_paths": util.GetPrePath(fullPath),
"fns": fns,
"theme": theme,
"version": module.VERSION,
"layout": layout,
"last_file": lastFile,
"next_file": nextFile,
"title": CurrentTitle(ac, module.GloablConfig, bypassName),
"path": path,
"full_path": fullPath,
"account": ac,
"accounts": service.GetAccounts(),
"config": module.GloablConfig,
"pwd_err_msg": c.GetString("pwd_err_msg"),
"has_pwd": c.GetBool("has_pwd"),
"pwd_path": pwdPath,
"has_parent": hasParent,
"parent_path": parentPath,
"account_path": CurrentAccountPath(ac.Name, bypassName),
"search_key": searchKey,
"pre_paths": util.GetPrePath(fullPath),
"fns": fns,
"theme": theme,
"version": module.VERSION,
"layout": layout,
"last_file": lastFile,
"next_file": nextFile,
"is_admin_login": isAdminLogin,
})
}

func Redirect404(c *gin.Context, flag bool) string {
func Redirect404(c *gin.Context, flag bool, isAdminLogin bool) string {
_, isView := c.GetQuery("v")
_, isSearch := c.GetQuery("search")
t := "templates/pan/admin/404.html"
Expand All @@ -93,11 +94,11 @@ func Redirect404(c *gin.Context, flag bool) string {
c.Next()
} else if module.GloablConfig.Access == "1" {
//仅直链
if isView || isSearch || !flag {
if !isAdminLogin && (isView || isSearch || !flag) {
c.Abort()
return t
}
} else if module.GloablConfig.Access == "2" {
} else if !isAdminLogin && (module.GloablConfig.Access == "2") {
//直链 + 预览
if isSearch || !flag {
c.Abort()
Expand Down
13 changes: 9 additions & 4 deletions control/middleware/jwt.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,18 @@ func JWTMiddlewar() (*jwt.GinJWTMiddleware, error) {
return "", jwt.ErrMissingLoginValues
}
password := loginVals.Password
if password == module.GloablConfig.AdminPassword {
user := loginVals.User
if user == module.GloablConfig.AdminUser &&
password == module.GloablConfig.AdminPassword {
return &User{
UserName: "admin",
UserName: module.GloablConfig.AdminUser,
}, nil
}

return nil, errors.New("密码错误!请重试")
},
Authorizator: func(data interface{}, c *gin.Context) bool {
if v, ok := data.(*User); ok && v.UserName == "admin" {
if v, ok := data.(*User); ok && v.UserName == module.GloablConfig.AdminUser {
return true
}
return false
Expand All @@ -69,11 +71,14 @@ func JWTMiddlewar() (*jwt.GinJWTMiddleware, error) {
}
},
LogoutResponse: func(c *gin.Context, code int) {
ThemeCheck(c)
theme := c.GetString("theme")
c.HTML(http.StatusOK, "templates/pan/admin/login.html", gin.H{
"error": true,
"msg": "退出成功",
"redirect_url": "login",
"config": module.GloablConfig,
"theme": theme,
})
},
Unauthorized: func(c *gin.Context, code int, message string) {
Expand Down Expand Up @@ -111,7 +116,6 @@ func JWTMiddlewar() (*jwt.GinJWTMiddleware, error) {
TimeFunc: time.Now,
})
errInit := authMiddleware.MiddlewareInit()

if errInit != nil {
log.Fatal("authMiddleware.MiddlewareInit() Error:" + errInit.Error())
}
Expand All @@ -123,6 +127,7 @@ func JWTMiddlewar() (*jwt.GinJWTMiddleware, error) {
}

type Login struct {
User string `form:"user" json:"user" binding:"required"`
Password string `form:"password" json:"password" binding:"required"`
}
type User struct {
Expand Down
68 changes: 41 additions & 27 deletions control/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,31 +25,31 @@ func SetRouters(r *gin.Engine) {
adminApi := api.Group(module.GloablConfig.AdminPath, jwt.MiddlewareFunc())
{
adminApi.GET("/refresh_token", jwt.RefreshHandler)
adminApi.POST("/config/upload", UploadConfig) //upload config
adminApi.POST("/config", SaveConfig) //save config
adminApi.GET("/config", GetConfig) //get config info
adminApi.GET("/account", GetAccount) //get account info
adminApi.POST("/account", SaveAccount) //save account info
adminApi.DELETE("/accounts", DeleteAccounts) //del accounts
adminApi.POST("/accounts/sort", SortAccounts) //sort accounts
adminApi.POST("/cache/update", UpdateCache) //update cache
adminApi.GET("/cache/update/all", UpdateAllCache) //update all cache
adminApi.POST("/refresh/login", RefreshLogin) //refresh login status
adminApi.POST("/upload", Upload) //simple upload file
adminApi.POST("/hide/file", Hide) //add hide file
adminApi.DELETE("/hide/file", DelHide) //del hide file by path
adminApi.POST("/password/file", PwdFile) //add pwd file
adminApi.DELETE("/password/file", DelPwdFile) //del pwd file by path
adminApi.POST("/password/file/upload", UploadPwdFile) //upload pwd file
adminApi.POST("/password/file/share/info", ShareInfo) //upload pwd file
adminApi.POST("/bypass", Bypass) //save bypass config
adminApi.DELETE("/bypass", DelBypass) //del bypass config
adminApi.GET("/bypass", GetBypass) //get bypass by account
adminApi.GET("/cache", GetCache) //get file cache data
adminApi.POST("/cache/clear", CacheClear) //clear file cache
adminApi.POST("/cache/config", CacheConfig) //save cache config
adminApi.GET("/ali/qrcode", AliQrcode) //ali qrcode
adminApi.POST("/ali/qrcode/check", AliQrcodeCheck) //ali qrcode check
adminApi.POST("/config/upload", UploadConfig) //upload config
adminApi.POST("/config", SaveConfig) //save config
adminApi.GET("/config", GetConfig) //get config info
adminApi.GET("/account", GetAccount) //get account info
adminApi.POST("/account", SaveAccount) //save account info
adminApi.DELETE("/accounts", DeleteAccounts) //del accounts
adminApi.POST("/accounts/sort", SortAccounts) //sort accounts
adminApi.POST("/cache/update", UpdateCache) //update cache
adminApi.POST("/cache/update/batch", BatchUpdateCache) //batch update cache
adminApi.POST("/refresh/login", RefreshLogin) //refresh login status
adminApi.POST("/upload", Upload) //simple upload file
adminApi.POST("/hide/file", Hide) //add hide file
adminApi.DELETE("/hide/file", DelHide) //del hide file by path
adminApi.POST("/password/file", PwdFile) //add pwd file
adminApi.DELETE("/password/file", DelPwdFile) //del pwd file by path
adminApi.POST("/password/file/upload", UploadPwdFile) //upload pwd file
adminApi.POST("/password/file/share/info", ShareInfo) //upload pwd file
adminApi.POST("/bypass", Bypass) //save bypass config
adminApi.DELETE("/bypass", DelBypass) //del bypass config
adminApi.GET("/bypass", GetBypass) //get bypass by account
adminApi.GET("/cache", GetCache) //get file cache data
adminApi.POST("/cache/clear", CacheClear) //clear file cache
adminApi.POST("/cache/config", CacheConfig) //save cache config
adminApi.GET("/ali/qrcode", AliQrcode) //ali qrcode
adminApi.POST("/ali/qrcode/check", AliQrcodeCheck) //ali qrcode check
}

admin := r.Group(module.GloablConfig.AdminPath)
Expand Down Expand Up @@ -87,8 +87,22 @@ func SetRouters(r *gin.Engine) {
dav.Handle("MOVE", "/*path", ServeWebDAV)
}
if module.GloablConfig.Access == "3" {
r.NoRoute(middleware.Check, jwt.MiddlewareFunc(), index)
r.NoRoute(middleware.Check, jwt.MiddlewareFunc(), func(c *gin.Context) {
claim, err := jwt.CheckIfTokenExpire(c)
isAdminLogin := false
if err != nil && claim["id"] == module.GloablConfig.AdminUser {
isAdminLogin = true
}
index(c, isAdminLogin)
})
} else {
r.NoRoute(middleware.Check, index)
r.NoRoute(middleware.Check, func(c *gin.Context) {
claim, err := jwt.CheckIfTokenExpire(c)
isAdminLogin := false
if err == nil && claim["id"] == module.GloablConfig.AdminUser {
isAdminLogin = true
}
index(c, isAdminLogin)
})
}
}
2 changes: 1 addition & 1 deletion control/webdav/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func (fs *FileSystem) File(account module.Account, path, fullPath string) (modul
if err != nil {
log.Error(err)
}
if fn.FileId != "" {
if fn.FileId != "" || (fn.FileId == "" && path == "/") {
return fn, true
}
return module.FileNode{}, false
Expand Down
15 changes: 11 additions & 4 deletions dao/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ import (

var DB *gorm.DB
var NewPassword = ""
var DB_TYPE = "sqlite"
var InitConfigItems = []module.ConfigItem{
{"site_name", "", "common"},
{"account_choose", "default", "common"},
{"admin_user", "admin", "common"},
{"admin_password", "PanIndex", "common"},
{"s_column", "default", "common"},
{"s_order", "asc", "common"},
Expand Down Expand Up @@ -197,7 +199,7 @@ func GetPwdFromPath(path string) ([]string, string, bool) {
filePath := ""
now := time.Now().Unix()
likeSql := ""
if _, ok := GetDb("sqlite"); ok {
if DB_TYPE == "sqlite" {
likeSql = "SELECT * FROM pwd_files WHERE ? LIKE file_path || '%' AND (expire_at =0 or expire_at >= ?) ORDER BY LENGTH(file_path) DESC"
} else if _, ok := GetDb("postgres"); ok {
likeSql = "SELECT * FROM pwd_files WHERE ? LIKE concat_ws(file_path, '%') AND (expire_at =0 or expire_at >= ?) ORDER BY LENGTH(file_path) DESC"
Expand Down Expand Up @@ -369,7 +371,6 @@ func SyncAccountStatus(account module.Account) {
var SYNC_STATUS = 0

func SyncFilesCache(account module.Account) {
log.Info(account.SyncDir)
syncDirs := strings.Split(account.SyncDir, ",")
for _, syncDir := range syncDirs {
t1 := time.Now()
Expand Down Expand Up @@ -681,14 +682,14 @@ func SaveAccount(account module.Account) string {
account.SyncCron = ""
account.LastOpTime = time.Now().Format("2006-01-02 15:04:05")
var seq int
DB.Table("account").Raw("select seq from account where 1=1 order by seq desc").First(&seq)
DB.Table("account").Raw("select seq from account where 1=1 order by seq desc limit 1").Take(&seq)
account.Seq = seq + 1
DB.Create(&account)
} else {
account.LastOpTime = time.Now().Format("2006-01-02 15:04:05")
DB.Model(&[]module.Account{}).
Select("Id", "Name", "Mode", "User", "Password", "RefreshToken", "AccessToken", "SiteId",
"RedirectUri", "ApiUrl", "RootId", "LastOpTime", "DownTransfer", "TransferUrl", "Host", "TransferDomain").
"RedirectUri", "ApiUrl", "RootId", "LastOpTime", "DownTransfer", "TransferUrl", "Host", "TransferDomain", "PathStyle", "Info").
Where("id=?", account.Id).
Updates(&account)
}
Expand Down Expand Up @@ -769,3 +770,9 @@ func FileNodeAuth(fn *module.FileNode, hide, hasPwd int) {
}
}
}

func SelectAccountsById(ids []string) []module.Account {
var accounts []module.Account
DB.Where("id IN ?", ids).Find(&accounts)
return accounts
}
2 changes: 1 addition & 1 deletion docs/_coverpage.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
![logo](_media/index.png)

# PanIndex <small>v3.0.8</small>
# PanIndex <small>v3.0.9</small>

> 一个简易的网盘目录列表.
>
Expand Down
22 changes: 19 additions & 3 deletions docs/changelog.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,33 @@
### [v3.0.9](https://nightly.link/libsgh/PanIndex/workflows/nightly-build/dev) (Unreleased)
### [v3.0.9](https://github.com/libsgh/PanIndex/compare/v3.0.8...v3.0.9)

##### Bug Fixes

- 修复文件扩展名为大写时文件类型识别错误 by [wshon](https://github.com/wshon)
- 更新播放器artplayer
- 修复跨域访问错误
- 提高webdav访问兼容性
- 新增网盘时排序错误
- 批量缓存无法并发执行

##### Improve
- 提高WebDav访问兼容性
- 优化暗黑主题显示
- 更新播放器artplayer

##### Features

- [配置管理]增加配置-访问控制
- 公开:自由访问任何未加密、未隐藏的目录、文件
- 仅直链:仅可访问文件下载直链,访问目录会返回404,登录后可显示文件列表
- 直链+预览:可访问文件下载直链、及文件预览页面,访问目录也会返回404,登录后可显示文件列表
- 登录:访问任意文件、目录均需要登录,登录后可以正常访问目录、文件

- [网盘新增]S3、PikPak

- [配置管理]管理接口刷新token

- [配置管理]优化密码配置,有效期、备注、随机密码、导入、生成密码文件短链

- [配置管理]网盘挂载新增备注字段

- 下载直链支持密码参数,可以直接下载密码文件,http://localhost:5238/a/b.txt?pwd=1234

- 支持密码重置,启动时指定参数`--rest_password=1234`
Expand All @@ -23,6 +36,9 @@

- 基于dev分支的自动构建版本,[nightly](https://nightly.link/libsgh/PanIndex/workflows/nightly-build/dev)

- 基于dev分支的docker镜像:iicm/pan-index:dev


### [v3.0.8](https://github.com/libsgh/PanIndex/compare/v3.0.7...v3.0.8) (2022-05-08)

##### Bug Fixes
Expand Down
Loading

1 comment on commit 83fcfef

@vercel
Copy link

@vercel vercel bot commented on 83fcfef Aug 23, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

pan-index – ./

pan-index-libsgh.vercel.app
pan-index-five.vercel.app
pan-index-git-main-libsgh.vercel.app

Please sign in to comment.