Add the md5-hashed user email to user objects for use with gravatar (#78)
This commit is contained in:
parent
bd930bf654
commit
f638fae4fd
12 changed files with 161 additions and 84 deletions
|
@ -65,7 +65,7 @@ Sorry for some of them being in German, I'll tranlate them at some point.
|
||||||
-> Bleibt noch Profile abrufen und Einstellungen -> Macht also keinen Sinn das auf den neuen Handler umzuziehen
|
-> Bleibt noch Profile abrufen und Einstellungen -> Macht also keinen Sinn das auf den neuen Handler umzuziehen
|
||||||
* [x] Email-Verifizierung beim Registrieren
|
* [x] Email-Verifizierung beim Registrieren
|
||||||
* [x] Password Reset
|
* [x] Password Reset
|
||||||
* [ ] New field in user model which holds a url of an avatar image - for now just Gravatar, later more
|
* [x] New field in user model which holds a url of an avatar image - for now just Gravatar, later more
|
||||||
* [ ] Settings
|
* [ ] Settings
|
||||||
* [ ] Password update
|
* [ ] Password update
|
||||||
* [ ] Email update
|
* [ ] Email update
|
||||||
|
|
|
@ -80,33 +80,33 @@ func TestListTask(t *testing.T) {
|
||||||
t.Run("by priority", func(t *testing.T) {
|
t.Run("by priority", func(t *testing.T) {
|
||||||
rec, err := testHandler.testReadAll(url.Values{"sort": []string{"priority"}}, nil)
|
rec, err := testHandler.testReadAll(url.Values{"sort": []string{"priority"}}, nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Contains(t, rec.Body.String(), `[{"id":3,"text":"task #3 high prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"parentTaskID":0,"priority":100,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","subtasks":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","created":0,"updated":0}},{"id":4,"text":"task #4 low prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"parentTaskID":0,"priority":1`)
|
assert.Contains(t, rec.Body.String(), `[{"id":3,"text":"task #3 high prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"parentTaskID":0,"priority":100,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","subtasks":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":4,"text":"task #4 low prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"parentTaskID":0,"priority":1`)
|
||||||
})
|
})
|
||||||
t.Run("by priority desc", func(t *testing.T) {
|
t.Run("by priority desc", func(t *testing.T) {
|
||||||
rec, err := testHandler.testReadAll(url.Values{"sort": []string{"prioritydesc"}}, nil)
|
rec, err := testHandler.testReadAll(url.Values{"sort": []string{"prioritydesc"}}, nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Contains(t, rec.Body.String(), `[{"id":3,"text":"task #3 high prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"parentTaskID":0,"priority":100,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","subtasks":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","created":0,"updated":0}},{"id":4,"text":"task #4 low prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"parentTaskID":0,"priority":1`)
|
assert.Contains(t, rec.Body.String(), `[{"id":3,"text":"task #3 high prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"parentTaskID":0,"priority":100,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","subtasks":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":4,"text":"task #4 low prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"parentTaskID":0,"priority":1`)
|
||||||
})
|
})
|
||||||
t.Run("by priority asc", func(t *testing.T) {
|
t.Run("by priority asc", func(t *testing.T) {
|
||||||
rec, err := testHandler.testReadAll(url.Values{"sort": []string{"priorityasc"}}, nil)
|
rec, err := testHandler.testReadAll(url.Values{"sort": []string{"priorityasc"}}, nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Contains(t, rec.Body.String(), `{"id":31,"text":"task #31 with color","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"parentTaskID":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"f0f0f0","subtasks":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","created":0,"updated":0}},{"id":4,"text":"task #4 low prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"parentTaskID":0,"priority":1,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","subtasks":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","created":0,"updated":0}},{"id":3,"text":"task #3 high prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"parentTaskID":0,"priority":100,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","subtasks":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","created":0,"updated":0}}]`)
|
assert.Contains(t, rec.Body.String(), `{"id":31,"text":"task #31 with color","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"parentTaskID":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"f0f0f0","subtasks":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":4,"text":"task #4 low prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"parentTaskID":0,"priority":1,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","subtasks":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":3,"text":"task #3 high prio","description":"","done":false,"doneAt":0,"dueDate":0,"reminderDates":null,"listID":1,"repeatAfter":0,"parentTaskID":0,"priority":100,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","subtasks":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}}]`)
|
||||||
})
|
})
|
||||||
// should equal duedate desc
|
// should equal duedate desc
|
||||||
t.Run("by duedate", func(t *testing.T) {
|
t.Run("by duedate", func(t *testing.T) {
|
||||||
rec, err := testHandler.testReadAll(url.Values{"sort": []string{"dueadate"}}, nil)
|
rec, err := testHandler.testReadAll(url.Values{"sort": []string{"dueadate"}}, nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Contains(t, rec.Body.String(), `[{"id":5,"text":"task #5 higher due date","description":"","done":false,"doneAt":0,"dueDate":1543636724,"reminderDates":null,"listID":1,"repeatAfter":0,"parentTaskID":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","subtasks":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","created":0,"updated":0}},{"id":6,"text":"task #6 lower due date"`)
|
assert.Contains(t, rec.Body.String(), `[{"id":5,"text":"task #5 higher due date","description":"","done":false,"doneAt":0,"dueDate":1543636724,"reminderDates":null,"listID":1,"repeatAfter":0,"parentTaskID":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","subtasks":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":6,"text":"task #6 lower due date"`)
|
||||||
})
|
})
|
||||||
t.Run("by duedate desc", func(t *testing.T) {
|
t.Run("by duedate desc", func(t *testing.T) {
|
||||||
rec, err := testHandler.testReadAll(url.Values{"sort": []string{"dueadatedesc"}}, nil)
|
rec, err := testHandler.testReadAll(url.Values{"sort": []string{"dueadatedesc"}}, nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Contains(t, rec.Body.String(), `[{"id":5,"text":"task #5 higher due date","description":"","done":false,"doneAt":0,"dueDate":1543636724,"reminderDates":null,"listID":1,"repeatAfter":0,"parentTaskID":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","subtasks":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","created":0,"updated":0}},{"id":6,"text":"task #6 lower due date"`)
|
assert.Contains(t, rec.Body.String(), `[{"id":5,"text":"task #5 higher due date","description":"","done":false,"doneAt":0,"dueDate":1543636724,"reminderDates":null,"listID":1,"repeatAfter":0,"parentTaskID":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","subtasks":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":6,"text":"task #6 lower due date"`)
|
||||||
})
|
})
|
||||||
t.Run("by duedate asc", func(t *testing.T) {
|
t.Run("by duedate asc", func(t *testing.T) {
|
||||||
rec, err := testHandler.testReadAll(url.Values{"sort": []string{"duedateasc"}}, nil)
|
rec, err := testHandler.testReadAll(url.Values{"sort": []string{"duedateasc"}}, nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Contains(t, rec.Body.String(), `{"id":6,"text":"task #6 lower due date","description":"","done":false,"doneAt":0,"dueDate":1543616724,"reminderDates":null,"listID":1,"repeatAfter":0,"parentTaskID":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","subtasks":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","created":0,"updated":0}},{"id":5,"text":"task #5 higher due date","description":"","done":false,"doneAt":0,"dueDate":1543636724,"reminderDates":null,"listID":1,"repeatAfter":0,"parentTaskID":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","subtasks":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","created":0,"updated":0}}]`)
|
assert.Contains(t, rec.Body.String(), `{"id":6,"text":"task #6 lower due date","description":"","done":false,"doneAt":0,"dueDate":1543616724,"reminderDates":null,"listID":1,"repeatAfter":0,"parentTaskID":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","subtasks":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}},{"id":5,"text":"task #5 higher due date","description":"","done":false,"doneAt":0,"dueDate":1543636724,"reminderDates":null,"listID":1,"repeatAfter":0,"parentTaskID":0,"priority":0,"startDate":0,"endDate":0,"assignees":null,"labels":null,"hexColor":"","subtasks":null,"created":1543626724,"updated":1543626724,"createdBy":{"id":1,"username":"user1","avatarUrl":"111d68d06e2d317b5a59c2c6c5bad808","created":0,"updated":0}}]`)
|
||||||
})
|
})
|
||||||
t.Run("invalid parameter", func(t *testing.T) {
|
t.Run("invalid parameter", func(t *testing.T) {
|
||||||
// Invalid parameter should not sort at all
|
// Invalid parameter should not sort at all
|
||||||
|
|
|
@ -50,6 +50,7 @@ func TestLabelTask_ReadAll(t *testing.T) {
|
||||||
ID: 2,
|
ID: 2,
|
||||||
Username: "user2",
|
Username: "user2",
|
||||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||||
|
AvatarURL: "ab53a2911ddf9b4817ac01ddcd3d975f", // hash for ""
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -48,6 +48,7 @@ func TestLabel_ReadAll(t *testing.T) {
|
||||||
Username: "user1",
|
Username: "user1",
|
||||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||||
IsActive: true,
|
IsActive: true,
|
||||||
|
AvatarURL: "111d68d06e2d317b5a59c2c6c5bad808",
|
||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
@ -88,6 +89,7 @@ func TestLabel_ReadAll(t *testing.T) {
|
||||||
ID: 2,
|
ID: 2,
|
||||||
Username: "user2",
|
Username: "user2",
|
||||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||||
|
AvatarURL: "ab53a2911ddf9b4817ac01ddcd3d975f",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -142,6 +144,7 @@ func TestLabel_ReadOne(t *testing.T) {
|
||||||
Username: "user1",
|
Username: "user1",
|
||||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||||
IsActive: true,
|
IsActive: true,
|
||||||
|
AvatarURL: "111d68d06e2d317b5a59c2c6c5bad808",
|
||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
@ -196,6 +199,7 @@ func TestLabel_ReadOne(t *testing.T) {
|
||||||
ID: 2,
|
ID: 2,
|
||||||
Username: "user2",
|
Username: "user2",
|
||||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||||
|
AvatarURL: "ab53a2911ddf9b4817ac01ddcd3d975f",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
auth: &User{ID: 1},
|
auth: &User{ID: 1},
|
||||||
|
|
|
@ -21,17 +21,20 @@ func sortTasksForTesting(by SortBy) (tasks []*ListTask) {
|
||||||
Username: "user1",
|
Username: "user1",
|
||||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||||
IsActive: true,
|
IsActive: true,
|
||||||
|
AvatarURL: "111d68d06e2d317b5a59c2c6c5bad808", // hash for ""
|
||||||
}
|
}
|
||||||
user2 := User{
|
user2 := User{
|
||||||
ID: 2,
|
ID: 2,
|
||||||
Username: "user2",
|
Username: "user2",
|
||||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||||
|
AvatarURL: "ab53a2911ddf9b4817ac01ddcd3d975f", // hash for ""
|
||||||
}
|
}
|
||||||
user6 := User{
|
user6 := User{
|
||||||
ID: 6,
|
ID: 6,
|
||||||
Username: "user6",
|
Username: "user6",
|
||||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||||
IsActive: true,
|
IsActive: true,
|
||||||
|
AvatarURL: "3efbe51f864c6666bc27caf4c6ff90ed", // hash for ""
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks = []*ListTask{
|
tasks = []*ListTask{
|
||||||
|
@ -347,6 +350,7 @@ func TestListTask_ReadAll(t *testing.T) {
|
||||||
Username: "user1",
|
Username: "user1",
|
||||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||||
IsActive: true,
|
IsActive: true,
|
||||||
|
AvatarURL: "111d68d06e2d317b5a59c2c6c5bad808", // hash for ""
|
||||||
}
|
}
|
||||||
|
|
||||||
type fields struct {
|
type fields struct {
|
||||||
|
|
|
@ -164,6 +164,7 @@ func TestListUser_ReadAll(t *testing.T) {
|
||||||
Username: "user1",
|
Username: "user1",
|
||||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||||
IsActive: true,
|
IsActive: true,
|
||||||
|
AvatarURL: "111d68d06e2d317b5a59c2c6c5bad808",
|
||||||
},
|
},
|
||||||
Right: RightRead,
|
Right: RightRead,
|
||||||
},
|
},
|
||||||
|
@ -172,6 +173,7 @@ func TestListUser_ReadAll(t *testing.T) {
|
||||||
ID: 2,
|
ID: 2,
|
||||||
Username: "user2",
|
Username: "user2",
|
||||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||||
|
AvatarURL: "ab53a2911ddf9b4817ac01ddcd3d975f",
|
||||||
},
|
},
|
||||||
Right: RightRead,
|
Right: RightRead,
|
||||||
},
|
},
|
||||||
|
|
|
@ -163,6 +163,7 @@ func TestNamespaceUser_ReadAll(t *testing.T) {
|
||||||
Username: "user1",
|
Username: "user1",
|
||||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||||
IsActive: true,
|
IsActive: true,
|
||||||
|
AvatarURL: "111d68d06e2d317b5a59c2c6c5bad808",
|
||||||
},
|
},
|
||||||
Right: RightRead,
|
Right: RightRead,
|
||||||
},
|
},
|
||||||
|
@ -171,6 +172,7 @@ func TestNamespaceUser_ReadAll(t *testing.T) {
|
||||||
ID: 2,
|
ID: 2,
|
||||||
Username: "user2",
|
Username: "user2",
|
||||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||||
|
AvatarURL: "ab53a2911ddf9b4817ac01ddcd3d975f",
|
||||||
},
|
},
|
||||||
Right: RightRead,
|
Right: RightRead,
|
||||||
},
|
},
|
||||||
|
|
|
@ -19,6 +19,7 @@ package models
|
||||||
import (
|
import (
|
||||||
"code.vikunja.io/api/pkg/log"
|
"code.vikunja.io/api/pkg/log"
|
||||||
"code.vikunja.io/api/pkg/metrics"
|
"code.vikunja.io/api/pkg/metrics"
|
||||||
|
"code.vikunja.io/api/pkg/utils"
|
||||||
"code.vikunja.io/web"
|
"code.vikunja.io/web"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/dgrijalva/jwt-go"
|
"github.com/dgrijalva/jwt-go"
|
||||||
|
@ -46,6 +47,8 @@ type User struct {
|
||||||
// The user's email address.
|
// The user's email address.
|
||||||
Email string `xorm:"varchar(250) null" json:"email,omitempty" valid:"email,length(0|250)" maxLength:"250"`
|
Email string `xorm:"varchar(250) null" json:"email,omitempty" valid:"email,length(0|250)" maxLength:"250"`
|
||||||
IsActive bool `xorm:"null" json:"-"`
|
IsActive bool `xorm:"null" json:"-"`
|
||||||
|
// The users md5-hashed email address, used to get the avatar from gravatar and the likes.
|
||||||
|
AvatarURL string `xorm:"-" json:"avatarUrl"`
|
||||||
|
|
||||||
PasswordResetToken string `xorm:"varchar(450) null" json:"-"`
|
PasswordResetToken string `xorm:"varchar(450) null" json:"-"`
|
||||||
EmailConfirmToken string `xorm:"varchar(450) null" json:"-"`
|
EmailConfirmToken string `xorm:"varchar(450) null" json:"-"`
|
||||||
|
@ -60,6 +63,7 @@ type User struct {
|
||||||
|
|
||||||
// AfterLoad is used to delete all emails to not have them leaked to the user
|
// AfterLoad is used to delete all emails to not have them leaked to the user
|
||||||
func (u *User) AfterLoad() {
|
func (u *User) AfterLoad() {
|
||||||
|
u.AvatarURL = utils.Md5String(u.Email)
|
||||||
u.Email = ""
|
u.Email = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||||
// This file was generated by swaggo/swag at
|
// This file was generated by swaggo/swag at
|
||||||
// 2019-05-25 11:35:41.214134069 +0200 CEST m=+0.124896065
|
// 2019-05-30 23:45:13.052367163 +0200 CEST m=+0.289150504
|
||||||
|
|
||||||
package swagger
|
package swagger
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ import (
|
||||||
var doc = `{
|
var doc = `{
|
||||||
"swagger": "2.0",
|
"swagger": "2.0",
|
||||||
"info": {
|
"info": {
|
||||||
"description": "This is the documentation for the [Vikunja](http://vikunja.io) API. Vikunja is a cross-plattform Todo-application with a lot of features, such as sharing lists with users or teams. \u003c!-- ReDoc-Inject: \u003csecurity-definitions\u003e --\u003e\n# Authorization\n**JWT-Auth:** Main authorization method, used for most of the requests. Needs ` + "`" + `Authorization: Bearer \u003cjwt-token\u003e` + "`" + `-header to authenticate successfully.\n\n**BasicAuth:** Only used when requesting tasks via caldav.\n\u003c!-- ReDoc-Inject: \u003csecurity-definitions\u003e --\u003e",
|
"description": "\u003c!-- ReDoc-Inject: \u003csecurity-definitions\u003e --\u003e",
|
||||||
"title": "Vikunja API",
|
"title": "Vikunja API",
|
||||||
"contact": {
|
"contact": {
|
||||||
"name": "General Vikunja contact",
|
"name": "General Vikunja contact",
|
||||||
|
@ -391,7 +391,7 @@ var doc = `{
|
||||||
"JWTKeyAuth": []
|
"JWTKeyAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Returns a list by its ID.",
|
"description": "Returns a team by its ID.",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
|
@ -399,13 +399,13 @@ var doc = `{
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"list"
|
"team"
|
||||||
],
|
],
|
||||||
"summary": "Gets one list",
|
"summary": "Gets one team",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"description": "List ID",
|
"description": "Team ID",
|
||||||
"name": "id",
|
"name": "id",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
|
@ -413,14 +413,14 @@ var doc = `{
|
||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "The list",
|
"description": "The team",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"$ref": "#/definitions/models.List"
|
"$ref": "#/definitions/models.Team"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"403": {
|
"403": {
|
||||||
"description": "The user does not have access to the list",
|
"description": "The user does not have access to the team",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"$ref": "#/definitions/code.vikunja.io.web.HTTPError"
|
"$ref": "#/definitions/code.vikunja.io.web.HTTPError"
|
||||||
|
@ -4243,6 +4243,10 @@ var doc = `{
|
||||||
"description": "Whether or not the member is an admin of the team. See the docs for more about what a team admin can do",
|
"description": "Whether or not the member is an admin of the team. See the docs for more about what a team admin can do",
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"avatarUrl": {
|
||||||
|
"description": "The users md5-hashed email address, used to get the avatar from gravatar and the likes.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"created": {
|
"created": {
|
||||||
"description": "A unix timestamp when this task was created. You cannot change this value.",
|
"description": "A unix timestamp when this task was created. You cannot change this value.",
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
|
@ -4315,6 +4319,10 @@ var doc = `{
|
||||||
"models.User": {
|
"models.User": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"avatarUrl": {
|
||||||
|
"description": "The users md5-hashed email address, used to get the avatar from gravatar and the likes.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"created": {
|
"created": {
|
||||||
"description": "A unix timestamp when this task was created. You cannot change this value.",
|
"description": "A unix timestamp when this task was created. You cannot change this value.",
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
|
@ -4356,6 +4364,10 @@ var doc = `{
|
||||||
"models.UserWithRight": {
|
"models.UserWithRight": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"avatarUrl": {
|
||||||
|
"description": "The users md5-hashed email address, used to get the avatar from gravatar and the likes.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"created": {
|
"created": {
|
||||||
"description": "A unix timestamp when this task was created. You cannot change this value.",
|
"description": "A unix timestamp when this task was created. You cannot change this value.",
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"swagger": "2.0",
|
"swagger": "2.0",
|
||||||
"info": {
|
"info": {
|
||||||
"description": "This is the documentation for the [Vikunja](http://vikunja.io) API. Vikunja is a cross-plattform Todo-application with a lot of features, such as sharing lists with users or teams. \u003c!-- ReDoc-Inject: \u003csecurity-definitions\u003e --\u003e\n# Authorization\n**JWT-Auth:** Main authorization method, used for most of the requests. Needs ` + \"`\" + `Authorization: Bearer \u003cjwt-token\u003e` + \"`\" + `-header to authenticate successfully.\n\n**BasicAuth:** Only used when requesting tasks via caldav.\n\u003c!-- ReDoc-Inject: \u003csecurity-definitions\u003e --\u003e",
|
"description": "\u003c!-- ReDoc-Inject: \u003csecurity-definitions\u003e --\u003e",
|
||||||
"title": "Vikunja API",
|
"title": "Vikunja API",
|
||||||
"contact": {
|
"contact": {
|
||||||
"name": "General Vikunja contact",
|
"name": "General Vikunja contact",
|
||||||
|
@ -378,7 +378,7 @@
|
||||||
"JWTKeyAuth": []
|
"JWTKeyAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Returns a list by its ID.",
|
"description": "Returns a team by its ID.",
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
|
@ -386,13 +386,13 @@
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"list"
|
"team"
|
||||||
],
|
],
|
||||||
"summary": "Gets one list",
|
"summary": "Gets one team",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"description": "List ID",
|
"description": "Team ID",
|
||||||
"name": "id",
|
"name": "id",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
|
@ -400,14 +400,14 @@
|
||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "The list",
|
"description": "The team",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"$ref": "#/definitions/models.List"
|
"$ref": "#/definitions/models.Team"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"403": {
|
"403": {
|
||||||
"description": "The user does not have access to the list",
|
"description": "The user does not have access to the team",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"$ref": "#/definitions/code.vikunja.io/web.HTTPError"
|
"$ref": "#/definitions/code.vikunja.io/web.HTTPError"
|
||||||
|
@ -4229,6 +4229,10 @@
|
||||||
"description": "Whether or not the member is an admin of the team. See the docs for more about what a team admin can do",
|
"description": "Whether or not the member is an admin of the team. See the docs for more about what a team admin can do",
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"avatarUrl": {
|
||||||
|
"description": "The users md5-hashed email address, used to get the avatar from gravatar and the likes.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"created": {
|
"created": {
|
||||||
"description": "A unix timestamp when this task was created. You cannot change this value.",
|
"description": "A unix timestamp when this task was created. You cannot change this value.",
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
|
@ -4301,6 +4305,10 @@
|
||||||
"models.User": {
|
"models.User": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"avatarUrl": {
|
||||||
|
"description": "The users md5-hashed email address, used to get the avatar from gravatar and the likes.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"created": {
|
"created": {
|
||||||
"description": "A unix timestamp when this task was created. You cannot change this value.",
|
"description": "A unix timestamp when this task was created. You cannot change this value.",
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
|
@ -4342,6 +4350,10 @@
|
||||||
"models.UserWithRight": {
|
"models.UserWithRight": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"avatarUrl": {
|
||||||
|
"description": "The users md5-hashed email address, used to get the avatar from gravatar and the likes.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"created": {
|
"created": {
|
||||||
"description": "A unix timestamp when this task was created. You cannot change this value.",
|
"description": "A unix timestamp when this task was created. You cannot change this value.",
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
|
|
|
@ -521,6 +521,10 @@ definitions:
|
||||||
description: Whether or not the member is an admin of the team. See the docs
|
description: Whether or not the member is an admin of the team. See the docs
|
||||||
for more about what a team admin can do
|
for more about what a team admin can do
|
||||||
type: boolean
|
type: boolean
|
||||||
|
avatarUrl:
|
||||||
|
description: The users md5-hashed email address, used to get the avatar from
|
||||||
|
gravatar and the likes.
|
||||||
|
type: string
|
||||||
created:
|
created:
|
||||||
description: A unix timestamp when this task was created. You cannot change
|
description: A unix timestamp when this task was created. You cannot change
|
||||||
this value.
|
this value.
|
||||||
|
@ -579,6 +583,10 @@ definitions:
|
||||||
type: object
|
type: object
|
||||||
models.User:
|
models.User:
|
||||||
properties:
|
properties:
|
||||||
|
avatarUrl:
|
||||||
|
description: The users md5-hashed email address, used to get the avatar from
|
||||||
|
gravatar and the likes.
|
||||||
|
type: string
|
||||||
created:
|
created:
|
||||||
description: A unix timestamp when this task was created. You cannot change
|
description: A unix timestamp when this task was created. You cannot change
|
||||||
this value.
|
this value.
|
||||||
|
@ -611,6 +619,10 @@ definitions:
|
||||||
type: object
|
type: object
|
||||||
models.UserWithRight:
|
models.UserWithRight:
|
||||||
properties:
|
properties:
|
||||||
|
avatarUrl:
|
||||||
|
description: The users md5-hashed email address, used to get the avatar from
|
||||||
|
gravatar and the likes.
|
||||||
|
type: string
|
||||||
created:
|
created:
|
||||||
description: A unix timestamp when this task was created. You cannot change
|
description: A unix timestamp when this task was created. You cannot change
|
||||||
this value.
|
this value.
|
||||||
|
@ -652,13 +664,7 @@ info:
|
||||||
email: hello@vikunja.io
|
email: hello@vikunja.io
|
||||||
name: General Vikunja contact
|
name: General Vikunja contact
|
||||||
url: http://vikunja.io/en/contact/
|
url: http://vikunja.io/en/contact/
|
||||||
description: |-
|
description: '<!-- ReDoc-Inject: <security-definitions> -->'
|
||||||
This is the documentation for the [Vikunja](http://vikunja.io) API. Vikunja is a cross-plattform Todo-application with a lot of features, such as sharing lists with users or teams. <!-- ReDoc-Inject: <security-definitions> -->
|
|
||||||
# Authorization
|
|
||||||
**JWT-Auth:** Main authorization method, used for most of the requests. Needs ` + "`" + `Authorization: Bearer <jwt-token>` + "`" + `-header to authenticate successfully.
|
|
||||||
|
|
||||||
**BasicAuth:** Only used when requesting tasks via caldav.
|
|
||||||
<!-- ReDoc-Inject: <security-definitions> -->
|
|
||||||
license:
|
license:
|
||||||
name: GPLv3
|
name: GPLv3
|
||||||
url: http://code.vikunja.io/api/src/branch/master/LICENSE
|
url: http://code.vikunja.io/api/src/branch/master/LICENSE
|
||||||
|
@ -942,9 +948,9 @@ paths:
|
||||||
get:
|
get:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
description: Returns a list by its ID.
|
description: Returns a team by its ID.
|
||||||
parameters:
|
parameters:
|
||||||
- description: List ID
|
- description: Team ID
|
||||||
in: path
|
in: path
|
||||||
name: id
|
name: id
|
||||||
required: true
|
required: true
|
||||||
|
@ -953,12 +959,12 @@ paths:
|
||||||
- application/json
|
- application/json
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
description: The list
|
description: The team
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/models.List'
|
$ref: '#/definitions/models.Team'
|
||||||
type: object
|
type: object
|
||||||
"403":
|
"403":
|
||||||
description: The user does not have access to the list
|
description: The user does not have access to the team
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/code.vikunja.io/web.HTTPError'
|
$ref: '#/definitions/code.vikunja.io/web.HTTPError'
|
||||||
type: object
|
type: object
|
||||||
|
@ -969,9 +975,9 @@ paths:
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- JWTKeyAuth: []
|
- JWTKeyAuth: []
|
||||||
summary: Gets one list
|
summary: Gets one team
|
||||||
tags:
|
tags:
|
||||||
- list
|
- team
|
||||||
post:
|
post:
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
|
|
30
pkg/utils/md5_string.go
Normal file
30
pkg/utils/md5_string.go
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
// Vikunja is a todo-list application to facilitate your life.
|
||||||
|
// Copyright 2019 Vikunja and contributors. All rights reserved.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/md5"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Md5String generates an md5 hash from a string
|
||||||
|
func Md5String(in string) string {
|
||||||
|
h := md5.New()
|
||||||
|
io.WriteString(h, in)
|
||||||
|
return fmt.Sprintf("%x", h.Sum(nil))
|
||||||
|
}
|
Loading…
Reference in a new issue