Skip to content

Commit 945eece

Browse files
authored
Merge pull request #314 from actiontech/support_issue_288
support workflow operation permission
2 parents 612abf7 + b615edc commit 945eece

File tree

6 files changed

+228
-18
lines changed

6 files changed

+228
-18
lines changed

sqle/api/controller/v1/task.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -216,10 +216,18 @@ func checkCurrentUserCanAccessTask(c echo.Context, task *model.Task) error {
216216
if err != nil {
217217
return err
218218
}
219-
if !access {
220-
return ErrTaskNoAccess
219+
if access {
220+
return nil
221+
}
222+
223+
ok, err := s.CheckUserHasOpToInstance(user, task.Instance, []uint{model.OP_WORKFLOW_VIEW_OTHERS})
224+
if err != nil {
225+
return err
226+
}
227+
if ok {
228+
return nil
221229
}
222-
return nil
230+
return ErrTaskNoAccess
223231
}
224232

225233
// @Summary 获取Sql审核任务信息

sqle/api/controller/v1/workflow.go

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ package v1
22

33
import (
44
"fmt"
5-
"github.com/actiontech/sqle/sqle/driver"
65
"net/http"
76
"strconv"
87
"time"
98

9+
"github.com/actiontech/sqle/sqle/driver"
10+
1011
"github.com/actiontech/sqle/sqle/api/controller"
1112
"github.com/actiontech/sqle/sqle/errors"
1213
"github.com/actiontech/sqle/sqle/log"
@@ -609,7 +610,7 @@ type WorkflowStepResV1 struct {
609610
Reason string `json:"reason,omitempty"`
610611
}
611612

612-
func checkCurrentUserCanAccessWorkflow(c echo.Context, workflow *model.Workflow) error {
613+
func checkCurrentUserCanAccessWorkflow(c echo.Context, workflow *model.Workflow, ops []uint) error {
613614
if controller.GetUserName(c) == model.DefaultAdminUser {
614615
return nil
615616
}
@@ -622,10 +623,23 @@ func checkCurrentUserCanAccessWorkflow(c echo.Context, workflow *model.Workflow)
622623
if err != nil {
623624
return err
624625
}
625-
if !access {
626-
return ErrWorkflowNoAccess
626+
if access {
627+
return nil
627628
}
628-
return nil
629+
if len(ops) > 0 {
630+
instance, err := s.GetInstanceByWorkflowID(workflow.ID)
631+
if err != nil {
632+
return err
633+
}
634+
ok, err := s.CheckUserHasOpToInstance(user, instance, ops)
635+
if err != nil {
636+
return err
637+
}
638+
if ok {
639+
return nil
640+
}
641+
}
642+
return ErrWorkflowNoAccess
629643
}
630644

631645
func convertWorkflowToRes(workflow *model.Workflow, task *model.Task) *WorkflowResV1 {
@@ -763,7 +777,7 @@ func GetWorkflow(c echo.Context) error {
763777
}
764778
err = checkCurrentUserCanAccessWorkflow(c, &model.Workflow{
765779
Model: model.Model{ID: uint(id)},
766-
})
780+
}, []uint{model.OP_WORKFLOW_VIEW_OTHERS})
767781
if err != nil {
768782
return controller.JSONBaseErrorReq(c, err)
769783
}
@@ -904,7 +918,7 @@ func GetWorkflows(c echo.Context) error {
904918
"offset": offset,
905919
}
906920
s := model.GetStorage()
907-
workflows, count, err := s.GetWorkflowsByReq(data)
921+
workflows, count, err := s.GetWorkflowsByReq(data, user)
908922
if err != nil {
909923
return controller.JSONBaseErrorReq(c, err)
910924
}
@@ -970,7 +984,7 @@ func ApproveWorkflow(c echo.Context) error {
970984
}
971985
err = checkCurrentUserCanAccessWorkflow(c, &model.Workflow{
972986
Model: model.Model{ID: uint(id)},
973-
})
987+
}, []uint{})
974988
if err != nil {
975989
return controller.JSONBaseErrorReq(c, err)
976990
}
@@ -1052,7 +1066,7 @@ func RejectWorkflow(c echo.Context) error {
10521066
}
10531067
err = checkCurrentUserCanAccessWorkflow(c, &model.Workflow{
10541068
Model: model.Model{ID: uint(id)},
1055-
})
1069+
}, []uint{})
10561070
if err != nil {
10571071
return controller.JSONBaseErrorReq(c, err)
10581072
}
@@ -1116,7 +1130,7 @@ func CancelWorkflow(c echo.Context) error {
11161130
}
11171131
err = checkCurrentUserCanAccessWorkflow(c, &model.Workflow{
11181132
Model: model.Model{ID: uint(id)},
1119-
})
1133+
}, []uint{})
11201134
if err != nil {
11211135
return controller.JSONBaseErrorReq(c, err)
11221136
}
@@ -1227,7 +1241,7 @@ func UpdateWorkflow(c echo.Context) error {
12271241
}
12281242
err = checkCurrentUserCanAccessWorkflow(c, &model.Workflow{
12291243
Model: model.Model{ID: uint(id)},
1230-
})
1244+
}, []uint{})
12311245
if err != nil {
12321246
return controller.JSONBaseErrorReq(c, err)
12331247
}
@@ -1354,7 +1368,7 @@ func UpdateWorkflowSchedule(c echo.Context) error {
13541368
}
13551369
err = checkCurrentUserCanAccessWorkflow(c, &model.Workflow{
13561370
Model: model.Model{ID: uint(id)},
1357-
})
1371+
}, []uint{})
13581372
if err != nil {
13591373
return controller.JSONBaseErrorReq(c, err)
13601374
}
@@ -1415,7 +1429,7 @@ func ExecuteTaskOnWorkflow(c echo.Context) error {
14151429
}
14161430
err = checkCurrentUserCanAccessWorkflow(c, &model.Workflow{
14171431
Model: model.Model{ID: uint(id)},
1418-
})
1432+
}, []uint{})
14191433
if err != nil {
14201434
return controller.JSONBaseErrorReq(c, err)
14211435
}

sqle/errors/errors.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ const (
1212

1313
HttpRequestFormatError ErrorCode = 2001
1414

15+
ErrAccessDeniedError ErrorCode = 3001
16+
1517
LoginAuthFail ErrorCode = 4001
1618
UserDisabled ErrorCode = 4005
1719
TaskNotExist ErrorCode = 4006
@@ -94,3 +96,7 @@ func HttpRequestFormatErrWrapper(err error) error {
9496
func ConnectStorageErrWrapper(err error) error {
9597
return New(ConnectStorageError, err)
9698
}
99+
100+
func NewAccessDeniedErr(format string, a ...interface{}) error {
101+
return New(ErrAccessDeniedError, fmt.Errorf(format, a...))
102+
}

sqle/model/instance.go

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,3 +183,146 @@ func (s *Storage) GetInstanceNamesByWorkflowTemplateId(id uint) ([]string, error
183183
}
184184
return names, nil
185185
}
186+
187+
func (s *Storage) CheckUserHasOpToInstance(user *User, instance *Instance, ops []uint) (bool, error) {
188+
query := `
189+
SELECT instances.id
190+
FROM instances
191+
LEFT JOIN instance_role ON instance_role.instance_id = instances.id
192+
LEFT JOIN roles ON roles.id = instance_role.role_id AND roles.deleted_at IS NULL AND roles.stat = 0
193+
LEFT JOIN role_operations ON role_operations.role_id = roles.id
194+
LEFT JOIN user_role ON user_role.role_id = roles.id
195+
LEFT JOIN users ON users.id = user_role.user_id AND users.stat = 0
196+
WHERE
197+
instances.deleted_at IS NULL
198+
AND instances.id = ?
199+
AND users.id = ?
200+
AND role_operations.op_code IN (?)
201+
GROUP BY instances.id
202+
UNION
203+
SELECT instances.id
204+
FROM instances
205+
LEFT JOIN instance_role ON instance_role.instance_id = instances.id
206+
LEFT JOIN roles ON roles.id = instance_role.role_id AND roles.deleted_at IS NULL AND roles.stat = 0
207+
LEFT JOIN role_operations ON role_operations.role_id = roles.id
208+
JOIN user_group_roles ON roles.id = user_group_roles.role_id
209+
JOIN user_groups ON user_groups.id = user_group_roles.user_group_id AND user_groups.deleted_at IS NULL
210+
JOIN user_group_users ON user_groups.id = user_group_users.user_group_id
211+
JOIN users ON users.id = user_group_users.user_id AND users.deleted_at IS NULL AND users.stat=0
212+
WHERE
213+
instances.deleted_at IS NULL
214+
AND instances.id = ?
215+
AND users.id = ?
216+
AND role_operations.op_code IN (?)
217+
GROUP BY instances.id
218+
`
219+
var instances []*Instance
220+
err := s.db.Raw(query, instance.ID, user.ID, ops, instance.ID, user.ID, ops).Scan(&instances).Error
221+
if err != nil {
222+
return false, errors.ConnectStorageErrWrapper(err)
223+
}
224+
return len(instances) > 0, nil
225+
}
226+
227+
func (s *Storage) GetUserCanOpInstances(user *User, ops []uint) (instances []*Instance, err error) {
228+
query := `
229+
SELECT instances.id
230+
FROM instances
231+
LEFT JOIN instance_role ON instance_role.instance_id = instances.id
232+
LEFT JOIN roles ON roles.id = instance_role.role_id AND roles.deleted_at IS NULL AND roles.stat = 0
233+
LEFT JOIN role_operations ON role_operations.role_id = roles.id
234+
LEFT JOIN user_role ON user_role.role_id = roles.id
235+
LEFT JOIN users ON users.id = user_role.user_id AND users.stat = 0
236+
WHERE
237+
instances.deleted_at IS NULL
238+
AND users.id = ?
239+
AND role_operations.op_code IN (?)
240+
GROUP BY instances.id
241+
UNION
242+
SELECT instances.id
243+
FROM instances
244+
LEFT JOIN instance_role ON instance_role.instance_id = instances.id
245+
LEFT JOIN roles ON roles.id = instance_role.role_id AND roles.deleted_at IS NULL AND roles.stat = 0
246+
LEFT JOIN role_operations ON role_operations.role_id = roles.id
247+
JOIN user_group_roles ON roles.id = user_group_roles.role_id
248+
JOIN user_groups ON user_groups.id = user_group_roles.user_group_id AND user_groups.deleted_at IS NULL
249+
JOIN user_group_users ON user_groups.id = user_group_users.user_group_id
250+
JOIN users ON users.id = user_group_users.user_id AND users.deleted_at IS NULL AND users.stat=0
251+
WHERE
252+
instances.deleted_at IS NULL
253+
AND users.id = ?
254+
AND role_operations.op_code IN (?)
255+
GROUP BY instances.id
256+
`
257+
err = s.db.Raw(query, user.ID, ops, user.ID, ops).Scan(&instances).Error
258+
if err != nil {
259+
return nil, errors.ConnectStorageErrWrapper(err)
260+
}
261+
return
262+
}
263+
264+
func getInstanceIDsFromInstances(instances []*Instance) (ids []uint) {
265+
ids = make([]uint, len(instances))
266+
for i := range instances {
267+
ids[i] = instances[i].ID
268+
}
269+
return ids
270+
}
271+
272+
//SELECT instances.id
273+
//FROM instances
274+
//LEFT JOIN instance_role ON instance_role.instance_id = instances.id
275+
//LEFT JOIN roles ON roles.id = instance_role.role_id AND roles.deleted_at IS NULL AND roles.stat = 0
276+
//LEFT JOIN role_operations ON role_operations.role_id = roles.id
277+
//LEFT JOIN user_role ON user_role.role_id = roles.id
278+
//LEFT JOIN users ON users.id = user_role.user_id AND users.stat = 0
279+
//WHERE
280+
//instances.deleted_at IS NULL
281+
//AND users.id = 5
282+
//AND role_operations.op_code IN (20200)
283+
//GROUP BY instances.id
284+
//UNION
285+
//SELECT instances.id
286+
//FROM instances
287+
//LEFT JOIN instance_role ON instance_role.instance_id = instances.id
288+
//LEFT JOIN roles ON roles.id = instance_role.role_id AND roles.deleted_at IS NULL AND roles.stat = 0
289+
//LEFT JOIN role_operations ON role_operations.role_id = roles.id
290+
//JOIN user_group_roles ON roles.id = user_group_roles.role_id
291+
//JOIN user_groups ON user_groups.id = user_group_roles.user_group_id AND user_groups.deleted_at IS NULL
292+
//JOIN user_group_users ON user_groups.id = user_group_users.user_group_id
293+
//JOIN users ON users.id = user_group_users.user_id AND users.deleted_at IS NULL AND users.stat=0
294+
//WHERE
295+
//instances.deleted_at IS NULL
296+
//AND users.id = 5
297+
//AND role_operations.op_code IN (20200)
298+
//GROUP BY instances.id
299+
300+
//SELECT instances.id
301+
//FROM instances
302+
//LEFT JOIN instance_role ON instance_role.instance_id = instances.id
303+
//LEFT JOIN roles ON roles.id = instance_role.role_id AND roles.deleted_at IS NULL AND roles.stat = 0
304+
//LEFT JOIN role_operations ON role_operations.role_id = roles.id
305+
//LEFT JOIN user_role ON user_role.role_id = roles.id
306+
//LEFT JOIN users ON users.id = user_role.user_id AND users.stat = 0
307+
//WHERE
308+
//instances.deleted_at IS NULL
309+
//AND instances.id = 5
310+
//AND users.id = 4
311+
//AND role_operations.op_code IN (20200)
312+
//GROUP BY instances.id
313+
//UNION
314+
//SELECT instances.id
315+
//FROM instances
316+
//LEFT JOIN instance_role ON instance_role.instance_id = instances.id
317+
//LEFT JOIN roles ON roles.id = instance_role.role_id AND roles.deleted_at IS NULL AND roles.stat = 0
318+
//LEFT JOIN role_operations ON role_operations.role_id = roles.id
319+
//JOIN user_group_roles ON roles.id = user_group_roles.role_id
320+
//JOIN user_groups ON user_groups.id = user_group_roles.user_group_id AND user_groups.deleted_at IS NULL
321+
//JOIN user_group_users ON user_groups.id = user_group_users.user_group_id
322+
//JOIN users ON users.id = user_group_users.user_id AND users.deleted_at IS NULL AND users.stat=0
323+
//WHERE
324+
//instances.deleted_at IS NULL
325+
//AND instances.id = 5
326+
//AND users.id = 4
327+
//AND role_operations.op_code IN (20200)
328+
//GROUP BY instances.id

sqle/model/workflow.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,3 +601,21 @@ func (s *Storage) TaskWorkflowIsRunning(taskIds []uint) (bool, error) {
601601
err := s.db.Where("status = ? AND task_id IN (?)", WorkflowStatusRunning, taskIds).Find(&workflowRecords).Error
602602
return len(workflowRecords) > 0, errors.New(errors.ConnectStorageError, err)
603603
}
604+
605+
func (s *Storage) GetInstanceByWorkflowID(workflowID uint) (*Instance, error) {
606+
query := `
607+
SELECT instances.id
608+
FROM workflows AS w
609+
LEFT JOIN workflow_records AS wr ON wr.id = w.workflow_record_id
610+
LEFT JOIN tasks ON tasks.id = wr.task_id
611+
LEFT JOIN instances ON instances.id = tasks.instance_id
612+
WHERE
613+
w.id = ?
614+
LIMIT 1`
615+
instance := &Instance{}
616+
err := s.db.Raw(query, workflowID).Scan(instance).Error
617+
if err != nil {
618+
return nil, errors.ConnectStorageErrWrapper(err)
619+
}
620+
return instance, err
621+
}

sqle/model/workflow_list.go

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package model
33
import (
44
"database/sql"
55
"time"
6+
7+
"github.com/actiontech/sqle/sqle/utils"
68
)
79

810
type WorkflowListDetail struct {
@@ -68,9 +70,15 @@ WHERE
6870
w.deleted_at IS NULL
6971
7072
{{- if .check_user_can_access }}
71-
AND (w.create_user_id = :current_user_id
73+
AND (
74+
w.create_user_id = :current_user_id
7275
OR curr_ass_user.id = :current_user_id
7376
OR all_ass_user.id = :current_user_id
77+
78+
{{- if .viewable_instance_ids }}
79+
OR inst.id IN (:viewable_instance_ids)
80+
{{- end }}
81+
7482
)
7583
{{- end }}
7684
@@ -121,9 +129,22 @@ AND inst.name = :filter_task_instance_name
121129
122130
`
123131

124-
func (s *Storage) GetWorkflowsByReq(data map[string]interface{}) (
132+
func (s *Storage) GetWorkflowsByReq(data map[string]interface{}, user *User) (
125133
result []*WorkflowListDetail, count uint64, err error) {
126134

135+
// get workflow ids only for user can access by OP_WORKFLOW_VIEW_OTHERS
136+
var ids []uint
137+
{
138+
instances, err := s.GetUserCanOpInstances(user, []uint{OP_WORKFLOW_VIEW_OTHERS})
139+
if err != nil {
140+
return result, 0, err
141+
}
142+
ids = getInstanceIDsFromInstances(instances)
143+
}
144+
if len(ids) > 0 {
145+
data["viewable_instance_ids"] = utils.JoinUintSliceToString(ids, ", ")
146+
}
147+
127148
err = s.getListResult(workflowsQueryBodyTpl, workflowsQueryTpl, data, &result)
128149
if err != nil {
129150
return result, 0, err

0 commit comments

Comments
 (0)