mirror of
https://github.com/semaphoreui/semaphore.git
synced 2024-11-21 08:51:05 +01:00
feat: admin can all
This commit is contained in:
parent
b31033323a
commit
d3923f18b3
@ -8,7 +8,7 @@ import (
|
||||
"github.com/gorilla/context"
|
||||
)
|
||||
|
||||
//nolint: gocyclo
|
||||
// nolint: gocyclo
|
||||
func getEvents(w http.ResponseWriter, r *http.Request, limit int) {
|
||||
user := context.Get(r, "user").(*db.User)
|
||||
projectObj, exists := context.GetOk(r, "project")
|
||||
@ -19,7 +19,9 @@ func getEvents(w http.ResponseWriter, r *http.Request, limit int) {
|
||||
if exists {
|
||||
project := projectObj.(db.Project)
|
||||
|
||||
_, err = helpers.Store(r).GetProjectUser(project.ID, user.ID)
|
||||
if !user.Admin { // check permissions to view events
|
||||
_, err = helpers.Store(r).GetProjectUser(project.ID, user.ID)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
helpers.WriteError(w, err)
|
||||
|
@ -26,7 +26,7 @@ func ProjectMiddleware(next http.Handler) http.Handler {
|
||||
// check if user in project's team
|
||||
projectUser, err := helpers.Store(r).GetProjectUser(projectID, user.ID)
|
||||
|
||||
if err != nil {
|
||||
if !user.Admin && err != nil {
|
||||
helpers.WriteError(w, err)
|
||||
return
|
||||
}
|
||||
|
@ -14,7 +14,13 @@ import (
|
||||
func GetProjects(w http.ResponseWriter, r *http.Request) {
|
||||
user := context.Get(r, "user").(*db.User)
|
||||
|
||||
projects, err := helpers.Store(r).GetProjects(user.ID)
|
||||
var err error
|
||||
var projects []db.Project
|
||||
if user.Admin {
|
||||
projects, err = helpers.Store(r).GetAllProjects()
|
||||
} else {
|
||||
projects, err = helpers.Store(r).GetProjects(user.ID)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
helpers.WriteError(w, err)
|
||||
|
@ -1,6 +1,7 @@
|
||||
package projects
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/ansible-semaphore/semaphore/api/helpers"
|
||||
"github.com/ansible-semaphore/semaphore/db"
|
||||
"net/http"
|
||||
@ -108,24 +109,30 @@ func AddUser(w http.ResponseWriter, r *http.Request) {
|
||||
// RemoveUser removes a user from a project team
|
||||
func RemoveUser(w http.ResponseWriter, r *http.Request) {
|
||||
project := context.Get(r, "project").(db.Project)
|
||||
projectUser := context.Get(r, "projectUser").(db.User)
|
||||
me := context.Get(r, "user").(*db.User) // logged in user
|
||||
targetUser := context.Get(r, "projectUser").(db.User) // target user
|
||||
targetUserRole := context.Get(r, "projectUserRole").(db.ProjectUserRole)
|
||||
|
||||
err := helpers.Store(r).DeleteProjectUser(project.ID, projectUser.ID)
|
||||
if !me.Admin && targetUser.ID == me.ID && targetUserRole == db.ProjectOwner {
|
||||
helpers.WriteError(w, fmt.Errorf("owner can not left the project"))
|
||||
return
|
||||
}
|
||||
|
||||
err := helpers.Store(r).DeleteProjectUser(project.ID, targetUser.ID)
|
||||
|
||||
if err != nil {
|
||||
helpers.WriteError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
user := context.Get(r, "user").(*db.User)
|
||||
objType := db.EventUser
|
||||
desc := "User ID " + strconv.Itoa(projectUser.ID) + " removed from team"
|
||||
desc := "User ID " + strconv.Itoa(targetUser.ID) + " removed from team"
|
||||
|
||||
_, err = helpers.Store(r).CreateEvent(db.Event{
|
||||
UserID: &user.ID,
|
||||
UserID: &me.ID,
|
||||
ProjectID: &project.ID,
|
||||
ObjectType: &objType,
|
||||
ObjectID: &projectUser.ID,
|
||||
ObjectID: &targetUser.ID,
|
||||
Description: &desc,
|
||||
})
|
||||
|
||||
@ -138,7 +145,14 @@ func RemoveUser(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func UpdateUser(w http.ResponseWriter, r *http.Request) {
|
||||
project := context.Get(r, "project").(db.Project)
|
||||
user := context.Get(r, "projectUser").(db.User)
|
||||
me := context.Get(r, "user").(*db.User) // logged in user
|
||||
targetUser := context.Get(r, "projectUser").(db.User)
|
||||
targetUserRole := context.Get(r, "projectUserRole").(db.ProjectUserRole)
|
||||
|
||||
if !me.Admin && targetUser.ID == me.ID && targetUserRole == db.ProjectOwner {
|
||||
helpers.WriteError(w, fmt.Errorf("owner can not change his role in the project"))
|
||||
return
|
||||
}
|
||||
|
||||
var projectUser struct {
|
||||
Role db.ProjectUserRole `json:"role"`
|
||||
@ -154,7 +168,7 @@ func UpdateUser(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
err := helpers.Store(r).UpdateProjectUser(db.ProjectUser{
|
||||
UserID: user.ID,
|
||||
UserID: targetUser.ID,
|
||||
ProjectID: project.ID,
|
||||
Role: projectUser.Role,
|
||||
})
|
||||
|
10
api/users.go
10
api/users.go
@ -73,7 +73,7 @@ func getUserMiddleware(next http.Handler) http.Handler {
|
||||
}
|
||||
|
||||
func updateUser(w http.ResponseWriter, r *http.Request) {
|
||||
oldUser := context.Get(r, "_user").(db.User)
|
||||
targetUser := context.Get(r, "_user").(db.User)
|
||||
editor := context.Get(r, "user").(*db.User)
|
||||
|
||||
var user db.UserWithPwd
|
||||
@ -81,25 +81,25 @@ func updateUser(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
if !editor.Admin && editor.ID != oldUser.ID {
|
||||
if !editor.Admin && editor.ID != targetUser.ID {
|
||||
log.Warn(editor.Username + " is not permitted to edit users")
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
if editor.ID == oldUser.ID && oldUser.Admin != user.Admin {
|
||||
if editor.ID == targetUser.ID && targetUser.Admin != user.Admin {
|
||||
log.Warn("User can't edit his own role")
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
if oldUser.External && oldUser.Username != user.Username {
|
||||
if targetUser.External && targetUser.Username != user.Username {
|
||||
log.Warn("Username is not editable for external users")
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
user.ID = oldUser.ID
|
||||
user.ID = targetUser.ID
|
||||
if err := helpers.Store(r).UpdateUser(user); err != nil {
|
||||
log.Error(err.Error())
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
|
@ -7,6 +7,7 @@ const (
|
||||
ProjectManager ProjectUserRole = "manager"
|
||||
ProjectTaskRunner ProjectUserRole = "task_runner"
|
||||
ProjectGuest ProjectUserRole = "guest"
|
||||
ProjectNone ProjectUserRole = ""
|
||||
)
|
||||
|
||||
type ProjectUserPermission int
|
||||
@ -37,11 +38,6 @@ type ProjectUser struct {
|
||||
Role ProjectUserRole `db:"role" json:"role"`
|
||||
}
|
||||
|
||||
func (u *ProjectUser) Can(permissions ProjectUserPermission) bool {
|
||||
userPermissions := rolePermissions[u.Role]
|
||||
return (userPermissions & permissions) == permissions
|
||||
}
|
||||
|
||||
func (r ProjectUserRole) Can(permissions ProjectUserPermission) bool {
|
||||
return (rolePermissions[r] & permissions) == permissions
|
||||
}
|
||||
|
@ -143,6 +143,7 @@ type Store interface {
|
||||
GetUserByLoginOrEmail(login string, email string) (User, error)
|
||||
|
||||
GetProject(projectID int) (Project, error)
|
||||
GetAllProjects() ([]Project, error)
|
||||
GetProjects(userID int) ([]Project, error)
|
||||
CreateProject(project Project) (Project, error)
|
||||
DeleteProject(projectID int) error
|
||||
|
@ -17,6 +17,12 @@ func (d *BoltDb) CreateProject(project db.Project) (db.Project, error) {
|
||||
return newProject.(db.Project), nil
|
||||
}
|
||||
|
||||
func (d *BoltDb) GetAllProjects() (projects []db.Project, err error) {
|
||||
err = d.getObjects(0, db.ProjectProps, db.RetrieveQueryParams{}, nil, &projects)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (d *BoltDb) GetProjects(userID int) (projects []db.Project, err error) {
|
||||
projects = make([]db.Project, 0)
|
||||
|
||||
|
@ -23,6 +23,21 @@ func (d *SqlDb) CreateProject(project db.Project) (newProject db.Project, err er
|
||||
return
|
||||
}
|
||||
|
||||
func (d *SqlDb) GetAllProjects() (projects []db.Project, err error) {
|
||||
query, args, err := squirrel.Select("p.*").
|
||||
From("project as p").
|
||||
OrderBy("p.name").
|
||||
ToSql()
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
_, err = d.selectAll(&projects, query, args...)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (d *SqlDb) GetProjects(userID int) (projects []db.Project, err error) {
|
||||
query, args, err := squirrel.Select("p.*").
|
||||
From("project as p").
|
||||
|
@ -314,11 +314,14 @@
|
||||
v-on="on"
|
||||
>
|
||||
<v-list-item-icon>
|
||||
<v-icon>mdi-account</v-icon>
|
||||
<v-icon :color="user.admin ? 'red' : ''">mdi-account</v-icon>
|
||||
</v-list-item-icon>
|
||||
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>{{ user.name }}</v-list-item-title>
|
||||
<v-list-item-title>
|
||||
{{ user.name }}
|
||||
<v-chip v-if="user.admin" small color="red" class="ml-1">admin</v-chip>
|
||||
</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</template>
|
||||
@ -366,6 +369,7 @@
|
||||
:projectId="projectId"
|
||||
:userPermissions="userRole.permissions"
|
||||
:userId="user ? user.id : null"
|
||||
:isAdmin="user ? user.admin : false"
|
||||
></router-view>
|
||||
</v-main>
|
||||
|
||||
|
@ -18,6 +18,7 @@ export default {
|
||||
projectId: Number,
|
||||
userId: Number,
|
||||
userPermissions: Number,
|
||||
isAdmin: Boolean,
|
||||
},
|
||||
|
||||
data() {
|
||||
@ -51,6 +52,9 @@ export default {
|
||||
},
|
||||
|
||||
can(permission) {
|
||||
if (this.isAdmin) {
|
||||
return true;
|
||||
}
|
||||
// eslint-disable-next-line no-bitwise
|
||||
return (this.userPermissions & permission) === permission;
|
||||
},
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
<div class="project-settings-form">
|
||||
<div style="height: 300px;">
|
||||
<ProjectForm item-id="new" ref="editForm" @save="onSave" :demo-project="true" />
|
||||
<ProjectForm item-id="new" ref="editForm" @save="onSave" :demo-project="demoProject" />
|
||||
</div>
|
||||
|
||||
<div class="text-right">
|
||||
|
Loading…
Reference in New Issue
Block a user