Merge branch 'fixes' into 'master'
Bunch of little fixes Closes #274, #230, #232, #311, #316 et #315 See merge request framasoft/mobilizon!322
This commit is contained in:
commit
792a2deddb
|
@ -55,7 +55,7 @@
|
|||
"@vue/cli-plugin-typescript": "^4.0.3",
|
||||
"@vue/cli-plugin-unit-mocha": "^4.0.3",
|
||||
"@vue/cli-service": "^4.0.3",
|
||||
"@vue/eslint-config-typescript": "^4.0.0",
|
||||
"@vue/eslint-config-typescript": "^5.0.0",
|
||||
"@vue/test-utils": "^1.0.0-beta.29",
|
||||
"apollo-link-error": "^1.1.12",
|
||||
"chai": "^4.2.0",
|
||||
|
@ -67,8 +67,8 @@
|
|||
"tslint": "^5.20.0",
|
||||
"tslint-config-airbnb": "^5.11.2",
|
||||
"typescript": "^3.6.3",
|
||||
"vue-cli-plugin-styleguidist": "^3.25.0",
|
||||
"vue-cli-plugin-webpack-bundle-analyzer": "^1.3.0",
|
||||
"vue-cli-plugin-styleguidist": "^4.0.1",
|
||||
"vue-cli-plugin-webpack-bundle-analyzer": "^2.0.0",
|
||||
"vue-i18n-extract": "^1.0.2",
|
||||
"vue-svg-inline-loader": "^1.3.0",
|
||||
"vue-template-compiler": "^2.6.10",
|
||||
|
|
|
@ -387,6 +387,7 @@ export default class EditorComponent extends Vue {
|
|||
placement: 'top-start',
|
||||
inertia: true,
|
||||
duration: [400, 200],
|
||||
// @ts-ignore for some reason
|
||||
showOnInit: true,
|
||||
arrow: true,
|
||||
arrowType: 'round',
|
||||
|
|
|
@ -70,7 +70,7 @@ query {
|
|||
}`;
|
||||
|
||||
export const CURRENT_ACTOR_CLIENT = gql`
|
||||
query {
|
||||
query currentActor {
|
||||
currentActor @client {
|
||||
id,
|
||||
avatar {
|
||||
|
|
|
@ -289,6 +289,7 @@ export const EDIT_EVENT = gql`
|
|||
$picture: PictureInput,
|
||||
$onlineAddress: String,
|
||||
$phoneAddress: String,
|
||||
$organizerActorId: ID,
|
||||
$category: String,
|
||||
$physicalAddress: AddressInput,
|
||||
$options: EventOptionsInput,
|
||||
|
@ -307,6 +308,7 @@ export const EDIT_EVENT = gql`
|
|||
picture: $picture,
|
||||
onlineAddress: $onlineAddress,
|
||||
phoneAddress: $phoneAddress,
|
||||
organizerActorId: $organizerActorId,
|
||||
category: $category,
|
||||
physicalAddress: $physicalAddress
|
||||
options: $options,
|
||||
|
|
35
js/src/mixins/identityEdition.ts
Normal file
35
js/src/mixins/identityEdition.ts
Normal file
|
@ -0,0 +1,35 @@
|
|||
import { Component, Mixins, Vue } from 'vue-property-decorator';
|
||||
import { Person } from '@/types/actor';
|
||||
|
||||
@Component
|
||||
export default class IdentityEditionMixin extends Mixins(Vue) {
|
||||
|
||||
identity = new Person();
|
||||
oldDisplayName: string | null = null;
|
||||
|
||||
autoUpdateUsername(newDisplayName: string | null) {
|
||||
const oldUsername = IdentityEditionMixin.convertToUsername(this.oldDisplayName);
|
||||
|
||||
if (this.identity.preferredUsername === oldUsername) {
|
||||
this.identity.preferredUsername = IdentityEditionMixin.convertToUsername(newDisplayName);
|
||||
}
|
||||
|
||||
this.oldDisplayName = newDisplayName;
|
||||
}
|
||||
|
||||
private static convertToUsername(value: string | null) {
|
||||
if (!value) return '';
|
||||
|
||||
// https://stackoverflow.com/a/37511463
|
||||
return value.toLocaleLowerCase()
|
||||
.normalize('NFD')
|
||||
.replace(/[\u0300-\u036f]/g, '')
|
||||
.replace(/ /g, '_')
|
||||
.replace(/[^a-z0-9_]/g, '')
|
||||
;
|
||||
}
|
||||
|
||||
validateUsername() {
|
||||
return this.identity.preferredUsername === IdentityEditionMixin.convertToUsername(this.identity.preferredUsername);
|
||||
}
|
||||
}
|
|
@ -10,7 +10,7 @@
|
|||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Prop, Vue } from 'vue-property-decorator';
|
||||
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
|
||||
import { IActor } from '@/types/actor';
|
||||
import IdentityPicker from './IdentityPicker.vue';
|
||||
|
||||
|
@ -22,6 +22,11 @@ export default class IdentityPickerWrapper extends Vue {
|
|||
isComponentModalActive: boolean = false;
|
||||
currentIdentity: IActor = this.value;
|
||||
|
||||
@Watch('value')
|
||||
updateCurrentActor(value) {
|
||||
this.currentIdentity = value;
|
||||
}
|
||||
|
||||
relay(identity: IActor) {
|
||||
this.currentIdentity = identity;
|
||||
this.$emit('input', identity);
|
||||
|
@ -36,4 +41,4 @@ export default class IdentityPickerWrapper extends Vue {
|
|||
height: 1.5em;
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
@ -9,6 +9,10 @@
|
|||
{{ $t('To achieve your registration, please create a first identity profile.')}}
|
||||
</b-message>
|
||||
<form v-if="!validationSent" @submit.prevent="submit">
|
||||
<b-field :label="$t('Display name')">
|
||||
<b-input aria-required="true" required v-model="identity.name" @input="autoUpdateUsername($event)"/>
|
||||
</b-field>
|
||||
|
||||
<b-field
|
||||
:label="$t('Username')"
|
||||
:type="errors.preferred_username ? 'is-danger' : null"
|
||||
|
@ -19,7 +23,7 @@
|
|||
aria-required="true"
|
||||
required
|
||||
expanded
|
||||
v-model="person.preferredUsername"
|
||||
v-model="identity.preferredUsername"
|
||||
/>
|
||||
<p class="control">
|
||||
<span class="button is-static">@{{ host }}</span>
|
||||
|
@ -27,12 +31,8 @@
|
|||
</b-field>
|
||||
</b-field>
|
||||
|
||||
<b-field :label="$t('Displayed name')">
|
||||
<b-input v-model="person.name"/>
|
||||
</b-field>
|
||||
|
||||
<b-field :label="$t('Description')">
|
||||
<b-input type="textarea" v-model="person.summary"/>
|
||||
<b-input type="textarea" v-model="identity.summary"/>
|
||||
</b-field>
|
||||
|
||||
<p class="control has-text-centered">
|
||||
|
@ -45,7 +45,7 @@
|
|||
<div v-if="validationSent && !userAlreadyActivated">
|
||||
<b-message title="Success" type="is-success" closable="false">
|
||||
<h2 class="title">
|
||||
{{ $t('Your account is nearly ready, {username}', { username: person.preferredUsername }) }}
|
||||
{{ $t('Your account is nearly ready, {username}', { username: identity.preferredUsername }) }}
|
||||
</h2>
|
||||
<p>
|
||||
{{ $t('A validation email was sent to {email}', { email }) }}
|
||||
|
@ -61,22 +61,22 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Prop, Vue } from 'vue-property-decorator';
|
||||
import { IPerson, Person } from '@/types/actor';
|
||||
import { Component, Prop } from 'vue-property-decorator';
|
||||
import { IPerson } from '@/types/actor';
|
||||
import { IDENTITIES, REGISTER_PERSON } from '@/graphql/actor';
|
||||
import { MOBILIZON_INSTANCE_HOST } from '@/api/_entrypoint';
|
||||
import { RouteName } from '@/router';
|
||||
import { changeIdentity } from '@/utils/auth';
|
||||
import { ICurrentUser } from '@/types/current-user.model';
|
||||
import { mixins } from 'vue-class-component';
|
||||
import identityEditionMixin from '@/mixins/identityEdition';
|
||||
|
||||
@Component
|
||||
export default class Register extends Vue {
|
||||
export default class Register extends mixins(identityEditionMixin) {
|
||||
@Prop({ type: String, required: true }) email!: string;
|
||||
@Prop({ type: Boolean, required: false, default: false }) userAlreadyActivated!: boolean;
|
||||
|
||||
host?: string = MOBILIZON_INSTANCE_HOST;
|
||||
|
||||
person: IPerson = new Person();
|
||||
errors: object = {};
|
||||
validationSent: boolean = false;
|
||||
sendingValidation: boolean = false;
|
||||
|
@ -94,7 +94,7 @@ export default class Register extends Vue {
|
|||
this.errors = {};
|
||||
const { data } = await this.$apollo.mutate<{ registerPerson: IPerson }>({
|
||||
mutation: REGISTER_PERSON,
|
||||
variables: Object.assign({ email: this.email }, this.person),
|
||||
variables: Object.assign({ email: this.email }, this.identity),
|
||||
update: (store, { data }) => {
|
||||
if (this.userAlreadyActivated) {
|
||||
const identitiesData = store.readQuery<{ identities: IPerson[] }>({ query: IDENTITIES });
|
||||
|
|
|
@ -7,13 +7,13 @@
|
|||
|
||||
<picture-upload v-model="avatarFile" class="picture-upload"></picture-upload>
|
||||
|
||||
<b-field :label="$t('Display name')">
|
||||
<b-field horizontal :label="$t('Display name')">
|
||||
<b-input aria-required="true" required v-model="identity.name" @input="autoUpdateUsername($event)"/>
|
||||
</b-field>
|
||||
|
||||
<b-field :label="$t('Username')">
|
||||
<b-field>
|
||||
<b-input aria-required="true" required v-model="identity.preferredUsername" :disabled="isUpdate"/>
|
||||
<b-field horizontal custom-class="username-field" expanded :label="$t('Username')" :message="message">
|
||||
<b-field expanded>
|
||||
<b-input aria-required="true" required v-model="identity.preferredUsername" :disabled="isUpdate" :use-html5-validation="!isUpdate" pattern="[a-z0-9_]+"/>
|
||||
|
||||
<p class="control">
|
||||
<span class="button is-static">@{{ getInstanceHost() }}</span>
|
||||
|
@ -21,7 +21,7 @@
|
|||
</b-field>
|
||||
</b-field>
|
||||
|
||||
<b-field :label="$t('Description')">
|
||||
<b-field horizontal :label="$t('Description')">
|
||||
<b-input type="textarea" aria-required="false" v-model="identity.summary"/>
|
||||
</b-field>
|
||||
|
||||
|
@ -77,10 +77,14 @@
|
|||
cursor: pointer;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.username-field + .field {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
|
||||
import { Component, Prop, Watch } from 'vue-property-decorator';
|
||||
import {
|
||||
CREATE_PERSON,
|
||||
CURRENT_ACTOR_CLIENT,
|
||||
|
@ -96,6 +100,8 @@ import { Dialog } from 'buefy/dist/components/dialog';
|
|||
import { RouteName } from '@/router';
|
||||
import { buildFileFromIPicture, buildFileVariable, readFileAsync } from '@/utils/image';
|
||||
import { changeIdentity } from '@/utils/auth';
|
||||
import { mixins } from 'vue-class-component';
|
||||
import identityEditionMixin from '@/mixins/identityEdition';
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
|
@ -108,18 +114,21 @@ import { changeIdentity } from '@/utils/auth';
|
|||
},
|
||||
},
|
||||
})
|
||||
export default class EditIdentity extends Vue {
|
||||
export default class EditIdentity extends mixins(identityEditionMixin) {
|
||||
@Prop({ type: Boolean }) isUpdate!: boolean;
|
||||
|
||||
errors: string[] = [];
|
||||
|
||||
identityName!: string | undefined;
|
||||
avatarFile: File | null = null;
|
||||
identity = new Person();
|
||||
|
||||
private oldDisplayName: string | null = null;
|
||||
private currentActor: IPerson | null = null;
|
||||
|
||||
get message() {
|
||||
if (this.isUpdate) return null;
|
||||
return this.$t('Only alphanumeric characters and underscores are supported.');
|
||||
}
|
||||
|
||||
@Watch('isUpdate')
|
||||
async isUpdateChanged () {
|
||||
this.resetFields();
|
||||
|
@ -153,16 +162,6 @@ export default class EditIdentity extends Vue {
|
|||
return this.createIdentity();
|
||||
}
|
||||
|
||||
autoUpdateUsername(newDisplayName: string | null) {
|
||||
const oldUsername = this.convertToUsername(this.oldDisplayName);
|
||||
|
||||
if (this.identity.preferredUsername === oldUsername) {
|
||||
this.identity.preferredUsername = this.convertToUsername(newDisplayName);
|
||||
}
|
||||
|
||||
this.oldDisplayName = newDisplayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an identity
|
||||
*/
|
||||
|
@ -309,18 +308,6 @@ export default class EditIdentity extends Vue {
|
|||
}
|
||||
}
|
||||
|
||||
private convertToUsername(value: string | null) {
|
||||
if (!value) return '';
|
||||
|
||||
// https://stackoverflow.com/a/37511463
|
||||
return value.toLocaleLowerCase()
|
||||
.normalize('NFD')
|
||||
.replace(/[\u0300-\u036f]/g, '')
|
||||
.replace(/ /g, '_')
|
||||
.replace(/[^a-z0-9._]/g, '')
|
||||
;
|
||||
}
|
||||
|
||||
private async buildVariables() {
|
||||
const avatarObj = buildFileVariable(this.avatarFile, 'avatar', `${this.identity.preferredUsername}'s avatar`);
|
||||
const res = Object.assign({}, this.identity, avatarObj);
|
||||
|
|
2571
js/yarn.lock
2571
js/yarn.lock
File diff suppressed because it is too large
Load diff
|
@ -203,14 +203,9 @@ defmodule Mobilizon.Actors.Actor do
|
|||
actor
|
||||
|> cast(attrs, @attrs)
|
||||
|> build_urls()
|
||||
|> cast_embed(:avatar)
|
||||
|> cast_embed(:banner)
|
||||
|> common_changeset()
|
||||
|> unique_username_validator()
|
||||
|> validate_required(@required_attrs)
|
||||
|> unique_constraint(:preferred_username,
|
||||
name: :actors_preferred_username_domain_type_index
|
||||
)
|
||||
|> unique_constraint(:url, name: :actors_url_index)
|
||||
end
|
||||
|
||||
@doc false
|
||||
|
@ -218,13 +213,8 @@ defmodule Mobilizon.Actors.Actor do
|
|||
def update_changeset(%__MODULE__{} = actor, attrs) do
|
||||
actor
|
||||
|> cast(attrs, @update_attrs)
|
||||
|> cast_embed(:avatar)
|
||||
|> cast_embed(:banner)
|
||||
|> common_changeset()
|
||||
|> validate_required(@update_required_attrs)
|
||||
|> unique_constraint(:preferred_username,
|
||||
name: :actors_preferred_username_domain_type_index
|
||||
)
|
||||
|> unique_constraint(:url, name: :actors_url_index)
|
||||
end
|
||||
|
||||
@doc """
|
||||
|
@ -235,13 +225,8 @@ defmodule Mobilizon.Actors.Actor do
|
|||
actor
|
||||
|> cast(attrs, @registration_attrs)
|
||||
|> build_urls()
|
||||
|> cast_embed(:avatar)
|
||||
|> cast_embed(:banner)
|
||||
|> common_changeset()
|
||||
|> unique_username_validator()
|
||||
|> unique_constraint(:preferred_username,
|
||||
name: :actors_preferred_username_domain_type_index
|
||||
)
|
||||
|> unique_constraint(:url, name: :actors_url_index)
|
||||
|> validate_required(@registration_required_attrs)
|
||||
end
|
||||
|
||||
|
@ -254,13 +239,8 @@ defmodule Mobilizon.Actors.Actor do
|
|||
%__MODULE__{}
|
||||
|> cast(attrs, @remote_actor_creation_attrs)
|
||||
|> validate_required(@remote_actor_creation_required_attrs)
|
||||
|> cast_embed(:avatar)
|
||||
|> cast_embed(:banner)
|
||||
|> common_changeset()
|
||||
|> unique_username_validator()
|
||||
|> unique_constraint(:preferred_username,
|
||||
name: :actors_preferred_username_domain_type_index
|
||||
)
|
||||
|> unique_constraint(:url, name: :actors_url_index)
|
||||
|> validate_length(:summary, max: 5000)
|
||||
|> validate_length(:preferred_username, max: 100)
|
||||
|
||||
|
@ -269,6 +249,16 @@ defmodule Mobilizon.Actors.Actor do
|
|||
changeset
|
||||
end
|
||||
|
||||
@spec common_changeset(Ecto.Changeset.t()) :: Ecto.Changeset.t()
|
||||
defp common_changeset(%Ecto.Changeset{} = changeset) do
|
||||
changeset
|
||||
|> cast_embed(:avatar)
|
||||
|> cast_embed(:banner)
|
||||
|> unique_constraint(:url, name: :actors_url_index)
|
||||
|> unique_constraint(:preferred_username, name: :actors_preferred_username_domain_type_index)
|
||||
|> validate_format(:preferred_username, ~r/[a-z0-9_]+/)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Changeset for relay creation.
|
||||
"""
|
||||
|
|
|
@ -128,7 +128,6 @@ defmodule Mobilizon.Events.Event do
|
|||
|> common_changeset(attrs)
|
||||
|> put_creator_if_published(:create)
|
||||
|> validate_required(@required_attrs)
|
||||
|> validate_lengths()
|
||||
end
|
||||
|
||||
@doc false
|
||||
|
@ -139,7 +138,6 @@ defmodule Mobilizon.Events.Event do
|
|||
|> common_changeset(attrs)
|
||||
|> put_creator_if_published(:update)
|
||||
|> validate_required(@update_required_attrs)
|
||||
|> validate_lengths()
|
||||
end
|
||||
|
||||
@spec common_changeset(Changeset.t(), map) :: Changeset.t()
|
||||
|
@ -149,6 +147,8 @@ defmodule Mobilizon.Events.Event do
|
|||
|> put_tags(attrs)
|
||||
|> put_address(attrs)
|
||||
|> put_picture(attrs)
|
||||
|> validate_lengths()
|
||||
|> validate_end_time()
|
||||
end
|
||||
|
||||
@spec validate_lengths(Changeset.t()) :: Changeset.t()
|
||||
|
@ -162,6 +162,20 @@ defmodule Mobilizon.Events.Event do
|
|||
|> validate_length(:slug, min: 3, max: 200)
|
||||
end
|
||||
|
||||
defp validate_end_time(%Changeset{} = changeset) do
|
||||
case fetch_field(changeset, :begins_on) do
|
||||
{_, begins_on} ->
|
||||
validate_change(changeset, :ends_on, fn :ends_on, ends_on ->
|
||||
if begins_on > ends_on,
|
||||
do: [ends_on: "ends_on cannot be set before begins_on"],
|
||||
else: []
|
||||
end)
|
||||
|
||||
:error ->
|
||||
changeset
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Checks whether an event can be managed.
|
||||
"""
|
||||
|
|
|
@ -275,6 +275,9 @@ defmodule MobilizonWeb.Resolvers.Event do
|
|||
{:is_owned, nil} ->
|
||||
{:error, "Organizer actor id is not owned by the user"}
|
||||
|
||||
{:error, _, %Ecto.Changeset{} = error, _} ->
|
||||
{:error, error}
|
||||
|
||||
{:error, %Ecto.Changeset{} = error} ->
|
||||
{:error, error}
|
||||
end
|
||||
|
@ -295,8 +298,9 @@ defmodule MobilizonWeb.Resolvers.Event do
|
|||
# See https://github.com/absinthe-graphql/absinthe/issues/490
|
||||
with args <- Map.put(args, :options, args[:options] || %{}),
|
||||
{:ok, %Event{} = event} <- Events.get_event_with_preload(event_id),
|
||||
organizer_actor_id <- args |> Map.get(:organizer_actor_id, event.organizer_actor_id),
|
||||
{:is_owned, %Actor{} = organizer_actor} <-
|
||||
User.owns_actor(user, event.organizer_actor_id),
|
||||
User.owns_actor(user, organizer_actor_id),
|
||||
args <- Map.put(args, :organizer_actor, organizer_actor),
|
||||
{:ok, %Activity{data: %{"object" => %{"type" => "Event"}}}, %Event{} = event} <-
|
||||
MobilizonWeb.API.Events.update_event(args, event) do
|
||||
|
@ -307,6 +311,9 @@ defmodule MobilizonWeb.Resolvers.Event do
|
|||
|
||||
{:is_owned, nil} ->
|
||||
{:error, "User doesn't own actor"}
|
||||
|
||||
{:error, _, %Ecto.Changeset{} = error, _} ->
|
||||
{:error, error}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -299,6 +299,7 @@ defmodule MobilizonWeb.Schema.EventType do
|
|||
|
||||
arg(:online_address, :string)
|
||||
arg(:phone_address, :string)
|
||||
arg(:organizer_actor_id, :id)
|
||||
arg(:category, :string)
|
||||
arg(:physical_address, :address_input)
|
||||
arg(:options, :event_options_input)
|
||||
|
|
|
@ -93,8 +93,6 @@ defmodule Mobilizon.Service.ActivityPub do
|
|||
{:ok, Actors.get_actor_by_url!(actor_url, true)}
|
||||
|
||||
e ->
|
||||
require Logger
|
||||
Logger.error(inspect(e))
|
||||
{:error, e}
|
||||
end
|
||||
end
|
||||
|
@ -135,14 +133,13 @@ defmodule Mobilizon.Service.ActivityPub do
|
|||
Logger.debug("creating an activity")
|
||||
Logger.debug(inspect(args))
|
||||
|
||||
{:ok, entity, create_data} =
|
||||
case type do
|
||||
:event -> create_event(args, additional)
|
||||
:comment -> create_comment(args, additional)
|
||||
:group -> create_group(args, additional)
|
||||
end
|
||||
|
||||
with {:ok, activity} <- create_activity(create_data, local),
|
||||
with {:ok, entity, create_data} <-
|
||||
(case type do
|
||||
:event -> create_event(args, additional)
|
||||
:comment -> create_comment(args, additional)
|
||||
:group -> create_group(args, additional)
|
||||
end),
|
||||
{:ok, activity} <- create_activity(create_data, local),
|
||||
:ok <- maybe_federate(activity) do
|
||||
{:ok, activity, entity}
|
||||
else
|
||||
|
@ -167,13 +164,12 @@ defmodule Mobilizon.Service.ActivityPub do
|
|||
Logger.debug("updating an activity")
|
||||
Logger.debug(inspect(args))
|
||||
|
||||
{:ok, entity, update_data} =
|
||||
case type do
|
||||
:event -> update_event(old_entity, args, additional)
|
||||
:actor -> update_actor(old_entity, args, additional)
|
||||
end
|
||||
|
||||
with {:ok, activity} <- create_activity(update_data, local),
|
||||
with {:ok, entity, update_data} <-
|
||||
(case type do
|
||||
:event -> update_event(old_entity, args, additional)
|
||||
:actor -> update_actor(old_entity, args, additional)
|
||||
end),
|
||||
{:ok, activity} <- create_activity(update_data, local),
|
||||
:ok <- maybe_federate(activity) do
|
||||
{:ok, activity, entity}
|
||||
else
|
||||
|
|
|
@ -339,8 +339,7 @@ defmodule Mobilizon.Service.ActivityPub.Transmogrifier do
|
|||
ActivityPub.update(:event, old_event, object_data, false) do
|
||||
{:ok, activity, new_event}
|
||||
else
|
||||
e ->
|
||||
Logger.error(inspect(e))
|
||||
_e ->
|
||||
:error
|
||||
end
|
||||
end
|
||||
|
@ -442,8 +441,7 @@ defmodule Mobilizon.Service.ActivityPub.Transmogrifier do
|
|||
|
||||
:error
|
||||
|
||||
e ->
|
||||
Logger.error(inspect(e))
|
||||
_e ->
|
||||
:error
|
||||
end
|
||||
end
|
||||
|
|
2
mix.exs
2
mix.exs
|
@ -100,7 +100,7 @@ defmodule Mobilizon.Mixfile do
|
|||
{:ex_cldr_dates_times, "~> 2.0"},
|
||||
{:ex_optimizer, "~> 0.1"},
|
||||
{:progress_bar, "~> 2.0"},
|
||||
{:oban, "~> 0.10"},
|
||||
{:oban, "~> 0.11.1"},
|
||||
# Dev and test dependencies
|
||||
{:phoenix_live_reload, "~> 1.2", only: [:dev, :e2e]},
|
||||
{:ex_machina, "~> 2.3", only: [:dev, :test]},
|
||||
|
|
18
mix.lock
18
mix.lock
|
@ -14,7 +14,7 @@
|
|||
"certifi": {:hex, :certifi, "2.5.1", "867ce347f7c7d78563450a18a6a28a8090331e77fa02380b4a21962a65d36ee5", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"cldr_utils": {:hex, :cldr_utils, "2.5.0", "2a15b82b5b56bba99b897ff5801a5b1dcbce425b6430445e97d024a9999afb03", [:mix], [{:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm"},
|
||||
"comeonin": {:hex, :comeonin, "5.1.2", "fbbbbbfcf0f0e9900c0336d16c8d462edf838ba1759577e29cc5fbd7c28a4540", [:mix], [], "hexpm"},
|
||||
"comeonin": {:hex, :comeonin, "5.1.3", "4c9880ed348cc0330c74086b4383ffb0b5a599aa603416497b7374c168cae340", [:mix], [], "hexpm"},
|
||||
"connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm"},
|
||||
"cors_plug": {:hex, :cors_plug, "2.0.0", "238ddb479f92b38f6dc1ae44b8d81f0387f9519101a6da442d543ab70ee0e482", [:mix], [{:plug, "~> 1.3 or ~> 1.4 or ~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"cowboy": {:hex, :cowboy, "2.7.0", "91ed100138a764355f43316b1d23d7ff6bdb0de4ea618cb5d8677c93a7a2f115", [:rebar3], [{:cowlib, "~> 2.8.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
|
@ -34,8 +34,8 @@
|
|||
"erlex": {:hex, :erlex, "0.2.5", "e51132f2f472e13d606d808f0574508eeea2030d487fc002b46ad97e738b0510", [:mix], [], "hexpm"},
|
||||
"eternal": {:hex, :eternal, "1.2.1", "d5b6b2499ba876c57be2581b5b999ee9bdf861c647401066d3eeed111d096bc4", [:mix], [], "hexpm"},
|
||||
"ex_cldr": {:hex, :ex_cldr, "2.11.1", "8e500a88b68be01a97315bea394d593e74e1035c0a5dc6f0b8281423857ec9b3", [:mix], [{:cldr_utils, "~> 2.3", [hex: :cldr_utils, repo: "hexpm", optional: false]}, {:decimal, "~> 1.6", [hex: :decimal, repo: "hexpm", optional: false]}, {:gettext, "~> 0.13", [hex: :gettext, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:nimble_parsec, "~> 0.5", [hex: :nimble_parsec, repo: "hexpm", optional: false]}, {:plug, "~> 1.4", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm"},
|
||||
"ex_cldr_calendars": {:hex, :ex_cldr_calendars, "1.4.0", "c7adf1e752b0cbad6f565246a583f1d056ad05fdc0c7fb8b66d498d1b381225f", [:mix], [{:ex_cldr, "~> 2.8", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:ex_cldr_lists, "~> 2.4", [hex: :ex_cldr_lists, repo: "hexpm", optional: true]}, {:ex_cldr_units, "~> 2.0", [hex: :ex_cldr_units, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"ex_cldr_currencies": {:hex, :ex_cldr_currencies, "2.3.0", "bffae489416b8b05d4683403263f5d62aae17de70c24ff915a533541fea514de", [:mix], [{:ex_cldr, "~> 2.6", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"},
|
||||
"ex_cldr_calendars": {:hex, :ex_cldr_calendars, "1.5.1", "136bc95c87791bfc558d19182e53790263981484085ffa23ceb9122ad52001c9", [:mix], [{:ex_cldr, "~> 2.8", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:ex_cldr_lists, "~> 2.4", [hex: :ex_cldr_lists, repo: "hexpm", optional: true]}, {:ex_cldr_units, "~> 2.0", [hex: :ex_cldr_units, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"ex_cldr_currencies": {:hex, :ex_cldr_currencies, "2.4.1", "a8e8330a6d0712b8bb34c5e3759311da1d53fa8bebef163d72615f0ea60c0738", [:mix], [{:ex_cldr, "~> 2.6", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"},
|
||||
"ex_cldr_dates_times": {:hex, :ex_cldr_dates_times, "2.2.3", "4a82f6af48f55c92c0d28be066e5b2451e807e3f49246d08845af664fd7cb712", [:mix], [{:ex_cldr, "~> 2.8", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:ex_cldr_calendars, "~> 1.2", [hex: :ex_cldr_calendars, repo: "hexpm", optional: false]}, {:ex_cldr_numbers, "~> 2.6", [hex: :ex_cldr_numbers, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"},
|
||||
"ex_cldr_numbers": {:hex, :ex_cldr_numbers, "2.9.0", "ffba3ba8cfa41194e57cc38f0cc78f83956ce5c1822b1e4d5f64394cb927ba2c", [:mix], [{:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:ex_cldr, "~> 2.11", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:ex_cldr_currencies, "~> 2.3", [hex: :ex_cldr_currencies, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"},
|
||||
"ex_crypto": {:hex, :ex_crypto, "0.10.0", "af600a89b784b36613a989da6e998c1b200ff1214c3cfbaf8deca4aa2f0a1739", [:mix], [{:poison, ">= 2.0.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
|
@ -64,7 +64,7 @@
|
|||
"html_sanitize_ex": {:hex, :html_sanitize_ex, "1.3.0", "f005ad692b717691203f940c686208aa3d8ffd9dd4bb3699240096a51fa9564e", [:mix], [{:mochiweb, "~> 2.15", [hex: :mochiweb, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"http_sign": {:hex, :http_sign, "0.1.1", "b16edb83aa282892f3271f9a048c155e772bf36e15700ab93901484c55f8dd10", [:mix], [{:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"http_signatures": {:git, "https://git.pleroma.social/pleroma/http_signatures.git", "293d77bb6f4a67ac8bde1428735c3b42f22cbb30", [ref: "293d77bb6f4a67ac8bde1428735c3b42f22cbb30"]},
|
||||
"httpoison": {:hex, :httpoison, "1.6.1", "2ce5bf6e535cd0ab02e905ba8c276580bab80052c5c549f53ddea52d72e81f33", [:mix], [{:hackney, "~> 1.15 and >= 1.15.2", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"httpoison": {:hex, :httpoison, "1.6.2", "ace7c8d3a361cebccbed19c283c349b3d26991eff73a1eaaa8abae2e3c8089b6", [:mix], [{:hackney, "~> 1.15 and >= 1.15.2", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"icalendar": {:git, "https://github.com/tcitworld/icalendar.git", "bd08e872c125f70a87c3ac7d87ea2f22a5577059", []},
|
||||
"idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"},
|
||||
|
@ -79,16 +79,16 @@
|
|||
"mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm"},
|
||||
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm"},
|
||||
"mimetype_parser": {:hex, :mimetype_parser, "0.1.3", "628ac9fe56aa7edcedb534d68397dd66674ab82493c8ebe39acb9a19b666099d", [:mix], [], "hexpm"},
|
||||
"mix_test_watch": {:hex, :mix_test_watch, "1.0.1", "ae6fc45bbc80b826046fb84208df4b06035e10fae6d44d0cb48c5a2f92ee2e1d", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"mix_test_watch": {:hex, :mix_test_watch, "1.0.2", "34900184cbbbc6b6ed616ed3a8ea9b791f9fd2088419352a6d3200525637f785", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"mmdb2_decoder": {:hex, :mmdb2_decoder, "1.1.0", "2e2347521bb3bf6b81b9ee58d3be2199cb68ea42dcbafcd0d8eb40214d2844cf", [:mix], [], "hexpm"},
|
||||
"mochiweb": {:hex, :mochiweb, "2.18.0", "eb55f1db3e6e960fac4e6db4e2db9ec3602cc9f30b86cd1481d56545c3145d2e", [:rebar3], [], "hexpm"},
|
||||
"mock": {:hex, :mock, "0.3.3", "42a433794b1291a9cf1525c6d26b38e039e0d3a360732b5e467bfc77ef26c914", [:mix], [{:meck, "~> 0.8.13", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"mogrify": {:hex, :mogrify, "0.7.3", "1494ee739f6e90de158dec4d4edee2d854d2f2d06a522e943f996ae176bca53d", [:mix], [], "hexpm"},
|
||||
"nimble_parsec": {:hex, :nimble_parsec, "0.5.1", "c90796ecee0289dbb5ad16d3ad06f957b0cd1199769641c961cfe0b97db190e0", [:mix], [], "hexpm"},
|
||||
"oban": {:hex, :oban, "0.10.1", "c2ca0a413fb66b21dd58c7cb67fd80b01e9d79a0fbb28573f110057e7fdc3807", [:mix], [{:ecto_sql, "~> 3.1", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.14", [hex: :postgrex, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"nimble_parsec": {:hex, :nimble_parsec, "0.5.2", "1d71150d5293d703a9c38d4329da57d3935faed2031d64bc19e77b654ef2d177", [:mix], [], "hexpm"},
|
||||
"oban": {:hex, :oban, "0.11.1", "e34964fad7f188c2c3d006485601a8897e537f7b88a31928be2833ae1cab59af", [:mix], [{:ecto_sql, "~> 3.1", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.14", [hex: :postgrex, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm"},
|
||||
"phoenix": {:hex, :phoenix, "1.4.10", "619e4a545505f562cd294df52294372d012823f4fd9d34a6657a8b242898c255", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.8.1 or ~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"phoenix_ecto": {:hex, :phoenix_ecto, "4.0.0", "c43117a136e7399ea04ecaac73f8f23ee0ffe3e07acfcb8062fe5f4c9f0f6531", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.9", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"phoenix": {:hex, :phoenix, "1.4.11", "d112c862f6959f98e6e915c3b76c7a87ca3efd075850c8daa7c3c7a609014b0d", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.8.1 or ~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"phoenix_ecto": {:hex, :phoenix_ecto, "4.1.0", "a044d0756d0464c5a541b4a0bf4bcaf89bffcaf92468862408290682c73ae50d", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.9", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"phoenix_html": {:hex, :phoenix_html, "2.13.3", "850e292ff6e204257f5f9c4c54a8cb1f6fbc16ed53d360c2b780a3d0ba333867", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"phoenix_live_reload": {:hex, :phoenix_live_reload, "1.2.1", "274a4b07c4adbdd7785d45a8b0bb57634d0b4f45b18d2c508b26c0344bd59b8f", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"phoenix_pubsub": {:hex, :phoenix_pubsub, "1.1.2", "496c303bdf1b2e98a9d26e89af5bba3ab487ba3a3735f74bf1f4064d2a845a3e", [:mix], [], "hexpm"},
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# source: http://localhost:4000/api
|
||||
# timestamp: Fri Nov 08 2019 17:20:47 GMT+0100 (Central European Standard Time)
|
||||
# timestamp: Mon Nov 18 2019 16:00:35 GMT+0100 (Central European Standard Time)
|
||||
|
||||
schema {
|
||||
query: RootQueryType
|
||||
|
@ -1081,6 +1081,7 @@ type RootMutationType {
|
|||
joinOptions: EventJoinOptions = FREE
|
||||
onlineAddress: String
|
||||
options: EventOptionsInput
|
||||
organizerActorId: ID
|
||||
phoneAddress: String
|
||||
physicalAddress: AddressInput
|
||||
|
||||
|
@ -1178,7 +1179,7 @@ type RootQueryType {
|
|||
reports(limit: Int = 10, page: Int = 1, status: ReportStatus = OPEN): [Report]
|
||||
|
||||
"""Reverse geocode coordinates"""
|
||||
reverseGeocode(latitude: Float!, longitude: Float!): [Address]
|
||||
reverseGeocode(latitude: Float!, locale: String = "en", longitude: Float!, zoom: Int = 15): [Address]
|
||||
|
||||
"""Search for an address"""
|
||||
searchAddress(limit: Int = 10, locale: String = "en", page: Int = 1, query: String!): [Address]
|
||||
|
|
|
@ -95,6 +95,40 @@ defmodule MobilizonWeb.Resolvers.EventResolverTest do
|
|||
"Organizer actor id is not owned by the user"
|
||||
end
|
||||
|
||||
test "create_event/3 should check that end time is after start time", %{
|
||||
conn: conn,
|
||||
actor: actor,
|
||||
user: user
|
||||
} do
|
||||
begins_on = DateTime.utc_now() |> DateTime.truncate(:second)
|
||||
ends_on = Timex.shift(begins_on, hours: -2)
|
||||
|
||||
mutation = """
|
||||
mutation {
|
||||
createEvent(
|
||||
title: "come to my event",
|
||||
description: "it will be fine",
|
||||
begins_on: "#{DateTime.to_iso8601(begins_on)}",
|
||||
ends_on: "#{DateTime.to_iso8601(ends_on)}",
|
||||
organizer_actor_id: "#{actor.id}",
|
||||
category: "birthday"
|
||||
) {
|
||||
id,
|
||||
title,
|
||||
uuid
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> post("/api", AbsintheHelpers.mutation_skeleton(mutation))
|
||||
|
||||
assert hd(json_response(res, 200)["errors"])["message"] ==
|
||||
"ends_on cannot be set before begins_on"
|
||||
end
|
||||
|
||||
test "create_event/3 creates an event", %{conn: conn, actor: actor, user: user} do
|
||||
mutation = """
|
||||
mutation {
|
||||
|
@ -661,6 +695,39 @@ defmodule MobilizonWeb.Resolvers.EventResolverTest do
|
|||
assert hd(json_response(res, 200)["errors"])["message"] == "User doesn't own actor"
|
||||
end
|
||||
|
||||
test "update_event/3 should check end time is after the beginning time", %{
|
||||
conn: conn,
|
||||
actor: actor,
|
||||
user: user
|
||||
} do
|
||||
event = insert(:event, organizer_actor: actor)
|
||||
|
||||
mutation = """
|
||||
mutation {
|
||||
updateEvent(
|
||||
title: "my event updated",
|
||||
ends_on: "#{Timex.shift(event.begins_on, hours: -2)}",
|
||||
event_id: #{event.id}
|
||||
) {
|
||||
title,
|
||||
uuid,
|
||||
tags {
|
||||
title,
|
||||
slug
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> post("/api", AbsintheHelpers.mutation_skeleton(mutation))
|
||||
|
||||
assert hd(json_response(res, 200)["errors"])["message"] ==
|
||||
"ends_on cannot be set before begins_on"
|
||||
end
|
||||
|
||||
test "update_event/3 updates an event", %{conn: conn, actor: actor, user: user} do
|
||||
event = insert(:event, organizer_actor: actor)
|
||||
_creator = insert(:participant, event: event, actor: actor, role: :creator)
|
||||
|
|
Loading…
Reference in a new issue