factory.go 12 KB

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