@@ -10,6 +10,8 @@ import (
1010 "os/exec"
1111 "sync"
1212 "syscall"
13+
14+ "github.com/script-development/rtcv_scraper_client/v2/crypto"
1315)
1416
1517// Env contains the structure of the .env file
@@ -23,22 +25,22 @@ type Env struct {
2325func (e * Env ) validate () error {
2426 if e .MockMode {
2527 if len (e .MockUsers ) == 0 {
26- fmt .Println (" \" mock_users\ " is empty in env.json, most scrapers require at least one user to login." )
27- fmt .Println (" For documentation about mocking see https://github.com/script-development/rtcv_scraper_client" )
28+ fmt .Println (`" mock_users" is empty in env.json, most scrapers require at least one user to login.` )
29+ fmt .Println (` For documentation about mocking see https://github.com/script-development/rtcv_scraper_client` )
2830 if e .MockUsers == nil {
2931 e .MockUsers = []EnvUser {}
3032 }
3133 }
3234 return nil
3335 }
3436
35- err := e .PrimaryServer .validate ()
37+ err := e .PrimaryServer .validate (true )
3638 if err != nil {
3739 return fmt .Errorf ("primary_server.%s" , err .Error ())
3840 }
3941
4042 for idx , server := range e .AlternativeServers {
41- err := server .validate ()
43+ err := server .validate (false )
4244 if err != nil {
4345 return fmt .Errorf ("%s[%d].%s" , "alternative_servers" , idx , err .Error ())
4446 }
@@ -52,9 +54,11 @@ type EnvServer struct {
5254 ServerLocation string `json:"server_location"`
5355 APIKeyID string `json:"api_key_id"`
5456 APIKey string `json:"api_key"`
57+ PrivateKey string `json:"private_key"`
58+ PublicKey string `json:"public_key"`
5559}
5660
57- func (e * EnvServer ) validate () error {
61+ func (e * EnvServer ) validate (isPrimary bool ) error {
5862 if e .ServerLocation == "" {
5963 return errors .New ("server_location is required" )
6064 }
@@ -64,6 +68,23 @@ func (e *EnvServer) validate() error {
6468 if e .APIKey == "" {
6569 return errors .New ("api_key is required" )
6670 }
71+ if isPrimary {
72+ if e .PrivateKey == "" && e .PublicKey == "" {
73+ return errors .New (`"public_key" and "private_key" required by "primary_server"` )
74+ } else if e .PrivateKey == "" {
75+ return errors .New (`"private_key" required by "primary_server"` )
76+ } else if e .PublicKey == "" {
77+ return errors .New (`"public_key" required by "primary_server"` )
78+ }
79+ } else {
80+ if e .PrivateKey != "" && e .PublicKey != "" {
81+ fmt .Println ("WARN: public_key and private_key pairs are not used by alternative servers" )
82+ } else if e .PrivateKey != "" {
83+ fmt .Println ("WARN: private_key not used by alternative servers" )
84+ } else if e .PublicKey != "" {
85+ fmt .Println ("WARN: public_key not used by alternative servers" )
86+ }
87+ }
6788
6889 return nil
6990}
@@ -79,8 +100,9 @@ func (e *EnvServer) toCredArg(isPrimary bool) SetCredentialsArg {
79100
80101// EnvUser contains the structure of the login_users inside the .env file
81102type EnvUser struct {
82- Username string `json:"username"`
83- Password string `json:"password"`
103+ Username string `json:"username"`
104+ Password string `json:"password"`
105+ EncryptedPassword string `json:"encryptedPassword,omitempty"`
84106}
85107
86108func main () {
@@ -120,16 +142,17 @@ func main() {
120142 credentials = append (credentials , server .toCredArg (false ))
121143 }
122144
123- loginUsers := []EnvUser {}
145+ var loginUsers []EnvUser
124146 if ! env .MockMode {
125147 err = api .SetCredentials (credentials )
126148 if err != nil {
127149 log .Fatal (err )
128150 }
151+ decryptionKey := crypto .LoadAndVerivyKeys (env .PrimaryServer .PublicKey , env .PrimaryServer .PrivateKey )
129152
130153 fmt .Println ("credentials set" )
131154 fmt .Println ("testing connections.." )
132- loginUsers = testServerConnections (api , credentials [0 ].APIKeyID )
155+ loginUsers = testServerConnections (api , credentials [0 ].APIKeyID , decryptionKey )
133156 fmt .Println ("connected to RTCV" )
134157 } else {
135158 api .SetMockMode ()
@@ -165,7 +188,7 @@ func main() {
165188 }
166189}
167190
168- func testServerConnections (api * API , apiKeyID string ) []EnvUser {
191+ func testServerConnections (api * API , apiKeyID string , decryptionKey * crypto. Key ) []EnvUser {
169192 var wg sync.WaitGroup
170193
171194 for _ , conn := range api .connections {
@@ -201,17 +224,38 @@ func testServerConnections(api *API, apiKeyID string) []EnvUser {
201224 }
202225
203226 scraperUsers := struct {
204- Users []EnvUser `json:"users"`
227+ ScraperPublicKey string `json:"scraperPubKey"`
228+ Users []EnvUser `json:"users"`
205229 }{}
206230 err := api .connections [0 ].Get ("/api/v1/scraperUsers/" + apiKeyID , & scraperUsers )
207-
208- // Wait for the connections above to complete checking before we do this error check but do the request already so we don't have to wait for that
209- // If one of the connections has an error they will throw
210- wg .Wait ()
211-
212231 if err != nil {
232+ // Wait for the connections above to complete checking before we do this error check but do the request already so we don't have to wait for that
233+ // If one of the connections has an error they will throw
234+ wg .Wait ()
213235 log .Fatal (err )
214236 }
215237
216- return scraperUsers .Users
238+ if scraperUsers .ScraperPublicKey != "" && scraperUsers .ScraperPublicKey != decryptionKey .PublicBase64 {
239+ log .Fatal ("the env.json provided contains a diffrent public key than registered in RTCV, scraper users won't be able to be decrypted" )
240+ }
241+
242+ loginUsers := []EnvUser {}
243+ for _ , user := range scraperUsers .Users {
244+ if user .EncryptedPassword != "" {
245+ user .Password , err = decryptionKey .DecryptScraperPassword (user .EncryptedPassword )
246+ if err != nil {
247+ log .Fatal ("unable to decrypt password for user " + user .Username + ", error: " + err .Error ())
248+ }
249+ loginUsers = append (loginUsers , user )
250+ } else if user .Password != "" {
251+ loginUsers = append (loginUsers , user )
252+ } else {
253+ fmt .Println ("WARN: unusable login user" , user .Username )
254+ }
255+ loginUsers = append (loginUsers , user )
256+ }
257+
258+ wg .Wait ()
259+
260+ return loginUsers
217261}
0 commit comments