feature/dockerize-server into develop 3 years ago
| @ -0,0 +1,137 @@ | |||
| package Friends_test | |||
| import ( | |||
| "bytes" | |||
| "encoding/base64" | |||
| "encoding/json" | |||
| "fmt" | |||
| "net/http" | |||
| "testing" | |||
| "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database" | |||
| "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database/Seeder" | |||
| "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models" | |||
| "git.tovijaeschke.xyz/tovi/Capsule/Backend/Tests" | |||
| ) | |||
| func Test_AcceptFriendRequest(t *testing.T) { | |||
| client, ts, err := Tests.InitTestEnv() | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| u, err := Database.GetUserByUsername("test") | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| u2, err := Tests.InitTestCreateUser("test2") | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| key, err := Seeder.GenerateAesKey() | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| decodedPublicKey := Seeder.GetPubKey() | |||
| encPublicKey, err := key.AesEncrypt([]byte(Seeder.PublicKey)) | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| friendReq := Models.FriendRequest{ | |||
| UserID: u.ID, | |||
| FriendID: base64.StdEncoding.EncodeToString( | |||
| Seeder.EncryptWithPublicKey( | |||
| []byte(u2.ID.String()), | |||
| decodedPublicKey, | |||
| ), | |||
| ), | |||
| FriendUsername: base64.StdEncoding.EncodeToString( | |||
| Seeder.EncryptWithPublicKey( | |||
| []byte(u2.Username), | |||
| decodedPublicKey, | |||
| ), | |||
| ), | |||
| FriendPublicAsymmetricKey: base64.StdEncoding.EncodeToString( | |||
| encPublicKey, | |||
| ), | |||
| SymmetricKey: base64.StdEncoding.EncodeToString( | |||
| Seeder.EncryptWithPublicKey(key.Key, decodedPublicKey), | |||
| ), | |||
| } | |||
| err = Database.CreateFriendRequest(&friendReq) | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| friendReqResponse := Models.FriendRequest{ | |||
| UserID: u2.ID, | |||
| FriendID: base64.StdEncoding.EncodeToString( | |||
| Seeder.EncryptWithPublicKey( | |||
| []byte(u.ID.String()), | |||
| decodedPublicKey, | |||
| ), | |||
| ), | |||
| FriendUsername: base64.StdEncoding.EncodeToString( | |||
| Seeder.EncryptWithPublicKey( | |||
| []byte(u.Username), | |||
| decodedPublicKey, | |||
| ), | |||
| ), | |||
| FriendPublicAsymmetricKey: base64.StdEncoding.EncodeToString( | |||
| encPublicKey, | |||
| ), | |||
| SymmetricKey: base64.StdEncoding.EncodeToString( | |||
| Seeder.EncryptWithPublicKey(key.Key, decodedPublicKey), | |||
| ), | |||
| } | |||
| jsonStr, _ := json.Marshal(friendReqResponse) | |||
| req, _ := http.NewRequest( | |||
| "POST", | |||
| fmt.Sprintf( | |||
| "%s/api/v1/auth/friend_request/%s", | |||
| ts.URL, | |||
| friendReq.ID, | |||
| ), | |||
| bytes.NewBuffer(jsonStr), | |||
| ) | |||
| req.Header.Set("Content-Type", "application/json") | |||
| resp, err := client.Do(req) | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| if resp.StatusCode != http.StatusNoContent { | |||
| t.Errorf("Expected %d, recieved %d", http.StatusNoContent, resp.StatusCode) | |||
| return | |||
| } | |||
| var reqs []Models.FriendRequest | |||
| err = Database.DB.Find(&reqs).Error | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| for _, r := range reqs { | |||
| if r.AcceptedAt.Valid != true { | |||
| t.Errorf("Expected true, recieved false") | |||
| return | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,204 @@ | |||
| package Friends_test | |||
| import ( | |||
| "bytes" | |||
| "encoding/base64" | |||
| "encoding/json" | |||
| "net/http" | |||
| "testing" | |||
| "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database" | |||
| "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database/Seeder" | |||
| "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models" | |||
| "git.tovijaeschke.xyz/tovi/Capsule/Backend/Tests" | |||
| ) | |||
| func Test_CreateFriendRequest(t *testing.T) { | |||
| client, ts, err := Tests.InitTestEnv() | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| u, err := Database.GetUserByUsername("test") | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| u2, err := Tests.InitTestCreateUser("test2") | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| key, err := Seeder.GenerateAesKey() | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| decodedPublicKey := Seeder.GetPubKey() | |||
| encPublicKey, err := key.AesEncrypt([]byte(Seeder.PublicKey)) | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| friendReq := Models.FriendRequest{ | |||
| UserID: u.ID, | |||
| FriendID: base64.StdEncoding.EncodeToString( | |||
| Seeder.EncryptWithPublicKey( | |||
| []byte(u2.ID.String()), | |||
| decodedPublicKey, | |||
| ), | |||
| ), | |||
| FriendUsername: base64.StdEncoding.EncodeToString( | |||
| Seeder.EncryptWithPublicKey( | |||
| []byte(u2.Username), | |||
| decodedPublicKey, | |||
| ), | |||
| ), | |||
| FriendPublicAsymmetricKey: base64.StdEncoding.EncodeToString( | |||
| encPublicKey, | |||
| ), | |||
| SymmetricKey: base64.StdEncoding.EncodeToString( | |||
| Seeder.EncryptWithPublicKey(key.Key, decodedPublicKey), | |||
| ), | |||
| } | |||
| jsonStr, _ := json.Marshal(friendReq) | |||
| req, _ := http.NewRequest("POST", ts.URL+"/api/v1/auth/friend_request", bytes.NewBuffer(jsonStr)) | |||
| req.Header.Set("Content-Type", "application/json") | |||
| resp, err := client.Do(req) | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| if resp.StatusCode != http.StatusOK { | |||
| t.Errorf("Expected %d, recieved %d", http.StatusOK, resp.StatusCode) | |||
| return | |||
| } | |||
| var r Models.FriendRequest | |||
| err = Database.DB.First(&r).Error | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| if r.AcceptedAt.Valid == true { | |||
| t.Errorf("Expected false, recieved true") | |||
| return | |||
| } | |||
| } | |||
| func Test_CreateFriendRequestQrCode(t *testing.T) { | |||
| client, ts, err := Tests.InitTestEnv() | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| u, err := Database.GetUserByUsername("test") | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| u2, err := Tests.InitTestCreateUser("test2") | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| key, err := Seeder.GenerateAesKey() | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| decodedPublicKey := Seeder.GetPubKey() | |||
| encPublicKey, err := key.AesEncrypt([]byte(Seeder.PublicKey)) | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| friendReq := Models.FriendRequest{ | |||
| UserID: u.ID, | |||
| FriendID: base64.StdEncoding.EncodeToString( | |||
| Seeder.EncryptWithPublicKey( | |||
| []byte(u2.ID.String()), | |||
| decodedPublicKey, | |||
| ), | |||
| ), | |||
| FriendUsername: base64.StdEncoding.EncodeToString( | |||
| Seeder.EncryptWithPublicKey( | |||
| []byte(u2.Username), | |||
| decodedPublicKey, | |||
| ), | |||
| ), | |||
| FriendPublicAsymmetricKey: base64.StdEncoding.EncodeToString( | |||
| encPublicKey, | |||
| ), | |||
| SymmetricKey: base64.StdEncoding.EncodeToString( | |||
| Seeder.EncryptWithPublicKey(key.Key, decodedPublicKey), | |||
| ), | |||
| } | |||
| friendReq2 := Models.FriendRequest{ | |||
| UserID: u2.ID, | |||
| FriendID: base64.StdEncoding.EncodeToString( | |||
| Seeder.EncryptWithPublicKey( | |||
| []byte(u.ID.String()), | |||
| decodedPublicKey, | |||
| ), | |||
| ), | |||
| FriendUsername: base64.StdEncoding.EncodeToString( | |||
| Seeder.EncryptWithPublicKey( | |||
| []byte(u.Username), | |||
| decodedPublicKey, | |||
| ), | |||
| ), | |||
| FriendPublicAsymmetricKey: base64.StdEncoding.EncodeToString( | |||
| encPublicKey, | |||
| ), | |||
| SymmetricKey: base64.StdEncoding.EncodeToString( | |||
| Seeder.EncryptWithPublicKey(key.Key, decodedPublicKey), | |||
| ), | |||
| } | |||
| jsonStr, _ := json.Marshal([]Models.FriendRequest{friendReq, friendReq2}) | |||
| req, _ := http.NewRequest("POST", ts.URL+"/api/v1/auth/friend_request/qr_code", bytes.NewBuffer(jsonStr)) | |||
| req.Header.Set("Content-Type", "application/json") | |||
| resp, err := client.Do(req) | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| if resp.StatusCode != http.StatusOK { | |||
| t.Errorf("Expected %d, recieved %d", http.StatusOK, resp.StatusCode) | |||
| return | |||
| } | |||
| var r Models.FriendRequest | |||
| err = Database.DB.First(&r).Error | |||
| if err != nil { | |||
| t.Errorf("Expected nil, recieved %s", err.Error()) | |||
| return | |||
| } | |||
| if r.AcceptedAt.Valid == false { | |||
| t.Errorf("Expected true, recieved false") | |||
| return | |||
| } | |||
| } | |||
| @ -1,60 +0,0 @@ | |||
| package Friends | |||
| import ( | |||
| "encoding/json" | |||
| "io/ioutil" | |||
| "net/http" | |||
| "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database" | |||
| "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models" | |||
| "git.tovijaeschke.xyz/tovi/Capsule/Backend/Util" | |||
| ) | |||
| func FriendRequest(w http.ResponseWriter, r *http.Request) { | |||
| var ( | |||
| user Models.User | |||
| requestBody []byte | |||
| requestJson map[string]interface{} | |||
| friendID string | |||
| friendRequest Models.FriendRequest | |||
| ok bool | |||
| err error | |||
| ) | |||
| user, err = Util.GetUserById(w, r) | |||
| if err != nil { | |||
| http.Error(w, "Not Found", http.StatusNotFound) | |||
| return | |||
| } | |||
| requestBody, err = ioutil.ReadAll(r.Body) | |||
| if err != nil { | |||
| http.Error(w, "Not Found", http.StatusNotFound) | |||
| return | |||
| } | |||
| json.Unmarshal(requestBody, &requestJson) | |||
| if requestJson["id"] == nil { | |||
| http.Error(w, "Invalid Data", http.StatusBadRequest) | |||
| return | |||
| } | |||
| friendID, ok = requestJson["id"].(string) | |||
| if !ok { | |||
| http.Error(w, "Error", http.StatusInternalServerError) | |||
| return | |||
| } | |||
| friendRequest = Models.FriendRequest{ | |||
| UserID: user.ID, | |||
| FriendID: friendID, | |||
| } | |||
| err = Database.CreateFriendRequest(&friendRequest) | |||
| if requestJson["id"] == nil { | |||
| http.Error(w, "Error", http.StatusInternalServerError) | |||
| return | |||
| } | |||
| w.WriteHeader(http.StatusNoContent) | |||
| } | |||
| @ -0,0 +1,74 @@ | |||
| package Messages | |||
| import ( | |||
| "encoding/json" | |||
| "io/ioutil" | |||
| "net/http" | |||
| "git.tovijaeschke.xyz/tovi/Capsule/Backend/Database" | |||
| "git.tovijaeschke.xyz/tovi/Capsule/Backend/Models" | |||
| "github.com/gorilla/mux" | |||
| ) | |||
| type rawChangeMessageExpiry struct { | |||
| MessageExpiry string `json:"message_expiry"` | |||
| } | |||
| // ChangeUserMessageExpiry handles changing default message expiry for user | |||
| func ChangeConversationMessageExpiry(w http.ResponseWriter, r *http.Request) { | |||
| var ( | |||
| // user Models.User | |||
| changeMessageExpiry rawChangeMessageExpiry | |||
| conversationDetail Models.ConversationDetail | |||
| requestBody []byte | |||
| urlVars map[string]string | |||
| detailID string | |||
| ok bool | |||
| err error | |||
| ) | |||
| urlVars = mux.Vars(r) | |||
| detailID, ok = urlVars["detailID"] | |||
| if !ok { | |||
| http.Error(w, "Not Found", http.StatusNotFound) | |||
| return | |||
| } | |||
| conversationDetail, err = Database.GetConversationDetailByID(detailID) | |||
| if err != nil { | |||
| http.Error(w, "Not Found", http.StatusNotFound) | |||
| return | |||
| } | |||
| // Ignore error here, as middleware should handle auth | |||
| // TODO: Check if user in conversation | |||
| // user, _ = Auth.CheckCookieCurrentUser(w, r) | |||
| requestBody, err = ioutil.ReadAll(r.Body) | |||
| if err != nil { | |||
| http.Error(w, "Error", http.StatusInternalServerError) | |||
| return | |||
| } | |||
| err = json.Unmarshal(requestBody, &changeMessageExpiry) | |||
| if err != nil { | |||
| http.Error(w, "Error", http.StatusInternalServerError) | |||
| return | |||
| } | |||
| err = conversationDetail.MessageExpiryDefault.Scan(changeMessageExpiry.MessageExpiry) | |||
| if err != nil { | |||
| http.Error(w, "Error", http.StatusUnprocessableEntity) | |||
| return | |||
| } | |||
| err = Database.UpdateConversationDetail( | |||
| &conversationDetail, | |||
| ) | |||
| if err != nil { | |||
| http.Error(w, "Error", http.StatusInternalServerError) | |||
| return | |||
| } | |||
| w.WriteHeader(http.StatusNoContent) | |||
| } | |||
| @ -0,0 +1,16 @@ | |||
| FROM golang:1.19-alpine | |||
| RUN mkdir -p /go/src/git.tovijaeschke.xyz/Capsule/Backend | |||
| COPY ./ /go/src/git.tovijaeschke.xyz/Capsule/Backend | |||
| WORKDIR /go/src/git.tovijaeschke.xyz/Capsule/Backend | |||
| # For "go test" | |||
| RUN apk add gcc libc-dev | |||
| RUN go mod download | |||
| RUN go build -o /go/bin/capsule-server main.go | |||
| CMD [ "/go/bin/capsule-server" ] | |||
| @ -0,0 +1,70 @@ | |||
| package Models | |||
| import ( | |||
| "database/sql/driver" | |||
| "errors" | |||
| ) | |||
| // MessageExpiry holds values for how long messages should expire by default | |||
| type MessageExpiry []uint8 | |||
| const ( | |||
| // MessageExpiryFifteenMin expires after 15 minutes | |||
| MessageExpiryFifteenMin = "fifteen_min" | |||
| // MessageExpiryThirtyMin expires after 30 minutes | |||
| MessageExpiryThirtyMin = "thirty_min" | |||
| // MessageExpiryOneHour expires after one hour | |||
| MessageExpiryOneHour = "one_hour" | |||
| // MessageExpiryThreeHour expires after three hours | |||
| MessageExpiryThreeHour = "three_hour" | |||
| // MessageExpirySixHour expires after six hours | |||
| MessageExpirySixHour = "six_hour" | |||
| // MessageExpiryTwelveHour expires after twelve hours | |||
| MessageExpiryTwelveHour = "twelve_hour" | |||
| // MessageExpiryOneDay expires after one day | |||
| MessageExpiryOneDay = "one_day" | |||
| // MessageExpiryThreeDay expires after three days | |||
| MessageExpiryThreeDay = "three_day" | |||
| // MessageExpiryNoExpiry never expires | |||
| MessageExpiryNoExpiry = "no_expiry" | |||
| ) | |||
| // MessageExpiryValues list of all expiry values for validation | |||
| var MessageExpiryValues = []string{ | |||
| MessageExpiryFifteenMin, | |||
| MessageExpiryThirtyMin, | |||
| MessageExpiryOneHour, | |||
| MessageExpiryThreeHour, | |||
| MessageExpirySixHour, | |||
| MessageExpiryTwelveHour, | |||
| MessageExpiryOneDay, | |||
| MessageExpiryThreeDay, | |||
| MessageExpiryNoExpiry, | |||
| } | |||
| // Scan new value into MessageExpiry | |||
| func (e *MessageExpiry) Scan(value interface{}) error { | |||
| var ( | |||
| strValue = value.(string) | |||
| m string | |||
| ) | |||
| for _, m = range MessageExpiryValues { | |||
| if strValue != m { | |||
| continue | |||
| } | |||
| *e = MessageExpiry(strValue) | |||
| return nil | |||
| } | |||
| return errors.New("Invalid MessageExpiry value") | |||
| } | |||
| // Value gets value out of MessageExpiry column | |||
| func (e MessageExpiry) Value() (driver.Value, error) { | |||
| return string(e), nil | |||
| } | |||
| func (e MessageExpiry) String() string { | |||
| return string(e) | |||
| } | |||
| @ -1,105 +1,33 @@ | |||
| package Models | |||
| import ( | |||
| "database/sql/driver" | |||
| "errors" | |||
| "github.com/gofrs/uuid" | |||
| "gorm.io/gorm" | |||
| ) | |||
| // BeforeUpdate prevents updating the email if it has not changed | |||
| // BeforeUpdate prevents updating the username or email if it has not changed | |||
| // This stops a unique constraint error | |||
| func (u *User) BeforeUpdate(tx *gorm.DB) (err error) { | |||
| if !tx.Statement.Changed("Username") { | |||
| tx.Statement.Omit("Username") | |||
| } | |||
| return nil | |||
| if !tx.Statement.Changed("Email") { | |||
| tx.Statement.Omit("Email") | |||
| } | |||
| // MessageExpiry holds values for how long messages should expire by default | |||
| type MessageExpiry []uint8 | |||
| const ( | |||
| // MessageExpiryFifteenMin expires after 15 minutes | |||
| MessageExpiryFifteenMin = "fifteen_min" | |||
| // MessageExpiryThirtyMin expires after 30 minutes | |||
| MessageExpiryThirtyMin = "thirty_min" | |||
| // MessageExpiryOneHour expires after one hour | |||
| MessageExpiryOneHour = "one_hour" | |||
| // MessageExpiryThreeHour expires after three hours | |||
| MessageExpiryThreeHour = "three_hour" | |||
| // MessageExpirySixHour expires after six hours | |||
| MessageExpirySixHour = "six_hour" | |||
| // MessageExpiryTwelveHour expires after twelve hours | |||
| MessageExpiryTwelveHour = "twelve_hour" | |||
| // MessageExpiryOneDay expires after one day | |||
| MessageExpiryOneDay = "one_day" | |||
| // MessageExpiryThreeDay expires after three days | |||
| MessageExpiryThreeDay = "three_day" | |||
| // MessageExpiryNoExpiry never expires | |||
| MessageExpiryNoExpiry = "no_expiry" | |||
| ) | |||
| // MessageExpiryValues list of all expiry values for validation | |||
| var MessageExpiryValues = []string{ | |||
| MessageExpiryFifteenMin, | |||
| MessageExpiryThirtyMin, | |||
| MessageExpiryOneHour, | |||
| MessageExpiryThreeHour, | |||
| MessageExpirySixHour, | |||
| MessageExpiryTwelveHour, | |||
| MessageExpiryOneDay, | |||
| MessageExpiryThreeDay, | |||
| MessageExpiryNoExpiry, | |||
| } | |||
| // Scan new value into MessageExpiry | |||
| func (e *MessageExpiry) Scan(value interface{}) error { | |||
| var ( | |||
| strValue = value.(string) | |||
| m string | |||
| ) | |||
| for _, m = range MessageExpiryValues { | |||
| if strValue != m { | |||
| continue | |||
| } | |||
| *e = MessageExpiry(strValue) | |||
| return nil | |||
| } | |||
| return errors.New("Invalid MessageExpiry value") | |||
| } | |||
| // Value gets value out of MessageExpiry column | |||
| func (e MessageExpiry) Value() (driver.Value, error) { | |||
| return string(e), nil | |||
| } | |||
| func (e MessageExpiry) String() string { | |||
| return string(e) | |||
| } | |||
| // User holds user data | |||
| type User struct { | |||
| Base | |||
| Username string `gorm:"not null;unique" json:"username"` | |||
| Password string `gorm:"not null" json:"password"` | |||
| ConfirmPassword string `gorm:"-" json:"confirm_password"` | |||
| Email string ` json:"email"` | |||
| AsymmetricPrivateKey string `gorm:"not null" json:"asymmetric_private_key"` // Stored encrypted | |||
| AsymmetricPublicKey string `gorm:"not null" json:"asymmetric_public_key"` | |||
| SymmetricKey string `gorm:"not null" json:"symmetric_key"` // Stored encrypted | |||
| AttachmentID *uuid.UUID ` json:"attachment_id"` | |||
| Attachment Attachment ` json:"attachment"` | |||
| MessageExpiryDefault MessageExpiry `gorm:"default:no_expiry" json:"-" sql:"type:ENUM( | |||
| 'fifteen_min', | |||
| 'thirty_min', | |||
| 'one_hour', | |||
| 'three_hour', | |||
| 'six_hour', | |||
| 'twelve_hour', | |||
| 'one_day', | |||
| 'three_day' | |||
| )"` // Stored encrypted | |||
| MessageExpiryDefault MessageExpiry `gorm:"default:no_expiry" json:"-" sql:"type:ENUM('fifteen_min', 'thirty_min', 'one_hour', 'three_hour', 'six_hour', 'twelve_hour', 'one_day', 'three_day', 'no_expiry')"` // Stored encrypted | |||
| } | |||
| @ -0,0 +1,8 @@ | |||
| #!/bin/sh | |||
| while true; do | |||
| go build main.go | |||
| ./main & | |||
| PID=$! | |||
| inotifywait -r -e modify . | |||
| kill $PID | |||
| done | |||
| @ -1 +1,2 @@ | |||
| #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" | |||
| #include "Generated.xcconfig" | |||
| @ -1 +1,2 @@ | |||
| #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" | |||
| #include "Generated.xcconfig" | |||
| @ -0,0 +1,41 @@ | |||
| # Uncomment this line to define a global platform for your project | |||
| # platform :ios, '11.0' | |||
| # CocoaPods analytics sends network stats synchronously affecting flutter build latency. | |||
| ENV['COCOAPODS_DISABLE_STATS'] = 'true' | |||
| project 'Runner', { | |||
| 'Debug' => :debug, | |||
| 'Profile' => :release, | |||
| 'Release' => :release, | |||
| } | |||
| def flutter_root | |||
| generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) | |||
| unless File.exist?(generated_xcode_build_settings_path) | |||
| raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" | |||
| end | |||
| File.foreach(generated_xcode_build_settings_path) do |line| | |||
| matches = line.match(/FLUTTER_ROOT\=(.*)/) | |||
| return matches[1].strip if matches | |||
| end | |||
| raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" | |||
| end | |||
| require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) | |||
| flutter_ios_podfile_setup | |||
| target 'Runner' do | |||
| use_frameworks! | |||
| use_modular_headers! | |||
| flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) | |||
| end | |||
| post_install do |installer| | |||
| installer.pods_project.targets.each do |target| | |||
| flutter_additional_ios_build_settings(target) | |||
| end | |||
| end | |||
| @ -0,0 +1,59 @@ | |||
| PODS: | |||
| - Flutter (1.0.0) | |||
| - FMDB (2.7.5): | |||
| - FMDB/standard (= 2.7.5) | |||
| - FMDB/standard (2.7.5) | |||
| - image_picker_ios (0.0.1): | |||
| - Flutter | |||
| - MTBBarcodeScanner (5.0.11) | |||
| - path_provider_ios (0.0.1): | |||
| - Flutter | |||
| - qr_code_scanner (0.2.0): | |||
| - Flutter | |||
| - MTBBarcodeScanner | |||
| - shared_preferences_ios (0.0.1): | |||
| - Flutter | |||
| - sqflite (0.0.2): | |||
| - Flutter | |||
| - FMDB (>= 2.7.5) | |||
| DEPENDENCIES: | |||
| - Flutter (from `Flutter`) | |||
| - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) | |||
| - path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`) | |||
| - qr_code_scanner (from `.symlinks/plugins/qr_code_scanner/ios`) | |||
| - shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`) | |||
| - sqflite (from `.symlinks/plugins/sqflite/ios`) | |||
| SPEC REPOS: | |||
| trunk: | |||
| - FMDB | |||
| - MTBBarcodeScanner | |||
| EXTERNAL SOURCES: | |||
| Flutter: | |||
| :path: Flutter | |||
| image_picker_ios: | |||
| :path: ".symlinks/plugins/image_picker_ios/ios" | |||
| path_provider_ios: | |||
| :path: ".symlinks/plugins/path_provider_ios/ios" | |||
| qr_code_scanner: | |||
| :path: ".symlinks/plugins/qr_code_scanner/ios" | |||
| shared_preferences_ios: | |||
| :path: ".symlinks/plugins/shared_preferences_ios/ios" | |||
| sqflite: | |||
| :path: ".symlinks/plugins/sqflite/ios" | |||
| SPEC CHECKSUMS: | |||
| Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 | |||
| FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a | |||
| image_picker_ios: b786a5dcf033a8336a657191401bfdf12017dabb | |||
| MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb | |||
| path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02 | |||
| qr_code_scanner: bb67d64904c3b9658ada8c402e8b4d406d5d796e | |||
| shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad | |||
| sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904 | |||
| PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3 | |||
| COCOAPODS: 1.11.3 | |||