diff --git a/api-activities.go b/api-activities.go index 0dc6634..f4b2581 100644 --- a/api-activities.go +++ b/api-activities.go @@ -86,7 +86,7 @@ func activitySourceToString(v ActivitySource) string { return "anon" } -// @Summary Get the requested set of activities, Paginated, filtered and sorted. +// @Summary Get the requested set of activities, Paginated, filtered and sorted. Is a POST because of some issues I was having, ideally should be a GET. // @Produce json // @Param GetActivitiesDTO body GetActivitiesDTO true "search parameters" // @Success 200 {object} GetActivitiesRespDTO diff --git a/api-invites.go b/api-invites.go index d8e53a1..34bbea7 100644 --- a/api-invites.go +++ b/api-invites.go @@ -11,7 +11,6 @@ import ( lm "github.com/hrfee/jfa-go/logmessages" "github.com/itchyny/timefmt-go" "github.com/lithammer/shortuuid/v3" - "github.com/timshannon/badgerhold/v4" ) const ( @@ -332,23 +331,8 @@ func (app *appContext) GetInvites(gc *gin.Context) { } invites = append(invites, invite) } - fullProfileList := app.storage.GetProfiles() - profiles := make([]string, len(fullProfileList)) - if len(profiles) != 0 { - defaultProfile := app.storage.GetDefaultProfile() - profiles[0] = defaultProfile.Name - i := 1 - if len(fullProfileList) > 1 { - app.storage.db.ForEach(badgerhold.Where("Name").Ne(profiles[0]), func(p *Profile) error { - profiles[i] = p.Name - i++ - return nil - }) - } - } resp := getInvitesDTO{ - Profiles: profiles, - Invites: invites, + Invites: invites, } gc.JSON(200, resp) } @@ -360,7 +344,7 @@ func (app *appContext) GetInvites(gc *gin.Context) { // @Failure 500 {object} stringResponse // @Router /invites/profile [post] // @Security Bearer -// @tags Profiles & Settings +// @tags Invites func (app *appContext) SetProfile(gc *gin.Context) { var req inviteProfileDTO gc.BindJSON(&req) diff --git a/api-profiles.go b/api-profiles.go index 0c7527f..5dbfc01 100644 --- a/api-profiles.go +++ b/api-profiles.go @@ -9,7 +9,34 @@ import ( "github.com/timshannon/badgerhold/v4" ) -// @Summary Get a list of profiles +// @Summary Get the names of all available profile. +// @Produce json +// @Success 200 {object} getProfileNamesDTO +// @Router /profiles/names [get] +// @Security Bearer +// @tags Profiles & Settings +func (app *appContext) GetProfileNames(gc *gin.Context) { + fullProfileList := app.storage.GetProfiles() + profiles := make([]string, len(fullProfileList)) + if len(profiles) != 0 { + defaultProfile := app.storage.GetDefaultProfile() + profiles[0] = defaultProfile.Name + i := 1 + if len(fullProfileList) > 1 { + app.storage.db.ForEach(badgerhold.Where("Name").Ne(profiles[0]), func(p *Profile) error { + profiles[i] = p.Name + i++ + return nil + }) + } + } + resp := getProfileNamesDTO{ + Profiles: profiles, + } + gc.JSON(200, resp) +} + +// @Summary Get all available profiles, indexed by their names. // @Produce json // @Success 200 {object} getProfilesDTO // @Router /profiles [get] diff --git a/api-users.go b/api-users.go index 010c1ab..43f7f67 100644 --- a/api-users.go +++ b/api-users.go @@ -20,7 +20,7 @@ import ( // @Produce json // @Param newUserDTO body newUserDTO true "New user request object" // @Success 200 -// @Router /users [post] +// @Router /user [post] // @Security Bearer // @tags Users func (app *appContext) NewUserFromAdmin(gc *gin.Context) { @@ -68,7 +68,7 @@ func (app *appContext) NewUserFromAdmin(gc *gin.Context) { // @Param newUserDTO body newUserDTO true "New user request object" // @Success 200 {object} PasswordValidation // @Failure 400 {object} PasswordValidation -// @Router /newUser [post] +// @Router /user/invite [post] // @tags Users func (app *appContext) NewUserFromInvite(gc *gin.Context) { /* @@ -709,7 +709,7 @@ func (app *appContext) SaveAnnounceTemplate(gc *gin.Context) { respondBool(200, true, gc) } -// @Summary Save an announcement as a template for use or editing later. +// @Summary Gets the names of each available announcement template. // @Produce json // @Success 200 {object} getAnnouncementsDTO // @Router /users/announce [get] diff --git a/models.go b/models.go index 157a41b..ee951c0 100644 --- a/models.go +++ b/models.go @@ -88,6 +88,10 @@ type getProfilesDTO struct { DefaultProfile string `json:"default_profile"` } +type getProfileNamesDTO struct { + Profiles []string `json:"profiles"` // List of profiles (name only) +} + type profileChangeDTO struct { Name string `json:"name" example:"DefaultProfile" binding:"required"` // Name of the profile } @@ -123,8 +127,7 @@ type inviteDTO struct { } type getInvitesDTO struct { - Profiles []string `json:"profiles"` // List of profiles (name only) - Invites []inviteDTO `json:"invites"` // List of invites + Invites []inviteDTO `json:"invites"` // List of invites } // fake DTO, if i actually used this the code would be a lot longer diff --git a/router.go b/router.go index 6d68d48..6316214 100644 --- a/router.go +++ b/router.go @@ -135,7 +135,7 @@ func (app *appContext) loadRoutes(router *gin.Engine) { router.GET(p+"/lang/:page/:file", app.ServeLang) router.GET(p+"/token/login", app.getTokenLogin) router.GET(p+"/token/refresh", app.getTokenRefresh) - router.POST(p+"/newUser", app.NewUserFromInvite) + router.POST(p+"/user/invite", app.NewUserFromInvite) router.Use(static.Serve(p+"/invite/", app.webFS)) router.GET(p+"/invite/:invCode", app.InviteProxy) if app.config.Section("captcha").Key("enabled").MustBool(false) { @@ -182,7 +182,7 @@ func (app *appContext) loadRoutes(router *gin.Engine) { router.POST(p+"/logout", app.Logout) api.DELETE(p+"/users", app.DeleteUsers) api.GET(p+"/users", app.GetUsers) - api.POST(p+"/users", app.NewUserFromAdmin) + api.POST(p+"/user", app.NewUserFromAdmin) api.POST(p+"/users/extend", app.ExtendExpiry) api.DELETE(p+"/users/:id/expiry", app.RemoveExpiry) api.POST(p+"/users/enable", app.EnableDisableUsers) @@ -191,6 +191,7 @@ func (app *appContext) loadRoutes(router *gin.Engine) { api.DELETE(p+"/invites", app.DeleteInvite) api.POST(p+"/invites/profile", app.SetProfile) api.GET(p+"/profiles", app.GetProfiles) + api.GET(p+"/profiles/names", app.GetProfileNames) api.POST(p+"/profiles/default", app.SetDefaultProfile) api.POST(p+"/profiles", app.CreateProfile) api.DELETE(p+"/profiles", app.DeleteProfile) diff --git a/ts/admin.ts b/ts/admin.ts index 333b9d1..86b540f 100644 --- a/ts/admin.ts +++ b/ts/admin.ts @@ -6,7 +6,7 @@ import { inviteList, createInvite } from "./modules/invites.js"; import { accountsList } from "./modules/accounts.js"; import { settingsList } from "./modules/settings.js"; import { activityList } from "./modules/activity.js"; -import { ProfileEditor } from "./modules/profiles.js"; +import { ProfileEditor, reloadProfileNames } from "./modules/profiles.js"; import { _get, _post, notificationBox, whichAnimationEvent, bindManualDropdowns } from "./modules/common.js"; import { Updater } from "./modules/update.js"; import { Login } from "./modules/login.js"; @@ -187,7 +187,7 @@ login.onLogin = () => { console.log("Logged in."); window.updater = new Updater(); // FIXME: Decide whether to autoload activity or not - window.invites.reload() + reloadProfileNames(); setInterval(() => { window.invites.reload(); accounts.reload(); }, 30*1000); const currentTab = window.tabs.current; switch (currentTab) { diff --git a/ts/form.ts b/ts/form.ts index 21a09cc..28bcd71 100644 --- a/ts/form.ts +++ b/ts/form.ts @@ -289,7 +289,7 @@ const create = (event: SubmitEvent) => { send.captcha_text = captcha.input.value; } } - _post("/newUser", send, (req: XMLHttpRequest) => { + _post("/user/invite", send, (req: XMLHttpRequest) => { if (req.readyState != 4) return; removeLoader(submitSpan); let vals = req.response as ValidatorRespDTO; diff --git a/ts/modules/accounts.ts b/ts/modules/accounts.ts index 512e047..ee4455f 100644 --- a/ts/modules/accounts.ts +++ b/ts/modules/accounts.ts @@ -1128,7 +1128,7 @@ export class accountsList { } } toggleLoader(button); - _post("/users", send, (req: XMLHttpRequest) => { + _post("/user", send, (req: XMLHttpRequest) => { if (req.readyState == 4) { toggleLoader(button); if (req.status == 200 || (req.response["user"] as boolean)) { diff --git a/ts/modules/invites.ts b/ts/modules/invites.ts index 673e078..0074aee 100644 --- a/ts/modules/invites.ts +++ b/ts/modules/invites.ts @@ -1,5 +1,6 @@ import { _get, _post, _delete, toClipboard, toggleLoader, toDateString } from "../modules/common.js"; import { DiscordUser, newDiscordSearch } from "../modules/discord.js"; +import { reloadProfileNames } from "../modules/profiles.js"; class DOMInvite implements Invite { updateNotify = (checkbox: HTMLInputElement) => { @@ -431,7 +432,6 @@ export class inviteList implements inviteList { private _list: HTMLDivElement; private _empty: boolean; // since invite reload sends profiles, this event it broadcast so the createInvite object can load them. - private _profileLoadEvent = new CustomEvent("profileLoadEvent"); invites: { [code: string]: DOMInvite }; @@ -502,13 +502,9 @@ export class inviteList implements inviteList { this._list.appendChild(domInv.asElement()); } - reload = (callback?: () => void) => _get("/invites", null, (req: XMLHttpRequest) => { + reload = (callback?: () => void) => reloadProfileNames(() => _get("/invites", null, (req: XMLHttpRequest) => { if (req.readyState == 4) { let data = req.response; - if (req.status == 200) { - window.availableProfiles = data["profiles"]; - document.dispatchEvent(this._profileLoadEvent); - } if (data["invites"] === undefined || data["invites"] == null || data["invites"].length == 0) { this.empty = true; return; @@ -534,7 +530,7 @@ export class inviteList implements inviteList { if (callback) callback(); } - }) + })); } export const inviteURLEvent = (id: string) => { return new CustomEvent(inviteList._inviteURLEvent, {"detail": id}) }; diff --git a/ts/modules/profiles.ts b/ts/modules/profiles.ts index cd8d5e2..bc68684 100644 --- a/ts/modules/profiles.ts +++ b/ts/modules/profiles.ts @@ -1,5 +1,13 @@ import { _get, _post, _delete, toggleLoader } from "../modules/common.js"; +export const profileLoadEvent = new CustomEvent("profileLoadEvent"); +export const reloadProfileNames = (then?: () => void) => _get("/profiles/names", null, (req: XMLHttpRequest) => { + if (req.readyState != 4) return; + window.availableProfiles = req.response["profiles"]; + document.dispatchEvent(profileLoadEvent); + if (then) then(); +}); + interface Profile { admin: boolean; libraries: string;