role.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. // Copyright (C) 2019 Nicola Murino
  2. //
  3. // This program is free software: you can redistribute it and/or modify
  4. // it under the terms of the GNU Affero General Public License as published
  5. // by the Free Software Foundation, version 3.
  6. //
  7. // This program is distributed in the hope that it will be useful,
  8. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. // GNU Affero General Public License for more details.
  11. //
  12. // You should have received a copy of the GNU Affero General Public License
  13. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. package dataprovider
  15. import (
  16. "encoding/json"
  17. "fmt"
  18. "github.com/drakkan/sftpgo/v2/internal/logger"
  19. "github.com/drakkan/sftpgo/v2/internal/util"
  20. )
  21. // Role defines an SFTPGo role.
  22. type Role struct {
  23. // Data provider unique identifier
  24. ID int64 `json:"id"`
  25. // Role name
  26. Name string `json:"name"`
  27. // optional description
  28. Description string `json:"description,omitempty"`
  29. // Creation time as unix timestamp in milliseconds
  30. CreatedAt int64 `json:"created_at"`
  31. // last update time as unix timestamp in milliseconds
  32. UpdatedAt int64 `json:"updated_at"`
  33. // list of admins associated with this role
  34. Admins []string `json:"admins,omitempty"`
  35. // list of usernames associated with this role
  36. Users []string `json:"users,omitempty"`
  37. }
  38. // RenderAsJSON implements the renderer interface used within plugins
  39. func (r *Role) RenderAsJSON(reload bool) ([]byte, error) {
  40. if reload {
  41. role, err := provider.roleExists(r.Name)
  42. if err != nil {
  43. providerLog(logger.LevelError, "unable to reload role before rendering as json: %v", err)
  44. return nil, err
  45. }
  46. return json.Marshal(role)
  47. }
  48. return json.Marshal(r)
  49. }
  50. func (r *Role) validate() error {
  51. if r.Name == "" {
  52. return util.NewI18nError(util.NewValidationError("name is mandatory"), util.I18nErrorNameRequired)
  53. }
  54. if len(r.Name) > 255 {
  55. return util.NewValidationError("name is too long, 255 is the maximum length allowed")
  56. }
  57. if config.NamingRules&1 == 0 && !usernameRegex.MatchString(r.Name) {
  58. return util.NewI18nError(
  59. util.NewValidationError(fmt.Sprintf("name %q is not valid, the following characters are allowed: a-zA-Z0-9-_.~", r.Name)),
  60. util.I18nErrorInvalidName,
  61. )
  62. }
  63. return nil
  64. }
  65. func (r *Role) getACopy() Role {
  66. users := make([]string, len(r.Users))
  67. copy(users, r.Users)
  68. admins := make([]string, len(r.Admins))
  69. copy(admins, r.Admins)
  70. return Role{
  71. ID: r.ID,
  72. Name: r.Name,
  73. Description: r.Description,
  74. CreatedAt: r.CreatedAt,
  75. UpdatedAt: r.UpdatedAt,
  76. Users: users,
  77. Admins: admins,
  78. }
  79. }