fixes #34 「动态指令」多行指令会被当作一行执行

fixes #32 会话无法维持,1分钟左右自动断开
fixes #31 更新"资产"会清空"标签"
fixes #13 建议添加用户权限功能、隐藏授权账户信息
This commit is contained in:
dushixiang 2021-01-18 18:28:33 +08:00
parent c93e03e951
commit c98b3adbe6
26 changed files with 642 additions and 378 deletions

View File

@ -8,7 +8,7 @@ WORKDIR /app
COPY . .
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories
RUN apk add gcc g++
RUN go env && CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -a -ldflags '-linkmode external -extldflags "-static"' -o next-terminal main.go

View File

@ -132,7 +132,7 @@ func Run() error {
if err := global.DB.AutoMigrate(&model.Property{}); err != nil {
return err
}
if err := global.DB.AutoMigrate(&model.Resource{}); err != nil {
if err := global.DB.AutoMigrate(&model.ResourceSharer{}); err != nil {
return err
}
if err := global.DB.AutoMigrate(&model.UserGroup{}); err != nil {

View File

@ -49,7 +49,7 @@ func LoginEndpoint(c echo.Context) error {
return Fail(c, -1, "您输入的账号或密码不正确")
}
if user.TOTPSecret != "" {
if user.TOTPSecret != "" && user.TOTPSecret != "-" {
return Fail(c, 0, "")
}

View File

@ -1,9 +1,11 @@
package api
import (
"fmt"
"github.com/labstack/echo/v4"
"github.com/sirupsen/logrus"
"next-terminal/pkg/global"
"next-terminal/pkg/model"
"strings"
"time"
)
@ -12,6 +14,12 @@ func ErrorHandler(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
if err := next(c); err != nil {
if he, ok := err.(*echo.HTTPError); ok {
message := fmt.Sprintf("%v", he.Message)
return Fail(c, he.Code, message)
}
return Fail(c, 0, err.Error())
}
return nil
@ -21,9 +29,6 @@ func ErrorHandler(next echo.HandlerFunc) echo.HandlerFunc {
func Auth(next echo.HandlerFunc) echo.HandlerFunc {
urls := []string{"download", "recording", "login", "static", "favicon", "logo"}
permissionUrls := H{
"/users": "admin",
}
return func(c echo.Context) error {
// 路由拦截 - 登录身份、资源权限判断等
@ -43,14 +48,6 @@ func Auth(next echo.HandlerFunc) echo.HandlerFunc {
return Fail(c, 401, "您的登录信息已失效,请重新登录后再试。")
}
for url := range permissionUrls {
if strings.HasPrefix(c.Request().RequestURI, url) {
if authorization.(Authorization).User.Type != permissionUrls[url] {
return Fail(c, 403, "permission denied")
}
}
}
if authorization.(Authorization).Remember {
// 记住登录有效期两周
global.Cache.Set(token, authorization, time.Hour*time.Duration(24*14))
@ -61,3 +58,16 @@ func Auth(next echo.HandlerFunc) echo.HandlerFunc {
return next(c)
}
}
func Admin(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
account, _ := GetCurrentAccount(c)
if account.Type != model.TypeAdmin {
return Fail(c, 403, "permission denied")
}
return next(c)
}
}

View File

@ -3,7 +3,6 @@ package api
import (
"github.com/labstack/echo/v4"
"next-terminal/pkg/model"
"strings"
)
type RU struct {
@ -12,8 +11,14 @@ type RU struct {
ResourceIds []string `json:"resourceIds"`
}
func ResourceGetAssignEndPoint(c echo.Context) error {
resourceId := c.Param("id")
type UR struct {
ResourceId string `json:"resourceId"`
ResourceType string `json:"resourceType"`
UserIds []string `json:"userIds"`
}
func RSGetSharersEndPoint(c echo.Context) error {
resourceId := c.QueryParam("resourceId")
userIds, err := model.FindUserIdsByResourceId(resourceId)
if err != nil {
return err
@ -21,13 +26,15 @@ func ResourceGetAssignEndPoint(c echo.Context) error {
return Success(c, userIds)
}
func ResourceOverwriteAssignEndPoint(c echo.Context) error {
resourceId := c.Param("id")
userIds := c.QueryParam("userIds")
resourceType := c.QueryParam("type")
uIds := strings.Split(userIds, ",")
func RSOverwriteSharersEndPoint(c echo.Context) error {
var ur UR
if err := c.Bind(&ur); err != nil {
return err
}
model.OverwriteUserIdsByResourceId(resourceId, resourceType, uIds)
if err := model.OverwriteUserIdsByResourceId(ur.ResourceId, ur.ResourceType, ur.UserIds); err != nil {
return err
}
return Success(c, "")
}

View File

@ -44,20 +44,22 @@ func SetupRoutes() *echo.Echo {
users := e.Group("/users")
{
users.POST("", UserCreateEndpoint)
users.POST("", Admin(UserCreateEndpoint))
users.GET("/paging", UserPagingEndpoint)
users.PUT("/:id", UserUpdateEndpoint)
users.DELETE("/:id", UserDeleteEndpoint)
users.GET("/:id", UserGetEndpoint)
users.PUT("/:id", Admin(UserUpdateEndpoint))
users.DELETE("/:id", Admin(UserDeleteEndpoint))
users.GET("/:id", Admin(UserGetEndpoint))
users.POST("/:id/change-password", Admin(UserChangePasswordEndpoint))
users.POST("/:id/reset-totp", Admin(UserResetTotpEndpoint))
}
userGroups := e.Group("/user-groups")
{
userGroups.POST("", UserGroupCreateEndpoint)
userGroups.GET("/paging", UserGroupPagingEndpoint)
userGroups.PUT("/:id", UserGroupUpdateEndpoint)
userGroups.DELETE("/:id", UserGroupDeleteEndpoint)
userGroups.GET("/:id", UserGroupGetEndpoint)
userGroups.POST("", Admin(UserGroupCreateEndpoint))
userGroups.GET("/paging", Admin(UserGroupPagingEndpoint))
userGroups.PUT("/:id", Admin(UserGroupUpdateEndpoint))
userGroups.DELETE("/:id", Admin(UserGroupDeleteEndpoint))
userGroups.GET("/:id", Admin(UserGroupGetEndpoint))
//userGroups.POST("/:id/members", UserGroupAddMembersEndpoint)
//userGroups.DELETE("/:id/members/:memberId", UserGroupDelMembersEndpoint)
}
@ -71,7 +73,7 @@ func SetupRoutes() *echo.Echo {
assets.PUT("/:id", AssetUpdateEndpoint)
assets.DELETE("/:id", AssetDeleteEndpoint)
assets.GET("/:id", AssetGetEndpoint)
assets.POST("/:id/change-owner", AssetChangeOwnerEndpoint)
assets.POST("/:id/change-owner", Admin(AssetChangeOwnerEndpoint))
}
e.GET("/tags", AssetTagsEndpoint)
@ -83,7 +85,7 @@ func SetupRoutes() *echo.Echo {
commands.PUT("/:id", CommandUpdateEndpoint)
commands.DELETE("/:id", CommandDeleteEndpoint)
commands.GET("/:id", CommandGetEndpoint)
commands.POST("/:id/change-owner", CommandChangeOwnerEndpoint)
commands.POST("/:id/change-owner", Admin(CommandChangeOwnerEndpoint))
}
credentials := e.Group("/credentials")
@ -94,7 +96,7 @@ func SetupRoutes() *echo.Echo {
credentials.PUT("/:id", CredentialUpdateEndpoint)
credentials.DELETE("/:id", CredentialDeleteEndpoint)
credentials.GET("/:id", CredentialGetEndpoint)
credentials.POST("/:id/change-owner", CredentialChangeOwnerEndpoint)
credentials.POST("/:id/change-owner", Admin(CredentialChangeOwnerEndpoint))
}
sessions := e.Group("/sessions")
@ -102,7 +104,7 @@ func SetupRoutes() *echo.Echo {
sessions.POST("", SessionCreateEndpoint)
sessions.GET("/paging", SessionPagingEndpoint)
sessions.POST("/:id/content", SessionContentEndpoint)
sessions.POST("/:id/discontent", SessionDiscontentEndpoint)
sessions.POST("/:id/discontent", Admin(SessionDiscontentEndpoint))
sessions.POST("/:id/resize", SessionResizeEndpoint)
sessions.POST("/:id/upload", SessionUploadEndpoint)
sessions.GET("/:id/download", SessionDownloadEndpoint)
@ -111,20 +113,20 @@ func SetupRoutes() *echo.Echo {
sessions.DELETE("/:id/rmdir", SessionRmDirEndpoint)
sessions.DELETE("/:id/rm", SessionRmEndpoint)
sessions.DELETE("/:id", SessionDeleteEndpoint)
sessions.GET("/:id/recording", SessionRecordingEndpoint)
sessions.GET("/:id/recording", Admin(SessionRecordingEndpoint))
sessions.GET("/:id", SessionGetEndpoint)
}
resources := e.Group("/resources")
resourceSharers := e.Group("/resource-sharers")
{
resources.GET("/:id/assign", ResourceGetAssignEndPoint)
resources.POST("/:id/assign", ResourceOverwriteAssignEndPoint)
resources.POST("/remove", ResourceRemoveByUserIdAssignEndPoint)
resources.POST("/add", ResourceAddByUserIdAssignEndPoint)
resourceSharers.GET("/sharers", RSGetSharersEndPoint)
resourceSharers.POST("/overwrite-sharers", RSOverwriteSharersEndPoint)
resourceSharers.POST("/remove-resources", Admin(ResourceRemoveByUserIdAssignEndPoint))
resourceSharers.POST("/add-resources", Admin(ResourceAddByUserIdAssignEndPoint))
}
e.GET("/properties", PropertyGetEndpoint)
e.PUT("/properties", PropertyUpdateEndpoint)
e.PUT("/properties", Admin(PropertyUpdateEndpoint))
e.GET("/overview/counter", OverviewCounterEndPoint)
e.GET("/overview/sessions", OverviewSessionPoint)
@ -174,15 +176,16 @@ func GetCurrentAccount(c echo.Context) (model.User, bool) {
}
func HasPermission(c echo.Context, owner string) bool {
// 检测是否为创建者
// 检测是否登录
account, found := GetCurrentAccount(c)
if !found {
return false
}
// 检测是否为管理人员
if model.TypeAdmin == account.Type {
return true
}
// 检测是否为所有者
if owner == account.ID {
return true
}

View File

@ -103,6 +103,15 @@ func CloseSessionById(sessionId string, code int, reason string) {
CloseSessionByWebSocket(tun.WebSocket, code, reason)
}
s, err := model.FindSessionById(sessionId)
if err != nil {
return
}
if s.Status == model.Disconnected {
return
}
global.Store.Del(sessionId)
session := model.Session{}
session.ID = sessionId

View File

@ -27,7 +27,6 @@ func UserCreateEndpoint(c echo.Context) error {
if err := model.CreateNewUser(&item); err != nil {
return err
}
return Success(c, item)
}
@ -89,3 +88,27 @@ func UserGetEndpoint(c echo.Context) error {
return Success(c, item)
}
func UserChangePasswordEndpoint(c echo.Context) error {
id := c.Param("id")
password := c.QueryParam("password")
passwd, err := utils.Encoder.Encode([]byte(password))
if err != nil {
return err
}
u := &model.User{
Password: string(passwd),
}
model.UpdateUserById(u, id)
return Success(c, "")
}
func UserResetTotpEndpoint(c echo.Context) error {
id := c.Param("id")
u := &model.User{
TOTPSecret: "-",
}
model.UpdateUserById(u, id)
return Success(c, "")
}

View File

@ -49,11 +49,11 @@ func FindAllAsset() (o []Asset, err error) {
}
func FindAssetByConditions(protocol string, account User) (o []Asset, err error) {
db := global.DB.Table("assets").Select("assets.id,assets.name,assets.ip,assets.port,assets.protocol,assets.active,assets.owner,assets.created, users.nickname as owner_name,COUNT(resources.user_id) as sharer_count").Joins("left join users on assets.owner = users.id").Joins("left join resources on assets.id = resources.resource_id").Group("assets.id")
db := global.DB.Table("assets").Select("assets.id,assets.name,assets.ip,assets.port,assets.protocol,assets.active,assets.owner,assets.created, users.nickname as owner_name,COUNT(resource_sharers.user_id) as sharer_count").Joins("left join users on assets.owner = users.id").Joins("left join resource_sharers on assets.id = resource_sharers.resource_id").Group("assets.id")
if TypeUser == account.Type {
owner := account.ID
db = db.Where("assets.owner = ? or resources.user_id = ?", owner, owner)
db = db.Where("assets.owner = ? or resource_sharers.user_id = ?", owner, owner)
}
if len(protocol) > 0 {
@ -64,21 +64,21 @@ func FindAssetByConditions(protocol string, account User) (o []Asset, err error)
}
func FindPageAsset(pageIndex, pageSize int, name, protocol, tags string, account User, owner, sharer string) (o []AssetVo, total int64, err error) {
db := global.DB.Table("assets").Select("assets.id,assets.name,assets.ip,assets.port,assets.protocol,assets.active,assets.owner,assets.created, users.nickname as owner_name,COUNT(resources.user_id) as sharer_count").Joins("left join users on assets.owner = users.id").Joins("left join resources on assets.id = resources.resource_id").Group("assets.id")
dbCounter := global.DB.Table("assets").Select("DISTINCT assets.id").Joins("left join resources on assets.id = resources.resource_id")
db := global.DB.Table("assets").Select("assets.id,assets.name,assets.ip,assets.port,assets.protocol,assets.active,assets.owner,assets.created, users.nickname as owner_name,COUNT(resource_sharers.user_id) as sharer_count").Joins("left join users on assets.owner = users.id").Joins("left join resource_sharers on assets.id = resource_sharers.resource_id").Group("assets.id")
dbCounter := global.DB.Table("assets").Select("DISTINCT assets.id").Joins("left join resource_sharers on assets.id = resource_sharers.resource_id")
if TypeUser == account.Type {
owner := account.ID
db = db.Where("assets.owner = ? or resources.user_id = ?", owner, owner)
dbCounter = dbCounter.Where("assets.owner = ? or resources.user_id = ?", owner, owner)
db = db.Where("assets.owner = ? or resource_sharers.user_id = ?", owner, owner)
dbCounter = dbCounter.Where("assets.owner = ? or resource_sharers.user_id = ?", owner, owner)
} else {
if len(owner) > 0 {
db = db.Where("assets.owner = ?", owner)
dbCounter = dbCounter.Where("assets.owner = ?", owner)
}
if len(sharer) > 0 {
db = db.Where("resources.user_id = ?", sharer)
dbCounter = dbCounter.Where("resources.user_id = ?", sharer)
db = db.Where("resource_sharers.user_id = ?", sharer)
dbCounter = dbCounter.Where("resource_sharers.user_id = ?", sharer)
}
}

View File

@ -29,13 +29,13 @@ func (r *Command) TableName() string {
func FindPageCommand(pageIndex, pageSize int, name, content string, account User) (o []CommandVo, total int64, err error) {
db := global.DB.Table("commands").Select("commands.id,commands.name,commands.content,commands.owner,commands.created, users.nickname as owner_name,COUNT(resources.user_id) as sharer_count").Joins("left join users on commands.owner = users.id").Joins("left join resources on commands.id = resources.resource_id").Group("commands.id")
dbCounter := global.DB.Table("commands").Select("DISTINCT commands.id").Joins("left join resources on commands.id = resources.resource_id")
db := global.DB.Table("commands").Select("commands.id,commands.name,commands.content,commands.owner,commands.created, users.nickname as owner_name,COUNT(resource_sharers.user_id) as sharer_count").Joins("left join users on commands.owner = users.id").Joins("left join resource_sharers on commands.id = resource_sharers.resource_id").Group("commands.id")
dbCounter := global.DB.Table("commands").Select("DISTINCT commands.id").Joins("left join resource_sharers on commands.id = resource_sharers.resource_id")
if TypeUser == account.Type {
owner := account.ID
db = db.Where("commands.owner = ? or resources.user_id = ?", owner, owner)
dbCounter = dbCounter.Where("commands.owner = ? or resources.user_id = ?", owner, owner)
db = db.Where("commands.owner = ? or resource_sharers.user_id = ?", owner, owner)
dbCounter = dbCounter.Where("commands.owner = ? or resource_sharers.user_id = ?", owner, owner)
}
if len(name) > 0 {

View File

@ -44,22 +44,22 @@ type CredentialSimpleVo struct {
}
func FindAllCredential(account User) (o []CredentialSimpleVo, err error) {
db := global.DB.Table("credentials").Select("DISTINCT credentials.id,credentials.name").Joins("left join resources on credentials.id = resources.resource_id")
db := global.DB.Table("credentials").Select("DISTINCT credentials.id,credentials.name").Joins("left join resource_sharers on credentials.id = resource_sharers.resource_id")
if account.Type == TypeUser {
db = db.Where("credentials.owner = ? or resources.user_id = ?", account.ID, account.ID)
db = db.Where("credentials.owner = ? or resource_sharers.user_id = ?", account.ID, account.ID)
}
err = db.Find(&o).Error
return
}
func FindPageCredential(pageIndex, pageSize int, name string, account User) (o []CredentialVo, total int64, err error) {
db := global.DB.Table("credentials").Select("credentials.id,credentials.name,credentials.type,credentials.username,credentials.owner,credentials.created,users.nickname as owner_name,COUNT(resources.user_id) as sharer_count").Joins("left join users on credentials.owner = users.id").Joins("left join resources on credentials.id = resources.resource_id").Group("credentials.id")
dbCounter := global.DB.Table("credentials").Select("DISTINCT credentials.id").Joins("left join resources on credentials.id = resources.resource_id")
db := global.DB.Table("credentials").Select("credentials.id,credentials.name,credentials.type,credentials.username,credentials.owner,credentials.created,users.nickname as owner_name,COUNT(resource_sharers.user_id) as sharer_count").Joins("left join users on credentials.owner = users.id").Joins("left join resource_sharers on credentials.id = resource_sharers.resource_id").Group("credentials.id")
dbCounter := global.DB.Table("credentials").Select("DISTINCT credentials.id").Joins("left join resource_sharers on credentials.id = resource_sharers.resource_id")
if TypeUser == account.Type {
owner := account.ID
db = db.Where("credentials.owner = ? or resources.user_id = ?", owner, owner)
dbCounter = dbCounter.Where("credentials.owner = ? or resources.user_id = ?", owner, owner)
db = db.Where("credentials.owner = ? or resource_sharers.user_id = ?", owner, owner)
dbCounter = dbCounter.Where("credentials.owner = ? or resource_sharers.user_id = ?", owner, owner)
}
if len(name) > 0 {

View File

@ -0,0 +1,128 @@
package model
import (
"github.com/labstack/echo/v4"
"gorm.io/gorm"
"next-terminal/pkg/global"
"next-terminal/pkg/utils"
)
type ResourceSharer struct {
ID string `gorm:"primary_key" json:"name"`
ResourceId string `json:"resourceId"`
ResourceType string `json:"resourceType"`
UserId string `json:"userId"`
}
func (r *ResourceSharer) TableName() string {
return "resource_sharers"
}
func FindUserIdsByResourceId(resourceId string) (r []string, err error) {
db := global.DB
err = db.Table("resource_sharers").Select("user_id").Where("resource_id = ?", resourceId).Find(&r).Error
if r == nil {
r = make([]string, 0)
}
return
}
func OverwriteUserIdsByResourceId(resourceId, resourceType string, userIds []string) (err error) {
db := global.DB.Begin()
var owner string
// 检查资产是否存在
switch resourceType {
case "asset":
resource := Asset{}
err = db.Where("id = ?", resourceId).First(&resource).Error
owner = resource.Owner
case "command":
resource := Command{}
err = db.Where("id = ?", resourceId).First(&resource).Error
owner = resource.Owner
case "credential":
resource := Credential{}
err = db.Where("id = ?", resourceId).First(&resource).Error
owner = resource.Owner
}
if err == gorm.ErrRecordNotFound {
return echo.NewHTTPError(404, "资源「"+resourceId+"」不存在")
}
for i := range userIds {
if owner == userIds[i] {
return echo.NewHTTPError(400, "参数错误")
}
}
db.Where("resource_id = ?", resourceId).Delete(&ResourceSharer{})
for i := range userIds {
userId := userIds[i]
if len(userId) == 0 {
continue
}
id := utils.Sign([]string{resourceId, resourceType, userId})
resource := &ResourceSharer{
ID: id,
ResourceId: resourceId,
ResourceType: resourceType,
UserId: userId,
}
err = db.Create(resource).Error
if err != nil {
return err
}
}
db.Commit()
return nil
}
func DeleteByUserIdAndResourceTypeAndResourceIdIn(userId, resourceType string, resourceIds []string) error {
return global.DB.Where("user_id = ? and resource_type = ? and resource_id in ?", userId, resourceType, resourceIds).Delete(&ResourceSharer{}).Error
}
func AddSharerResources(userId, resourceType string, resourceIds []string) error {
return global.DB.Transaction(func(tx *gorm.DB) (err error) {
for i := range resourceIds {
resourceId := resourceIds[i]
var owner string
// 检查资产是否存在
switch resourceType {
case "asset":
resource := Asset{}
err = tx.Where("id = ?", resourceId).First(&resource).Error
owner = resource.Owner
case "command":
resource := Command{}
err = tx.Where("id = ?", resourceId).First(&resource).Error
owner = resource.Owner
case "credential":
resource := Credential{}
err = tx.Where("id = ?", resourceId).First(&resource).Error
owner = resource.Owner
}
if owner == userId {
return echo.NewHTTPError(400, "参数错误")
}
id := utils.Sign([]string{resourceId, resourceType, userId})
resource := &ResourceSharer{
ID: id,
ResourceId: resourceId,
ResourceType: resourceType,
UserId: userId,
}
err = tx.Create(resource).Error
if err != nil {
return err
}
}
return nil
})
}

View File

@ -1,73 +0,0 @@
package model
import (
"gorm.io/gorm"
"next-terminal/pkg/global"
"next-terminal/pkg/utils"
)
type Resource struct {
ID string `gorm:"primary_key" json:"name"`
ResourceId string `json:"resourceId"`
ResourceType string `json:"resourceType"`
UserId string `json:"userId"`
}
func (r *Resource) TableName() string {
return "resources"
}
func FindUserIdsByResourceId(resourceId string) (r []string, err error) {
db := global.DB
err = db.Table("resources").Select("user_id").Where("resource_id = ?", resourceId).Find(&r).Error
if r == nil {
r = make([]string, 0)
}
return
}
func OverwriteUserIdsByResourceId(resourceId, resourceType string, userIds []string) {
db := global.DB.Begin()
db.Where("resource_id = ?", resourceId).Delete(&Resource{})
for i := range userIds {
userId := userIds[i]
if len(userId) == 0 {
continue
}
id := utils.Sign([]string{resourceId, resourceType, userId})
resource := &Resource{
ID: id,
ResourceId: resourceId,
ResourceType: resourceType,
UserId: userId,
}
_ = db.Create(resource).Error
}
db.Commit()
}
func DeleteByUserIdAndResourceTypeAndResourceIdIn(userId, resourceType string, resourceIds []string) error {
return global.DB.Where("user_id = ? and resource_type = ? and resource_id in ?", userId, resourceType, resourceIds).Delete(&Resource{}).Error
}
func AddSharerResources(userId, resourceType string, resourceIds []string) error {
return global.DB.Transaction(func(tx *gorm.DB) (err error) {
for i := range resourceIds {
resourceId := resourceIds[i]
id := utils.Sign([]string{resourceId, resourceType, userId})
resource := &Resource{
ID: id,
ResourceId: resourceId,
ResourceType: resourceType,
UserId: userId,
}
err = tx.Create(resource).Error
if err != nil {
return err
}
}
return nil
})
}

View File

@ -24,15 +24,14 @@ type User struct {
}
type UserVo struct {
ID string `gorm:"primary_key" json:"id"`
Username string `json:"username"`
Nickname string `json:"nickname"`
Online bool `json:"online"`
Enabled bool `json:"enabled"`
Created utils.JsonTime `json:"created"`
Type string `json:"type"`
//OwnerAssetCount int64 `json:"ownerAssetCount"`
SharerAssetCount int64 `json:"sharerAssetCount"`
ID string `gorm:"primary_key" json:"id"`
Username string `json:"username"`
Nickname string `json:"nickname"`
Online bool `json:"online"`
Enabled bool `json:"enabled"`
Created utils.JsonTime `json:"created"`
Type string `json:"type"`
SharerAssetCount int64 `json:"sharerAssetCount"`
}
func (r *User) TableName() string {
@ -51,7 +50,7 @@ func FindAllUser() (o []User) {
}
func FindPageUser(pageIndex, pageSize int, username, nickname string) (o []UserVo, total int64, err error) {
db := global.DB.Table("users").Select("users.id,users.username,users.nickname,users.online,users.enabled,users.created,users.type, count(resources.user_id) as sharer_asset_count").Joins("left join resources on users.id = resources.user_id and resources.resource_type = 'asset'").Group("users.id")
db := global.DB.Table("users").Select("users.id,users.username,users.nickname,users.online,users.enabled,users.created,users.type, count(resource_sharers.user_id) as sharer_asset_count").Joins("left join resource_sharers on users.id = resource_sharers.user_id and resource_sharers.resource_type = 'asset'").Group("users.id")
dbCounter := global.DB.Table("users")
if len(username) > 0 {
db = db.Where("users.username like ?", "%"+username+"%")

View File

@ -95,10 +95,6 @@ class App extends Component {
}
subMenuChange = (openKeys) => {
console.debug("current open keys");
console.table(openKeys);
this.setState({
openKeys: openKeys
})

View File

@ -247,6 +247,14 @@ class Asset extends Component {
tags = r2['data'];
}
if (asset['tags'] && typeof (asset['tags']) === 'string') {
if (asset['tags'] === '-') {
asset['tags'] = [];
} else {
asset['tags'] = asset['tags'].split(',');
}
}
this.setState({
modalTitle: title,
modalVisible: true,
@ -269,8 +277,9 @@ class Asset extends Component {
modalConfirmLoading: true
});
if (formData['tagArr']) {
formData.tags = formData['tagArr'].join(',');
console.log(formData)
if (formData['tags']) {
formData.tags = formData['tags'].join(',');
}
if (formData.id) {
@ -368,7 +377,7 @@ class Asset extends Component {
handleShowSharer = async (record) => {
let r1 = this.handleSearchByNickname('');
let r2 = request.get(`/resources/${record['id']}/assign`);
let r2 = request.get(`/resource-sharers/sharers?resourceId=${record['id']}`);
await r1;
let result = await r2;
@ -380,10 +389,20 @@ class Asset extends Component {
selectedSharers = result['data'];
}
let users = this.state.users;
users = users.map(item => {
let disabled = false;
if (record['owner'] === item['id']) {
disabled = true;
}
return {...item, 'disabled': disabled}
});
this.setState({
selectedSharers: selectedSharers,
selected: record,
changeSharerModalVisible: true
changeSharerModalVisible: true,
users: users
})
}
@ -687,9 +706,8 @@ class Asset extends Component {
: null
}
<Modal title={<text>更换资源<strong style={{color: '#1890ff'}}>{this.state.selected['name']}</strong>
</text>}
<Modal title={<Text>更换资源<strong style={{color: '#1890ff'}}>{this.state.selected['name']}</strong>
</Text>}
visible={this.state.changeOwnerModalVisible}
confirmLoading={this.state.changeOwnerConfirmLoading}
onOk={() => {
@ -746,54 +764,64 @@ class Asset extends Component {
</Form>
</Modal>
<Modal title={<text>更新资源<strong style={{color: '#1890ff'}}>{this.state.selected['name']}</strong>
</text>}
visible={this.state.changeSharerModalVisible}
confirmLoading={this.state.changeSharerConfirmLoading}
onOk={async () => {
this.setState({
changeSharerConfirmLoading: true
});
let changeSharerModalVisible = false;
{
this.state.changeSharerModalVisible ?
<Modal title={<Text>更新资源<strong
style={{color: '#1890ff'}}>{this.state.selected['name']}</strong>
</Text>}
visible={this.state.changeSharerModalVisible}
confirmLoading={this.state.changeSharerConfirmLoading}
onOk={async () => {
this.setState({
changeSharerConfirmLoading: true
});
let result = await request.post(`/resources/${this.state.selected['id']}/assign?type=asset&userIds=${this.state.selectedSharers.join(',')}`);
if (result['code'] === 1) {
message.success('操作成功');
this.loadTableData();
} else {
message.error(result['message'], 10);
changeSharerModalVisible = true;
}
let changeSharerModalVisible = false;
this.setState({
changeSharerConfirmLoading: false,
changeSharerModalVisible: changeSharerModalVisible
})
}}
onCancel={() => {
this.setState({
changeSharerModalVisible: false
})
}}
okButtonProps={{disabled: !hasPermission(this.state.selected['owner'])}}
>
let result = await request.post(`/resource-sharers/overwrite-sharers`, {
resourceId: this.state.selected['id'],
resourceType: 'asset',
userIds: this.state.selectedSharers
});
if (result['code'] === 1) {
message.success('操作成功');
this.loadTableData();
} else {
message.error(result['message'], 10);
changeSharerModalVisible = true;
}
this.setState({
changeSharerConfirmLoading: false,
changeSharerModalVisible: changeSharerModalVisible
})
}}
onCancel={() => {
this.setState({
changeSharerModalVisible: false
})
}}
okButtonProps={{disabled: !hasPermission(this.state.selected['owner'])}}
>
<Transfer
dataSource={this.state.users}
disabled={!hasPermission(this.state.selected['owner'])}
showSearch
titles={['未授权', '已授权']}
operations={['授权', '移除']}
listStyle={{
width: 250,
height: 300,
}}
targetKeys={this.state.selectedSharers}
onChange={this.handleSharersChange}
render={item => `${item.nickname}`}
/>
</Modal> : undefined
}
<Transfer
dataSource={this.state.users}
disabled={!hasPermission(this.state.selected['owner'])}
showSearch
titles={['未授权', '已授权']}
operations={['授权', '移除']}
listStyle={{
width: 250,
height: 300,
}}
targetKeys={this.state.selectedSharers}
onChange={this.handleSharersChange}
render={item => `${item.nickname}`}
/>
</Modal>
</Content>
</>
);

View File

@ -39,13 +39,6 @@ const AssetModal = function ({title, visible, handleOk, handleCancel, confirmLoa
}
}
let initAssetTags = [];
if (!isEmpty(model['tags'])) {
initAssetTags = model['tags'].split(',');
}
let [assetTags, setAssetTags] = useState(initAssetTags);
const formItemLayout = {
labelCol: {span: 6},
wrapperCol: {span: 14},
@ -100,10 +93,6 @@ const AssetModal = function ({title, visible, handleOk, handleCancel, confirmLoa
model.accountType = v;
}
const handleTagsChange = v => {
setAssetTags(v);
}
return (
<Modal
@ -209,8 +198,8 @@ const AssetModal = function ({title, visible, handleOk, handleCancel, confirmLoa
: null
}
<Form.Item label="标签" name='tagArr'>
<Select mode="tags" placeholder="请选择标签" defaultValue={assetTags} onChange={handleTagsChange}>
<Form.Item label="标签" name='tags'>
<Select mode="tags" placeholder="请选择标签">
{tags.map(tag => {
if (tag === '-') {
return undefined;

View File

@ -311,7 +311,7 @@ class DynamicCommand extends Component {
handleShowSharer = async (record) => {
let r1 = this.handleSearchByNickname('');
let r2 = request.get(`/resources/${record['id']}/assign`);
let r2 = request.get(`/resource-sharers/sharers?resourceId=${record['id']}`);
await r1;
let result = await r2;
@ -323,10 +323,20 @@ class DynamicCommand extends Component {
selectedSharers = result['data'];
}
let users = this.state.users;
users = users.map(item => {
let disabled = false;
if (record['owner'] === item['id']) {
disabled = true;
}
return {...item, 'disabled': disabled}
});
this.setState({
selectedSharers: selectedSharers,
selected: record,
changeSharerModalVisible: true
changeSharerModalVisible: true,
users: users
})
}
@ -657,8 +667,8 @@ class DynamicCommand extends Component {
</Modal>
<Modal title={<text>更换资源<strong style={{color: '#1890ff'}}>{this.state.selected['name']}</strong>
</text>}
<Modal title={<Text>更换资源<strong style={{color: '#1890ff'}}>{this.state.selected['name']}</strong>
</Text>}
visible={this.state.changeOwnerModalVisible}
confirmLoading={this.state.changeOwnerConfirmLoading}
onOk={() => {
@ -715,54 +725,63 @@ class DynamicCommand extends Component {
</Form>
</Modal>
<Modal title={<text>更新资源<strong style={{color: '#1890ff'}}>{this.state.selected['name']}</strong>
</text>}
visible={this.state.changeSharerModalVisible}
confirmLoading={this.state.changeSharerConfirmLoading}
onOk={async () => {
this.setState({
changeSharerConfirmLoading: true
});
{
this.state.changeSharerModalVisible ?
<Modal title={<Text>更新资源<strong
style={{color: '#1890ff'}}>{this.state.selected['name']}</strong>
</Text>}
visible={this.state.changeSharerModalVisible}
confirmLoading={this.state.changeSharerConfirmLoading}
onOk={async () => {
this.setState({
changeSharerConfirmLoading: true
});
let changeSharerModalVisible = false;
let changeSharerModalVisible = false;
let result = await request.post(`/resources/${this.state.selected['id']}/assign?type=command&userIds=${this.state.selectedSharers.join(',')}`);
if (result['code'] === 1) {
message.success('操作成功');
this.loadTableData();
} else {
message.error(result['message'], 10);
changeSharerModalVisible = true;
}
let result = await request.post(`/resource-sharers/overwrite-sharers`, {
resourceId: this.state.selected['id'],
resourceType: 'command',
userIds: this.state.selectedSharers
});
if (result['code'] === 1) {
message.success('操作成功');
this.loadTableData();
} else {
message.error(result['message'], 10);
changeSharerModalVisible = true;
}
this.setState({
changeSharerConfirmLoading: false,
changeSharerModalVisible: changeSharerModalVisible
})
}}
onCancel={() => {
this.setState({
changeSharerModalVisible: false
})
}}
okButtonProps={{disabled: !hasPermission(this.state.selected['owner'])}}
>
this.setState({
changeSharerConfirmLoading: false,
changeSharerModalVisible: changeSharerModalVisible
})
}}
onCancel={() => {
this.setState({
changeSharerModalVisible: false
})
}}
okButtonProps={{disabled: !hasPermission(this.state.selected['owner'])}}
>
<Transfer
dataSource={this.state.users}
disabled={!hasPermission(this.state.selected['owner'])}
showSearch
titles={['未授权', '已授权']}
operations={['授权', '移除']}
listStyle={{
width: 250,
height: 300,
}}
targetKeys={this.state.selectedSharers}
onChange={this.handleSharersChange}
render={item => `${item.nickname}`}
/>
</Modal> : undefined
}
<Transfer
dataSource={this.state.users}
disabled={!hasPermission(this.state.selected['owner'])}
showSearch
titles={['未授权', '已授权']}
operations={['授权', '移除']}
listStyle={{
width: 250,
height: 300,
}}
targetKeys={this.state.selectedSharers}
onChange={this.handleSharersChange}
render={item => `${item.nickname}`}
/>
</Modal>
</Content>
</>

View File

@ -44,11 +44,11 @@ const DynamicCommandModal = ({title, visible, handleOk, handleCancel, confirmLoa
</Form.Item>
<Form.Item label="指令名称" name='name' rules={[{required: true, message: '请输入指令名称'}]}>
<Input placeholder="请输入指令内容"/>
<Input placeholder="请输入指令名称"/>
</Form.Item>
<Form.Item label="指令内容" name='content' rules={[{required: true, message: '请输入指令内容'}]}>
<TextArea autoSize={{ minRows: 5, maxRows: 10 }} placeholder="一行一个命令"/>
<TextArea autoSize={{minRows: 5, maxRows: 10}} placeholder="多行指令也会当做一行执行,请使用 && 或 其他方式进行连接"/>
</Form.Item>
</Form>

View File

@ -278,7 +278,7 @@ class Credential extends Component {
}
const items = result['data']['items'].map(item => {
return {'key': item['id'], ...item}
return {'key': item['id'], 'disabled': false, ...item}
})
this.setState({
@ -294,7 +294,7 @@ class Credential extends Component {
handleShowSharer = async (record) => {
let r1 = this.handleSearchByNickname('');
let r2 = request.get(`/resources/${record['id']}/assign`);
let r2 = request.get(`/resource-sharers/sharers?resourceId=${record['id']}`);
await r1;
let result = await r2;
@ -306,10 +306,20 @@ class Credential extends Component {
selectedSharers = result['data'];
}
let users = this.state.users;
users = users.map(item => {
let disabled = false;
if (record['owner'] === item['id']) {
disabled = true;
}
return {...item, 'disabled': disabled}
});
this.setState({
selectedSharers: selectedSharers,
selected: record,
changeSharerModalVisible: true
changeSharerModalVisible: true,
users: users
})
}
@ -573,7 +583,8 @@ class Credential extends Component {
: null
}
<Modal title={<text>更换资源<strong style={{color: '#1890ff'}}>{this.state.selected['name']}</strong></text>}
<Modal title={<Text>更换资源<strong style={{color: '#1890ff'}}>{this.state.selected['name']}</strong>
</Text>}
visible={this.state.changeOwnerModalVisible}
confirmLoading={this.state.changeOwnerConfirmLoading}
onOk={() => {
@ -627,53 +638,63 @@ class Credential extends Component {
</Form>
</Modal>
<Modal title={<text>更新资源<strong style={{color: '#1890ff'}}>{this.state.selected['name']}</strong></text>}
visible={this.state.changeSharerModalVisible}
confirmLoading={this.state.changeSharerConfirmLoading}
onOk={async () => {
this.setState({
changeSharerConfirmLoading: true
});
{
this.state.changeSharerModalVisible ?
<Modal title={<Text>更新资源<strong
style={{color: '#1890ff'}}>{this.state.selected['name']}</strong>
</Text>}
visible={this.state.changeSharerModalVisible}
confirmLoading={this.state.changeSharerConfirmLoading}
onOk={async () => {
this.setState({
changeSharerConfirmLoading: true
});
let changeSharerModalVisible = false;
let changeSharerModalVisible = false;
let result = await request.post(`/resources/${this.state.selected['id']}/assign?type=credential&userIds=${this.state.selectedSharers.join(',')}`);
if (result['code'] === 1) {
message.success('操作成功');
this.loadTableData();
} else {
message.error(result['message'], 10);
changeSharerModalVisible = true;
}
let result = await request.post(`/resource-sharers/overwrite-sharers`, {
resourceId: this.state.selected['id'],
resourceType: 'credential',
userIds: this.state.selectedSharers
});
if (result['code'] === 1) {
message.success('操作成功');
this.loadTableData();
} else {
message.error(result['message'], 10);
changeSharerModalVisible = true;
}
this.setState({
changeSharerConfirmLoading: false,
changeSharerModalVisible: changeSharerModalVisible
})
}}
onCancel={() => {
this.setState({
changeSharerModalVisible: false
})
}}
okButtonProps={{disabled: !hasPermission(this.state.selected['owner'])}}
>
this.setState({
changeSharerConfirmLoading: false,
changeSharerModalVisible: changeSharerModalVisible
})
}}
onCancel={() => {
this.setState({
changeSharerModalVisible: false
})
}}
okButtonProps={{disabled: !hasPermission(this.state.selected['owner'])}}
>
<Transfer
dataSource={this.state.users}
disabled={!hasPermission(this.state.selected['owner'])}
showSearch
titles={['未授权', '已授权']}
operations={['授权', '移除']}
listStyle={{
width: 250,
height: 300,
}}
targetKeys={this.state.selectedSharers}
onChange={this.handleSharersChange}
render={item => `${item.nickname}`}
/>
</Modal> : undefined
}
<Transfer
dataSource={this.state.users}
disabled={!hasPermission(this.state.selected['owner'])}
showSearch
titles={['未授权', '已授权']}
operations={['授权', '移除']}
listStyle={{
width: 250,
height: 300,
}}
targetKeys={this.state.selectedSharers}
onChange={this.handleSharersChange}
render={item => `${item.nickname}`}
/>
</Modal>
</Content>
</>
);

View File

@ -22,14 +22,7 @@ import request from "../../common/request";
import {differTime, formatDate, itemRender} from "../../utils/utils";
import Playback from "./Playback";
import {message} from "antd/es";
import {
DeleteOutlined,
DeleteTwoTone,
ExclamationCircleOutlined,
PlaySquareTwoTone,
SyncOutlined,
UndoOutlined
} from "@ant-design/icons";
import {DeleteOutlined, ExclamationCircleOutlined, SyncOutlined, UndoOutlined} from "@ant-design/icons";
import {PROTOCOL_COLORS} from "../../common/constants";
import Logout from "../user/Logout";

View File

@ -22,14 +22,7 @@ import request from "../../common/request";
import {differTime, formatDate, itemRender} from "../../utils/utils";
import {message} from "antd/es";
import {PROTOCOL_COLORS} from "../../common/constants";
import {
ApiTwoTone,
DisconnectOutlined,
ExclamationCircleOutlined,
EyeTwoTone,
SyncOutlined,
UndoOutlined
} from "@ant-design/icons";
import {DisconnectOutlined, ExclamationCircleOutlined, SyncOutlined, UndoOutlined} from "@ant-design/icons";
import Monitor from "../access/Monitor";
import Logout from "../user/Logout";
@ -287,10 +280,10 @@ class OnlineSession extends Component {
return (
<div>
<Button type="link" size='small' icon={<EyeTwoTone/>} onClick={() => {
<Button type="link" size='small' onClick={() => {
this.showMonitor(record)
}}>监控</Button>
<Button type="link" size='small' icon={<ApiTwoTone/>} onClick={async () => {
<Button type="link" size='small' onClick={async () => {
confirm({
title: '您确定要断开此会话吗?',

View File

@ -6,8 +6,11 @@ import {
Button,
Col,
Divider,
Dropdown,
Form,
Input,
Layout,
Menu,
Modal,
PageHeader,
Row,
@ -21,9 +24,18 @@ import qs from "qs";
import UserModal from "./UserModal";
import request from "../../common/request";
import {message} from "antd/es";
import {DeleteOutlined, ExclamationCircleOutlined, PlusOutlined, SyncOutlined, UndoOutlined} from '@ant-design/icons';
import {
DeleteOutlined,
DownOutlined,
ExclamationCircleOutlined,
LockOutlined,
PlusOutlined,
SyncOutlined,
UndoOutlined
} from '@ant-design/icons';
import Logout from "./Logout";
import UserShareAsset from "./UserShareAsset";
import {hasPermission} from "../../service/permission";
const confirm = Modal.confirm;
const {Search} = Input;
@ -45,6 +57,7 @@ class User extends Component {
inputRefOfNickname = React.createRef();
inputRefOfUsername = React.createRef();
changePasswordFormRef = React.createRef()
state = {
items: [],
@ -60,7 +73,10 @@ class User extends Component {
model: null,
selectedRowKeys: [],
delBtnLoading: false,
assetVisible: false
assetVisible: false,
changePasswordVisible: false,
changePasswordConfirmLoading: false,
selectedRow: {}
};
componentDidMount() {
@ -246,6 +262,24 @@ class User extends Component {
})
}
handleChangePassword = async (values) => {
this.setState({
changePasswordConfirmLoading: true
})
let result = await request.post(`/users/${this.state.selectedRow['id']}/change-password?password=${values['password']}`);
if (result['code'] === 1) {
message.success('操作成功', 3);
} else {
message.error(result['message'], 10);
}
this.setState({
changePasswordConfirmLoading: false,
changePasswordVisible: false
})
}
render() {
const columns = [{
@ -294,7 +328,7 @@ class User extends Component {
}
}
}, {
title: '共享资产',
title: '授权资产',
dataIndex: 'sharerAssetCount',
key: 'sharerAssetCount',
render: (text, record, index) => {
@ -315,13 +349,56 @@ class User extends Component {
key: 'action',
render: (text, record) => {
const menu = (
<Menu>
<Menu.Item key="1">
<Button type="text" size='small'
onClick={() => {
this.setState({
changePasswordVisible: true,
selectedRow: record
})
}}>修改密码</Button>
</Menu.Item>
<Menu.Item key="2">
<Button type="text" size='small'
onClick={() => {
confirm({
title: '您确定要重置此用户的双因素认证吗?',
content: record['name'],
okText: '确定',
cancelText: '取消',
onOk: async () => {
let result = await request.post(`/users/${record['id']}/reset-totp`);
if (result['code'] === 1) {
message.success('操作成功', 3);
} else {
message.error(result['message'], 10);
}
}
});
}}>重置双因素认证</Button>
</Menu.Item>
<Menu.Divider/>
<Menu.Item key="5">
<Button type="text" size='small' danger
disabled={!hasPermission(record['owner'])}
onClick={() => this.showDeleteConfirm(record.id, record.name)}>删除</Button>
</Menu.Item>
</Menu>
);
return (
<div>
<Button type="link" size='small'
onClick={() => this.showModal('更新用户', record)}>编辑</Button>
<Button type="link" size='small'
onClick={() => this.showDeleteConfirm(record.id, record.name)}>删除</Button>
<Dropdown overlay={menu}>
<Button type="link" size='small'>
更多 <DownOutlined/>
</Button>
</Dropdown>
</div>
)
},
@ -511,7 +588,7 @@ class User extends Component {
<Modal
width={window.innerWidth * 0.8}
title='已共享资产'
title='已授权资产'
visible={this.state.assetVisible}
maskClosable={false}
destroyOnClose={true}
@ -528,6 +605,37 @@ class User extends Component {
owner={this.state.owner}
/>
</Modal>
{
this.state.changePasswordVisible ?
<Modal title="修改密码" visible={this.state.changePasswordVisible}
confirmLoading={this.state.changePasswordConfirmLoading}
onOk={() => {
this.changePasswordFormRef.current
.validateFields()
.then(values => {
this.changePasswordFormRef.current.resetFields();
this.handleChangePassword(values);
})
.catch(info => {
});
}}
onCancel={() => {
this.setState({
changePasswordVisible: false
})
}}>
<Form ref={this.changePasswordFormRef}>
<Form.Item name='password' rules={[{required: true, message: '请输入新密码'}]}>
<Input prefix={<LockOutlined/>} placeholder="请输入新密码"/>
</Form.Item>
</Form>
</Modal> : undefined
}
</Content>
</>
);

View File

@ -233,7 +233,7 @@ class UserShareAsset extends Component {
<div style={{marginBottom: 20}}>
<Row justify="space-around" align="middle" gutter={24}>
<Col span={8} key={1}>
<Title level={3}>共享资产列表</Title>
<Title level={3}>授权资产列表</Title>
</Col>
<Col span={16} key={2} style={{textAlign: 'right'}}>
<Space>
@ -284,7 +284,7 @@ class UserShareAsset extends Component {
<Divider type="vertical"/>
<Tooltip title="新增">
<Tooltip title="添加授权资产">
<Button type="dashed" icon={<PlusOutlined/>}
onClick={() => {
this.setState({
@ -303,20 +303,20 @@ class UserShareAsset extends Component {
</Button>
</Tooltip>
<Tooltip title="移除共享">
<Tooltip title="移除授权资产">
<Button type="dashed" danger disabled={!hasSelected} icon={<DeleteOutlined/>}
loading={this.state.delBtnLoading}
onClick={() => {
const content = <div>
您确定要移除选中的<Text style={{color: '#1890FF'}}
strong>{this.state.selectedRowKeys.length}</Text>
strong>{this.state.selectedRowKeys.length}</Text>
</div>;
confirm({
icon: <ExclamationCircleOutlined/>,
content: content,
onOk: async () => {
let userId = this.state.queryParams.sharer;
let result = await request.post(`/resources/remove`, {
let result = await request.post(`/resource-sharers/remove-resources`, {
userId: userId,
resourceType: 'asset',
resourceIds: this.state.selectedRowKeys
@ -363,7 +363,7 @@ class UserShareAsset extends Component {
{this.state.chooseAssetVisible ?
<Drawer
title="添加资产"
title="添加授权资产"
placement="right"
closable={true}
onClose={() => {

View File

@ -1,21 +1,6 @@
import React, {Component} from 'react';
import {
Badge,
Button,
Col,
Divider,
Input,
Layout,
Modal,
Row,
Select,
Space,
Table,
Tag,
Tooltip,
Typography
} from "antd";
import {Badge, Button, Col, Divider, Input, Layout, Row, Select, Space, Table, Tag, Tooltip, Typography} from "antd";
import qs from "qs";
import request from "../../common/request";
import {message} from "antd/es";
@ -24,10 +9,9 @@ import {message} from "antd/es";
import {PlusOutlined, SyncOutlined, UndoOutlined} from '@ant-design/icons';
import {PROTOCOL_COLORS} from "../../common/constants";
const confirm = Modal.confirm;
const {Search} = Input;
const {Content} = Layout;
const {Title, Text} = Typography;
const {Title} = Typography;
class UserShareAsset extends Component {
@ -63,23 +47,30 @@ class UserShareAsset extends Component {
this.setState({
sharer: this.props.sharer
})
let r2 = await request.get('/assets/paging?pageIndex=1&pageSize=1000&sharer=' + this.props.sharer);
if (r2['code'] === 1) {
let items = r2['data']['items'];
this.setState({
totalSelectedRows: items
})
}
this.loadTableData();
this.init(this.props.sharer)
}
let result = await request.get('/tags');
if (result['code'] === 1) {
async init(sharer) {
let q1 = request.get('/tags');
let q2 = request.get('/assets/paging?pageIndex=1&pageSize=1000&sharer=' + sharer);
let r1 = await q1;
let r2 = await q2;
if (r1['code'] === 1) {
this.setState({
tags: result['data']
tags: r1['data']
})
}
if (r2['code'] === 1) {
this.setState({
totalSelectedRows: r2['data']['items']
})
}
}
async loadTableData(queryParams) {
@ -107,8 +98,13 @@ class UserShareAsset extends Component {
} catch (e) {
} finally {
let sharer = this.state.sharer;
const items = data.items.map(item => {
return {'key': item['id'], ...item}
let disabled = false;
if (sharer === item['owner']) {
disabled = true;
}
return {...item, 'key': item['id'], 'disabled': disabled}
})
let totalSelectedRows = this.state.totalSelectedRows;
let selectedRowKeys = totalSelectedRows.map(item => item['id']);
@ -172,7 +168,7 @@ class UserShareAsset extends Component {
unSelectRow = async (assetId) => {
let userId = this.state.sharer;
let result = await request.post(`/resources/remove`, {
let result = await request.post(`/resource-sharers/remove-resources`, {
userId: userId,
resourceType: 'asset',
resourceIds: [assetId]
@ -259,6 +255,9 @@ class UserShareAsset extends Component {
onChange: (selectedRowKeys, selectedRows) => {
this.setState({selectedRowKeys, selectedRows});
},
getCheckboxProps: (record) => ({
disabled: record['disabled'],
}),
};
let hasSelected = false;
if (selectedRowKeys.length > 0) {
@ -275,7 +274,7 @@ class UserShareAsset extends Component {
return (
<>
<Title level={3}>共享资产列表</Title>
<Title level={3}>授权资产列表</Title>
<div>
{
this.state.totalSelectedRows.map(item => {
@ -350,7 +349,7 @@ class UserShareAsset extends Component {
</Button>
</Tooltip>
<Tooltip title="添加共享">
<Tooltip title="添加授权">
<Button type="primary" disabled={!hasSelected} icon={<PlusOutlined/>}
onClick={async () => {
console.log(this.state.selectedRows)
@ -369,7 +368,7 @@ class UserShareAsset extends Component {
}
let userId = this.state.sharer;
let result = await request.post(`/resources/add`, {
let result = await request.post(`/resource-sharers/add-resources`, {
userId: userId,
resourceType: 'asset',
resourceIds: newRowKeys

View File

@ -2,6 +2,9 @@ import {isEmpty} from "../utils/utils";
export function hasPermission(owner) {
let userJsonStr = sessionStorage.getItem('user');
if (isEmpty(userJsonStr)) {
return false;
}
let user = JSON.parse(userJsonStr);
if (user['type'] === 'admin') {
return true;
@ -10,11 +13,20 @@ export function hasPermission(owner) {
return user['id'] === owner;
}
export function isAdmin(){
export function isAdmin() {
let userJsonStr = sessionStorage.getItem('user');
if(isEmpty(userJsonStr)){
if (isEmpty(userJsonStr)) {
return false;
}
let user = JSON.parse(userJsonStr);
return user['type'] === 'admin';
}
export function getCurrentUser() {
let userJsonStr = sessionStorage.getItem('user');
if (isEmpty(userJsonStr)) {
return {};
}
return JSON.parse(userJsonStr);
}