Merge branch 'feature/whitelist-registration' into 'master'
Add a config option to whitelist users registration See merge request framasoft/mobilizon!358
This commit is contained in:
commit
bf0b1fdb27
|
@ -18,6 +18,7 @@ config :mobilizon, :instance,
|
|||
version: "1.0.0-dev",
|
||||
hostname: System.get_env("MOBILIZON_INSTANCE_HOST") || "localhost",
|
||||
registrations_open: System.get_env("MOBILIZON_INSTANCE_REGISTRATIONS_OPEN") || false,
|
||||
registration_email_whitelist: [],
|
||||
demo: System.get_env("MOBILIZON_INSTANCE_DEMO_MODE") || false,
|
||||
repository: Mix.Project.config()[:source_url],
|
||||
allow_relay: true,
|
||||
|
|
|
@ -6,6 +6,7 @@ query {
|
|||
name,
|
||||
description,
|
||||
registrationsOpen,
|
||||
registrationsWhitelist,
|
||||
demoMode,
|
||||
countryCode,
|
||||
location {
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
"Add to my calendar": "Zu meinem Kalender hinzufügen",
|
||||
"Additional comments": "Zusätzliche Kommentare",
|
||||
"Administration": "Administration",
|
||||
"All data will be deleted every 48 hours, so please don't use this for anything real.": "Alle Daten werden alle 48 Stunden gelöscht, also benutze diesen Service bitte nur zu Testzwecken.",
|
||||
"All the places have already been taken": "Alle Plätze sind besetzt|Ein Platz ist noch verfügbar|{places} Plätze sind noch verfügbar",
|
||||
"Allow all comments": "Erlaube alle Kommentare",
|
||||
"An error has occurred.": "Ein Fehler ist aufgetreten.",
|
||||
|
|
|
@ -7,17 +7,21 @@
|
|||
"About this event": "About this event",
|
||||
"About this instance": "About this instance",
|
||||
"About": "About",
|
||||
"Accepted": "Accepted",
|
||||
"Add a note": "Add a note",
|
||||
"Add an address": "Add an address",
|
||||
"Add an instance": "Add an instance",
|
||||
"Add some tags": "Add some tags",
|
||||
"Add to my calendar": "Add to my calendar",
|
||||
"Add": "Add",
|
||||
"Additional comments": "Additional comments",
|
||||
"Administration": "Administration",
|
||||
"All data will be deleted every 48 hours, so please don't use this for anything real.": "All data will be deleted every 48 hours, so please don't use this for anything real.",
|
||||
"All the places have already been taken": "All the places have been taken|One place is still available|{places} places are still available",
|
||||
"Allow all comments": "Allow all comments",
|
||||
"An error has occurred.": "An error has occurred.",
|
||||
"Approve": "Approve",
|
||||
"Are you sure you want to <b>delete</b> this comment? This action cannot be undone.": "Are you sure you want to <b>delete</b> this comment? This action cannot be undone.",
|
||||
"Are you sure you want to <b>delete</b> this event? This action cannot be undone. You may want to engage the conversation with the event creator or edit its event instead.": "Are you sure you want to <b>delete</b> this event? This action cannot be undone. You may want to engage the conversation with the event creator or edit its event instead.",
|
||||
"Are you sure you want to cancel the event creation? You'll lose all modifications.": "Are you sure you want to cancel the event creation? You'll lose all modifications.",
|
||||
"Are you sure you want to cancel the event edition? You'll lose all modifications.": "Are you sure you want to cancel the event edition? You'll lose all modifications.",
|
||||
"Are you sure you want to cancel your participation at event \"{title}\"?": "Are you sure you want to cancel your participation at event \"{title}\"?",
|
||||
|
@ -40,6 +44,9 @@
|
|||
"Click to select": "Click to select",
|
||||
"Click to upload": "Click to upload",
|
||||
"Close comments for all (except for admins)": "Close comments for all (except for admins)",
|
||||
"Close": "Close",
|
||||
"Closed": "Closed",
|
||||
"Comment deleted": "Comment deleted",
|
||||
"Comment from @{username} reported": "Comment from @{username} reported",
|
||||
"Comments have been closed.": "Comments have been closed.",
|
||||
"Comments": "Comments",
|
||||
|
@ -60,18 +67,25 @@
|
|||
"Create": "Create",
|
||||
"Creator": "Creator",
|
||||
"Current identity has been changed to {identityName} in order to manage this event.": "Current identity has been changed to {identityName} in order to manage this event.",
|
||||
"Dashboard": "Dashboard",
|
||||
"Date and time settings": "Date and time settings",
|
||||
"Date parameters": "Date parameters",
|
||||
"Date": "Date",
|
||||
"Delete Comment": "Delete Comment",
|
||||
"Delete Event": "Delete Event",
|
||||
"Delete event": "Delete event",
|
||||
"Delete this identity": "Delete this identity",
|
||||
"Delete your identity": "Delete your identity",
|
||||
"Delete {eventTitle}": "Delete {eventTitle}",
|
||||
"Delete {preferredUsername}": "Delete {preferredUsername}",
|
||||
"Delete": "Delete",
|
||||
"Deleting comment": "Deleting comment",
|
||||
"Deleting event": "Deleting event",
|
||||
"Description": "Description",
|
||||
"Didn't receive the instructions ?": "Didn't receive the instructions ?",
|
||||
"Display name": "Display name",
|
||||
"Display participation price": "Display participation price",
|
||||
"Domain": "Domain",
|
||||
"Draft": "Draft",
|
||||
"Drafts": "Drafts",
|
||||
"Edit": "Edit",
|
||||
|
@ -96,12 +110,15 @@
|
|||
"Event {eventTitle} reported": "Event {eventTitle} reported",
|
||||
"Event": "Event",
|
||||
"Events": "Events",
|
||||
"Ex: test.mobilizon.org": "Ex: test.mobilizon.org",
|
||||
"Exclude": "Exclude",
|
||||
"Explore": "Explore",
|
||||
"Featured events": "Featured events",
|
||||
"Features": "Features",
|
||||
"Find an address": "Find an address",
|
||||
"Find an instance": "Find an instance",
|
||||
"Followers": "Followers",
|
||||
"Followings": "Followings",
|
||||
"For instance: London, Taekwondo, Architecture…": "For instance: London, Taekwondo, Architecture…",
|
||||
"Forgot your password ?": "Forgot your password ?",
|
||||
"From a birthday party with friends and family to a march for climate change, right now, our gatherings are <b>trapped inside the tech giants’ platforms</b>. How can we organize, how can we click “Attend,” without <b>providing private data</b> to Facebook or <b>locking ourselves up</b> inside MeetUp?": "From a birthday party with friends and family to a march for climate change, right now, our gatherings are <b>trapped inside the tech giants’ platforms</b>. How can we organize, how can we click “Attend,” without <b>providing private data</b> to Facebook or <b>locking ourselves up</b> inside MeetUp?",
|
||||
|
@ -130,6 +147,7 @@
|
|||
"Impossible to login, your email or password seems incorrect.": "Impossible to login, your email or password seems incorrect.",
|
||||
"In the meantime, please consider that the software is not (yet) finished. More information {onBlog}.": "In the meantime, please consider that the software is not (yet) finished. More information {onBlog}.",
|
||||
"Installing Mobilizon will allow communities to free themselves from the services of tech giants by creating <b>their own event platform</b>.": "Installing Mobilizon will allow communities to free themselves from the services of tech giants by creating <b>their own event platform</b>.",
|
||||
"Instances": "Instances",
|
||||
"Join {instance}, a Mobilizon instance": "Join {instance}, a Mobilizon instance",
|
||||
"Last published event": "Last published event",
|
||||
"Last week": "Last week",
|
||||
|
@ -147,6 +165,7 @@
|
|||
"Login on Mobilizon!": "Login on Mobilizon!",
|
||||
"Login": "Login",
|
||||
"Manage participations": "Manage participations",
|
||||
"Mark as resolved": "Mark as resolved",
|
||||
"Members": "Members",
|
||||
"Mobilizon is a free/libre software that will allow communities to create <b>their own spaces</b> to publish events in order to better emancipate themselves from tech giants.": "Mobilizon is a free/libre software that will allow communities to create <b>their own spaces</b> to publish events in order to better emancipate themselves from tech giants.",
|
||||
"Mobilizon is under development, we will add new features to this site during regular updates, until the release of <b>version 1 of the software in the first half of 2020</b>.": "Mobilizon is under development, we will add new features to this site during regular updates, until the release of <b>version 1 of the software in the first half of 2020</b>.",
|
||||
|
@ -156,16 +175,26 @@
|
|||
"My events": "My events",
|
||||
"My identities": "My identities",
|
||||
"Name": "Name",
|
||||
"New note": "New note",
|
||||
"New password": "New password",
|
||||
"No actors found": "No actors found",
|
||||
"No address defined": "No address defined",
|
||||
"No closed reports yet": "No closed reports yet",
|
||||
"No comment": "No comment",
|
||||
"No comments yet": "No comments yet",
|
||||
"No end date": "No end date",
|
||||
"No events found": "No events found",
|
||||
"No group found": "No group found",
|
||||
"No groups found": "No groups found",
|
||||
"No instance follows your instance yet.": "No instance follows your instance yet.",
|
||||
"No instance to approve|Approve instance|Approve {number} instances": "No instance to approve|Approve instance|Approve {number} instances",
|
||||
"No instance to reject|Reject instance|Reject {number} instances": "No instance to reject|Reject instance|Reject {number} instances",
|
||||
"No instance to remove|Remove instance|Remove {number} instances": "No instances to remove|Remove instance|Remove {number} instances",
|
||||
"No open reports yet": "No open reports yet",
|
||||
"No resolved reports yet": "No resolved reports yet",
|
||||
"No results for \"{queryText}\"": "No results for \"{queryText}\"",
|
||||
"No user account with this email was found. Maybe you made a typo?": "No user account with this email was found. Maybe you made a typo?",
|
||||
"Notes": "Notes",
|
||||
"Number of places": "Number of places",
|
||||
"OK": "OK",
|
||||
"Old password": "Old password",
|
||||
|
@ -176,6 +205,7 @@
|
|||
"One person is going": "No one is going | One person is going | {approved} persons are going",
|
||||
"Only accessible through link and search (private)": "Only accessible through link and search (private)",
|
||||
"Only alphanumeric characters and underscores are supported.": "Only alphanumeric characters and underscores are supported.",
|
||||
"Open": "Open",
|
||||
"Opened reports": "Opened reports",
|
||||
"Organized by {name}": "Organized by {name}",
|
||||
"Organized": "Organized",
|
||||
|
@ -194,6 +224,7 @@
|
|||
"Password reset": "Password reset",
|
||||
"Password": "Password",
|
||||
"Past events": "Passed events",
|
||||
"Pending": "Pending",
|
||||
"Pick an identity": "Pick an identity",
|
||||
"Please check your spam folder if you didn't receive the email.": "Please check your spam folder if you didn't receive the email.",
|
||||
"Please contact this instance's Mobilizon admin if you think this is a mistake.": "Please contact this instance's Mobilizon admin if you think this is a mistake.",
|
||||
|
@ -219,15 +250,25 @@
|
|||
"Register for an event by choosing one of your identities": "Register for an event by choosing one of your identities",
|
||||
"Register": "Register",
|
||||
"Registration is currently closed.": "Registration is currently closed.",
|
||||
"Registrations are restricted by whitelisting.": "Registrations are restricted by whitelisting.",
|
||||
"Reject": "Reject",
|
||||
"Rejected participations": "Rejected participations",
|
||||
"Rejected": "Rejected",
|
||||
"Reopen": "Reopen",
|
||||
"Reply": "Reply",
|
||||
"Report this comment": "Report this comment",
|
||||
"Report this event": "Report this event",
|
||||
"Report": "Report",
|
||||
"Reported by someone on {domain}": "Reported by someone on {domain}",
|
||||
"Reported by {reporter}": "Reported by {reporter}",
|
||||
"Reported by": "Reported by",
|
||||
"Reported identity": "Reported identity",
|
||||
"Reported": "Reported",
|
||||
"Reports": "Reports",
|
||||
"Requests": "Requests",
|
||||
"Resend confirmation email": "Resend confirmation email",
|
||||
"Reset my password": "Reset my password",
|
||||
"Resolved": "Resolved",
|
||||
"Save draft": "Save draft",
|
||||
"Save": "Save",
|
||||
"Search events, groups, etc.": "Search events, groups, etc.",
|
||||
|
@ -273,13 +314,17 @@
|
|||
"To confirm, type your event title \"{eventTitle}\"": "To confirm, type your event title \"{eventTitle}\"",
|
||||
"To confirm, type your identity username \"{preferredUsername}\"": "To confirm, type your identity username \"{preferredUsername}\"",
|
||||
"Transfer to {outsideDomain}": "Transfer to {outsideDomain}",
|
||||
"Type": "Type",
|
||||
"Unfortunately, this instance isn't opened to registrations": "Unfortunately, this instance isn't opened to registrations",
|
||||
"Unfortunately, your participation request was rejected by the organizers.": "Unfortunately, your participation request was rejected by the organizers.",
|
||||
"Unknown actor": "Unknown actor",
|
||||
"Unknown error.": "Unknown error.",
|
||||
"Unknown": "Unknown",
|
||||
"Unsaved changes": "Unsaved changes",
|
||||
"Upcoming": "Upcoming",
|
||||
"Update event {name}": "Update event {name}",
|
||||
"Update my event": "Update my event",
|
||||
"Updated": "Updated",
|
||||
"Username": "Username",
|
||||
"Users": "Users",
|
||||
"View a reply": "|View one reply|View {totalReplies} replies",
|
||||
|
@ -307,6 +352,7 @@
|
|||
"You can add tags by hitting the Enter key or by adding a comma": "You can add tags by hitting the Enter key or by adding a comma",
|
||||
"You can try another search term or drag and drop the marker on the map": "You can try another search term or drag and drop the marker on the map",
|
||||
"You can't remove your last identity.": "You can't remove your last identity.",
|
||||
"You don't follow any instances yet.": "You don't follow any instances yet.",
|
||||
"You have been disconnected": "You have been disconnected",
|
||||
"You have cancelled your participation": "You have cancelled your participation",
|
||||
"You have one event in {days} days.": "You have no events in {days} days | You have one event in {days} days. | You have {count} events in {days} days",
|
||||
|
@ -317,12 +363,16 @@
|
|||
"Your account has been validated": "Your account has been validated",
|
||||
"Your account is being validated": "Your account is being validated",
|
||||
"Your account is nearly ready, {username}": "Your account is nearly ready, {username}",
|
||||
"Your email is not whitelisted, you can't register.": "Your email is not whitelisted, you can't register.",
|
||||
"Your local administrator resumed its policy:": "Your local administrator resumed its policy:",
|
||||
"Your participation has been confirmed": "Your participation has been confirmed",
|
||||
"Your participation has been rejected": "Your participation has been rejected",
|
||||
"Your participation has been requested": "Your participation has been requested",
|
||||
"Your participation status has been changed": "Your participation status has been changed",
|
||||
"[This comment has been deleted]": "[This comment has been deleted]",
|
||||
"[deleted]": "[deleted]",
|
||||
"a decentralised federation protocol": "a decentralised federation protocol",
|
||||
"as {identity}": "as {identity}",
|
||||
"e.g. 10 Rue Jangot": "e.g. 10 Rue Jangot",
|
||||
"firstDayOfWeek": "0",
|
||||
"iCal Feed": "iCal Feed",
|
||||
|
@ -332,59 +382,10 @@
|
|||
"resend confirmation email": "resend confirmation email",
|
||||
"respect of the fundamental freedoms": "respect of the fundamental freedoms",
|
||||
"with another identity…": "with another identity…",
|
||||
"as {identity}": "as {identity}",
|
||||
"{approved} / {total} seats": "{approved} / {total} seats",
|
||||
"{count} participants": "No participants yet | One participant | {count} participants",
|
||||
"{count} requests waiting": "{count} requests waiting",
|
||||
"{license} guarantees {respect} of the people who will use it. Since {source}, anyone can audit it, which guarantees its transparency.": "{license} guarantees {respect} of the people who will use it. Since {source}, anyone can audit it, which guarantees its transparency.",
|
||||
"© The Mobilizon Contributors {date} - Made with Elixir, Phoenix, VueJS & with some love and some weeks": "© The Mobilizon Contributors {date} - Made with Elixir, Phoenix, VueJS & with some love and some weeks",
|
||||
"© The OpenStreetMap Contributors": "© The OpenStreetMap Contributors",
|
||||
"Reply": "Reply",
|
||||
"Accepted": "Accepted",
|
||||
"Pending": "Pending",
|
||||
"No instance to remove|Remove instance|Remove {number} instances": "No instances to remove|Remove instance|Remove {number} instances",
|
||||
"Dashboard": "Dashboard",
|
||||
"Reports": "Reports",
|
||||
"Mark as resolved": "Mark as resolved",
|
||||
"Reopen": "Reopen",
|
||||
"Close": "Close",
|
||||
"Reported identity": "Reported identity",
|
||||
"Reported by": "Reported by",
|
||||
"Reported": "Reported",
|
||||
"Updated": "Updated",
|
||||
"Open": "Open",
|
||||
"Closed": "Closed",
|
||||
"Resolved": "Resolved",
|
||||
"Unknown": "Unknown",
|
||||
"No comment": "No comment",
|
||||
"Notes": "Notes",
|
||||
"New note": "New note",
|
||||
"Add a note": "Add a note",
|
||||
"Deleting event": "Deleting event",
|
||||
"Are you sure you want to <b>delete</b> this event? This action cannot be undone. You may want to engage the conversation with the event creator or edit its event instead.": "Are you sure you want to <b>delete</b> this event? This action cannot be undone. You may want to engage the conversation with the event creator or edit its event instead.",
|
||||
"Delete Event": "Delete Event",
|
||||
"Type": "Type",
|
||||
"Domain": "Domain",
|
||||
"Date": "Date",
|
||||
"No instance to approve|Approve instance|Approve {number} instances": "No instance to approve|Approve instance|Approve {number} instances",
|
||||
"No instance to reject|Reject instance|Reject {number} instances": "No instance to reject|Reject instance|Reject {number} instances",
|
||||
"No instance follows your instance yet.": "No instance follows your instance yet.",
|
||||
"Followers": "Followers",
|
||||
"Add an instance": "Add an instance",
|
||||
"Ex: test.mobilizon.org": "Ex: test.mobilizon.org",
|
||||
"You don't follow any instances yet.": "You don't follow any instances yet.",
|
||||
"Followings": "Followings",
|
||||
"Instances": "Instances",
|
||||
"Reported by {reporter}": "Reported by {reporter}",
|
||||
"No open reports yet": "No open reports yet",
|
||||
"No resolved reports yet": "No resolved reports yet",
|
||||
"No closed reports yet": "No closed reports yet",
|
||||
"Reported by someone on {domain}": "Reported by someone on {domain}",
|
||||
"Your participation has been rejected": "Your participation has been rejected",
|
||||
"Your participation status has been changed": "Your participation status has been changed",
|
||||
"Unknown actor": "Unknown actor",
|
||||
"Deleting comment": "Deleting comment",
|
||||
"Are you sure you want to <b>delete</b> this comment? This action cannot be undone.": "Are you sure you want to <b>delete</b> this comment? This action cannot be undone.",
|
||||
"Delete Comment": "Delete Comment",
|
||||
"Comment deleted": "Comment deleted"
|
||||
"© The OpenStreetMap Contributors": "© The OpenStreetMap Contributors"
|
||||
}
|
|
@ -16,7 +16,6 @@
|
|||
"Add": "Ajouter",
|
||||
"Additional comments": "Commentaires additionnels",
|
||||
"Administration": "Administration",
|
||||
"All data will be deleted every 48 hours, so please don't use this for anything real.": "Toutes les données seront effacées toutes les 48 heures, donc n'utilisez pas ce site à des fins autres que de démonstration.",
|
||||
"All the places have already been taken": "Toutes les places ont été prises|Une place est encore disponible|{places} places sont encore disponibles",
|
||||
"Allow all comments": "Autoriser tous les commentaires",
|
||||
"An error has occurred.": "Une erreur est survenue.",
|
||||
|
@ -253,6 +252,7 @@
|
|||
"Register for an event by choosing one of your identities": "S'inscrire à un événement en choisissant une de vos identités",
|
||||
"Register": "S'inscrire",
|
||||
"Registration is currently closed.": "Les inscriptions sont actuellement fermées.",
|
||||
"Registrations are restricted by whitelisting.": "Les inscriptions sont restreintes par liste blanche.",
|
||||
"Reject": "Rejetter",
|
||||
"Rejected participations": "Participations rejetées",
|
||||
"Rejected": "Rejetés",
|
||||
|
@ -365,6 +365,7 @@
|
|||
"Your account has been validated": "Votre compte a été validé",
|
||||
"Your account is being validated": "Votre compte est en cours de validation",
|
||||
"Your account is nearly ready, {username}": "Votre compte est presque prêt, {username}",
|
||||
"Your email is not whitelisted, you can't register.": "Votre email n'est pas sur la liste blanche, vous ne pouvez pas vous inscrire.",
|
||||
"Your local administrator resumed its policy:": "Votre administrateur local a résumé sa politique ainsi :",
|
||||
"Your participation has been confirmed": "Votre participation a été confirmée",
|
||||
"Your participation has been rejected": "Votre participation a été rejettée",
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
"Add to my calendar": "Aan mijn kalender toevoegen",
|
||||
"Additional comments": "Meer opmerkingen",
|
||||
"Administration": "Administratie",
|
||||
"All data will be deleted every 48 hours, so please don't use this for anything real.": "Alle gegevens worden iedere 48 uur verwijderd, dus gebruik dit enkel als test.",
|
||||
"All the places have already been taken": "Ale plaatsen zijn bezet|Er is nog één plaats vrij|Er zijn nog {places} plaatsen vrij",
|
||||
"Allow all comments": "Alle opmerkingen toestaan",
|
||||
"An error has occurred.": "Er is een fout opgetreden.",
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
"Add": "Ajustar",
|
||||
"Additional comments": "Comentari adicional",
|
||||
"Administration": "Administracion",
|
||||
"All data will be deleted every 48 hours, so please don't use this for anything real.": "Estant que totas las donadas son suprimidas cada 48 oras, utilizetz pas aquò per quicòm mai qu’una demostracion.",
|
||||
"All the places have already been taken": "Totas las plaças son presas|Una plaça es encara disponibla|{places} plaças son encara disponiblas",
|
||||
"Allow all comments": "Autorizar totes los comentaris",
|
||||
"An error has occurred.": "Una error s’es producha.",
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
"Add to my calendar": "Dodaj do kalendarza",
|
||||
"Additional comments": "Dodatkowe komentarze",
|
||||
"Administration": "Administracja",
|
||||
"All data will be deleted every 48 hours, so please don't use this for anything real.": "Wszystkie dane zostaną usunięte co 48 godzin, więc nie używaj tego do rzeczywistych działań.",
|
||||
"Allow all comments": "Pozwól na wszystkie komentarze",
|
||||
"An error has occurred.": "Wystąpił błąd.",
|
||||
"Approve": "Zatwierdź",
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
"Add to my calendar": "Lägg till i min kalender",
|
||||
"Additional comments": "Yttligare kommentarer",
|
||||
"Administration": "Administration",
|
||||
"All data will be deleted every 48 hours, so please don't use this for anything real.": "All data kommer raderas varje 48e timme, så använd inte detta för något riktigt.",
|
||||
"All the places have already been taken": "Alla platser är bokade|Det finns en plats kvar|Det finns {places} kvar",
|
||||
"Allow all comments": "Tillåt alla kommentarer",
|
||||
"An error has occurred.": "Ett fel har uppstått.",
|
||||
|
|
|
@ -12,7 +12,7 @@ export const beforeRegisterGuard: NavigationGuard = async function (to, from, ne
|
|||
|
||||
const config: IConfig = data.config;
|
||||
|
||||
if (!config.registrationsOpen) {
|
||||
if (!config.registrationsOpen && !config.registrationsWhitelist) {
|
||||
return next({
|
||||
name: ErrorRouteName.ERROR,
|
||||
query: { code: ErrorCode.REGISTRATION_CLOSED },
|
||||
|
|
|
@ -3,6 +3,7 @@ export interface IConfig {
|
|||
description: string;
|
||||
|
||||
registrationsOpen: boolean;
|
||||
registrationsWhitelist: boolean;
|
||||
demoMode: boolean;
|
||||
countryCode: string;
|
||||
location: {
|
||||
|
|
|
@ -48,6 +48,11 @@ export const errors: IError[] = [
|
|||
value: i18n.t("The current identity doesn't have any permission on this event. You should probably change it.") as string,
|
||||
suggestRefresh: false,
|
||||
},
|
||||
{
|
||||
match: /Your email is not on the whitelist$/,
|
||||
value: i18n.t("Your email is not whitelisted, you can't register.") as string,
|
||||
suggestRefresh: false,
|
||||
},
|
||||
{
|
||||
match: /Cannot remove the last identity of a user/,
|
||||
value: i18n.t("You can't remove your last identity.") as string,
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
</p>
|
||||
<ul>
|
||||
<li>{{ $t('Enjoy discovering Mobilizon!') }}</li>
|
||||
<li>{{ $t("All data will be deleted every 48 hours, so please don't use this for anything real.") }}</li>
|
||||
</ul>
|
||||
<!-- <p>-->
|
||||
<!-- {{ $t('Please read the full rules') }}-->
|
||||
|
@ -37,6 +36,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="column">
|
||||
<b-message type="is-warning" v-if="config.registrationsWhitelist">{{ $t('Registrations are restricted by whitelisting.') }}</b-message>
|
||||
<form v-on:submit.prevent="submit()">
|
||||
<b-field
|
||||
:label="$t('Email')"
|
||||
|
@ -105,6 +105,8 @@
|
|||
import { CREATE_USER } from '@/graphql/user';
|
||||
import { Component, Prop, Vue } from 'vue-property-decorator';
|
||||
import { RouteName } from '@/router';
|
||||
import { IConfig } from '@/types/config.model';
|
||||
import { CONFIG } from '@/graphql/config';
|
||||
|
||||
@Component({
|
||||
metaInfo() {
|
||||
|
@ -115,6 +117,9 @@ import { RouteName } from '@/router';
|
|||
titleTemplate: '%s | Mobilizon',
|
||||
};
|
||||
},
|
||||
apollo: {
|
||||
config: CONFIG,
|
||||
},
|
||||
})
|
||||
export default class Register extends Vue {
|
||||
@Prop({ type: String, required: false, default: '' }) email!: string;
|
||||
|
@ -129,6 +134,7 @@ export default class Register extends Vue {
|
|||
sendingValidation: boolean = false;
|
||||
validationSent: boolean = false;
|
||||
RouteName = RouteName;
|
||||
config!: IConfig;
|
||||
|
||||
async submit() {
|
||||
this.credentials.locale = this.$i18n.locale;
|
||||
|
|
|
@ -21,6 +21,12 @@ defmodule Mobilizon.Config do
|
|||
@spec instance_registrations_open? :: boolean
|
||||
def instance_registrations_open?, do: to_boolean(instance_config()[:registrations_open])
|
||||
|
||||
@spec instance_registrations_whitelist :: list(String.t())
|
||||
def instance_registrations_whitelist, do: instance_config()[:registration_email_whitelist]
|
||||
|
||||
@spec instance_registrations_whitelist? :: boolean
|
||||
def instance_registrations_whitelist?, do: length(instance_registrations_whitelist()) > 0
|
||||
|
||||
@spec instance_demo_mode? :: boolean
|
||||
def instance_demo_mode?, do: to_boolean(instance_config()[:demo])
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ defmodule MobilizonWeb.Resolvers.Config do
|
|||
%{
|
||||
name: Config.instance_name(),
|
||||
registrations_open: Config.instance_registrations_open?(),
|
||||
registrations_whitelist: Config.instance_registrations_whitelist?(),
|
||||
demo_mode: Config.instance_demo_mode?(),
|
||||
description: Config.instance_description(),
|
||||
location: location,
|
||||
|
|
|
@ -116,20 +116,46 @@ defmodule MobilizonWeb.Resolvers.User do
|
|||
"""
|
||||
@spec create_user(any(), map(), any()) :: tuple()
|
||||
def create_user(_parent, args, _resolution) do
|
||||
with {:registrations_open, true} <-
|
||||
{:registrations_open, Config.instance_registrations_open?()},
|
||||
with :registration_ok <- check_registration_config(args),
|
||||
{:ok, %User{} = user} <- Users.register(args) do
|
||||
Activation.send_confirmation_email(user, Map.get(args, :locale, "en"))
|
||||
{:ok, user}
|
||||
else
|
||||
{:registrations_open, false} ->
|
||||
:registration_closed ->
|
||||
{:error, "Registrations are not enabled"}
|
||||
|
||||
:not_whitelisted ->
|
||||
{:error, "Your email is not on the whitelist"}
|
||||
|
||||
error ->
|
||||
error
|
||||
end
|
||||
end
|
||||
|
||||
@spec check_registration_config(map()) :: atom()
|
||||
defp check_registration_config(%{email: email}) do
|
||||
cond do
|
||||
Config.instance_registrations_open?() ->
|
||||
:registration_ok
|
||||
|
||||
Config.instance_registrations_whitelist?() ->
|
||||
check_white_listed_email?(email)
|
||||
|
||||
true ->
|
||||
:registration_closed
|
||||
end
|
||||
end
|
||||
|
||||
@spec check_white_listed_email?(String.t()) :: :registration_ok | :not_whitelisted
|
||||
defp check_white_listed_email?(email) do
|
||||
[_, domain] = String.split(email, "@", parts: 2, trim: true)
|
||||
|
||||
if domain in Config.instance_registrations_whitelist() or
|
||||
email in Config.instance_registrations_whitelist(),
|
||||
do: :registration_ok,
|
||||
else: :not_whitelisted
|
||||
end
|
||||
|
||||
@doc """
|
||||
Validate an user, get its actor and a token
|
||||
"""
|
||||
|
|
|
@ -13,6 +13,7 @@ defmodule MobilizonWeb.Schema.ConfigType do
|
|||
field(:description, :string)
|
||||
|
||||
field(:registrations_open, :boolean)
|
||||
field(:registrations_whitelist, :boolean)
|
||||
field(:demo_mode, :boolean)
|
||||
field(:country_code, :string)
|
||||
field(:location, :lonlat)
|
||||
|
|
251
schema.graphql
251
schema.graphql
|
@ -1,5 +1,5 @@
|
|||
# source: http://localhost:4000/api
|
||||
# timestamp: Wed Dec 11 2019 15:24:29 GMT+0100 (heure normale d’Europe centrale)
|
||||
# timestamp: Tue Dec 17 2019 11:21:37 GMT+0100 (heure normale d’Europe centrale)
|
||||
|
||||
schema {
|
||||
query: RootQueryType
|
||||
|
@ -256,6 +256,7 @@ type Config {
|
|||
maps: Maps
|
||||
name: String
|
||||
registrationsOpen: Boolean
|
||||
registrationsWhitelist: Boolean
|
||||
}
|
||||
|
||||
type Dashboard {
|
||||
|
@ -996,70 +997,6 @@ enum ReportStatus {
|
|||
}
|
||||
|
||||
type RootMutationType {
|
||||
"""Change default actor for user"""
|
||||
changeDefaultActor(preferredUsername: String!): User
|
||||
|
||||
"""Create a new person for user"""
|
||||
createPerson(
|
||||
"""
|
||||
The avatar for the profile, either as an object or directly the ID of an existing Picture
|
||||
"""
|
||||
avatar: PictureInput
|
||||
|
||||
"""
|
||||
The banner for the profile, either as an object or directly the ID of an existing Picture
|
||||
"""
|
||||
banner: PictureInput
|
||||
|
||||
"""The displayed name for the new profile"""
|
||||
name: String = ""
|
||||
preferredUsername: String!
|
||||
|
||||
"""The summary for the new profile"""
|
||||
summary: String = ""
|
||||
): Person
|
||||
|
||||
"""Upload a picture"""
|
||||
uploadPicture(actorId: ID!, alt: String, file: Upload!, name: String!): Picture
|
||||
|
||||
"""Delete an event"""
|
||||
deleteEvent(actorId: ID!, eventId: ID!): DeletedObject
|
||||
|
||||
"""Create a note on a report"""
|
||||
createReportNote(content: String, moderatorId: ID!, reportId: ID!): ReportNote
|
||||
|
||||
"""Accept a relay subscription"""
|
||||
acceptRelay(address: String!): Follower
|
||||
|
||||
"""Delete a feed token"""
|
||||
deleteFeedToken(token: String!): DeletedFeedToken
|
||||
|
||||
"""Validate an user after registration"""
|
||||
validateUser(token: String!): Login
|
||||
|
||||
"""Resend registration confirmation token"""
|
||||
resendConfirmationEmail(email: String!, locale: String): String
|
||||
|
||||
"""Update an identity"""
|
||||
updatePerson(
|
||||
"""
|
||||
The avatar for the profile, either as an object or directly the ID of an existing Picture
|
||||
"""
|
||||
avatar: PictureInput
|
||||
|
||||
"""
|
||||
The banner for the profile, either as an object or directly the ID of an existing Picture
|
||||
"""
|
||||
banner: PictureInput
|
||||
id: ID!
|
||||
|
||||
"""The displayed name for this profile"""
|
||||
name: String
|
||||
|
||||
"""The summary for this profile"""
|
||||
summary: String
|
||||
): Person
|
||||
|
||||
"""Create an event"""
|
||||
createEvent(
|
||||
beginsOn: DateTime!
|
||||
|
@ -1087,47 +1024,24 @@ type RootMutationType {
|
|||
visibility: EventVisibility = PUBLIC
|
||||
): Event
|
||||
|
||||
"""Register a first profile on registration"""
|
||||
registerPerson(
|
||||
"""
|
||||
The avatar for the profile, either as an object or directly the ID of an existing Picture
|
||||
"""
|
||||
avatar: PictureInput
|
||||
"""Create a Feed Token"""
|
||||
createFeedToken(actorId: ID): FeedToken
|
||||
|
||||
"""
|
||||
The banner for the profile, either as an object or directly the ID of an existing Picture
|
||||
"""
|
||||
banner: PictureInput
|
||||
"""Create a report"""
|
||||
createReport(commentsIds: [ID] = [""], content: String, eventId: ID, forward: Boolean = false, reportedId: ID!, reporterId: ID!): Report
|
||||
|
||||
"""The email from the user previously created"""
|
||||
email: String!
|
||||
|
||||
"""The displayed name for the new profile"""
|
||||
name: String = ""
|
||||
preferredUsername: String!
|
||||
|
||||
"""The summary for the new profile"""
|
||||
summary: String = ""
|
||||
): Person
|
||||
|
||||
"""Accept a participation"""
|
||||
updateParticipation(id: ID!, moderatorActorId: ID!, role: ParticipantRoleEnum!): Participant
|
||||
|
||||
"""Delete a group"""
|
||||
deleteGroup(actorId: ID!, groupId: ID!): DeletedObject
|
||||
"""Change default actor for user"""
|
||||
changeDefaultActor(preferredUsername: String!): User
|
||||
deleteComment(actorId: ID!, commentId: ID!): Comment
|
||||
|
||||
"""Create an user"""
|
||||
createUser(email: String!, locale: String, password: String!): User
|
||||
"""Delete an event"""
|
||||
deleteEvent(actorId: ID!, eventId: ID!): DeletedObject
|
||||
|
||||
"""Leave an event"""
|
||||
leaveEvent(actorId: ID!, eventId: ID!): DeletedParticipant
|
||||
"""Join an event"""
|
||||
joinEvent(actorId: ID!, eventId: ID!): Participant
|
||||
|
||||
"""Refresh a token"""
|
||||
refreshToken(refreshToken: String!): RefreshedToken
|
||||
|
||||
"""Join a group"""
|
||||
joinGroup(actorId: ID!, groupId: ID!): Member
|
||||
"""Reset user password"""
|
||||
resetPassword(locale: String = "en", password: String!, token: String!): Login
|
||||
|
||||
"""Update an event"""
|
||||
updateEvent(
|
||||
|
@ -1156,42 +1070,75 @@ type RootMutationType {
|
|||
visibility: EventVisibility = PUBLIC
|
||||
): Event
|
||||
|
||||
"""Reset user password"""
|
||||
resetPassword(locale: String = "en", password: String!, token: String!): Login
|
||||
"""Change an user password"""
|
||||
changePassword(newPassword: String!, oldPassword: String!): User
|
||||
|
||||
"""Create a report"""
|
||||
createReport(commentsIds: [ID] = [""], content: String, eventId: ID, forward: Boolean = false, reportedId: ID!, reporterId: ID!): Report
|
||||
"""Delete a feed token"""
|
||||
deleteFeedToken(token: String!): DeletedFeedToken
|
||||
|
||||
"""Update a report"""
|
||||
updateReportStatus(moderatorId: ID!, reportId: ID!, status: ReportStatus!): Report
|
||||
deleteReportNote(moderatorId: ID!, noteId: ID!): DeletedObject
|
||||
"""Register a first profile on registration"""
|
||||
registerPerson(
|
||||
"""
|
||||
The avatar for the profile, either as an object or directly the ID of an existing Picture
|
||||
"""
|
||||
avatar: PictureInput
|
||||
|
||||
"""Delete a relay subscription"""
|
||||
removeRelay(address: String!): Follower
|
||||
"""
|
||||
The banner for the profile, either as an object or directly the ID of an existing Picture
|
||||
"""
|
||||
banner: PictureInput
|
||||
|
||||
"""Create a comment"""
|
||||
createComment(actorId: ID!, eventId: ID, inReplyToCommentId: ID, text: String!): Comment
|
||||
"""The email from the user previously created"""
|
||||
email: String!
|
||||
|
||||
"""The displayed name for the new profile"""
|
||||
name: String = ""
|
||||
preferredUsername: String!
|
||||
|
||||
"""The summary for the new profile"""
|
||||
summary: String = ""
|
||||
): Person
|
||||
|
||||
"""Delete an identity"""
|
||||
deletePerson(id: ID!): Person
|
||||
|
||||
"""Reject a relay subscription"""
|
||||
rejectRelay(address: String!): Follower
|
||||
"""Leave an event"""
|
||||
leaveEvent(actorId: ID!, eventId: ID!): DeletedParticipant
|
||||
|
||||
"""Accept a participation"""
|
||||
updateParticipation(id: ID!, moderatorActorId: ID!, role: ParticipantRoleEnum!): Participant
|
||||
|
||||
"""Login an user"""
|
||||
login(email: String!, password: String!): Login
|
||||
|
||||
"""Leave an event"""
|
||||
leaveGroup(actorId: ID!, groupId: ID!): DeletedMember
|
||||
"""Upload a picture"""
|
||||
uploadPicture(actorId: ID!, alt: String, file: Upload!, name: String!): Picture
|
||||
|
||||
"""Change an user password"""
|
||||
changePassword(newPassword: String!, oldPassword: String!): User
|
||||
"""Create a new person for user"""
|
||||
createPerson(
|
||||
"""
|
||||
The avatar for the profile, either as an object or directly the ID of an existing Picture
|
||||
"""
|
||||
avatar: PictureInput
|
||||
|
||||
"""Add a relay subscription"""
|
||||
addRelay(address: String!): Follower
|
||||
"""
|
||||
The banner for the profile, either as an object or directly the ID of an existing Picture
|
||||
"""
|
||||
banner: PictureInput
|
||||
|
||||
"""Join an event"""
|
||||
joinEvent(actorId: ID!, eventId: ID!): Participant
|
||||
"""The displayed name for the new profile"""
|
||||
name: String = ""
|
||||
preferredUsername: String!
|
||||
|
||||
"""The summary for the new profile"""
|
||||
summary: String = ""
|
||||
): Person
|
||||
|
||||
"""Send a link through email to reset user password"""
|
||||
sendResetPassword(email: String!, locale: String): String
|
||||
|
||||
"""Create a comment"""
|
||||
createComment(actorId: ID!, eventId: ID, inReplyToCommentId: ID, text: String!): Comment
|
||||
|
||||
"""Create a group"""
|
||||
createGroup(
|
||||
|
@ -1218,11 +1165,65 @@ type RootMutationType {
|
|||
summary: String = ""
|
||||
): Group
|
||||
|
||||
"""Send a link through email to reset user password"""
|
||||
sendResetPassword(email: String!, locale: String): String
|
||||
"""Update a report"""
|
||||
updateReportStatus(moderatorId: ID!, reportId: ID!, status: ReportStatus!): Report
|
||||
|
||||
"""Create a Feed Token"""
|
||||
createFeedToken(actorId: ID): FeedToken
|
||||
"""Create an user"""
|
||||
createUser(email: String!, locale: String, password: String!): User
|
||||
deleteReportNote(moderatorId: ID!, noteId: ID!): DeletedObject
|
||||
|
||||
"""Update an identity"""
|
||||
updatePerson(
|
||||
"""
|
||||
The avatar for the profile, either as an object or directly the ID of an existing Picture
|
||||
"""
|
||||
avatar: PictureInput
|
||||
|
||||
"""
|
||||
The banner for the profile, either as an object or directly the ID of an existing Picture
|
||||
"""
|
||||
banner: PictureInput
|
||||
id: ID!
|
||||
|
||||
"""The displayed name for this profile"""
|
||||
name: String
|
||||
|
||||
"""The summary for this profile"""
|
||||
summary: String
|
||||
): Person
|
||||
|
||||
"""Join a group"""
|
||||
joinGroup(actorId: ID!, groupId: ID!): Member
|
||||
|
||||
"""Delete a group"""
|
||||
deleteGroup(actorId: ID!, groupId: ID!): DeletedObject
|
||||
|
||||
"""Resend registration confirmation token"""
|
||||
resendConfirmationEmail(email: String!, locale: String): String
|
||||
|
||||
"""Delete a relay subscription"""
|
||||
removeRelay(address: String!): Follower
|
||||
|
||||
"""Refresh a token"""
|
||||
refreshToken(refreshToken: String!): RefreshedToken
|
||||
|
||||
"""Add a relay subscription"""
|
||||
addRelay(address: String!): Follower
|
||||
|
||||
"""Reject a relay subscription"""
|
||||
rejectRelay(address: String!): Follower
|
||||
|
||||
"""Leave an event"""
|
||||
leaveGroup(actorId: ID!, groupId: ID!): DeletedMember
|
||||
|
||||
"""Validate an user after registration"""
|
||||
validateUser(token: String!): Login
|
||||
|
||||
"""Create a note on a report"""
|
||||
createReportNote(content: String, moderatorId: ID!, reportId: ID!): ReportNote
|
||||
|
||||
"""Accept a relay subscription"""
|
||||
acceptRelay(address: String!): Follower
|
||||
}
|
||||
|
||||
"""
|
||||
|
|
|
@ -2,11 +2,10 @@ defmodule MobilizonWeb.Resolvers.UserResolverTest do
|
|||
use MobilizonWeb.ConnCase
|
||||
|
||||
import Mobilizon.Factory
|
||||
import Mock
|
||||
|
||||
use Bamboo.Test
|
||||
|
||||
alias Mobilizon.{Actors, Config, Users}
|
||||
alias Mobilizon.{Actors, Users}
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Service.Users.ResetPassword
|
||||
alias Mobilizon.Users
|
||||
|
@ -321,6 +320,123 @@ defmodule MobilizonWeb.Resolvers.UserResolverTest do
|
|||
assert hd(json_response(res, 200)["errors"])["message"] == "This email is already used."
|
||||
end
|
||||
|
||||
test "create_user/3 doesn't allow registration when registration is closed", %{conn: conn} do
|
||||
Mobilizon.Config.put([:instance, :registrations_open], false)
|
||||
Mobilizon.Config.put([:instance, :registration_email_whitelist], [])
|
||||
|
||||
mutation = """
|
||||
mutation createUser($email: String!, $password: String!) {
|
||||
createUser(
|
||||
email: $email,
|
||||
password: $password,
|
||||
) {
|
||||
id,
|
||||
email
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
res =
|
||||
conn
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: mutation,
|
||||
variables: %{email: @user_creation.email, password: @user_creation.password}
|
||||
)
|
||||
|
||||
assert hd(res["errors"])["message"] == "Registrations are not enabled"
|
||||
Mobilizon.Config.put([:instance, :registrations_open], true)
|
||||
end
|
||||
|
||||
test "create_user/3 doesn't allow registration when user email is not on the whitelist", %{
|
||||
conn: conn
|
||||
} do
|
||||
Mobilizon.Config.put([:instance, :registrations_open], false)
|
||||
Mobilizon.Config.put([:instance, :registration_email_whitelist], ["random.org"])
|
||||
|
||||
mutation = """
|
||||
mutation createUser($email: String!, $password: String!) {
|
||||
createUser(
|
||||
email: $email,
|
||||
password: $password,
|
||||
) {
|
||||
id,
|
||||
email
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
res =
|
||||
conn
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: mutation,
|
||||
variables: %{email: @user_creation.email, password: @user_creation.password}
|
||||
)
|
||||
|
||||
assert hd(res["errors"])["message"] == "Your email is not on the whitelist"
|
||||
Mobilizon.Config.put([:instance, :registrations_open], true)
|
||||
Mobilizon.Config.put([:instance, :registration_email_whitelist], [])
|
||||
end
|
||||
|
||||
test "create_user/3 allows registration when user email domain is on the whitelist", %{
|
||||
conn: conn
|
||||
} do
|
||||
Mobilizon.Config.put([:instance, :registrations_open], false)
|
||||
Mobilizon.Config.put([:instance, :registration_email_whitelist], ["demo.tld"])
|
||||
|
||||
mutation = """
|
||||
mutation createUser($email: String!, $password: String!) {
|
||||
createUser(
|
||||
email: $email,
|
||||
password: $password,
|
||||
) {
|
||||
id,
|
||||
email
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
res =
|
||||
conn
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: mutation,
|
||||
variables: %{email: @user_creation.email, password: @user_creation.password}
|
||||
)
|
||||
|
||||
refute res["errors"]
|
||||
assert res["data"]["createUser"]["email"] == @user_creation.email
|
||||
Mobilizon.Config.put([:instance, :registrations_open], true)
|
||||
Mobilizon.Config.put([:instance, :registration_email_whitelist], [])
|
||||
end
|
||||
|
||||
test "create_user/3 allows registration when user email is on the whitelist", %{conn: conn} do
|
||||
Mobilizon.Config.put([:instance, :registrations_open], false)
|
||||
Mobilizon.Config.put([:instance, :registration_email_whitelist], [@user_creation.email])
|
||||
|
||||
mutation = """
|
||||
mutation createUser($email: String!, $password: String!) {
|
||||
createUser(
|
||||
email: $email,
|
||||
password: $password,
|
||||
) {
|
||||
id,
|
||||
email
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
res =
|
||||
conn
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: mutation,
|
||||
variables: %{email: @user_creation.email, password: @user_creation.password}
|
||||
)
|
||||
|
||||
refute res["errors"]
|
||||
assert res["data"]["createUser"]["email"] == @user_creation.email
|
||||
Mobilizon.Config.put([:instance, :registrations_open], true)
|
||||
Mobilizon.Config.put([:instance, :registration_email_whitelist], [])
|
||||
end
|
||||
|
||||
test "register_person/3 doesn't register a profile from an unknown email", context do
|
||||
mutation = """
|
||||
mutation {
|
||||
|
@ -450,29 +566,6 @@ defmodule MobilizonWeb.Resolvers.UserResolverTest do
|
|||
assert hd(json_response(res, 200)["errors"])["message"] ==
|
||||
"Email doesn't fit required format"
|
||||
end
|
||||
|
||||
test "test create_user/3 doesn't create a user when registration is disabled", context do
|
||||
with_mock Config, instance_registrations_open?: fn -> false end do
|
||||
mutation = """
|
||||
mutation {
|
||||
createUser(
|
||||
email: "#{@user_creation.email}",
|
||||
password: "#{@user_creation.password}",
|
||||
) {
|
||||
id,
|
||||
email
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
res =
|
||||
context.conn
|
||||
|> post("/api", AbsintheHelpers.mutation_skeleton(mutation))
|
||||
|
||||
assert hd(json_response(res, 200)["errors"])["message"] ==
|
||||
"Registrations are not enabled"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "Resolver: Validate an user" do
|
||||
|
|
Loading…
Reference in a new issue