cup/controllers/adminusers.go

605 lines
15 KiB
Go
Raw Normal View History

2024-12-04 08:39:08 -05:00
// Copyright (c) 2024 Zeni Kim <zenik@smarteching.com>
// Use of this source code is governed by MIT-style
// license that can be found in the LICENSE file.
package controllers
import (
"errors"
"fmt"
"strconv"
"git.smarteching.com/goffee/core"
"git.smarteching.com/goffee/core/template/components"
"git.smarteching.com/goffee/cup/events"
"git.smarteching.com/goffee/cup/models"
2024-12-06 04:48:10 -05:00
"git.smarteching.com/goffee/cup/utils"
2024-12-04 08:39:08 -05:00
"gorm.io/gorm"
)
func AdminUsersList(c *core.Context) *core.Response {
// initiate authority
auth := new(utils.Authority)
var session = new(utils.SessionUser)
// true if session is active
hassession := session.Init(c)
if !hassession {
type emptytemplate struct{}
emptyData := emptytemplate{}
return c.Response.Template("nopermission.html", emptyData)
}
session_uid := session.GetUserID()
// check if user has role admin
is_admin, _ := auth.CheckUserRole(c, session_uid, "admin")
if !is_admin {
type emptytemplate struct{}
emptyData := emptytemplate{}
return c.Response.Template("nopermission.html", emptyData)
}
// continue if has session and is admin
2024-12-04 08:39:08 -05:00
var users []models.User
db := c.GetGorm()
db.Find(&users)
// -- response template
type templateData struct {
TableUsers components.ContentTable
AddButton components.ContentHref
}
cols := []components.ContentTableTH{
{
Value: "UID",
ValueType: "number",
},
{
Value: "Name",
ValueType: "string",
},
{
Value: "Fullname",
ValueType: "string",
},
{
Value: "Email",
ValueType: "string",
},
{
Value: "Roles",
ValueType: "string",
},
2024-12-04 08:39:08 -05:00
{
Value: "Created",
},
{
Value: "Updated",
},
{
ValueType: "href",
},
}
var listroles string
2024-12-04 08:39:08 -05:00
rows := make([][]components.ContentTableTD, len(users))
for i, u := range users {
roles, _ := auth.GetUserRoles(c, u.ID)
listroles = ""
for _, role := range roles {
if listroles != "" {
listroles += ", "
}
listroles += role.Name
}
2024-12-04 08:39:08 -05:00
row := []components.ContentTableTD{
{Value: strconv.Itoa(int(u.ID))},
{Value: u.Name},
{Value: u.Fullname},
{Value: u.Email},
{Value: listroles},
2024-12-06 04:48:10 -05:00
{Value: utils.FormatUnix(u.Created)},
{Value: utils.FormatUnix(u.Updated)},
2024-12-04 08:39:08 -05:00
{Value: components.ContentHref{
Text: "edit",
Link: "/admin/users/edit/" + strconv.Itoa(int(u.ID)),
TypeClass: "outline-secondary",
}},
}
rows[i] = row
}
tmplData := templateData{
TableUsers: components.ContentTable{
ID: "table_demo",
AllTH: cols,
AllTD: rows,
},
AddButton: components.ContentHref{
Text: "Register",
Link: "/admin/users/add",
IsButton: true,
TypeClass: "outline-primary",
},
}
return c.Response.Template("admin_userlist.html", tmplData)
}
func AdminUsersAdd(c *core.Context) *core.Response {
// initiate authority
auth := new(utils.Authority)
var session = new(utils.SessionUser)
// true if session is active
hassession := session.Init(c)
if !hassession {
type emptytemplate struct{}
emptyData := emptytemplate{}
return c.Response.Template("nopermission.html", emptyData)
}
session_uid := session.GetUserID()
// check if user has role admin
is_admin, _ := auth.CheckUserRole(c, session_uid, "admin")
if !is_admin {
type emptytemplate struct{}
emptyData := emptytemplate{}
return c.Response.Template("nopermission.html", emptyData)
}
2024-12-04 08:39:08 -05:00
// check if is submit
submit := c.GetRequestParam("submit").(string)
errormessages := make([]string, 0)
var listroles []components.FormCheckboxItem
systemroles, _ := auth.GetAllRoles(c)
for _, systemrole := range systemroles {
var userrole components.FormCheckboxItem
userrole.Label = systemrole.Name
userrole.Name = "roles"
userrole.Value = systemrole.Slug
if systemrole.Slug == "authenticated" {
userrole.IsChecked = true
}
listroles = append(listroles, userrole)
}
2024-12-04 08:39:08 -05:00
name := ""
fullname := ""
email := ""
password := ""
if submit != "" {
name = c.GetRequestParam("name").(string)
fullname = c.GetRequestParam("fullname").(string)
email = c.GetRequestParam("email").(string)
password = c.GetRequestParam("password").(string)
roles := c.GetRequesForm("roles").([]string)
2024-12-04 08:39:08 -05:00
// check if email exists
var user models.User
res := c.GetGorm().Where("email = ?", c.CastToString(email)).First(&user)
if res.Error != nil && !errors.Is(res.Error, gorm.ErrRecordNotFound) {
c.GetLogger().Error(res.Error.Error())
errormessages = append(errormessages, "Error")
}
if res.Error == nil {
errormessages = append(errormessages, "Error, email already exists in the database")
}
// validation data
data := map[string]interface{}{
"name": name,
"fullname": fullname,
"email": email,
"password": password,
}
// validation rules
rules := map[string]interface{}{
"name": "required|alphaNumeric",
"fullname": "required",
"email": "required|email",
"password": "required|length:6,20",
}
// validate
v := c.GetValidator().Validate(data, rules)
if v.Failed() {
c.GetLogger().Error(v.GetErrorMessagesJson())
for _, v := range v.GetErrorMessagesMap() {
errormessages = append(errormessages, v)
}
}
if len(errormessages) == 0 {
//hash the password
passwordHashed, _ := c.GetHashing().HashPassword(c.CastToString(password))
// store the record in db
user = models.User{
Name: c.CastToString(name),
Fullname: c.CastToString(fullname),
Email: c.CastToString(email),
Password: passwordHashed,
}
res = c.GetGorm().Create(&user)
if res.Error != nil {
c.GetLogger().Error(res.Error.Error())
errormessages = append(errormessages, res.Error.Error())
} else {
// assign roles
for _, role := range roles {
auth.AssignRoleToUser(c, user.ID, role)
}
2024-12-04 08:39:08 -05:00
// fire user registered event
err := c.GetEventsManager().Fire(&core.Event{Name: events.USER_REGISTERED, Payload: map[string]interface{}{
"user": user,
}})
if err != nil {
c.GetLogger().Error(err.Error())
errormessages = append(errormessages, "Internal server error")
} else {
// redirect to list
return c.Response.Redirect("/admin/users")
}
}
}
}
// -- response template
type templateData struct {
FieldName components.FormInput
FieldFullname components.FormInput
FieldEmail components.FormInput
FieldRoles components.FormCheckbox
2024-12-04 08:39:08 -05:00
FieldPassword components.FormInput
ErrorMessages []string
SubmitButton components.FormButton
}
tmplData := templateData{
FieldName: components.FormInput{
ID: "name",
Label: "Name",
Type: "text",
Value: name,
IsRequired: true,
},
FieldFullname: components.FormInput{
ID: "fullname",
Label: "Full name",
Type: "text",
Value: fullname,
IsRequired: true,
},
FieldEmail: components.FormInput{
ID: "email",
Label: "e-mail",
Type: "text",
Value: email,
//Autocomplete: true,
IsRequired: true,
},
FieldRoles: components.FormCheckbox{
Label: "Roles",
AllCheckbox: listroles,
},
2024-12-04 08:39:08 -05:00
FieldPassword: components.FormInput{
ID: "password",
Label: "Password",
Type: "password",
Value: password,
IsRequired: true,
},
SubmitButton: components.FormButton{
ID: "submit",
Text: "Add user",
Value: "submit",
IsSubmit: true,
TypeClass: "primary",
},
ErrorMessages: errormessages,
}
return c.Response.Template("admin_useradd.html", tmplData)
}
func AdminUsersEdit(c *core.Context) *core.Response {
// check if is submit
submit := c.GetRequestParam("submit").(string)
user_id := c.GetPathParam("id")
errormessages := make([]string, 0)
// initiate authority
auth := new(utils.Authority)
var listroles []components.FormCheckboxItem
systemroles, _ := auth.GetAllRoles(c)
user_id_uint, _ := strconv.ParseUint(user_id.(string), 10, 32)
userroles, _ := auth.GetUserRoles(c, uint(user_id_uint))
for _, systemrole := range systemroles {
var userrole components.FormCheckboxItem
userrole.Label = systemrole.Name
userrole.Name = "roles"
userrole.Value = systemrole.Slug
for _, ur := range userroles {
if ur.Slug == systemrole.Slug {
userrole.IsChecked = true
break
}
}
listroles = append(listroles, userrole)
}
2024-12-04 08:39:08 -05:00
var origin_user models.User
db := c.GetGorm()
// check if existes
result_db := db.First(&origin_user, user_id)
if result_db.RowsAffected == 0 {
c.GetLogger().Error("User ID not found")
return c.Response.Redirect("/admin/users")
}
name := origin_user.Name
fullname := origin_user.Fullname
email := origin_user.Email
password := ""
user_id_string := c.GetPathParam("id").(string)
if submit != "" {
name = c.GetRequestParam("name").(string)
fullname = c.GetRequestParam("fullname").(string)
email = c.GetRequestParam("email").(string)
password = c.GetRequestParam("password").(string)
roles := c.GetRequesForm("roles").([]string)
2024-12-04 08:39:08 -05:00
key := c.GetRequestParam("key")
// check if email exists
var user models.User
res := c.GetGorm().Where("email = ? AND id != ?", c.CastToString(email), key).First(&user)
if res.Error != nil && !errors.Is(res.Error, gorm.ErrRecordNotFound) {
c.GetLogger().Error(res.Error.Error())
errormessages = append(errormessages, "Error")
}
if res.Error == nil {
errormessages = append(errormessages, "Error, email already exists to another user")
}
// validation data
data := map[string]interface{}{
"name": name,
"fullname": fullname,
"email": email,
}
// validation rules
rules := map[string]interface{}{
"name": "required|alphaNumeric",
"fullname": "required",
"email": "required|email",
}
// nee update password
if password != "" {
data["password"] = password
rules["password"] = "required|length:6,20"
}
// validate
v := c.GetValidator().Validate(data, rules)
if v.Failed() {
c.GetLogger().Error(v.GetErrorMessagesJson())
for _, v := range v.GetErrorMessagesMap() {
errormessages = append(errormessages, v)
}
}
if len(errormessages) == 0 {
//hash the password
if password != "" {
passwordHashed, _ := c.GetHashing().HashPassword(c.CastToString(password))
origin_user.Password = passwordHashed
}
// store the record in db
origin_user.Name = name
origin_user.Fullname = fullname
origin_user.Email = email
result_db = db.Save(&origin_user)
if result_db.RowsAffected == 0 {
c.GetLogger().Error("Admin user: error updating")
errormessages = append(errormessages, fmt.Sprintf("Error updating user %s:", user_id_string))
} else {
// delete roles
auth.RevokeAllUserRole(c, origin_user.ID)
// assign roles
for _, role := range roles {
auth.AssignRoleToUser(c, origin_user.ID, role)
}
2024-12-04 08:39:08 -05:00
return c.Response.Redirect("/admin/users")
}
}
}
// -- response template
type templateData struct {
FieldName components.FormInput
FieldFullname components.FormInput
FieldEmail components.FormInput
FieldRoles components.FormCheckbox
2024-12-04 08:39:08 -05:00
FieldPassword components.FormInput
FieldKey components.FormInput
ErrorMessages []string
SubmitButton components.FormButton
DeleteButton components.FormButton
}
tmplData := templateData{
FieldName: components.FormInput{
ID: "name",
Label: "Name",
Type: "text",
Value: name,
IsRequired: true,
},
FieldFullname: components.FormInput{
ID: "fullname",
Label: "Full name",
Type: "text",
Value: fullname,
IsRequired: true,
},
FieldEmail: components.FormInput{
ID: "email",
Label: "e-mail",
Type: "text",
Value: email,
//Autocomplete: true,
IsRequired: true,
},
FieldRoles: components.FormCheckbox{
Label: "Roles",
AllCheckbox: listroles,
},
2024-12-04 08:39:08 -05:00
FieldPassword: components.FormInput{
ID: "password",
Label: "Password",
Type: "password",
Hint: "Leave blank if you don't want to change it",
Value: password,
IsRequired: false,
},
FieldKey: components.FormInput{
ID: "key",
Type: "hidden",
Value: user_id_string,
},
SubmitButton: components.FormButton{
ID: "submit",
Text: "Update user",
Value: "submit",
IsSubmit: true,
TypeClass: "primary",
},
DeleteButton: components.FormButton{
ID: "submit",
Text: "Delete user",
Value: "submit",
IsSubmit: true,
TypeClass: "warning",
},
ErrorMessages: errormessages,
}
return c.Response.Template("admin_useredit.html", tmplData)
}
2024-12-06 04:48:10 -05:00
func AdminUsersDelete(c *core.Context) *core.Response {
user_id := c.GetRequestParam("key").(string)
errormessages := make([]string, 0)
warningmessages := make([]string, 0)
var origin_user models.User
db := c.GetGorm()
// check if existes
result_db := db.First(&origin_user, user_id)
if result_db.RowsAffected == 0 {
errormessages = append(errormessages, "User ID not found")
} else {
// check if is the seed user
seed := "1"
if user_id == seed {
errormessages = append(errormessages, "You can't delete the seed user")
}
}
// sample warning message
warningmessages = append(warningmessages, fmt.Sprintf("Are you sure you want to cancel the account %s?", origin_user.Name))
// -- response template
type templateData struct {
ErrorMessages []string
WarningMessages []string
FieldKey components.FormInput
ConfirmButton components.FormButton
BackButton components.ContentHref
}
tmplData := templateData{
FieldKey: components.FormInput{
ID: "key",
Type: "hidden",
Value: user_id,
},
ConfirmButton: components.FormButton{
ID: "submit",
Text: "Confirm",
Value: "submit",
IsSubmit: true,
TypeClass: "primary",
},
BackButton: components.ContentHref{
Link: "/admin/users",
Text: "Cancel",
IsButton: true,
},
ErrorMessages: errormessages,
WarningMessages: warningmessages,
}
return c.Response.Template("admin_confirmuserdel.html", tmplData)
}
func AdminUsersDelConfirm(c *core.Context) *core.Response {
user_id := c.GetRequestParam("key").(string)
var origin_user models.User
db := c.GetGorm()
// check if existes
result_db := db.First(&origin_user, user_id)
if result_db.RowsAffected != 0 {
// check if is the seed user
seed := "1"
if user_id != seed {
// initiate authority
auth := new(utils.Authority)
2024-12-06 04:48:10 -05:00
// Delete the user
// fire user delete event
err := c.GetEventsManager().Fire(&core.Event{Name: events.USER_DELETED, Payload: map[string]interface{}{
"user": origin_user,
}})
if err != nil {
c.GetLogger().Error(err.Error())
}
auth.RevokeAllUserRole(c, origin_user.ID)
2024-12-06 04:48:10 -05:00
result_db.Unscoped().Delete(&origin_user)
}
}
return c.Response.Redirect("/admin/users")
}