diff --git a/.marscode/deviceInfo.json b/.marscode/deviceInfo.json new file mode 100644 index 0000000..ff6378d --- /dev/null +++ b/.marscode/deviceInfo.json @@ -0,0 +1,3 @@ +{ + "deviceId": "8f56238c248b96b6f8b965c2f2f9b847422004bbab8228a7ca739364e20175e1" +} \ No newline at end of file diff --git a/gin/filter-gin.go b/gin/filter-gin.go index 6bbde20..bc9296a 100644 --- a/gin/filter-gin.go +++ b/gin/filter-gin.go @@ -65,7 +65,7 @@ func authorize() gin.HandlerFunc { } permissionCode := c.Request.Method + ":" + fullPath - defined, err := service.RbacPermissionDefined(permissionCode) + defined, err := service.RolePermissionDefined(permissionCode) if err != nil { c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{ "data": "权限校验失败", @@ -77,27 +77,14 @@ func authorize() gin.HandlerFunc { return } - roleID, found, err := service.RbacUserRoleIDByUserID(u.ID) - if err != nil { - c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{ - "data": "权限校验失败", - }) - return - } - if !found { - c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{ - "data": "无效TOKEN, 请重新登录!", - }) - return - } - if roleID == nil || *roleID == "" { + if u.RoleID == "" { c.AbortWithStatusJSON(http.StatusForbidden, gin.H{ "data": "无权限访问", }) return } - allowed, err := service.RbacRoleHasPermission(roleID, permissionCode) + allowed, err := service.RoleHasPermission(&u.RoleID, permissionCode) if err != nil { c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{ "data": "权限校验失败", diff --git a/handler/project-handler.go b/handler/project-handler.go index b72e5f3..17c1d81 100644 --- a/handler/project-handler.go +++ b/handler/project-handler.go @@ -105,12 +105,12 @@ func ProjectCreate(c *gin.Context) { p.CompletedAt = completedAt } - out, err := service.ProjectCreateProject(p) + out, err := service.ProjectCreate(p) if err != nil { c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"data": err.Error()}) return } - c.JSON(http.StatusOK, gin.H{"project": out}) + c.JSON(http.StatusOK, gin.H{"data": out}) } func ProjectUpdate(c *gin.Context) { @@ -189,7 +189,7 @@ func ProjectUpdate(c *gin.Context) { patch.Remark = *req.Remark } - out, err := service.ProjectUpdateProject(id, patch) + out, err := service.ProjectUpdate(id, patch) if err != nil { if err == service.ErrNotFound { c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"data": "不存在"}) @@ -198,12 +198,13 @@ func ProjectUpdate(c *gin.Context) { c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"data": err.Error()}) return } - c.JSON(http.StatusOK, gin.H{"project": out}) + c.JSON(http.StatusOK, gin.H{"data": out}) } func ProjectDelete(c *gin.Context) { + usr := currentUser(c) id := c.Param("id") - if err := service.ProjectDelete(id); err != nil { + if err := service.ProjectDelete(usr, &id); err != nil { if err == service.ErrNotFound { c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"data": "不存在"}) return @@ -242,7 +243,7 @@ func ProjectList(c *gin.Context) { kw = &keyword } - items, total, err := service.ProjectList(oid, kw, page, size) + items, total, err := service.ProjectPage(oid, kw, page, size) if err != nil { c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"data": "查询失败"}) return diff --git a/model/device-model.go b/model/device-model.go index 8515d09..8e4a6d9 100644 --- a/model/device-model.go +++ b/model/device-model.go @@ -1,45 +1,41 @@ package model -import "time" +import ( + "time" + + "gorm.io/gorm" +) type Device struct { ID string `json:"id" gorm:"type:varchar(32);primaryKey"` - Name string `json:"name" gorm:"type:varchar(128);not null"` - ModelID string `json:"modelId" gorm:"type:varchar(32);index"` - SerialNo string `json:"serialNo" gorm:"type:varchar(64);index"` - StatusCode string `json:"statusCode" gorm:"type:varchar(64);not null;index"` - PointID string `json:"pointId" gorm:"type:varchar(32);index"` - InstalledAt *time.Time `json:"installedAt"` - InstalledImage string `json:"installedImage" gorm:"type:text;not null"` - - Channel1ParamID string `json:"channel1ParamId" gorm:"type:varchar(32);index"` - Channel2ParamID string `json:"channel2ParamId" gorm:"type:varchar(32);index"` - Channel3ParamID string `json:"channel3ParamId" gorm:"type:varchar(32);index"` - - CreatorUserID string `json:"creatorUserId" gorm:"type:varchar(32);not null;index"` - - Remark string `json:"remark" gorm:"type:varchar(255);default:''"` - Deleted bool `json:"deleted" gorm:"not null;default:false;index"` - CreatedAt time.Time `json:"createdAt" gorm:"autoCreateTime"` - UpdatedAt time.Time `json:"updatedAt" gorm:"autoUpdateTime"` + Name string `json:"name" gorm:"type:varchar(128);not null"` + ModelID string `json:"modelId" gorm:"type:varchar(32);index"` + SerialNo string `json:"serialNo" gorm:"type:varchar(64);index"` + StatusCode string `json:"statusCode" gorm:"type:varchar(64);not null;index"` + PointID string `json:"pointId" gorm:"type:varchar(32);index"` + InstalledAt *time.Time `json:"installedAt"` + InstalledImage string `json:"installedImage" gorm:"type:text;not null"` + Channel1ParamID string `json:"channel1ParamId" gorm:"type:varchar(32);index"` + Channel2ParamID string `json:"channel2ParamId" gorm:"type:varchar(32);index"` + Channel3ParamID string `json:"channel3ParamId" gorm:"type:varchar(32);index"` + CreatorUserID string `json:"creatorUserId" gorm:"type:varchar(32);not null;index"` + Remark string `json:"remark" gorm:"type:varchar(255);default:''"` + DeletedAt gorm.DeletedAt `gorm:"index"` + CreatedAt time.Time `json:"createdAt" gorm:"autoCreateTime"` + UpdatedAt time.Time `json:"updatedAt" gorm:"autoUpdateTime"` } type DeviceIngestData struct { - ID string `json:"id" gorm:"type:varchar(32);primaryKey"` - - DeviceID string `json:"deviceId" gorm:"type:varchar(32);not null;index"` - PointID string `json:"pointId" gorm:"type:varchar(32);not null;index"` - - Raw1 string `json:"raw1" gorm:"type:varchar(64);default:''"` - Raw2 string `json:"raw2" gorm:"type:varchar(64);default:''"` - Raw3 string `json:"raw3" gorm:"type:varchar(64);default:''"` - - Value1 string `json:"value1" gorm:"type:varchar(64);default:''"` - Value2 string `json:"value2" gorm:"type:varchar(64);default:''"` - Value3 string `json:"value3" gorm:"type:varchar(64);default:''"` - - CollectedAt time.Time `json:"collectedAt" gorm:"not null;index"` - - Deleted bool `json:"deleted" gorm:"not null;default:false;index"` + ID string `json:"id" gorm:"type:varchar(32);primaryKey"` + DeviceID string `json:"deviceId" gorm:"type:varchar(32);not null;index"` + PointID string `json:"pointId" gorm:"type:varchar(32);not null;index"` + Raw1 string `json:"raw1" gorm:"type:varchar(64);default:''"` + Raw2 string `json:"raw2" gorm:"type:varchar(64);default:''"` + Raw3 string `json:"raw3" gorm:"type:varchar(64);default:''"` + Value1 string `json:"value1" gorm:"type:varchar(64);default:''"` + Value2 string `json:"value2" gorm:"type:varchar(64);default:''"` + Value3 string `json:"value3" gorm:"type:varchar(64);default:''"` + CollectedAt time.Time `json:"collectedAt" gorm:"not null;index"` + DeletedAt gorm.DeletedAt `gorm:"index"` } diff --git a/model/project-model.go b/model/project-model.go index 80535f1..50d3a17 100644 --- a/model/project-model.go +++ b/model/project-model.go @@ -1,32 +1,31 @@ package model -import "time" +import ( + "time" + + "gorm.io/gorm" +) type Project struct { - ID string `json:"id" gorm:"type:varchar(32);primaryKey"` - - ProjectNo string `json:"projectNo" gorm:"type:varchar(32);not null;uniqueIndex"` - Name string `json:"name" gorm:"type:varchar(100);not null"` - TypeCode string `json:"typeCode" gorm:"type:varchar(64);not null;index"` - BuildingIDs string `json:"buildingIds" gorm:"type:text;not null"` - StatusCode string `json:"statusCode" gorm:"type:varchar(64);not null;index"` - - ResponsibleOrgID string `json:"responsibleOrgId" gorm:"type:varchar(32);not null;index"` - ImplementOrgIDs string `json:"implementOrgIds" gorm:"type:text;not null"` - - LeaderPersonID string `json:"leaderPersonId" gorm:"type:varchar(32);not null;index"` - ParticipantPersonIDs string `json:"participantPersonIds" gorm:"type:text;not null"` - - StartAt time.Time `json:"startAt" gorm:"not null;index"` - EndAt time.Time `json:"endAt" gorm:"not null;index"` - CompletedAt *time.Time `json:"completedAt"` - Description string `json:"description" gorm:"type:text;not null"` - Attachments string `json:"attachments" gorm:"type:text;not null"` - OrgID string `json:"orgId" gorm:"type:varchar(32);not null;index"` - CreatorUserID string `json:"creatorUserId" gorm:"type:varchar(32);not null;index"` - - Remark string `json:"remark" gorm:"type:varchar(255);default:''"` - Deleted bool `json:"deleted" gorm:"not null;default:false;index"` - CreatedAt time.Time `json:"createdAt" gorm:"autoCreateTime"` - UpdatedAt time.Time `json:"updatedAt" gorm:"autoUpdateTime"` + ID string `json:"id" gorm:"type:varchar(32);primaryKey"` + ProjectNo string `json:"projectNo" gorm:"type:varchar(32);not null;uniqueIndex"` + Name string `json:"name" gorm:"type:varchar(100);not null"` + TypeCode string `json:"typeCode" gorm:"type:varchar(64);not null;index"` + BuildingIDs string `json:"buildingIds" gorm:"type:text;not null"` + StatusCode string `json:"statusCode" gorm:"type:varchar(64);not null;index"` + ResponsibleOrgID string `json:"responsibleOrgId" gorm:"type:varchar(32);not null;index"` + ImplementOrgIDs string `json:"implementOrgIds" gorm:"type:text;not null"` + LeaderPersonID string `json:"leaderPersonId" gorm:"type:varchar(32);not null;index"` + ParticipantPersonIDs string `json:"participantPersonIds" gorm:"type:text;not null"` + StartAt time.Time `json:"startAt" gorm:"not null;index"` + EndAt time.Time `json:"endAt" gorm:"not null;index"` + CompletedAt *time.Time `json:"completedAt"` + Description string `json:"description" gorm:"type:text;not null"` + Attachments string `json:"attachments" gorm:"type:text;not null"` + OrgID string `json:"orgId" gorm:"type:varchar(32);not null;index"` + CreatorUserID string `json:"creatorUserId" gorm:"type:varchar(32);not null;index"` + Remark string `json:"remark" gorm:"type:varchar(255);default:''"` + DeletedAt gorm.DeletedAt `gorm:"index"` + CreatedAt time.Time `json:"createdAt" gorm:"autoCreateTime"` + UpdatedAt time.Time `json:"updatedAt" gorm:"autoUpdateTime"` } diff --git a/model/user-model.go b/model/user-model.go index 0d5bb4b..9bc33e0 100644 --- a/model/user-model.go +++ b/model/user-model.go @@ -9,4 +9,6 @@ type User struct { RoleID string `json:"roleId" gorm:"type:varchar(32);index"` Role Role `json:"role" gorm:"foreignKey:RoleID;references:ID"` OrgID string `json:"orgId" gorm:"type:varchar(32);not null;index"` + CreatedAt int64 `json:"createdAt" gorm:"autoCreateTime;"` + UpdatedAt int64 `json:"updatedAt" gorm:"autoUpdateTime;"` } diff --git a/mysql/project-mysql.go b/mysql/project-mysql.go index 5c90ca8..bc84da2 100644 --- a/mysql/project-mysql.go +++ b/mysql/project-mysql.go @@ -20,38 +20,36 @@ func ProjectUpdate(p *model.Project) (bool, error) { if err != nil { return false, err } - tx := db.Model(&model.Project{}).Where("id = ? AND deleted = false", p.ID).Updates(p) + tx := db.Model(&model.Project{}).Where("id = ? AND deleted_at = ?", p.ID).Updates(p) if tx.Error != nil { return false, tx.Error } return tx.RowsAffected > 0, nil } -func ProjectDelete(id *string) (bool, error) { +func ProjectDelete(id *string) error { db, err := newDB() if err != nil { - return false, err + return err } - tx := db.Model(&model.Project{}).Where("id = ? AND deleted = false", *id).Update("deleted", true) - if tx.Error != nil { - return false, tx.Error + if err := db.Model(&model.Project{}).Where("id = ?", *id).Delete(&model.Project{}).Error; err != nil { + return err } - return tx.RowsAffected > 0, nil + return nil } -func ProjectByID(id *string) (*model.Project, bool, error) { +func ProjectFirst(id *string) (*model.Project, error) { db, err := newDB() if err != nil { - return nil, false, err + return nil, err } var p model.Project - if err := db.Where("id = ? AND deleted = false", *id).First(&p).Error; err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - return nil, false, nil + if err := db.Where("id = ?", *id).First(&p).Error; err != nil { + if !errors.Is(err, gorm.ErrRecordNotFound) { + return nil, err } - return nil, false, err } - return &p, true, nil + return &p, nil } func ProjectList(orgID, keyword *string, offset, limit *int) ([]model.Project, int64, error) { @@ -60,7 +58,7 @@ func ProjectList(orgID, keyword *string, offset, limit *int) ([]model.Project, i return nil, 0, err } - q := db.Model(&model.Project{}).Where("deleted = false") + q := db.Model(&model.Project{}) if orgID != nil && *orgID != "" { q = q.Where("org_id = ?", *orgID) } diff --git a/mysql/role-mysql.go b/mysql/role-mysql.go index 94d5262..9c5b5fb 100644 --- a/mysql/role-mysql.go +++ b/mysql/role-mysql.go @@ -1,6 +1,11 @@ package mysql -import "myschools.me/heritage/heritage-api/model" +import ( + "errors" + + "gorm.io/gorm" + "myschools.me/heritage/heritage-api/model" +) func RolePermissionsList(roleID *string) ([]string, error) { db, err := newDB() @@ -15,6 +20,21 @@ func RolePermissionsList(roleID *string) ([]string, error) { return codes, nil } +func RoleFirst(userID *string) (*model.User, error) { + db, err := newDB() + if err != nil { + return nil, err + } + + var u model.User + if err := db.Select("id", "role_id").Where("id = ?", *userID).First(&u).Error; err != nil { + if !errors.Is(err, gorm.ErrRecordNotFound) { + return nil, err + } + } + return &u, nil +} + func RoleHasPermission(roleID, permissionCode *string) (bool, error) { db, err := newDB() if err != nil { diff --git a/mysql/user-mysql.go b/mysql/user-mysql.go index 1cef2d3..321cb5d 100644 --- a/mysql/user-mysql.go +++ b/mysql/user-mysql.go @@ -1,8 +1,6 @@ package mysql import ( - "errors" - "gorm.io/gorm" "myschools.me/heritage/heritage-api/model" ) @@ -38,22 +36,6 @@ func UserFirst(userID *string) (*model.User, error) { return &u, nil } -func UserRoleIDByUserID(userID *string) (*string, bool, error) { - db, err := newDB() - if err != nil { - return nil, false, err - } - - var u model.User - if err := db.Select("id", "role_id").Where("id = ?", *userID).First(&u).Error; err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - return nil, false, nil - } - return nil, false, err - } - return &u.RoleID, true, nil -} - func UserCount() (*int64, error) { db, err := newDB() if err != nil { diff --git a/service/project-service.go b/service/project-service.go index 510eae0..393e1ba 100644 --- a/service/project-service.go +++ b/service/project-service.go @@ -9,7 +9,7 @@ import ( "myschools.me/heritage/heritage-api/mysql" ) -func ProjectCreateProject(p *model.Project) (*model.Project, error) { +func ProjectCreate(p *model.Project) (*model.Project, error) { if p == nil { return nil, errors.New("invalid project") } @@ -47,29 +47,29 @@ func ProjectCreateProject(p *model.Project) (*model.Project, error) { if err := mysql.ProjectCreate(p); err != nil { logrus.WithFields(logrus.Fields{ - "func": "ProjectCreateProject", + "func": "ProjectCreate", }).Warnf("mysql.ProjectCreate: %v", err) return nil, err } return p, nil } -func ProjectUpdateProject(idv string, patch *model.Project) (*model.Project, error) { +func ProjectUpdate(idv string, patch *model.Project) (*model.Project, error) { pid := strings.TrimSpace(idv) if pid == "" { return nil, ErrNotFound } - existing, found, err := mysql.ProjectByID(&pid) + existing, err := mysql.ProjectFirst(&pid) if err != nil { logrus.WithFields(logrus.Fields{ - "func": "ProjectUpdateProject", - }).Warnf("mysql.ProjectByID: %v", err) + "func": "ProjectUpdate", + }).Warnf("mysql.ProjectFirst: %v", err) return nil, err } - if !found || existing == nil { + if existing == nil || existing.ID == "" { logrus.WithFields(logrus.Fields{ - "func": "ProjectUpdateProject", - }).Warnf("mysql.ProjectByID: not found") + "func": "ProjectUpdate", + }).Warnf("mysql.ProjectFirst: not found") return nil, ErrNotFound } if patch == nil { @@ -135,37 +135,38 @@ func ProjectUpdateProject(idv string, patch *model.Project) (*model.Project, err ok, err := mysql.ProjectUpdate(existing) if err != nil { logrus.WithFields(logrus.Fields{ - "func": "ProjectUpdateProject", + "func": "ProjectUpdate", }).Warnf("mysql.ProjectUpdate: %v", err) return nil, err } if !ok { logrus.WithFields(logrus.Fields{ - "func": "ProjectUpdateProject", + "func": "ProjectUpdate", }).Warnf("mysql.ProjectUpdate: not found") return nil, ErrNotFound } return existing, nil } -func ProjectDelete(idv string) error { - pid := strings.TrimSpace(idv) - if pid == "" { - return ErrNotFound - } - ok, err := mysql.ProjectDelete(&pid) +func ProjectDelete(usr *model.User, pid *string) error { + project, err := mysql.ProjectFirst(pid) if err != nil { + logrus.WithFields(logrus.Fields{ + "func": "ProjectDelete", + }).Warnf("mysql.ProjectFirst: %v", err) + return err + } + if project.OrgID != usr.OrgID { + return errors.New("not in org") + } + + if err := mysql.ProjectDelete(pid); err != nil { logrus.WithFields(logrus.Fields{ "func": "ProjectDelete", }).Warnf("mysql.ProjectDelete: %v", err) return err } - if !ok { - logrus.WithFields(logrus.Fields{ - "func": "ProjectDelete", - }).Warnf("mysql.ProjectDelete: not found") - return ErrNotFound - } + return nil } @@ -174,23 +175,23 @@ func ProjectGet(idv string) (*model.Project, error) { if pid == "" { return nil, ErrNotFound } - p, found, err := mysql.ProjectByID(&pid) + p, err := mysql.ProjectFirst(&pid) if err != nil { logrus.WithFields(logrus.Fields{ "func": "ProjectGet", - }).Warnf("mysql.ProjectByID: %v", err) + }).Warnf("mysql.ProjectFirst: %v", err) return nil, err } - if !found || p == nil { + if p == nil || p.ID == "" { logrus.WithFields(logrus.Fields{ "func": "ProjectGet", - }).Warnf("mysql.ProjectByID: not found") + }).Warnf("mysql.ProjectFirst: not found") return nil, ErrNotFound } return p, nil } -func ProjectList(orgID, keyword *string, page, size int) ([]model.Project, int64, error) { +func ProjectPage(orgID, keyword *string, page, size int) ([]model.Project, int64, error) { if page < 1 { page = 1 } diff --git a/service/rbac-service.go b/service/rbac-service.go deleted file mode 100644 index 5f4e03a..0000000 --- a/service/rbac-service.go +++ /dev/null @@ -1,15 +0,0 @@ -package service - -import "myschools.me/heritage/heritage-api/mysql" - -func RbacPermissionDefined(permissionCode string) (bool, error) { - return mysql.PermissionDefined(&permissionCode) -} - -func RbacUserRoleIDByUserID(userID string) (*string, bool, error) { - return mysql.UserRoleIDByUserID(&userID) -} - -func RbacRoleHasPermission(roleID *string, permissionCode string) (bool, error) { - return mysql.RoleHasPermission(roleID, &permissionCode) -} diff --git a/service/role-service.go b/service/role-service.go new file mode 100644 index 0000000..6b22e9b --- /dev/null +++ b/service/role-service.go @@ -0,0 +1,11 @@ +package service + +import "myschools.me/heritage/heritage-api/mysql" + +func RolePermissionDefined(permissionCode string) (bool, error) { + return mysql.PermissionDefined(&permissionCode) +} + +func RoleHasPermission(roleID *string, permissionCode string) (bool, error) { + return mysql.RoleHasPermission(roleID, &permissionCode) +}