github.com/mattermosttest/mattermost-server/v5@v5.0.0-20200917143240-9dfa12e121f9/store/sqlstore/webhook_store.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package sqlstore 5 6 import ( 7 "database/sql" 8 9 "github.com/pkg/errors" 10 11 sq "github.com/Masterminds/squirrel" 12 "github.com/mattermost/mattermost-server/v5/einterfaces" 13 "github.com/mattermost/mattermost-server/v5/model" 14 "github.com/mattermost/mattermost-server/v5/store" 15 ) 16 17 type SqlWebhookStore struct { 18 SqlStore 19 metrics einterfaces.MetricsInterface 20 } 21 22 func (s SqlWebhookStore) ClearCaches() { 23 } 24 25 func newSqlWebhookStore(sqlStore SqlStore, metrics einterfaces.MetricsInterface) store.WebhookStore { 26 s := &SqlWebhookStore{ 27 SqlStore: sqlStore, 28 metrics: metrics, 29 } 30 31 for _, db := range sqlStore.GetAllConns() { 32 table := db.AddTableWithName(model.IncomingWebhook{}, "IncomingWebhooks").SetKeys(false, "Id") 33 table.ColMap("Id").SetMaxSize(26) 34 table.ColMap("UserId").SetMaxSize(26) 35 table.ColMap("ChannelId").SetMaxSize(26) 36 table.ColMap("TeamId").SetMaxSize(26) 37 table.ColMap("DisplayName").SetMaxSize(64) 38 table.ColMap("Description").SetMaxSize(500) 39 40 tableo := db.AddTableWithName(model.OutgoingWebhook{}, "OutgoingWebhooks").SetKeys(false, "Id") 41 tableo.ColMap("Id").SetMaxSize(26) 42 tableo.ColMap("Token").SetMaxSize(26) 43 tableo.ColMap("CreatorId").SetMaxSize(26) 44 tableo.ColMap("ChannelId").SetMaxSize(26) 45 tableo.ColMap("TeamId").SetMaxSize(26) 46 tableo.ColMap("TriggerWords").SetMaxSize(1024) 47 tableo.ColMap("CallbackURLs").SetMaxSize(1024) 48 tableo.ColMap("DisplayName").SetMaxSize(64) 49 tableo.ColMap("Description").SetMaxSize(500) 50 tableo.ColMap("ContentType").SetMaxSize(128) 51 tableo.ColMap("TriggerWhen").SetMaxSize(1) 52 tableo.ColMap("Username").SetMaxSize(64) 53 tableo.ColMap("IconURL").SetMaxSize(1024) 54 } 55 56 return s 57 } 58 59 func (s SqlWebhookStore) createIndexesIfNotExists() { 60 s.CreateIndexIfNotExists("idx_incoming_webhook_user_id", "IncomingWebhooks", "UserId") 61 s.CreateIndexIfNotExists("idx_incoming_webhook_team_id", "IncomingWebhooks", "TeamId") 62 s.CreateIndexIfNotExists("idx_outgoing_webhook_team_id", "OutgoingWebhooks", "TeamId") 63 64 s.CreateIndexIfNotExists("idx_incoming_webhook_update_at", "IncomingWebhooks", "UpdateAt") 65 s.CreateIndexIfNotExists("idx_incoming_webhook_create_at", "IncomingWebhooks", "CreateAt") 66 s.CreateIndexIfNotExists("idx_incoming_webhook_delete_at", "IncomingWebhooks", "DeleteAt") 67 68 s.CreateIndexIfNotExists("idx_outgoing_webhook_update_at", "OutgoingWebhooks", "UpdateAt") 69 s.CreateIndexIfNotExists("idx_outgoing_webhook_create_at", "OutgoingWebhooks", "CreateAt") 70 s.CreateIndexIfNotExists("idx_outgoing_webhook_delete_at", "OutgoingWebhooks", "DeleteAt") 71 } 72 73 func (s SqlWebhookStore) InvalidateWebhookCache(webhookId string) { 74 } 75 76 func (s SqlWebhookStore) SaveIncoming(webhook *model.IncomingWebhook) (*model.IncomingWebhook, error) { 77 78 if len(webhook.Id) > 0 { 79 return nil, store.NewErrInvalidInput("IncomingWebhook", "id", webhook.Id) 80 } 81 82 webhook.PreSave() 83 if err := webhook.IsValid(); err != nil { 84 return nil, err 85 } 86 87 if err := s.GetMaster().Insert(webhook); err != nil { 88 return nil, errors.Wrapf(err, "failed to save IncomingWebhook with id=%s", webhook.Id) 89 } 90 91 return webhook, nil 92 93 } 94 95 func (s SqlWebhookStore) UpdateIncoming(hook *model.IncomingWebhook) (*model.IncomingWebhook, error) { 96 hook.UpdateAt = model.GetMillis() 97 98 if _, err := s.GetMaster().Update(hook); err != nil { 99 return nil, errors.Wrapf(err, "failed to update IncomingWebhook with id=%s", hook.Id) 100 } 101 return hook, nil 102 } 103 104 func (s SqlWebhookStore) GetIncoming(id string, allowFromCache bool) (*model.IncomingWebhook, error) { 105 var webhook model.IncomingWebhook 106 if err := s.GetReplica().SelectOne(&webhook, "SELECT * FROM IncomingWebhooks WHERE Id = :Id AND DeleteAt = 0", map[string]interface{}{"Id": id}); err != nil { 107 if err == sql.ErrNoRows { 108 return nil, store.NewErrNotFound("IncomingWebhook", id) 109 } 110 return nil, errors.Wrapf(err, "failed to get IncomingWebhook with id=%s", id) 111 } 112 113 return &webhook, nil 114 } 115 116 func (s SqlWebhookStore) DeleteIncoming(webhookId string, time int64) error { 117 _, err := s.GetMaster().Exec("Update IncomingWebhooks SET DeleteAt = :DeleteAt, UpdateAt = :UpdateAt WHERE Id = :Id", map[string]interface{}{"DeleteAt": time, "UpdateAt": time, "Id": webhookId}) 118 if err != nil { 119 return errors.Wrapf(err, "failed to update IncomingWebhook with id=%s", webhookId) 120 } 121 122 return nil 123 } 124 125 func (s SqlWebhookStore) PermanentDeleteIncomingByUser(userId string) error { 126 _, err := s.GetMaster().Exec("DELETE FROM IncomingWebhooks WHERE UserId = :UserId", map[string]interface{}{"UserId": userId}) 127 if err != nil { 128 return errors.Wrapf(err, "failed to delete IncomingWebhook with userId=%s", userId) 129 } 130 131 return nil 132 } 133 134 func (s SqlWebhookStore) PermanentDeleteIncomingByChannel(channelId string) error { 135 _, err := s.GetMaster().Exec("DELETE FROM IncomingWebhooks WHERE ChannelId = :ChannelId", map[string]interface{}{"ChannelId": channelId}) 136 if err != nil { 137 return errors.Wrapf(err, "failed to delete IncomingWebhook with channelId=%s", channelId) 138 } 139 140 return nil 141 } 142 143 func (s SqlWebhookStore) GetIncomingList(offset, limit int) ([]*model.IncomingWebhook, error) { 144 return s.GetIncomingListByUser("", offset, limit) 145 } 146 147 func (s SqlWebhookStore) GetIncomingListByUser(userId string, offset, limit int) ([]*model.IncomingWebhook, error) { 148 var webhooks []*model.IncomingWebhook 149 150 query := s.getQueryBuilder(). 151 Select("*"). 152 From("IncomingWebhooks"). 153 Where(sq.Eq{"DeleteAt": int(0)}).Limit(uint64(limit)).Offset(uint64(offset)) 154 155 if len(userId) > 0 { 156 query = query.Where(sq.Eq{"UserId": userId}) 157 } 158 159 queryString, args, err := query.ToSql() 160 if err != nil { 161 return nil, errors.Wrap(err, "incoming_webhook_tosql") 162 } 163 164 if _, err := s.GetReplica().Select(&webhooks, queryString, args...); err != nil { 165 return nil, errors.Wrap(err, "failed to find IncomingWebhooks") 166 } 167 168 return webhooks, nil 169 170 } 171 172 func (s SqlWebhookStore) GetIncomingByTeamByUser(teamId string, userId string, offset, limit int) ([]*model.IncomingWebhook, error) { 173 var webhooks []*model.IncomingWebhook 174 175 query := s.getQueryBuilder(). 176 Select("*"). 177 From("IncomingWebhooks"). 178 Where(sq.And{ 179 sq.Eq{"TeamId": teamId}, 180 sq.Eq{"DeleteAt": int(0)}, 181 }).Limit(uint64(limit)).Offset(uint64(offset)) 182 183 if len(userId) > 0 { 184 query = query.Where(sq.Eq{"UserId": userId}) 185 } 186 187 queryString, args, err := query.ToSql() 188 if err != nil { 189 return nil, errors.Wrap(err, "incoming_webhook_tosql") 190 } 191 192 if _, err := s.GetReplica().Select(&webhooks, queryString, args...); err != nil { 193 return nil, errors.Wrapf(err, "failed to find IncomingWebhoook with teamId=%s", teamId) 194 } 195 196 return webhooks, nil 197 } 198 199 func (s SqlWebhookStore) GetIncomingByTeam(teamId string, offset, limit int) ([]*model.IncomingWebhook, error) { 200 return s.GetIncomingByTeamByUser(teamId, "", offset, limit) 201 } 202 203 func (s SqlWebhookStore) GetIncomingByChannel(channelId string) ([]*model.IncomingWebhook, error) { 204 var webhooks []*model.IncomingWebhook 205 206 if _, err := s.GetReplica().Select(&webhooks, "SELECT * FROM IncomingWebhooks WHERE ChannelId = :ChannelId AND DeleteAt = 0", map[string]interface{}{"ChannelId": channelId}); err != nil { 207 return nil, errors.Wrapf(err, "failed to find IncomingWebhooks with channelId=%s", channelId) 208 } 209 210 return webhooks, nil 211 } 212 213 func (s SqlWebhookStore) SaveOutgoing(webhook *model.OutgoingWebhook) (*model.OutgoingWebhook, error) { 214 if len(webhook.Id) > 0 { 215 return nil, store.NewErrInvalidInput("OutgoingWebhook", "id", webhook.Id) 216 } 217 218 webhook.PreSave() 219 if err := webhook.IsValid(); err != nil { 220 return nil, err 221 } 222 223 if err := s.GetMaster().Insert(webhook); err != nil { 224 return nil, errors.Wrapf(err, "failed to save OutgoingWebhook with id=%s", webhook.Id) 225 } 226 227 return webhook, nil 228 } 229 230 func (s SqlWebhookStore) GetOutgoing(id string) (*model.OutgoingWebhook, error) { 231 232 var webhook model.OutgoingWebhook 233 234 if err := s.GetReplica().SelectOne(&webhook, "SELECT * FROM OutgoingWebhooks WHERE Id = :Id AND DeleteAt = 0", map[string]interface{}{"Id": id}); err != nil { 235 if err == sql.ErrNoRows { 236 return nil, store.NewErrNotFound("OutgoingWebhook", id) 237 } 238 239 return nil, errors.Wrapf(err, "failed to get OutgoingWebhook with id=%s", id) 240 } 241 242 return &webhook, nil 243 } 244 245 func (s SqlWebhookStore) GetOutgoingListByUser(userId string, offset, limit int) ([]*model.OutgoingWebhook, error) { 246 var webhooks []*model.OutgoingWebhook 247 248 query := s.getQueryBuilder(). 249 Select("*"). 250 From("OutgoingWebhooks"). 251 Where(sq.And{ 252 sq.Eq{"DeleteAt": int(0)}, 253 }).Limit(uint64(limit)).Offset(uint64(offset)) 254 255 if len(userId) > 0 { 256 query = query.Where(sq.Eq{"CreatorId": userId}) 257 } 258 259 queryString, args, err := query.ToSql() 260 if err != nil { 261 return nil, errors.Wrap(err, "outgoing_webhook_tosql") 262 } 263 264 if _, err := s.GetReplica().Select(&webhooks, queryString, args...); err != nil { 265 return nil, errors.Wrap(err, "failed to find OutgoingWebhooks") 266 } 267 268 return webhooks, nil 269 } 270 271 func (s SqlWebhookStore) GetOutgoingList(offset, limit int) ([]*model.OutgoingWebhook, error) { 272 return s.GetOutgoingListByUser("", offset, limit) 273 274 } 275 276 func (s SqlWebhookStore) GetOutgoingByChannelByUser(channelId string, userId string, offset, limit int) ([]*model.OutgoingWebhook, error) { 277 var webhooks []*model.OutgoingWebhook 278 279 query := s.getQueryBuilder(). 280 Select("*"). 281 From("OutgoingWebhooks"). 282 Where(sq.And{ 283 sq.Eq{"ChannelId": channelId}, 284 sq.Eq{"DeleteAt": int(0)}, 285 }) 286 287 if len(userId) > 0 { 288 query = query.Where(sq.Eq{"CreatorId": userId}) 289 } 290 if limit >= 0 && offset >= 0 { 291 query = query.Limit(uint64(limit)).Offset(uint64(offset)) 292 } 293 294 queryString, args, err := query.ToSql() 295 if err != nil { 296 return nil, errors.Wrap(err, "outgoing_webhook_tosql") 297 } 298 299 if _, err := s.GetReplica().Select(&webhooks, queryString, args...); err != nil { 300 return nil, errors.Wrap(err, "failed to find OutgoingWebhooks") 301 } 302 303 return webhooks, nil 304 } 305 306 func (s SqlWebhookStore) GetOutgoingByChannel(channelId string, offset, limit int) ([]*model.OutgoingWebhook, error) { 307 return s.GetOutgoingByChannelByUser(channelId, "", offset, limit) 308 } 309 310 func (s SqlWebhookStore) GetOutgoingByTeamByUser(teamId string, userId string, offset, limit int) ([]*model.OutgoingWebhook, error) { 311 var webhooks []*model.OutgoingWebhook 312 313 query := s.getQueryBuilder(). 314 Select("*"). 315 From("OutgoingWebhooks"). 316 Where(sq.And{ 317 sq.Eq{"TeamId": teamId}, 318 sq.Eq{"DeleteAt": int(0)}, 319 }) 320 321 if len(userId) > 0 { 322 query = query.Where(sq.Eq{"CreatorId": userId}) 323 } 324 if limit >= 0 && offset >= 0 { 325 query = query.Limit(uint64(limit)).Offset(uint64(offset)) 326 } 327 328 queryString, args, err := query.ToSql() 329 if err != nil { 330 return nil, errors.Wrap(err, "outgoing_webhook_tosql") 331 } 332 333 if _, err := s.GetReplica().Select(&webhooks, queryString, args...); err != nil { 334 return nil, errors.Wrap(err, "failed to find OutgoingWebhooks") 335 } 336 337 return webhooks, nil 338 } 339 340 func (s SqlWebhookStore) GetOutgoingByTeam(teamId string, offset, limit int) ([]*model.OutgoingWebhook, error) { 341 return s.GetOutgoingByTeamByUser(teamId, "", offset, limit) 342 } 343 344 func (s SqlWebhookStore) DeleteOutgoing(webhookId string, time int64) error { 345 _, err := s.GetMaster().Exec("Update OutgoingWebhooks SET DeleteAt = :DeleteAt, UpdateAt = :UpdateAt WHERE Id = :Id", map[string]interface{}{"DeleteAt": time, "UpdateAt": time, "Id": webhookId}) 346 if err != nil { 347 return errors.Wrapf(err, "failed to update OutgoingWebhook with id=%s", webhookId) 348 } 349 350 return nil 351 } 352 353 func (s SqlWebhookStore) PermanentDeleteOutgoingByUser(userId string) error { 354 _, err := s.GetMaster().Exec("DELETE FROM OutgoingWebhooks WHERE CreatorId = :UserId", map[string]interface{}{"UserId": userId}) 355 if err != nil { 356 return errors.Wrapf(err, "failed to delete OutgoingWebhook with creatorId=%s", userId) 357 } 358 359 return nil 360 } 361 362 func (s SqlWebhookStore) PermanentDeleteOutgoingByChannel(channelId string) error { 363 _, err := s.GetMaster().Exec("DELETE FROM OutgoingWebhooks WHERE ChannelId = :ChannelId", map[string]interface{}{"ChannelId": channelId}) 364 if err != nil { 365 return errors.Wrapf(err, "failed to delete OutgoingWebhook with channelId=%s", channelId) 366 } 367 368 s.ClearCaches() 369 370 return nil 371 } 372 373 func (s SqlWebhookStore) UpdateOutgoing(hook *model.OutgoingWebhook) (*model.OutgoingWebhook, error) { 374 hook.UpdateAt = model.GetMillis() 375 376 if _, err := s.GetMaster().Update(hook); err != nil { 377 return nil, errors.Wrapf(err, "failed to update OutgoingWebhook with id=%s", hook.Id) 378 } 379 380 return hook, nil 381 } 382 383 func (s SqlWebhookStore) AnalyticsIncomingCount(teamId string) (int64, error) { 384 query := 385 `SELECT 386 COUNT(*) 387 FROM 388 IncomingWebhooks 389 WHERE 390 DeleteAt = 0` 391 392 if len(teamId) > 0 { 393 query += " AND TeamId = :TeamId" 394 } 395 396 v, err := s.GetReplica().SelectInt(query, map[string]interface{}{"TeamId": teamId}) 397 if err != nil { 398 return 0, errors.Wrap(err, "failed to count IncomingWebhooks") 399 } 400 401 return v, nil 402 } 403 404 func (s SqlWebhookStore) AnalyticsOutgoingCount(teamId string) (int64, error) { 405 query := 406 `SELECT 407 COUNT(*) 408 FROM 409 OutgoingWebhooks 410 WHERE 411 DeleteAt = 0` 412 413 if len(teamId) > 0 { 414 query += " AND TeamId = :TeamId" 415 } 416 417 v, err := s.GetReplica().SelectInt(query, map[string]interface{}{"TeamId": teamId}) 418 if err != nil { 419 return 0, errors.Wrap(err, "failed to count OutgoingWebhooks") 420 } 421 422 return v, nil 423 }