diff --git a/app/v1/friend.go b/app/v1/friend.go index ee9d0a4..44ed9a7 100644 --- a/app/v1/friend.go +++ b/app/v1/friend.go @@ -43,7 +43,7 @@ func FriendsGET(md common.MethodData) common.CodeMessager { // Yes. myFriendsQuery := ` SELECT - users.id, users.username, users.register_datetime, users.rank, users.latest_activity, + users.id, users.username, users.register_datetime, users.privileges, users.latest_activity, users_stats.username_aka, users_stats.country, users_stats.show_country @@ -90,7 +90,7 @@ func friendPuts(md common.MethodData, row *sql.Rows) (user friendData) { registeredOn := int64(0) latestActivity := int64(0) var showcountry bool - err = row.Scan(&user.ID, &user.Username, ®isteredOn, &user.Rank, &latestActivity, &user.UsernameAKA, &user.Country, &showcountry) + err = row.Scan(&user.ID, &user.Username, ®isteredOn, &user.Privileges, &latestActivity, &user.UsernameAKA, &user.Country, &showcountry) if err != nil { md.Err(err) return diff --git a/app/v1/leaderboard.go b/app/v1/leaderboard.go index 093658f..3c5b435 100644 --- a/app/v1/leaderboard.go +++ b/app/v1/leaderboard.go @@ -21,7 +21,7 @@ type leaderboardResponse struct { const lbUserQuery = ` SELECT - users.id, users.username, users.register_datetime, users.rank, users.latest_activity, + users.id, users.username, users.register_datetime, users.privileges, users.latest_activity, users_stats.username_aka, users_stats.country, users_stats.show_country, users_stats.play_style, users_stats.favourite_mode, @@ -53,7 +53,7 @@ func LeaderboardGET(md common.MethodData) common.CodeMessager { showCountry bool ) err := rows.Scan( - &u.ID, &u.Username, ®ister, &u.Rank, &latestActivity, + &u.ID, &u.Username, ®ister, &u.Privileges, &latestActivity, &u.UsernameAKA, &u.Country, &showCountry, &u.PlayStyle, &u.FavouriteMode, diff --git a/app/v1/manage_user.go b/app/v1/manage_user.go index eb54b6e..b751fab 100644 --- a/app/v1/manage_user.go +++ b/app/v1/manage_user.go @@ -30,7 +30,7 @@ func UserManageSetAllowedPOST(md common.MethodData) common.CodeMessager { } if data.Allowed == 0 { banDatetime = time.Now().Unix() - newPrivileges = privileges &^(common.UserPrivilegeNormal | common.UserPrivilegePublic) + newPrivileges = privileges &^ (common.UserPrivilegeNormal | common.UserPrivilegePublic) } else { banDatetime = 0 newPrivileges = privileges | (common.UserPrivilegeNormal | common.UserPrivilegePublic) @@ -42,7 +42,7 @@ func UserManageSetAllowedPOST(md common.MethodData) common.CodeMessager { } go fixPrivileges(data.UserID, md.DB) query := ` -SELECT users.id, users.username, register_datetime, rank, +SELECT users.id, users.username, register_datetime, privileges, latest_activity, users_stats.username_aka, users_stats.country, users_stats.show_country FROM users diff --git a/app/v1/token.go b/app/v1/token.go index 6d53b57..0f61c68 100644 --- a/app/v1/token.go +++ b/app/v1/token.go @@ -50,7 +50,7 @@ func TokenNewPOST(md common.MethodData) common.CodeMessager { } var q *sql.Row - const base = "SELECT id, username, rank, password_md5, password_version, privileges FROM users " + const base = "SELECT id, username, privileges, password_md5, password_version, privileges FROM users " if data.UserID != 0 { q = md.DB.QueryRow(base+"WHERE id = ? LIMIT 1", data.UserID) } else { @@ -58,10 +58,10 @@ func TokenNewPOST(md common.MethodData) common.CodeMessager { } var ( - rank int - pw string - pwVersion int - privileges int + rank int + pw string + pwVersion int + privileges int ) err = q.Scan(&r.ID, &r.Username, &rank, &pw, &pwVersion, &privileges) @@ -88,13 +88,14 @@ func TokenNewPOST(md common.MethodData) common.CodeMessager { md.Err(err) return Err500 } - if (privileges & 0) == 0 { + const want = (common.UserPrivilegePublic | common.UserPrivilegeNormal) + if (privileges & want) != want { r.Code = 200 r.Message = "That user is banned." r.Banned = true return r } - r.Privileges = int(common.Privileges(data.Privileges).CanOnly(rank)) + r.Privileges = int(common.Privileges(data.Privileges).CanOnly(privileges)) var ( tokenStr string @@ -104,7 +105,7 @@ func TokenNewPOST(md common.MethodData) common.CodeMessager { tokenStr = common.RandomString(32) tokenMD5 = fmt.Sprintf("%x", md5.Sum([]byte(tokenStr))) r.Token = tokenStr - id := 0 + var id int err := md.DB.QueryRow("SELECT id FROM tokens WHERE token=? LIMIT 1", tokenMD5).Scan(&id) if err == sql.ErrNoRows { @@ -210,7 +211,7 @@ func fixPrivileges(user int, db *sql.DB) { } rows, err := db.Query(` SELECT - tokens.id, tokens.privileges, users.rank + tokens.id, tokens.privileges, users.privileges FROM tokens LEFT JOIN users ON users.id = tokens.user `+wc, params...) @@ -221,15 +222,15 @@ LEFT JOIN users ON users.id = tokens.user } for rows.Next() { var ( - id int - privsRaw uint64 - privs common.Privileges - newPrivs common.Privileges - rank int + id int + privsRaw uint64 + privs common.Privileges + newPrivs common.Privileges + privileges int ) - rows.Scan(&id, &privsRaw, &rank) + rows.Scan(&id, &privsRaw, &privileges) privs = common.Privileges(privsRaw) - newPrivs = privs.CanOnly(rank) + newPrivs = privs.CanOnly(privileges) if newPrivs != privs { _, err := db.Exec("UPDATE tokens SET privileges = ? WHERE id = ? LIMIT 1", uint64(newPrivs), id) if err != nil { diff --git a/app/v1/user.go b/app/v1/user.go index d338fcc..b8b37e7 100644 --- a/app/v1/user.go +++ b/app/v1/user.go @@ -16,7 +16,7 @@ type userData struct { Username string `json:"username"` UsernameAKA string `json:"username_aka"` RegisteredOn time.Time `json:"registered_on"` - Rank int `json:"rank"` + Privileges uint64 `json:"rank"` LatestActivity time.Time `json:"latest_activity"` Country string `json:"country"` } @@ -29,7 +29,7 @@ func UsersGET(md common.MethodData) common.CodeMessager { } query := ` -SELECT users.id, users.username, register_datetime, rank, +SELECT users.id, users.username, register_datetime, privileges, latest_activity, users_stats.username_aka, users_stats.country, users_stats.show_country FROM users @@ -54,7 +54,7 @@ func userPuts(md common.MethodData, row *sql.Row) common.CodeMessager { latestActivity int64 showCountry bool ) - err = row.Scan(&user.ID, &user.Username, ®isteredOn, &user.Rank, &latestActivity, &user.UsernameAKA, &user.Country, &showCountry) + err = row.Scan(&user.ID, &user.Username, ®isteredOn, &user.Privileges, &latestActivity, &user.UsernameAKA, &user.Country, &showCountry) switch { case err == sql.ErrNoRows: return common.SimpleResponse(404, "No such user was found!") @@ -109,11 +109,11 @@ type whatIDResponse struct { // UserWhatsTheIDGET is an API request that only returns an user's ID. func UserWhatsTheIDGET(md common.MethodData) common.CodeMessager { var ( - r whatIDResponse + r whatIDResponse privileges int ) err := md.DB.QueryRow("SELECT id, privileges FROM users WHERE username = ? LIMIT 1", md.C.Query("name")).Scan(&r.ID, &privileges) - if err != nil || ( (privileges & common.UserPrivilegePublic) == 0 && !md.User.Privileges.HasPrivilegeViewUserAdvanced()) { + if err != nil || ((privileges&common.UserPrivilegePublic) == 0 && !md.User.Privileges.HasPrivilegeViewUserAdvanced()) { return common.SimpleResponse(404, "That user could not be found!") } r.Code = 200 @@ -153,7 +153,7 @@ func UserFullGET(md common.MethodData) common.CodeMessager { // Hellest query I've ever done. query := ` SELECT - users.id, users.username, users.register_datetime, users.rank, users.latest_activity, + users.id, users.username, users.register_datetime, users.privileges, users.latest_activity, users_stats.username_aka, users_stats.badges_shown, users_stats.country, users_stats.show_country, users_stats.play_style, users_stats.favourite_mode, @@ -198,7 +198,7 @@ LIMIT 1 latestActivity int64 ) err := md.DB.QueryRow(query, param).Scan( - &r.ID, &r.Username, ®isteredOn, &r.Rank, &latestActivity, + &r.ID, &r.Username, ®isteredOn, &r.Privileges, &latestActivity, &r.UsernameAKA, &badges, &country, &showCountry, &r.PlayStyle, &r.FavouriteMode, diff --git a/common/privileges.go b/common/privileges.go index e8abcc6..0749ee0 100644 --- a/common/privileges.go +++ b/common/privileges.go @@ -114,27 +114,27 @@ func (p Privileges) String() string { } var privilegeMustBe = [...]int{ - 1, - 1, - 1, - 3, - 3, - 4, - 4, - 4, - 4, - 4, - 3, - 4, - 4, + UserPrivilegeNormal, + UserPrivilegeNormal, + UserPrivilegeNormal, + AdminPrivilegeAccessRAP | AdminPrivilegeManageBadges, + AdminPrivilegeAccessRAP | AdminPrivilegeManageBetaKey, + AdminPrivilegeAccessRAP | AdminPrivilegeManageSetting, + AdminPrivilegeAccessRAP, + AdminPrivilegeAccessRAP | AdminPrivilegeManageUsers | AdminPrivilegeBanUsers, + AdminPrivilegeAccessRAP | AdminPrivilegeManageUsers | AdminPrivilegeManagePrivilege, + AdminPrivilegeAccessRAP | AdminPrivilegeManageUsers | AdminPrivilegeManageServer, + AdminPrivilegeChatMod, // temporary? + AdminPrivilegeManageServer, + AdminPrivilegeAccessRAP | AdminPrivilegeManageBeatmap, } // CanOnly removes any privilege that the user has requested to have, but cannot have due to their rank. -func (p Privileges) CanOnly(rank int) Privileges { +func (p Privileges) CanOnly(userPrivs int) Privileges { newPrivilege := 0 for i, v := range privilegeMustBe { wants := p&1 == 1 - can := rank >= v + can := userPrivs&v == v if wants && can { newPrivilege |= 1 << uint(i) } diff --git a/common/user_privileges.go b/common/user_privileges.go index f8d8260..046b614 100644 --- a/common/user_privileges.go +++ b/common/user_privileges.go @@ -1,5 +1,6 @@ package common +// user/admin privileges const ( UserPrivilegePublic = 1 << iota UserPrivilegeNormal