feat: restrict certain endpoints from API tokens and/or read-only tokens
This commit is contained in:
parent
2716471fa9
commit
ff75075b81
|
@ -167,8 +167,8 @@ func (s *Server) discordLink(w http.ResponseWriter, r *http.Request) error {
|
||||||
claims, _ := server.ClaimsFromContext(ctx)
|
claims, _ := server.ClaimsFromContext(ctx)
|
||||||
|
|
||||||
// only site tokens can be used for this endpoint
|
// only site tokens can be used for this endpoint
|
||||||
if claims.APIToken || !claims.TokenWrite {
|
if claims.APIToken {
|
||||||
return server.APIError{Code: server.ErrInvalidToken}
|
return server.APIError{Code: server.ErrMissingPermissions, Details: "This endpoint cannot be used by API tokens"}
|
||||||
}
|
}
|
||||||
|
|
||||||
req, err := Decode[linkRequest](r)
|
req, err := Decode[linkRequest](r)
|
||||||
|
@ -213,8 +213,8 @@ func (s *Server) discordUnlink(w http.ResponseWriter, r *http.Request) error {
|
||||||
claims, _ := server.ClaimsFromContext(ctx)
|
claims, _ := server.ClaimsFromContext(ctx)
|
||||||
|
|
||||||
// only site tokens can be used for this endpoint
|
// only site tokens can be used for this endpoint
|
||||||
if claims.APIToken || !claims.TokenWrite {
|
if claims.APIToken {
|
||||||
return server.APIError{Code: server.ErrInvalidToken}
|
return server.APIError{Code: server.ErrMissingPermissions, Details: "This endpoint cannot be used by API tokens"}
|
||||||
}
|
}
|
||||||
|
|
||||||
u, err := s.DB.User(ctx, claims.UserID)
|
u, err := s.DB.User(ctx, claims.UserID)
|
||||||
|
|
|
@ -189,8 +189,8 @@ func (s *Server) mastodonLink(w http.ResponseWriter, r *http.Request) error {
|
||||||
claims, _ := server.ClaimsFromContext(ctx)
|
claims, _ := server.ClaimsFromContext(ctx)
|
||||||
|
|
||||||
// only site tokens can be used for this endpoint
|
// only site tokens can be used for this endpoint
|
||||||
if claims.APIToken || !claims.TokenWrite {
|
if claims.APIToken {
|
||||||
return server.APIError{Code: server.ErrInvalidToken}
|
return server.APIError{Code: server.ErrMissingPermissions, Details: "This endpoint cannot be used by API tokens"}
|
||||||
}
|
}
|
||||||
|
|
||||||
req, err := Decode[fediLinkRequest](r)
|
req, err := Decode[fediLinkRequest](r)
|
||||||
|
@ -240,8 +240,8 @@ func (s *Server) mastodonUnlink(w http.ResponseWriter, r *http.Request) error {
|
||||||
claims, _ := server.ClaimsFromContext(ctx)
|
claims, _ := server.ClaimsFromContext(ctx)
|
||||||
|
|
||||||
// only site tokens can be used for this endpoint
|
// only site tokens can be used for this endpoint
|
||||||
if claims.APIToken || !claims.TokenWrite {
|
if claims.APIToken {
|
||||||
return server.APIError{Code: server.ErrInvalidToken}
|
return server.APIError{Code: server.ErrMissingPermissions, Details: "This endpoint cannot be used by API tokens"}
|
||||||
}
|
}
|
||||||
|
|
||||||
u, err := s.DB.User(ctx, claims.UserID)
|
u, err := s.DB.User(ctx, claims.UserID)
|
||||||
|
|
|
@ -164,8 +164,8 @@ func (s *Server) misskeyLink(w http.ResponseWriter, r *http.Request) error {
|
||||||
claims, _ := server.ClaimsFromContext(ctx)
|
claims, _ := server.ClaimsFromContext(ctx)
|
||||||
|
|
||||||
// only site tokens can be used for this endpoint
|
// only site tokens can be used for this endpoint
|
||||||
if claims.APIToken || !claims.TokenWrite {
|
if claims.APIToken {
|
||||||
return server.APIError{Code: server.ErrInvalidToken}
|
return server.APIError{Code: server.ErrMissingPermissions, Details: "This endpoint cannot be used by API tokens"}
|
||||||
}
|
}
|
||||||
|
|
||||||
req, err := Decode[fediLinkRequest](r)
|
req, err := Decode[fediLinkRequest](r)
|
||||||
|
|
|
@ -32,6 +32,10 @@ func (s *Server) getInvites(w http.ResponseWriter, r *http.Request) error {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
claims, _ := server.ClaimsFromContext(ctx)
|
claims, _ := server.ClaimsFromContext(ctx)
|
||||||
|
|
||||||
|
if claims.APIToken {
|
||||||
|
return server.APIError{Code: server.ErrMissingPermissions, Details: "This endpoint cannot be used by API tokens"}
|
||||||
|
}
|
||||||
|
|
||||||
is, err := s.DB.UserInvites(ctx, claims.UserID)
|
is, err := s.DB.UserInvites(ctx, claims.UserID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "getting user invites")
|
return errors.Wrap(err, "getting user invites")
|
||||||
|
@ -54,6 +58,10 @@ func (s *Server) createInvite(w http.ResponseWriter, r *http.Request) error {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
claims, _ := server.ClaimsFromContext(ctx)
|
claims, _ := server.ClaimsFromContext(ctx)
|
||||||
|
|
||||||
|
if claims.APIToken {
|
||||||
|
return server.APIError{Code: server.ErrMissingPermissions, Details: "This endpoint cannot be used by API tokens"}
|
||||||
|
}
|
||||||
|
|
||||||
inv, err := s.DB.CreateInvite(ctx, claims.UserID)
|
inv, err := s.DB.CreateInvite(ctx, claims.UserID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == db.ErrTooManyInvites {
|
if err == db.ErrTooManyInvites {
|
||||||
|
|
|
@ -33,6 +33,10 @@ func (s *Server) getTokens(w http.ResponseWriter, r *http.Request) error {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
claims, _ := server.ClaimsFromContext(ctx)
|
claims, _ := server.ClaimsFromContext(ctx)
|
||||||
|
|
||||||
|
if claims.APIToken {
|
||||||
|
return server.APIError{Code: server.ErrMissingPermissions, Details: "This endpoint cannot be used by API tokens"}
|
||||||
|
}
|
||||||
|
|
||||||
tokens, err := s.DB.Tokens(ctx, claims.UserID)
|
tokens, err := s.DB.Tokens(ctx, claims.UserID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "getting tokens")
|
return errors.Wrap(err, "getting tokens")
|
||||||
|
@ -52,7 +56,7 @@ func (s *Server) deleteToken(w http.ResponseWriter, r *http.Request) error {
|
||||||
claims, _ := server.ClaimsFromContext(ctx)
|
claims, _ := server.ClaimsFromContext(ctx)
|
||||||
|
|
||||||
if claims.APIToken {
|
if claims.APIToken {
|
||||||
return server.APIError{Code: server.ErrInvalidToken}
|
return server.APIError{Code: server.ErrMissingPermissions, Details: "This endpoint cannot be used by API tokens"}
|
||||||
}
|
}
|
||||||
|
|
||||||
tx, err := s.DB.Begin(ctx)
|
tx, err := s.DB.Begin(ctx)
|
||||||
|
@ -89,7 +93,7 @@ func (s *Server) createToken(w http.ResponseWriter, r *http.Request) error {
|
||||||
claims, _ := server.ClaimsFromContext(ctx)
|
claims, _ := server.ClaimsFromContext(ctx)
|
||||||
|
|
||||||
if claims.APIToken {
|
if claims.APIToken {
|
||||||
return server.APIError{Code: server.ErrInvalidToken}
|
return server.APIError{Code: server.ErrMissingPermissions, Details: "This endpoint cannot be used by API tokens"}
|
||||||
}
|
}
|
||||||
|
|
||||||
readOnly := r.FormValue("read_only") == "true"
|
readOnly := r.FormValue("read_only") == "true"
|
||||||
|
|
|
@ -27,6 +27,10 @@ func (s *Server) createMember(w http.ResponseWriter, r *http.Request) (err error
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
claims, _ := server.ClaimsFromContext(ctx)
|
claims, _ := server.ClaimsFromContext(ctx)
|
||||||
|
|
||||||
|
if !claims.TokenWrite {
|
||||||
|
return server.APIError{Code: server.ErrMissingPermissions, Details: "This token is read-only"}
|
||||||
|
}
|
||||||
|
|
||||||
u, err := s.DB.User(ctx, claims.UserID)
|
u, err := s.DB.User(ctx, claims.UserID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "getting user")
|
return errors.Wrap(err, "getting user")
|
||||||
|
|
|
@ -17,6 +17,10 @@ func (s *Server) deleteMember(w http.ResponseWriter, r *http.Request) error {
|
||||||
|
|
||||||
claims, _ := server.ClaimsFromContext(ctx)
|
claims, _ := server.ClaimsFromContext(ctx)
|
||||||
|
|
||||||
|
if !claims.TokenWrite {
|
||||||
|
return server.APIError{Code: server.ErrMissingPermissions, Details: "this token is read-only"}
|
||||||
|
}
|
||||||
|
|
||||||
id, err := xid.FromString(chi.URLParam(r, "memberRef"))
|
id, err := xid.FromString(chi.URLParam(r, "memberRef"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return server.APIError{Code: server.ErrMemberNotFound}
|
return server.APIError{Code: server.ErrMemberNotFound}
|
||||||
|
|
|
@ -30,6 +30,10 @@ func (s *Server) patchMember(w http.ResponseWriter, r *http.Request) error {
|
||||||
|
|
||||||
claims, _ := server.ClaimsFromContext(ctx)
|
claims, _ := server.ClaimsFromContext(ctx)
|
||||||
|
|
||||||
|
if !claims.TokenWrite {
|
||||||
|
return server.APIError{Code: server.ErrMissingPermissions, Details: "This token is read-only"}
|
||||||
|
}
|
||||||
|
|
||||||
id, err := xid.FromString(chi.URLParam(r, "memberRef"))
|
id, err := xid.FromString(chi.URLParam(r, "memberRef"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return server.APIError{Code: server.ErrMemberNotFound}
|
return server.APIError{Code: server.ErrMemberNotFound}
|
||||||
|
|
|
@ -22,6 +22,10 @@ func (s *Server) createUserReport(w http.ResponseWriter, r *http.Request) error
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
claims, _ := server.ClaimsFromContext(ctx)
|
claims, _ := server.ClaimsFromContext(ctx)
|
||||||
|
|
||||||
|
if !claims.TokenWrite {
|
||||||
|
return server.APIError{Code: server.ErrMissingPermissions, Details: "This token is read-only"}
|
||||||
|
}
|
||||||
|
|
||||||
userID, err := xid.FromString(chi.URLParam(r, "id"))
|
userID, err := xid.FromString(chi.URLParam(r, "id"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return server.APIError{Code: server.ErrBadRequest, Details: "Invalid user ID"}
|
return server.APIError{Code: server.ErrBadRequest, Details: "Invalid user ID"}
|
||||||
|
@ -65,6 +69,10 @@ func (s *Server) createMemberReport(w http.ResponseWriter, r *http.Request) erro
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
claims, _ := server.ClaimsFromContext(ctx)
|
claims, _ := server.ClaimsFromContext(ctx)
|
||||||
|
|
||||||
|
if !claims.TokenWrite {
|
||||||
|
return server.APIError{Code: server.ErrMissingPermissions, Details: "This token is read-only"}
|
||||||
|
}
|
||||||
|
|
||||||
memberID, err := xid.FromString(chi.URLParam(r, "id"))
|
memberID, err := xid.FromString(chi.URLParam(r, "id"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return server.APIError{Code: server.ErrBadRequest, Details: "Invalid member ID"}
|
return server.APIError{Code: server.ErrBadRequest, Details: "Invalid member ID"}
|
||||||
|
|
|
@ -44,6 +44,10 @@ func (s *Server) ackWarning(w http.ResponseWriter, r *http.Request) (err error)
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
claims, _ := server.ClaimsFromContext(ctx)
|
claims, _ := server.ClaimsFromContext(ctx)
|
||||||
|
|
||||||
|
if !claims.APIToken {
|
||||||
|
return server.APIError{Code: server.ErrMissingPermissions, Details: "This endpoint cannot be used by API tokens"}
|
||||||
|
}
|
||||||
|
|
||||||
id, err := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
|
id, err := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return server.APIError{Code: server.ErrBadRequest}
|
return server.APIError{Code: server.ErrBadRequest}
|
||||||
|
|
|
@ -12,8 +12,8 @@ func (s *Server) deleteUser(w http.ResponseWriter, r *http.Request) error {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
claims, _ := server.ClaimsFromContext(ctx)
|
claims, _ := server.ClaimsFromContext(ctx)
|
||||||
|
|
||||||
if claims.APIToken || !claims.TokenWrite {
|
if claims.APIToken {
|
||||||
return server.APIError{Code: server.ErrMissingPermissions}
|
return server.APIError{Code: server.ErrMissingPermissions, Details: "This endpoint cannot be used by API tokens"}
|
||||||
}
|
}
|
||||||
|
|
||||||
tx, err := s.DB.Begin(ctx)
|
tx, err := s.DB.Begin(ctx)
|
||||||
|
|
|
@ -14,6 +14,10 @@ func (s *Server) startExport(w http.ResponseWriter, r *http.Request) error {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
claims, _ := server.ClaimsFromContext(ctx)
|
claims, _ := server.ClaimsFromContext(ctx)
|
||||||
|
|
||||||
|
if claims.APIToken {
|
||||||
|
return server.APIError{Code: server.ErrMissingPermissions, Details: "This endpoint cannot be used by API tokens"}
|
||||||
|
}
|
||||||
|
|
||||||
hasExport, err := s.DB.HasRecentExport(ctx, claims.UserID)
|
hasExport, err := s.DB.HasRecentExport(ctx, claims.UserID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("checking if user has recent export: %v", err)
|
log.Errorf("checking if user has recent export: %v", err)
|
||||||
|
@ -56,6 +60,10 @@ func (s *Server) getExport(w http.ResponseWriter, r *http.Request) error {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
claims, _ := server.ClaimsFromContext(ctx)
|
claims, _ := server.ClaimsFromContext(ctx)
|
||||||
|
|
||||||
|
if claims.APIToken {
|
||||||
|
return server.APIError{Code: server.ErrMissingPermissions, Details: "This endpoint cannot be used by API tokens"}
|
||||||
|
}
|
||||||
|
|
||||||
de, err := s.DB.UserExport(ctx, claims.UserID)
|
de, err := s.DB.UserExport(ctx, claims.UserID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == db.ErrNoExport {
|
if err == db.ErrNoExport {
|
||||||
|
|
|
@ -28,6 +28,10 @@ func (s *Server) patchUser(w http.ResponseWriter, r *http.Request) error {
|
||||||
|
|
||||||
claims, _ := server.ClaimsFromContext(ctx)
|
claims, _ := server.ClaimsFromContext(ctx)
|
||||||
|
|
||||||
|
if !claims.TokenWrite {
|
||||||
|
return server.APIError{Code: server.ErrMissingPermissions, Details: "This token is read-only"}
|
||||||
|
}
|
||||||
|
|
||||||
var req PatchUserRequest
|
var req PatchUserRequest
|
||||||
err := render.Decode(r, &req)
|
err := render.Decode(r, &req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in New Issue