package server import ( "sort" "code.severnaya.net/kordophone-mock/v2/data" "code.severnaya.net/kordophone-mock/v2/model" "github.com/rs/zerolog/log" ) const VERSION = "Kordophone-2.0" const ( AUTH_USERNAME = "test" AUTH_PASSWORD = "test" ) type Server struct { version string conversations []model.Conversation authTokens []model.AuthToken messageStore map[string][]model.Message } type AuthError struct { message string } func (e *AuthError) Error() string { return e.message } type DatabaseError struct { message string } func (e *DatabaseError) Error() string { return e.message } func NewServer() *Server { return &Server{ version: VERSION, conversations: []model.Conversation{}, authTokens: []model.AuthToken{}, messageStore: make(map[string][]model.Message), } } func (s *Server) Version() string { return s.version } func (s *Server) Conversations() []model.Conversation { return s.conversations } func (s *Server) SortedConversations() []model.Conversation { conversations := s.Conversations() sort.Slice(conversations, func(i, j int) bool { return conversations[i].Date.After(conversations[j].Date) }) return conversations } func (s *Server) ConversationForGUID(guid string) (*model.Conversation, error) { var conversation *model.Conversation = nil for i := range s.conversations { c := &s.conversations[i] if c.Guid == guid { conversation = c break } } if conversation != nil { return conversation, nil } return nil, &DatabaseError{message: "Conversation not found"} } func (s *Server) AddConversation(c model.Conversation) { s.conversations = append(s.conversations, c) } func (s *Server) PopulateWithTestData() { numConversations := 100 cs := make([]model.Conversation, numConversations) for i := 0; i < numConversations; i++ { cs[i] = data.GenerateRandomConversation() // Generate messages convo := &cs[i] var lastMessage model.Message for i := 0; i < 100; i++ { message := data.GenerateRandomMessage(convo.Participants) s.AppendMessageToConversation(convo, message) if lastMessage.Date.Before(message.Date) { lastMessage = message } } // Update last message preview convo.LastMessagePreview = lastMessage.Text } s.conversations = cs } func (s *Server) Authenticate(username string, password string) (*model.AuthToken, error) { if username != AUTH_USERNAME || password != AUTH_PASSWORD { return nil, &AuthError{"Invalid username or password"} } token, err := model.NewAuthToken(username) if err != nil { return nil, err } // Register for future auth s.registerAuthToken(token) return token, nil } func (s *Server) CheckBearerToken(token string) bool { return s.authenticateToken(token) } func (s *Server) MessagesForConversation(conversation *model.Conversation) []model.Message { messages := s.messageStore[conversation.Guid] sort.Slice(messages, func(i int, j int) bool { return messages[i].Date.Before(messages[j].Date) }) return messages } func (s *Server) AppendMessageToConversation(conversation *model.Conversation, message model.Message) { s.messageStore[conversation.Guid] = append(s.messageStore[conversation.Guid], message) } func (s *Server) SendMessage(conversation *model.Conversation, message model.Message) { s.AppendMessageToConversation(conversation, message) conversation.LastMessagePreview = message.Text conversation.Date = message.Date log.Info().EmbedObject(message).Msgf("Sent message to conversation %s", conversation.Guid) } // Private func (s *Server) registerAuthToken(token *model.AuthToken) { s.authTokens = append(s.authTokens, *token) } func (s *Server) authenticateToken(token string) bool { for _, t := range s.authTokens { if t.SignedToken == token { return true } } return false }