wip
This commit is contained in:
parent
e765209ee3
commit
82ea25f1ec
162
zx
162
zx
@ -1403,6 +1403,11 @@ dialyze() ->
|
|||||||
%%% Create Realm & Sysop
|
%%% Create Realm & Sysop
|
||||||
|
|
||||||
create_realm() ->
|
create_realm() ->
|
||||||
|
ConfFile = filename:join(zomp_dir(), "zomp.conf"),
|
||||||
|
{ok, ZompConf} = file:consult(ConfFile),
|
||||||
|
create_realm(ZompConf).
|
||||||
|
|
||||||
|
create_realm(ZompConf) ->
|
||||||
Instructions =
|
Instructions =
|
||||||
"~n"
|
"~n"
|
||||||
" Enter a name for your new realm.~n"
|
" Enter a name for your new realm.~n"
|
||||||
@ -1415,22 +1420,64 @@ create_realm() ->
|
|||||||
RealmFile = filename:join(zomp_dir(), Realm ++ ".realm"),
|
RealmFile = filename:join(zomp_dir(), Realm ++ ".realm"),
|
||||||
case filelib:is_regular(RealmFile) of
|
case filelib:is_regular(RealmFile) of
|
||||||
false ->
|
false ->
|
||||||
create_realm(Realm);
|
create_realm(ZompConf, Realm);
|
||||||
true ->
|
true ->
|
||||||
ok = io:format("That realm already exists. Be more original.~n"),
|
ok = io:format("That realm already exists. Be more original.~n"),
|
||||||
create_realm()
|
create_realm(ZompConf)
|
||||||
end;
|
end;
|
||||||
false ->
|
false ->
|
||||||
ok = io:format("Bad realm name ~tp. Try again.~n", [Realm]),
|
ok = io:format("Bad realm name ~tp. Try again.~n", [Realm]),
|
||||||
create_realm()
|
create_realm(ZompConf)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
create_realm(Realm) ->
|
create_realm(ZompConf, Realm) ->
|
||||||
|
{external_address, XA} = lists:keyfind(external_address, 1, ZompConf),
|
||||||
|
XAString =
|
||||||
|
case inet:ntoa(XA) of
|
||||||
|
{error, einval} -> XA;
|
||||||
|
String -> String
|
||||||
|
end,
|
||||||
|
Message =
|
||||||
|
"~n"
|
||||||
|
" Enter a static, valid hostname or IPv4 or IPv6 address at which this host "
|
||||||
|
"can be reached from the public internet (or internal network if it will never "
|
||||||
|
"need to be reached from the internet).~n"
|
||||||
|
" The current public address is: ~ts. Press <ENTER> to keep this address.~n"
|
||||||
|
" DO NOT INCLUDE A PORT NUMBER IN THIS STEP~n",
|
||||||
|
ok = io:format(Message, [XAString]),
|
||||||
|
Input = get_input(),
|
||||||
|
ExAddress =
|
||||||
|
case
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{Host, Port} =
|
||||||
|
case proplists:get(external_address, 1, ZompConf) of
|
||||||
|
{external_address, ExAddress} ->
|
||||||
|
{external_port, ExPort} = lists:keyfind(external_port, 1, ZompConf),
|
||||||
|
{ExAddress, ExPort};
|
||||||
|
false ->
|
||||||
|
prompt_prime(Realm)
|
||||||
|
end,
|
||||||
|
HostString =
|
||||||
|
Instructions =
|
||||||
|
"~n"
|
||||||
|
" Accept current config?~n"
|
||||||
|
" Host: ~ts Port: ~w~n",
|
||||||
|
ok = io:format(Instructions, [Host, Port]),
|
||||||
|
case string:trim(io:get_line("(^C to quit) [Y]/n: ")) of
|
||||||
|
"" -> create_realm(Realm, Prime);
|
||||||
|
"Y" -> create_realm(Realm, Prime);
|
||||||
|
"y" -> create_realm(Realm, Prime);
|
||||||
|
_ -> prompt_prime(Realm)
|
||||||
|
end.
|
||||||
|
|
||||||
|
prompt_prime(Realm) ->
|
||||||
HostInstructions =
|
HostInstructions =
|
||||||
"~n"
|
"~n"
|
||||||
" Enter the prime (permanent) server's publicly accessible hostname or~n"
|
" Enter the prime (permanent) server's publicly accessible hostname or "
|
||||||
" address. If prime is identified by an address and not a name, enter it~n"
|
"address. If prime is identified by an address and not a name, enter it "
|
||||||
" as either a normal IPv4 dot-notation or IPv6 colon-notation.~n"
|
"as either a normal IPv4 dot-notation or IPv6 colon-notation.~n"
|
||||||
" Note that address ranges will not be checked for validity.~n",
|
" Note that address ranges will not be checked for validity.~n",
|
||||||
ok = io:format(HostInstructions),
|
ok = io:format(HostInstructions),
|
||||||
HostString = get_input(),
|
HostString = get_input(),
|
||||||
@ -1439,29 +1486,43 @@ create_realm(Realm) ->
|
|||||||
{ok, Address} -> Address;
|
{ok, Address} -> Address;
|
||||||
{error, einval} -> HostString
|
{error, einval} -> HostString
|
||||||
end,
|
end,
|
||||||
PortInstructions =
|
|
||||||
"~n"
|
create_prime(Realm, Host) ->
|
||||||
" Enter the port number the host will be listening on.~n"
|
ok = io:format("~n Enter the local port number on which the host listen.~n"),
|
||||||
" The port can be any number from 1 to 65535.~n"
|
case prompt_port_number() of
|
||||||
" [Press enter for the default: 11311]~n",
|
{ok, ExPort} -> create_prime(Realm, Host, ExPort);
|
||||||
ok = io:format(PortInstructions),
|
error -> create_prime(Realm, Host)
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
create_realm(Realm, Host, InPort) ->
|
||||||
|
Message = "~n Enter the global port number on which the host will be available.~n",
|
||||||
|
ok = io:format(Message),
|
||||||
|
case prompt_port_number() of
|
||||||
|
{ok, ExPort} -> create_prime(Realm, Host, ExPort, InPort);
|
||||||
|
error -> create_prime(Realm, Host, ExPort)
|
||||||
|
end.
|
||||||
|
|
||||||
|
prompt_port_number() ->
|
||||||
|
Instructions =
|
||||||
|
" A port can be any number from 1 to 65535.~n"
|
||||||
|
" [Press enter to accept the default port: 11311]~n",
|
||||||
|
ok = io:format(Instructions),
|
||||||
case get_input() of
|
case get_input() of
|
||||||
"" ->
|
"" ->
|
||||||
create_realm(Realm, {HostString, 11311});
|
{ok, 11311};
|
||||||
S ->
|
S ->
|
||||||
try
|
try
|
||||||
case list_to_integer(S) of
|
case list_to_integer(S) of
|
||||||
Port when 16#ffff >= Port, Port > 0 ->
|
Port when 16#ffff >= Port, Port > 0 ->
|
||||||
create_realm(Realm, {Host, Port});
|
{ok, Port};
|
||||||
Illegal ->
|
Illegal ->
|
||||||
Whoops = "~p is out of bounds (1~65535). Try again...",
|
Whoops = "~p is out of bounds (1~65535). Try again...",
|
||||||
ok = io:format(Whoops, [Illegal]),
|
error
|
||||||
create_realm(Realm)
|
|
||||||
end
|
end
|
||||||
catch error:badarg ->
|
catch error:badarg ->
|
||||||
Error = "~tp is not a port number. Try again...",
|
ok = io:format("~tp is not a port number. Try again...", [S]),
|
||||||
ok = io:format(Error, [S]),
|
error
|
||||||
create_realm(Realm)
|
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
@ -1485,9 +1546,9 @@ create_realm(Realm, Prime, UserName) ->
|
|||||||
Instructions =
|
Instructions =
|
||||||
"~n"
|
"~n"
|
||||||
" Enter an email address for the realm sysop.~n"
|
" Enter an email address for the realm sysop.~n"
|
||||||
" Valid email address rules apply though the checking done here is quite~n"
|
" Valid email address rules apply though the checking done here is quite "
|
||||||
" minimal. Check the address you enter carefully. The only people who will~n"
|
"minimal. Check the address you enter carefully. The only people who will "
|
||||||
" suffer from an invalid address are your users.~n",
|
"suffer from an invalid address are your users.~n",
|
||||||
ok = io:format(Instructions),
|
ok = io:format(Instructions),
|
||||||
Email = get_input(),
|
Email = get_input(),
|
||||||
[User, Host] = string:lexemes(Email, "@"),
|
[User, Host] = string:lexemes(Email, "@"),
|
||||||
@ -1519,7 +1580,8 @@ create_realm(Realm, Prime, UserName, Email) ->
|
|||||||
{ok, RealmKey, RealmPub} = generate_rsa({Realm, Realm ++ ".1.realm"}),
|
{ok, RealmKey, RealmPub} = generate_rsa({Realm, Realm ++ ".1.realm"}),
|
||||||
{ok, PackageKey, PackagePub} = generate_rsa({Realm, Realm ++ ".1.package"}),
|
{ok, PackageKey, PackagePub} = generate_rsa({Realm, Realm ++ ".1.package"}),
|
||||||
{ok, SysopKey, SysopPub} = generate_rsa({Realm, UserName ++ ".1"}),
|
{ok, SysopKey, SysopPub} = generate_rsa({Realm, UserName ++ ".1"}),
|
||||||
AllKeys = [RealmKey, RealmPub, PackageKey, PackagePub, SysopKey, SysopPub],
|
AllKeys = [RealmKey, RealmPub, PackageKey, PackagePub, SysopKey, SysopPub],
|
||||||
|
DangerousKeys = [PackageKey, SysopKey],
|
||||||
Copy =
|
Copy =
|
||||||
fun(From) ->
|
fun(From) ->
|
||||||
To = filename:basename(From),
|
To = filename:basename(From),
|
||||||
@ -1540,21 +1602,23 @@ create_realm(Realm, Prime, UserName, Email) ->
|
|||||||
ok = file:delete(File),
|
ok = file:delete(File),
|
||||||
log(info, "Deleting ~ts", [File])
|
log(info, "Deleting ~ts", [File])
|
||||||
end,
|
end,
|
||||||
DangerousKeys = [PackageKey, SysopKey],
|
|
||||||
ok = lists:foreach(Copy, AllKeys),
|
ok = lists:foreach(Copy, AllKeys),
|
||||||
ok = lists:foreach(Drop, DangerousKeys),
|
ok = lists:foreach(Drop, DangerousKeys),
|
||||||
Message =
|
Message =
|
||||||
"~n"
|
"~n"
|
||||||
" All of the keys generated have been moved to the current directory.~n"
|
" All of the keys generated have been moved to the current directory.~n"
|
||||||
|
"~n"
|
||||||
" MAKE AND SECURELY STORE COPIES OF THESE KEYS.~n"
|
" MAKE AND SECURELY STORE COPIES OF THESE KEYS.~n"
|
||||||
" The private package and sysop login keys have been deleted from the~n"
|
"~n"
|
||||||
" key directory. These should only exist on your local system, not a prime.~n"
|
" The private package and sysop login keys have been deleted from the "
|
||||||
" realm server (particularly if other services are run on that machine).~n"
|
"key directory. These should only exist on your local system, not a prime "
|
||||||
" The package and sysop keys will need to be copied to the ~~/.zomp/keys/~p/~n"
|
"realm server (particularly if other services are run on that machine).~n"
|
||||||
|
" The package and sysop keys will need to be copied to the ~~/.zomp/keys/~s/~n"
|
||||||
" directory on your personal or dev machine.~n",
|
" directory on your personal or dev machine.~n",
|
||||||
ok = io:format(Message, [Realm]),
|
ok = io:format(Message, [Realm]),
|
||||||
Timestamp = calendar:now_to_universal_time(erlang:timestamp()),
|
Timestamp = calendar:now_to_universal_time(erlang:timestamp()),
|
||||||
UserRecord = {{UserName, Realm}, [SysopPub], Email, RealName, 1, Timestamp},
|
UserRecord = {{UserName, Realm}, [SysopPub], Email, RealName, 1, Timestamp},
|
||||||
|
RealmFile = filename:join(zomp_dir(), Realm ++ ".realm"),
|
||||||
RealmMeta =
|
RealmMeta =
|
||||||
[{realm, Realm},
|
[{realm, Realm},
|
||||||
{revision, 0},
|
{revision, 0},
|
||||||
@ -1564,7 +1628,15 @@ create_realm(Realm, Prime, UserName, Email) ->
|
|||||||
{sysops, [UserRecord]},
|
{sysops, [UserRecord]},
|
||||||
{realm_keys, [RealmPub]},
|
{realm_keys, [RealmPub]},
|
||||||
{package_keys, [PackagePub]}],
|
{package_keys, [PackagePub]}],
|
||||||
ok = log(info, "Would be writing~n ~tp", [RealmMeta]),
|
ZompFile = filename:join(zomp_dir(), "zomp.conf"),
|
||||||
|
ZompConf =
|
||||||
|
[{prime, Prime},
|
||||||
|
{external_port, ExPort},
|
||||||
|
{internal_port, InPort}],
|
||||||
|
ok = write_terms(RealmFile, RealmMeta),
|
||||||
|
ok = write_terms(ZompFile, ZompConf),
|
||||||
|
ok = log(info, "Wrote to ~ts:~n ~tp", [RealmFile, RealmMeta]),
|
||||||
|
ok = log(info, "Wrote to ~ts:~n ~tp", [ZompFile, ZompConf]),
|
||||||
halt(0).
|
halt(0).
|
||||||
|
|
||||||
|
|
||||||
@ -2124,6 +2196,7 @@ ensure_zomp_home() ->
|
|||||||
SubDirs = ["tmp", "key", "var", "lib", "zrp", "etc"],
|
SubDirs = ["tmp", "key", "var", "lib", "zrp", "etc"],
|
||||||
ok = lists:foreach(fun file:make_dir/1, SubDirs),
|
ok = lists:foreach(fun file:make_dir/1, SubDirs),
|
||||||
ok = write_terms(default_realm_file(), default_realm()),
|
ok = write_terms(default_realm_file(), default_realm()),
|
||||||
|
ok = write_terms("zomp.conf", default_conf()),
|
||||||
ok = file:write_file(default_pubkey_file(), default_pubkey()),
|
ok = file:write_file(default_pubkey_file(), default_pubkey()),
|
||||||
ok = log(info, "Zomp userland directory initialized."),
|
ok = log(info, "Zomp userland directory initialized."),
|
||||||
file:set_cwd(CWD)
|
file:set_cwd(CWD)
|
||||||
@ -2240,18 +2313,31 @@ realm_file(Realm) ->
|
|||||||
Realm ++ ".realm".
|
Realm ++ ".realm".
|
||||||
|
|
||||||
|
|
||||||
-spec default_realm() -> RealmData
|
-spec default_realm() -> [{Key :: atom(), Value :: term()}].
|
||||||
when RealmData :: [{atom(), term()}].
|
|
||||||
%% @private
|
%% @private
|
||||||
%% Returns the default realm file's data contents for the default "otpr" realm.
|
%% Returns the default realm file's data contents for the default "otpr" realm.
|
||||||
|
|
||||||
default_realm() ->
|
default_realm() ->
|
||||||
[{name, "otpr"},
|
[{realm, "otpr"},
|
||||||
% {prime, {"repo.psychobitch.party", 11311}},
|
{revision, 0},
|
||||||
{prime, {"localhost", 11311}},
|
{prime, {"repo.psychobitch.party", 11311}},
|
||||||
{pubkey, default_pubkey_file()},
|
{private, [{"localhost", 11311}]},
|
||||||
{serial, 0},
|
{mirrors, []},
|
||||||
{mirrors, []}].
|
{sysops, [{"otpr, ""zxq9"}]},
|
||||||
|
{realm_keys, []},
|
||||||
|
{package_keys, [default_pubkey_file()]}].
|
||||||
|
|
||||||
|
|
||||||
|
-spec default_conf() -> [{Key :: atom(), Value :: term()}].
|
||||||
|
%% @private
|
||||||
|
%% Return the default local config values for a zomp server.
|
||||||
|
%% The external and local port values are global values needed to make a zomp server
|
||||||
|
%% work in the face of unique port forwarding and NAT configurations outside the control
|
||||||
|
%% of the zomp server itself. zx references these values in a few places (namely when
|
||||||
|
%% setting up a mirror or prime realm).
|
||||||
|
default_conf() ->
|
||||||
|
[{external_port, 11311},
|
||||||
|
{local_port, 11311}].
|
||||||
|
|
||||||
|
|
||||||
-spec default_pubkey_file() -> file:filename().
|
-spec default_pubkey_file() -> file:filename().
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user