mirror of
https://github.com/go-vikunja/vikunja.git
synced 2026-11-09 00:22:38 -06:00
Both helpers compared a.GetID() against users.id, but *LinkSharing also satisfies web.Auth and its GetID() is a link_shares.id - a different id namespace. Passing one would have emitted users.id = <share id> and lent that share another user's identity, which is the confusion behind GHSA-vvcv-vpph-h844. Guarded at every call site, but the helpers moved out of models and into user, so the guard drifted away from the code needing it. Taking *User makes the case unrepresentable. Also fail closed on a zero id: humans store bot_owner_id = 0, so an unguarded zero would have matched all of them. The doc claimed JWT and CalDAV auth carry no BotOwnerID, but bots can reach neither path, and claimed bots-cannot-own-bots as an invariant when the guard is inert for JWT principals. Reworded to chain-safety by construction, which holds regardless.
56 lines
2.1 KiB
Go
56 lines
2.1 KiB
Go
// Vikunja is a to-do list application to facilitate your life.
|
|
// Copyright 2018-present Vikunja and contributors. All rights reserved.
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
package user
|
|
|
|
import (
|
|
"xorm.io/builder"
|
|
)
|
|
|
|
// IsBotOwnedBy reports whether u is a bot owned by owner.
|
|
func (u *User) IsBotOwnedBy(owner *User) bool {
|
|
return u.IsBot() && u.BotOwnerID == owner.ID
|
|
}
|
|
|
|
// SameBotIdentityCond matches a user ID column against users sharing u's root:
|
|
// a bot's owner or a human themselves. It is symmetric across an owner's fleet.
|
|
//
|
|
// The root is resolved in SQL so the result never depends on how populated the
|
|
// passed struct happens to be; callers routinely hold a User carrying only an ID.
|
|
//
|
|
// Resolving only one owner hop keeps accidental bot chains out of a human's identity set.
|
|
//
|
|
// column is interpolated as a raw SQL identifier and must be a trusted literal.
|
|
func SameBotIdentityCond(u *User, column string) builder.Cond {
|
|
if u == nil || u.ID <= 0 {
|
|
// Humans are stored with bot_owner_id = 0, so an unguarded zero id would
|
|
// match every one of them.
|
|
return builder.In(column, []int64{})
|
|
}
|
|
|
|
root := builder.Select("bot_owner_id").From("users").
|
|
Where(builder.And(builder.Eq{"id": u.ID}, builder.Gt{"bot_owner_id": 0}))
|
|
|
|
return builder.In(column,
|
|
builder.Select("id").From("users").Where(builder.Or(
|
|
builder.Eq{"id": u.ID},
|
|
builder.Eq{"bot_owner_id": u.ID},
|
|
builder.In("id", root),
|
|
builder.In("bot_owner_id", root),
|
|
)),
|
|
)
|
|
}
|