diff --git a/.env-dev b/.env-dev index c88f67a..ded2eab 100644 --- a/.env-dev +++ b/.env-dev @@ -8,7 +8,7 @@ App_HTTP_HOST=localhost App_HTTP_PORT=8080 App_USE_HTTPS=false App_USE_LETSENCRYPT=false -App_USE_CORESERVICES=true +App_USE_CORESERVICES=false APP_LETSENCRYPT_EMAIL=mail@example.com App_HTTPS_HOSTS=example.com, www.example.com App_REDIRECT_HTTP_TO_HTTPS=false @@ -19,8 +19,6 @@ App_KEY_FILE_PATH=tls/server.key ###### TEMPLATES ###### ####################################### TEMPLATE_ENABLE=true -APP_ENABLE=true -CDNEnable=false COOKIE_SECRET=13d6b4dff8f84a10851021ec8608f814570d562c92fe6b5ec4c9f595bcb3234b ####################################### diff --git a/.env-example b/.env-example index d0780b5..ded2eab 100644 --- a/.env-example +++ b/.env-example @@ -20,9 +20,6 @@ App_KEY_FILE_PATH=tls/server.key ####################################### TEMPLATE_ENABLE=true COOKIE_SECRET=13d6b4dff8f84a10851021ec8608f814570d562c92fe6b5ec4c9f595bcb3234b -APP_ENABLE=true -CDNEnable=false - ####################################### ###### JWT ###### diff --git a/.gitignore b/.gitignore index 90a928b..84146d5 100644 --- a/.gitignore +++ b/.gitignore @@ -7,5 +7,3 @@ tls/* !tls/.gitkeep .DS_Store storage/sqlite/* -.idea -cup diff --git a/README.md b/README.md index 4ae95df..7397849 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![goffee logo](https://git.smarteching.com/avatars/cd7cd5b690adc8e5ec6d6cdb117f1bf5a9e9353dae111bfbb394d2c3d4497537?size=200) +![gocondor logo](https://git.smarteching.com/avatars/cd7cd5b690adc8e5ec6d6cdb117f1bf5a9e9353dae111bfbb394d2c3d4497537?size=200) # Cup of Goffee ## What is Goffee? diff --git a/config/queue.go b/config/queue.go deleted file mode 100644 index 8060572..0000000 --- a/config/queue.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2025 Zeni Kim -// Use of this source code is governed by MIT-style -// license that can be found in the LICENSE file. - -package config - -import "git.smarteching.com/goffee/core" - -// Retrieve the main config for the Queue -func GetQueueConfig() core.QueueConfig { - //##################################### - //# Main configuration for Queue ##### - //##################################### - - return core.QueueConfig{ - // For enabling and disabling the queue system - // set to true to enable it, set to false to disable - EnableQueue: false, - } -} diff --git a/controllers/adminusers.go b/controllers/adminusers.go index 9ffb762..b051308 100644 --- a/controllers/adminusers.go +++ b/controllers/adminusers.go @@ -19,29 +19,6 @@ import ( 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 var users []models.User db := c.GetGorm() db.Find(&users) @@ -69,10 +46,6 @@ func AdminUsersList(c *core.Context) *core.Response { Value: "Email", ValueType: "string", }, - { - Value: "Roles", - ValueType: "string", - }, { Value: "Created", }, @@ -84,26 +57,13 @@ func AdminUsersList(c *core.Context) *core.Response { }, } - var listroles string 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 - } - row := []components.ContentTableTD{ {Value: strconv.Itoa(int(u.ID))}, {Value: u.Name}, {Value: u.Fullname}, {Value: u.Email}, - {Value: listroles}, {Value: utils.FormatUnix(u.Created)}, {Value: utils.FormatUnix(u.Updated)}, {Value: components.ContentHref{ @@ -133,44 +93,10 @@ func AdminUsersList(c *core.Context) *core.Response { 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) - } - // 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) - } + errormessages := make([]string, 0) name := "" fullname := "" @@ -183,7 +109,6 @@ func AdminUsersAdd(c *core.Context) *core.Response { fullname = c.GetRequestParam("fullname").(string) email = c.GetRequestParam("email").(string) password = c.GetRequestParam("password").(string) - roles := c.GetRequesForm("roles").([]string) // check if email exists var user models.User @@ -236,11 +161,6 @@ func AdminUsersAdd(c *core.Context) *core.Response { errormessages = append(errormessages, res.Error.Error()) } else { - // assign roles - for _, role := range roles { - auth.AssignRoleToUser(c, user.ID, role) - } - // fire user registered event err := c.GetEventsManager().Fire(&core.Event{Name: events.USER_REGISTERED, Payload: map[string]interface{}{ "user": user, @@ -260,7 +180,6 @@ func AdminUsersAdd(c *core.Context) *core.Response { FieldName components.FormInput FieldFullname components.FormInput FieldEmail components.FormInput - FieldRoles components.FormCheckbox FieldPassword components.FormInput ErrorMessages []string SubmitButton components.FormButton @@ -289,10 +208,6 @@ func AdminUsersAdd(c *core.Context) *core.Response { //Autocomplete: true, IsRequired: true, }, - FieldRoles: components.FormCheckbox{ - Label: "Roles", - AllCheckbox: listroles, - }, FieldPassword: components.FormInput{ ID: "password", Label: "Password", @@ -321,29 +236,6 @@ func AdminUsersEdit(c *core.Context) *core.Response { 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) - } var origin_user models.User @@ -367,7 +259,6 @@ func AdminUsersEdit(c *core.Context) *core.Response { fullname = c.GetRequestParam("fullname").(string) email = c.GetRequestParam("email").(string) password = c.GetRequestParam("password").(string) - roles := c.GetRequesForm("roles").([]string) key := c.GetRequestParam("key") // check if email exists @@ -425,14 +316,6 @@ func AdminUsersEdit(c *core.Context) *core.Response { 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) - } - return c.Response.Redirect("/admin/users") } } @@ -442,7 +325,6 @@ func AdminUsersEdit(c *core.Context) *core.Response { FieldName components.FormInput FieldFullname components.FormInput FieldEmail components.FormInput - FieldRoles components.FormCheckbox FieldPassword components.FormInput FieldKey components.FormInput ErrorMessages []string @@ -473,10 +355,6 @@ func AdminUsersEdit(c *core.Context) *core.Response { //Autocomplete: true, IsRequired: true, }, - FieldRoles: components.FormCheckbox{ - Label: "Roles", - AllCheckbox: listroles, - }, FieldPassword: components.FormInput{ ID: "password", Label: "Password", @@ -583,9 +461,6 @@ func AdminUsersDelConfirm(c *core.Context) *core.Response { // check if is the seed user seed := "1" if user_id != seed { - - // initiate authority - auth := new(utils.Authority) // Delete the user // fire user delete event err := c.GetEventsManager().Fire(&core.Event{Name: events.USER_DELETED, Payload: map[string]interface{}{ @@ -594,7 +469,6 @@ func AdminUsersDelConfirm(c *core.Context) *core.Response { if err != nil { c.GetLogger().Error(err.Error()) } - auth.RevokeAllUserRole(c, origin_user.ID) result_db.Unscoped().Delete(&origin_user) } } diff --git a/controllers/queuesample.go b/controllers/queuesample.go deleted file mode 100644 index d289aee..0000000 --- a/controllers/queuesample.go +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2025 Zeni Kim -// Use of this source code is governed by MIT-style -// license that can be found in the LICENSE file. - -package controllers - -import ( - "encoding/json" - "log" - "time" - - "git.smarteching.com/goffee/core" - "git.smarteching.com/goffee/cup/workers" - "github.com/hibiken/asynq" -) - -// Make samples queues -func Queuesample(c *core.Context) *core.Response { - - // Get client queue asynq - client := c.GetQueueClient() - - // Create a task with typename and payload. - payload, err := json.Marshal(workers.EmailTaskPayload{UserID: 42}) - if err != nil { - log.Fatal(err) - } - - t1 := asynq.NewTask(workers.TypeWelcomeEmail, payload) - - t2 := asynq.NewTask(workers.TypeReminderEmail, payload) - - // Process the task immediately. - info, err := client.Enqueue(t1) - if err != nil { - log.Fatal(err) - } - log.Printf(" [*] Successfully enqueued task: %+v", info) - - // Process 2 task 1 min later. - for i := 1; i < 3; i++ { - info, err = client.Enqueue(t2, asynq.ProcessIn(1*time.Minute)) - if err != nil { - log.Fatal(err) - } - log.Printf(" [*] Successfully enqueued task: %+v", info) - } - - message := "{\"message\": \"Task queued\"}" - return c.Response.Json(message) - -} diff --git a/controllers/themedemo.go b/controllers/themedemo.go index 03c55c1..bbde3c6 100644 --- a/controllers/themedemo.go +++ b/controllers/themedemo.go @@ -643,42 +643,11 @@ func Themecontent(c *core.Context) *core.Response { // first, include all compoments type templateData struct { - ContentTable components.ContentTable - ContentTabledetail components.ContentTabledetail - ContentGraph components.ContentGraph - FieldText components.FormInput - FormSelectCityM components.FormSelect - Pagination components.ContentPagination - ShouldShowPagination bool + ContentTable components.ContentTable + ContentTabledetail components.ContentTabledetail + ContentGraph components.ContentGraph } - // for select options - var allOptions []components.FormSelectOption - var option components.FormSelectOption - option.Value = "ch" - option.Caption = "China" - allOptions = append(allOptions, option) - option.Value = "ba" - option.Caption = "Buenos Aires" - allOptions = append(allOptions, option) - option.Value = "fr" - option.Caption = "France" - selectedOption := option - allOptions = append(allOptions, option) - option.Value = "kr" - option.Caption = "Korea" - allOptions = append(allOptions, option) - - // for custom attributes in form - var customAtt []components.CustomAtt - var attribute components.CustomAtt - attribute.AttName = "code" - attribute.AttValue = "five" - customAtt = append(customAtt, attribute) - attribute.AttName = "mytag" - attribute.AttValue = "My value" - customAtt = append(customAtt, attribute) - // TABLES // for th head var allTh []components.ContentTableTH @@ -701,7 +670,7 @@ func Themecontent(c *core.Context) *core.Response { var allTd [][]components.ContentTableTD //var vals []components.ContentTableTD // rows - for i := 1; i <= 28; i++ { + for i := 1; i <= 10; i++ { vals := make([]components.ContentTableTD, len(allTh)) for b := 0; b < len(allTh)-2; b++ { vals[b].Value = fmt.Sprintf("%s%d%d", "TD data: ", i, b) @@ -720,46 +689,6 @@ func Themecontent(c *core.Context) *core.Response { allTd = append(allTd, vals) } - // Pagination demo - // start config - limit := 10 - shouldShowPagination := false - pageViewTableOffset := 0 - // Get the length of AllOptions - totalrecords := len(allTd) - // get current table offset - tpage := c.RequestParamExists("tpage") - if tpage { - pageViewTableOffset, _ = strconv.Atoi(c.GetRequestParam("tpage").(string)) - } - - // start default option paginator - var pagination components.ContentPagination - pagination.PageStartRecord = pageViewTableOffset + 1 - pagination.PageEndRecord = 0 - pagination.TotalRecords = 0 - pagination.PrevLink = "" - pagination.NextLink = "" - - // check current page - // fake function to emulate a query offset - newTd := getPaginatedPageViews(allTd, limit, pageViewTableOffset) - - if len(newTd) > 0 { - pagination.TotalRecords = totalrecords - pagination.PageStartRecord = pageViewTableOffset + 1 - pagination.PageEndRecord = pageViewTableOffset + len(newTd) - shouldShowPagination = totalrecords > limit - } - - if shouldShowPagination && pageViewTableOffset != 0 { - pagination.PrevLink = fmt.Sprintf("/themecontent?tpage=%d", pageViewTableOffset-limit) - } - - if shouldShowPagination && pageViewTableOffset+limit < totalrecords { - pagination.NextLink = fmt.Sprintf("/themecontent?tpage=%d", pageViewTableOffset+limit) - } - // for td items in table detail var allTdetail []components.ContentTabledetailTD // table detail @@ -796,25 +725,10 @@ func Themecontent(c *core.Context) *core.Response { // now fill data of the components tmplData := templateData{ - FormSelectCityM: components.FormSelect{ - ID: "city", - Label: "Select city", - AllOptions: allOptions, - SelectedOption: selectedOption, - IsMultiple: true, - }, - FieldText: components.FormInput{ - ID: "text", - Label: "Name", - Type: "text", - Hint: "This is sample hint", - Placeholder: "Enter your name", - CustomAtt: customAtt, - }, ContentTable: components.ContentTable{ ID: "table_demo", AllTH: allTh, - AllTD: newTd, + AllTD: allTd, }, ContentTabledetail: components.ContentTabledetail{ ID: "table_demodetail", @@ -827,8 +741,6 @@ func Themecontent(c *core.Context) *core.Response { Labels: "Berlin|Paris|Venecia", Values: valuesgraph, }, - Pagination: pagination, - ShouldShowPagination: shouldShowPagination, } return c.Response.Template("custom_theme_contentpage.html", tmplData) @@ -841,23 +753,3 @@ func Themecontent(c *core.Context) *core.Response { } } - -func getPaginatedPageViews(values [][]components.ContentTableTD, limit int, offset int) [][]components.ContentTableTD { - - // Validate the offset and adjust if necessary - if offset < 0 { - offset = 0 // Ensure offset is not negative - } else if offset >= len(values) { - var emptytd [][]components.ContentTableTD - return emptytd - } - - // Calculate the end index (limit the slice to the size of the array) - end := offset + limit - if end > len(values) { - end = len(values) // Ensure end doesn't exceed the length of the array - } - - return values[offset:end] // Slice the array - -} diff --git a/go.mod b/go.mod index bdafa0f..e70b070 100644 --- a/go.mod +++ b/go.mod @@ -7,15 +7,14 @@ replace ( git.smarteching.com/goffee/cup/models => ./models ) -go 1.24.1 +go 1.23.1 require ( - git.smarteching.com/goffee/core v1.9.5 + git.smarteching.com/goffee/core v1.8.4 github.com/google/uuid v1.6.0 - github.com/hibiken/asynq v0.25.1 github.com/joho/godotenv v1.5.1 github.com/julienschmidt/httprouter v1.3.0 - gorm.io/gorm v1.30.0 + gorm.io/gorm v1.25.12 ) require ( @@ -25,40 +24,35 @@ require ( github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect - github.com/go-chi/chi/v5 v5.2.2 // indirect + github.com/go-chi/chi/v5 v5.1.0 // indirect github.com/go-ozzo/ozzo-validation v3.6.0+incompatible // indirect - github.com/go-sql-driver/mysql v1.9.3 // indirect - github.com/golang-jwt/jwt/v5 v5.2.3 // indirect + github.com/go-sql-driver/mysql v1.8.1 // indirect + github.com/golang-jwt/jwt/v5 v5.2.1 // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/harranali/mailing v1.2.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect - github.com/jackc/pgx/v5 v5.7.5 // indirect + github.com/jackc/pgx/v5 v5.7.1 // indirect github.com/jackc/puddle/v2 v2.2.2 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/mailgun/errors v0.4.0 // indirect - github.com/mailgun/mailgun-go/v4 v4.23.0 // indirect - github.com/mattn/go-sqlite3 v1.14.28 // indirect + github.com/mailgun/mailgun-go/v4 v4.17.3 // indirect + github.com/mattn/go-sqlite3 v1.14.24 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/redis/go-redis/v9 v9.11.0 // indirect - github.com/robfig/cron/v3 v3.0.1 // indirect + github.com/redis/go-redis/v9 v9.7.0 // indirect github.com/sendgrid/rest v2.6.9+incompatible // indirect - github.com/sendgrid/sendgrid-go v3.16.1+incompatible // indirect + github.com/sendgrid/sendgrid-go v3.16.0+incompatible // indirect github.com/sirupsen/logrus v1.9.3 // indirect - github.com/spf13/cast v1.9.2 // indirect - golang.org/x/crypto v0.40.0 // indirect - golang.org/x/image v0.29.0 // indirect - golang.org/x/net v0.42.0 // indirect - golang.org/x/sync v0.16.0 // indirect - golang.org/x/sys v0.34.0 // indirect - golang.org/x/text v0.27.0 // indirect - golang.org/x/time v0.12.0 // indirect - google.golang.org/protobuf v1.36.6 // indirect - gorm.io/driver/mysql v1.6.0 // indirect - gorm.io/driver/postgres v1.6.0 // indirect - gorm.io/driver/sqlite v1.6.0 // indirect + golang.org/x/crypto v0.28.0 // indirect + golang.org/x/image v0.21.0 // indirect + golang.org/x/net v0.30.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/text v0.19.0 // indirect + gorm.io/driver/mysql v1.5.7 // indirect + gorm.io/driver/postgres v1.5.9 // indirect + gorm.io/driver/sqlite v1.5.6 // indirect ) diff --git a/go.sum b/go.sum index 0ea3916..be301b7 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,7 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= -git.smarteching.com/goffee/core v1.9.2 h1:SpLAhsTxssPItgkBYLN3UxMH5s+q8qVtbvmRom3WKh8= -git.smarteching.com/goffee/core v1.9.2/go.mod h1:L9a+kL1RVHRHzp+DzCS1apwVLyZAvGE6B94UlyIMhIg= -git.smarteching.com/goffee/core v1.9.5 h1:rq6vI4WSUMGQNzJvhNWmtY2ycC7UszEvXpQ7uUR8sZY= -git.smarteching.com/goffee/core v1.9.5/go.mod h1:ifiBgTOR4zCMzdGsabNrEO792EHny2o149NGe3TSlms= +git.smarteching.com/goffee/core v1.8.4 h1:XB+vpe7e8muiDChRVDaJ1TG7H+/FBxDQcMfWp4zloPs= +git.smarteching.com/goffee/core v1.8.4/go.mod h1:JxXDvTQU2shKYY6c9aS3s6sFh7mEDzgmjzdc85HhBV8= git.smarteching.com/zeni/go-chart/v2 v2.1.4 h1:pF06+F6eqJLIG8uMiTVPR5TygPGMjM/FHMzTxmu5V/Q= git.smarteching.com/zeni/go-chart/v2 v2.1.4/go.mod h1:b3ueW9h3pGGXyhkormZAvilHaG4+mQti+bMNPdQBeOQ= github.com/SparkPost/gosparkpost v0.2.0 h1:yzhHQT7cE+rqzd5tANNC74j+2x3lrPznqPJrxC1yR8s= @@ -25,44 +23,36 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= -github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= -github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= -github.com/go-chi/chi/v5 v5.2.1 h1:KOIHODQj58PmL80G2Eak4WdvUzjSJSm0vG72crDCqb8= -github.com/go-chi/chi/v5 v5.2.1/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= -github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618= -github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= +github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 h1:0JZ+dUmQeA8IIVUMzysrX4/AKuQwWhV2dYQuPZdvdSQ= +github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= +github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870 h1:E2s37DuLxFhQDg5gKsWoLBOB0n+ZW8s599zru8FJ2/Y= +github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= +github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw= +github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-ozzo/ozzo-validation v3.6.0+incompatible h1:msy24VGS42fKO9K1vLz82/GeYW1cILu7Nuuj1N3BBkE= github.com/go-ozzo/ozzo-validation v3.6.0+incompatible/go.mod h1:gsEKFIVnabGBt6mXmxK0MoFy+cZoTJY6mu5Ll3LVLBU= github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= -github.com/go-sql-driver/mysql v1.9.0 h1:Y0zIbQXhQKmQgTp44Y1dp3wTXcn804QoTptLZT1vtvo= -github.com/go-sql-driver/mysql v1.9.0/go.mod h1:pDetrLJeA3oMujJuvXc8RJoasr589B6A9fwzD3QMrqw= -github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo= -github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU= +github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= +github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/gogs/chardet v0.0.0-20150115103509-2404f7772561/go.mod h1:Pcatq5tYkCW2Q6yrR2VRHlbHpZ/R4/7qyL1TCF7vl14= github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= -github.com/golang-jwt/jwt/v5 v5.2.3 h1:kkGXqQOBSDDWRhWNXTFpqGSCMyh/PLnqUvMGJPDJDs0= -github.com/golang-jwt/jwt/v5 v5.2.3/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/harranali/mailing v1.2.0 h1:ihIyJwB8hyRVcdk+v465wk1PHMrSrgJqo/kMd+gZClY= github.com/harranali/mailing v1.2.0/go.mod h1:4a5N3yG98pZKluMpmcYlTtll7bisvOfGQEMIng3VQk4= -github.com/hibiken/asynq v0.25.1 h1:phj028N0nm15n8O2ims+IvJ2gz4k2auvermngh9JhTw= -github.com/hibiken/asynq v0.25.1/go.mod h1:pazWNOLBu0FEynQRBvHA26qdIKRSmfdIfUm4HdsLmXg= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgx/v5 v5.7.2 h1:mLoDLV6sonKlvjIEsV56SkWNCnuNv531l94GaIzO+XI= -github.com/jackc/pgx/v5 v5.7.2/go.mod h1:ncY89UGWxg82EykZUwSpUKEfccBGGYq1xjrOpsbsfGQ= -github.com/jackc/pgx/v5 v5.7.5 h1:JHGfMnQY+IEtGM63d+NGMjoRpysB2JBwDr5fsngwmJs= -github.com/jackc/pgx/v5 v5.7.5/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M= +github.com/jackc/pgx/v5 v5.7.1 h1:x7SYsPBYDkHDksogeSmZZ5xzThcTgRz++I5E+ePFUcs= +github.com/jackc/pgx/v5 v5.7.1/go.mod h1:e7O26IywZZ+naJtWWos6i6fvWK+29etgITqrqHLfoZA= github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jaytaylor/html2text v0.0.0-20190408195923-01ec452cbe43/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk= @@ -77,21 +67,15 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/mailgun/errors v0.4.0 h1:6LFBvod6VIW83CMIOT9sYNp28TCX0NejFPP4dSX++i8= github.com/mailgun/errors v0.4.0/go.mod h1:xGBaaKdEdQT0/FhwvoXv4oBaqqmVZz9P1XEnvD/onc0= -github.com/mailgun/mailgun-go/v4 v4.23.0 h1:jPEMJzzin2s7lvehcfv/0UkyBu18GvcURPr2+xtZRbk= -github.com/mailgun/mailgun-go/v4 v4.23.0/go.mod h1:imTtizoFtpfZqPqGP8vltVBB6q9yWcv6llBhfFeElZU= +github.com/mailgun/mailgun-go/v4 v4.17.3 h1:WoO48/VeXgAVSzjgzyeLvF08AoPzWU2EBz79INN8rEA= +github.com/mailgun/mailgun-go/v4 v4.17.3/go.mod h1:0ood70bQR/SffQ9NxIsAY06H+HG0hrvMVApfUp9TihI= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM= github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= -github.com/mattn/go-sqlite3 v1.14.28 h1:ThEiQrnbtumT+QMknw63Befp/ce/nUPgBPMlRFEum7A= -github.com/mattn/go-sqlite3 v1.14.28/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -103,92 +87,50 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/redis/go-redis/v9 v9.7.1 h1:4LhKRCIduqXqtvCUlaq9c8bdHOkICjDMrr1+Zb3osAc= -github.com/redis/go-redis/v9 v9.7.1/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw= -github.com/redis/go-redis/v9 v9.11.0 h1:E3S08Gl/nJNn5vkxd2i78wZxWAPNZgUNTp8WIJUAiIs= -github.com/redis/go-redis/v9 v9.11.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= -github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= -github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= -github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E= +github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw= github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU= github.com/sendgrid/rest v2.6.9+incompatible h1:1EyIcsNdn9KIisLW50MKwmSRSK+ekueiEMJ7NEoxJo0= github.com/sendgrid/rest v2.6.9+incompatible/go.mod h1:kXX7q3jZtJXK5c5qK83bSGMdV6tsOE70KbHoqJls4lE= github.com/sendgrid/sendgrid-go v3.16.0+incompatible h1:i8eE6IMkiCy7vusSdacHHSBUpXyTcTXy/Rl9N9aZ/Qw= github.com/sendgrid/sendgrid-go v3.16.0+incompatible/go.mod h1:QRQt+LX/NmgVEvmdRw0VT/QgUn499+iza2FnDca9fg8= -github.com/sendgrid/sendgrid-go v3.16.1+incompatible h1:zWhTmB0Y8XCDzeWIm2/BIt1GjJohAA0p6hVEaDtHWWs= -github.com/sendgrid/sendgrid-go v3.16.1+incompatible/go.mod h1:QRQt+LX/NmgVEvmdRw0VT/QgUn499+iza2FnDca9fg8= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= -github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= -github.com/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE= -github.com/spf13/cast v1.9.2/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf/go.mod h1:RJID2RhlZKId02nZ62WenDCkgHFerpIOmW0iT7GKmXM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= -go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= -golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= -golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= -golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= -golang.org/x/image v0.25.0 h1:Y6uW6rH1y5y/LK1J8BPWZtr6yZ7hrsy6hFrXjgsc2fQ= -golang.org/x/image v0.25.0/go.mod h1:tCAmOEGthTtkalusGp1g3xa2gke8J6c2N565dTyl9Rs= -golang.org/x/image v0.29.0 h1:HcdsyR4Gsuys/Axh0rDEmlBmB68rW1U9BUdB3UVHsas= -golang.org/x/image v0.29.0/go.mod h1:RVJROnf3SLK8d26OW91j4FrIHGbsJ8QnbEocVTOWQDA= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= +golang.org/x/image v0.21.0 h1:c5qV36ajHpdj4Qi0GnE0jUc/yuo33OLFaa0d+crTD5s= +golang.org/x/image v0.21.0/go.mod h1:vUbsLavqK/W303ZroQQVKQ+Af3Yl6Uz1Ppu5J/cLz78= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= -golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= -golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= -golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= -golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= -golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= -golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= -golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= -golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= -golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= -golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= -golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= -golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= -golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= -golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= -google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= -google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= -google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo= gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM= -gorm.io/driver/mysql v1.6.0 h1:eNbLmNTpPpTOVZi8MMxCi2aaIm0ZpInbORNXDwyLGvg= -gorm.io/driver/mysql v1.6.0/go.mod h1:D/oCC2GWK3M/dqoLxnOlaNKmXz8WNTfcS9y5ovaSqKo= -gorm.io/driver/postgres v1.5.11 h1:ubBVAfbKEUld/twyKZ0IYn9rSQh448EdelLYk9Mv314= -gorm.io/driver/postgres v1.5.11/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI= -gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4= -gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo= -gorm.io/driver/sqlite v1.5.7 h1:8NvsrhP0ifM7LX9G4zPB97NwovUakUxc+2V2uuf3Z1I= -gorm.io/driver/sqlite v1.5.7/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4= -gorm.io/driver/sqlite v1.6.0 h1:WHRRrIiulaPiPFmDcod6prc4l2VGVWHz80KspNsxSfQ= -gorm.io/driver/sqlite v1.6.0/go.mod h1:AO9V1qIQddBESngQUKWL9yoH93HIeA1X6V633rBwyT8= +gorm.io/driver/postgres v1.5.9 h1:DkegyItji119OlcaLjqN11kHoUgZ/j13E0jkJZgD6A8= +gorm.io/driver/postgres v1.5.9/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI= +gorm.io/driver/sqlite v1.5.6 h1:fO/X46qn5NUEEOZtnjJRWRzZMe8nqJiQ9E+0hi+hKQE= +gorm.io/driver/sqlite v1.5.6/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4= gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8= gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ= -gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs= -gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE= diff --git a/main.go b/main.go index 5fac06e..4b9c956 100644 --- a/main.go +++ b/main.go @@ -62,9 +62,6 @@ func main() { registerGlobalHooks() registerRoutes() registerEvents() - if config.GetQueueConfig().EnableQueue == true { - registerQueues() - } if config.GetGormConfig().EnableGorm == true { RunAutoMigrations() } diff --git a/models/permission.go b/models/permission.go deleted file mode 100644 index 933b16d..0000000 --- a/models/permission.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2025 Zeni Kim -// Use of this source code is governed by MIT-style -// license that can be found in the LICENSE file. - -package models - -type Permission struct { - BaseModel - Name string - Slug string -} - -// TableName sets the table name -func (Permission) TableName() string { - return "permissions" -} diff --git a/models/role-permissions.go b/models/role-permissions.go deleted file mode 100644 index 99cf3fe..0000000 --- a/models/role-permissions.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2025 Zeni Kim -// Use of this source code is governed by MIT-style -// license that can be found in the LICENSE file. - -package models - -type RolePermission struct { - BaseModel - RoleID uint // Role id - PermissionID uint // Permission id -} - -// TableName sets the table name -func (RolePermission) TableName() string { - return "role_permissions" -} diff --git a/models/roles.go b/models/roles.go deleted file mode 100644 index decd675..0000000 --- a/models/roles.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2025 Zeni Kim -// Use of this source code is governed by MIT-style -// license that can be found in the LICENSE file. - -package models - -type Role struct { - BaseModel - Name string // The name of the role - Slug string // String based unique identifier of the role, (use hyphen seperated role name '-', instead of space) -} - -// TableName sets the table name -func (Role) TableName() string { - return "roles" -} diff --git a/models/user-roles.go b/models/user-roles.go deleted file mode 100644 index 1dfcc18..0000000 --- a/models/user-roles.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2025 Zeni Kim -// Use of this source code is governed by MIT-style -// license that can be found in the LICENSE file. - -package models - -type UserRole struct { - BaseModel - UserID uint // The user id - RoleID uint // The role id -} - -// TableName sets the table name -func (UserRole) TableName() string { - return "user_roles" -} diff --git a/register-queues.go b/register-queues.go deleted file mode 100644 index a1cf059..0000000 --- a/register-queues.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2025 Zeni Kim -// Use of this source code is governed by MIT-style -// license that can be found in the LICENSE file. - -package main - -import ( - "git.smarteching.com/goffee/core" - "git.smarteching.com/goffee/cup/workers" -) - -// Register queues -func registerQueues() { - - var queque = new(core.Queuemux) - queque.QueueInit() - //######################################## - //# quques registration ##### - //######################################## - - // register your queues here ... - - queque.AddWork(workers.TypeWelcomeEmail, workers.HandleWelcomeEmailTask) - queque.AddWork(workers.TypeReminderEmail, workers.HandleReminderEmailTask) - - //######################################## - // Start queue server, DO NOT TOUCH - //######################################## - go queque.RunQueueserver() -} diff --git a/routes.go b/routes.go index f8d7fec..785c59e 100644 --- a/routes.go +++ b/routes.go @@ -26,7 +26,6 @@ func registerRoutes() { controller.Get("/themecontent", controllers.Themecontent) controller.Get("/themepanel", controllers.Themedemo) controller.Get("/themeelements", controllers.ThemeElements) - controller.Get("/queuesample", controllers.Queuesample) // Uncomment the lines below to enable authentication controller.Post("/signup", controllers.Signup) diff --git a/run-auto-migrations.go b/run-auto-migrations.go index 996ae15..8410637 100644 --- a/run-auto-migrations.go +++ b/run-auto-migrations.go @@ -6,12 +6,8 @@ package main import ( - "errors" - "git.smarteching.com/goffee/core" "git.smarteching.com/goffee/cup/models" - "git.smarteching.com/goffee/cup/utils" - "gorm.io/gorm" ) func RunAutoMigrations() { @@ -21,18 +17,5 @@ func RunAutoMigrations() { //############################## // Add auto migrations for your models here... - db.AutoMigrate(&models.UserRole{}) - db.AutoMigrate(&models.Role{}) - db.AutoMigrate(&models.RolePermission{}) - db.AutoMigrate(&models.Permission{}) - - // End your auto migrations - - // Create seed data data, DO NOT TOUCH - if err := db.AutoMigrate(&models.User{}); err == nil && db.Migrator().HasTable(&models.User{}) { - if err := db.First(&models.User{}).Error; errors.Is(err, gorm.ErrRecordNotFound) { - utils.CreateSeedData() - } - } - + db.AutoMigrate(&models.User{}) } diff --git a/storage/app/img/goffee.png b/storage/app/img/goffee.png deleted file mode 100644 index d0491fc..0000000 Binary files a/storage/app/img/goffee.png and /dev/null differ diff --git a/storage/app/index.html b/storage/app/index.html deleted file mode 100644 index 326fcb0..0000000 --- a/storage/app/index.html +++ /dev/null @@ -1,9 +0,0 @@ - - - - Title! - - -

This is an example conten.

- - diff --git a/storage/templates/admin_useradd.html b/storage/templates/admin_useradd.html index bc5d780..ccdb363 100644 --- a/storage/templates/admin_useradd.html +++ b/storage/templates/admin_useradd.html @@ -15,8 +15,7 @@
{{template "form_input" .FieldName}} {{template "form_input" .FieldFullname}} - {{template "form_input" .FieldEmail}} - {{template "form_checkbox" .FieldRoles}} + {{template "form_input" .FieldEmail}} {{template "form_input" .FieldPassword}}
{{template "form_button" .SubmitButton}} diff --git a/storage/templates/admin_useredit.html b/storage/templates/admin_useredit.html index 3c49e08..36ebfdf 100644 --- a/storage/templates/admin_useredit.html +++ b/storage/templates/admin_useredit.html @@ -15,8 +15,7 @@ {{template "form_input" .FieldName}} {{template "form_input" .FieldFullname}} - {{template "form_input" .FieldEmail}} - {{template "form_checkbox" .FieldRoles}} + {{template "form_input" .FieldEmail}} {{template "form_input" .FieldPassword}} {{template "form_input" .FieldKey}} {{template "form_button" .SubmitButton}} diff --git a/storage/templates/custom_theme_contentpage.html b/storage/templates/custom_theme_contentpage.html index 422c253..67b35f9 100644 --- a/storage/templates/custom_theme_contentpage.html +++ b/storage/templates/custom_theme_contentpage.html @@ -7,17 +7,11 @@ Content demos
{{template "content_table" .ContentTable}} - {{if .ShouldShowPagination}} - {{template "content_pagination" .Pagination}} - {{end}}

Pie chart

{{template "content_graph" .ContentGraph}} -
- {{template "form_input" .FieldText}} - {{template "form_select" .FormSelectCityM}}
{{template "content_tabledetail" .ContentTabledetail}} diff --git a/storage/templates/nopermission.html b/storage/templates/nopermission.html deleted file mode 100644 index bec8f39..0000000 --- a/storage/templates/nopermission.html +++ /dev/null @@ -1,12 +0,0 @@ - - - {{template "page_head" "No permission"}} - -
-
- You do not have permission to visit this page. -
-
- {{template "page_footer"}} - - \ No newline at end of file diff --git a/utils/authority.go b/utils/authority.go deleted file mode 100644 index 823f845..0000000 --- a/utils/authority.go +++ /dev/null @@ -1,436 +0,0 @@ -// Copyright (c) 2025 Zeni Kim -// Use of this source code is governed by MIT-style -// license that can be found in the LICENSE file. - -package utils - -import ( - "errors" - "fmt" - - "git.smarteching.com/goffee/core" - "git.smarteching.com/goffee/cup/models" - "gorm.io/gorm" -) - -type Authority struct{} - -var auth *Authority - -var ( - ErrPermissionInUse = errors.New("cannot delete assigned permission") - ErrPermissionNotFound = errors.New("permission not found") - ErrRoleInUse = errors.New("cannot delete assigned role") - ErrRoleNotFound = errors.New("role not found") -) - -// Add a new role to the database -func (a *Authority) CreateRole(c *core.Context, r models.Role) error { - roleSlug := r.Slug - var dbRole models.Role - res := c.GetGorm().Where("slug = ?", roleSlug).First(&dbRole) - if res.Error != nil { - if errors.Is(res.Error, gorm.ErrRecordNotFound) { - // create - createRes := c.GetGorm().Create(&r) - if createRes.Error != nil { - return createRes.Error - } - return nil - } - return res.Error - } - - return errors.New(fmt.Sprintf("role '%v' already exists", roleSlug)) -} - -// Add a new permission to the database -func (a *Authority) CreatePermission(c *core.Context, p models.Permission) error { - permSlug := p.Slug - var dbPerm models.Permission - res := c.GetGorm().Where("slug = ?", permSlug).First(&dbPerm) - if res.Error != nil { - if errors.Is(res.Error, gorm.ErrRecordNotFound) { - // create - createRes := c.GetGorm().Create(&p) - if createRes.Error != nil { - return createRes.Error - } - return nil - } - return res.Error - } - - return errors.New(fmt.Sprintf("permission '%v' already exists", permSlug)) -} - -// Assigns a group of permissions to a given role -func (a *Authority) AssignPermissionsToRole(c *core.Context, roleSlug string, permSlugs []string) error { - var role models.Role - rRes := c.GetGorm().Where("slug = ?", roleSlug).First(&role) - if rRes.Error != nil { - if errors.Is(rRes.Error, gorm.ErrRecordNotFound) { - return ErrRoleNotFound - } - return rRes.Error - } - var perms []models.Permission - for _, permSlug := range permSlugs { - var perm models.Permission - pRes := c.GetGorm().Where("slug = ?", permSlug).First(&perm) - if pRes.Error != nil { - if errors.Is(pRes.Error, gorm.ErrRecordNotFound) { - return ErrPermissionNotFound - } - return pRes.Error - } - perms = append(perms, perm) - } - tx := c.GetGorm().Begin() - for _, perm := range perms { - var rolePerm models.RolePermission - res := c.GetGorm().Where("role_id = ?", role.ID).Where("permission_id =?", perm.ID).First(&rolePerm) - if res.Error != nil && errors.Is(res.Error, gorm.ErrRecordNotFound) { - cRes := tx.Create(&models.RolePermission{RoleID: role.ID, PermissionID: perm.ID}) - if cRes.Error != nil { - tx.Rollback() - return cRes.Error - } - } - if res.Error != nil && !errors.Is(res.Error, gorm.ErrRecordNotFound) { - tx.Rollback() - return res.Error - } - if rolePerm != (models.RolePermission{}) { - tx.Rollback() - return errors.New(fmt.Sprintf("permission '%v' is aleady assigned to the role '%v'", perm.Name, role.Name)) - } - rolePerm = models.RolePermission{} - } - return tx.Commit().Error -} - -// Assigns a role to a given user -func (a *Authority) AssignRoleToUser(c *core.Context, userID uint, roleSlug string) error { - var role models.Role - res := c.GetGorm().Where("slug = ?", roleSlug).First(&role) - if res.Error != nil { - if errors.Is(res.Error, gorm.ErrRecordNotFound) { - return ErrRoleNotFound - } - return res.Error - } - var userRole models.UserRole - res = c.GetGorm().Where("user_id = ?", userID).Where("role_id = ?", role.ID).First(&userRole) - if res.Error != nil && errors.Is(res.Error, gorm.ErrRecordNotFound) { - c.GetGorm().Create(&models.UserRole{UserID: userID, RoleID: role.ID}) - return nil - } - if res.Error != nil && !errors.Is(res.Error, gorm.ErrRecordNotFound) { - return res.Error - } - - return errors.New(fmt.Sprintf("this role '%v' is aleady assigned to the user", roleSlug)) -} - -// Checks if a role is assigned to a user -func (a *Authority) CheckUserRole(c *core.Context, userID uint, roleSlug string) (bool, error) { - // find the role - var role models.Role - res := c.GetGorm().Where("slug = ?", roleSlug).First(&role) - if res.Error != nil { - if errors.Is(res.Error, gorm.ErrRecordNotFound) { - return false, ErrRoleNotFound - } - return false, res.Error - } - - // check if the role is a assigned - var userRole models.UserRole - res = c.GetGorm().Where("user_id = ?", userID).Where("role_id = ?", role.ID).First(&userRole) - if res.Error != nil { - if errors.Is(res.Error, gorm.ErrRecordNotFound) { - return false, nil - } - return false, res.Error - } - - return true, nil -} - -// Checks if a permission is assigned to a user -func (a *Authority) CheckUserPermission(c *core.Context, userID uint, permSlug string) (bool, error) { - // the user role - var userRoles []models.UserRole - res := c.GetGorm().Where("user_id = ?", userID).Find(&userRoles) - if res.Error != nil { - if errors.Is(res.Error, gorm.ErrRecordNotFound) { - return false, nil - } - return false, res.Error - } - - //prepare an array of role ids - var roleIDs []interface{} - for _, r := range userRoles { - roleIDs = append(roleIDs, r.RoleID) - } - - // find the permission - var perm models.Permission - res = c.GetGorm().Where("slug = ?", permSlug).First(&perm) - if res.Error != nil { - if errors.Is(res.Error, gorm.ErrRecordNotFound) { - return false, ErrPermissionNotFound - } - return false, res.Error - } - - // find the role permission - var rolePermission models.RolePermission - res = c.GetGorm().Where("role_id IN (?)", roleIDs).Where("permission_id = ?", perm.ID).First(&rolePermission) - if res.Error != nil && errors.Is(res.Error, gorm.ErrRecordNotFound) { - return false, nil - } - if res.Error != nil && !errors.Is(res.Error, gorm.ErrRecordNotFound) { - return false, res.Error - } - - return true, nil -} - -// Checks if a permission is assigned to a role -func (a *Authority) CheckRolePermission(c *core.Context, roleSlug string, permSlug string) (bool, error) { - // find the role - var role models.Role - res := c.GetGorm().Where("slug = ?", roleSlug).First(&role) - if res.Error != nil { - if errors.Is(res.Error, gorm.ErrRecordNotFound) { - return false, ErrRoleNotFound - } - return false, res.Error - } - - // find the permission - var perm models.Permission - res = c.GetGorm().Where("slug = ?", permSlug).First(&perm) - if res.Error != nil { - if errors.Is(res.Error, gorm.ErrRecordNotFound) { - return false, ErrPermissionNotFound - } - return false, res.Error - } - - // find the rolePermission - var rolePermission models.RolePermission - res = c.GetGorm().Where("role_id = ?", role.ID).Where("permission_id = ?", perm.ID).First(&rolePermission) - if res.Error != nil { - if errors.Is(res.Error, gorm.ErrRecordNotFound) { - return false, nil - } - return false, res.Error - } - - return true, nil -} - -// Revokes a roles's permission -func (a *Authority) RevokeRolePermission(c *core.Context, roleSlug string, permSlug string) error { - // find the role - var role models.Role - res := c.GetGorm().Where("slug = ?", roleSlug).First(&role) - if res.Error != nil { - if errors.Is(res.Error, gorm.ErrRecordNotFound) { - return ErrRoleNotFound - } - return res.Error - } - - // find the permission - var perm models.Permission - res = c.GetGorm().Where("slug = ?", permSlug).First(&perm) - if res.Error != nil { - if errors.Is(res.Error, gorm.ErrRecordNotFound) { - return ErrPermissionNotFound - } - return res.Error - } - - // revoke the permission - rRes := c.GetGorm().Where("role_id = ?", role.ID).Where("permission_id = ?", perm.ID).Delete(models.RolePermission{}) - if rRes.Error != nil { - return rRes.Error - } - - return nil -} - -// Revokes a user's role -func (a *Authority) RevokeUserRole(c *core.Context, userID uint, roleSlug string) error { - // find the role - var role models.Role - res := c.GetGorm().Where("slug = ?", roleSlug).First(&role) - if res.Error != nil { - if errors.Is(res.Error, gorm.ErrRecordNotFound) { - return ErrRoleNotFound - } - return res.Error - } - - // revoke the role - rRes := c.GetGorm().Where("user_id = ?", userID).Where("role_id = ?", role.ID).Delete(models.UserRole{}) - if rRes.Error != nil { - return rRes.Error - } - - return nil -} - -// Revokes all user's role -func (a *Authority) RevokeAllUserRole(c *core.Context, userID uint) error { - // revoke the role - rRes := c.GetGorm().Where("user_id = ?", userID).Delete(models.UserRole{}) - if rRes.Error != nil { - return rRes.Error - } - - return nil -} - -// Returns all stored roles -func (a *Authority) GetAllRoles(c *core.Context) ([]models.Role, error) { - var roles []models.Role - res := c.GetGorm().Find(&roles) - if res.Error != nil { - return nil, res.Error - } - - return roles, nil -} - -// Returns all user assigned roles -func (a *Authority) GetUserRoles(c *core.Context, userID uint) ([]models.Role, error) { - var userRoles []models.UserRole - res := c.GetGorm().Where("user_id = ?", userID).Find(&userRoles) - if res.Error != nil { - return nil, res.Error - } - - var roleIDs []interface{} - for _, r := range userRoles { - roleIDs = append(roleIDs, r.RoleID) - } - - var roles []models.Role - res = c.GetGorm().Where("id IN (?)", roleIDs).Find(&roles) - if res.Error != nil { - return nil, res.Error - } - - return roles, nil -} - -// Returns all role assigned permissions -func (a *Authority) GetRolePermissions(c *core.Context, roleSlug string) ([]models.Permission, error) { - var role models.Role - res := c.GetGorm().Where("slug = ?", roleSlug).Find(&role) - if res.Error != nil { - return nil, res.Error - } - - var rolePerms []models.RolePermission - res = c.GetGorm().Where("role_id = ?", role.ID).Find(&rolePerms) - if res.Error != nil { - return nil, res.Error - } - var permIDs []interface{} - for _, rolePerm := range rolePerms { - permIDs = append(permIDs, rolePerm.PermissionID) - } - - var perms []models.Permission - res = c.GetGorm().Where("id IN (?)", permIDs).Find(&perms) - if res.Error != nil { - return nil, res.Error - } - - return perms, nil -} - -// Returns all stored permissions -func (a *Authority) GetAllPermissions(c *core.Context) ([]models.Permission, error) { - var perms []models.Permission - res := c.GetGorm().Find(&perms) - if res.Error != nil { - return nil, res.Error - } - - return perms, nil -} - -// Deletes a given role even if it's has assigned permissions -func (a *Authority) DeleteRole(c *core.Context, roleSlug string) error { - // find the role - var role models.Role - res := c.GetGorm().Where("slug = ?", roleSlug).First(&role) - if res.Error != nil { - return res.Error - } - - // check if the role is assigned to a user - var ca int64 - res = c.GetGorm().Model(models.UserRole{}).Where("role_id = ?", role.ID).Count(&ca) - if res.Error != nil { - return res.Error - } - - if ca != 0 { - // role is assigned - return ErrRoleInUse - } - tx := c.GetGorm().Begin() - // revoke the assignment of permissions before deleting the role - dRes := tx.Where("role_id = ?", role.ID).Delete(models.RolePermission{}) - if dRes.Error != nil { - tx.Rollback() - return dRes.Error - } - - // delete the role - dRes = c.GetGorm().Where("slug = ?", roleSlug).Delete(models.Role{}) - if dRes.Error != nil { - tx.Rollback() - return dRes.Error - } - - return tx.Commit().Error -} - -// Deletes a given permission -func (a *Authority) DeletePermission(c *core.Context, permSlug string) error { - // find the permission - var perm models.Permission - res := c.GetGorm().Where("slug = ?", permSlug).First(&perm) - if res.Error != nil { - return res.Error - } - - // check if the permission is assigned to a role - var rolePermission models.RolePermission - res = c.GetGorm().Where("permission_id = ?", perm.ID).First(&rolePermission) - if res.Error != nil && !errors.Is(res.Error, gorm.ErrRecordNotFound) { - return res.Error - } - - if res.Error == nil { - return ErrPermissionInUse - } - - // delete the permission - dRes := c.GetGorm().Where("slug = ?", permSlug).Delete(models.Permission{}) - if dRes.Error != nil { - return dRes.Error - } - - return nil -} diff --git a/utils/helpers.go b/utils/helpers.go index 8ca7dd8..36ac76b 100644 --- a/utils/helpers.go +++ b/utils/helpers.go @@ -8,69 +8,9 @@ package utils import ( "crypto/md5" "fmt" - "log" "time" - - "git.smarteching.com/goffee/core" - "git.smarteching.com/goffee/cup/models" ) -func CreateSeedData() { - - db := core.ResolveGorm() - var hashing = new(core.Hashing) - var role models.Role - - // seed user - password := "goffee" - name := "admin" - fullname := "Goffee administrator" - email := "change@me.com" - passwordHashed, _ := hashing.HashPassword(password) - - user := models.User{ - Name: name, - Fullname: fullname, - Email: email, - Password: passwordHashed, - } - result := db.Create(&user) - if result.Error != nil { - log.Fatal("Can't create seed user in database") - } - // seed roles - roles := []models.Role{ - {Name: "Administrator", Slug: "admin"}, - {Name: "Authenticated", Slug: "authenticated"}, - } - - for _, role := range roles { - result = db.Create(&role) - if result.Error != nil { - log.Fatal("Can't create seed role in database") - } - } - - // seed permission - permission := models.Permission{Name: "Users administration", Slug: "admin-users"} - result = db.Create(&permission) - if result.Error != nil { - log.Fatal("Can't create seed permission in database") - } - result = db.Where("slug = ?", "admin").First(&role) - if result.Error != nil { - log.Fatal("Can't find user admin in database") - } - result = db.Create(&models.RolePermission{RoleID: role.ID, PermissionID: permission.ID}) - if result.Error != nil { - log.Fatal("Can't register permission role in database") - } - result = db.Create(&models.UserRole{UserID: user.ID, RoleID: role.ID}) - if result.Error != nil { - log.Fatal("Can't assign role administrator to user in database") - } -} - // generate a hashed string to be used as key for caching auth jwt token func CreateAuthTokenHashedCacheKey(userID uint, userAgent string) string { cacheKey := fmt.Sprintf("userid:_%v_useragent:_%v_jwt_token", userID, userAgent) diff --git a/workers/workers.go b/workers/workers.go deleted file mode 100644 index e7a9cad..0000000 --- a/workers/workers.go +++ /dev/null @@ -1,39 +0,0 @@ -package workers - -import ( - "context" - "encoding/json" - "log" - - "github.com/hibiken/asynq" -) - -// A list of task types. -const ( - TypeWelcomeEmail = "email:welcome" - TypeReminderEmail = "email:reminder" -) - -// Task payload for any email related tasks. -type EmailTaskPayload struct { - // ID for the email recipient. - UserID int -} - -func HandleWelcomeEmailTask(ctx context.Context, t *asynq.Task) error { - var p EmailTaskPayload - if err := json.Unmarshal(t.Payload(), &p); err != nil { - return err - } - log.Printf(" [*] Send Welcome Email to User %d", p.UserID) - return nil -} - -func HandleReminderEmailTask(ctx context.Context, t *asynq.Task) error { - var p EmailTaskPayload - if err := json.Unmarshal(t.Payload(), &p); err != nil { - return err - } - log.Printf(" [*] Send Reminder Email to User %d", p.UserID) - return nil -}