mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 11:27:44 +00:00
feat: device authorization RFC 8628 (#5646)
* device auth: implement the write events * add grant type device code * fix(init): check if default value implements stringer --------- Co-authored-by: adlerhurst <silvan.reusser@gmail.com>
This commit is contained in:
161
internal/query/projection/device_auth.go
Normal file
161
internal/query/projection/device_auth.go
Normal file
@@ -0,0 +1,161 @@
|
||||
package projection
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/errors"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/eventstore/handler"
|
||||
"github.com/zitadel/zitadel/internal/eventstore/handler/crdb"
|
||||
"github.com/zitadel/zitadel/internal/repository/deviceauth"
|
||||
)
|
||||
|
||||
const (
|
||||
DeviceAuthProjectionTable = "projections.device_authorizations"
|
||||
|
||||
DeviceAuthColumnID = "id"
|
||||
DeviceAuthColumnClientID = "client_id"
|
||||
DeviceAuthColumnDeviceCode = "device_code"
|
||||
DeviceAuthColumnUserCode = "user_code"
|
||||
DeviceAuthColumnExpires = "expires"
|
||||
DeviceAuthColumnScopes = "scopes"
|
||||
DeviceAuthColumnState = "state"
|
||||
DeviceAuthColumnSubject = "subject"
|
||||
|
||||
DeviceAuthColumnCreationDate = "creation_date"
|
||||
DeviceAuthColumnChangeDate = "change_date"
|
||||
DeviceAuthColumnSequence = "sequence"
|
||||
DeviceAuthColumnInstanceID = "instance_id"
|
||||
)
|
||||
|
||||
type deviceAuthProjection struct {
|
||||
crdb.StatementHandler
|
||||
}
|
||||
|
||||
func newDeviceAuthProjection(ctx context.Context, config crdb.StatementHandlerConfig) *deviceAuthProjection {
|
||||
p := new(deviceAuthProjection)
|
||||
config.ProjectionName = DeviceAuthProjectionTable
|
||||
config.Reducers = p.reducers()
|
||||
config.InitCheck = crdb.NewTableCheck(
|
||||
crdb.NewTable([]*crdb.Column{
|
||||
crdb.NewColumn(DeviceAuthColumnID, crdb.ColumnTypeText),
|
||||
crdb.NewColumn(DeviceAuthColumnClientID, crdb.ColumnTypeText),
|
||||
crdb.NewColumn(DeviceAuthColumnDeviceCode, crdb.ColumnTypeText),
|
||||
crdb.NewColumn(DeviceAuthColumnUserCode, crdb.ColumnTypeText),
|
||||
crdb.NewColumn(DeviceAuthColumnExpires, crdb.ColumnTypeTimestamp),
|
||||
crdb.NewColumn(DeviceAuthColumnScopes, crdb.ColumnTypeTextArray),
|
||||
crdb.NewColumn(DeviceAuthColumnState, crdb.ColumnTypeEnum, crdb.Default(domain.DeviceAuthStateInitiated)),
|
||||
crdb.NewColumn(DeviceAuthColumnSubject, crdb.ColumnTypeText, crdb.Default("")),
|
||||
crdb.NewColumn(DeviceAuthColumnCreationDate, crdb.ColumnTypeTimestamp),
|
||||
crdb.NewColumn(DeviceAuthColumnChangeDate, crdb.ColumnTypeTimestamp),
|
||||
crdb.NewColumn(DeviceAuthColumnSequence, crdb.ColumnTypeInt64),
|
||||
crdb.NewColumn(DeviceAuthColumnInstanceID, crdb.ColumnTypeText),
|
||||
},
|
||||
crdb.NewPrimaryKey(DeviceAuthColumnInstanceID, DeviceAuthColumnID),
|
||||
crdb.WithIndex(crdb.NewIndex("user_code", []string{DeviceAuthColumnInstanceID, DeviceAuthColumnUserCode})),
|
||||
crdb.WithIndex(crdb.NewIndex("device_code", []string{DeviceAuthColumnInstanceID, DeviceAuthColumnClientID, DeviceAuthColumnDeviceCode})),
|
||||
),
|
||||
)
|
||||
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *deviceAuthProjection) reducers() []handler.AggregateReducer {
|
||||
return []handler.AggregateReducer{
|
||||
{
|
||||
Aggregate: deviceauth.AggregateType,
|
||||
EventRedusers: []handler.EventReducer{
|
||||
{
|
||||
Event: deviceauth.AddedEventType,
|
||||
Reduce: p.reduceAdded,
|
||||
},
|
||||
{
|
||||
Event: deviceauth.ApprovedEventType,
|
||||
Reduce: p.reduceAppoved,
|
||||
},
|
||||
{
|
||||
Event: deviceauth.CanceledEventType,
|
||||
Reduce: p.reduceCanceled,
|
||||
},
|
||||
{
|
||||
Event: deviceauth.RemovedEventType,
|
||||
Reduce: p.reduceRemoved,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (p *deviceAuthProjection) reduceAdded(event eventstore.Event) (*handler.Statement, error) {
|
||||
e, ok := event.(*deviceauth.AddedEvent)
|
||||
if !ok {
|
||||
return nil, errors.ThrowInvalidArgumentf(nil, "HANDL-chu6O", "reduce.wrong.event.type %T != %s", event, deviceauth.AddedEventType)
|
||||
}
|
||||
return crdb.NewCreateStatement(
|
||||
e,
|
||||
[]handler.Column{
|
||||
handler.NewCol(DeviceAuthColumnID, e.Aggregate().ID),
|
||||
handler.NewCol(DeviceAuthColumnClientID, e.ClientID),
|
||||
handler.NewCol(DeviceAuthColumnDeviceCode, e.DeviceCode),
|
||||
handler.NewCol(DeviceAuthColumnUserCode, e.UserCode),
|
||||
handler.NewCol(DeviceAuthColumnExpires, e.Expires),
|
||||
handler.NewCol(DeviceAuthColumnScopes, e.Scopes),
|
||||
handler.NewCol(DeviceAuthColumnCreationDate, e.CreationDate()),
|
||||
handler.NewCol(DeviceAuthColumnChangeDate, e.CreationDate()),
|
||||
handler.NewCol(DeviceAuthColumnSequence, e.Sequence()),
|
||||
handler.NewCol(DeviceAuthColumnInstanceID, e.Aggregate().InstanceID),
|
||||
},
|
||||
), nil
|
||||
}
|
||||
|
||||
func (p *deviceAuthProjection) reduceAppoved(event eventstore.Event) (*handler.Statement, error) {
|
||||
e, ok := event.(*deviceauth.ApprovedEvent)
|
||||
if !ok {
|
||||
return nil, errors.ThrowInvalidArgumentf(nil, "HANDL-kei0A", "reduce.wrong.event.type %T != %s", event, deviceauth.ApprovedEventType)
|
||||
}
|
||||
return crdb.NewUpdateStatement(e,
|
||||
[]handler.Column{
|
||||
handler.NewCol(DeviceAuthColumnState, domain.DeviceAuthStateApproved),
|
||||
handler.NewCol(DeviceAuthColumnSubject, e.Subject),
|
||||
handler.NewCol(DeviceAuthColumnChangeDate, e.CreationDate()),
|
||||
handler.NewCol(DeviceAuthColumnSequence, e.Sequence()),
|
||||
},
|
||||
[]handler.Condition{
|
||||
handler.NewCond(DeviceAuthColumnInstanceID, e.Aggregate().InstanceID),
|
||||
handler.NewCond(DeviceAuthColumnID, e.Aggregate().ID),
|
||||
},
|
||||
), nil
|
||||
}
|
||||
|
||||
func (p *deviceAuthProjection) reduceCanceled(event eventstore.Event) (*handler.Statement, error) {
|
||||
e, ok := event.(*deviceauth.CanceledEvent)
|
||||
if !ok {
|
||||
return nil, errors.ThrowInvalidArgumentf(nil, "HANDL-eeS8d", "reduce.wrong.event.type %T != %s", event, deviceauth.CanceledEventType)
|
||||
}
|
||||
return crdb.NewUpdateStatement(e,
|
||||
[]handler.Column{
|
||||
handler.NewCol(DeviceAuthColumnState, e.Reason.State()),
|
||||
handler.NewCol(DeviceAuthColumnChangeDate, e.CreationDate()),
|
||||
handler.NewCol(DeviceAuthColumnSequence, e.Sequence()),
|
||||
},
|
||||
[]handler.Condition{
|
||||
handler.NewCond(DeviceAuthColumnInstanceID, e.Aggregate().InstanceID),
|
||||
handler.NewCond(DeviceAuthColumnID, e.Aggregate().ID),
|
||||
},
|
||||
), nil
|
||||
}
|
||||
|
||||
func (p *deviceAuthProjection) reduceRemoved(event eventstore.Event) (*handler.Statement, error) {
|
||||
e, ok := event.(*deviceauth.RemovedEvent)
|
||||
if !ok {
|
||||
return nil, errors.ThrowInvalidArgumentf(nil, "HANDL-AJi1u", "reduce.wrong.event.type %T != %s", event, deviceauth.RemovedEventType)
|
||||
}
|
||||
return crdb.NewDeleteStatement(e,
|
||||
[]handler.Condition{
|
||||
handler.NewCond(DeviceAuthColumnInstanceID, e.Aggregate().InstanceID),
|
||||
handler.NewCond(DeviceAuthColumnID, e.Aggregate().ID),
|
||||
},
|
||||
), nil
|
||||
}
|
Reference in New Issue
Block a user