Warning: session_start(): open(/var/lib/php/sessions/sess_51mlh017drls3b2ebmlrhs953e, O_RDWR) failed: No space left on device (28) in /var/www/tb-usercake/models/config.php on line 51
Warning: session_start(): Failed to read session data: files (path: /var/lib/php/sessions) in /var/www/tb-usercake/models/config.php on line 51
!7
sS passwordSalt() {
ret loadTextFileOrCreateWithRandomID(javaxSecretDir("password-salt"));
}
concept User {
S name;
SecretValue passwordMD5;
S contact; // e.g. mail address
bool isMaster;
toString { ret or2(name, super.toString()); }
}
extend AuthedDialogID {
new Ref user; // who is logged in
}
concept UserCreatedObject {
new Ref creator;
S nameInRepo; // unique by user, for URL
bool isPublic = true;
}
concept UserPost > UserCreatedObject {
S type, text;
}
concept PostReference {
new Ref post;
new Ref referenced;
S as;
}
!include once #1029928 // new Compact Module include
/*c*/module GazelleExamples > DynNewBot2 {
void start {
botName = heading = "Gazelle Examples";
adminName = heading + " Admin";
set enableUsers;
set useWebSockets;
set showRegisterLink;
unset showTalkToBotLink;
passwordSalt(); // make early
super.start();
indexConceptFieldCI(User, "name");
}
L crudClasses(Req req) {
L l = super.crudClasses(req);
l.add(UserPost);
if (req.masterAuthed)
l.add(User);
ret l;
}
S serveRegisterForm(SS params) {
S user = trim(params.get("user"));
S pw = trim(params.get("pw"));
S pw2 = trim(params.get("pw2"));
S redirect = params.get("redirect");
redirect = dropParamFromURL(redirect, "logout"); // don't log us out right again
if (empty(redirect)) redirect = baseLink + "/";
new LS msgs;
if (nempty(user) || nempty(pw)) {
lock dbLock();
if (empty(user)) msgs.add("Please enter a user name");
else if (l(user) < 4) msgs.add("Minimum user name length: 4 characters");
else if (l(user) > 30) msgs.add("Maximum user name length: 30 characters");
if (regexpContainsIC("[^a-z0-9\\-\\.]", user))
msgs.add("Bad characters in user name (please use only a-z, 0-9, - and .)");
if (empty(pw)) msgs.add("Please enter a password");
else if (l(pw) < 6) msgs.add("Minimum password length: 6 characters");
if (neq(pw, pw2)) msgs.add("Passwords don't match");
if (hasConceptIC User(name := user))
msgs.add("A user with this name exists, please choose another one");
if (empty(msgs)) {
cnew User(name := user, passwordMD5 := SecretValue(hashPW(pw)));
ret hrefresh(5.0, redirect) + "User " + user + " created! Redirecting...";
}
}
ret hhtml(hhead(htitle("Register new user")
+ hsansserif() + hmobilefix() + hresponstable()) + hbody(hfullcenter(
h3_htmlEncode(adminName + " | Register new user")
+ hpostform(
hhidden(+redirect)
+ tag table(
(empty(msgs) ? "" : tr(td() + td() + td(htmlEncode2_nlToBr(lines_rtrim(msgs)))))
+ tr(td_valignTop("Choose a user name:")
+ td_valignTop(hinputfield(+user) + "
" + "(Minimum length 4. Characters allowed: a-z, 0-9, - and .)"))
+ tr(td_valignTop("Choose a password:")
+ td_valignTop(hpassword(+pw) + "
" + "(Minimum length 6 characters)"))
+ tr(td_valignTop("Repeat the password please:") + td(hpassword(+pw2)))
+ tr(td() + td(hsubmit("Register"))), class := "responstable"),
action := baseLink + "/register")
)));
}
bool calcMasterAuthed(Req req) {
ret super.calcMasterAuthed(req)
|| req.auth != null && req.auth.user.has() && req.auth.user->isMaster;
}
O serveOtherPage(Req req) {
S uri = req.uri;
if (eq(uri, "/register"))
ret serveRegisterForm(req.params);
if (eq(uri, "/becomeMaster") && req.auth != null && req.auth.user != null) {
S pw = trim(req.params.get("masterPW"));
if (eq(pw, realPW())) {
cset(req.auth.user, isMaster := true);
ret "You are master, " + req.auth.user + "!";
}
if (nempty(pw))
ret "Bad master PW";
ret hhtml(hhead(htitle("Become master")
+ hsansserif() + hmobilefix() + hresponstable()) + hbody(hfullcenter(
h3_htmlEncode(adminName + " | Become master")
+ hpostform(
tag table(
tr(td_valignTop("You are:")
+ td_valignTop(htmlEncode2(req.auth.user->name)))
+ tr(td_valignTop("Enter the master password:")
+ td_valignTop(hpassword(masterPW := pw)))
+ tr(td() + td(hsubmit("Become master user"))), class := "responstable"),
action := baseLink + "/becomeMaster")
)));
}
ret super.serveOtherPage(req);
}
// handle user log-in (create/update AuthedDialogID concept)
O handleAuth(Req req, S cookie) null {
S name = trim(req.params.get('user)), pw = trim(req.params.get('pw));
if (nempty(name) && nempty(pw) && nempty(cookie)) {
Domain authDomain;
User user = conceptWhereCI User(+name);
if (user == null)
ret errorMsg("User " + htmlEncode2(name) + " not found");
if (!eq(getVar(user.passwordMD5), hashPW(pw)))
ret errorMsg("Bad password, please try again");
// auth
cset(uniq AuthedDialogID(+cookie), restrictedToDomain := null, master := user.isMaster, +user);
S redirect = req.params.get('redirect);
if (nempty(redirect))
ret hrefresh(redirect);
}
}
S hashPW(S pw) { ret md5(pw + passwordSalt()); }
MapSO filtersForClass(Class c, Req req) {
if (c == UserPost) {
User user = req.auth.user!;
if (!req.masterAuthed && !user.isMaster)
ret litmap(creator := user);
}
ret super.filtersForClass(c, req);
}
S loggedInUserDesc(Req req) {
ret req.auth == null ? "not logged in" : req.auth.user! == null ? (req.masterAuthed ? "master user" : "weird user") : "user " + req.auth.user->name;
}
HCRUD_Concepts crudData(Class c) {
HCRUD_Concepts cc = super.crudData(c);
if (c == UserPost) {
cc.addRenderer("text", new HCRUD_Data.TextArea(80, 10));
cc.fieldHelp(
type := "Type of post (any format)",
text := "Text contents of this post (any format)");
}
ret cc;
}
S authFormHeading() {
ret super.authFormHeading()
+ p(hsnippetimg_scaleToWidth(200, #1101484, 425, 257, title := "Sleepy Gazelle"));
}
} // end of module