Better caldav support (#73)
This commit is contained in:
@ -86,6 +86,11 @@ func (lt *LabelTask) Create(a web.Auth) (err error) {
|
||||
|
||||
// Insert it
|
||||
_, err = x.Insert(lt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = updateListByTaskID(lt.TaskID)
|
||||
return
|
||||
}
|
||||
|
||||
@ -272,6 +277,8 @@ func (t *ListTask) updateTaskLabels(creator web.Auth, labels []*Label) (err erro
|
||||
}
|
||||
t.Labels = append(t.Labels, label)
|
||||
}
|
||||
|
||||
err = updateListLastUpdated(&List{ID: t.ListID})
|
||||
return
|
||||
}
|
||||
|
||||
@ -299,7 +306,7 @@ type LabelTaskBulk struct {
|
||||
// @Failure 500 {object} models.Message "Internal error"
|
||||
// @Router /tasks/{taskID}/labels/bulk [post]
|
||||
func (ltb *LabelTaskBulk) Create(a web.Auth) (err error) {
|
||||
task, err := GetListTaskByID(ltb.TaskID)
|
||||
task, err := GetTaskByID(ltb.TaskID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ func (ltb *LabelTaskBulk) CanCreate(a web.Auth) (bool, error) {
|
||||
// always the same check for either deleting or adding a label to a task
|
||||
func canDoLabelTask(taskID int64, a web.Auth) (bool, error) {
|
||||
// A user can add a label to a task if he can write to the task
|
||||
task, err := getTaskByIDSimple(taskID)
|
||||
task, err := GetTaskByIDSimple(taskID)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
@ -166,6 +166,8 @@ func TestLabelTask_Create(t *testing.T) {
|
||||
a: &User{ID: 1},
|
||||
},
|
||||
wantForbidden: true,
|
||||
wantErr: true,
|
||||
errType: IsErrListTaskDoesNotExist,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
|
@ -71,6 +71,21 @@ func (l *List) Update() (err error) {
|
||||
return CreateOrUpdateList(l)
|
||||
}
|
||||
|
||||
func updateListLastUpdated(list *List) error {
|
||||
_, err := x.ID(list.ID).Cols("updated").Update(list)
|
||||
return err
|
||||
}
|
||||
|
||||
func updateListByTaskID(taskID int64) (err error) {
|
||||
// need to get the task to update the list last updated timestamp
|
||||
task, err := GetTaskByIDSimple(taskID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return updateListLastUpdated(&List{ID: task.ListID})
|
||||
}
|
||||
|
||||
// Create implements the create method of CRUDable
|
||||
// @Summary Creates a new list
|
||||
// @Description Creates a new list in a given namespace. The user needs write-access to the namespace.
|
||||
|
@ -125,6 +125,8 @@ func (t *ListTask) updateTaskAssignees(assignees []*User) (err error) {
|
||||
}
|
||||
|
||||
t.setTaskAssignees(assignees)
|
||||
|
||||
err = updateListLastUpdated(&List{ID: t.ListID})
|
||||
return
|
||||
}
|
||||
|
||||
@ -152,6 +154,11 @@ func (t *ListTask) setTaskAssignees(assignees []*User) {
|
||||
// @Router /tasks/{taskID}/assignees/{userID} [delete]
|
||||
func (la *ListTaskAssginee) Delete() (err error) {
|
||||
_, err = x.Delete(&ListTaskAssginee{TaskID: la.TaskID, UserID: la.UserID})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = updateListByTaskID(la.TaskID)
|
||||
return
|
||||
}
|
||||
|
||||
@ -198,7 +205,11 @@ func (t *ListTask) addNewAssigneeByID(newAssigneeID int64, list *List) (err erro
|
||||
TaskID: t.ID,
|
||||
UserID: newAssigneeID,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = updateListLastUpdated(&List{ID: t.ListID})
|
||||
return
|
||||
}
|
||||
|
||||
@ -249,7 +260,7 @@ type BulkAssignees struct {
|
||||
// @Failure 500 {object} models.Message "Internal error"
|
||||
// @Router /tasks/{taskID}/assignees/bulk [post]
|
||||
func (ba *BulkAssignees) Create(a web.Auth) (err error) {
|
||||
task, err := GetListTaskByID(ba.TaskID) // We need to use the full method here because we need all current assignees.
|
||||
task, err := GetTaskByID(ba.TaskID) // We need to use the full method here because we need all current assignees.
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -31,6 +31,8 @@ type ListTask struct {
|
||||
Description string `xorm:"varchar(250)" json:"description" valid:"runelength(0|250)" maxLength:"250"`
|
||||
// Whether a task is done or not.
|
||||
Done bool `xorm:"INDEX null" json:"done"`
|
||||
// The unix timestamp when a task was marked as done.
|
||||
DoneAtUnix int64 `xorm:"INDEX null" json:"doneAt"`
|
||||
// A unix timestamp when the task is due.
|
||||
DueDateUnix int64 `xorm:"int(11) INDEX null" json:"dueDate"`
|
||||
// An array of unix timestamps when the user wants to be reminded of the task.
|
||||
@ -55,6 +57,9 @@ type ListTask struct {
|
||||
// The task color in hex
|
||||
HexColor string `xorm:"varchar(6) null" json:"hexColor" valid:"runelength(0|6)" maxLength:"6"`
|
||||
|
||||
// The UID is currently not used for anything other than caldav, which is why we don't expose it over json
|
||||
UID string `xorm:"varchar(250) null" json:"-"`
|
||||
|
||||
Sorting string `xorm:"-" json:"-" query:"sort"` // Parameter to sort by
|
||||
StartDateSortUnix int64 `xorm:"-" json:"-" query:"startdate"`
|
||||
EndDateSortUnix int64 `xorm:"-" json:"-" query:"enddate"`
|
||||
@ -88,96 +93,36 @@ func GetTasksByListID(listID int64) (tasks []*ListTask, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// No need to iterate over users and stuff if the list doesn't has tasks
|
||||
if len(taskMap) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// Get all users & task ids and put them into the array
|
||||
var userIDs []int64
|
||||
var taskIDs []int64
|
||||
for _, i := range taskMap {
|
||||
taskIDs = append(taskIDs, i.ID)
|
||||
userIDs = append(userIDs, i.CreatedByID)
|
||||
}
|
||||
|
||||
// Get all assignees
|
||||
taskAssignees, err := getRawTaskAssigneesForTasks(taskIDs)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// Put the assignees in the task map
|
||||
for _, a := range taskAssignees {
|
||||
if a != nil {
|
||||
taskMap[a.TaskID].Assignees = append(taskMap[a.TaskID].Assignees, &a.User)
|
||||
}
|
||||
}
|
||||
|
||||
// Get all labels for the tasks
|
||||
labels, err := getLabelsByTaskIDs(&LabelByTaskIDsOptions{TaskIDs: taskIDs})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, l := range labels {
|
||||
if l != nil {
|
||||
taskMap[l.TaskID].Labels = append(taskMap[l.TaskID].Labels, &l.Label)
|
||||
}
|
||||
}
|
||||
|
||||
users := make(map[int64]*User)
|
||||
err = x.In("id", userIDs).Find(&users)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Add all user objects to the appropriate tasks
|
||||
for _, task := range taskMap {
|
||||
|
||||
// Make created by user objects
|
||||
taskMap[task.ID].CreatedBy = *users[task.CreatedByID]
|
||||
|
||||
// Reorder all subtasks
|
||||
if task.ParentTaskID != 0 {
|
||||
taskMap[task.ParentTaskID].Subtasks = append(taskMap[task.ParentTaskID].Subtasks, task)
|
||||
delete(taskMap, task.ID)
|
||||
}
|
||||
}
|
||||
|
||||
// make a complete slice from the map
|
||||
tasks = []*ListTask{}
|
||||
for _, t := range taskMap {
|
||||
tasks = append(tasks, t)
|
||||
}
|
||||
|
||||
// Sort the output. In Go, contents on a map are put on that map in no particular order (saved on heap).
|
||||
// Because of this, tasks are not sorted anymore in the output, this leads to confiusion.
|
||||
// To avoid all this, we need to sort the slice afterwards
|
||||
sort.Slice(tasks, func(i, j int) bool {
|
||||
return tasks[i].ID < tasks[j].ID
|
||||
})
|
||||
|
||||
tasks, err = addMoreInfoToTasks(taskMap)
|
||||
return
|
||||
}
|
||||
|
||||
func getTaskByIDSimple(taskID int64) (task ListTask, err error) {
|
||||
// GetTaskByIDSimple returns a raw task without extra data by the task ID
|
||||
func GetTaskByIDSimple(taskID int64) (task ListTask, err error) {
|
||||
if taskID < 1 {
|
||||
return ListTask{}, ErrListTaskDoesNotExist{taskID}
|
||||
}
|
||||
|
||||
exists, err := x.ID(taskID).Get(&task)
|
||||
return GetTaskSimple(&ListTask{ID: taskID})
|
||||
}
|
||||
|
||||
// GetTaskSimple returns a raw task without extra data
|
||||
func GetTaskSimple(t *ListTask) (task ListTask, err error) {
|
||||
task = *t
|
||||
exists, err := x.Get(&task)
|
||||
if err != nil {
|
||||
return ListTask{}, err
|
||||
}
|
||||
|
||||
if !exists {
|
||||
return ListTask{}, ErrListTaskDoesNotExist{taskID}
|
||||
return ListTask{}, ErrListTaskDoesNotExist{t.ID}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetListTaskByID returns all tasks a list has
|
||||
func GetListTaskByID(listTaskID int64) (listTask ListTask, err error) {
|
||||
listTask, err = getTaskByIDSimple(listTaskID)
|
||||
// GetTaskByID returns all tasks a list has
|
||||
func GetTaskByID(listTaskID int64) (listTask ListTask, err error) {
|
||||
listTask, err = GetTaskByIDSimple(listTaskID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -221,37 +166,101 @@ func (bt *BulkTask) GetTasksByIDs() (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
err = x.In("id", bt.IDs).Find(&bt.Tasks)
|
||||
taskMap := make(map[int64]*ListTask, len(bt.Tasks))
|
||||
err = x.In("id", bt.IDs).Find(&taskMap)
|
||||
if err != nil {
|
||||
return err
|
||||
return
|
||||
}
|
||||
|
||||
// We use a map, to avoid looping over two slices at once
|
||||
var usermapids = make(map[int64]bool) // Bool ist just something, doesn't acutually matter
|
||||
for _, list := range bt.Tasks {
|
||||
usermapids[list.CreatedByID] = true
|
||||
}
|
||||
bt.Tasks, err = addMoreInfoToTasks(taskMap)
|
||||
return
|
||||
}
|
||||
|
||||
// Make a slice from the map
|
||||
var userids []int64
|
||||
for uid := range usermapids {
|
||||
userids = append(userids, uid)
|
||||
}
|
||||
|
||||
// Get all users for the tasks
|
||||
var users []*User
|
||||
err = x.In("id", userids).Find(&users)
|
||||
// GetTasksByUIDs gets all tasks from a bunch of uids
|
||||
func GetTasksByUIDs(uids []string) (tasks []*ListTask, err error) {
|
||||
taskMap := make(map[int64]*ListTask)
|
||||
err = x.In("uid", uids).Find(&taskMap)
|
||||
if err != nil {
|
||||
return err
|
||||
return
|
||||
}
|
||||
|
||||
for in, task := range bt.Tasks {
|
||||
for _, u := range users {
|
||||
if task.CreatedByID == u.ID {
|
||||
bt.Tasks[in].CreatedBy = *u
|
||||
}
|
||||
tasks, err = addMoreInfoToTasks(taskMap)
|
||||
return
|
||||
}
|
||||
|
||||
// This function takes a map with pointers and returns a slice with pointers to tasks
|
||||
// It adds more stuff like assignees/labels/etc to a bunch of tasks
|
||||
func addMoreInfoToTasks(taskMap map[int64]*ListTask) (tasks []*ListTask, err error) {
|
||||
|
||||
// No need to iterate over users and stuff if the list doesn't has tasks
|
||||
if len(taskMap) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// Get all users & task ids and put them into the array
|
||||
var userIDs []int64
|
||||
var taskIDs []int64
|
||||
for _, i := range taskMap {
|
||||
taskIDs = append(taskIDs, i.ID)
|
||||
userIDs = append(userIDs, i.CreatedByID)
|
||||
}
|
||||
|
||||
// Get all assignees
|
||||
taskAssignees, err := getRawTaskAssigneesForTasks(taskIDs)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// Put the assignees in the task map
|
||||
for _, a := range taskAssignees {
|
||||
if a != nil {
|
||||
taskMap[a.TaskID].Assignees = append(taskMap[a.TaskID].Assignees, &a.User)
|
||||
}
|
||||
}
|
||||
|
||||
// Get all labels for all the tasks
|
||||
labels, err := getLabelsByTaskIDs(&LabelByTaskIDsOptions{TaskIDs: taskIDs})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, l := range labels {
|
||||
if l != nil {
|
||||
taskMap[l.TaskID].Labels = append(taskMap[l.TaskID].Labels, &l.Label)
|
||||
}
|
||||
}
|
||||
|
||||
// Get all users of a task
|
||||
// aka the ones who created a task
|
||||
users := make(map[int64]*User)
|
||||
err = x.In("id", userIDs).Find(&users)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Add all user objects to the appropriate tasks
|
||||
for _, task := range taskMap {
|
||||
|
||||
// Make created by user objects
|
||||
taskMap[task.ID].CreatedBy = *users[task.CreatedByID]
|
||||
|
||||
// Reorder all subtasks
|
||||
if task.ParentTaskID != 0 {
|
||||
taskMap[task.ParentTaskID].Subtasks = append(taskMap[task.ParentTaskID].Subtasks, task)
|
||||
delete(taskMap, task.ID)
|
||||
}
|
||||
}
|
||||
|
||||
// make a complete slice from the map
|
||||
tasks = []*ListTask{}
|
||||
for _, t := range taskMap {
|
||||
tasks = append(tasks, t)
|
||||
}
|
||||
|
||||
// Sort the output. In Go, contents on a map are put on that map in no particular order.
|
||||
// Because of this, tasks are not sorted anymore in the output, this leads to confiusion.
|
||||
// To avoid all this, we need to sort the slice afterwards
|
||||
sort.Slice(tasks, func(i, j int) bool {
|
||||
return tasks[i].ID < tasks[j].ID
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -18,8 +18,10 @@ package models
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/metrics"
|
||||
"code.vikunja.io/api/pkg/utils"
|
||||
"code.vikunja.io/web"
|
||||
"github.com/imdario/mergo"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Create is the implementation to create a list task
|
||||
@ -60,6 +62,11 @@ func (t *ListTask) Create(a web.Auth) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
// Generate a uuid if we don't already have one
|
||||
if t.UID == "" {
|
||||
t.UID = utils.MakeRandomString(40)
|
||||
}
|
||||
|
||||
t.CreatedByID = u.ID
|
||||
t.CreatedBy = u
|
||||
if _, err = x.Insert(t); err != nil {
|
||||
@ -72,6 +79,8 @@ func (t *ListTask) Create(a web.Auth) (err error) {
|
||||
}
|
||||
|
||||
metrics.UpdateCount(1, metrics.TaskCountKey)
|
||||
|
||||
err = updateListLastUpdated(&List{ID: t.ListID})
|
||||
return
|
||||
}
|
||||
|
||||
@ -91,7 +100,7 @@ func (t *ListTask) Create(a web.Auth) (err error) {
|
||||
// @Router /tasks/{id} [post]
|
||||
func (t *ListTask) Update() (err error) {
|
||||
// Check if the task exists
|
||||
ot, err := GetListTaskByID(t.ID)
|
||||
ot, err := GetTaskByID(t.ID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -189,12 +198,20 @@ func (t *ListTask) Update() (err error) {
|
||||
"priority",
|
||||
"start_date_unix",
|
||||
"end_date_unix",
|
||||
"hex_color").
|
||||
"hex_color",
|
||||
"done_at_unix").
|
||||
Update(ot)
|
||||
*t = ot
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = updateListLastUpdated(&List{ID: t.ListID})
|
||||
return
|
||||
}
|
||||
|
||||
// This helper function updates the reminders and doneAtUnix of the *old* task (since that's the one we're inserting
|
||||
// with updated values into the db)
|
||||
func updateDone(oldTask *ListTask, newTask *ListTask) {
|
||||
if !oldTask.Done && newTask.Done && oldTask.RepeatAfter > 0 {
|
||||
oldTask.DueDateUnix = oldTask.DueDateUnix + oldTask.RepeatAfter // assuming we'll save the old task (merged)
|
||||
@ -205,4 +222,13 @@ func updateDone(oldTask *ListTask, newTask *ListTask) {
|
||||
|
||||
newTask.Done = false
|
||||
}
|
||||
|
||||
// Update the "done at" timestamp
|
||||
if !oldTask.Done && newTask.Done {
|
||||
oldTask.DoneAtUnix = time.Now().Unix()
|
||||
}
|
||||
// When unmarking a task as done, reset the timestamp
|
||||
if oldTask.Done && !newTask.Done {
|
||||
oldTask.DoneAtUnix = 0
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ import (
|
||||
func (t *ListTask) Delete() (err error) {
|
||||
|
||||
// Check if it exists
|
||||
_, err = GetListTaskByID(t.ID)
|
||||
_, err = GetTaskByID(t.ID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -51,5 +51,7 @@ func (t *ListTask) Delete() (err error) {
|
||||
}
|
||||
|
||||
metrics.UpdateCount(-1, metrics.TaskCountKey)
|
||||
|
||||
err = updateListLastUpdated(&List{ID: t.ListID})
|
||||
return
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ func (t *ListTask) CanCreate(a web.Auth) (bool, error) {
|
||||
func (t *ListTask) CanRead(a web.Auth) (canRead bool, err error) {
|
||||
//return t.canDoListTask(a)
|
||||
// Get the task, error out if it doesn't exist
|
||||
*t, err = getTaskByIDSimple(t.ID)
|
||||
*t, err = GetTaskByIDSimple(t.ID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -58,7 +58,7 @@ func (t *ListTask) canDoListTask(a web.Auth) (bool, error) {
|
||||
doer := getUserForRights(a)
|
||||
|
||||
// Get the task
|
||||
lI, err := getTaskByIDSimple(t.ID)
|
||||
lI, err := GetTaskByIDSimple(t.ID)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ func TestListTask_Create(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Check if it was updated
|
||||
li, err := GetListTaskByID(listtask.ID)
|
||||
li, err := GetTaskByID(listtask.ID)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, li.Text, "Test34")
|
||||
|
||||
@ -91,3 +91,18 @@ func TestListTask_Create(t *testing.T) {
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrUserDoesNotExist(err))
|
||||
}
|
||||
|
||||
func TestUpdateDone(t *testing.T) {
|
||||
t.Run("marking a task as done", func(t *testing.T) {
|
||||
oldTask := &ListTask{Done: false}
|
||||
newTask := &ListTask{Done: true}
|
||||
updateDone(oldTask, newTask)
|
||||
assert.NotEqual(t, int64(0), oldTask.DoneAtUnix)
|
||||
})
|
||||
t.Run("unmarking a task as done", func(t *testing.T) {
|
||||
oldTask := &ListTask{Done: true}
|
||||
newTask := &ListTask{Done: false}
|
||||
updateDone(oldTask, newTask)
|
||||
assert.Equal(t, int64(0), oldTask.DoneAtUnix)
|
||||
})
|
||||
}
|
||||
|
@ -67,6 +67,10 @@ func (lu *ListUser) Create(a web.Auth) (err error) {
|
||||
|
||||
// Insert user <-> list relation
|
||||
_, err = x.Insert(lu)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = updateListLastUpdated(l)
|
||||
return
|
||||
}
|
||||
|
@ -51,5 +51,10 @@ func (lu *ListUser) Delete() (err error) {
|
||||
|
||||
_, err = x.Where("user_id = ? AND list_id = ?", lu.UserID, lu.ListID).
|
||||
Delete(&ListUser{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = updateListLastUpdated(&List{ID: lu.ListID})
|
||||
return
|
||||
}
|
||||
|
@ -44,5 +44,10 @@ func (lu *ListUser) Update() (err error) {
|
||||
Where("list_id = ? AND user_id = ?", lu.ListID, lu.UserID).
|
||||
Cols("right").
|
||||
Update(lu)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = updateListLastUpdated(&List{ID: lu.ListID})
|
||||
return
|
||||
}
|
||||
|
@ -65,5 +65,10 @@ func (tl *TeamList) Create(a web.Auth) (err error) {
|
||||
|
||||
// Insert the new team
|
||||
_, err = x.Insert(tl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = updateListLastUpdated(l)
|
||||
return
|
||||
}
|
||||
|
@ -53,6 +53,10 @@ func (tl *TeamList) Delete() (err error) {
|
||||
_, err = x.Where("team_id = ?", tl.TeamID).
|
||||
And("list_id = ?", tl.ListID).
|
||||
Delete(TeamList{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = updateListLastUpdated(&List{ID: tl.ListID})
|
||||
return
|
||||
}
|
||||
|
@ -44,5 +44,10 @@ func (tl *TeamList) Update() (err error) {
|
||||
Where("list_id = ? AND team_id = ?", tl.ListID, tl.TeamID).
|
||||
Cols("right").
|
||||
Update(tl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = updateListLastUpdated(&List{ID: tl.ListID})
|
||||
return
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ func CreateUser(user User) (newUser User, err error) {
|
||||
|
||||
// HashPassword hashes a password
|
||||
func hashPassword(password string) (string, error) {
|
||||
bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14)
|
||||
bytes, err := bcrypt.GenerateFromPassword([]byte(password), 11)
|
||||
return string(bytes), err
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user