mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-12-22 17:10:10 +00:00
Settings functional, start adding logging
Modifying settings also formats it nicely, as a bonus. Also we using shortuuid instead of normal uuidv4 now because its the same length as what I used in the python version.
This commit is contained in:
parent
024c0b56aa
commit
326b274329
80
api.go
80
api.go
@ -3,8 +3,9 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/knz/strtime"
|
"github.com/knz/strtime"
|
||||||
|
"github.com/lithammer/shortuuid/v3"
|
||||||
|
"gopkg.in/ini.v1"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -82,25 +83,24 @@ func (ctx *appContext) checkInvite(code string, used bool, username string) bool
|
|||||||
changed := false
|
changed := false
|
||||||
for invCode, data := range ctx.storage.invites {
|
for invCode, data := range ctx.storage.invites {
|
||||||
expiry := data.ValidTill
|
expiry := data.ValidTill
|
||||||
fmt.Println("Expiry:", expiry)
|
|
||||||
if current_time.After(expiry) {
|
if current_time.After(expiry) {
|
||||||
// NOTIFICATIONS
|
ctx.debug.Printf("Housekeeping: Deleting old invite %s", code)
|
||||||
notify := data.Notify
|
notify := data.Notify
|
||||||
if ctx.config.Section("notifications").Key("enabled").MustBool(false) && len(notify) != 0 {
|
if ctx.config.Section("notifications").Key("enabled").MustBool(false) && len(notify) != 0 {
|
||||||
|
ctx.debug.Printf("%s: Expiry notification", code)
|
||||||
for address, settings := range notify {
|
for address, settings := range notify {
|
||||||
if settings["notify-expiry"] {
|
if settings["notify-expiry"] {
|
||||||
if ctx.email.constructExpiry(invCode, data, ctx) != nil {
|
if ctx.email.constructExpiry(invCode, data, ctx) != nil {
|
||||||
fmt.Println("failed expiry construct")
|
ctx.err.Printf("%s: Failed to construct expiry notification", code)
|
||||||
|
} else if ctx.email.send(address, ctx) != nil {
|
||||||
|
ctx.err.Printf("%s: Failed to send expiry notification", code)
|
||||||
} else {
|
} else {
|
||||||
if ctx.email.send(address, ctx) != nil {
|
ctx.info.Printf("Sent expiry notification to %s", address)
|
||||||
fmt.Println("failed expiry send")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
changed = true
|
changed = true
|
||||||
fmt.Println("Deleting:", invCode)
|
|
||||||
delete(ctx.storage.invites, invCode)
|
delete(ctx.storage.invites, invCode)
|
||||||
} else if invCode == code {
|
} else if invCode == code {
|
||||||
match = true
|
match = true
|
||||||
@ -130,7 +130,6 @@ func (ctx *appContext) checkInvite(code string, used bool, username string) bool
|
|||||||
|
|
||||||
// Routes from now on!
|
// Routes from now on!
|
||||||
|
|
||||||
// POST
|
|
||||||
type newUserReq struct {
|
type newUserReq struct {
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
@ -141,7 +140,9 @@ type newUserReq struct {
|
|||||||
func (ctx *appContext) NewUser(gc *gin.Context) {
|
func (ctx *appContext) NewUser(gc *gin.Context) {
|
||||||
var req newUserReq
|
var req newUserReq
|
||||||
gc.BindJSON(&req)
|
gc.BindJSON(&req)
|
||||||
|
ctx.debug.Printf("%s: New user attempt", req.Code)
|
||||||
if !ctx.checkInvite(req.Code, false, "") {
|
if !ctx.checkInvite(req.Code, false, "") {
|
||||||
|
ctx.info.Printf("%s New user failed: invalid code", req.Code)
|
||||||
gc.JSON(401, map[string]bool{"success": false})
|
gc.JSON(401, map[string]bool{"success": false})
|
||||||
gc.Abort()
|
gc.Abort()
|
||||||
return
|
return
|
||||||
@ -155,18 +156,21 @@ func (ctx *appContext) NewUser(gc *gin.Context) {
|
|||||||
}
|
}
|
||||||
if !valid {
|
if !valid {
|
||||||
// 200 bcs idk what i did in js
|
// 200 bcs idk what i did in js
|
||||||
fmt.Println("invalid")
|
ctx.info.Printf("%s New user failed: Invalid password", req.Code)
|
||||||
gc.JSON(200, validation)
|
gc.JSON(200, validation)
|
||||||
gc.Abort()
|
gc.Abort()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
existingUser, _, _ := ctx.jf.userByName(req.Username, false)
|
existingUser, _, _ := ctx.jf.userByName(req.Username, false)
|
||||||
if existingUser != nil {
|
if existingUser != nil {
|
||||||
respond(401, fmt.Sprintf("User already exists named %s", req.Username), gc)
|
msg := fmt.Sprintf("User already exists named %s", req.Username)
|
||||||
|
ctx.info.Printf("%s New user failed: %s", req.Code, msg)
|
||||||
|
respond(401, msg, gc)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
user, status, err := ctx.jf.newUser(req.Username, req.Password)
|
user, status, err := ctx.jf.newUser(req.Username, req.Password)
|
||||||
if !(status == 200 || status == 204) || err != nil {
|
if !(status == 200 || status == 204) || err != nil {
|
||||||
|
ctx.err.Printf("%s New user failed: Jellyfin responded with %d", req.Code, status)
|
||||||
respond(401, "Unknown error", gc)
|
respond(401, "Unknown error", gc)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -176,9 +180,13 @@ func (ctx *appContext) NewUser(gc *gin.Context) {
|
|||||||
for address, settings := range invite.Notify {
|
for address, settings := range invite.Notify {
|
||||||
if settings["notify-creation"] {
|
if settings["notify-creation"] {
|
||||||
if ctx.email.constructCreated(req.Code, req.Username, req.Email, invite, ctx) != nil {
|
if ctx.email.constructCreated(req.Code, req.Username, req.Email, invite, ctx) != nil {
|
||||||
fmt.Println("created template failed")
|
ctx.err.Printf("%s: Failed to construct user creation notification", req.Code)
|
||||||
|
ctx.debug.Printf("%s: Error: %s", req.Code, err)
|
||||||
} else if ctx.email.send(address, ctx) != nil {
|
} else if ctx.email.send(address, ctx) != nil {
|
||||||
fmt.Println("created send failed")
|
ctx.err.Printf("%s: Failed to send user creation notification", req.Code)
|
||||||
|
ctx.debug.Printf("%s: Error: %s", req.Code, err)
|
||||||
|
} else {
|
||||||
|
ctx.info.Printf("%s: Sent user creation notification to %s", req.Code, address)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -190,13 +198,15 @@ func (ctx *appContext) NewUser(gc *gin.Context) {
|
|||||||
if len(ctx.storage.policy) != 0 {
|
if len(ctx.storage.policy) != 0 {
|
||||||
status, err = ctx.jf.setPolicy(id, ctx.storage.policy)
|
status, err = ctx.jf.setPolicy(id, ctx.storage.policy)
|
||||||
if !(status == 200 || status == 204) {
|
if !(status == 200 || status == 204) {
|
||||||
fmt.Printf("Failed to set user policy")
|
ctx.err.Printf("%s: Failed to set user policy: Code %d", req.Code, status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(ctx.storage.configuration) != 0 && len(ctx.storage.displayprefs) != 0 {
|
if len(ctx.storage.configuration) != 0 && len(ctx.storage.displayprefs) != 0 {
|
||||||
status, err = ctx.jf.setConfiguration(id, ctx.storage.configuration)
|
status, err = ctx.jf.setConfiguration(id, ctx.storage.configuration)
|
||||||
if (status == 200 || status == 204) && err != nil {
|
if (status == 200 || status == 204) && err == nil {
|
||||||
status, err = ctx.jf.setDisplayPreferences(id, ctx.storage.displayprefs)
|
status, err = ctx.jf.setDisplayPreferences(id, ctx.storage.displayprefs)
|
||||||
|
} else {
|
||||||
|
ctx.err.Printf("%s: Failed to set configuration template: Code %d", req.Code, status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ctx.config.Section("password_resets").Key("enabled").MustBool(false) {
|
if ctx.config.Section("password_resets").Key("enabled").MustBool(false) {
|
||||||
@ -213,18 +223,18 @@ type generateInviteReq struct {
|
|||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
MultipleUses bool `json:"multiple-uses"`
|
MultipleUses bool `json:"multiple-uses"`
|
||||||
NoLimit bool `json:"no-limit"`
|
NoLimit bool `json:"no-limit"`
|
||||||
RemainingUses int `json:remaining-uses"`
|
RemainingUses int `json:"remaining-uses"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctx *appContext) GenerateInvite(gc *gin.Context) {
|
func (ctx *appContext) GenerateInvite(gc *gin.Context) {
|
||||||
var req generateInviteReq
|
var req generateInviteReq
|
||||||
|
ctx.debug.Println("Generating new invite")
|
||||||
ctx.storage.loadInvites()
|
ctx.storage.loadInvites()
|
||||||
gc.BindJSON(&req)
|
gc.BindJSON(&req)
|
||||||
current_time := time.Now()
|
current_time := time.Now()
|
||||||
fmt.Println(req.Days, req.Hours, req.Minutes)
|
|
||||||
valid_till := current_time.AddDate(0, 0, req.Days)
|
valid_till := current_time.AddDate(0, 0, req.Days)
|
||||||
valid_till = valid_till.Add(time.Hour*time.Duration(req.Hours) + time.Minute*time.Duration(req.Minutes))
|
valid_till = valid_till.Add(time.Hour*time.Duration(req.Hours) + time.Minute*time.Duration(req.Minutes))
|
||||||
invite_code, _ := uuid.NewRandom()
|
invite_code := shortuuid.New()
|
||||||
var invite Invite
|
var invite Invite
|
||||||
invite.Created = current_time
|
invite.Created = current_time
|
||||||
if req.MultipleUses {
|
if req.MultipleUses {
|
||||||
@ -238,22 +248,27 @@ func (ctx *appContext) GenerateInvite(gc *gin.Context) {
|
|||||||
}
|
}
|
||||||
invite.ValidTill = valid_till
|
invite.ValidTill = valid_till
|
||||||
if req.Email != "" && ctx.config.Section("invite_emails").Key("enabled").MustBool(false) {
|
if req.Email != "" && ctx.config.Section("invite_emails").Key("enabled").MustBool(false) {
|
||||||
|
ctx.debug.Printf("%s: Sending invite email", invite_code)
|
||||||
invite.Email = req.Email
|
invite.Email = req.Email
|
||||||
if err := ctx.email.constructInvite(invite_code.String(), invite, ctx); err != nil {
|
if err := ctx.email.constructInvite(invite_code, invite, ctx); err != nil {
|
||||||
fmt.Println("error sending:", err)
|
|
||||||
invite.Email = fmt.Sprintf("Failed to send to %s", req.Email)
|
invite.Email = fmt.Sprintf("Failed to send to %s", req.Email)
|
||||||
|
ctx.err.Printf("%s: Failed to construct invite email", invite_code)
|
||||||
|
ctx.debug.Printf("%s: Error: %s", invite_code, err)
|
||||||
} else if err := ctx.email.send(req.Email, ctx); err != nil {
|
} else if err := ctx.email.send(req.Email, ctx); err != nil {
|
||||||
fmt.Println("error sending:", err)
|
|
||||||
invite.Email = fmt.Sprintf("Failed to send to %s", req.Email)
|
invite.Email = fmt.Sprintf("Failed to send to %s", req.Email)
|
||||||
|
ctx.err.Printf("%s: %s", invite_code, invite.Email)
|
||||||
|
ctx.debug.Printf("%s: Error: %s", invite_code, err)
|
||||||
|
} else {
|
||||||
|
ctx.info.Printf("%s: Sent invite email to %s", invite_code, req.Email)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx.storage.invites[invite_code.String()] = invite
|
ctx.storage.invites[invite_code] = invite
|
||||||
fmt.Println("INVITES FROM API:", ctx.storage.invites)
|
|
||||||
ctx.storage.storeInvites()
|
ctx.storage.storeInvites()
|
||||||
fmt.Println("New inv")
|
|
||||||
gc.JSON(200, map[string]bool{"success": true})
|
gc.JSON(200, map[string]bool{"success": true})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// logged up to here!
|
||||||
|
|
||||||
func (ctx *appContext) GetInvites(gc *gin.Context) {
|
func (ctx *appContext) GetInvites(gc *gin.Context) {
|
||||||
current_time := time.Now()
|
current_time := time.Now()
|
||||||
// checking one checks all of them
|
// checking one checks all of them
|
||||||
@ -494,3 +509,20 @@ func (ctx *appContext) GetConfig(gc *gin.Context) {
|
|||||||
}
|
}
|
||||||
gc.JSON(200, resp)
|
gc.JSON(200, resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ctx *appContext) ModifyConfig(gc *gin.Context) {
|
||||||
|
var req map[string]interface{}
|
||||||
|
gc.BindJSON(&req)
|
||||||
|
tempConfig, _ := ini.Load(ctx.config_path)
|
||||||
|
for section, settings := range req {
|
||||||
|
_, err := tempConfig.GetSection(section)
|
||||||
|
if section != "restart-program" && err == nil {
|
||||||
|
for setting, value := range settings.(map[string]interface{}) {
|
||||||
|
tempConfig.Section(section).Key(setting).SetValue(value.(string))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tempConfig.SaveTo(ctx.config_path)
|
||||||
|
gc.JSON(200, map[string]bool{"success": true})
|
||||||
|
ctx.loadConfig()
|
||||||
|
}
|
||||||
|
14
auth.go
14
auth.go
@ -5,7 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/dgrijalva/jwt-go"
|
"github.com/dgrijalva/jwt-go"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/google/uuid"
|
"github.com/lithammer/shortuuid/v3"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -37,10 +37,10 @@ func (ctx *appContext) authenticate(gc *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
claims, ok := token.Claims.(jwt.MapClaims)
|
claims, ok := token.Claims.(jwt.MapClaims)
|
||||||
var userId uuid.UUID
|
var userId string
|
||||||
var jfId string
|
var jfId string
|
||||||
if ok && token.Valid {
|
if ok && token.Valid {
|
||||||
userId, _ = uuid.Parse(claims["id"].(string))
|
userId = claims["id"].(string)
|
||||||
jfId = claims["jfid"].(string)
|
jfId = claims["jfid"].(string)
|
||||||
} else {
|
} else {
|
||||||
respond(401, "Unauthorized", gc)
|
respond(401, "Unauthorized", gc)
|
||||||
@ -59,7 +59,7 @@ func (ctx *appContext) authenticate(gc *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
gc.Set("jfId", jfId)
|
gc.Set("jfId", jfId)
|
||||||
gc.Set("userId", userId.String())
|
gc.Set("userId", userId)
|
||||||
gc.Next()
|
gc.Next()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ func (ctx *appContext) GetToken(gc *gin.Context) {
|
|||||||
auth, _ := base64.StdEncoding.DecodeString(header[1])
|
auth, _ := base64.StdEncoding.DecodeString(header[1])
|
||||||
creds := strings.SplitN(string(auth), ":", 2)
|
creds := strings.SplitN(string(auth), ":", 2)
|
||||||
match := false
|
match := false
|
||||||
var userId uuid.UUID
|
var userId string
|
||||||
for _, user := range ctx.users {
|
for _, user := range ctx.users {
|
||||||
if user.Username == creds[0] && user.Password == creds[1] {
|
if user.Username == creds[0] && user.Password == creds[1] {
|
||||||
match = true
|
match = true
|
||||||
@ -101,7 +101,7 @@ func (ctx *appContext) GetToken(gc *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
newuser := User{}
|
newuser := User{}
|
||||||
newuser.UserID, _ = uuid.NewRandom()
|
newuser.UserID = shortuuid.New()
|
||||||
userId = newuser.UserID
|
userId = newuser.UserID
|
||||||
// uuid, nothing else identifiable!
|
// uuid, nothing else identifiable!
|
||||||
ctx.users = append(ctx.users, newuser)
|
ctx.users = append(ctx.users, newuser)
|
||||||
@ -115,7 +115,7 @@ func (ctx *appContext) GetToken(gc *gin.Context) {
|
|||||||
gc.JSON(200, resp)
|
gc.JSON(200, resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateToken(userId uuid.UUID, jfId string) (string, error) {
|
func CreateToken(userId string, jfId string) (string, error) {
|
||||||
claims := jwt.MapClaims{
|
claims := jwt.MapClaims{
|
||||||
"valid": true,
|
"valid": true,
|
||||||
"id": userId,
|
"id": userId,
|
||||||
|
2
go.mod
2
go.mod
@ -18,7 +18,7 @@ require (
|
|||||||
github.com/labstack/echo/v4 v4.1.16
|
github.com/labstack/echo/v4 v4.1.16
|
||||||
github.com/lestrrat-go/strftime v1.0.3
|
github.com/lestrrat-go/strftime v1.0.3
|
||||||
github.com/lib/pq v1.7.1 // indirect
|
github.com/lib/pq v1.7.1 // indirect
|
||||||
github.com/lithammer/shortuuid/v3 v3.0.4 // indirect
|
github.com/lithammer/shortuuid/v3 v3.0.4
|
||||||
github.com/mailgun/mailgun-go v2.0.0+incompatible
|
github.com/mailgun/mailgun-go v2.0.0+incompatible
|
||||||
github.com/mailgun/mailgun-go/v4 v4.1.3
|
github.com/mailgun/mailgun-go/v4 v4.1.3
|
||||||
github.com/mattn/go-colorable v0.1.7 // indirect
|
github.com/mattn/go-colorable v0.1.7 // indirect
|
||||||
|
84
main.go
84
main.go
@ -7,38 +7,40 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gin-contrib/static"
|
"github.com/gin-contrib/static"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/google/uuid"
|
"github.com/lithammer/shortuuid/v3"
|
||||||
"gopkg.in/ini.v1"
|
"gopkg.in/ini.v1"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Username is JWT!
|
// Username is JWT!
|
||||||
type User struct {
|
type User struct {
|
||||||
UserID uuid.UUID `json:"id"`
|
UserID string `json:"id"`
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type appContext struct {
|
type appContext struct {
|
||||||
config *ini.File
|
config *ini.File
|
||||||
config_path string
|
config_path string
|
||||||
configBase_path string
|
configBase_path string
|
||||||
configBase map[string]interface{}
|
configBase map[string]interface{}
|
||||||
data_path string
|
data_path string
|
||||||
local_path string
|
local_path string
|
||||||
cssFile string
|
cssFile string
|
||||||
bsVersion int
|
bsVersion int
|
||||||
jellyfinLogin bool
|
jellyfinLogin bool
|
||||||
users []User
|
users []User
|
||||||
jf Jellyfin
|
jf Jellyfin
|
||||||
authJf Jellyfin
|
authJf Jellyfin
|
||||||
datePattern string
|
datePattern string
|
||||||
timePattern string
|
timePattern string
|
||||||
storage Storage
|
storage Storage
|
||||||
validator Validator
|
validator Validator
|
||||||
email Emailer
|
email Emailer
|
||||||
|
info, debug, err *log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenerateSecret(length int) (string, error) {
|
func GenerateSecret(length int) (string, error) {
|
||||||
@ -73,7 +75,20 @@ func main() {
|
|||||||
ctx.config_path = "/home/hrfee/.jf-accounts/config.ini"
|
ctx.config_path = "/home/hrfee/.jf-accounts/config.ini"
|
||||||
ctx.data_path = "/home/hrfee/.jf-accounts"
|
ctx.data_path = "/home/hrfee/.jf-accounts"
|
||||||
ctx.local_path = "data"
|
ctx.local_path = "data"
|
||||||
ctx.loadConfig()
|
if ctx.loadConfig() != nil {
|
||||||
|
ctx.err.Fatalf("Failed to load config file \"%s\"", ctx.config_path)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.info = log.New(os.Stdout, "INFO: ", log.Ltime)
|
||||||
|
ctx.err = log.New(os.Stdout, "INFO: ", log.Ltime|log.Lshortfile)
|
||||||
|
if ctx.config.Section("ui").Key("debug").MustBool(true) {
|
||||||
|
ctx.debug = log.New(os.Stdout, "DEBUG: ", log.Ltime|log.Lshortfile)
|
||||||
|
} else {
|
||||||
|
ctx.debug = log.New(nil, "", 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.debug.Printf("Loaded config file \"%s\"", ctx.config_path)
|
||||||
|
|
||||||
if val, _ := ctx.config.Section("ui").Key("bs5").Bool(); val {
|
if val, _ := ctx.config.Section("ui").Key("bs5").Bool(); val {
|
||||||
ctx.cssFile = "bs5-jf.css"
|
ctx.cssFile = "bs5-jf.css"
|
||||||
ctx.bsVersion = 5
|
ctx.bsVersion = 5
|
||||||
@ -82,6 +97,7 @@ func main() {
|
|||||||
ctx.bsVersion = 4
|
ctx.bsVersion = 4
|
||||||
}
|
}
|
||||||
// ctx.storage.formatter, _ = strftime.New("%Y-%m-%dT%H:%M:%S.%f")
|
// ctx.storage.formatter, _ = strftime.New("%Y-%m-%dT%H:%M:%S.%f")
|
||||||
|
ctx.debug.Println("Loading storage")
|
||||||
ctx.storage.invite_path = filepath.Join(ctx.data_path, "invites.json")
|
ctx.storage.invite_path = filepath.Join(ctx.data_path, "invites.json")
|
||||||
ctx.storage.loadInvites()
|
ctx.storage.loadInvites()
|
||||||
ctx.storage.emails_path = filepath.Join(ctx.data_path, "emails.json")
|
ctx.storage.emails_path = filepath.Join(ctx.data_path, "emails.json")
|
||||||
@ -96,7 +112,7 @@ func main() {
|
|||||||
ctx.configBase_path = filepath.Join(ctx.local_path, "config-base.json")
|
ctx.configBase_path = filepath.Join(ctx.local_path, "config-base.json")
|
||||||
config_base, _ := ioutil.ReadFile(ctx.configBase_path)
|
config_base, _ := ioutil.ReadFile(ctx.configBase_path)
|
||||||
json.Unmarshal(config_base, &ctx.configBase)
|
json.Unmarshal(config_base, &ctx.configBase)
|
||||||
//bson.UnmarshalExtJSON(config_base, true, &ctx.configBase)
|
|
||||||
themes := map[string]string{
|
themes := map[string]string{
|
||||||
"Jellyfin (Dark)": fmt.Sprintf("bs%d-jf.css", ctx.bsVersion),
|
"Jellyfin (Dark)": fmt.Sprintf("bs%d-jf.css", ctx.bsVersion),
|
||||||
"Bootstrap (Light)": fmt.Sprintf("bs%d.css", ctx.bsVersion),
|
"Bootstrap (Light)": fmt.Sprintf("bs%d.css", ctx.bsVersion),
|
||||||
@ -105,23 +121,32 @@ func main() {
|
|||||||
if val, ok := themes[ctx.config.Section("ui").Key("theme").String()]; ok {
|
if val, ok := themes[ctx.config.Section("ui").Key("theme").String()]; ok {
|
||||||
ctx.cssFile = val
|
ctx.cssFile = val
|
||||||
}
|
}
|
||||||
|
ctx.debug.Printf("Using css file \"%s\"", ctx.cssFile)
|
||||||
secret, err := GenerateSecret(16)
|
secret, err := GenerateSecret(16)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
ctx.err.Fatal(err)
|
||||||
}
|
}
|
||||||
os.Setenv("JFA_SECRET", secret)
|
os.Setenv("JFA_SECRET", secret)
|
||||||
ctx.jellyfinLogin = true
|
ctx.jellyfinLogin = true
|
||||||
if val, _ := ctx.config.Section("ui").Key("jellyfin_login").Bool(); !val {
|
if val, _ := ctx.config.Section("ui").Key("jellyfin_login").Bool(); !val {
|
||||||
ctx.jellyfinLogin = false
|
ctx.jellyfinLogin = false
|
||||||
user := User{}
|
user := User{}
|
||||||
user.UserID, _ = uuid.NewUUID()
|
user.UserID = shortuuid.New()
|
||||||
user.Username = ctx.config.Section("ui").Key("username").String()
|
user.Username = ctx.config.Section("ui").Key("username").String()
|
||||||
user.Password = ctx.config.Section("ui").Key("password").String()
|
user.Password = ctx.config.Section("ui").Key("password").String()
|
||||||
ctx.users = append(ctx.users, user)
|
ctx.users = append(ctx.users, user)
|
||||||
|
} else {
|
||||||
|
ctx.debug.Println("Using Jellyfin for authentication")
|
||||||
}
|
}
|
||||||
|
|
||||||
server := ctx.config.Section("jellyfin").Key("server").String()
|
server := ctx.config.Section("jellyfin").Key("server").String()
|
||||||
ctx.jf.init(server, "jfa-go", "0.1", "hrfee-arch", "hrfee-arch")
|
ctx.jf.init(server, "jfa-go", "0.1", "hrfee-arch", "hrfee-arch")
|
||||||
ctx.jf.authenticate(ctx.config.Section("jellyfin").Key("username").String(), ctx.config.Section("jellyfin").Key("password").String())
|
var status int
|
||||||
|
_, status, err = ctx.jf.authenticate(ctx.config.Section("jellyfin").Key("username").String(), ctx.config.Section("jellyfin").Key("password").String())
|
||||||
|
if status != 200 || err != nil {
|
||||||
|
ctx.err.Fatalf("Failed to authenticate with Jellyfin @ %s: Code %d", server, status)
|
||||||
|
}
|
||||||
|
ctx.info.Printf("Authenticated with %s", server)
|
||||||
ctx.authJf.init(server, "jfa-go", "0.1", "auth", "auth")
|
ctx.authJf.init(server, "jfa-go", "0.1", "auth", "auth")
|
||||||
|
|
||||||
ctx.loadStrftime()
|
ctx.loadStrftime()
|
||||||
@ -133,7 +158,6 @@ func main() {
|
|||||||
"numbers": ctx.config.Section("password_validation").Key("number").MustInt(0),
|
"numbers": ctx.config.Section("password_validation").Key("number").MustInt(0),
|
||||||
"special characters": ctx.config.Section("password_validation").Key("special").MustInt(0),
|
"special characters": ctx.config.Section("password_validation").Key("special").MustInt(0),
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ctx.config.Section("password_validation").Key("enabled").MustBool(false) {
|
if !ctx.config.Section("password_validation").Key("enabled").MustBool(false) {
|
||||||
for key := range validatorConf {
|
for key := range validatorConf {
|
||||||
validatorConf[key] = 0
|
validatorConf[key] = 0
|
||||||
@ -143,6 +167,7 @@ func main() {
|
|||||||
|
|
||||||
ctx.email.init(ctx)
|
ctx.email.init(ctx)
|
||||||
|
|
||||||
|
ctx.debug.Println("Loading routes")
|
||||||
router := gin.Default()
|
router := gin.Default()
|
||||||
router.Use(static.Serve("/", static.LocalFile("data/static", false)))
|
router.Use(static.Serve("/", static.LocalFile("data/static", false)))
|
||||||
router.Use(static.Serve("/invite/", static.LocalFile("data/static", false)))
|
router.Use(static.Serve("/invite/", static.LocalFile("data/static", false)))
|
||||||
@ -161,6 +186,7 @@ func main() {
|
|||||||
api.POST("/modifyUsers", ctx.ModifyEmails)
|
api.POST("/modifyUsers", ctx.ModifyEmails)
|
||||||
api.POST("/setDefaults", ctx.SetDefaults)
|
api.POST("/setDefaults", ctx.SetDefaults)
|
||||||
api.GET("/getConfig", ctx.GetConfig)
|
api.GET("/getConfig", ctx.GetConfig)
|
||||||
|
api.POST("/modifyConfig", ctx.ModifyConfig)
|
||||||
router.Run(":8080")
|
addr := fmt.Sprintf("%s:%d", ctx.config.Section("ui").Key("host").String(), ctx.config.Section("ui").Key("port").MustInt(8056))
|
||||||
|
router.Run(addr)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user