Servez votre site et vendez des cours avec un serveur auto-hébergé.
SServer est un serveur simple sans tête pour l'hébergement des cours et un contenu blog / statique associé à partir du référentiel GitHub privé avec des frais généraux minimaux.
Il fournit HTTPS hors de la boîte afin que vous n'ayez pas à faire face aux certificats d'installation / gestion. Il synchronise automatiquement le contenu à partir de GitHub afin que vous n'ayez pas à télécharger votre contenu sur serveur. Il prend également en charge le contenu premium avec un fichier de configuration simple sans affecter votre flux de travail de contenu pour EG si vous utilisez un générateur de sites statique comme Hugo, vous pouvez masquer le contenu premium au public en le spécifiant dans le fichier de configuration. Il a une intégration de rayures afin que vous puissiez vendre votre contenu premium. Il a une gestion des utilisateurs intégrée pour l'ajout / authentification des utilisateurs. Il dispose également d'une API d'administration afin que vous puissiez surveiller les commandes / utilisateurs de votre site.
Voici quelques exemples de la façon dont il peut être utilisé, assurez-vous de définir SS _ <> Variables d'environnement avant de les essayer, par exemple
export SS_GITHUB_TOKEN=<github_token>
export SS_STRIPE_TOKEN=<stripe_token>
export SS_SMTP_FROM=<email_id>
export SS_SMTP_USER=<smtp_username>
export SS_SMTP_PWD=<smtp_password>
export SS_SMTP_HOST=<smtp_host_address>
export SS_SMTP_PORT=<smtp_port>
export SS_ADMIN_EMAIL=<admin_email>
export SS_ADMIN_PWD=<admin_password_for_sserver>
./sserver -repo "https://github.com/newbeelearn/sserver.git"
Le référentiel doit avoir index.html et ssconfig.toml dans son répertoire racine. Si Hugo / Jekyll etc. Comme le générateur de sites statique est utilisé, le référentiel doit contenir le site généré. (Il aurait index.html en racine par défaut)
./sserver -repo "https://github.com/newbeelearn/sserver.git?folder=public"
Le référentiel doit avoir index.html dans le dossier à partir de l'endroit où vous souhaitez servir le contenu, il est généralement public si Hugo / Jekyll etc. Les générateurs de sites statiques sont utilisés. Il devrait avoir ssconfig.toml dans le répertoire racine
./sserver -repo "https://github.com/newbeelearn/sserver.git?ref=test-config"
La branche doit avoir index.html et ssconfig.toml dans son répertoire racine. Si Hugo / Jekyll etc. Comme le générateur de sites statique est utilisé, la branche doit contenir le site généré (il aurait index.html en racine par défaut)
./sserver -repo "https://github.com/newbeelearn/sserver.git?domain=example.com"
Le référentiel doit avoir index.html et ssconfig.toml dans son répertoire racine l'accès au domaine à partir duquel le site est servi SServer devrait avoir des autorisations pour se lier au port 443, cela peut être fait avec la commande suivante
sudo setcap 'cap_net_bind_service=+ep' sserver
./sserver -repo "file:///workspace/projects/newbeelearn.com/sserver"
Le référentiel doit avoir index.html et ssconfig.toml dans son répertoire racine. Toutes les options IE Folder / Domain, etc. peuvent également être spécifiées en cas de fichiers locaux
Un échantillon ssconfig.toml peut être trouvé ci-dessous
# specify the site
[site]
# period to check for new content
syncinterval = "@every 12h"
# product/course details
[[site.prod]]
name = "course1"
# path from root, this will be accessible to users who have bought the course
path = "courses/course1"
# can be draft/active, buying functionality will be enabled when status is active
status = "active"
# unique identifier for the course
sku = "prod-course-1"
# price in cents
price = 10000
# currency
currency = "USD"
SServer crée un répertoire "wwwss" d'où il est exécuté
drwxrwxr-x 2 test test 4096 Nov 30 17:04 a
drwxrwxr-x 8 test test 4096 Nov 30 17:04 b
drwxrwxr-x 2 test test 4096 Nov 30 17:04 certs
drwxrwxr-x 2 test test 4096 Nov 30 17:04 logs
-rw-rw-r-- 1 test test 527483 Nov 30 17:04 tmp.zip
-rw-rw-r-- 1 test test 49152 Nov 30 17:05 ssapp.db
Le fichier de configuration est utilisé pour spécifier les produits / cours que vous souhaitez vendre ainsi que certains paramètres de serveur comme la fréquence à laquelle le site doit être synchronisé, etc.
L'exemple de fichier ssconfig.toml est illustré ci-dessous
#specify the site
[site]
#period to check for new content default is 12 hours
syncinterval = "@every 12h"
[[site.prod]]
name = "course1"
path = "courses/course1"
status = "active"
sku = "prod-course-1"
price = 10000
currency = "USD"
Tous les points de terminaison de l'API sont relatifs au domaine utilisé pour servir le contenu, c'est-à-dire si le domaine est example.com et qu'API est /api/v1/product/list
Demande serait https://example.com/api/v1/product/list
La hiérarchie des rôles est comme cet administrateur> utilisateur> invité toute API accessible à l'invité est également accessible à l'utilisateur et toute API accessible à l'utilisateur est également accessible à l'administrateur pour accéder au cookie de session de l'API de l'utilisateur obtenu après la connexion doit être fourni avec chaque demande dans pratiquer cela sera pris en charge par le navigateur
Description | Demande | Rôle |
---|---|---|
Enregistrer l'utilisateur | Post /api/v1/user/register | invité |
Utilisateur de connexion | Post /api/v1/user/login | invité |
Déconnexion | Get /api/v1/user/logout | invité |
Vérifier l'utilisateur | Get /api/v1/user/verify/:id | invité |
Réinitialiser le mot de passe de l'utilisateur | Post /api/v1/user/reset | invité |
Obtenir la liste des produits | Get /api/v1/product/list | invité |
Créer une commande | Post /api/v1/order/id | invité |
Modifier la commande | Put /api/v1/order/id | utilisateur |
Commande de paiement | Post /api/v1/order/checkout | utilisateur |
Obtenez la commande par ID de commande | Get /api/v1/order/id/:id | utilisateur |
Obtenez toutes les commandes par l'utilisateur | Get /api/v1/order/id/list | utilisateur |
Modifier le mot de passe utilisateur | Post /api/v1/user/changepwd | utilisateur |
Obtenez toutes les commandes | Get /api/v1/order/list | administrer |
Obtenez tous les utilisateurs | Get /api/v1/user/list | administrer |
Enregistrez le nouvel utilisateur avec e-mail et mot de passe. Envoie le courrier à l'e-mail utilisé pour s'inscrire avec le code de vérification si la configuration du serveur SMTP est définie.
Exemple de demande
curl 'http://localhost:54545/api/v1/user/register'
-H 'Content-Type: application/x-www-form-urlencoded'
-X POST
--data-raw 'email=stripe%40newbeelearn.com&password=test&confirm-password=test&remember=on'
Exemple de réponse
{"status":"success"}
Connectez-vous à l'utilisateur avec e-mail et mot de passe. Renvoie JSON Si le champ "Postlogin" n'est pas défini dans le fichier de configuration, sinon, il redirige vers la page spécifiée dans "Postlogin"
Exemple de demande
curl 'http://localhost:54545/api/v1/user/login'
-H 'Content-Type: application/x-www-form-urlencoded'
-X POST
--data-raw 'email=admin%40example.com&password=admin'
Exemple de réponse
{
"data": {
"user_id": "1",
"username": ""
},
"msg": "user found",
"status": "success"
}
Connects connectés à l'utilisateur et redirige vers la page d'accueil
Exemple de demande
curl 'http://localhost:54545/api/v1/user/logout'
-H 'Cookie: session_id=9e8b22a3-15ac-442f-bf65-15c37dbfc889; max-age=300; path=/; secure; SameSite=Lax'
Exemple de réponse
<!doctype html>
<html lang="en">
<head>
</head>
<body>
</body>
</html>
Vérifie l'e-mail de l'utilisateur enregistré en envoyant une URL si le domaine est défini ou le code qui doit être ajouté après l'API Vérifier si le domaine n'est pas défini
Exemple de demande
curl 'http://localhost:54545/api/v1/user/verify/cafj5grn0gpog1j3a0m0'
Exemple de réponse
{"status":"success"}
Réinitialise le mot de passe de l'utilisateur et envoie le nouveau code temporaire pour la connexion. L'utilisateur doit utiliser ce code lors de la connexion suivante et modifier le mot de passe
Exemple de demande
curl 'http://localhost:54545/api/v1/user/reset'
-H 'Content-Type: application/x-www-form-urlencoded'
-X POST
--data-raw 'email=stripe%40newbeelearn.com'
Exemple de réponse
{
"data": null,
"msg": "password reset successful",
"status": "success"
}
Obtenez tous les produits répertoriés à vendre sur le site Web. Prend "Limit" et "Offset" en tant que requêtes. Si la requête n'est pas définie, les valeurs de limite par défaut sont définies sur 10 et le décalage sur 0
Exemple de demande
curl 'http://localhost:54545/api/v1/product/list?limit=1&offset=0'
Exemple de réponse
{
"data": [
{
"prd_id": 1,
"prd_name": "course1",
"sku": "prod-course-1",
"permalink": "users/list/",
"price": 10000,
"currency": "USD",
"period": 365,
"status": "active"
}
],
"msg": "Order found",
"status": "success"
}
Crée une nouvelle commande avec des produits répertoriés dans le champ "line_item"
. La demande doit être valide JSON. Les champs order_id/user_id
etc. sont remplis par le serveur, toute valeur factice peut être transmise.
Exemple de demande
curl 'http://localhost:54545/api/v1/order/id'
-H 'Content-Type: application/json; charset=utf-8'
-H 'Cookie: session_id=cad8439e-dcc4-475e-94fc-12b75f85bb20; max-age=300; path=/; secure; SameSite=Lax'
-X POST
--data-raw ' {
"order_id": 1,
"user_id": 3,
"currency": "USD",
"line_items": [
{
"sku": "prod-course-1"
},
{
"sku": "prod-course-3"
}
]
}'
Exemple de réponse
{
"data": {
"order_id": 1,
"user_id": 3,
"created_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"modified_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"status": "active",
"currency": "USD",
"order_number": "cafjktbn0gpp5hq3dt4g",
"grand_total": 11000,
"line_items": [
{
"line_id": 1,
"order_id": 1,
"prd_id": 1,
"created_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"modified_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"grand": 10000,
"enabled": true,
"sku": "prod-course-1"
},
{
"line_id": 2,
"order_id": 1,
"prd_id": 2,
"created_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"modified_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"grand": 1000,
"enabled": true,
"sku": "prod-course-3"
}
]
},
"msg": "Order found",
"status": "success"
}
Modifie la commande existante en ajoutant / supprimant des produits dans le champ line_item
. L'utilisateur doit être connecté pour modifier l'ordre et l'ordre doit être à l'état actif. Utilisez la réponse précédente de Créer une commande ou passez de l'ordre pour ajouter / supprimer des produits
Exemple de demande
curl 'http://localhost:54545/api/v1/order/id'
-H 'Content-Type: application/json; charset=utf-8'
-H 'Cookie: session_id=cad8439e-dcc4-475e-94fc-12b75f85bb20; max-age=300; path=/; secure; SameSite=Lax'
-X PUT
--data-raw ' {
"order_id": 1,
"user_id": 3,
"created_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"modified_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"status": "active",
"currency": "USD",
"order_number": "cafjktbn0gpp5hq3dt4g",
"grand_total": 11000,
"line_items": [
{
"line_id": 2,
"order_id": 1,
"prd_id": 2,
"created_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"modified_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"grand": 1000,
"enabled": true,
"sku": "prod-course-3"
}
]
}'
Exemple de réponse
{
"data": {
"order_id": 1,
"user_id": 3,
"created_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"modified_at": "2022-06-07 11:48:05.425488765 +0000 UTC",
"status": "active",
"currency": "USD",
"order_number": "cafjktbn0gpp5hq3dt4g",
"grand_total": 1000,
"line_items": [
{
"line_id": 2,
"order_id": 1,
"prd_id": 2,
"created_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"modified_at": "2022-06-07 11:48:05.425488765 +0000 UTC",
"grand": 1000,
"enabled": true,
"sku": "prod-course-3"
}
]
},
"msg": "Order found",
"status": "success"
}
Obtient une URL Stripe pour le paiement de la commande créée par API Créer des commandes. Utilisez la réponse à partir de l'API Créer / modifier Order / Get Order pour envoyer la demande. Ne modifiez pas la réponse dans cette demande, cela entraînera une défaillance.
Exemple de demande
curl 'http://localhost:54545/api/v1/order/checkout'
-H 'Content-Type: application/json; charset=utf-8'
-H 'Cookie: session_id=2f1be070-7256-4e84-a4ef-c14754cabcdb; max-age=300; path=/; secure; SameSite=Lax'
-X POST
--data-raw ' {
"order_id": 1,
"user_id": 3,
"created_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"modified_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"status": "active",
"currency": "USD",
"order_number": "cafjktbn0gpp5hq3dt4g",
"grand_total": 11000,
"line_items": [
{
"line_id": 2,
"order_id": 1,
"prd_id": 2,
"created_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"modified_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"grand": 1000,
"enabled": true,
"sku": "prod-course-3"
}
]
}'
Exemple de réponse
{
"data": {
"url": "https://checkout.stripe.com/pay/cs_test_a17D2l74NsKMv29YJ1c5rSBPx7BGSsNAsObGAsOanEJqyFNXKEYDLji4BZ#fidkdWxOYHwnPyd1blpxYHZxWjA0TlVKPHNMaW9vYEd1YmhdUWQ3UUJqSEpMYTMza11ObGAyXDFPcXA8bz1yY1VicVZVdDN8c1NkaUZEazxIQWdjM04wdz1DTmF3PXxHaVE9bTVuZz1pUWw3NTUybHZLZldgaicpJ2N3amhWYHdzYHcnP3F3cGApJ2lkfGpwcVF8dWAnPyd2bGtiaWBabHFgaCcpJ2BrZGdpYFVpZGZgbWppYWB3dic%2FcXdwYHgl"
},
"msg": "Order found",
"status": "success"
}
Obtenez les détails de la commande par numéro de commande
Exemple de demande
curl 'http://localhost:54545/api/v1/order/id/cafjktbn0gpp5hq3dt4g'
-H 'Content-Type: application/json; charset=utf-8'
-H 'Cookie: session_id=fe9b9fff-c5c0-4745-becf-ecb0e5abca81; max-age=300; path=/; secure; SameSite=Lax'
Exemple de réponse
{
"data": {
"order_id": 1,
"user_id": 3,
"created_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"modified_at": "2022-06-07 11:48:05.425488765 +0000 UTC",
"status": "active",
"currency": "USD",
"order_number": "cafjktbn0gpp5hq3dt4g",
"grand_total": 1000,
"line_items": [
{
"line_id": 2,
"order_id": 1,
"prd_id": 2,
"created_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"modified_at": "2022-06-07 11:48:05.425488765 +0000 UTC",
"grand": 1000,
"enabled": true
}
]
},
"msg": "Order found",
"status": "success"
}
Obtenez toutes les commandes par l'utilisateur. Prend la limite et le décalage à mesure que les paramètres de requête les valeurs par défaut sont respectivement de 10 et 0
Exemple de demande
curl 'http://localhost:54545/api/v1/order/id/list?limit=1&offset=0'
-H 'Content-Type: application/json; charset=utf-8'
-H 'Cookie: session_id=fe9b9fff-c5c0-4745-becf-ecb0e5abca81; max-age=300; path=/; secure; SameSite=Lax'
Exemple de réponse
{
"data": [
{
"order_id": 1,
"user_id": 3,
"created_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"modified_at": "2022-06-07 11:48:05.425488765 +0000 UTC",
"status": "active",
"currency": "USD",
"order_number": "cafjktbn0gpp5hq3dt4g",
"grand_total": 1000
}
],
"msg": "Order found",
"status": "success"
}
Modifier le mot de passe utilisateur. L'utilisateur doit être connecté pour faire cette demande
Exemple de demande
curl 'http://localhost:54545/api/v1/user/changepwd'
-H 'Content-Type: application/x-www-form-urlencoded'
-H 'Cookie: session_id=fe9b9fff-c5c0-4745-becf-ecb0e5abca81; max-age=300; path=/; secure; SameSite=Lax'
-X POST
--data-raw 'oldpassword=cafjjjbn0gpp5hq3dt40&password=test123'
Exemple de réponse
{
"data": null,
"msg": "password change successful",
"status": "success"
}
Obtenez toutes les commandes créées dans le magasin. Prend des limites et des décalages car les paramètres de requête Les valeurs par défaut sont 10 et 0 respectivement disponibles pour les utilisateurs d'administration uniquement. Obtenez toutes les commandes
Exemple de demande
curl 'http://localhost:54545/api/v1/order/list?limit=1&offset=0'
-H 'Content-Type: application/json; charset=utf-8'
-H 'Cookie: session_id=e4ecd3a4-b8be-493e-a33d-518ab11c65e8; max-age=300; path=/; secure; SameSite=Lax'
Exemple de réponse
{
"data": [
{
"order_id": 1,
"user_id": 3,
"created_at": "2022-06-07 11:45:57.601996759 +0000 UTC",
"modified_at": "2022-06-07 11:48:05.425488765 +0000 UTC",
"status": "active",
"currency": "USD",
"order_number": "cafjktbn0gpp5hq3dt4g",
"price_total": 1000,
"discount_total": 0,
"sub_total": 1000,
"taxes_total": 0,
"grand_total": 1000,
"refunds_total": 0,
"created_channel": "",
"payment_provider": ""
}
],
"msg": "Order found",
"status": "success"
}
Faites inscrire tous les utilisateurs sur le site Web. Prend des limites et des décalages car les paramètres de requête Les valeurs par défaut sont 10 et 0 respectivement disponibles pour les utilisateurs d'administration uniquement.
Exemple de demande
curl 'http://localhost:54545/api/v1/user/list?limit=1&offset=0'
-H 'Content-Type: application/json; charset=utf-8'
-H 'Cookie: session_id=e4ecd3a4-b8be-493e-a33d-518ab11c65e8; max-age=300; path=/; secure; SameSite=Lax'
Exemple de réponse
{
"data": [
{
"user_id": 1,
"email": "[email protected]",
"created_at": "2022-06-07 10:53:00.480128762 +0000 UTC",
"username": "",
"last_password_set": "2022-06-07 10:53:00.480128762 +0000 UTC",
"last_login": "2022-06-07 10:53:00.480128762 +0000 UTC",
"verified": 0,
"reset": 0,
"user_role": "admin"
},
{
"user_id": 2,
"email": "[email protected]",
"created_at": "2022-06-07 10:53:00.532691788 +0000 UTC",
"username": "",
"last_password_set": "2022-06-07 10:53:00.532691788 +0000 UTC",
"last_login": "2022-06-07 10:53:00.532691788 +0000 UTC",
"verified": 0,
"reset": 0,
"user_role": "guest"
},
{
"user_id": 3,
"email": "[email protected]",
"created_at": "2022-06-07 11:13:06.947313364 +0000 UTC",
"username": "",
"last_password_set": "2022-06-07 11:13:06.947313364 +0000 UTC",
"last_login": "2022-06-07 11:13:06.947313364 +0000 UTC",
"verified": 2,
"reset": 1,
"user_role": "user"
}
],
"msg": "Order found",
"status": "success"
}
Non, seuls des binaires sont publiés et le site est utilisé pour des discussions sur le produit.
Il est dans la fonctionnalité de stade alpha est terminé, mais il peut contenir des bugs
Cela a été créé en raison de la nécessité d'organiser des cours
Pas pour le moment, car l'abonnement n'est pas pris en charge, il est uniquement pour les produits numériques. Il n'a pas non plus de fonctionnalité de transfert d'itinéraire où votre propre SaaS peut être branché. Cependant, ces modifications peuvent être ajoutées s'il y a suffisamment d'intérêt pour commencer la discussion si vous souhaitez avoir ces fonctionnalités à ce jour, il n'est pas sur la feuille de route.
Il peut être utilisé pour l'hébergement des cours et des blogs associés. Blogs avec newsletter. Blogs avec contenu premium. Page de destination du démarrage et du blog associé. Thèmes de vente, etc.
Linux et MacOS sont pris en charge hors de la boîte. Les utilisateurs de Windows peuvent utiliser WSL mais il n'est pas testé.
Créer un problème et le marquer avec la fonctionnalité
Ce n'est pas encore décidé à ce jour, il est gratuit. Le produit payant si disponible utilisera un canal séparé. Donc, si vous téléchargez à partir de la version GitHub, c'est gratuit pour toujours. Aidez-nous à le décider, dites-nous ce que vous paieriez pour cela dans le forum de discussion.