mirror of https://github.com/cloudreve/Cloudreve
Feat: hash id decode and verification
parent
880d224169
commit
94b13393a9
|
@ -197,8 +197,7 @@ func (policy *Policy) GetUploadURL() string {
|
||||||
var controller *url.URL
|
var controller *url.URL
|
||||||
switch policy.Type {
|
switch policy.Type {
|
||||||
case "local", "onedrive":
|
case "local", "onedrive":
|
||||||
server = GetSiteURL()
|
return "/api/v3/file/upload"
|
||||||
controller, _ = url.Parse("/api/v3/file/upload")
|
|
||||||
case "remote":
|
case "remote":
|
||||||
controller, _ = url.Parse("/api/v3/slave/upload")
|
controller, _ = url.Parse("/api/v3/slave/upload")
|
||||||
case "oss", "cos":
|
case "oss", "cos":
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/HFO4/cloudreve/pkg/hashid"
|
||||||
"github.com/HFO4/cloudreve/pkg/util"
|
"github.com/HFO4/cloudreve/pkg/util"
|
||||||
"github.com/jinzhu/gorm"
|
"github.com/jinzhu/gorm"
|
||||||
"time"
|
"time"
|
||||||
|
@ -29,3 +30,18 @@ func (share *Share) Create() (uint, error) {
|
||||||
}
|
}
|
||||||
return share.ID, nil
|
return share.ID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetShareByHashID 根据HashID查找分享
|
||||||
|
func GetShareByHashID(hashID string) *Share {
|
||||||
|
id, err := hashid.DecodeHashID(hashID, hashid.ShareID)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var share Share
|
||||||
|
result := DB.First(&share, id)
|
||||||
|
if result.Error != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &share
|
||||||
|
}
|
||||||
|
|
|
@ -233,3 +233,17 @@ func (user *User) SetPassword(password string) error {
|
||||||
user.Password = salt + ":" + string(bs)
|
user.Password = salt + ":" + string(bs)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewAnonymousUser 返回一个匿名用户
|
||||||
|
// TODO 测试
|
||||||
|
func NewAnonymousUser() *User {
|
||||||
|
user := User{}
|
||||||
|
user.Group, _ = GetGroupByID(3)
|
||||||
|
return &user
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsAnonymous 返回是否为未登录用户
|
||||||
|
// TODO 测试
|
||||||
|
func (user *User) IsAnonymous() bool {
|
||||||
|
return user.ID == 0
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package hashid
|
package hashid
|
||||||
|
|
||||||
import "github.com/HFO4/cloudreve/pkg/conf"
|
import (
|
||||||
|
"errors"
|
||||||
|
"github.com/HFO4/cloudreve/pkg/conf"
|
||||||
|
)
|
||||||
import "github.com/speps/go-hashids"
|
import "github.com/speps/go-hashids"
|
||||||
|
|
||||||
// ID类型
|
// ID类型
|
||||||
|
@ -9,6 +12,10 @@ const (
|
||||||
UserID // 用户
|
UserID // 用户
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrTypeNotMatch = errors.New("ID类型不匹配")
|
||||||
|
)
|
||||||
|
|
||||||
// HashEncode 对给定数据计算HashID
|
// HashEncode 对给定数据计算HashID
|
||||||
func HashEncode(v []int) (string, error) {
|
func HashEncode(v []int) (string, error) {
|
||||||
hd := hashids.NewData()
|
hd := hashids.NewData()
|
||||||
|
@ -26,8 +33,32 @@ func HashEncode(v []int) (string, error) {
|
||||||
return id, nil
|
return id, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HashDecode 对给定数据计算原始数据
|
||||||
|
func HashDecode(raw string) ([]int, error) {
|
||||||
|
hd := hashids.NewData()
|
||||||
|
hd.Salt = conf.SystemConfig.HashIDSalt
|
||||||
|
|
||||||
|
h, err := hashids.NewWithData(hd)
|
||||||
|
if err != nil {
|
||||||
|
return []int{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return h.DecodeWithError(raw)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// HashID 计算数据库内主键对应的HashID
|
// HashID 计算数据库内主键对应的HashID
|
||||||
func HashID(id uint, t int) string {
|
func HashID(id uint, t int) string {
|
||||||
v, _ := HashEncode([]int{int(id), t})
|
v, _ := HashEncode([]int{int(id), t})
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DecodeHashID 计算HashID对应的数据库ID
|
||||||
|
// TODO 测试
|
||||||
|
func DecodeHashID(id string, t int) (uint, error) {
|
||||||
|
v, _ := HashDecode(id)
|
||||||
|
if len(v) != 2 || v[1] != t {
|
||||||
|
return 0, ErrTypeNotMatch
|
||||||
|
}
|
||||||
|
return uint(v[0]), nil
|
||||||
|
}
|
||||||
|
|
|
@ -15,3 +15,14 @@ func CreateShare(c *gin.Context) {
|
||||||
c.JSON(200, ErrorResponse(err))
|
c.JSON(200, ErrorResponse(err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetShare 查看分享
|
||||||
|
func GetShare(c *gin.Context) {
|
||||||
|
var service share.ShareGetService
|
||||||
|
if err := c.ShouldBindQuery(&service); err == nil {
|
||||||
|
res := service.Get(c)
|
||||||
|
c.JSON(200, res)
|
||||||
|
} else {
|
||||||
|
c.JSON(200, ErrorResponse(err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -167,6 +167,13 @@ func InitMasterRouter() *gin.Engine {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 分享相关
|
||||||
|
share := v3.Group("share")
|
||||||
|
{
|
||||||
|
// 获取分享
|
||||||
|
share.GET(":id", controllers.GetShare)
|
||||||
|
}
|
||||||
|
|
||||||
// 需要登录保护的
|
// 需要登录保护的
|
||||||
auth := v3.Group("")
|
auth := v3.Group("")
|
||||||
auth.Use(middleware.AuthRequired())
|
auth.Use(middleware.AuthRequired())
|
||||||
|
|
|
@ -19,10 +19,14 @@ type ShareCreateService struct {
|
||||||
Score int `json:"score" binding:"gte=0"`
|
Score int `json:"score" binding:"gte=0"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ShareGetService 获取分享服务
|
||||||
|
type ShareGetService struct {
|
||||||
|
Password string `form:"password" binding:"max=255"`
|
||||||
|
}
|
||||||
|
|
||||||
// Create 创建新分享
|
// Create 创建新分享
|
||||||
func (service *ShareCreateService) Create(c *gin.Context) serializer.Response {
|
func (service *ShareCreateService) Create(c *gin.Context) serializer.Response {
|
||||||
userCtx, _ := c.Get("user")
|
user := currentUser(c)
|
||||||
user := userCtx.(*model.User)
|
|
||||||
|
|
||||||
// 是否拥有权限
|
// 是否拥有权限
|
||||||
if !user.Group.ShareEnabled {
|
if !user.Group.ShareEnabled {
|
||||||
|
@ -80,3 +84,27 @@ func (service *ShareCreateService) Create(c *gin.Context) serializer.Response {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get 获取分享内容
|
||||||
|
func (service *ShareGetService) Get(c *gin.Context) serializer.Response {
|
||||||
|
user := currentUser(c)
|
||||||
|
share := model.GetShareByHashID(c.Param("id"))
|
||||||
|
if share == nil {
|
||||||
|
return serializer.Err(serializer.CodeNotFound, "分享不存在或已被取消", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
return serializer.Response{
|
||||||
|
Code: 0,
|
||||||
|
Data: user,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func currentUser(c *gin.Context) *model.User {
|
||||||
|
var user *model.User
|
||||||
|
if userCtx, ok := c.Get("user"); ok {
|
||||||
|
user = userCtx.(*model.User)
|
||||||
|
} else {
|
||||||
|
user = model.NewAnonymousUser()
|
||||||
|
}
|
||||||
|
return user
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue