mirror of
https://github.com/hrfee/jfa-go.git
synced 2025-01-01 05:50:12 +00:00
Compare commits
7 Commits
406fef6595
...
1bf1e994fe
Author | SHA1 | Date | |
---|---|---|---|
|
1bf1e994fe | ||
|
7f91a27e4f | ||
|
f66510c74b | ||
|
e5de8b20ff | ||
dd96d71280 | |||
|
a687b2c438 | ||
ea262ca60b |
46
api.go
46
api.go
@ -233,19 +233,28 @@ func (app *appContext) getOmbiUser(jfID string) (map[string]interface{}, int, er
|
|||||||
// @Security Bearer
|
// @Security Bearer
|
||||||
// @tags Users
|
// @tags Users
|
||||||
func (app *appContext) NewUserAdmin(gc *gin.Context) {
|
func (app *appContext) NewUserAdmin(gc *gin.Context) {
|
||||||
|
respondUser := func(code int, user, email bool, msg string, gc *gin.Context) {
|
||||||
|
resp := newUserResponse{
|
||||||
|
User: user,
|
||||||
|
Email: email,
|
||||||
|
Error: msg,
|
||||||
|
}
|
||||||
|
gc.JSON(code, resp)
|
||||||
|
gc.Abort()
|
||||||
|
}
|
||||||
var req newUserDTO
|
var req newUserDTO
|
||||||
gc.BindJSON(&req)
|
gc.BindJSON(&req)
|
||||||
existingUser, _, _ := app.jf.UserByName(req.Username, false)
|
existingUser, _, _ := app.jf.UserByName(req.Username, false)
|
||||||
if existingUser != nil {
|
if existingUser != nil {
|
||||||
msg := fmt.Sprintf("User already exists named %s", req.Username)
|
msg := fmt.Sprintf("User already exists named %s", req.Username)
|
||||||
app.info.Printf("%s New user failed: %s", req.Username, msg)
|
app.info.Printf("%s New user failed: %s", req.Username, msg)
|
||||||
respond(401, msg, gc)
|
respondUser(401, false, false, msg, gc)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
user, status, err := app.jf.NewUser(req.Username, req.Password)
|
user, status, err := app.jf.NewUser(req.Username, req.Password)
|
||||||
if !(status == 200 || status == 204) || err != nil {
|
if !(status == 200 || status == 204) || err != nil {
|
||||||
app.err.Printf("%s New user failed: Jellyfin responded with %d", req.Username, status)
|
app.err.Printf("%s New user failed: Jellyfin responded with %d", req.Username, status)
|
||||||
respond(401, "Unknown error", gc)
|
respondUser(401, false, false, "Unknown error", gc)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var id string
|
var id string
|
||||||
@ -268,6 +277,7 @@ func (app *appContext) NewUserAdmin(gc *gin.Context) {
|
|||||||
app.err.Printf("%s: Failed to set configuration template: Code %d", req.Username, status)
|
app.err.Printf("%s: Failed to set configuration template: Code %d", req.Username, status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
app.jf.CacheExpiry = time.Now()
|
||||||
if app.config.Section("password_resets").Key("enabled").MustBool(false) {
|
if app.config.Section("password_resets").Key("enabled").MustBool(false) {
|
||||||
app.storage.emails[id] = req.Email
|
app.storage.emails[id] = req.Email
|
||||||
app.storage.storeEmails()
|
app.storage.storeEmails()
|
||||||
@ -284,7 +294,22 @@ func (app *appContext) NewUserAdmin(gc *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
app.jf.CacheExpiry = time.Now()
|
if app.config.Section("welcome_email").Key("enabled").MustBool(false) && req.Email != "" {
|
||||||
|
app.debug.Printf("%s: Sending welcome email to %s", req.Username, req.Email)
|
||||||
|
msg, err := app.email.constructWelcome(req.Username, app)
|
||||||
|
if err != nil {
|
||||||
|
app.err.Printf("%s: Failed to construct welcome email: %s", req.Username, err)
|
||||||
|
respondUser(500, true, false, err.Error(), gc)
|
||||||
|
return
|
||||||
|
} else if err := app.email.send(req.Email, msg); err != nil {
|
||||||
|
app.err.Printf("%s: Failed to send welcome email: %s", req.Username, err)
|
||||||
|
respondUser(500, true, false, err.Error(), gc)
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
app.info.Printf("%s: Sent welcome email to %s", req.Username, req.Email)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
respondUser(200, true, true, "", gc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary Creates a new Jellyfin user via invite code
|
// @Summary Creates a new Jellyfin user via invite code
|
||||||
@ -398,6 +423,17 @@ func (app *appContext) NewUser(gc *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if app.config.Section("welcome_email").Key("enabled").MustBool(false) && req.Email != "" {
|
||||||
|
app.debug.Printf("%s: Sending welcome email to %s", req.Username, req.Email)
|
||||||
|
msg, err := app.email.constructWelcome(req.Username, app)
|
||||||
|
if err != nil {
|
||||||
|
app.err.Printf("%s: Failed to construct welcome email: %s", req.Username, err)
|
||||||
|
} else if err := app.email.send(req.Email, msg); err != nil {
|
||||||
|
app.err.Printf("%s: Failed to send welcome email: %s", req.Username, err)
|
||||||
|
} else {
|
||||||
|
app.info.Printf("%s: Sent welcome email to %s", req.Username, req.Email)
|
||||||
|
}
|
||||||
|
}
|
||||||
code := 200
|
code := 200
|
||||||
for _, val := range validation {
|
for _, val := range validation {
|
||||||
if !val {
|
if !val {
|
||||||
@ -496,6 +532,9 @@ func (app *appContext) GenerateInvite(gc *gin.Context) {
|
|||||||
_, err = strconv.Atoi(string(inviteCode[0]))
|
_, err = strconv.Atoi(string(inviteCode[0]))
|
||||||
}
|
}
|
||||||
var invite Invite
|
var invite Invite
|
||||||
|
if req.Label != "" {
|
||||||
|
invite.Label = req.Label
|
||||||
|
}
|
||||||
invite.Created = currentTime
|
invite.Created = currentTime
|
||||||
if req.MultipleUses {
|
if req.MultipleUses {
|
||||||
if req.NoLimit {
|
if req.NoLimit {
|
||||||
@ -696,6 +735,7 @@ func (app *appContext) GetInvites(gc *gin.Context) {
|
|||||||
Created: app.formatDatetime(inv.Created),
|
Created: app.formatDatetime(inv.Created),
|
||||||
Profile: inv.Profile,
|
Profile: inv.Profile,
|
||||||
NoLimit: inv.NoLimit,
|
NoLimit: inv.NoLimit,
|
||||||
|
Label: inv.Label,
|
||||||
}
|
}
|
||||||
if len(inv.UsedBy) != 0 {
|
if len(inv.UsedBy) != 0 {
|
||||||
invite.UsedBy = inv.UsedBy
|
invite.UsedBy = inv.UsedBy
|
||||||
|
@ -44,6 +44,9 @@ func (app *appContext) loadConfig() error {
|
|||||||
app.config.Section("deletion").Key("email_html").SetValue(app.config.Section("deletion").Key("email_html").MustString(filepath.Join(app.localPath, "deleted.html")))
|
app.config.Section("deletion").Key("email_html").SetValue(app.config.Section("deletion").Key("email_html").MustString(filepath.Join(app.localPath, "deleted.html")))
|
||||||
app.config.Section("deletion").Key("email_text").SetValue(app.config.Section("deletion").Key("email_text").MustString(filepath.Join(app.localPath, "deleted.txt")))
|
app.config.Section("deletion").Key("email_text").SetValue(app.config.Section("deletion").Key("email_text").MustString(filepath.Join(app.localPath, "deleted.txt")))
|
||||||
|
|
||||||
|
app.config.Section("welcome_email").Key("email_html").SetValue(app.config.Section("welcome_email").Key("email_html").MustString(filepath.Join(app.localPath, "welcome.html")))
|
||||||
|
app.config.Section("welcome_email").Key("email_text").SetValue(app.config.Section("welcome_email").Key("email_text").MustString(filepath.Join(app.localPath, "welcome.txt")))
|
||||||
|
|
||||||
app.config.Section("jellyfin").Key("version").SetValue(VERSION)
|
app.config.Section("jellyfin").Key("version").SetValue(VERSION)
|
||||||
app.config.Section("jellyfin").Key("device").SetValue("jfa-go")
|
app.config.Section("jellyfin").Key("device").SetValue("jfa-go")
|
||||||
app.config.Section("jellyfin").Key("device_id").SetValue(fmt.Sprintf("jfa-go-%s-%s", VERSION, COMMIT))
|
app.config.Section("jellyfin").Key("device_id").SetValue(fmt.Sprintf("jfa-go-%s-%s", VERSION, COMMIT))
|
||||||
|
@ -448,7 +448,7 @@
|
|||||||
"requires_restart": false,
|
"requires_restart": false,
|
||||||
"depends_true": "enabled",
|
"depends_true": "enabled",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"value": "Password Reset - Jellyfin",
|
"value": "",
|
||||||
"description": "Subject of password reset emails."
|
"description": "Subject of password reset emails."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -491,7 +491,7 @@
|
|||||||
"requires_restart": false,
|
"requires_restart": false,
|
||||||
"depends_true": "enabled",
|
"depends_true": "enabled",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"value": "Invite - Jellyfin",
|
"value": "",
|
||||||
"description": "Subject of invite emails."
|
"description": "Subject of invite emails."
|
||||||
},
|
},
|
||||||
"url_base": {
|
"url_base": {
|
||||||
@ -667,6 +667,47 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"welcome_email": {
|
||||||
|
"order": [],
|
||||||
|
"meta": {
|
||||||
|
"name": "Welcome Emails",
|
||||||
|
"description": "Optionally send a welcome email to new users with the Jellyfin URL and their username."
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"enabled": {
|
||||||
|
"name": "Enabled",
|
||||||
|
"required": false,
|
||||||
|
"requires_restart": true,
|
||||||
|
"type": "bool",
|
||||||
|
"value": false,
|
||||||
|
"description": "Enable to send welcome emails to new users."
|
||||||
|
},
|
||||||
|
"subject": {
|
||||||
|
"name": "Email subject",
|
||||||
|
"required": false,
|
||||||
|
"requires_restart": false,
|
||||||
|
"type": "text",
|
||||||
|
"value": "",
|
||||||
|
"description": "Subject of welcome emails."
|
||||||
|
},
|
||||||
|
"email_html": {
|
||||||
|
"name": "Custom email (HTML)",
|
||||||
|
"required": false,
|
||||||
|
"requires_restart": false,
|
||||||
|
"type": "text",
|
||||||
|
"value": "",
|
||||||
|
"description": "Path to custom email html"
|
||||||
|
},
|
||||||
|
"email_text": {
|
||||||
|
"name": "Custom email (plaintext)",
|
||||||
|
"required": false,
|
||||||
|
"requires_restart": false,
|
||||||
|
"type": "text",
|
||||||
|
"value": "",
|
||||||
|
"description": "Path to custom email in plain text"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"deletion": {
|
"deletion": {
|
||||||
"order": [],
|
"order": [],
|
||||||
"meta": {
|
"meta": {
|
||||||
|
@ -200,7 +200,7 @@ sup.\~critical, .text-critical {
|
|||||||
max-width: 40%;
|
max-width: 40%;
|
||||||
min-width: 10rem;
|
min-width: 10rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: start;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
36
email.go
36
email.go
@ -262,7 +262,7 @@ func (emailer *Emailer) constructCreated(code, username, address string, invite
|
|||||||
|
|
||||||
func (emailer *Emailer) constructReset(pwr PasswordReset, app *appContext) (*Email, error) {
|
func (emailer *Emailer) constructReset(pwr PasswordReset, app *appContext) (*Email, error) {
|
||||||
email := &Email{
|
email := &Email{
|
||||||
subject: emailer.lang.PasswordReset.get("title"),
|
subject: app.config.Section("password_resets").Key("subject").MustString(emailer.lang.PasswordReset.get("title")),
|
||||||
}
|
}
|
||||||
d, t, expiresIn := emailer.formatExpiry(pwr.Expiry, true, app.datePattern, app.timePattern)
|
d, t, expiresIn := emailer.formatExpiry(pwr.Expiry, true, app.datePattern, app.timePattern)
|
||||||
message := app.config.Section("email").Key("message").String()
|
message := app.config.Section("email").Key("message").String()
|
||||||
@ -297,7 +297,7 @@ func (emailer *Emailer) constructReset(pwr PasswordReset, app *appContext) (*Ema
|
|||||||
|
|
||||||
func (emailer *Emailer) constructDeleted(reason string, app *appContext) (*Email, error) {
|
func (emailer *Emailer) constructDeleted(reason string, app *appContext) (*Email, error) {
|
||||||
email := &Email{
|
email := &Email{
|
||||||
subject: emailer.lang.UserDeleted.get("title"),
|
subject: app.config.Section("deletion").Key("subject").MustString(emailer.lang.UserDeleted.get("title")),
|
||||||
}
|
}
|
||||||
for _, key := range []string{"html", "text"} {
|
for _, key := range []string{"html", "text"} {
|
||||||
fpath := app.config.Section("deletion").Key("email_" + key).String()
|
fpath := app.config.Section("deletion").Key("email_" + key).String()
|
||||||
@ -323,6 +323,38 @@ func (emailer *Emailer) constructDeleted(reason string, app *appContext) (*Email
|
|||||||
return email, nil
|
return email, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (emailer *Emailer) constructWelcome(username string, app *appContext) (*Email, error) {
|
||||||
|
email := &Email{
|
||||||
|
subject: app.config.Section("welcome_email").Key("subject").MustString(emailer.lang.WelcomeEmail.get("title")),
|
||||||
|
}
|
||||||
|
for _, key := range []string{"html", "text"} {
|
||||||
|
fpath := app.config.Section("welcome_email").Key("email_" + key).String()
|
||||||
|
tpl, err := template.ParseFiles(fpath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var tplData bytes.Buffer
|
||||||
|
err = tpl.Execute(&tplData, map[string]string{
|
||||||
|
"welcome": emailer.lang.WelcomeEmail.get("welcome"),
|
||||||
|
"youCanLoginWith": emailer.lang.WelcomeEmail.get("youCanLoginWith"),
|
||||||
|
"jellyfinURL": emailer.lang.WelcomeEmail.get("jellyfinURL"),
|
||||||
|
"jellyfinURLVal": app.config.Section("jellyfin").Key("public_server").String(),
|
||||||
|
"username": emailer.lang.WelcomeEmail.get("username"),
|
||||||
|
"usernameVal": username,
|
||||||
|
"message": app.config.Section("email").Key("message").String(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if key == "html" {
|
||||||
|
email.html = tplData.String()
|
||||||
|
} else {
|
||||||
|
email.text = tplData.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return email, nil
|
||||||
|
}
|
||||||
|
|
||||||
// calls the send method in the underlying emailClient.
|
// calls the send method in the underlying emailClient.
|
||||||
func (emailer *Emailer) send(address string, email *Email) error {
|
func (emailer *Emailer) send(address string, email *Email) error {
|
||||||
return emailer.sender.send(address, emailer.fromName, emailer.fromAddr, email)
|
return emailer.sender.send(address, emailer.fromName, emailer.fromAddr, email)
|
||||||
|
@ -219,12 +219,14 @@
|
|||||||
<option>0</option>
|
<option>0</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
<label class="label supra" for="create-label"> {{ .strings.label }}</label>
|
||||||
|
<input type="text" id="create-label" class="input ~neutral !normal mb-1 mt-half">
|
||||||
</div>
|
</div>
|
||||||
<div class="card ~neutral !normal col">
|
<div class="card ~neutral !normal col">
|
||||||
<label class="label supra" for="create-uses">{{ .strings.inviteNumberOfUses }}</label>
|
<label class="label supra" for="create-uses">{{ .strings.inviteNumberOfUses }}</label>
|
||||||
<div class="flex-expand mb-1 mt-half">
|
<div class="flex-expand mb-1 mt-half">
|
||||||
<input type="number" min="0" id="create-uses" class="input ~neutral !normal mr-1" value=1>
|
<input type="number" min="0" id="create-uses" class="input ~neutral !normal mr-1" value=1>
|
||||||
<label for="create-inf-uses" class="button ~neutral !normal">
|
<label for="create-inf-uses" class="button ~neutral !normal" title="Set uses to infinite">
|
||||||
<span>∞</span>
|
<span>∞</span>
|
||||||
<input type="checkbox" class="unfocused" id="create-inf-uses" aria-label="Set uses to infinite">
|
<input type="checkbox" class="unfocused" id="create-inf-uses" aria-label="Set uses to infinite">
|
||||||
</label>
|
</label>
|
||||||
|
1
lang.go
1
lang.go
@ -74,6 +74,7 @@ type emailLang struct {
|
|||||||
PasswordReset langSection `json:"passwordReset"`
|
PasswordReset langSection `json:"passwordReset"`
|
||||||
UserDeleted langSection `json:"userDeleted"`
|
UserDeleted langSection `json:"userDeleted"`
|
||||||
InviteEmail langSection `json:"inviteEmail"`
|
InviteEmail langSection `json:"inviteEmail"`
|
||||||
|
WelcomeEmail langSection `json:"welcomeEmail"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type langSection map[string]string
|
type langSection map[string]string
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
"success": "Success",
|
"success": "Success",
|
||||||
"error": "Error",
|
"error": "Error",
|
||||||
"unknown": "Unknown",
|
"unknown": "Unknown",
|
||||||
|
"label": "Label",
|
||||||
"modifySettings": "Modify Settings",
|
"modifySettings": "Modify Settings",
|
||||||
"modifySettingsDescription": "Apply settings from an existing profile, or source them directly from a user.",
|
"modifySettingsDescription": "Apply settings from an existing profile, or source them directly from a user.",
|
||||||
"applyHomescreenLayout": "Apply homescreen layout",
|
"applyHomescreenLayout": "Apply homescreen layout",
|
||||||
@ -98,7 +99,9 @@
|
|||||||
"errorLoadOmbiUsers": "Failed to load ombi users.",
|
"errorLoadOmbiUsers": "Failed to load ombi users.",
|
||||||
"errorChangedEmailAddress": "Couldn't change email address of {n}.",
|
"errorChangedEmailAddress": "Couldn't change email address of {n}.",
|
||||||
"errorFailureCheckLogs": "Failed (check console/logs)",
|
"errorFailureCheckLogs": "Failed (check console/logs)",
|
||||||
"errorPartialFailureCheckLogs": "Partial failure (check console/logs)"
|
"errorPartialFailureCheckLogs": "Partial failure (check console/logs)",
|
||||||
|
"errorUserCreated": "Failed to create user {n}.",
|
||||||
|
"errorSendWelcomeEmail": "Failed to send welcome email (check console/logs)"
|
||||||
},
|
},
|
||||||
|
|
||||||
"quantityStrings": {
|
"quantityStrings": {
|
||||||
|
@ -41,26 +41,26 @@
|
|||||||
"modifySettingsDescription": "Appliquez les paramètres à partir d'un profil existant ou obtenez-les directement auprès d'un utilisateur.",
|
"modifySettingsDescription": "Appliquez les paramètres à partir d'un profil existant ou obtenez-les directement auprès d'un utilisateur.",
|
||||||
"applyHomescreenLayout": "Appliquer la disposition de l'écran d'accueil",
|
"applyHomescreenLayout": "Appliquer la disposition de l'écran d'accueil",
|
||||||
"sendDeleteNotificationEmail": "Envoyer un e-mail de notification",
|
"sendDeleteNotificationEmail": "Envoyer un e-mail de notification",
|
||||||
"sendDeleteNotifiationExample": "Votre compte a été supprimé. ",
|
"sendDeleteNotifiationExample": "Votre compte a été supprimé.",
|
||||||
"settingsRestartRequired": "Redémarrage nécessaire ",
|
"settingsRestartRequired": "Redémarrage nécessaire",
|
||||||
"settingsRestartRequiredDescription": "Un redémarrage est nécessaire pour appliquer certains paramètres que vous avez modifiés. Redémarrer maintenant ou plus tard?",
|
"settingsRestartRequiredDescription": "Un redémarrage est nécessaire pour appliquer certains paramètres que vous avez modifiés. Redémarrer maintenant ou plus tard ?",
|
||||||
"settingsApplyRestartLater": "Appliquer, redémarrer plus tard ",
|
"settingsApplyRestartLater": "Appliquer, redémarrer plus tard",
|
||||||
"settingsApplyRestartNow": "Appliquer et redémarrer ",
|
"settingsApplyRestartNow": "Appliquer et redémarrer",
|
||||||
"settingsApplied": "Paramètres appliqués.",
|
"settingsApplied": "Paramètres appliqués.",
|
||||||
"settingsRefreshPage": "Actualisez la page dans quelques secondes ",
|
"settingsRefreshPage": "Actualisez la page dans quelques secondes",
|
||||||
"settingsRequiredOrRestartMessage": "Remarque: {n} indique un champ obligatoire, {n} indique que les modifications nécessitent un redémarrage. ",
|
"settingsRequiredOrRestartMessage": "Remarque: {n} indique un champ obligatoire, {n} indique que les modifications nécessitent un redémarrage.",
|
||||||
"settingsSave": "Sauver",
|
"settingsSave": "Sauver",
|
||||||
"ombiUserDefaults": "Paramètres par défaut de l'utilisateur Ombi",
|
"ombiUserDefaults": "Paramètres par défaut de l'utilisateur Ombi",
|
||||||
"ombiUserDefaultsDescription": "Créez un utilisateur Ombi et configurez-le, puis sélectionnez-le ci-dessous. Ses paramètres / autorisations seront stockés et appliqués aux nouveaux utilisateurs Ombi créés par jfa-go ",
|
"ombiUserDefaultsDescription": "Créez un utilisateur Ombi et configurez-le, puis sélectionnez-le ci-dessous. Ses paramètres/autorisations seront stockés et appliqués aux nouveaux utilisateurs Ombi créés par jfa-go",
|
||||||
"userProfiles": "Profils d'utilisateurs",
|
"userProfiles": "Profils d'utilisateurs",
|
||||||
"userProfilesDescription": "Les profils sont appliqués aux utilisateurs lorsqu'ils créent un compte. Un profil inclut les droits d'accès à la bibliothèque et la disposition de l'écran d'accueil. ",
|
"userProfilesDescription": "Les profils sont appliqués aux utilisateurs lorsqu'ils créent un compte. Un profil inclut les droits d'accès à la bibliothèque et la disposition de l'écran d'accueil.",
|
||||||
"userProfilesIsDefault": "Défaut",
|
"userProfilesIsDefault": "Défaut",
|
||||||
"userProfilesLibraries": "Bibliothèques",
|
"userProfilesLibraries": "Bibliothèques",
|
||||||
"addProfile": "Ajouter un profil",
|
"addProfile": "Ajouter un profil",
|
||||||
"addProfileDescription": "Créez un utilisateur Jellyfin et configurez-le, puis sélectionnez-le ci-dessous. Lorsque ce profil est appliqué à une invitation, de nouveaux utilisateurs seront créés avec les paramètres. ",
|
"addProfileDescription": "Créez un utilisateur Jellyfin et configurez-le, puis sélectionnez-le ci-dessous. Lorsque ce profil est appliqué à une invitation, les nouveaux utilisateurs seront créés avec ces paramètres.",
|
||||||
"addProfileNameOf": "Nom de profil",
|
"addProfileNameOf": "Nom de profil",
|
||||||
"addProfileStoreHomescreenLayout": "Enregistrer la disposition de l'écran d'accueil",
|
"addProfileStoreHomescreenLayout": "Enregistrer la disposition de l'écran d'accueil",
|
||||||
"inviteNoUsersCreated": "Aucun pour l'instant!",
|
"inviteNoUsersCreated": "Aucun pour l'instant !",
|
||||||
"inviteUsersCreated": "Utilisateurs créer",
|
"inviteUsersCreated": "Utilisateurs créer",
|
||||||
"inviteNoProfile": "Aucun profil",
|
"inviteNoProfile": "Aucun profil",
|
||||||
"copy": "Copier",
|
"copy": "Copier",
|
||||||
@ -68,9 +68,10 @@
|
|||||||
"inviteRemainingUses": "Utilisations restantes",
|
"inviteRemainingUses": "Utilisations restantes",
|
||||||
"inviteNoInvites": "Aucune",
|
"inviteNoInvites": "Aucune",
|
||||||
"inviteExpiresInTime": "Expires dans {n}",
|
"inviteExpiresInTime": "Expires dans {n}",
|
||||||
"notifyEvent": "Notifier sur:",
|
"notifyEvent": "Notifier sur :",
|
||||||
"notifyInviteExpiry": "À l'expiration",
|
"notifyInviteExpiry": "À l'expiration",
|
||||||
"notifyUserCreation": "à la création de l'utilisateur"
|
"notifyUserCreation": "à la création de l'utilisateur",
|
||||||
|
"label": "Etiquette"
|
||||||
},
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"changedEmailAddress": "Adresse e-mail modifiée de {n}.",
|
"changedEmailAddress": "Adresse e-mail modifiée de {n}.",
|
||||||
@ -83,13 +84,13 @@
|
|||||||
"errorSettingsAppliedNoHomescreenLayout": "Les paramètres ont été appliqués, mais l'application de la disposition de l'écran d'accueil a peut-être échoué.",
|
"errorSettingsAppliedNoHomescreenLayout": "Les paramètres ont été appliqués, mais l'application de la disposition de l'écran d'accueil a peut-être échoué.",
|
||||||
"errorHomescreenAppliedNoSettings": "La disposition de l'écran d'accueil a été appliquée, mais l'application des paramètres a peut-être échoué.",
|
"errorHomescreenAppliedNoSettings": "La disposition de l'écran d'accueil a été appliquée, mais l'application des paramètres a peut-être échoué.",
|
||||||
"errorSettingsFailed": "L'application a échoué.",
|
"errorSettingsFailed": "L'application a échoué.",
|
||||||
"errorLoginBlank": "Le nom d'utilisateur et / ou le mot de passe sont vides",
|
"errorLoginBlank": "Le nom d'utilisateur et/ou le mot de passe sont vides.",
|
||||||
"errorUnknown": "Erreur inconnue.",
|
"errorUnknown": "Erreur inconnue.",
|
||||||
"errorBlankFields": "Les champs sont vides",
|
"errorBlankFields": "Les champs sont vides",
|
||||||
"errorDeleteProfile": "Échec de la suppression du profil {n}",
|
"errorDeleteProfile": "Échec de la suppression du profil {n}",
|
||||||
"errorLoadProfiles": "Échec du chargement des profils.",
|
"errorLoadProfiles": "Échec du chargement des profils.",
|
||||||
"errorCreateProfile": "Échec de la création du profil {n}",
|
"errorCreateProfile": "Échec de la création du profil {n}",
|
||||||
"errorSetDefaultProfile": "Échec de la définition du profil par défaut",
|
"errorSetDefaultProfile": "Échec de la définition du profil par défaut.",
|
||||||
"errorLoadUsers": "Échec du chargement des utilisateurs.",
|
"errorLoadUsers": "Échec du chargement des utilisateurs.",
|
||||||
"errorSaveSettings": "Impossible d'enregistrer les paramètres.",
|
"errorSaveSettings": "Impossible d'enregistrer les paramètres.",
|
||||||
"errorLoadSettings": "Échec du chargement des paramètres.",
|
"errorLoadSettings": "Échec du chargement des paramètres.",
|
||||||
@ -97,7 +98,9 @@
|
|||||||
"errorLoadOmbiUsers": "Échec du chargement des utilisateurs Ombi.",
|
"errorLoadOmbiUsers": "Échec du chargement des utilisateurs Ombi.",
|
||||||
"errorChangedEmailAddress": "Impossible de modifier l'adresse e-mail de {n}.",
|
"errorChangedEmailAddress": "Impossible de modifier l'adresse e-mail de {n}.",
|
||||||
"errorFailureCheckLogs": "Échec (vérifier la console / les journaux)",
|
"errorFailureCheckLogs": "Échec (vérifier la console / les journaux)",
|
||||||
"errorPartialFailureCheckLogs": "Panne partielle (vérifier la console / les journaux)"
|
"errorPartialFailureCheckLogs": "Panne partielle (vérifier la console / les journaux)",
|
||||||
|
"errorUserCreated": "Echec lors de la création de l'utilisateur {n}.",
|
||||||
|
"errorSendWelcomeEmail": "Echec lors de l'envoi du mail de bienvenue (vérifier la console/les journaux)"
|
||||||
},
|
},
|
||||||
"quantityStrings": {
|
"quantityStrings": {
|
||||||
"modifySettingsFor": {
|
"modifySettingsFor": {
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
"inviteDays": "Dagen",
|
"inviteDays": "Dagen",
|
||||||
"inviteHours": "Uren",
|
"inviteHours": "Uren",
|
||||||
"inviteMinutes": "Minuten",
|
"inviteMinutes": "Minuten",
|
||||||
"inviteNumberOfUses": "Aantal keer gebruikt",
|
"inviteNumberOfUses": "Aantal keer te gebruiken",
|
||||||
"warning": "Waarschuwing",
|
"warning": "Waarschuwing",
|
||||||
"inviteInfiniteUsesWarning": "ongelimiteerde uitnodigingen kunnen misbruikt worden",
|
"inviteInfiniteUsesWarning": "ongelimiteerde uitnodigingen kunnen misbruikt worden",
|
||||||
"inviteSendToEmail": "Stuur naar",
|
"inviteSendToEmail": "Stuur naar",
|
||||||
@ -24,7 +24,7 @@
|
|||||||
"date": "Datum",
|
"date": "Datum",
|
||||||
"username": "Gebruikersnaam",
|
"username": "Gebruikersnaam",
|
||||||
"password": "Wachtwoord",
|
"password": "Wachtwoord",
|
||||||
"emailAddress": "Email adres",
|
"emailAddress": "E-mailadres",
|
||||||
"lastActiveTime": "Laatst actief",
|
"lastActiveTime": "Laatst actief",
|
||||||
"from": "Van",
|
"from": "Van",
|
||||||
"user": "Gebruiker",
|
"user": "Gebruiker",
|
||||||
@ -39,7 +39,7 @@
|
|||||||
"modifySettings": "Instellingen aanpassen",
|
"modifySettings": "Instellingen aanpassen",
|
||||||
"modifySettingsDescription": "Pas instellingen van een bestaand profiel toe, of neem ze direct over van een gebruiker.",
|
"modifySettingsDescription": "Pas instellingen van een bestaand profiel toe, of neem ze direct over van een gebruiker.",
|
||||||
"applyHomescreenLayout": "Sla startpagina indeling op",
|
"applyHomescreenLayout": "Sla startpagina indeling op",
|
||||||
"sendDeleteNotificationEmail": "Stuur meldingsemail",
|
"sendDeleteNotificationEmail": "Stuur meldingse-mail",
|
||||||
"sendDeleteNotifiationExample": "Je account is verwijderd.",
|
"sendDeleteNotifiationExample": "Je account is verwijderd.",
|
||||||
"settingsRestartRequired": "Herstart nodig",
|
"settingsRestartRequired": "Herstart nodig",
|
||||||
"settingsRestartRequiredDescription": "Er is een herstart nodig om de wijzigingen door te voeren. Herstart nu of later?",
|
"settingsRestartRequiredDescription": "Er is een herstart nodig om de wijzigingen door te voeren. Herstart nu of later?",
|
||||||
@ -59,22 +59,20 @@
|
|||||||
"addProfileDescription": "Maak een Jellyfin gebruiker aan met de gewenste instellingen en selecteer deze hieronder. Wanneer dit profiel wordt toegepast op een uitnodiging, worden nieuwe gebruikers aangemaakt met deze instellingen.",
|
"addProfileDescription": "Maak een Jellyfin gebruiker aan met de gewenste instellingen en selecteer deze hieronder. Wanneer dit profiel wordt toegepast op een uitnodiging, worden nieuwe gebruikers aangemaakt met deze instellingen.",
|
||||||
"addProfileNameOf": "Profielnaam",
|
"addProfileNameOf": "Profielnaam",
|
||||||
"addProfileStoreHomescreenLayout": "Sla startpaginaindeling op",
|
"addProfileStoreHomescreenLayout": "Sla startpaginaindeling op",
|
||||||
|
|
||||||
"inviteNoUsersCreated": "Nog geen!",
|
"inviteNoUsersCreated": "Nog geen!",
|
||||||
"inviteUsersCreated": "Aangemaakte gebruikers",
|
"inviteUsersCreated": "Aangemaakte gebruikers",
|
||||||
"inviteNoProfile": "Geen profiel",
|
"inviteNoProfile": "Geen profiel",
|
||||||
"copy": "Kopiëer",
|
"copy": "Kopiëer",
|
||||||
"inviteDateCreated": "Aangemaakt",
|
"inviteDateCreated": "Aangemaakt",
|
||||||
"inviteRemainingUses": "Resterend aantal gebruiken",
|
"inviteRemainingUses": "Resterend aantal keer te gebruiken",
|
||||||
"inviteNoInvites": "Geen",
|
"inviteNoInvites": "Geen",
|
||||||
"inviteExpiresInTime": "Verloopt over {n}",
|
"inviteExpiresInTime": "Verloopt over {n}",
|
||||||
|
|
||||||
"notifyEvent": "Meldingen:",
|
"notifyEvent": "Meldingen:",
|
||||||
"notifyInviteExpiry": "Bij verloop",
|
"notifyInviteExpiry": "Bij verloop",
|
||||||
"notifyUserCreation": "Bij aanmaken gebruiker"
|
"notifyUserCreation": "Bij aanmaken gebruiker"
|
||||||
},
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"changedEmailAddress": "Email adres van {n} gewijzigd.",
|
"changedEmailAddress": "E-mailadres van {n} gewijzigd.",
|
||||||
"userCreated": "Gebruiker {n} aangemaakt.",
|
"userCreated": "Gebruiker {n} aangemaakt.",
|
||||||
"createProfile": "Profiel {n} aangemaakt.",
|
"createProfile": "Profiel {n} aangemaakt.",
|
||||||
"saveSettings": "De instellingen zijn opgeslagen",
|
"saveSettings": "De instellingen zijn opgeslagen",
|
||||||
@ -96,11 +94,10 @@
|
|||||||
"errorLoadSettings": "Laden van instellingen mislukt.",
|
"errorLoadSettings": "Laden van instellingen mislukt.",
|
||||||
"errorSetOmbiDefaults": "Opslaan van ombi standaardinstellingen mislukt.",
|
"errorSetOmbiDefaults": "Opslaan van ombi standaardinstellingen mislukt.",
|
||||||
"errorLoadOmbiUsers": "Laden van ombi gebruikers mislukt.",
|
"errorLoadOmbiUsers": "Laden van ombi gebruikers mislukt.",
|
||||||
"errorChangedEmailAddress": "Wijzigen van emailadres van {n} mislukt.",
|
"errorChangedEmailAddress": "Wijzigen van e-mailadres van {n} mislukt.",
|
||||||
"errorFailureCheckLogs": "Mislukt (controleer console/logbestanden)",
|
"errorFailureCheckLogs": "Mislukt (controleer console/logbestanden)",
|
||||||
"errorPartialFailureCheckLogs": "Gedeeltelijke fout (controleer console/logbestanden)"
|
"errorPartialFailureCheckLogs": "Gedeeltelijke fout (controleer console/logbestanden)"
|
||||||
},
|
},
|
||||||
|
|
||||||
"quantityStrings": {
|
"quantityStrings": {
|
||||||
"modifySettingsFor": {
|
"modifySettingsFor": {
|
||||||
"singular": "Wijzig instellingen voor {n} gebruiker",
|
"singular": "Wijzig instellingen voor {n} gebruiker",
|
||||||
|
@ -37,5 +37,12 @@
|
|||||||
"toJoin": "To join, follow the below link.",
|
"toJoin": "To join, follow the below link.",
|
||||||
"inviteExpiry": "This invite will expire on {n}, at {n}, which is in {n}, so act quick.",
|
"inviteExpiry": "This invite will expire on {n}, at {n}, which is in {n}, so act quick.",
|
||||||
"linkButton": "Setup your account"
|
"linkButton": "Setup your account"
|
||||||
|
},
|
||||||
|
"welcomeEmail": {
|
||||||
|
"title": "Welcome to Jellyfin",
|
||||||
|
"welcome": "Welcome to Jellyfin!",
|
||||||
|
"youCanLoginWith": "You can login with the details below",
|
||||||
|
"jellyfinURL": "URL",
|
||||||
|
"username": "Username"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,17 +5,17 @@
|
|||||||
},
|
},
|
||||||
"userCreated": {
|
"userCreated": {
|
||||||
"title": "Notification : Utilisateur créé",
|
"title": "Notification : Utilisateur créé",
|
||||||
"aUserWasCreated": "Un utilisateur a été créé avec ce code {n}",
|
"aUserWasCreated": "Un utilisateur a été créé avec ce code {n}.",
|
||||||
"name": "Nom",
|
"name": "Nom",
|
||||||
"emailAddress": "Adresse",
|
"emailAddress": "Adresse",
|
||||||
"time": "Date",
|
"time": "Date",
|
||||||
"notificationNotice": ""
|
"notificationNotice": "Note : Les emails de notification peuvent être activés sur le tableau de bord administrateur."
|
||||||
},
|
},
|
||||||
"inviteExpiry": {
|
"inviteExpiry": {
|
||||||
"title": "Notification : Invitation expirée",
|
"title": "Notification : Invitation expirée",
|
||||||
"inviteExpired": "Invitation expirée.",
|
"inviteExpired": "Invitation expirée.",
|
||||||
"expiredAt": "Le code {n} a expiré à {n}.",
|
"expiredAt": "Le code {n} a expiré à {n}.",
|
||||||
"notificationNotice": ""
|
"notificationNotice": "Note : Les emails de notification peuvent être activés sur le tableau de bord administrateur."
|
||||||
},
|
},
|
||||||
"passwordReset": {
|
"passwordReset": {
|
||||||
"title": "Réinitialisation de mot du passe demandée - Jellyfin",
|
"title": "Réinitialisation de mot du passe demandée - Jellyfin",
|
||||||
@ -38,5 +38,12 @@
|
|||||||
"toJoin": "Pour continuer, suis le lien en dessous.",
|
"toJoin": "Pour continuer, suis le lien en dessous.",
|
||||||
"inviteExpiry": "L'invitation expirera le {n}, à {n}, soit dans {n}, alors fais vite !",
|
"inviteExpiry": "L'invitation expirera le {n}, à {n}, soit dans {n}, alors fais vite !",
|
||||||
"linkButton": "Lien"
|
"linkButton": "Lien"
|
||||||
|
},
|
||||||
|
"welcomeEmail": {
|
||||||
|
"youCanLoginWith": "Tu peux te connecter avec les informations ci-dessous",
|
||||||
|
"title": "Bienvenue sur Jellyfin",
|
||||||
|
"welcome": "Bienvenue sur Jellyfin !",
|
||||||
|
"jellyfinURL": "URL",
|
||||||
|
"username": "Nom d'utilisateur"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
"createAccountHeader": "Création du compte",
|
"createAccountHeader": "Création du compte",
|
||||||
"accountDetails": "Détails",
|
"accountDetails": "Détails",
|
||||||
"emailAddress": "Email",
|
"emailAddress": "Email",
|
||||||
"username": "Pseudo",
|
"username": "Nom d'utilisateur",
|
||||||
"password": "Mot de passe",
|
"password": "Mot de passe",
|
||||||
"reEnterPassword": "Confirmez mot de passe",
|
"reEnterPassword": "Confirmez mot de passe",
|
||||||
"reEnterPasswordInvalid": "Les mots de passe ne correspondent pas.",
|
"reEnterPasswordInvalid": "Les mots de passe ne correspondent pas.",
|
||||||
|
38
mail/welcome.mjml
Normal file
38
mail/welcome.mjml
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<mjml>
|
||||||
|
<mj-head>
|
||||||
|
<mj-attributes>
|
||||||
|
<mj-class name="bg" background-color="#101010" />
|
||||||
|
<mj-class name="bg2" background-color="#242424" />
|
||||||
|
<mj-class name="text" color="rgba(255,255,255,0.8)" />
|
||||||
|
<mj-class name="bold" color="rgba(255,255,255,0.87)" />
|
||||||
|
<mj-class name="secondary" color="rgb(153,153,153)" />
|
||||||
|
<mj-class name="blue" background-color="rgb(0,164,220)" />
|
||||||
|
</mj-attributes>
|
||||||
|
<mj-font name="Quicksand" href="https://fonts.googleapis.com/css2?family=Quicksand" />
|
||||||
|
<mj-font name="Noto Sans" href="https://fonts.googleapis.com/css2?family=Noto+Sans" />
|
||||||
|
</mj-head>
|
||||||
|
<mj-body>
|
||||||
|
<mj-section mj-class="bg2">
|
||||||
|
<mj-column>
|
||||||
|
<mj-text mj-class="bold" font-size="25px" font-family="Quicksand, Noto Sans, Helvetica, Arial, sans-serif"> Jellyfin </mj-text>
|
||||||
|
</mj-column>
|
||||||
|
</mj-section>
|
||||||
|
<mj-section mj-class="bg">
|
||||||
|
<mj-column>
|
||||||
|
<mj-text mj-class="text" font-size="16px" font-family="Noto Sans, Helvetica, Arial, sans-serif">
|
||||||
|
<h3>{{ .welcome }}</h3>
|
||||||
|
<p>{{ .youCanLoginWith }}:</p>
|
||||||
|
{{ .jellyfinURL }}: <a href="{{ .jellyfinURLVal }}">{{ .jellyfinURLVal }}</a>
|
||||||
|
<p>{{ .username }}: <i>{{ .usernameVal }}</i></p>
|
||||||
|
</mj-text>
|
||||||
|
</mj-column>
|
||||||
|
</mj-section>
|
||||||
|
<mj-section mj-class="bg2">
|
||||||
|
<mj-column>
|
||||||
|
<mj-text mj-class="secondary" font-style="italic" font-size="14px">
|
||||||
|
{{ .message }}
|
||||||
|
</mj-text>
|
||||||
|
</mj-column>
|
||||||
|
</mj-section>
|
||||||
|
</body>
|
||||||
|
</mjml>
|
9
mail/welcome.txt
Normal file
9
mail/welcome.txt
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{{ .welcome }}
|
||||||
|
|
||||||
|
{{ .youCanLoginWith }}:
|
||||||
|
|
||||||
|
{{ .jellyfinURL }}: {{ .jellyfinURLVal }}
|
||||||
|
{{ .username }}: {{ .usernameVal }}
|
||||||
|
|
||||||
|
|
||||||
|
{{ .message }}
|
32
models.go
32
models.go
@ -17,6 +17,12 @@ type newUserDTO struct {
|
|||||||
Code string `json:"code" example:"abc0933jncjkcjj"` // Invite code (required on /newUser)
|
Code string `json:"code" example:"abc0933jncjkcjj"` // Invite code (required on /newUser)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type newUserResponse struct {
|
||||||
|
User bool `json:"user" binding:"required"` // Whether user was created successfully
|
||||||
|
Email bool `json:"email"` // Whether welcome email was successfully sent (always true if feature is disabled
|
||||||
|
Error string `json:"error"` // Optional error message.
|
||||||
|
}
|
||||||
|
|
||||||
type deleteUserDTO struct {
|
type deleteUserDTO struct {
|
||||||
Users []string `json:"users" binding:"required"` // List of usernames to delete
|
Users []string `json:"users" binding:"required"` // List of usernames to delete
|
||||||
Notify bool `json:"notify"` // Whether to notify users of deletion
|
Notify bool `json:"notify"` // Whether to notify users of deletion
|
||||||
@ -32,6 +38,7 @@ type generateInviteDTO struct {
|
|||||||
NoLimit bool `json:"no-limit" example:"false"` // No invite use limit
|
NoLimit bool `json:"no-limit" example:"false"` // No invite use limit
|
||||||
RemainingUses int `json:"remaining-uses" example:"5"` // Remaining invite uses
|
RemainingUses int `json:"remaining-uses" example:"5"` // Remaining invite uses
|
||||||
Profile string `json:"profile" example:"DefaultProfile"` // Name of profile to apply on this invite
|
Profile string `json:"profile" example:"DefaultProfile"` // Name of profile to apply on this invite
|
||||||
|
Label string `json:"label" example:"For Friends"` // Optional label for the invite
|
||||||
}
|
}
|
||||||
|
|
||||||
type inviteProfileDTO struct {
|
type inviteProfileDTO struct {
|
||||||
@ -61,18 +68,19 @@ type newProfileDTO struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type inviteDTO struct {
|
type inviteDTO struct {
|
||||||
Code string `json:"code" example:"sajdlj23423j23"` // Invite code
|
Code string `json:"code" example:"sajdlj23423j23"` // Invite code
|
||||||
Days int `json:"days" example:"1"` // Number of days till expiry
|
Days int `json:"days" example:"1"` // Number of days till expiry
|
||||||
Hours int `json:"hours" example:"2"` // Number of hours till expiry
|
Hours int `json:"hours" example:"2"` // Number of hours till expiry
|
||||||
Minutes int `json:"minutes" example:"3"` // Number of minutes till expiry
|
Minutes int `json:"minutes" example:"3"` // Number of minutes till expiry
|
||||||
Created string `json:"created" example:"01/01/20 12:00"` // Date of creation
|
Created string `json:"created" example:"01/01/20 12:00"` // Date of creation
|
||||||
Profile string `json:"profile" example:"DefaultProfile"` // Profile used on this invite
|
Profile string `json:"profile" example:"DefaultProfile"` // Profile used on this invite
|
||||||
UsedBy [][]string `json:"used-by,omitempty"` // Users who have used this invite
|
UsedBy [][]string `json:"used-by,omitempty"` // Users who have used this invite
|
||||||
NoLimit bool `json:"no-limit,omitempty"` // If true, invite can be used any number of times
|
NoLimit bool `json:"no-limit,omitempty"` // If true, invite can be used any number of times
|
||||||
RemainingUses int `json:"remaining-uses,omitempty"` // Remaining number of uses (if applicable)
|
RemainingUses int `json:"remaining-uses,omitempty"` // Remaining number of uses (if applicable)
|
||||||
Email string `json:"email,omitempty"` // Email the invite was sent to (if applicable)
|
Email string `json:"email,omitempty"` // Email the invite was sent to (if applicable)
|
||||||
NotifyExpiry bool `json:"notify-expiry,omitempty"` // Whether to notify the requesting user of expiry or not
|
NotifyExpiry bool `json:"notify-expiry,omitempty"` // Whether to notify the requesting user of expiry or not
|
||||||
NotifyCreation bool `json:"notify-creation,omitempty"` // Whether to notify the requesting user of account creation or not
|
NotifyCreation bool `json:"notify-creation,omitempty"` // Whether to notify the requesting user of account creation or not
|
||||||
|
Label string `json:"label,omitempty" example:"For Friends"` // Optional label for the invite
|
||||||
}
|
}
|
||||||
|
|
||||||
type getInvitesDTO struct {
|
type getInvitesDTO struct {
|
||||||
|
@ -41,6 +41,7 @@ type Invite struct {
|
|||||||
UsedBy [][]string `json:"used-by"`
|
UsedBy [][]string `json:"used-by"`
|
||||||
Notify map[string]map[string]bool `json:"notify"`
|
Notify map[string]map[string]bool `json:"notify"`
|
||||||
Profile string `json:"profile"`
|
Profile string `json:"profile"`
|
||||||
|
Label string `json:"label,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Lang struct {
|
type Lang struct {
|
||||||
@ -71,6 +72,9 @@ func (st *Storage) loadLang() (err error) {
|
|||||||
|
|
||||||
// If a given language has missing values, fill it in with the english value.
|
// If a given language has missing values, fill it in with the english value.
|
||||||
func patchLang(english, other *langSection) {
|
func patchLang(english, other *langSection) {
|
||||||
|
if *other == nil {
|
||||||
|
*other = langSection{}
|
||||||
|
}
|
||||||
for n, ev := range *english {
|
for n, ev := range *english {
|
||||||
if v, ok := (*other)[n]; !ok || v == "" {
|
if v, ok := (*other)[n]; !ok || v == "" {
|
||||||
(*other)[n] = ev
|
(*other)[n] = ev
|
||||||
@ -215,6 +219,7 @@ func (st *Storage) loadLangEmail() error {
|
|||||||
patchLang(&english.PasswordReset, &lang.PasswordReset)
|
patchLang(&english.PasswordReset, &lang.PasswordReset)
|
||||||
patchLang(&english.UserDeleted, &lang.UserDeleted)
|
patchLang(&english.UserDeleted, &lang.UserDeleted)
|
||||||
patchLang(&english.InviteEmail, &lang.InviteEmail)
|
patchLang(&english.InviteEmail, &lang.InviteEmail)
|
||||||
|
patchLang(&english.WelcomeEmail, &lang.WelcomeEmail)
|
||||||
}
|
}
|
||||||
st.lang.Email[index] = lang
|
st.lang.Email[index] = lang
|
||||||
return nil
|
return nil
|
||||||
|
@ -214,13 +214,23 @@ export class accountsList {
|
|||||||
_post("/users", send, (req: XMLHttpRequest) => {
|
_post("/users", send, (req: XMLHttpRequest) => {
|
||||||
if (req.readyState == 4) {
|
if (req.readyState == 4) {
|
||||||
toggleLoader(button);
|
toggleLoader(button);
|
||||||
if (req.status == 200) {
|
if (req.status == 200 || (req.response["user"] as boolean)) {
|
||||||
window.notifications.customSuccess("addUser", window.lang.var("notifications", "userCreated", `"${send['username']}"`));
|
window.notifications.customSuccess("addUser", window.lang.var("notifications", "userCreated", `"${send['username']}"`));
|
||||||
|
if (!req.response["email"]) {
|
||||||
|
window.notifications.customError("sendWelcome", window.lang.notif("errorSendWelcomeEmail"));
|
||||||
|
console.log("User created, but welcome email failed");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
window.notifications.customError("addUser", window.lang.var("notifications", "errorUserCreated", `"${send['username']}"`));
|
||||||
}
|
}
|
||||||
|
if (req.response["error"] as String) {
|
||||||
|
console.log(req.response["error"]);
|
||||||
|
}
|
||||||
|
|
||||||
this.reload();
|
this.reload();
|
||||||
window.modals.addUser.close();
|
window.modals.addUser.close();
|
||||||
}
|
}
|
||||||
});
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteUsers = () => {
|
deleteUsers = () => {
|
||||||
|
@ -25,7 +25,18 @@ export class DOMInvite implements Invite {
|
|||||||
document.dispatchEvent(inviteDeletedEvent);
|
document.dispatchEvent(inviteDeletedEvent);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
private _label: string = "";
|
||||||
|
get label(): string { return this._label; }
|
||||||
|
set label(label: string) {
|
||||||
|
this._label = label;
|
||||||
|
const linkEl = this._codeArea.querySelector("a") as HTMLAnchorElement;
|
||||||
|
if (label == "") {
|
||||||
|
linkEl.textContent = this.code.replace(/-/g, '-');
|
||||||
|
} else {
|
||||||
|
linkEl.textContent = label;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private _code: string = "None";
|
private _code: string = "None";
|
||||||
get code(): string { return this._code; }
|
get code(): string { return this._code; }
|
||||||
set code(code: string) {
|
set code(code: string) {
|
||||||
@ -36,7 +47,9 @@ export class DOMInvite implements Invite {
|
|||||||
}
|
}
|
||||||
this._codeLink = codeLink + "invite/" + code;
|
this._codeLink = codeLink + "invite/" + code;
|
||||||
const linkEl = this._codeArea.querySelector("a") as HTMLAnchorElement;
|
const linkEl = this._codeArea.querySelector("a") as HTMLAnchorElement;
|
||||||
linkEl.textContent = code.replace(/-/g, '-');
|
if (this.label == "") {
|
||||||
|
linkEl.textContent = code.replace(/-/g, '-');
|
||||||
|
}
|
||||||
linkEl.href = this._codeLink;
|
linkEl.href = this._codeLink;
|
||||||
}
|
}
|
||||||
private _codeLink: string;
|
private _codeLink: string;
|
||||||
@ -345,6 +358,9 @@ export class DOMInvite implements Invite {
|
|||||||
this.profile = invite.profile;
|
this.profile = invite.profile;
|
||||||
this.remainingUses = invite.remainingUses;
|
this.remainingUses = invite.remainingUses;
|
||||||
this.usedBy = invite.usedBy;
|
this.usedBy = invite.usedBy;
|
||||||
|
if (invite.label) {
|
||||||
|
this.label = invite.label;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
asElement = (): HTMLDivElement => { return this._container; }
|
asElement = (): HTMLDivElement => { return this._container; }
|
||||||
@ -443,6 +459,7 @@ function parseInvite(invite: { [f: string]: string | number | string[][] | boole
|
|||||||
let parsed: Invite = {};
|
let parsed: Invite = {};
|
||||||
parsed.code = invite["code"] as string;
|
parsed.code = invite["code"] as string;
|
||||||
parsed.email = invite["email"] as string || "";
|
parsed.email = invite["email"] as string || "";
|
||||||
|
parsed.label = invite["label"] as string || "";
|
||||||
let time = "";
|
let time = "";
|
||||||
const fields = ["days", "hours", "minutes"];
|
const fields = ["days", "hours", "minutes"];
|
||||||
for (let i = 0; i < fields.length; i++) {
|
for (let i = 0; i < fields.length; i++) {
|
||||||
@ -468,6 +485,7 @@ export class createInvite {
|
|||||||
private _infUsesWarning = document.getElementById('create-inf-uses-warning') as HTMLParagraphElement;
|
private _infUsesWarning = document.getElementById('create-inf-uses-warning') as HTMLParagraphElement;
|
||||||
private _createButton = document.getElementById("create-submit") as HTMLSpanElement;
|
private _createButton = document.getElementById("create-submit") as HTMLSpanElement;
|
||||||
private _profile = document.getElementById("create-profile") as HTMLSelectElement;
|
private _profile = document.getElementById("create-profile") as HTMLSelectElement;
|
||||||
|
private _label = document.getElementById("create-label") as HTMLInputElement;
|
||||||
|
|
||||||
private _days = document.getElementById("create-days") as HTMLSelectElement;
|
private _days = document.getElementById("create-days") as HTMLSelectElement;
|
||||||
private _hours = document.getElementById("create-hours") as HTMLSelectElement;
|
private _hours = document.getElementById("create-hours") as HTMLSelectElement;
|
||||||
@ -492,6 +510,9 @@ export class createInvite {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get label(): string { return this._label.value; }
|
||||||
|
set label(label: string) { this._label.value = label; }
|
||||||
|
|
||||||
get sendToEnabled(): boolean {
|
get sendToEnabled(): boolean {
|
||||||
return this._sendToEnabled.checked;
|
return this._sendToEnabled.checked;
|
||||||
}
|
}
|
||||||
@ -599,7 +620,8 @@ export class createInvite {
|
|||||||
"no-limit": this.infiniteUses,
|
"no-limit": this.infiniteUses,
|
||||||
"remaining-uses": this.uses,
|
"remaining-uses": this.uses,
|
||||||
"email": this.sendToEnabled ? this.sendTo : "",
|
"email": this.sendToEnabled ? this.sendTo : "",
|
||||||
"profile": this.profile
|
"profile": this.profile,
|
||||||
|
"label": this.label
|
||||||
};
|
};
|
||||||
_post("/invites", send, (req: XMLHttpRequest) => {
|
_post("/invites", send, (req: XMLHttpRequest) => {
|
||||||
if (req.readyState == 4) {
|
if (req.readyState == 4) {
|
||||||
@ -623,6 +645,7 @@ export class createInvite {
|
|||||||
this._createButton.onclick = this.create;
|
this._createButton.onclick = this.create;
|
||||||
this.sendTo = "";
|
this.sendTo = "";
|
||||||
this.uses = 1;
|
this.uses = 1;
|
||||||
|
this.label = "";
|
||||||
|
|
||||||
this._days.onchange = this._checkDurationValidity;
|
this._days.onchange = this._checkDurationValidity;
|
||||||
this._hours.onchange = this._checkDurationValidity;
|
this._hours.onchange = this._checkDurationValidity;
|
||||||
|
@ -86,6 +86,7 @@ interface Invite {
|
|||||||
notifyExpiry?: boolean;
|
notifyExpiry?: boolean;
|
||||||
notifyCreation?: boolean;
|
notifyCreation?: boolean;
|
||||||
profile?: string;
|
profile?: string;
|
||||||
|
label?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface inviteList {
|
interface inviteList {
|
||||||
|
Loading…
Reference in New Issue
Block a user