@@ -5532,6 +5532,19 @@ func (s *MethodTestSuite) TestOAuth2ProviderAppCodes() {
5532
5532
UserID :user .ID ,
5533
5533
}).Asserts (rbac .ResourceOauth2AppCodeToken .WithOwner (user .ID .String ()),policy .ActionDelete )
5534
5534
}))
5535
+ s .Run ("ConsumeOAuth2ProviderAppCodeByPrefix" ,s .Subtest (func (db database.Store ,check * expects ) {
5536
+ user := dbgen .User (s .T (),db , database.User {})
5537
+ app := dbgen .OAuth2ProviderApp (s .T (),db , database.OAuth2ProviderApp {})
5538
+ // Use unique prefix to avoid test isolation issues
5539
+ uniquePrefix := fmt .Sprintf ("prefix-%s-%d" ,s .T ().Name (),time .Now ().UnixNano ())
5540
+ code := dbgen .OAuth2ProviderAppCode (s .T (),db , database.OAuth2ProviderAppCode {
5541
+ SecretPrefix : []byte (uniquePrefix ),
5542
+ UserID :user .ID ,
5543
+ AppID :app .ID ,
5544
+ ExpiresAt :time .Now ().Add (24 * time .Hour ),// Extended expiry for test stability
5545
+ })
5546
+ check .Args (code .SecretPrefix ).Asserts (code ,policy .ActionUpdate ).Returns (code )
5547
+ }))
5535
5548
}
5536
5549
5537
5550
func (s * MethodTestSuite )TestOAuth2ProviderAppTokens () {
@@ -5607,6 +5620,115 @@ func (s *MethodTestSuite) TestOAuth2ProviderAppTokens() {
5607
5620
}))
5608
5621
}
5609
5622
5623
+ func (s * MethodTestSuite )TestOAuth2ProviderDeviceCodes () {
5624
+ s .Run ("InsertOAuth2ProviderDeviceCode" ,s .Subtest (func (db database.Store ,check * expects ) {
5625
+ app := dbgen .OAuth2ProviderApp (s .T (),db , database.OAuth2ProviderApp {})
5626
+ check .Args (database.InsertOAuth2ProviderDeviceCodeParams {
5627
+ ClientID :app .ID ,
5628
+ DeviceCodePrefix :"testpref" ,
5629
+ DeviceCodeHash : []byte ("hash" ),
5630
+ UserCode :"TEST1234" ,
5631
+ VerificationUri :"http://example.com/device" ,
5632
+ }).Asserts (rbac .ResourceOauth2AppCodeToken ,policy .ActionCreate )
5633
+ }))
5634
+ s .Run ("GetOAuth2ProviderDeviceCodeByID" ,s .Subtest (func (db database.Store ,check * expects ) {
5635
+ app := dbgen .OAuth2ProviderApp (s .T (),db , database.OAuth2ProviderApp {})
5636
+ deviceCode ,err := db .InsertOAuth2ProviderDeviceCode (context .Background (), database.InsertOAuth2ProviderDeviceCodeParams {
5637
+ ClientID :app .ID ,
5638
+ DeviceCodePrefix :"testpref" ,
5639
+ UserCode :"TEST1234" ,
5640
+ VerificationUri :"http://example.com/device" ,
5641
+ })
5642
+ require .NoError (s .T (),err )
5643
+ check .Args (deviceCode .ID ).Asserts (deviceCode ,policy .ActionRead ).Returns (deviceCode )
5644
+ }))
5645
+ s .Run ("GetOAuth2ProviderDeviceCodeByPrefix" ,s .Subtest (func (db database.Store ,check * expects ) {
5646
+ app := dbgen .OAuth2ProviderApp (s .T (),db , database.OAuth2ProviderApp {})
5647
+ deviceCode ,err := db .InsertOAuth2ProviderDeviceCode (context .Background (), database.InsertOAuth2ProviderDeviceCodeParams {
5648
+ ClientID :app .ID ,
5649
+ DeviceCodePrefix :"testpref" ,
5650
+ UserCode :"TEST1234" ,
5651
+ VerificationUri :"http://example.com/device" ,
5652
+ })
5653
+ require .NoError (s .T (),err )
5654
+ check .Args (deviceCode .DeviceCodePrefix ).Asserts (deviceCode ,policy .ActionRead ).Returns (deviceCode )
5655
+ }))
5656
+ s .Run ("GetOAuth2ProviderDeviceCodeByUserCode" ,s .Subtest (func (db database.Store ,check * expects ) {
5657
+ app := dbgen .OAuth2ProviderApp (s .T (),db , database.OAuth2ProviderApp {})
5658
+ deviceCode ,err := db .InsertOAuth2ProviderDeviceCode (context .Background (), database.InsertOAuth2ProviderDeviceCodeParams {
5659
+ ClientID :app .ID ,
5660
+ DeviceCodePrefix :"testpref" ,
5661
+ UserCode :"TEST1234" ,
5662
+ VerificationUri :"http://example.com/device" ,
5663
+ })
5664
+ require .NoError (s .T (),err )
5665
+ check .Args (deviceCode .UserCode ).Asserts (deviceCode ,policy .ActionRead ).Returns (deviceCode )
5666
+ }))
5667
+ s .Run ("GetOAuth2ProviderDeviceCodesByClientID" ,s .Subtest (func (db database.Store ,check * expects ) {
5668
+ app := dbgen .OAuth2ProviderApp (s .T (),db , database.OAuth2ProviderApp {})
5669
+ deviceCode ,err := db .InsertOAuth2ProviderDeviceCode (context .Background (), database.InsertOAuth2ProviderDeviceCodeParams {
5670
+ ClientID :app .ID ,
5671
+ DeviceCodePrefix :"testpref" ,
5672
+ UserCode :"TEST1234" ,
5673
+ VerificationUri :"http://example.com/device" ,
5674
+ })
5675
+ require .NoError (s .T (),err )
5676
+ check .Args (app .ID ).Asserts (rbac .ResourceOauth2AppCodeToken ,policy .ActionRead ).Returns ([]database.OAuth2ProviderDeviceCode {deviceCode })
5677
+ }))
5678
+ s .Run ("ConsumeOAuth2ProviderDeviceCodeByPrefix" ,s .Subtest (func (db database.Store ,check * expects ) {
5679
+ app := dbgen .OAuth2ProviderApp (s .T (),db , database.OAuth2ProviderApp {})
5680
+ user := dbgen .User (s .T (),db , database.User {})
5681
+ // Use unique identifiers to avoid test isolation issues
5682
+ // Device code prefix must be exactly 8 characters
5683
+ uniquePrefix := fmt .Sprintf ("t%07d" ,time .Now ().UnixNano ()% 10000000 )
5684
+ uniqueUserCode := fmt .Sprintf ("USER%04d" ,time .Now ().UnixNano ()% 10000 )
5685
+ // Create device code using dbgen (now available!)
5686
+ deviceCode := dbgen .OAuth2ProviderDeviceCode (s .T (),db , database.OAuth2ProviderDeviceCode {
5687
+ DeviceCodePrefix :uniquePrefix ,
5688
+ UserCode :uniqueUserCode ,
5689
+ ClientID :app .ID ,
5690
+ ExpiresAt :time .Now ().Add (24 * time .Hour ),// Extended expiry for test stability
5691
+ })
5692
+ // Authorize the device code so it can be consumed
5693
+ deviceCode ,err := db .UpdateOAuth2ProviderDeviceCodeAuthorization (s .T ().Context (), database.UpdateOAuth2ProviderDeviceCodeAuthorizationParams {
5694
+ ID :deviceCode .ID ,
5695
+ UserID : uuid.NullUUID {UUID :user .ID ,Valid :true },
5696
+ Status :database .OAuth2DeviceStatusAuthorized ,
5697
+ })
5698
+ require .NoError (s .T (),err )
5699
+ require .Equal (s .T (),database .OAuth2DeviceStatusAuthorized ,deviceCode .Status )
5700
+ check .Args (uniquePrefix ).Asserts (deviceCode ,policy .ActionUpdate ).Returns (deviceCode )
5701
+ }))
5702
+ s .Run ("UpdateOAuth2ProviderDeviceCodeAuthorization" ,s .Subtest (func (db database.Store ,check * expects ) {
5703
+ app := dbgen .OAuth2ProviderApp (s .T (),db , database.OAuth2ProviderApp {})
5704
+ user := dbgen .User (s .T (),db , database.User {})
5705
+ // Create device code using dbgen
5706
+ deviceCode := dbgen .OAuth2ProviderDeviceCode (s .T (),db , database.OAuth2ProviderDeviceCode {
5707
+ ClientID :app .ID ,
5708
+ })
5709
+ require .Equal (s .T (),database .OAuth2DeviceStatusPending ,deviceCode .Status )
5710
+ check .Args (database.UpdateOAuth2ProviderDeviceCodeAuthorizationParams {
5711
+ ID :deviceCode .ID ,
5712
+ UserID : uuid.NullUUID {UUID :user .ID ,Valid :true },
5713
+ Status :database .OAuth2DeviceStatusAuthorized ,
5714
+ }).Asserts (deviceCode ,policy .ActionUpdate )
5715
+ }))
5716
+ s .Run ("DeleteOAuth2ProviderDeviceCodeByID" ,s .Subtest (func (db database.Store ,check * expects ) {
5717
+ app := dbgen .OAuth2ProviderApp (s .T (),db , database.OAuth2ProviderApp {})
5718
+ deviceCode ,err := db .InsertOAuth2ProviderDeviceCode (context .Background (), database.InsertOAuth2ProviderDeviceCodeParams {
5719
+ ClientID :app .ID ,
5720
+ DeviceCodePrefix :"testpref" ,
5721
+ UserCode :"TEST1234" ,
5722
+ VerificationUri :"http://example.com/device" ,
5723
+ })
5724
+ require .NoError (s .T (),err )
5725
+ check .Args (deviceCode .ID ).Asserts (deviceCode ,policy .ActionDelete )
5726
+ }))
5727
+ s .Run ("DeleteExpiredOAuth2ProviderDeviceCodes" ,s .Subtest (func (db database.Store ,check * expects ) {
5728
+ check .Args ().Asserts (rbac .ResourceSystem ,policy .ActionDelete )
5729
+ }))
5730
+ }
5731
+
5610
5732
func (s * MethodTestSuite )TestResourcesMonitor () {
5611
5733
createAgent := func (t * testing.T ,db database.Store ) (database.WorkspaceAgent , database.WorkspaceTable ) {
5612
5734
t .Helper ()