diff --git a/go.sum b/go.sum
index b1a11877..ae0982a7 100644
--- a/go.sum
+++ b/go.sum
@@ -248,8 +248,6 @@ github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zV
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
-github.com/golang-jwt/jwt/v4 v4.1.0 h1:XUgk2Ex5veyVFVeLm0xhusUTQybEbexJXrvPNOKkSY0=
-github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU=
github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
@@ -785,8 +783,6 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871 h1:/pEO3GD/ABYAjuakUS6xSEmmlyVS4kxBNkeA9tLJiTI=
-golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20211202192323-5770296d904e h1:MUP6MR3rJ7Gk9LEia0LP2ytiH6MuCfs7qYz+47jGdD8=
golang.org/x/crypto v0.0.0-20211202192323-5770296d904e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -992,8 +988,6 @@ golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211124211545-fe61309f8881 h1:TyHqChC80pFkXWraUUf6RuB5IqFdQieMLwwCJokV2pc=
-golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211204120058-94396e421777 h1:QAkhGVjOxMa+n4mlsAWeAU+BMZmimQAaNiMu+iUi94E=
golang.org/x/sys v0.0.0-20211204120058-94396e421777/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d h1:FjkYO/PPp4Wi0EAUOVLxePm7qVW4r4ctbWpURyuOD0E=
diff --git a/pkg/modules/avatar/marble/marble.go b/pkg/modules/avatar/marble/marble.go
new file mode 100644
index 00000000..a3686168
--- /dev/null
+++ b/pkg/modules/avatar/marble/marble.go
@@ -0,0 +1,122 @@
+// Vikunja is a to-do list application to facilitate your life.
+// Copyright 2018-2021 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 Affero General Public Licensee 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 Affero General Public Licensee for more details.
+//
+// You should have received a copy of the GNU Affero General Public Licensee
+// along with this program. If not, see .
+
+package marble
+
+import (
+ "math"
+ "strconv"
+
+ "code.vikunja.io/api/pkg/user"
+)
+
+// Provider generates a random avatar based on https://github.com/boringdesigners/boring-avatars
+type Provider struct {
+}
+
+const avatarSize = 80
+
+var colors = []string{
+ "#A3A948",
+ "#EDB92E",
+ "#F85931",
+ "#CE1836",
+ "#009989",
+}
+
+type props struct {
+ Color string
+ TranslateX int
+ TranslateY int
+ Rotate int
+ Scale float64
+}
+
+func getUnit(number int, rang, index int) int {
+ value := number % rang
+
+ digit := math.Floor(math.Mod(float64(number)/math.Pow(10, float64(index)), 10))
+
+ if index > 0 && (math.Mod(digit, 2) == 0) {
+ return -value
+ }
+
+ return value
+}
+
+func getPropsForUser(u *user.User) []*props {
+ ps := []*props{}
+ for i := 0; i < 3; i++ {
+ f := float64(getUnit(int(u.ID)*(i+1), avatarSize/10, 0))
+ ps = append(ps, &props{
+ Color: colors[(int(u.ID)+i)%(len(colors)-1)],
+ TranslateX: getUnit(int(u.ID)*(i+1), avatarSize/10, 1),
+ TranslateY: getUnit(int(u.ID)*(i+1), avatarSize/10, 2),
+ Scale: 1.2 + f/10,
+ Rotate: getUnit(int(u.ID)*(i+1), 360, 1),
+ })
+ }
+
+ return ps
+}
+
+func (p *Provider) GetAvatar(u *user.User, size int64) (avatar []byte, mimeType string, err error) {
+
+ s := strconv.FormatInt(size, 10)
+ avatarSizeStr := strconv.Itoa(avatarSize)
+ avatarSizeHalf := strconv.Itoa(avatarSize / 2)
+
+ ps := getPropsForUser(u)
+
+ return []byte(``), "image/svg+xml", nil
+}
diff --git a/pkg/routes/api/v1/avatar.go b/pkg/routes/api/v1/avatar.go
index 03c9e057..7b52254f 100644
--- a/pkg/routes/api/v1/avatar.go
+++ b/pkg/routes/api/v1/avatar.go
@@ -25,6 +25,7 @@ import (
"code.vikunja.io/api/pkg/modules/avatar/empty"
"code.vikunja.io/api/pkg/modules/avatar/gravatar"
"code.vikunja.io/api/pkg/modules/avatar/initials"
+ "code.vikunja.io/api/pkg/modules/avatar/marble"
"code.vikunja.io/api/pkg/modules/avatar/upload"
"code.vikunja.io/api/pkg/user"
"code.vikunja.io/web/handler"
@@ -77,6 +78,8 @@ func GetAvatar(c echo.Context) error {
avatarProvider = &initials.Provider{}
case "upload":
avatarProvider = &upload.Provider{}
+ case "marble":
+ avatarProvider = &marble.Provider{}
default:
avatarProvider = &empty.Provider{}
}
diff --git a/pkg/routes/api/v1/user_settings.go b/pkg/routes/api/v1/user_settings.go
index c112e031..62b2ba74 100644
--- a/pkg/routes/api/v1/user_settings.go
+++ b/pkg/routes/api/v1/user_settings.go
@@ -29,7 +29,7 @@ import (
// UserAvatarProvider holds the user avatar provider type
type UserAvatarProvider struct {
- // The avatar provider. Valid types are `gravatar` (uses the user email), `upload`, `initials`, `default`.
+ // The avatar provider. Valid types are `gravatar` (uses the user email), `upload`, `initials`, `marble` (generates a random avatar for each user), `default`.
AvatarProvider string `json:"avatar_provider"`
}
diff --git a/pkg/swagger/docs.go b/pkg/swagger/docs.go
index bd1fb705..3177e0aa 100644
--- a/pkg/swagger/docs.go
+++ b/pkg/swagger/docs.go
@@ -8915,7 +8915,7 @@ var doc = `{
"type": "object",
"properties": {
"avatar_provider": {
- "description": "The avatar provider. Valid types are ` + "`" + `gravatar` + "`" + ` (uses the user email), ` + "`" + `upload` + "`" + `, ` + "`" + `initials` + "`" + `, ` + "`" + `default` + "`" + `.",
+ "description": "The avatar provider. Valid types are ` + "`" + `gravatar` + "`" + ` (uses the user email), ` + "`" + `upload` + "`" + `, ` + "`" + `initials` + "`" + `, ` + "`" + `marble` + "`" + ` (generates a random avatar for each user), ` + "`" + `default` + "`" + `.",
"type": "string"
}
}
diff --git a/pkg/swagger/swagger.json b/pkg/swagger/swagger.json
index 43816ac8..85855386 100644
--- a/pkg/swagger/swagger.json
+++ b/pkg/swagger/swagger.json
@@ -8899,7 +8899,7 @@
"type": "object",
"properties": {
"avatar_provider": {
- "description": "The avatar provider. Valid types are `gravatar` (uses the user email), `upload`, `initials`, `default`.",
+ "description": "The avatar provider. Valid types are `gravatar` (uses the user email), `upload`, `initials`, `marble` (generates a random avatar for each user), `default`.",
"type": "string"
}
}
diff --git a/pkg/swagger/swagger.yaml b/pkg/swagger/swagger.yaml
index 3a9efe63..47f36a40 100644
--- a/pkg/swagger/swagger.yaml
+++ b/pkg/swagger/swagger.yaml
@@ -1235,7 +1235,8 @@ definitions:
properties:
avatar_provider:
description: The avatar provider. Valid types are `gravatar` (uses the user
- email), `upload`, `initials`, `default`.
+ email), `upload`, `initials`, `marble` (generates a random avatar for each
+ user), `default`.
type: string
type: object
v1.UserDeletionRequestConfirm:
diff --git a/pkg/user/user.go b/pkg/user/user.go
index ac1786d9..ccf50ce2 100644
--- a/pkg/user/user.go
+++ b/pkg/user/user.go
@@ -455,7 +455,8 @@ func UpdateUser(s *xorm.Session, user *User) (updatedUser *User, err error) {
if user.AvatarProvider != "default" &&
user.AvatarProvider != "gravatar" &&
user.AvatarProvider != "initials" &&
- user.AvatarProvider != "upload" {
+ user.AvatarProvider != "upload" &&
+ user.AvatarProvider != "marble" {
return updatedUser, &ErrInvalidAvatarProvider{AvatarProvider: user.AvatarProvider}
}
}