/
cloudfeedauth.go
180 lines (154 loc) · 6.88 KB
/
cloudfeedauth.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
package repositories
import (
"time"
"github.com/energietransitie/twomes-backoffice-api/internal/encryption"
"github.com/energietransitie/twomes-backoffice-api/internal/helpers"
"github.com/energietransitie/twomes-backoffice-api/twomes/cloudfeedauth"
"github.com/energietransitie/twomes-backoffice-api/twomes/device"
"gorm.io/gorm"
)
type CloudFeedAuthRepository struct {
db *gorm.DB
}
func NewCloudFeedAuthRepository(db *gorm.DB) *CloudFeedAuthRepository {
return &CloudFeedAuthRepository{
db: db,
}
}
// Database representation of [cloudfeedauth.CloudFeedAuth].
type CloudFeedAuthModel struct {
AccountID uint `gorm:"primaryKey;autoIncrement:false"`
CloudFeedID uint `gorm:"primaryKey;autoIncrement:false"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
// TODO: WARNING encrypted string encryption not yet implemented.
AccessToken encryption.EncryptedString
RefreshToken encryption.EncryptedString
Expiry time.Time
AuthGrantToken encryption.EncryptedString
}
// Set the name of the table in the database.
func (CloudFeedAuthModel) TableName() string {
return "cloud_feed_auth"
}
// Create a new CloudFeedAuthModel from a [twomes.cloudFeedAuth].
func MakeCloudFeedAuthModel(cloudFeedAuth cloudfeedauth.CloudFeedAuth) CloudFeedAuthModel {
return CloudFeedAuthModel{
AccountID: cloudFeedAuth.AccountID,
CloudFeedID: cloudFeedAuth.CloudFeedID,
AccessToken: encryption.EncryptedString(cloudFeedAuth.AccessToken),
RefreshToken: encryption.EncryptedString(cloudFeedAuth.RefreshToken),
Expiry: cloudFeedAuth.Expiry,
AuthGrantToken: encryption.EncryptedString(cloudFeedAuth.AuthGrantToken),
}
}
// Create a [cloudfeedauth.CloudFeedAuth] from an CloudFeedAuthModel.
func (m *CloudFeedAuthModel) fromModel() cloudfeedauth.CloudFeedAuth {
return cloudfeedauth.CloudFeedAuth{
AccountID: m.AccountID,
CloudFeedID: m.CloudFeedID,
AccessToken: string(m.AccessToken),
RefreshToken: string(m.RefreshToken),
Expiry: m.Expiry,
AuthGrantToken: string(m.AuthGrantToken),
}
}
func (r *CloudFeedAuthRepository) Find(cloudFeedAuth cloudfeedauth.CloudFeedAuth) (cloudfeedauth.CloudFeedAuth, error) {
cloudFeedAuthModel := MakeCloudFeedAuthModel(cloudFeedAuth)
err := r.db.Where(&cloudFeedAuthModel).First(&cloudFeedAuthModel).Error
return cloudFeedAuthModel.fromModel(), err
}
func (r *CloudFeedAuthRepository) FindOAuthInfo(accountID uint, cloudFeedID uint) (string, string, string, string, error) {
var result struct {
TokenURL string
RefreshToken string
ClientID string
ClientSecret string
}
err := r.db.Table("cloud_feed").Select("cloud_feed.token_url, cloud_feed_auth.refresh_token AS refresh_token, cloud_feed.client_id, cloud_feed.client_secret").Joins("JOIN cloud_feed_auth ON cloud_feed.id = cloud_feed_auth.cloud_feed_id").Where("cloud_feed_auth.account_id = ? AND cloud_feed_auth.cloud_feed_id = ?", accountID, cloudFeedID).Scan(&result).Error
return result.TokenURL, result.RefreshToken, result.ClientID, result.ClientSecret, err
}
func (r *CloudFeedAuthRepository) FindFirstTokenToExpire() (uint, uint, time.Time, error) {
var cloudFeedAuthModel CloudFeedAuthModel
err := r.db.Order("expiry ASC").Where("expiry <> ''").First(&cloudFeedAuthModel).Error
return cloudFeedAuthModel.AccountID, cloudFeedAuthModel.CloudFeedID, cloudFeedAuthModel.Expiry, err
}
func (r *CloudFeedAuthRepository) FindDevice(cloudFeedAuth cloudfeedauth.CloudFeedAuth) (*device.Device, error) {
var device DeviceModel
// err := r.db.Table("cloud_feed_auth").
// Select("device.*").
// Joins("JOIN cloud_feed ON cloud_feed_auth.cloud_feed_id = cloud_feed.id").
// Joins("JOIN device_type ON cloud_feed.name = device_type.name").
// Joins("JOIN device ON device_type.id = device.device_type_id").
// Joins("JOIN building ON device.building_id = building.id").
// Where("building.account_id = cloud_feed_auth.account_id AND cloud_feed_auth.account_id = ? AND cloud_feed_auth.cloud_feed_id = ?", cloudFeedAuth.AccountID, cloudFeedAuth.CloudFeedID).
// Order("cloud_feed_auth.account_id DESC").
// First(&device).
// Error
err := r.db.Model(&device).
Joins("JOIN device_type ON device_type.id = device.device_type_id").
Joins("JOIN cloud_feed ON cloud_feed.name = device_type.name").
Joins("JOIN cloud_feed_auth ON cloud_feed_auth.cloud_feed_id = cloud_feed.id").
Joins("JOIN building ON building.id = device.building_id").
Where("building.account_id = cloud_feed_auth.account_id AND cloud_feed_auth.account_id = ? AND cloud_feed_auth.cloud_feed_id = ?", cloudFeedAuth.AccountID, cloudFeedAuth.CloudFeedID).
First(&device).
Error
if err != nil {
return nil, err
}
d := device.fromModel()
return &d, nil
}
func (r *CloudFeedAuthRepository) GetAll() ([]cloudfeedauth.CloudFeedAuth, error) {
var cloudFeedAuths []cloudfeedauth.CloudFeedAuth
var cloudFeedAuthModels []CloudFeedAuthModel
err := r.db.Find(&cloudFeedAuthModels).Error
if err != nil {
return nil, err
}
for _, cloudFeedAuthModel := range cloudFeedAuthModels {
cloudFeedAuths = append(cloudFeedAuths, cloudFeedAuthModel.fromModel())
}
return cloudFeedAuths, nil
}
func (r *CloudFeedAuthRepository) Create(cloudFeedAuth cloudfeedauth.CloudFeedAuth) (cloudfeedauth.CloudFeedAuth, error) {
// First check if a soft deleted entry exists.
// We need to do this because we can't create a new one if one exists.
cfaCheck := CloudFeedAuthModel{}
err := r.db.Unscoped().Where(&CloudFeedAuthModel{
AccountID: cloudFeedAuth.AccountID,
CloudFeedID: cloudFeedAuth.CloudFeedID,
}).First(&cfaCheck).Error
// Return immediately if there is an error,
// except if the error was RecordNotFound.
if err != nil && !helpers.IsMySQLRecordNotFoundError(err) {
return cloudFeedAuth, err
}
// At this point we know that there are no errors,
// except maybe that the record was not found, so check.
if !helpers.IsMySQLRecordNotFoundError(err) {
// Record was found. Check if it was soft deleted.
if cfaCheck.DeletedAt.Valid {
// Record was soft deleted. Delete it so we can create a new one.
err := r.db.Unscoped().Delete(&cfaCheck).Error
if err != nil {
return cloudFeedAuth, err
}
}
}
// If we reach this, it means there was not previous record,
// or it was deleted, and we can just create a new one.
cloudFeedAuthModel := MakeCloudFeedAuthModel(cloudFeedAuth)
err = r.db.Create(&cloudFeedAuthModel).Error
return cloudFeedAuthModel.fromModel(), err
}
func (r *CloudFeedAuthRepository) Update(cloudFeedAuth cloudfeedauth.CloudFeedAuth) (cloudfeedauth.CloudFeedAuth, error) {
cloudFeedAuthModel := MakeCloudFeedAuthModel(cloudFeedAuth)
err := r.db.Model(&cloudFeedAuthModel).Updates(cloudFeedAuthModel).Error
return cloudFeedAuthModel.fromModel(), err
}
func (r *CloudFeedAuthRepository) Delete(cloudFeedAuth cloudfeedauth.CloudFeedAuth) error {
CloudFeedAuthModel := MakeCloudFeedAuthModel(cloudFeedAuth)
return r.db.Delete(&CloudFeedAuthModel).Error
}