Skip to content

Commit

Permalink
Merge branch 'main' into homepage
Browse files Browse the repository at this point in the history
  • Loading branch information
DOOduneye committed Apr 16, 2024
2 parents 16de412 + 65b4378 commit b135a26
Show file tree
Hide file tree
Showing 44 changed files with 569 additions and 11,012 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
.DS_Store

# Cli
sac-cli
sac

# VSCode
.vscode
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@

### SAC CLI

To install use `./install.sh` and then run `sac-cli` to see all commands.
To install use `./install.sh` and then run `sac` to see all commands.

# Git Flow

Expand Down
2 changes: 1 addition & 1 deletion backend/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.22.2

require (
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5
github.com/aws/aws-sdk-go v1.50.5
github.com/aws/aws-sdk-go v1.51.21
github.com/garrettladley/mattress v0.4.0
github.com/go-playground/validator/v10 v10.19.0
github.com/goccy/go-json v0.10.2
Expand Down
4 changes: 2 additions & 2 deletions backend/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ github.com/awnumar/memcall v0.2.0 h1:sRaogqExTOOkkNwO9pzJsL8jrOV29UuUW7teRMfbqtI
github.com/awnumar/memcall v0.2.0/go.mod h1:S911igBPR9CThzd/hYQQmTc9SWNu3ZHIlCGaWsWsoJo=
github.com/awnumar/memguard v0.22.5 h1:PH7sbUVERS5DdXh3+mLo8FDcl1eIeVjJVYMnyuYpvuI=
github.com/awnumar/memguard v0.22.5/go.mod h1:+APmZGThMBWjnMlKiSM1X7MVpbIVewen2MTkqWkA/zE=
github.com/aws/aws-sdk-go v1.50.5 h1:H2Aadcgwr7a2aqS6ZwcE+l1mA6ZrTseYCvjw2QLmxIA=
github.com/aws/aws-sdk-go v1.50.5/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.51.21 h1:UrT6JC9R9PkYYXDZBV0qDKTualMr+bfK2eboTknMgbs=
github.com/aws/aws-sdk-go v1.51.21/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
Expand Down
39 changes: 39 additions & 0 deletions backend/src/auth/password.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package auth

import (
"regexp"
"strings"

"github.com/GenerateNU/sac/backend/src/constants"
"github.com/GenerateNU/sac/backend/src/errors"
)

func ValidatePassword(password string) *errors.Error {
if len(password) < 8 {
return &errors.InvalidPasswordNotLongEnough
}

if !hasDigit(password) {
return &errors.InvalidPasswordNoDigit
}

if !hasSpecialChar(password) {
return &errors.InvalidPasswordNoSpecialCharacter
}

return nil
}

func hasDigit(str string) bool {
return regexp.MustCompile(`[0-9]`).MatchString(str)
}

func hasSpecialChar(str string) bool {
for _, c := range constants.SPECIAL_CHARACTERS {
if strings.Contains(str, string(c)) {
return true
}
}

return false
}
2 changes: 2 additions & 0 deletions backend/src/constants/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ const (
ACCESS_TOKEN_EXPIRY time.Duration = time.Minute * 24 * 30 // temporary TODO: change to 60 minutes
REFRESH_TOKEN_EXPIRY time.Duration = time.Minute * 24 * 30
)

var SPECIAL_CHARACTERS = []rune{' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_', '`', '{', '|', '}', '~'} // see https://owasp.org/www-community/password-special-characters
1 change: 1 addition & 0 deletions backend/src/database/super.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func SuperUser(superUserSettings config.SuperUserSettings) (*models.User, *error
PasswordHash: *passwordHash,
FirstName: "SAC",
LastName: "Super",
Major0: models.ComputerScience,
College: models.KCCS,
GraduationCycle: models.May,
GraduationYear: 2025,
Expand Down
12 changes: 12 additions & 0 deletions backend/src/errors/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,16 @@ var (
StatusCode: fiber.StatusNotFound,
Message: "otp not found",
}
InvalidPasswordNotLongEnough = Error{
StatusCode: fiber.StatusBadRequest,
Message: "password must be at least 8 characters long",
}
InvalidPasswordNoDigit = Error{
StatusCode: fiber.StatusBadRequest,
Message: "password must contain at least one digit",
}
InvalidPasswordNoSpecialCharacter = Error{
StatusCode: fiber.StatusBadRequest,
Message: "password must contain at least one special character",
}
)
1 change: 0 additions & 1 deletion backend/src/file/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,6 @@ func (aw *AWSClient) UploadFile(folder string, fileHeader *multipart.FileHeader,
Body: bytes.NewReader(file),
})
if s3Err != nil {
fmt.Printf("Failed to upload data to %s/%s, %v\n", bucket, key, err)
return nil, &errors.FailedToUploadFile
}

Expand Down
2 changes: 0 additions & 2 deletions backend/src/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,6 @@ func main() {
configPath := flag.String("config", filepath.Join("..", "..", "config"), "Specify the path to the config directory")
useDevDotEnv := flag.Bool("use-dev-dot-env", true, "Specify if you want to use the .env.dev file")

fmt.Println("foo", *useDevDotEnv)

flag.Parse()

config, err := config.GetConfiguration(*configPath, *useDevDotEnv)
Expand Down
2 changes: 1 addition & 1 deletion backend/src/models/category.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package models
type Category struct {
Model

Name string `gorm:"type:varchar(255);unique" json:"name" validate:"required,max=255"`
Name string `gorm:"type:varchar(255);unique;not null" json:"name" validate:"required,max=255"`
Tag []Tag `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-" validate:"-"`
}

Expand Down
14 changes: 7 additions & 7 deletions backend/src/models/club.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ type Club struct {

SoftDeletedAt gorm.DeletedAt `gorm:"type:timestamptz;default:NULL" json:"-" validate:"-"`

Name string `gorm:"type:varchar(255)" json:"name" validate:"required,max=255"`
Preview string `gorm:"type:varchar(255)" json:"preview" validate:"required,max=255"`
Description string `gorm:"type:text" json:"description" validate:"required,http_url,s3_url,max=255"` // S3 URL
NumMembers int `gorm:"type:int" json:"num_members" validate:"required,min=1"`
IsRecruiting bool `gorm:"type:bool;default:false" json:"is_recruiting" validate:"required"`
RecruitmentCycle RecruitmentCycle `gorm:"type:varchar(255);default:always" json:"recruitment_cycle" validate:"required,max=255,oneof=fall spring fallSpring always"`
RecruitmentType RecruitmentType `gorm:"type:varchar(255);default:unrestricted" json:"recruitment_type" validate:"required,max=255,oneof=unrestricted tryout application"`
Name string `gorm:"type:varchar(255);not null" json:"name" validate:"required,max=255"`
Preview string `gorm:"type:varchar(255);not null" json:"preview" validate:"required,max=255"`
Description string `gorm:"type:text;not null" json:"description" validate:"required,http_url,s3_url,max=255"` // S3 URL
NumMembers int `gorm:"type:int;not null" json:"num_members" validate:"required,min=1"`
IsRecruiting bool `gorm:"type:bool;default:false;not null" json:"is_recruiting" validate:"required"`
RecruitmentCycle RecruitmentCycle `gorm:"type:varchar(255);default:always;not null" json:"recruitment_cycle" validate:"required,max=255,oneof=fall spring fallSpring always"`
RecruitmentType RecruitmentType `gorm:"type:varchar(255);default:unrestricted;not null" json:"recruitment_type" validate:"required,max=255,oneof=unrestricted tryout application"`
ApplicationLink string `gorm:"type:varchar(255);default:NULL" json:"application_link" validate:"required,max=255,http_url"`
Logo string `gorm:"type:varchar(255);default:NULL" json:"logo" validate:"omitempty,http_url,s3_url,max=255"` // S3 URL

Expand Down
14 changes: 7 additions & 7 deletions backend/src/models/comment.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ import "github.com/google/uuid"
type Comment struct {
Model

Question string `gorm:"type:varchar(255)" json:"question" validate:"required,max=255"`
Answer string `gorm:"type:varchar(255)" json:"answer" validate:",max=255"`
NumFoundHelpful uint `gorm:"type:int;default:0" json:"num_found_helpful" validate:"min=0"`
Question string `gorm:"type:varchar(255);not null" json:"question" validate:"required,max=255"`
Answer string `gorm:"type:varchar(255);not null" json:"answer" validate:",max=255"`
NumFoundHelpful uint `gorm:"type:int;default:0;not null" json:"num_found_helpful" validate:"min=0"`

AskedByID uuid.UUID `gorm:"type:uuid" json:"-" validate:"uuid4"`
AskedBy User `gorm:"foreignKey:AskedByID" json:"-" validate:"-"`
AskedByID uuid.UUID `gorm:"type:uuid;not null" json:"-" validate:"uuid4"`
AskedBy User `gorm:"foreignKey:AskedByID;not null" json:"-" validate:"-"`

ClubID uuid.UUID `gorm:"type:uuid" json:"-" validate:"uuid4"`
Club Club `gorm:"foreignKey:ClubID" json:"-" validate:"-"`
ClubID uuid.UUID `gorm:"type:uuid;not null" json:"-" validate:"uuid4"`
Club Club `gorm:"foreignKey:ClubID;not null" json:"-" validate:"-"`

AnsweredByID *uuid.UUID `gorm:"type:uuid" json:"-" validate:"uuid4"`
AnsweredBy *User `gorm:"foreignKey:AnsweredBy" json:"-" validate:"-"`
Expand Down
6 changes: 3 additions & 3 deletions backend/src/models/contact.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ func GetContentPrefix(contactType ContactType) string {
type Contact struct {
Model

Type ContactType `gorm:"type:varchar(255);uniqueIndex:idx_contact_type" json:"type" validate:"required,max=255,oneof=facebook instagram x linkedin youtube github slack discord email customSite"`
Content string `gorm:"type:varchar(255)" json:"content" validate:"required,max=255"`
Type ContactType `gorm:"type:varchar(255);uniqueIndex:idx_contact_type;not null" json:"type" validate:"required,max=255,oneof=facebook instagram x linkedin youtube github slack discord email customSite"`
Content string `gorm:"type:varchar(255);not null" json:"content" validate:"required,max=255"`

ClubID uuid.UUID `gorm:"foreignKey:ClubID;uniqueIndex:idx_contact_type" json:"-" validate:"uuid4"`
ClubID uuid.UUID `gorm:"foreignKey:ClubID;uniqueIndex:idx_contact_type;not null" json:"-" validate:"uuid4"`
}

type PutContactRequestBody struct {
Expand Down
44 changes: 22 additions & 22 deletions backend/src/models/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,16 @@ const (
type Event struct {
Model

Name string `gorm:"type:varchar(255)" json:"name" validate:"required,max=255"`
Preview string `gorm:"type:varchar(255)" json:"preview" validate:"required,max=255"`
Content string `gorm:"type:varchar(255)" json:"content" validate:"required,max=255"`
StartTime time.Time `gorm:"type:timestamptz" json:"start_time" validate:"required,ltecsfield=EndTime"`
EndTime time.Time `gorm:"type:timestamptz" json:"end_time" validate:"required,gtecsfield=StartTime"`
Location string `gorm:"type:varchar(255)" json:"location" validate:"required,max=255"`
EventType EventType `gorm:"type:varchar(255);default:open" json:"event_type" validate:"required,max=255,oneof=open membersOnly"`
IsRecurring bool `gorm:"not null;type:bool;default:false" json:"is_recurring" validate:"-"`

Host *uuid.UUID `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-" validate:"uuid4"`
Name string `gorm:"type:varchar(255);not null" json:"name" validate:"required,max=255"`
Preview string `gorm:"type:varchar(255);not null" json:"preview" validate:"required,max=255"`
Content string `gorm:"type:varchar(255);not null" json:"content" validate:"required,max=255"`
StartTime time.Time `gorm:"type:timestamptz;not null" json:"start_time" validate:"required,ltecsfield=EndTime"`
EndTime time.Time `gorm:"type:timestamptz;not null" json:"end_time" validate:"required,gtecsfield=StartTime"`
Location string `gorm:"type:varchar(255);not null" json:"location" validate:"required,max=255"`
EventType EventType `gorm:"type:varchar(255);default:open;not null" json:"event_type" validate:"required,max=255,oneof=open membersOnly"`
IsRecurring bool `gorm:"type:bool;default:false;not null" json:"is_recurring" validate:"-"`

Host *uuid.UUID `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;not null;" json:"-" validate:"uuid4"`
RSVP []User `gorm:"many2many:user_event_rsvps;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-" validate:"-"`
Waitlist []User `gorm:"many2many:user_event_waitlists;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-" validate:"-"`
Clubs []Club `gorm:"many2many:club_events;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-" validate:"-"`
Expand All @@ -43,28 +43,27 @@ type Event struct {

type Series struct {
Model
RecurringType RecurringType `gorm:"type:varchar(255);default:open" json:"recurring_type" validate:"max=255"`
MaxOccurrences int `gorm:"type:int" json:"max_occurrences" validate:"min=1"`
RecurringType RecurringType `gorm:"type:varchar(255);default:open;not null" json:"recurring_type" validate:"max=255"`
MaxOccurrences int `gorm:"type:int;not null" json:"max_occurrences" validate:"min=1"`
Events []Event `gorm:"many2many:event_series;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"events" validate:"-"`
}

// TODO: add not null to required fields on all gorm models
type EventSeries struct {
EventID uuid.UUID `gorm:"not null; type:uuid;" json:"event_id" validate:"uuid4"`
EventID uuid.UUID `gorm:"type:uuid;not null" json:"event_id" validate:"uuid4"`
Event Event `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-" validate:"-"`
SeriesID uuid.UUID `gorm:"not null; type:uuid;" json:"series_id" validate:"uuid4"`
SeriesID uuid.UUID `gorm:"type:uuid;not null" json:"series_id" validate:"uuid4"`
Series Series `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-" validate:"-"`
}

// Not needed for now, we will just update the events separately
type EventInstanceException struct {
Model
EventID int `gorm:"not null; type:uuid" json:"event_id" validate:"required"`
EventID int `gorm:"type:uuid;not null" json:"event_id" validate:"required"`
Event Event
IsRescheduled bool `gorm:"type:bool;default:true" json:"is_rescheduled" validate:"required"`
IsCancelled bool `gorm:"type:bool;default:false" json:"is_cancelled" validate:"required"`
StartTime time.Time `gorm:"type:timestamptz" json:"start_time" validate:"required,datetime,ltecsfield=EndTime"`
EndTime time.Time `gorm:"type:timestamptz" json:"end_time" validate:"required,datetime,gtecsfield=StartTime"`
IsRescheduled bool `gorm:"type:bool;default:true;not null" json:"is_rescheduled" validate:"required"`
IsCancelled bool `gorm:"type:bool;default:false;not null" json:"is_cancelled" validate:"required"`
StartTime time.Time `gorm:"type:timestamptz;not null" json:"start_time" validate:"required,datetime,ltecsfield=EndTime"`
EndTime time.Time `gorm:"type:timestamptz;not null" json:"end_time" validate:"required,datetime,gtecsfield=StartTime"`
}

// TODO We will likely need to update the create and update structs to account for recurring series
Expand All @@ -79,7 +78,7 @@ type CreateEventRequestBody struct {
IsRecurring *bool `json:"is_recurring" validate:"required"`

// TODO club/tag/notification logic
Host *uuid.UUID `json:"host" validate:"omitempty"`
Host *uuid.UUID `json:"host" validate:"required,uuid4"`
Clubs []Club `json:"-" validate:"omitempty"`
Tag []Tag `json:"-" validate:"omitempty"`
Notification []Notification `json:"-" validate:"omitempty"`
Expand All @@ -100,8 +99,9 @@ type UpdateEventRequestBody struct {
StartTime time.Time `json:"start_time" validate:"omitempty,ltecsfield=EndTime"`
EndTime time.Time `json:"end_time" validate:"omitempty,gtecsfield=StartTime"`
Location string `json:"location" validate:"omitempty,max=255"`
EventType EventType `gorm:"type:varchar(255);default:open" json:"event_type" validate:"omitempty,max=255,oneof=open membersOnly"`
EventType EventType `json:"event_type" validate:"omitempty,max=255,oneof=open membersOnly"`

Host *uuid.UUID `json:"host" validate:"omitempty"`
RSVP []User `json:"-" validate:"omitempty"`
Waitlist []User `json:"-" validate:"omitempty"`
Clubs []Club `json:"-" validate:"omitempty"`
Expand Down
10 changes: 5 additions & 5 deletions backend/src/models/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ type File struct {
OwnerID uuid.UUID `gorm:"uniqueIndex:compositeindex;index;not null;type:uuid" json:"-" validate:"required,uuid4"`
OwnerType string `gorm:"uniqueIndex:compositeindex;index;not null;type:varchar(255)" json:"-" validate:"required,max=255"`

FileName string `gorm:"type:varchar(255)" json:"file_name" validate:"required,max=255"`
FileType string `gorm:"type:varchar(255)" json:"file_type" validate:"required,max=255"`
FileSize int `gorm:"type:int" json:"file_size" validate:"required,min=1"`
FileURL string `gorm:"type:varchar(255)" json:"file_url" validate:"required,max=255"`
ObjectKey string `gorm:"type:varchar(255)" json:"object_key" validate:"required,max=255"`
FileName string `gorm:"type:varchar(255);not null" json:"file_name" validate:"required,max=255"`
FileType string `gorm:"type:varchar(255);not null" json:"file_type" validate:"required,max=255"`
FileSize int `gorm:"type:int;not null" json:"file_size" validate:"required,min=1"`
FileURL string `gorm:"type:varchar(255);not null" json:"file_url" validate:"required,max=255"`
ObjectKey string `gorm:"type:varchar(255);not null" json:"object_key" validate:"required,max=255"`
}

type CreateFileRequestBody struct {
Expand Down
4 changes: 2 additions & 2 deletions backend/src/models/follower.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ func (Follower) TableName() string {
}

type Follower struct {
UserID uuid.UUID `gorm:"type:uuid;not null;primaryKey" json:"user_id" validate:"required,uuid4"`
ClubID uuid.UUID `gorm:"type:uuid;not null;primaryKey" json:"club_id" validate:"required,uuid4"`
UserID uuid.UUID `gorm:"type:uuid;primaryKey;not null" json:"user_id" validate:"required,uuid4"`
ClubID uuid.UUID `gorm:"type:uuid;primaryKey;not null" json:"club_id" validate:"required,uuid4"`

Club *Club `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-" validate:"-"`
User *User `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-" validate:"-"`
Expand Down
6 changes: 3 additions & 3 deletions backend/src/models/membership.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ func (Membership) TableName() string {
}

type Membership struct {
UserID uuid.UUID `gorm:"type:uuid;not null;primaryKey" json:"user_id" validate:"required,uuid4"`
ClubID uuid.UUID `gorm:"type:uuid;not null;primaryKey" json:"club_id" validate:"required,uuid4"`
UserID uuid.UUID `gorm:"type:uuid;primaryKey;not null" json:"user_id" validate:"required,uuid4"`
ClubID uuid.UUID `gorm:"type:uuid;primaryKey;not null" json:"club_id" validate:"required,uuid4"`

Club *Club `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-" validate:"-"`
User *User `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-" validate:"-"`

MembershipType MembershipType `gorm:"type:varchar(255);not null;default:member" json:"membership_type" validate:"required,oneof=member admin"`
MembershipType MembershipType `gorm:"type:varchar(255);default:member;not null" json:"membership_type" validate:"required,oneof=member admin"`
}
14 changes: 7 additions & 7 deletions backend/src/models/notification.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ const (
type Notification struct {
Model

SendAt time.Time `gorm:"type:timestamptz" json:"send_at" validate:"required"`
Title string `gorm:"type:varchar(255)" json:"title" validate:"required,max=255"`
Content string `gorm:"type:varchar(255)" json:"content" validate:"required,max=255"`
DeepLink string `gorm:"type:varchar(255)" json:"deep_link" validate:"required,max=255"`
Icon string `gorm:"type:varchar(255)" json:"icon" validate:"required,http_url,max=255"` // S3 URL
SendAt time.Time `gorm:"type:timestamptz;not null" json:"send_at" validate:"required"`
Title string `gorm:"type:varchar(255);not null" json:"title" validate:"required,max=255"`
Content string `gorm:"type:varchar(255);not null" json:"content" validate:"required,max=255"`
DeepLink string `gorm:"type:varchar(255);not null" json:"deep_link" validate:"required,max=255"`
Icon string `gorm:"type:varchar(255);not null" json:"icon" validate:"required,s3_url,http_url,max=255"` // S3 URL

ReferenceID uuid.UUID `gorm:"type:int" json:"-" validate:"uuid4"`
ReferenceType NotificationType `gorm:"type:varchar(255)" json:"-" validate:"max=255"`
ReferenceID uuid.UUID `gorm:"type:int;not null" json:"-" validate:"uuid4"`
ReferenceType NotificationType `gorm:"type:varchar(255);not null" json:"-" validate:"max=255"`
}
Loading

0 comments on commit b135a26

Please sign in to comment.