1
0

Add link share password authentication (#831)

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/831
Co-authored-by: konrad <konrad@kola-entertainments.de>
Co-committed-by: konrad <konrad@kola-entertainments.de>
This commit is contained in:
konrad
2021-04-11 13:17:50 +00:00
parent 6a927c0703
commit b3c604fd2f
20 changed files with 471 additions and 40 deletions

View File

@ -17,8 +17,11 @@
package models
import (
"errors"
"time"
"golang.org/x/crypto/bcrypt"
"code.vikunja.io/api/pkg/user"
"code.vikunja.io/api/pkg/utils"
"code.vikunja.io/web"
@ -49,9 +52,12 @@ type LinkSharing struct {
// The right this list is shared with. 0 = Read only, 1 = Read & Write, 2 = Admin. See the docs for more details.
Right Right `xorm:"bigint INDEX not null default 0" json:"right" valid:"length(0|2)" maximum:"2" default:"0"`
// The kind of this link. 0 = undefined, 1 = without password, 2 = with password (currently not implemented).
// The kind of this link. 0 = undefined, 1 = without password, 2 = with password.
SharingType SharingType `xorm:"bigint INDEX not null default 0" json:"sharing_type" valid:"length(0|2)" maximum:"2" default:"0"`
// The password of this link share. You can only set it, not retrieve it after the link share has been created.
Password string `xorm:"text null" json:"password"`
// The user who shared this list
SharedBy *user.User `xorm:"-" json:"shared_by"`
SharedByID int64 `xorm:"bigint INDEX not null" json:"-"`
@ -129,7 +135,19 @@ func (share *LinkSharing) Create(s *xorm.Session, a web.Auth) (err error) {
share.SharedByID = a.GetID()
share.Hash = utils.MakeRandomString(40)
if share.Password != "" {
share.SharingType = SharingTypeWithPassword
share.Password, err = user.HashPassword(share.Password)
if err != nil {
return
}
} else {
share.SharingType = SharingTypeWithoutPassword
}
_, err = s.Insert(share)
share.Password = ""
share.SharedBy, _ = user.GetFromAuth(a)
return
}
@ -156,6 +174,7 @@ func (share *LinkSharing) ReadOne(s *xorm.Session, a web.Auth) (err error) {
if !exists {
return ErrListShareDoesNotExist{ID: share.ID, Hash: share.Hash}
}
share.Password = ""
return
}
@ -212,6 +231,7 @@ func (share *LinkSharing) ReadAll(s *xorm.Session, a web.Auth, search string, pa
for _, s := range shares {
s.SharedBy = users[s.SharedByID]
s.Password = ""
}
// Total count
@ -287,3 +307,20 @@ func GetLinkSharesByIDs(s *xorm.Session, ids []int64) (shares map[int64]*LinkSha
err = s.In("id", ids).Find(&shares)
return
}
// VerifyLinkSharePassword checks if a password of a link share matches a provided one.
func VerifyLinkSharePassword(share *LinkSharing, password string) (err error) {
if password == "" {
return &ErrLinkSharePasswordRequired{ShareID: share.ID}
}
err = bcrypt.CompareHashAndPassword([]byte(share.Password), []byte(password))
if err != nil {
if errors.Is(err, bcrypt.ErrMismatchedHashAndPassword) {
return &ErrLinkSharePasswordInvalid{ShareID: share.ID}
}
return err
}
return nil
}