Есть API который принимает запросы от пользователей 2 типов.
1. Хочу ограничить доступ к API по ролям, что бы они могли посещать только страницы предназначеные для них.
Сделал middleware:
1. Он проверяет jwt токен.
2. В Casbin сверяет роль из payload и путь.
3. Получает пользователя.
func (c *MiddlewareCollection) UserAuthorization(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
header := r.Header.Get(authorizationHeader)
// . . .
payload, err := (*c.js).Validate(headerParts[1])
if err != nil {
controllers.Unauthorized(w, err)
return
}
res, err := (*c.e).Enforce(
strconv.Itoa(payload.Role),
r.URL.Path,
r.Method,
)
if !res {
controllers.Unauthorized(w, errors.New("access denied"))
return
}
user, err := (*c.us).FindById(payload.UserId)
if err != nil {
// . . .
}
if !user.DeletedAt.IsZero() {
controllers.Unauthorized(w, err)
return
}
ctx := context.WithValue(r.Context(), "user", user)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
Модель Casbin
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = r.sub == p.sub && keyMatch2(r.obj, p.obj) && regexMatch(r.act, p.act)
Policy
p, client, /v1/users/:id/reset-password, GET
p, client, /v1/users/:id, PUT
p,specialist,/v1/specialist/:id, PUT
2. Пользователь может изменять только свои данные. Id пользователя указывается в url
/v1/users/:id
Мой вариант, это создать новый middleware для таких маршрутов (с id в url) и взять id из url, и сравнить с payload.UserId.
3. Пользователь может редактировать сущности которые он создал, статья, комментарий и тд.
Здесь я планирую делать проверку в сервесе, получить статью и проверить её
OwnerId* с
Id пользователя.
Как правильно создавать авторизации такого рода?
Где должна происходить проверка?
Буду благодарен за реальные примеры.