mirror of
https://github.com/matrix-org/dendrite.git
synced 2025-12-29 09:43:10 -06:00
130 lines
3.5 KiB
Go
130 lines
3.5 KiB
Go
package internal
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"errors"
|
|
"net/url"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/matrix-org/dendrite/internal"
|
|
"github.com/matrix-org/dendrite/userapi/api"
|
|
"github.com/matrix-org/dendrite/userapi/mail"
|
|
"github.com/matrix-org/dendrite/userapi/storage/threepid"
|
|
)
|
|
|
|
const (
|
|
tokenByteLength = 48
|
|
)
|
|
|
|
var ErrBadSession = errors.New("provided sid, client_secret and token does not point to valid session")
|
|
|
|
func (a *UserInternalAPI) CreateSession(ctx context.Context, req *api.CreateSessionRequest, res *api.CreateSessionResponse) error {
|
|
s, err := a.ThreePidDB.GetSessionByThreePidAndSecret(ctx, req.ThreePid, req.ClientSecret)
|
|
if err != nil {
|
|
if err == sql.ErrNoRows {
|
|
var token string
|
|
token, err = internal.GenerateBlob(tokenByteLength)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
s = &api.Session{
|
|
ClientSecret: req.ClientSecret,
|
|
ThreePid: req.ThreePid,
|
|
SendAttempt: req.SendAttempt,
|
|
Token: token,
|
|
NextLink: req.NextLink,
|
|
}
|
|
s.Sid, err = a.ThreePidDB.InsertSession(ctx, req.ClientSecret, req.ThreePid, token, req.NextLink, 0, false, req.SendAttempt)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
return err
|
|
}
|
|
} else {
|
|
if req.SendAttempt > s.SendAttempt {
|
|
err = a.ThreePidDB.UpdateSendAttemptNextLink(ctx, s.Sid, req.NextLink)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
res.Sid = s.Sid
|
|
return nil
|
|
}
|
|
}
|
|
res.Sid = s.Sid
|
|
query := url.Values{
|
|
"sid": []string{strconv.Itoa(int(s.Sid))},
|
|
"client_secret": []string{s.ClientSecret},
|
|
"token": []string{s.Token},
|
|
}
|
|
link := url.URL{
|
|
Scheme: "https",
|
|
Host: string(a.ServerName),
|
|
Path: req.SessionType.SubmitPath(),
|
|
RawQuery: query.Encode(),
|
|
}
|
|
// TODO - if we fail sending email, send_attempt for next requests must be bumped,
|
|
// otherwise we will just return nil from this function and not sent email
|
|
return a.Mail.Send(&mail.Mail{
|
|
To: s.ThreePid,
|
|
Link: link.String(),
|
|
Token: s.Token,
|
|
Extra: req.Extra,
|
|
}, req.SessionType)
|
|
}
|
|
|
|
func (a *UserInternalAPI) ValidateSession(ctx context.Context, req *api.ValidateSessionRequest, res struct{}) error {
|
|
s, err := getSessionByOwnership(ctx, &req.SessionOwnership, a.ThreePidDB)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if s.Token != req.Token {
|
|
return ErrBadSession
|
|
}
|
|
return a.ThreePidDB.ValidateSession(ctx, s.Sid, time.Now().Unix())
|
|
}
|
|
|
|
func (a *UserInternalAPI) GetThreePidForSession(ctx context.Context, req *api.SessionOwnership, res *api.GetThreePidForSessionResponse) error {
|
|
s, err := getSessionByOwnership(ctx, req, a.ThreePidDB)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
res.ThreePid = s.ThreePid
|
|
return nil
|
|
}
|
|
|
|
func (a *UserInternalAPI) DeleteSession(ctx context.Context, req *api.SessionOwnership, res struct{}) error {
|
|
s, err := getSessionByOwnership(ctx, req, a.ThreePidDB)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return a.ThreePidDB.DeleteSession(ctx, s.Sid)
|
|
}
|
|
|
|
func (a *UserInternalAPI) IsSessionValidated(ctx context.Context, req *api.SessionOwnership, res *api.IsSessionValidatedResponse) error {
|
|
s, err := getSessionByOwnership(ctx, req, a.ThreePidDB)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
res.Validated = s.Validated
|
|
res.ValidatedAt = int(s.ValidatedAt)
|
|
return nil
|
|
}
|
|
|
|
func getSessionByOwnership(ctx context.Context, so *api.SessionOwnership, d threepid.Database) (*api.Session, error) {
|
|
s, err := d.GetSession(ctx, so.Sid)
|
|
if err != nil {
|
|
if err == sql.ErrNoRows {
|
|
return nil, ErrBadSession
|
|
}
|
|
return nil, err
|
|
}
|
|
if s.ClientSecret != so.ClientSecret {
|
|
return nil, ErrBadSession
|
|
}
|
|
return s, err
|
|
}
|