factory.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. package main
  2. import (
  3. "fmt"
  4. "log/slog"
  5. "net"
  6. "github.com/kelseyhightower/envconfig"
  7. "github.com/mk6i/retro-aim-server/config"
  8. "github.com/mk6i/retro-aim-server/foodgroup"
  9. "github.com/mk6i/retro-aim-server/server/http"
  10. "github.com/mk6i/retro-aim-server/server/oscar"
  11. "github.com/mk6i/retro-aim-server/server/oscar/handler"
  12. "github.com/mk6i/retro-aim-server/server/oscar/middleware"
  13. "github.com/mk6i/retro-aim-server/state"
  14. )
  15. // Container groups together common dependencies.
  16. type Container struct {
  17. adjListBuddyListStore *state.AdjListBuddyListStore
  18. cfg config.Config
  19. chatSessionManager *state.InMemoryChatSessionManager
  20. hmacCookieBaker state.HMACCookieBaker
  21. inMemorySessionManager *state.InMemorySessionManager
  22. logger *slog.Logger
  23. sqLiteUserStore *state.SQLiteUserStore
  24. }
  25. // MakeCommonDeps creates common dependencies used by the food group services.
  26. func MakeCommonDeps() (Container, error) {
  27. c := Container{}
  28. err := envconfig.Process("", &c.cfg)
  29. if err != nil {
  30. return c, fmt.Errorf("unable to process app config: %s\n", err.Error())
  31. }
  32. c.sqLiteUserStore, err = state.NewSQLiteUserStore(c.cfg.DBPath)
  33. if err != nil {
  34. return c, fmt.Errorf("unable to create feedbag store: %s\n", err.Error())
  35. }
  36. c.hmacCookieBaker, err = state.NewHMACCookieBaker()
  37. if err != nil {
  38. return c, fmt.Errorf("unable to create HMAC cookie baker: %s\n", err.Error())
  39. }
  40. c.logger = middleware.NewLogger(c.cfg)
  41. c.inMemorySessionManager = state.NewInMemorySessionManager(c.logger)
  42. c.chatSessionManager = state.NewInMemoryChatSessionManager(c.logger)
  43. c.adjListBuddyListStore = state.NewAdjListBuddyListStore()
  44. return c, nil
  45. }
  46. // Admin creates an OSCAR server for the Admin food group.
  47. func Admin(deps Container) oscar.AdminServer {
  48. logger := deps.logger.With("svc", "ADMIN")
  49. buddyService := foodgroup.NewBuddyService(deps.inMemorySessionManager, deps.sqLiteUserStore, deps.adjListBuddyListStore)
  50. adminService := foodgroup.NewAdminService(deps.inMemorySessionManager, deps.sqLiteUserStore, buddyService, deps.inMemorySessionManager)
  51. authService := foodgroup.NewAuthService(deps.cfg, deps.inMemorySessionManager, deps.chatSessionManager,
  52. deps.sqLiteUserStore, deps.adjListBuddyListStore, deps.hmacCookieBaker, deps.inMemorySessionManager,
  53. deps.sqLiteUserStore, deps.chatSessionManager, deps.sqLiteUserStore)
  54. oServiceService := foodgroup.NewOServiceServiceForAdmin(deps.cfg, logger, buddyService)
  55. return oscar.AdminServer{
  56. AuthService: authService,
  57. Config: deps.cfg,
  58. Handler: handler.NewAdminRouter(handler.Handlers{
  59. AdminHandler: handler.NewAdminHandler(logger, adminService),
  60. OServiceHandler: handler.NewOServiceHandler(logger, oServiceService),
  61. }),
  62. Logger: logger,
  63. OnlineNotifier: oServiceService,
  64. ListenAddr: net.JoinHostPort("", deps.cfg.AdminPort),
  65. }
  66. }
  67. // Alert creates an OSCAR server for the Alert food group.
  68. func Alert(deps Container) oscar.BOSServer {
  69. logger := deps.logger.With("svc", "ALERT")
  70. sessionManager := state.NewInMemorySessionManager(logger)
  71. authService := foodgroup.NewAuthService(deps.cfg, sessionManager, deps.chatSessionManager, deps.sqLiteUserStore,
  72. deps.adjListBuddyListStore, deps.hmacCookieBaker, sessionManager, deps.sqLiteUserStore, deps.chatSessionManager, deps.sqLiteUserStore)
  73. oServiceService := foodgroup.NewOServiceServiceForAlert(deps.cfg, logger, sessionManager, deps.adjListBuddyListStore, deps.sqLiteUserStore)
  74. return oscar.BOSServer{
  75. AuthService: authService,
  76. Config: deps.cfg,
  77. Handler: handler.NewAlertRouter(handler.Handlers{
  78. AlertHandler: handler.NewAlertHandler(logger),
  79. OServiceHandler: handler.NewOServiceHandler(logger, oServiceService),
  80. }),
  81. Logger: logger,
  82. OnlineNotifier: oServiceService,
  83. ListenAddr: net.JoinHostPort("", deps.cfg.AlertPort),
  84. }
  85. }
  86. // Auth creates an OSCAR server for the Auth food group.
  87. func Auth(deps Container) oscar.AuthServer {
  88. logger := deps.logger.With("svc", "AUTH")
  89. authHandler := foodgroup.NewAuthService(deps.cfg, deps.inMemorySessionManager, deps.chatSessionManager,
  90. deps.sqLiteUserStore, deps.adjListBuddyListStore, deps.hmacCookieBaker, nil, nil, deps.chatSessionManager, deps.sqLiteUserStore)
  91. return oscar.AuthServer{
  92. AuthService: authHandler,
  93. Config: deps.cfg,
  94. Logger: logger,
  95. }
  96. }
  97. // BART creates an OSCAR server for the BART food group.
  98. func BART(deps Container) oscar.BOSServer {
  99. logger := deps.logger.With("svc", "BART")
  100. sessionManager := state.NewInMemorySessionManager(logger)
  101. bartService := foodgroup.NewBARTService(logger, deps.sqLiteUserStore, sessionManager, deps.sqLiteUserStore, deps.adjListBuddyListStore)
  102. authService := foodgroup.NewAuthService(deps.cfg, sessionManager, deps.chatSessionManager, deps.sqLiteUserStore,
  103. deps.adjListBuddyListStore, deps.hmacCookieBaker, sessionManager, deps.sqLiteUserStore, deps.chatSessionManager, deps.sqLiteUserStore)
  104. oServiceService := foodgroup.NewOServiceServiceForBART(deps.cfg, logger, sessionManager, deps.adjListBuddyListStore, deps.sqLiteUserStore)
  105. return oscar.BOSServer{
  106. AuthService: authService,
  107. Config: deps.cfg,
  108. Handler: handler.NewBARTRouter(handler.Handlers{
  109. BARTHandler: handler.NewBARTHandler(logger, bartService),
  110. OServiceHandler: handler.NewOServiceHandler(logger, oServiceService),
  111. }),
  112. ListenAddr: net.JoinHostPort("", deps.cfg.BARTPort),
  113. Logger: logger,
  114. OnlineNotifier: oServiceService,
  115. }
  116. }
  117. // BOS creates an OSCAR server for the BOS food group.
  118. func BOS(deps Container) oscar.BOSServer {
  119. logger := deps.logger.With("svc", "BOS")
  120. authService := foodgroup.NewAuthService(deps.cfg, deps.inMemorySessionManager, deps.chatSessionManager,
  121. deps.sqLiteUserStore, deps.adjListBuddyListStore, deps.hmacCookieBaker, deps.inMemorySessionManager,
  122. deps.sqLiteUserStore, deps.chatSessionManager, deps.sqLiteUserStore)
  123. bartService := foodgroup.NewBARTService(logger, deps.sqLiteUserStore, deps.inMemorySessionManager,
  124. deps.sqLiteUserStore, deps.adjListBuddyListStore)
  125. buddyService := foodgroup.NewBuddyService(deps.inMemorySessionManager, deps.sqLiteUserStore, deps.adjListBuddyListStore)
  126. chatNavService := foodgroup.NewChatNavService(logger, deps.sqLiteUserStore)
  127. feedbagService := foodgroup.NewFeedbagService(logger, deps.inMemorySessionManager, deps.sqLiteUserStore,
  128. deps.sqLiteUserStore, deps.adjListBuddyListStore)
  129. permitDenyService := foodgroup.NewPermitDenyService()
  130. icbmService := foodgroup.NewICBMService(deps.inMemorySessionManager, deps.sqLiteUserStore,
  131. deps.adjListBuddyListStore, deps.sqLiteUserStore)
  132. icqService := foodgroup.NewICQService(deps.inMemorySessionManager, deps.sqLiteUserStore, deps.sqLiteUserStore,
  133. logger, deps.inMemorySessionManager, deps.sqLiteUserStore)
  134. locateService := foodgroup.NewLocateService(deps.inMemorySessionManager, deps.sqLiteUserStore, deps.sqLiteUserStore,
  135. deps.adjListBuddyListStore)
  136. oServiceService := foodgroup.NewOServiceServiceForBOS(deps.cfg, deps.inMemorySessionManager,
  137. deps.adjListBuddyListStore, logger, deps.hmacCookieBaker, deps.sqLiteUserStore, deps.sqLiteUserStore)
  138. userLookupService := foodgroup.NewUserLookupService(deps.sqLiteUserStore)
  139. return oscar.BOSServer{
  140. AuthService: authService,
  141. Config: deps.cfg,
  142. Handler: handler.NewBOSRouter(handler.Handlers{
  143. AlertHandler: handler.NewAlertHandler(logger),
  144. BARTHandler: handler.NewBARTHandler(logger, bartService),
  145. BuddyHandler: handler.NewBuddyHandler(logger, buddyService),
  146. ChatNavHandler: handler.NewChatNavHandler(chatNavService, logger),
  147. FeedbagHandler: handler.NewFeedbagHandler(logger, feedbagService),
  148. ICQHandler: handler.NewICQHandler(logger, icqService),
  149. ICBMHandler: handler.NewICBMHandler(logger, icbmService),
  150. LocateHandler: handler.NewLocateHandler(locateService, logger),
  151. OServiceHandler: handler.NewOServiceHandler(logger, oServiceService),
  152. PermitDenyHandler: handler.NewPermitDenyHandler(logger, permitDenyService),
  153. UserLookupHandler: handler.NewUserLookupHandler(logger, userLookupService),
  154. }),
  155. Logger: logger,
  156. OnlineNotifier: oServiceService,
  157. ListenAddr: net.JoinHostPort("", deps.cfg.BOSPort),
  158. }
  159. }
  160. // Chat creates an OSCAR server for the Chat food group.
  161. func Chat(deps Container) oscar.ChatServer {
  162. logger := deps.logger.With("svc", "CHAT")
  163. sessionManager := state.NewInMemorySessionManager(logger)
  164. authService := foodgroup.NewAuthService(deps.cfg, sessionManager, deps.chatSessionManager, deps.sqLiteUserStore,
  165. deps.adjListBuddyListStore, deps.hmacCookieBaker, sessionManager, deps.sqLiteUserStore, deps.chatSessionManager, deps.sqLiteUserStore)
  166. chatService := foodgroup.NewChatService(deps.chatSessionManager)
  167. oServiceService := foodgroup.NewOServiceServiceForChat(deps.cfg, logger, sessionManager, deps.adjListBuddyListStore,
  168. deps.sqLiteUserStore, deps.sqLiteUserStore, deps.chatSessionManager)
  169. return oscar.ChatServer{
  170. AuthService: authService,
  171. Config: deps.cfg,
  172. Handler: handler.NewChatRouter(handler.Handlers{
  173. ChatHandler: handler.NewChatHandler(logger, chatService),
  174. OServiceHandler: handler.NewOServiceHandler(logger, oServiceService),
  175. }),
  176. Logger: logger,
  177. OnlineNotifier: oServiceService,
  178. }
  179. }
  180. // ChatNav creates an OSCAR server for the ChatNav food group.
  181. func ChatNav(deps Container) oscar.BOSServer {
  182. logger := deps.logger.With("svc", "CHAT_NAV")
  183. sessionManager := state.NewInMemorySessionManager(logger)
  184. authService := foodgroup.NewAuthService(deps.cfg, sessionManager, deps.chatSessionManager, deps.sqLiteUserStore,
  185. deps.adjListBuddyListStore, deps.hmacCookieBaker, sessionManager, deps.sqLiteUserStore, deps.chatSessionManager,
  186. deps.sqLiteUserStore)
  187. chatNavService := foodgroup.NewChatNavService(logger, deps.sqLiteUserStore)
  188. oServiceService := foodgroup.NewOServiceServiceForChatNav(deps.cfg, logger, sessionManager, deps.adjListBuddyListStore, deps.sqLiteUserStore)
  189. return oscar.BOSServer{
  190. AuthService: authService,
  191. Config: deps.cfg,
  192. Handler: handler.NewChatNavRouter(handler.Handlers{
  193. ChatNavHandler: handler.NewChatNavHandler(chatNavService, logger),
  194. OServiceHandler: handler.NewOServiceHandler(logger, oServiceService),
  195. }),
  196. Logger: logger,
  197. OnlineNotifier: oServiceService,
  198. ListenAddr: net.JoinHostPort("", deps.cfg.ChatNavPort),
  199. }
  200. }
  201. // MgmtAPI creates an HTTP server for the management API.
  202. func MgmtAPI(deps Container) *http.Server {
  203. bld := config.Build{
  204. Version: version,
  205. Commit: commit,
  206. Date: date,
  207. }
  208. return http.NewManagementAPI(bld, deps.cfg, deps.sqLiteUserStore, deps.inMemorySessionManager, deps.sqLiteUserStore,
  209. deps.sqLiteUserStore, deps.chatSessionManager, deps.sqLiteUserStore, deps.inMemorySessionManager,
  210. deps.sqLiteUserStore, deps.sqLiteUserStore, deps.sqLiteUserStore, deps.sqLiteUserStore, deps.logger)
  211. }
  212. // ODir creates an OSCAR server for the ODir food group.
  213. func ODir(deps Container) oscar.BOSServer {
  214. logger := deps.logger.With("svc", "ODIR")
  215. sessionManager := state.NewInMemorySessionManager(logger)
  216. authService := foodgroup.NewAuthService(deps.cfg, sessionManager, deps.chatSessionManager, deps.sqLiteUserStore,
  217. deps.adjListBuddyListStore, deps.hmacCookieBaker, sessionManager, deps.sqLiteUserStore, deps.chatSessionManager,
  218. deps.sqLiteUserStore)
  219. oServiceService := foodgroup.NewOServiceServiceForODir(deps.cfg, logger)
  220. oDirService := foodgroup.NewODirService(logger, deps.sqLiteUserStore)
  221. return oscar.BOSServer{
  222. AuthService: authService,
  223. Config: deps.cfg,
  224. Handler: handler.NewODirRouter(handler.Handlers{
  225. OServiceHandler: handler.NewOServiceHandler(logger, oServiceService),
  226. ODirHandler: handler.NewODirHandler(logger, oDirService),
  227. }),
  228. Logger: logger,
  229. OnlineNotifier: oServiceService,
  230. ListenAddr: net.JoinHostPort("", deps.cfg.ODirPort),
  231. }
  232. }