github.com/Azareal/Gosora@v0.0.0-20210729070923-553e66b59003/routes/panel/groups.go (about) 1 package panel 2 3 import ( 4 "database/sql" 5 "net/http" 6 "strconv" 7 "strings" 8 9 c "github.com/Azareal/Gosora/common" 10 p "github.com/Azareal/Gosora/common/phrases" 11 ) 12 13 func Groups(w http.ResponseWriter, r *http.Request, u *c.User) c.RouteError { 14 bPage, ferr := buildBasePage(w, r, u, "groups", "groups") 15 if ferr != nil { 16 return ferr 17 } 18 page, _ := strconv.Atoi(r.FormValue("page")) 19 perPage := 15 20 offset, page, lastPage := c.PageOffset(bPage.Stats.Groups, page, perPage) 21 22 // Skip the 'Unknown' group 23 offset++ 24 25 var count int 26 var groupList []c.GroupAdmin 27 groups, _ := c.Groups.GetRange(offset, 0) 28 for _, g := range groups { 29 if count == perPage { 30 break 31 } 32 var rank, rankClass string 33 canDelete := false 34 35 // TODO: Localise this 36 switch { 37 case g.IsAdmin: 38 rank = "Admin" 39 rankClass = "admin" 40 case g.IsMod: 41 rank = "Mod" 42 rankClass = "mod" 43 case g.IsBanned: 44 rank = "Banned" 45 rankClass = "banned" 46 case g.ID == 6: 47 rank = "Guest" 48 rankClass = "guest" 49 default: 50 rank = "Member" 51 rankClass = "member" 52 } 53 54 canEdit := u.Perms.EditGroup && (!g.IsAdmin || u.Perms.EditGroupAdmin) && (!g.IsMod || u.Perms.EditGroupSuperMod) 55 groupList = append(groupList, c.GroupAdmin{g.ID, g.Name, rank, rankClass, canEdit, canDelete}) 56 count++ 57 } 58 59 pageList := c.Paginate(page, lastPage, 5) 60 pi := c.PanelGroupPage{bPage, groupList, c.Paginator{pageList, page, lastPage}} 61 return renderTemplate("panel", w, r, bPage.Header, c.Panel{bPage, "", "", "panel_groups", &pi}) 62 } 63 64 func GroupsEdit(w http.ResponseWriter, r *http.Request, user *c.User, sgid string) c.RouteError { 65 basePage, ferr := buildBasePage(w, r, user, "edit_group", "groups") 66 if ferr != nil { 67 return ferr 68 } 69 if !user.Perms.EditGroup { 70 return c.NoPermissions(w, r, user) 71 } 72 73 gid, err := strconv.Atoi(sgid) 74 if err != nil { 75 return c.LocalError(p.GetErrorPhrase("url_id_must_be_integer"), w, r, user) 76 } 77 g, err := c.Groups.Get(gid) 78 if err == sql.ErrNoRows { 79 //log.Print("aaaaa monsters") 80 return c.NotFound(w, r, basePage.Header) 81 } 82 ferr = groupCheck(w, r, user, g, err) 83 if ferr != nil { 84 return ferr 85 } 86 87 var rank string 88 switch { 89 case g.IsAdmin: 90 rank = "Admin" 91 case g.IsMod: 92 rank = "Mod" 93 case g.IsBanned: 94 rank = "Banned" 95 case g.ID == 6: 96 rank = "Guest" 97 default: 98 rank = "Member" 99 } 100 disableRank := !user.Perms.EditGroupGlobalPerms || (g.ID == 6) 101 102 pi := c.PanelEditGroupPage{basePage, g.ID, g.Name, g.Tag, rank, disableRank} 103 return renderTemplate("panel_group_edit", w, r, basePage.Header, pi) 104 } 105 106 func GroupsEditPromotions(w http.ResponseWriter, r *http.Request, user *c.User, sgid string) c.RouteError { 107 basePage, ferr := buildBasePage(w, r, user, "edit_group", "groups") 108 if ferr != nil { 109 return ferr 110 } 111 if !user.Perms.EditGroup { 112 return c.NoPermissions(w, r, user) 113 } 114 115 gid, err := strconv.Atoi(sgid) 116 if err != nil { 117 return c.LocalError(p.GetErrorPhrase("url_id_must_be_integer"), w, r, user) 118 } 119 g, err := c.Groups.Get(gid) 120 if err == sql.ErrNoRows { 121 //log.Print("aaaaa monsters") 122 return c.NotFound(w, r, basePage.Header) 123 } 124 ferr = groupCheck(w, r, user, g, err) 125 if ferr != nil { 126 return ferr 127 } 128 129 promotions, err := c.GroupPromotions.GetByGroup(g.ID) 130 if err != sql.ErrNoRows && err != nil { 131 return c.InternalError(err, w, r) 132 } 133 promoteExt := make([]*c.GroupPromotionExtend, len(promotions)) 134 for i, promote := range promotions { 135 fg, err := c.Groups.Get(promote.From) 136 if err == sql.ErrNoRows { 137 fg = &c.Group{Name: "Deleted Group"} 138 } else if err != nil { 139 return c.InternalError(err, w, r) 140 } 141 tg, err := c.Groups.Get(promote.To) 142 if err == sql.ErrNoRows { 143 tg = &c.Group{Name: "Deleted Group"} 144 } else if err != nil { 145 return c.InternalError(err, w, r) 146 } 147 promoteExt[i] = &c.GroupPromotionExtend{promote, fg, tg} 148 } 149 150 // ? - Should we stop admins from deleting all the groups? Maybe, protect the group they're currently using? 151 groups, err := c.Groups.GetRange(1, 0) // ? - 0 = Go to the end 152 if err != nil { 153 return c.InternalError(err, w, r) 154 } 155 156 var groupList []*c.Group 157 for _, group := range groups { 158 if !user.Perms.EditUserGroupAdmin && group.IsAdmin { 159 continue 160 } 161 if !user.Perms.EditUserGroupSuperMod && group.IsMod { 162 continue 163 } 164 groupList = append(groupList, group) 165 } 166 167 pi := c.PanelEditGroupPromotionsPage{basePage, g.ID, g.Name, promoteExt, groupList} 168 return renderTemplate("panel_group_edit_promotions", w, r, basePage.Header, pi) 169 } 170 171 func groupCheck(w http.ResponseWriter, r *http.Request, u *c.User, g *c.Group, err error) c.RouteError { 172 if err == sql.ErrNoRows { 173 return c.LocalError("No such group.", w, r, u) 174 } else if err != nil { 175 return c.InternalError(err, w, r) 176 } 177 if g.IsAdmin && !u.Perms.EditGroupAdmin { 178 return c.LocalError(p.GetErrorPhrase("panel_groups_cannot_edit_admin"), w, r, u) 179 } 180 if g.IsMod && !u.Perms.EditGroupSuperMod { 181 return c.LocalError(p.GetErrorPhrase("panel_groups_cannot_edit_supermod"), w, r, u) 182 } 183 return nil 184 } 185 186 func GroupsPromotionsCreateSubmit(w http.ResponseWriter, r *http.Request, u *c.User, sgid string) c.RouteError { 187 if !u.Perms.EditGroup { 188 return c.NoPermissions(w, r, u) 189 } 190 gid, err := strconv.Atoi(sgid) 191 if err != nil { 192 return c.LocalError(p.GetErrorPhrase("url_id_must_be_integer"), w, r, u) 193 } 194 195 from, err := strconv.Atoi(r.FormValue("from")) 196 if err != nil { 197 return c.LocalError("from must be integer", w, r, u) 198 } 199 to, err := strconv.Atoi(r.FormValue("to")) 200 if err != nil { 201 return c.LocalError("to must be integer", w, r, u) 202 } 203 if from == to { 204 return c.LocalError("the from group and to group cannot be the same", w, r, u) 205 } 206 twoWay := r.FormValue("two-way") == "1" 207 208 level, err := strconv.Atoi(r.FormValue("level")) 209 if err != nil { 210 return c.LocalError("level must be integer", w, r, u) 211 } 212 posts, err := strconv.Atoi(r.FormValue("posts")) 213 if err != nil { 214 return c.LocalError("posts must be integer", w, r, u) 215 } 216 217 regHours, err := strconv.Atoi(r.FormValue("reg_hours")) 218 if err != nil { 219 return c.LocalError("reg_hours must be integer", w, r, u) 220 } 221 regDays, err := strconv.Atoi(r.FormValue("reg_days")) 222 if err != nil { 223 return c.LocalError("reg_days must be integer", w, r, u) 224 } 225 regMonths, err := strconv.Atoi(r.FormValue("reg_months")) 226 if err != nil { 227 return c.LocalError("reg_months must be integer", w, r, u) 228 } 229 regMinutes := (regHours * 60) + (regDays * 24 * 60) + (regMonths * 30 * 24 * 60) 230 231 g, err := c.Groups.Get(from) 232 ferr := groupCheck(w, r, u, g, err) 233 if err != nil { 234 return ferr 235 } 236 g, err = c.Groups.Get(to) 237 ferr = groupCheck(w, r, u, g, err) 238 if err != nil { 239 return ferr 240 } 241 pid, err := c.GroupPromotions.Create(from, to, twoWay, level, posts, regMinutes) 242 if err != nil { 243 return c.InternalError(err, w, r) 244 } 245 err = c.AdminLogs.Create("create", pid, "group_promotion", u.GetIP(), u.ID) 246 if err != nil { 247 return c.InternalError(err, w, r) 248 } 249 250 http.Redirect(w, r, "/panel/groups/edit/promotions/"+strconv.Itoa(gid), http.StatusSeeOther) 251 return nil 252 } 253 254 func GroupsPromotionsDeleteSubmit(w http.ResponseWriter, r *http.Request, u *c.User, sspl string) c.RouteError { 255 if !u.Perms.EditGroup { 256 return c.NoPermissions(w, r, u) 257 } 258 spl := strings.Split(sspl, "-") 259 if len(spl) < 2 { 260 return c.LocalError("need two params", w, r, u) 261 } 262 gid, err := strconv.Atoi(spl[0]) 263 if err != nil { 264 return c.LocalError(p.GetErrorPhrase("url_id_must_be_integer"), w, r, u) 265 } 266 pid, err := strconv.Atoi(spl[1]) 267 if err != nil { 268 return c.LocalError(p.GetErrorPhrase("url_id_must_be_integer"), w, r, u) 269 } 270 271 pro, err := c.GroupPromotions.Get(pid) 272 if err == sql.ErrNoRows { 273 return c.LocalError("That group promotion doesn't exist", w, r, u) 274 } else if err != nil { 275 return c.InternalError(err, w, r) 276 } 277 278 g, err := c.Groups.Get(pro.From) 279 ferr := groupCheck(w, r, u, g, err) 280 if err != nil { 281 return ferr 282 } 283 g, err = c.Groups.Get(pro.To) 284 ferr = groupCheck(w, r, u, g, err) 285 if err != nil { 286 return ferr 287 } 288 err = c.GroupPromotions.Delete(pid) 289 if err != nil { 290 return c.InternalError(err, w, r) 291 } 292 err = c.AdminLogs.Create("delete", pid, "group_promotion", u.GetIP(), u.ID) 293 if err != nil { 294 return c.InternalError(err, w, r) 295 } 296 297 http.Redirect(w, r, "/panel/groups/edit/promotions/"+strconv.Itoa(gid), http.StatusSeeOther) 298 return nil 299 } 300 301 func GroupsEditPerms(w http.ResponseWriter, r *http.Request, u *c.User, sgid string) c.RouteError { 302 basePage, ferr := buildBasePage(w, r, u, "edit_group", "groups") 303 if ferr != nil { 304 return ferr 305 } 306 if !u.Perms.EditGroup { 307 return c.NoPermissions(w, r, u) 308 } 309 gid, err := strconv.Atoi(sgid) 310 if err != nil { 311 return c.LocalError(p.GetErrorPhrase("url_id_must_be_integer"), w, r, u) 312 } 313 314 g, err := c.Groups.Get(gid) 315 if err == sql.ErrNoRows { 316 //log.Print("aaaaa monsters") 317 return c.NotFound(w, r, basePage.Header) 318 } else if err != nil { 319 return c.InternalError(err, w, r) 320 } 321 if g.IsAdmin && !u.Perms.EditGroupAdmin { 322 return c.LocalError(p.GetErrorPhrase("panel_groups_cannot_edit_admin"), w, r, u) 323 } 324 if g.IsMod && !u.Perms.EditGroupSuperMod { 325 return c.LocalError(p.GetErrorPhrase("panel_groups_cannot_edit_supermod"), w, r, u) 326 } 327 328 // TODO: Load the phrases in bulk for efficiency? 329 var localPerms []c.NameLangToggle 330 addPerm := func(permStr string, perm bool) { 331 localPerms = append(localPerms, c.NameLangToggle{permStr, p.GetPermPhrase(permStr), perm}) 332 } 333 334 addPerm("ViewTopic", g.Perms.ViewTopic) 335 addPerm("LikeItem", g.Perms.LikeItem) 336 addPerm("CreateTopic", g.Perms.CreateTopic) 337 //<-- 338 addPerm("EditTopic", g.Perms.EditTopic) 339 addPerm("DeleteTopic", g.Perms.DeleteTopic) 340 addPerm("CreateReply", g.Perms.CreateReply) 341 addPerm("EditReply", g.Perms.EditReply) 342 addPerm("DeleteReply", g.Perms.DeleteReply) 343 addPerm("PinTopic", g.Perms.PinTopic) 344 addPerm("CloseTopic", g.Perms.CloseTopic) 345 addPerm("MoveTopic", g.Perms.MoveTopic) 346 347 var globalPerms []c.NameLangToggle 348 addPerm = func(permStr string, perm bool) { 349 globalPerms = append(globalPerms, c.NameLangToggle{permStr, p.GetPermPhrase(permStr), perm}) 350 } 351 352 addPerm("UploadFiles", g.Perms.UploadFiles) 353 addPerm("UploadAvatars", g.Perms.UploadAvatars) 354 addPerm("UseConvos", g.Perms.UseConvos) 355 addPerm("UseConvosOnlyWithMod", g.Perms.UseConvosOnlyWithMod) 356 addPerm("CreateProfileReply", g.Perms.CreateProfileReply) 357 addPerm("AutoEmbed", g.Perms.AutoEmbed) 358 addPerm("AutoLink", g.Perms.AutoLink) 359 360 var modPerms []c.NameLangToggle 361 addPerm = func(permStr string, perm bool) { 362 modPerms = append(modPerms, c.NameLangToggle{permStr, p.GetPermPhrase(permStr), perm}) 363 } 364 365 addPerm("BanUsers", g.Perms.BanUsers) 366 addPerm("ActivateUsers", g.Perms.ActivateUsers) 367 addPerm("EditUser", g.Perms.EditUser) 368 addPerm("EditUserEmail", g.Perms.EditUserEmail) 369 addPerm("EditUserPassword", g.Perms.EditUserPassword) 370 addPerm("EditUserGroup", g.Perms.EditUserGroup) 371 addPerm("EditUserGroupSuperMod", g.Perms.EditUserGroupSuperMod) 372 addPerm("EditUserGroupAdmin", g.Perms.EditUserGroupAdmin) 373 addPerm("EditGroup", g.Perms.EditGroup) 374 addPerm("EditGroupLocalPerms", g.Perms.EditGroupLocalPerms) 375 addPerm("EditGroupGlobalPerms", g.Perms.EditGroupGlobalPerms) 376 addPerm("EditGroupSuperMod", g.Perms.EditGroupSuperMod) 377 addPerm("EditGroupAdmin", g.Perms.EditGroupAdmin) 378 addPerm("ManageForums", g.Perms.ManageForums) 379 addPerm("EditSettings", g.Perms.EditSettings) 380 addPerm("ManageThemes", g.Perms.ManageThemes) 381 addPerm("ManagePlugins", g.Perms.ManagePlugins) 382 addPerm("ViewAdminLogs", g.Perms.ViewAdminLogs) 383 addPerm("ViewIPs", g.Perms.ViewIPs) 384 385 pi := c.PanelEditGroupPermsPage{basePage, g.ID, g.Name, localPerms, globalPerms, modPerms} 386 return renderTemplate("panel_group_edit_perms", w, r, basePage.Header, pi) 387 } 388 389 func GroupsEditSubmit(w http.ResponseWriter, r *http.Request, user *c.User, sgid string) c.RouteError { 390 _, ferr := c.SimplePanelUserCheck(w, r, user) 391 if ferr != nil { 392 return ferr 393 } 394 if !user.Perms.EditGroup { 395 return c.NoPermissions(w, r, user) 396 } 397 gid, err := strconv.Atoi(sgid) 398 if err != nil { 399 return c.LocalError(p.GetErrorPhrase("id_must_be_integer"), w, r, user) 400 } 401 group, err := c.Groups.Get(gid) 402 if err == sql.ErrNoRows { 403 //log.Print("aaaaa monsters") 404 return c.NotFound(w, r, nil) 405 } 406 ferr = groupCheck(w, r, user, group, err) 407 if ferr != nil { 408 return ferr 409 } 410 411 name := r.FormValue("name") 412 if name == "" { 413 return c.LocalError(p.GetErrorPhrase("panel_groups_need_name"), w, r, user) 414 } 415 tag := r.FormValue("tag") 416 rank := r.FormValue("type") 417 418 var originalRank string 419 // TODO: Use a switch for this 420 switch { 421 case group.IsAdmin: 422 originalRank = "Admin" 423 case group.IsMod: 424 originalRank = "Mod" 425 case group.IsBanned: 426 originalRank = "Banned" 427 case group.ID == 6: 428 originalRank = "Guest" 429 default: 430 originalRank = "Member" 431 } 432 433 if rank != originalRank && originalRank != "Guest" { 434 if !user.Perms.EditGroupGlobalPerms { 435 return c.LocalError(p.GetErrorPhrase("panel_groups_cannot_edit_group_type"), w, r, user) 436 } 437 switch rank { 438 case "Admin": 439 if !user.Perms.EditGroupAdmin { 440 return c.LocalError(p.GetErrorPhrase("panel_groups_edit_cannot_designate_admin"), w, r, user) 441 } 442 err = group.ChangeRank(true, true, false) 443 case "Mod": 444 if !user.Perms.EditGroupSuperMod { 445 return c.LocalError(p.GetErrorPhrase("panel_groups_edit_cannot_designate_supermod"), w, r, user) 446 } 447 err = group.ChangeRank(false, true, false) 448 case "Banned": 449 err = group.ChangeRank(false, false, true) 450 case "Guest": 451 return c.LocalError(p.GetErrorPhrase("panel_groups_cannot_be_guest"), w, r, user) 452 case "Member": 453 err = group.ChangeRank(false, false, false) 454 default: 455 return c.LocalError(p.GetErrorPhrase("panel_groups_invalid_group_type"), w, r, user) 456 } 457 if err != nil { 458 return c.InternalError(err, w, r) 459 } 460 } 461 462 err = group.Update(name, tag) 463 if err != nil { 464 return c.InternalError(err, w, r) 465 } 466 err = c.AdminLogs.Create("edit", group.ID, "group", user.GetIP(), user.ID) 467 if err != nil { 468 return c.InternalError(err, w, r) 469 } 470 471 http.Redirect(w, r, "/panel/groups/edit/"+strconv.Itoa(gid), http.StatusSeeOther) 472 return nil 473 } 474 475 func GroupsEditPermsSubmit(w http.ResponseWriter, r *http.Request, user *c.User, sgid string) c.RouteError { 476 _, ferr := c.SimplePanelUserCheck(w, r, user) 477 if ferr != nil { 478 return ferr 479 } 480 if !user.Perms.EditGroup { 481 return c.NoPermissions(w, r, user) 482 } 483 gid, err := strconv.Atoi(sgid) 484 if err != nil { 485 return c.LocalError(p.GetErrorPhrase("id_must_be_integer"), w, r, user) 486 } 487 488 group, err := c.Groups.Get(gid) 489 if err == sql.ErrNoRows { 490 //log.Print("aaaaa monsters o.o") 491 return c.NotFound(w, r, nil) 492 } 493 ferr = groupCheck(w, r, user, group, err) 494 if ferr != nil { 495 return ferr 496 } 497 498 // TODO: Don't unset perms we don't have permission to set? 499 pmap := make(map[string]bool) 500 pCheck := func(hasPerm bool, perms []string) { 501 if hasPerm { 502 for _, perm := range perms { 503 pvalue := r.PostFormValue("perm-" + perm) 504 pmap[perm] = (pvalue == "1") 505 } 506 } 507 } 508 pCheck(user.Perms.EditGroupLocalPerms, c.LocalPermList) 509 pCheck(user.Perms.EditGroupGlobalPerms, c.GlobalPermList) 510 511 err = group.UpdatePerms(pmap) 512 if err != nil { 513 return c.InternalError(err, w, r) 514 } 515 err = c.AdminLogs.Create("edit", group.ID, "group", user.GetIP(), user.ID) 516 if err != nil { 517 return c.InternalError(err, w, r) 518 } 519 520 http.Redirect(w, r, "/panel/groups/edit/perms/"+strconv.Itoa(gid), http.StatusSeeOther) 521 return nil 522 } 523 524 func GroupsCreateSubmit(w http.ResponseWriter, r *http.Request, user *c.User) c.RouteError { 525 _, ferr := c.SimplePanelUserCheck(w, r, user) 526 if ferr != nil { 527 return ferr 528 } 529 if !user.Perms.EditGroup { 530 return c.NoPermissions(w, r, user) 531 } 532 533 name := r.PostFormValue("name") 534 if name == "" { 535 return c.LocalError(p.GetErrorPhrase("panel_groups_need_name"), w, r, user) 536 } 537 tag := r.PostFormValue("tag") 538 539 var admin, mod, banned bool 540 if user.Perms.EditGroupGlobalPerms { 541 switch r.PostFormValue("type") { 542 case "Admin": 543 if !user.Perms.EditGroupAdmin { 544 return c.LocalError(p.GetErrorPhrase("panel_groups_create_cannot_designate_admin"), w, r, user) 545 } 546 admin = true 547 mod = true 548 case "Mod": 549 if !user.Perms.EditGroupSuperMod { 550 return c.LocalError(p.GetErrorPhrase("panel_groups_create_cannot_designate_supermod"), w, r, user) 551 } 552 mod = true 553 case "Banned": 554 banned = true 555 } 556 } 557 558 gid, err := c.Groups.Create(name, tag, admin, mod, banned) 559 if err != nil { 560 return c.InternalError(err, w, r) 561 } 562 err = c.AdminLogs.Create("create", gid, "group", user.GetIP(), user.ID) 563 if err != nil { 564 return c.InternalError(err, w, r) 565 } 566 567 http.Redirect(w, r, "/panel/groups/edit/"+strconv.Itoa(gid), http.StatusSeeOther) 568 return nil 569 }