Allow users with AdminManageUsers to see banned users
Also: - General code refactoring - Allow banned/restricted users to see their scores etc - common.MethodData now contains UserPrivileges - UserPrivileges have now their own type - Implement md.HasQuery, to know if there's a GET querystring parameter or not
This commit is contained in:
parent
476cd385f8
commit
e4d27f8d6b
|
@ -75,7 +75,7 @@ func initialCaretaker(c *gin.Context, f func(md common.MethodData) common.CodeMe
|
|||
|
||||
missingPrivileges := 0
|
||||
for _, privilege := range privilegesNeeded {
|
||||
if int(md.User.Privileges)&privilege == 0 {
|
||||
if uint64(md.User.TokenPrivileges)&uint64(privilege) == 0 {
|
||||
missingPrivileges |= privilege
|
||||
}
|
||||
}
|
||||
|
@ -95,13 +95,13 @@ func initialCaretaker(c *gin.Context, f func(md common.MethodData) common.CodeMe
|
|||
}
|
||||
}
|
||||
|
||||
if _, exists := c.GetQuery("pls200"); exists {
|
||||
if md.HasQuery("pls200") {
|
||||
c.Writer.WriteHeader(200)
|
||||
} else {
|
||||
c.Writer.WriteHeader(resp.GetCode())
|
||||
}
|
||||
|
||||
if _, exists := c.GetQuery("callback"); exists {
|
||||
if md.HasQuery("callback") {
|
||||
c.Header("Content-Type", "application/javascript; charset=utf-8")
|
||||
} else {
|
||||
c.Header("Content-Type", "application/json; charset=utf-8")
|
||||
|
|
|
@ -62,7 +62,6 @@ func Start(conf common.Conf, dbO *sqlx.DB) *gin.Engine {
|
|||
// Auth-free API endpoints (public data)
|
||||
gv1.GET("/ping", Method(v1.PingGET))
|
||||
gv1.GET("/surprise_me", Method(v1.SurpriseMeGET))
|
||||
gv1.GET("/privileges", Method(v1.PrivilegesGET))
|
||||
gv1.GET("/doc", Method(v1.DocGET))
|
||||
gv1.GET("/doc/content", Method(v1.DocContentGET))
|
||||
gv1.GET("/doc/rules", Method(v1.DocRulesGET))
|
||||
|
|
|
@ -13,17 +13,25 @@ import (
|
|||
// GetTokenFull retrieves an user ID and their token privileges knowing their API token.
|
||||
func GetTokenFull(token string, db *sqlx.DB) (common.Token, bool) {
|
||||
var t common.Token
|
||||
var privs uint64
|
||||
var (
|
||||
tokenPrivsRaw uint64
|
||||
userPrivsRaw uint64
|
||||
)
|
||||
var priv8 bool
|
||||
err := db.QueryRow("SELECT id, user, privileges, private FROM tokens WHERE token = ? LIMIT 1",
|
||||
err := db.QueryRow(`SELECT
|
||||
t.id, t.user, t.privileges, t.private, u.privileges
|
||||
FROM tokens t
|
||||
LEFT JOIN users u ON u.id = t.user
|
||||
WHERE token = ? LIMIT 1`,
|
||||
fmt.Sprintf("%x", md5.Sum([]byte(token)))).
|
||||
Scan(
|
||||
&t.ID, &t.UserID, &privs, &priv8,
|
||||
&t.ID, &t.UserID, &tokenPrivsRaw, &priv8, &userPrivsRaw,
|
||||
)
|
||||
if priv8 {
|
||||
privs = common.PrivilegeReadConfidential | common.PrivilegeWrite
|
||||
tokenPrivsRaw = common.PrivilegeReadConfidential | common.PrivilegeWrite
|
||||
}
|
||||
t.Privileges = common.Privileges(privs)
|
||||
t.TokenPrivileges = common.Privileges(tokenPrivsRaw)
|
||||
t.UserPrivileges = common.UserPrivileges(userPrivsRaw)
|
||||
switch {
|
||||
case err == sql.ErrNoRows:
|
||||
return common.Token{}, false
|
||||
|
|
|
@ -71,7 +71,7 @@ type blogPostContent struct {
|
|||
// BlogPostsContentGET retrieves the content of a specific blog post.
|
||||
func BlogPostsContentGET(md common.MethodData) common.CodeMessager {
|
||||
field := "markdown"
|
||||
if _, present := md.C.GetQuery("html"); present {
|
||||
if md.HasQuery("html") {
|
||||
field = "html"
|
||||
}
|
||||
var (
|
||||
|
|
|
@ -21,7 +21,7 @@ type docResponse struct {
|
|||
// DocGET retrieves a list of documentation files.
|
||||
func DocGET(md common.MethodData) common.CodeMessager {
|
||||
var wc string
|
||||
if !md.User.Privileges.HasPrivilegeBlog() || md.Query("public") == "1" {
|
||||
if md.User.TokenPrivileges&common.PrivilegeBlog == 0 || md.Query("public") == "1" {
|
||||
wc = "WHERE public = '1'"
|
||||
}
|
||||
rows, err := md.DB.Query("SELECT id, doc_name, public, is_rule FROM docs " + wc)
|
||||
|
@ -55,7 +55,7 @@ func DocContentGET(md common.MethodData) common.CodeMessager {
|
|||
return common.SimpleResponse(404, "Documentation file not found!")
|
||||
}
|
||||
var wc string
|
||||
if !md.User.Privileges.HasPrivilegeBlog() || md.Query("public") == "1" {
|
||||
if md.User.TokenPrivileges&common.PrivilegeBlog == 0 || md.Query("public") == "1" {
|
||||
wc = "AND public = '1'"
|
||||
}
|
||||
var r docContentResponse
|
||||
|
|
|
@ -157,7 +157,8 @@ func addFriend(md common.MethodData, u int) common.CodeMessager {
|
|||
|
||||
// userExists makes sure an user exists.
|
||||
func userExists(md common.MethodData, u int) (r bool) {
|
||||
err := md.DB.QueryRow("SELECT EXISTS(SELECT 1 FROM users WHERE id = ? AND users.privileges & 1 > 0)", u).Scan(&r)
|
||||
err := md.DB.QueryRow("SELECT EXISTS(SELECT 1 FROM users WHERE id = ? AND "+
|
||||
md.User.OnlyUserPublic(true)+")", u).Scan(&r)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
md.Err(err)
|
||||
}
|
||||
|
|
|
@ -36,8 +36,10 @@ INNER JOIN users_stats ON users_stats.id = leaderboard_%[1]s.user
|
|||
// LeaderboardGET gets the leaderboard.
|
||||
func LeaderboardGET(md common.MethodData) common.CodeMessager {
|
||||
m := getMode(md.Query("mode"))
|
||||
query := fmt.Sprintf(lbUserQuery, m, `WHERE users.privileges & 1 > 0 ORDER BY leaderboard_`+m+`.position `+
|
||||
common.Paginate(md.Query("p"), md.Query("l"), 100))
|
||||
// Admins may not want to see banned users on the leaderboard.
|
||||
// This is the default setting. In case they do, they have to activate see_everything.
|
||||
query := fmt.Sprintf(lbUserQuery, m, `WHERE `+md.User.OnlyUserPublic(md.HasQuery("see_everything"))+
|
||||
` ORDER BY leaderboard_`+m+`.position `+common.Paginate(md.Query("p"), md.Query("l"), 100))
|
||||
rows, err := md.DB.Query(query)
|
||||
if err != nil {
|
||||
md.Err(err)
|
||||
|
|
|
@ -21,21 +21,15 @@ func UserManageSetAllowedPOST(md common.MethodData) common.CodeMessager {
|
|||
return common.SimpleResponse(400, "Allowed status must be between 0 and 2")
|
||||
}
|
||||
var banDatetime int64
|
||||
var privileges int32
|
||||
var newPrivileges int32
|
||||
err := md.DB.QueryRow("SELECT privileges FROM users WHERE id = ?", data.UserID).Scan(&privileges)
|
||||
if err != nil {
|
||||
md.Err(err)
|
||||
return Err500
|
||||
}
|
||||
var privsSet string
|
||||
if data.Allowed == 0 {
|
||||
banDatetime = time.Now().Unix()
|
||||
newPrivileges = privileges &^ (common.UserPrivilegeNormal | common.UserPrivilegePublic)
|
||||
privsSet = "privileges = (privileges & ~3)"
|
||||
} else {
|
||||
banDatetime = 0
|
||||
newPrivileges = privileges | (common.UserPrivilegeNormal | common.UserPrivilegePublic)
|
||||
privsSet = "privileges = (privileges | 3)"
|
||||
}
|
||||
_, err = md.DB.Exec("UPDATE users SET privileges = ?, ban_datetime = ? WHERE id = ?", newPrivileges, banDatetime, data.UserID)
|
||||
_, err := md.DB.Exec("UPDATE users SET "+privsSet+", ban_datetime = ? WHERE id = ?", banDatetime, data.UserID)
|
||||
if err != nil {
|
||||
md.Err(err)
|
||||
return Err500
|
||||
|
|
|
@ -88,7 +88,7 @@ func surpriseMe() string {
|
|||
type pingResponse struct {
|
||||
common.ResponseBase
|
||||
ID int `json:"user_id"`
|
||||
Privileges int `json:"privileges"`
|
||||
Privileges uint64 `json:"privileges"`
|
||||
}
|
||||
|
||||
// PingGET is a message to check with the API that we are logged in, and know what are our privileges.
|
||||
|
@ -103,7 +103,7 @@ func PingGET(md common.MethodData) common.CodeMessager {
|
|||
}
|
||||
|
||||
r.ID = md.ID()
|
||||
r.Privileges = int(md.User.Privileges)
|
||||
r.Privileges = uint64(md.User.TokenPrivileges)
|
||||
|
||||
return r
|
||||
}
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
package v1
|
||||
|
||||
import (
|
||||
"git.zxq.co/ripple/rippleapi/common"
|
||||
)
|
||||
|
||||
type privilegesData struct {
|
||||
common.ResponseBase
|
||||
Read bool `json:"read"`
|
||||
ReadConfidential bool `json:"read_confidential"`
|
||||
Write bool `json:"write"`
|
||||
ManageBadges bool `json:"manage_badges"`
|
||||
BetaKeys bool `json:"beta_keys"`
|
||||
ManageSettings bool `json:"manage_settings"`
|
||||
ViewUserAdvanced bool `json:"view_user_advanced"`
|
||||
ManageUser bool `json:"manage_user"`
|
||||
ManageRoles bool `json:"manage_roles"`
|
||||
ManageAPIKeys bool `json:"manage_api_keys"`
|
||||
Blog bool `json:"blog"`
|
||||
APIMeta bool `json:"api_meta"`
|
||||
Beatmap bool `json:"beatmap"`
|
||||
}
|
||||
|
||||
// PrivilegesGET returns an explaination for the privileges, telling the client what they can do with this token.
|
||||
func PrivilegesGET(md common.MethodData) common.CodeMessager {
|
||||
r := privilegesData{}
|
||||
r.Code = 200
|
||||
// This code sucks.
|
||||
r.Read = true
|
||||
r.ReadConfidential = md.User.Privileges.HasPrivilegeReadConfidential()
|
||||
r.Write = md.User.Privileges.HasPrivilegeWrite()
|
||||
r.ManageBadges = md.User.Privileges.HasPrivilegeManageBadges()
|
||||
r.BetaKeys = md.User.Privileges.HasPrivilegeBetaKeys()
|
||||
r.ManageSettings = md.User.Privileges.HasPrivilegeManageSettings()
|
||||
r.ViewUserAdvanced = md.User.Privileges.HasPrivilegeViewUserAdvanced()
|
||||
r.ManageUser = md.User.Privileges.HasPrivilegeManageUser()
|
||||
r.ManageRoles = md.User.Privileges.HasPrivilegeManageRoles()
|
||||
r.ManageAPIKeys = md.User.Privileges.HasPrivilegeManageAPIKeys()
|
||||
r.Blog = md.User.Privileges.HasPrivilegeBlog()
|
||||
r.APIMeta = md.User.Privileges.HasPrivilegeAPIMeta()
|
||||
r.Beatmap = md.User.Privileges.HasPrivilegeBeatmap()
|
||||
return r
|
||||
}
|
|
@ -83,7 +83,8 @@ SELECT
|
|||
FROM scores
|
||||
INNER JOIN users ON users.id = scores.userid
|
||||
INNER JOIN users_stats ON users_stats.id = scores.userid
|
||||
WHERE scores.beatmap_md5 = ? AND scores.completed = '3' AND users.privileges & 1 > 0 `+genModeClause(md)+`
|
||||
WHERE scores.beatmap_md5 = ? AND scores.completed = '3' AND `+md.User.OnlyUserPublic(true)+
|
||||
` `+genModeClause(md)+`
|
||||
`+sort+common.Paginate(md.Query("p"), md.Query("l"), 100), beatmapMD5)
|
||||
if err != nil {
|
||||
md.Err(err)
|
||||
|
|
|
@ -63,10 +63,10 @@ func TokenNewPOST(md common.MethodData) common.CodeMessager {
|
|||
rank int
|
||||
pw string
|
||||
pwVersion int
|
||||
privileges int
|
||||
privilegesRaw uint64
|
||||
)
|
||||
|
||||
err = q.Scan(&r.ID, &r.Username, &rank, &pw, &pwVersion, &privileges)
|
||||
err = q.Scan(&r.ID, &r.Username, &rank, &pw, &pwVersion, &privilegesRaw)
|
||||
switch {
|
||||
case err == sql.ErrNoRows:
|
||||
return common.SimpleResponse(404, "No user with that username/id was found.")
|
||||
|
@ -74,6 +74,7 @@ func TokenNewPOST(md common.MethodData) common.CodeMessager {
|
|||
md.Err(err)
|
||||
return Err500
|
||||
}
|
||||
privileges := common.UserPrivileges(privilegesRaw)
|
||||
|
||||
if nFailedAttempts(r.ID) > 20 {
|
||||
return common.SimpleResponse(429, "You've made too many login attempts. Try again later.")
|
||||
|
@ -231,9 +232,14 @@ LEFT JOIN users ON users.id = tokens.user
|
|||
privsRaw uint64
|
||||
privs common.Privileges
|
||||
newPrivs common.Privileges
|
||||
privileges int
|
||||
privilegesRaw uint64
|
||||
)
|
||||
rows.Scan(&id, &privsRaw, &privileges)
|
||||
err := rows.Scan(&id, &privsRaw, &privilegesRaw)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
continue
|
||||
}
|
||||
privileges := common.UserPrivileges(privilegesRaw)
|
||||
privs = common.Privileges(privsRaw)
|
||||
newPrivs = privs.CanOnly(privileges)
|
||||
if newPrivs != privs {
|
||||
|
|
|
@ -36,7 +36,7 @@ SELECT users.id, users.username, register_datetime, privileges,
|
|||
FROM users
|
||||
LEFT JOIN users_stats
|
||||
ON users.id=users_stats.id
|
||||
WHERE ` + whereClause + ` AND users.privileges & 1 > 0
|
||||
WHERE ` + whereClause + ` AND ` + md.User.OnlyUserPublic(true) + `
|
||||
LIMIT 1`
|
||||
return userPuts(md, md.DB.QueryRowx(query, param))
|
||||
}
|
||||
|
@ -92,10 +92,11 @@ type whatIDResponse struct {
|
|||
func UserWhatsTheIDGET(md common.MethodData) common.CodeMessager {
|
||||
var (
|
||||
r whatIDResponse
|
||||
privileges int
|
||||
privileges uint64
|
||||
)
|
||||
err := md.DB.QueryRow("SELECT id, privileges FROM users WHERE username = ? LIMIT 1", md.Query("name")).Scan(&r.ID, &privileges)
|
||||
if err != nil || ((privileges&common.UserPrivilegePublic) == 0 && !md.User.Privileges.HasPrivilegeViewUserAdvanced()) {
|
||||
if err != nil || ((privileges&uint64(common.UserPrivilegePublic)) == 0 &&
|
||||
(md.User.UserPrivileges&common.AdminPrivilegeManageUsers == 0)) {
|
||||
return common.SimpleResponse(404, "That user could not be found!")
|
||||
}
|
||||
r.Code = 200
|
||||
|
@ -167,7 +168,7 @@ LEFT JOIN leaderboard_ctb
|
|||
ON users.id=leaderboard_ctb.user
|
||||
LEFT JOIN leaderboard_mania
|
||||
ON users.id=leaderboard_mania.user
|
||||
WHERE ` + whereClause + ` AND users.privileges & 1 > 0
|
||||
WHERE ` + whereClause + ` AND ` + md.User.OnlyUserPublic(true) + `
|
||||
LIMIT 1
|
||||
`
|
||||
// Fuck.
|
||||
|
@ -278,7 +279,8 @@ func UserLookupGET(md common.MethodData) common.CodeMessager {
|
|||
return common.SimpleResponse(400, "please provide an username to start searching")
|
||||
}
|
||||
name = "%" + name + "%"
|
||||
rows, err := md.DB.Query("SELECT users.id, users.username FROM users WHERE username LIKE ? AND privileges & 1 > 0 LIMIT 25", name)
|
||||
rows, err := md.DB.Query("SELECT users.id, users.username FROM users WHERE username LIKE ? AND "+
|
||||
md.User.OnlyUserPublic(true)+" LIMIT 25", name)
|
||||
if err != nil {
|
||||
md.Err(err)
|
||||
return Err500
|
||||
|
|
|
@ -52,7 +52,7 @@ func UserScoresBestGET(md common.MethodData) common.CodeMessager {
|
|||
scores.completed = '3'
|
||||
AND %s
|
||||
%s
|
||||
AND users.privileges & 1 > 0
|
||||
AND `+md.User.OnlyUserPublic(true)+`
|
||||
ORDER BY scores.pp DESC, scores.score DESC %s`,
|
||||
wc, mc, common.Paginate(md.Query("p"), md.Query("l"), 100),
|
||||
), param)
|
||||
|
@ -68,7 +68,7 @@ func UserScoresRecentGET(md common.MethodData) common.CodeMessager {
|
|||
`WHERE
|
||||
%s
|
||||
%s
|
||||
AND users.privileges & 1 > 0
|
||||
AND `+md.User.OnlyUserPublic(true)+`
|
||||
ORDER BY scores.time DESC %s`,
|
||||
wc, genModeClause(md), common.Paginate(md.Query("p"), md.Query("l"), 100),
|
||||
), param)
|
||||
|
|
|
@ -30,6 +30,13 @@ func (md MethodData) Query(q string) string {
|
|||
return md.C.Query(q)
|
||||
}
|
||||
|
||||
// HasQuery returns true if the parameter is encountered in the querystring.
|
||||
// It returns true even if the parameter is "" (the case of ?param&etc=etc)
|
||||
func (md MethodData) HasQuery(q string) bool {
|
||||
_, has := md.C.GetQuery(q)
|
||||
return has
|
||||
}
|
||||
|
||||
// RequestData is the body of a request. It is wrapped into this type
|
||||
// to implement the Unmarshal function, which is just a shorthand to
|
||||
// json.Unmarshal.
|
||||
|
|
|
@ -22,66 +22,6 @@ const (
|
|||
// Privileges is a bitwise enum of the privileges of an user's API key.
|
||||
type Privileges uint64
|
||||
|
||||
// HasPrivilegeReadConfidential returns whether the ReadConfidential privilege is included in the privileges.
|
||||
func (p Privileges) HasPrivilegeReadConfidential() bool {
|
||||
return p&PrivilegeReadConfidential != 0
|
||||
}
|
||||
|
||||
// HasPrivilegeWrite returns whether the Write privilege is included in the privileges.
|
||||
func (p Privileges) HasPrivilegeWrite() bool {
|
||||
return p&PrivilegeWrite != 0
|
||||
}
|
||||
|
||||
// HasPrivilegeManageBadges returns whether the ManageBadges privilege is included in the privileges.
|
||||
func (p Privileges) HasPrivilegeManageBadges() bool {
|
||||
return p&PrivilegeManageBadges != 0
|
||||
}
|
||||
|
||||
// HasPrivilegeBetaKeys returns whether the BetaKeys privilege is included in the privileges.
|
||||
func (p Privileges) HasPrivilegeBetaKeys() bool {
|
||||
return p&PrivilegeBetaKeys != 0
|
||||
}
|
||||
|
||||
// HasPrivilegeManageSettings returns whether the ManageSettings privilege is included in the privileges.
|
||||
func (p Privileges) HasPrivilegeManageSettings() bool {
|
||||
return p&PrivilegeManageSettings != 0
|
||||
}
|
||||
|
||||
// HasPrivilegeViewUserAdvanced returns whether the ViewUserAdvanced privilege is included in the privileges.
|
||||
func (p Privileges) HasPrivilegeViewUserAdvanced() bool {
|
||||
return p&PrivilegeViewUserAdvanced != 0
|
||||
}
|
||||
|
||||
// HasPrivilegeManageUser returns whether the ManageUser privilege is included in the privileges.
|
||||
func (p Privileges) HasPrivilegeManageUser() bool {
|
||||
return p&PrivilegeManageUser != 0
|
||||
}
|
||||
|
||||
// HasPrivilegeManageRoles returns whether the ManageRoles privilege is included in the privileges.
|
||||
func (p Privileges) HasPrivilegeManageRoles() bool {
|
||||
return p&PrivilegeManageRoles != 0
|
||||
}
|
||||
|
||||
// HasPrivilegeManageAPIKeys returns whether the ManageAPIKeys privilege is included in the privileges.
|
||||
func (p Privileges) HasPrivilegeManageAPIKeys() bool {
|
||||
return p&PrivilegeManageAPIKeys != 0
|
||||
}
|
||||
|
||||
// HasPrivilegeBlog returns whether the Blog privilege is included in the privileges.
|
||||
func (p Privileges) HasPrivilegeBlog() bool {
|
||||
return p&PrivilegeBlog != 0
|
||||
}
|
||||
|
||||
// HasPrivilegeAPIMeta returns whether the APIMeta privilege is included in the privileges.
|
||||
func (p Privileges) HasPrivilegeAPIMeta() bool {
|
||||
return p&PrivilegeAPIMeta != 0
|
||||
}
|
||||
|
||||
// HasPrivilegeBeatmap returns whether the Beatmap privilege is included in the privileges.
|
||||
func (p Privileges) HasPrivilegeBeatmap() bool {
|
||||
return p&PrivilegeBeatmap != 0
|
||||
}
|
||||
|
||||
var privilegeString = [...]string{
|
||||
"Read",
|
||||
"ReadConfidential",
|
||||
|
@ -101,14 +41,14 @@ var privilegeString = [...]string{
|
|||
func (p Privileges) String() string {
|
||||
var pvs []string
|
||||
for i, v := range privilegeString {
|
||||
if int(p)&(1<<uint(i)) != 0 {
|
||||
if uint64(p)&uint64(1<<uint(i)) != 0 {
|
||||
pvs = append(pvs, v)
|
||||
}
|
||||
}
|
||||
return strings.Join(pvs, ", ")
|
||||
}
|
||||
|
||||
var privilegeMustBe = [...]int{
|
||||
var privilegeMustBe = [...]UserPrivileges{
|
||||
1 << 30, // read is deprecated, and should be given out to no-one.
|
||||
UserPrivilegeNormal,
|
||||
UserPrivilegeNormal,
|
||||
|
@ -125,7 +65,7 @@ var privilegeMustBe = [...]int{
|
|||
}
|
||||
|
||||
// CanOnly removes any privilege that the user has requested to have, but cannot have due to their rank.
|
||||
func (p Privileges) CanOnly(userPrivs int) Privileges {
|
||||
func (p Privileges) CanOnly(userPrivs UserPrivileges) Privileges {
|
||||
newPrivilege := 0
|
||||
for i, v := range privilegeMustBe {
|
||||
wants := p&1 == 1
|
||||
|
|
|
@ -1,9 +1,23 @@
|
|||
package common
|
||||
|
||||
// Token Is an API token.
|
||||
import "fmt"
|
||||
|
||||
// Token is an API token.
|
||||
type Token struct {
|
||||
ID int
|
||||
Value string
|
||||
UserID int
|
||||
Privileges Privileges
|
||||
TokenPrivileges Privileges
|
||||
UserPrivileges UserPrivileges
|
||||
}
|
||||
|
||||
// OnlyUserPublic returns a string containing "(user.privileges & 1 = 1 OR users.id = <userID>)"
|
||||
// if the user does not have the UserPrivilege AdminManageUsers, and returns "1" otherwise.
|
||||
func (t Token) OnlyUserPublic(userManagerSeesEverything bool) string {
|
||||
if userManagerSeesEverything &&
|
||||
t.UserPrivileges&AdminPrivilegeManageUsers == AdminPrivilegeManageUsers {
|
||||
return "1"
|
||||
}
|
||||
// It's safe to use sprintf directly even if it's a query, because UserID is an int.
|
||||
return fmt.Sprintf("(user.privileges & 1 = 1 OR users.id = '%d')", t.UserID)
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package common
|
||||
|
||||
import "strings"
|
||||
|
||||
// user/admin privileges
|
||||
const (
|
||||
UserPrivilegePublic = 1 << iota
|
||||
UserPrivilegePublic UserPrivileges = 1 << iota
|
||||
UserPrivilegeNormal
|
||||
UserPrivilegeDonor
|
||||
AdminPrivilegeAccessRAP
|
||||
|
@ -22,4 +24,42 @@ const (
|
|||
AdminPrivilegeSendAlerts
|
||||
AdminPrivilegeChatMod
|
||||
AdminPrivilegeKickUsers
|
||||
UserPrivilegePendingVerification
|
||||
)
|
||||
|
||||
// UserPrivileges represents a bitwise enum of the privileges of an user.
|
||||
type UserPrivileges uint64
|
||||
|
||||
var userPrivilegeString = [...]string{
|
||||
"UserPublic",
|
||||
"UserNormal",
|
||||
"UserDonor",
|
||||
"AdminAccessRAP",
|
||||
"AdminManageUsers",
|
||||
"AdminBanUsers",
|
||||
"AdminSilenceUsers",
|
||||
"AdminWipeUsers",
|
||||
"AdminManageBeatmap",
|
||||
"AdminManageServer",
|
||||
"AdminManageSetting",
|
||||
"AdminManageBetaKey",
|
||||
"AdminManageReport",
|
||||
"AdminManageDocs",
|
||||
"AdminManageBadges",
|
||||
"AdminViewRAPLogs",
|
||||
"AdminManagePrivilege",
|
||||
"AdminSendAlerts",
|
||||
"AdminChatMod",
|
||||
"AdminKickUsers",
|
||||
"UserPendingVerification",
|
||||
}
|
||||
|
||||
func (p UserPrivileges) String() string {
|
||||
var pvs []string
|
||||
for i, v := range userPrivilegeString {
|
||||
if uint64(p)&uint64(1<<uint(i)) != 0 {
|
||||
pvs = append(pvs, v)
|
||||
}
|
||||
}
|
||||
return strings.Join(pvs, ", ")
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user