factory.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  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(
  48. deps.sqLiteUserStore,
  49. deps.sqLiteUserStore,
  50. deps.inMemorySessionManager,
  51. deps.inMemorySessionManager,
  52. )
  53. authService := foodgroup.NewAuthService(
  54. deps.cfg,
  55. deps.inMemorySessionManager,
  56. deps.chatSessionManager,
  57. deps.sqLiteUserStore,
  58. deps.hmacCookieBaker,
  59. deps.chatSessionManager,
  60. deps.sqLiteUserStore,
  61. deps.inMemorySessionManager,
  62. )
  63. oServiceService := foodgroup.NewOServiceServiceForAdmin(
  64. deps.cfg,
  65. logger,
  66. deps.inMemorySessionManager,
  67. deps.sqLiteUserStore,
  68. deps.inMemorySessionManager,
  69. )
  70. return oscar.AdminServer{
  71. AuthService: authService,
  72. Config: deps.cfg,
  73. Handler: handler.NewAdminRouter(handler.Handlers{
  74. AdminHandler: handler.NewAdminHandler(logger, adminService),
  75. OServiceHandler: handler.NewOServiceHandler(logger, oServiceService),
  76. }),
  77. Logger: logger,
  78. OnlineNotifier: oServiceService,
  79. ListenAddr: net.JoinHostPort("", deps.cfg.AdminPort),
  80. }
  81. }
  82. // Alert creates an OSCAR server for the Alert food group.
  83. func Alert(deps Container) oscar.BOSServer {
  84. logger := deps.logger.With("svc", "ALERT")
  85. sessionManager := state.NewInMemorySessionManager(logger)
  86. authService := foodgroup.NewAuthService(
  87. deps.cfg,
  88. sessionManager,
  89. deps.chatSessionManager,
  90. deps.sqLiteUserStore,
  91. deps.hmacCookieBaker,
  92. deps.chatSessionManager,
  93. deps.sqLiteUserStore,
  94. nil,
  95. )
  96. oServiceService := foodgroup.NewOServiceServiceForAlert(
  97. deps.cfg,
  98. logger,
  99. sessionManager,
  100. deps.sqLiteUserStore,
  101. sessionManager,
  102. )
  103. return oscar.BOSServer{
  104. AuthService: authService,
  105. Config: deps.cfg,
  106. Handler: handler.NewAlertRouter(handler.Handlers{
  107. AlertHandler: handler.NewAlertHandler(logger),
  108. OServiceHandler: handler.NewOServiceHandler(logger, oServiceService),
  109. }),
  110. Logger: logger,
  111. OnlineNotifier: oServiceService,
  112. ListenAddr: net.JoinHostPort("", deps.cfg.AlertPort),
  113. }
  114. }
  115. // Auth creates an OSCAR server for the Auth food group.
  116. func Auth(deps Container) oscar.AuthServer {
  117. logger := deps.logger.With("svc", "AUTH")
  118. authHandler := foodgroup.NewAuthService(
  119. deps.cfg,
  120. deps.inMemorySessionManager,
  121. deps.chatSessionManager,
  122. deps.sqLiteUserStore,
  123. deps.hmacCookieBaker,
  124. deps.chatSessionManager,
  125. deps.sqLiteUserStore,
  126. nil,
  127. )
  128. return oscar.AuthServer{
  129. AuthService: authHandler,
  130. Config: deps.cfg,
  131. Logger: logger,
  132. }
  133. }
  134. // BART creates an OSCAR server for the BART food group.
  135. func BART(deps Container) oscar.BOSServer {
  136. logger := deps.logger.With("svc", "BART")
  137. sessionManager := state.NewInMemorySessionManager(logger)
  138. bartService := foodgroup.NewBARTService(
  139. logger,
  140. deps.sqLiteUserStore,
  141. sessionManager,
  142. deps.sqLiteUserStore,
  143. sessionManager,
  144. )
  145. authService := foodgroup.NewAuthService(
  146. deps.cfg,
  147. sessionManager,
  148. deps.chatSessionManager,
  149. deps.sqLiteUserStore,
  150. deps.hmacCookieBaker,
  151. deps.chatSessionManager,
  152. deps.sqLiteUserStore,
  153. nil,
  154. )
  155. oServiceService := foodgroup.NewOServiceServiceForBART(
  156. deps.cfg,
  157. logger,
  158. sessionManager,
  159. deps.sqLiteUserStore,
  160. sessionManager,
  161. )
  162. return oscar.BOSServer{
  163. AuthService: authService,
  164. Config: deps.cfg,
  165. Handler: handler.NewBARTRouter(handler.Handlers{
  166. BARTHandler: handler.NewBARTHandler(logger, bartService),
  167. OServiceHandler: handler.NewOServiceHandler(logger, oServiceService),
  168. }),
  169. ListenAddr: net.JoinHostPort("", deps.cfg.BARTPort),
  170. Logger: logger,
  171. OnlineNotifier: oServiceService,
  172. }
  173. }
  174. // BOS creates an OSCAR server for the BOS food group.
  175. func BOS(deps Container) oscar.BOSServer {
  176. logger := deps.logger.With("svc", "BOS")
  177. authService := foodgroup.NewAuthService(
  178. deps.cfg,
  179. deps.inMemorySessionManager,
  180. deps.chatSessionManager,
  181. deps.sqLiteUserStore,
  182. deps.hmacCookieBaker,
  183. deps.chatSessionManager,
  184. deps.sqLiteUserStore,
  185. nil,
  186. )
  187. bartService := foodgroup.NewBARTService(
  188. logger,
  189. deps.sqLiteUserStore,
  190. deps.inMemorySessionManager,
  191. deps.sqLiteUserStore,
  192. deps.inMemorySessionManager,
  193. )
  194. buddyService := foodgroup.NewBuddyService(
  195. deps.inMemorySessionManager,
  196. deps.sqLiteUserStore,
  197. deps.sqLiteUserStore,
  198. deps.inMemorySessionManager,
  199. )
  200. chatNavService := foodgroup.NewChatNavService(logger, deps.sqLiteUserStore)
  201. feedbagService := foodgroup.NewFeedbagService(
  202. logger,
  203. deps.inMemorySessionManager,
  204. deps.sqLiteUserStore,
  205. deps.sqLiteUserStore,
  206. deps.sqLiteUserStore,
  207. deps.inMemorySessionManager,
  208. )
  209. permitDenyService := foodgroup.NewPermitDenyService(
  210. deps.sqLiteUserStore,
  211. deps.sqLiteUserStore,
  212. deps.inMemorySessionManager,
  213. deps.inMemorySessionManager,
  214. )
  215. icbmService := foodgroup.NewICBMService(
  216. deps.inMemorySessionManager,
  217. deps.sqLiteUserStore,
  218. deps.sqLiteUserStore,
  219. deps.inMemorySessionManager,
  220. )
  221. icqService := foodgroup.NewICQService(deps.inMemorySessionManager, deps.sqLiteUserStore, deps.sqLiteUserStore,
  222. logger, deps.inMemorySessionManager, deps.sqLiteUserStore)
  223. locateService := foodgroup.NewLocateService(
  224. deps.inMemorySessionManager,
  225. deps.sqLiteUserStore,
  226. deps.sqLiteUserStore,
  227. deps.inMemorySessionManager,
  228. )
  229. oServiceService := foodgroup.NewOServiceServiceForBOS(
  230. deps.cfg,
  231. deps.inMemorySessionManager,
  232. logger,
  233. deps.hmacCookieBaker,
  234. deps.sqLiteUserStore,
  235. deps.sqLiteUserStore,
  236. deps.inMemorySessionManager,
  237. )
  238. userLookupService := foodgroup.NewUserLookupService(deps.sqLiteUserStore)
  239. return oscar.BOSServer{
  240. AuthService: authService,
  241. BuddyListRegistry: deps.sqLiteUserStore,
  242. Config: deps.cfg,
  243. DepartureNotifier: buddyService,
  244. Handler: handler.NewBOSRouter(handler.Handlers{
  245. AlertHandler: handler.NewAlertHandler(logger),
  246. BARTHandler: handler.NewBARTHandler(logger, bartService),
  247. BuddyHandler: handler.NewBuddyHandler(logger, buddyService),
  248. ChatNavHandler: handler.NewChatNavHandler(chatNavService, logger),
  249. FeedbagHandler: handler.NewFeedbagHandler(logger, feedbagService),
  250. ICQHandler: handler.NewICQHandler(logger, icqService),
  251. ICBMHandler: handler.NewICBMHandler(logger, icbmService),
  252. LocateHandler: handler.NewLocateHandler(locateService, logger),
  253. OServiceHandler: handler.NewOServiceHandler(logger, oServiceService),
  254. PermitDenyHandler: handler.NewPermitDenyHandler(logger, permitDenyService),
  255. UserLookupHandler: handler.NewUserLookupHandler(logger, userLookupService),
  256. }),
  257. Logger: logger,
  258. OnlineNotifier: oServiceService,
  259. ListenAddr: net.JoinHostPort("", deps.cfg.BOSPort),
  260. }
  261. }
  262. // Chat creates an OSCAR server for the Chat food group.
  263. func Chat(deps Container) oscar.ChatServer {
  264. logger := deps.logger.With("svc", "CHAT")
  265. sessionManager := state.NewInMemorySessionManager(logger)
  266. authService := foodgroup.NewAuthService(
  267. deps.cfg,
  268. sessionManager,
  269. deps.chatSessionManager,
  270. deps.sqLiteUserStore,
  271. deps.hmacCookieBaker,
  272. deps.chatSessionManager,
  273. deps.sqLiteUserStore,
  274. nil,
  275. )
  276. chatService := foodgroup.NewChatService(deps.chatSessionManager)
  277. oServiceService := foodgroup.NewOServiceServiceForChat(
  278. deps.cfg,
  279. logger,
  280. sessionManager,
  281. deps.sqLiteUserStore,
  282. deps.chatSessionManager,
  283. deps.sqLiteUserStore,
  284. sessionManager,
  285. )
  286. return oscar.ChatServer{
  287. AuthService: authService,
  288. Config: deps.cfg,
  289. Handler: handler.NewChatRouter(handler.Handlers{
  290. ChatHandler: handler.NewChatHandler(logger, chatService),
  291. OServiceHandler: handler.NewOServiceHandler(logger, oServiceService),
  292. }),
  293. Logger: logger,
  294. OnlineNotifier: oServiceService,
  295. }
  296. }
  297. // ChatNav creates an OSCAR server for the ChatNav food group.
  298. func ChatNav(deps Container) oscar.BOSServer {
  299. logger := deps.logger.With("svc", "CHAT_NAV")
  300. sessionManager := state.NewInMemorySessionManager(logger)
  301. authService := foodgroup.NewAuthService(
  302. deps.cfg,
  303. sessionManager,
  304. deps.chatSessionManager,
  305. deps.sqLiteUserStore,
  306. deps.hmacCookieBaker,
  307. deps.chatSessionManager,
  308. deps.sqLiteUserStore,
  309. nil,
  310. )
  311. chatNavService := foodgroup.NewChatNavService(logger, deps.sqLiteUserStore)
  312. oServiceService := foodgroup.NewOServiceServiceForChatNav(
  313. deps.cfg,
  314. logger,
  315. sessionManager,
  316. deps.sqLiteUserStore,
  317. sessionManager,
  318. )
  319. return oscar.BOSServer{
  320. AuthService: authService,
  321. Config: deps.cfg,
  322. Handler: handler.NewChatNavRouter(handler.Handlers{
  323. ChatNavHandler: handler.NewChatNavHandler(chatNavService, logger),
  324. OServiceHandler: handler.NewOServiceHandler(logger, oServiceService),
  325. }),
  326. Logger: logger,
  327. OnlineNotifier: oServiceService,
  328. ListenAddr: net.JoinHostPort("", deps.cfg.ChatNavPort),
  329. }
  330. }
  331. // MgmtAPI creates an HTTP server for the management API.
  332. func MgmtAPI(deps Container) *http.Server {
  333. bld := config.Build{
  334. Version: version,
  335. Commit: commit,
  336. Date: date,
  337. }
  338. return http.NewManagementAPI(bld, deps.cfg, deps.sqLiteUserStore, deps.inMemorySessionManager, deps.sqLiteUserStore,
  339. deps.sqLiteUserStore, deps.chatSessionManager, deps.sqLiteUserStore, deps.inMemorySessionManager,
  340. deps.sqLiteUserStore, deps.sqLiteUserStore, deps.sqLiteUserStore, deps.sqLiteUserStore, deps.logger)
  341. }
  342. // ODir creates an OSCAR server for the ODir food group.
  343. func ODir(deps Container) oscar.BOSServer {
  344. logger := deps.logger.With("svc", "ODIR")
  345. sessionManager := state.NewInMemorySessionManager(logger)
  346. authService := foodgroup.NewAuthService(
  347. deps.cfg,
  348. sessionManager,
  349. deps.chatSessionManager,
  350. deps.sqLiteUserStore,
  351. deps.hmacCookieBaker,
  352. deps.chatSessionManager,
  353. deps.sqLiteUserStore,
  354. nil,
  355. )
  356. oServiceService := foodgroup.NewOServiceServiceForODir(deps.cfg, logger)
  357. oDirService := foodgroup.NewODirService(logger, deps.sqLiteUserStore)
  358. return oscar.BOSServer{
  359. AuthService: authService,
  360. Config: deps.cfg,
  361. Handler: handler.NewODirRouter(handler.Handlers{
  362. OServiceHandler: handler.NewOServiceHandler(logger, oServiceService),
  363. ODirHandler: handler.NewODirHandler(logger, oDirService),
  364. }),
  365. Logger: logger,
  366. OnlineNotifier: oServiceService,
  367. ListenAddr: net.JoinHostPort("", deps.cfg.ODirPort),
  368. }
  369. }