Added the /api/me/ API endpoint.
Moved a script block into an API endpoint. Split the gigantic switch in ServeHTTP into it's own function. Scripts should load more efficiently now.
This commit is contained in:
parent
18c5223143
commit
a9a1d667c0
|
@ -138,6 +138,9 @@ func panelUserCheck(w http.ResponseWriter, r *http.Request, user *User) (header
|
|||
}
|
||||
}
|
||||
|
||||
//h := w.Header()
|
||||
//h.Set("Content-Security-Policy", "default-src 'self'")
|
||||
|
||||
// TODO: GDPR. Add a global control panel notice warning the admins of staff members who don't have 2FA enabled
|
||||
stats.Users = Users.GlobalCount()
|
||||
stats.Groups = Groups.GlobalCount()
|
||||
|
|
|
@ -78,6 +78,39 @@ type WsJSONUser struct {
|
|||
Liked int
|
||||
}
|
||||
|
||||
func (user *User) Me() *MeUser {
|
||||
var groupID = user.Group
|
||||
if user.TempGroup != 0 {
|
||||
groupID = user.TempGroup
|
||||
}
|
||||
return &MeUser{user.ID, user.Link, user.Name, groupID, user.Active, user.IsMod, user.IsSuperMod, user.IsAdmin, user.IsBanned, user.Session, user.Avatar, user.MicroAvatar, user.Tag, user.Level, user.Score, user.Liked}
|
||||
}
|
||||
|
||||
// For when users need to see their own data, I've omitted some redundancies and less useful items, so we don't wind up sending them on every request
|
||||
type MeUser struct {
|
||||
ID int
|
||||
Link string
|
||||
Name string
|
||||
Group int
|
||||
Active bool
|
||||
IsMod bool
|
||||
IsSuperMod bool
|
||||
IsAdmin bool
|
||||
IsBanned bool
|
||||
|
||||
// TODO: Implement these as copies (might already be the case for Perms, but we'll want to look at it's definition anyway)
|
||||
//Perms Perms
|
||||
//PluginPerms map[string]bool
|
||||
|
||||
Session string
|
||||
Avatar string
|
||||
MicroAvatar string
|
||||
Tag string
|
||||
Level int
|
||||
Score int
|
||||
Liked int
|
||||
}
|
||||
|
||||
type UserStmts struct {
|
||||
activate *sql.Stmt
|
||||
changeGroup *sql.Stmt
|
||||
|
|
712
gen_router.go
712
gen_router.go
File diff suppressed because it is too large
Load Diff
|
@ -7,6 +7,7 @@ var alertList = [];
|
|||
var alertCount = 0;
|
||||
var moreTopicCount = 0;
|
||||
var conn;
|
||||
var me = {};
|
||||
var selectedTopics = [];
|
||||
var attachItemCallback = function(){}
|
||||
var hooks = {
|
||||
|
@ -196,7 +197,7 @@ function runWebSockets() {
|
|||
console.log("The WebSockets connection was opened");
|
||||
conn.send("page " + document.location.pathname + '\r');
|
||||
// TODO: Don't ask again, if it's denied. We could have a setting in the UCP which automatically requests this when someone flips desktop notifications on
|
||||
if(loggedIn) {
|
||||
if(me.User.ID > 0) {
|
||||
Notification.requestPermission();
|
||||
}
|
||||
}
|
||||
|
@ -258,14 +259,11 @@ function runWebSockets() {
|
|||
for(var i = 0; i < messages.length; i++) {
|
||||
let message = messages[i];
|
||||
//console.log("Message: ",message);
|
||||
let msgblocks = SplitN(message," ",3);
|
||||
if(msgblocks.length < 3) continue;
|
||||
if(message.startsWith("set ")) {
|
||||
//msgblocks = message.split(' ',3);
|
||||
let msgblocks = SplitN(message," ",3);
|
||||
if(msgblocks.length < 3) continue;
|
||||
document.querySelector(msgblocks[1]).innerHTML = msgblocks[2];
|
||||
} else if(message.startsWith("set-class ")) {
|
||||
let msgblocks = SplitN(message," ",3);
|
||||
if(msgblocks.length < 3) continue;
|
||||
document.querySelector(msgblocks[1]).className = msgblocks[2];
|
||||
}
|
||||
}
|
||||
|
@ -278,7 +276,7 @@ function len(item) {
|
|||
}
|
||||
|
||||
function loadScript(name, callback) {
|
||||
let url = "//" +siteURL+"/static/"+name
|
||||
let url = "//" +me.Site.URL+"/static/"+name
|
||||
$.getScript(url)
|
||||
.done(callback)
|
||||
.fail((e,xhr,settings,ex) => {
|
||||
|
@ -296,7 +294,7 @@ function DoNothingButPassBack(item) {
|
|||
}
|
||||
|
||||
function fetchPhrases() {
|
||||
fetch("//" +siteURL+"/api/phrases/?query=status,topic_list")
|
||||
fetch("//" +me.Site.URL+"/api/phrases/?query=status,topic_list")
|
||||
.then((resp) => resp.json())
|
||||
.then((data) => {
|
||||
console.log("loaded phrase endpoint data");
|
||||
|
@ -328,29 +326,44 @@ function fetchPhrases() {
|
|||
});
|
||||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
runHook("start_init");
|
||||
if(loggedIn) {
|
||||
let toLoad = 1;
|
||||
loadScript("template_topics_topic.js", () => {
|
||||
console.log("Loaded template_topics_topic.js");
|
||||
toLoad--;
|
||||
if(toLoad===0) fetchPhrases();
|
||||
(() => {
|
||||
runHook("pre_me");
|
||||
fetch("/api/me/")
|
||||
.then((resp) => resp.json())
|
||||
.then((data) => {
|
||||
console.log("loaded me endpoint data");
|
||||
console.log("data:",data);
|
||||
me = data;
|
||||
runHook("pre_init");
|
||||
|
||||
if(me.User.ID > 0) {
|
||||
let toLoad = 1;
|
||||
loadScript("template_topics_topic.js", () => {
|
||||
console.log("Loaded template_topics_topic.js");
|
||||
toLoad--;
|
||||
if(toLoad===0) fetchPhrases();
|
||||
});
|
||||
}
|
||||
|
||||
// We can only get away with this because template_alert has no phrases, otherwise it too would have to be part of the "dance", I miss Go concurrency :(
|
||||
loadScript("template_alert.js", () => {
|
||||
console.log("Loaded template_alert.js");
|
||||
alertsInitted = true;
|
||||
var alertMenuList = document.getElementsByClassName("menu_alerts");
|
||||
for(var i = 0; i < alertMenuList.length; i++) {
|
||||
loadAlerts(alertMenuList[i]);
|
||||
}
|
||||
});
|
||||
|
||||
if(window["WebSocket"]) runWebSockets();
|
||||
else conn = false;
|
||||
|
||||
$(document).ready(mainInit);
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
||||
// We can only get away with this because template_alert has no phrases, otherwise it too would have to be part of the "dance", I miss Go concurrency :(
|
||||
loadScript("template_alert.js", () => {
|
||||
console.log("Loaded template_alert.js");
|
||||
alertsInitted = true;
|
||||
var alertMenuList = document.getElementsByClassName("menu_alerts");
|
||||
for(var i = 0; i < alertMenuList.length; i++) {
|
||||
loadAlerts(alertMenuList[i]);
|
||||
}
|
||||
});
|
||||
|
||||
if(window["WebSocket"]) runWebSockets();
|
||||
else conn = false;
|
||||
function mainInit(){
|
||||
runHook("start_init");
|
||||
|
||||
$(".more_topics").click((event) => {
|
||||
event.preventDefault();
|
||||
|
@ -484,7 +497,7 @@ $(document).ready(function(){
|
|||
let formAction = $(this).closest('a').attr("href");
|
||||
//console.log("Form Action:", formAction);
|
||||
$.ajax({
|
||||
url: formAction + "?session=" + session,
|
||||
url: formAction + "?session=" + me.User.Session,
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
error: ajaxError,
|
||||
|
@ -559,7 +572,7 @@ $(document).ready(function(){
|
|||
var formAction = $(this).closest('a').attr("href");
|
||||
//console.log("Form Action:", formAction);
|
||||
//console.log(outData);
|
||||
$.ajax({ url: formAction + "?session=" + session, type:"POST", dataType:"json", data: outData, error: ajaxError });
|
||||
$.ajax({ url: formAction + "?session=" + me.User.Session, type:"POST", dataType:"json", data: outData, error: ajaxError });
|
||||
blockParent.find('.hide_on_edit').show();
|
||||
blockParent.find('.show_on_edit').hide();
|
||||
});
|
||||
|
@ -654,8 +667,8 @@ $(document).ready(function(){
|
|||
console.log("content.value", content.value);
|
||||
|
||||
let attachItem;
|
||||
if(content.value == "") attachItem = "//" + siteURL + "/attachs/" + hash + "." + ext;
|
||||
else attachItem = "\r\n//" + siteURL + "/attachs/" + hash + "." + ext;
|
||||
if(content.value == "") attachItem = "//" + me.Site.URL + "/attachs/" + hash + "." + ext;
|
||||
else attachItem = "\r\n//" + me.Site.URL + "/attachs/" + hash + "." + ext;
|
||||
content.value = content.value + attachItem;
|
||||
console.log("content.value", content.value);
|
||||
|
||||
|
@ -667,9 +680,9 @@ $(document).ready(function(){
|
|||
}
|
||||
reader.readAsDataURL(files[i]);
|
||||
}
|
||||
if(totalSize>maxRequestSize) {
|
||||
if(totalSize > me.Site.MaxRequestSize) {
|
||||
// TODO: Use a notice instead
|
||||
alert("You can't upload this much data at once, max: " + maxRequestSize);
|
||||
alert("You can't upload this much data at once, max: " + me.Site.MaxRequestSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -696,7 +709,7 @@ $(document).ready(function(){
|
|||
});
|
||||
|
||||
let bulkActionSender = function(action, selectedTopics, fragBit) {
|
||||
let url = "/topic/"+action+"/submit/"+fragBit+"?session=" + session;
|
||||
let url = "/topic/"+action+"/submit/"+fragBit+"?session=" + me.User.Session;
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: "POST",
|
||||
|
@ -746,7 +759,7 @@ $(document).ready(function(){
|
|||
$("#themeSelectorSelect").change(function(){
|
||||
console.log("Changing the theme to " + this.options[this.selectedIndex].getAttribute("val"));
|
||||
$.ajax({
|
||||
url: this.form.getAttribute("action") + "?session=" + session,
|
||||
url: this.form.getAttribute("action") + "?session=" + me.User.Session,
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
data: { "newTheme": this.options[this.selectedIndex].getAttribute("val"), isJs: "1" },
|
||||
|
@ -825,4 +838,4 @@ $(document).ready(function(){
|
|||
});
|
||||
|
||||
runHook("end_init");
|
||||
});
|
||||
};
|
||||
|
|
|
@ -645,6 +645,10 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
"routeMapEnum: ", routeMapEnum)
|
||||
}
|
||||
|
||||
router.routeSwitch(w, req, user, prefix, extraData)
|
||||
}
|
||||
|
||||
func (router *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user common.User, prefix string, extraData string) {
|
||||
var err common.RouteError
|
||||
switch(prefix) {` + out + `
|
||||
/*case "/sitemaps": // TODO: Count these views
|
||||
|
|
|
@ -14,6 +14,7 @@ func routes() {
|
|||
apiGroup := newRouteGroup("/api/",
|
||||
View("routeAPI", "/api/"),
|
||||
View("routeAPIPhrases", "/api/phrases/"), // TODO: Be careful with exposing the panel phrases here
|
||||
View("routes.APIMe", "/api/me/"),
|
||||
View("routeJSAntispam", "/api/watches/"),
|
||||
)
|
||||
addRouteGroup(apiGroup)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package routes
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
@ -220,3 +221,35 @@ func SitemapUsers(w http.ResponseWriter, r *http.Request) common.RouteError {
|
|||
w.Write([]byte("<sitemapindex xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n"))
|
||||
return nil
|
||||
}
|
||||
|
||||
type JsonMe struct {
|
||||
User *common.MeUser
|
||||
Site MeSite
|
||||
}
|
||||
|
||||
// We don't want to expose too much information about the site, so we'll make this a small subset of common.site
|
||||
type MeSite struct {
|
||||
URL string
|
||||
MaxRequestSize int
|
||||
}
|
||||
|
||||
// APIMe returns information about the current logged-in user
|
||||
// TODO: Find some way to stop intermediaries from doing compression to avoid the BREACH attack
|
||||
// TODO: Decouple site settings into a different API? I'd like to avoid having too many requests, if possible, maybe we can use a different name for this?
|
||||
func APIMe(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||
// TODO: Don't make this too JSON dependent so that we can swap in newer more efficient formats
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
// We don't want an intermediary accidentally caching this
|
||||
// TODO: Use this header anywhere with a user check?
|
||||
w.Header().Set("Cache-Control", "private")
|
||||
|
||||
me := JsonMe{(&user).Me(), MeSite{common.Site.URL, common.Site.MaxRequestSize}}
|
||||
|
||||
jsonBytes, err := json.Marshal(me)
|
||||
if err != nil {
|
||||
return common.InternalErrorJS(err, w, r)
|
||||
}
|
||||
w.Write(jsonBytes)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -11,12 +11,6 @@
|
|||
{{range .Header.Scripts}}
|
||||
<script type="text/javascript" src="/static/{{.}}"></script>
|
||||
{{end}}
|
||||
<script type="text/javascript">
|
||||
var session = "{{.CurrentUser.Session}}";
|
||||
var loggedIn = {{.CurrentUser.Loggedin}};
|
||||
var siteURL = "{{.Header.Site.URL}}";
|
||||
var maxRequestSize = "{{.Header.Site.MaxRequestSize}}";
|
||||
</script>
|
||||
<script type="text/javascript" src="/static/global.js"></script>
|
||||
<meta name="viewport" content="width=device-width,initial-scale = 1.0, maximum-scale=1.0,user-scalable=no" />
|
||||
{{if .Header.MetaDesc}}<meta name="description" content="{{.Header.MetaDesc}}" />{{end}}
|
||||
|
|
Loading…
Reference in New Issue