Commit 17636ee9 authored by Olivér FACKLAM's avatar Olivér FACKLAM

Merge branch 'mutations_priority_2' into 'master'

Mutations priority 2

See merge request !69
parents b002cd0f 6b372e20
Pipeline #5738 passed with stages
in 3 minutes and 58 seconds
......@@ -14,6 +14,7 @@ import { Group as LDAP_Group, groupData } from "../../ldap/export/group";
import { GroupCollection, GroupSet, Tools } from "../../utils/tools";
import { createSubgroupArgs, editGroupArgs } from "../typeDefs/queries";
import {Cache} from "../../utils/cache";
import { ApolloError } from "apollo-server-core";
export class GroupModel {
......@@ -54,6 +55,24 @@ export class GroupModel {
return null;
}
/**
* @summary Ensures the group exists in SQL database. Inserts it if needed.
*/
async ensureExists(gid: string) {
let g = await this.getGroup(gid);
if(!g || g instanceof MetaGroup) return;
let groups = await knex("groups").select("gid").where("gid", gid);
if(groups.length <= 0) {
await knex("groups").insert({gid: gid, type: "simple"});
}
let sgroups = await knex("simplegroups").select("gid").where("gid", gid);
if (sgroups.length <= 0) {
await knex("simplegroups").insert({gid: gid});
}
}
/**
* @memberof GraphQL.GroupModel#
* @function getSimpleGroup
......@@ -280,7 +299,7 @@ export class GroupModel {
* @rights member du groupe
*/
async userLeaveGroup(gid: string): Promise<boolean> {
throw "Not implemented";
return LDAP_Group.remMember(this.contextUser, gid);
}
/**
......@@ -441,7 +460,55 @@ export class GroupModel {
* @rights admin du groupe
*/
async editGroup(args: editGroupArgs): Promise<Group> {
throw "Not implemented";
let data = await knex('groups').select('type').where('gid', args.forGroup);
if(data.length > 0 && data[0].type == 'meta') {
// Update metagroup data
let ret = await knex('metagroups').where('gid', args.forGroup).update({
name: args.name,
description: args.description,
website: args.website,
mail: args.mail,
frontPage: args.frontPage
}, ['gid']);
if(ret.length > 0)
return this.getMetaGroup(args.forGroup);
else
throw new ApolloError("Edit failed");
}
else {
// It is a simplegroup
try {
// Modify LDAP data
let oldData = await LDAP_Group.peek(args.forGroup);
let newData = {
name: args.name,
description: args.description,
email: args.mail,
site: args.website
};
let editArgs = { ...oldData, ...newData };
if(! await LDAP_Group.edit(editArgs))
throw "LDAP edit fail";
// Modify SQL data
let ret = await knex('simplegroups').where('gid', args.forGroup).update({ frontPage: args.frontPage }, ['gid']);
if (ret.length <= 0) {
if(data.length <= 0)
await knex('groups').insert({gid: args.forGroup, type: 'simple'});
let ret = await knex('simplegroups').insert({ gid: args.forGroup, frontPage: args.frontPage }, ['gid']);
if(ret.length <= 0)
throw "SQL edit fail";
}
return this.getSimpleGroup(args.forGroup);
}
catch {
throw new ApolloError("Edit failed");
}
}
}
/**
......
......@@ -42,18 +42,22 @@ export class MessageModel {
protected cachePrivatePosts : Cache<PrivatePost, number>;
protected cachePublicPosts : Cache<PublicPost, number>;
flushMessageCache(mid: number) {
this.cachePrivatePosts.removeKey(mid);
this.cachePublicPosts.removeKey(mid);
}
/**
* @memberof GraphQL.MessageModel#
* @function getEvent
* @summary Fonction qui renvoie un evenement donné.
* @arg {number} mid - Identifiant demandé.
* @arg {number} eid - Identifiant demandé.
* @arg {boolean} load - Si load vaut false, les données ne seront pas chargées
* @return {Promise(Event)} Renvoie l'évenement dont l'identifiant est 'mid'
* @async
* @rights speaker d'un groupe author ou membre d'un groupe recipient
*/
async getEvent(mid: number, load: boolean = true): Promise<Event> {
return this.cacheEvents.get(mid, id => Event.tryCreate(id, load));
async getEvent(eid: number, load: boolean = true): Promise<Event> {
return this.cacheEvents.get(eid, id => Event.tryCreate(id, load));
}
/**
......@@ -565,7 +569,9 @@ export class MessageModel {
* @rights speaker d'un author ou d'un recipient
*/
async editMessage(mid: number, title: string, content: string): Promise<Message> {
let res = await knex("messages").where('mid', mid).update({ title: title, content: content });
await knex("messages").where('mid', mid).update({ title: title, content: content });
// NOTE : cache has to be flushed because loading the message and its author in resolver also cached the old title and content
this.flushMessageCache(mid);
return this.getMessage(mid);
}
......@@ -579,85 +585,114 @@ export class MessageModel {
* @rights speaker d'un author ou d'un recipient
*/
async removeMessage(mid: number): Promise<boolean> {
try {
let res = await knex("messages").where('mid', mid).del();
return true;
} catch (e) {
return false;
}
let nb_affected = await knex("messages").where('mid', mid).del();
return nb_affected > 0;
}
/**
* @memberof GraphQL.MessageModel#
* @function createPrivatePost
* @summary Fonction pour créer un post privé.
* @arg {string} gid - Identifiant du groupe.
* @arg {string} title - Titre.
* @arg {string} content - Contenu.
* @arg {string} uid - Identifiant de l'auteur.
* @summary Fonction pour créer un post privé. Les objets (users, groupes) doivent exister en SQL.
* @return {Promise(PrivatePost)} Renvoie le post créé.
* @async
* @rights member du groupe
*/
async createPrivatePost(gid: string, title: string, content: string, uid : string): Promise<PrivatePost> {
let res= await knex("messages_private_posts").insert({recipient : gid, author : uid, title : title, content:content}, ['mid']);
return PrivatePost.tryCreate(res);
* @rights speaker de l'auteur et si UserPost membre du recipient
*/
async createPrivatePost(fromGroup: string, toGroups: GroupSet, title: string, content: string, parent: number, forEvent: number): Promise<PrivatePost> {
let authorUser = fromGroup ? null : this.contextUser; // only set if it is a user post (no fromGroup)
// Add to messages table
let res = await knex("messages").insert({
title: title,
content: content,
authorUser: authorUser,
isPublic: false,
parent: parent,
for_event: forEvent
}, ['mid']);
let mid = res[0].mid;
// Add author group if exists
if(fromGroup) {
await knex("messages_authors").insert({mid: mid, gid: fromGroup, uid: this.contextUser});
}
// Add recipient groups
await knex("messages_recipients").insert([...toGroups].map(function(gid) { return {mid: mid, gid: gid}; }));
return this.getPrivatePost(mid, true);
}
/**
* @memberof GraphQL.MessageModel#
* @function createPublicPost
* @summary Fonction pour créer un post public.
* @arg {string} from_gid - Identifiant du groupe émetteur.
* @arg {GroupSet} to_groups - Les groupes destinataires.
* @arg {string} title - Titre.
* @arg {string} content - Contenu.
* @arg {number} event_mid - Identifiant de l'évenement.
* @return {Promise(Announcement)} Renvoie l'annonce créée.
* @async
* @rights speaker du groupe émetteur
*/
async createPublicPost(from_gid: string, to_groups: GroupSet, title: string, content: string, event_mid: number): Promise<PublicPost> {
throw "Not implemented";
* @summary Fonction pour créer un post public. Les objets doivent exister en SQL.
* @async
* @rights speaker de l'auteur
*/
async createPublicPost(fromGroup: string, toGroups: GroupSet, title: string, content: string, parent: number): Promise<PublicPost> {
let authorUser = fromGroup ? null : this.contextUser; // only set if it is a user post (no fromGroup)
// Add to messages table
let res = await knex("messages").insert({
title: title,
content: content,
authorUser: authorUser,
isPublic: true,
parent: parent
}, ['mid']);
let mid = res[0].mid;
// Add author group if exists
if (fromGroup) {
await knex("messages_authors").insert({ mid: mid, gid: fromGroup, uid: this.contextUser });
}
// Add recipient groups
await knex("messages_recipients").insert([...toGroups].map(function (gid) { return { mid: mid, gid: gid }; }));
return this.getPublicPost(mid, true);
}
/**
* @memberof GraphQL.MessageModel#
* @function createEvent
* @summary Fonction pour créer un évenement.
* @arg {string} from_gid - Identifiant du groupe émetteur.
* @arg {GroupSet} to_groups - Les groupes destinataires.
* @arg {string} title - Titre.
* @arg {string} content - Contenu.
* @arg {string} location - Lieu.
* @arg {string} startTime - Date de début.
* @arg {string} endTime - Date de fin.
* @arg {number} announcement_mid - Identifiant de l'annonce.
* @return {Promise(Event)} Renvoie l'évenement créé.
* @return {Promise(Event)} Renvoie l'évenement créé. Les objets doivent exister en SQL.
* @async
* @rights speaker du groupe émetteur
*/
async createEvent(from_gid: string, to_groups: GroupSet, title: string, content: string, location: string, startTime: string, endTime: string, announcement_mid: number): Promise<Event> {
throw "Not implemented";
async createEvent(fromGroup: string, toGroups: GroupSet, title: string, content: string, location: string, startTime: string, endTime: string): Promise<Event> {
// Add to events table
let res = await knex("events").insert({
title: title,
content: content,
location: location,
start_time: startTime,
end_time: endTime
}, ['eid']);
let eid = res[0].eid;
// Add author group
await knex("events_authors").insert({ eid: eid, gid: fromGroup, uid: this.contextUser });
// Add recipient groups
await knex("events_recipients").insert([...toGroups].map(function (gid) { return { eid: eid, gid: gid }; }));
return this.getEvent(eid, true);
}
/**
* @memberof GraphQL.MessageModel#
* @function editEvent
* @summary Fonction pour modifier un evenement.
* @arg {number} mid - Identifiant de l'évenement.
* @arg {string} title - Titre.
* @arg {string} content - Contenu.
* @arg {string} location - Lieu.
* @arg {string} startTime - Date de début.
* @arg {string} endTime - Date de fin.
* @arg {number} announcement_mid - Identifiant de l'annonce.
* @return {Promise(Event)} Renvoie l'evenement modifié.
* @async
* @rights speaker du groupe émetteur
* @rights speaker du groupe émetteur ou destinataire
*/
async editEvent(mid: number, title: string, content: string, location: string, startTime: string, endTime: string, announcement_mid: number): Promise<Event> {
throw "Not implemented";
async editEvent(eid: number, title: string, content: string, location: string, startTime: string, endTime: string): Promise<Event> {
await knex("events").where('eid', eid).update({
title: title,
content: content,
location: location,
start_time: startTime,
end_time: endTime
});
// NOTE : cache does not need to be flushed since event object was not loaded, only author and recipient gids.
return this.getEvent(eid);
}
/**
......@@ -667,15 +702,11 @@ export class MessageModel {
* @arg {number} eid - Identifiant de l'évenement.
* @return {Promise(boolean)} Renvoie true si suppression réussie.
* @async
* @rights speaker du groupe
* @rights speaker d'un groupe auteur ou destinataire
*/
async removeEvent(eid: number): Promise<boolean> {
try{
let res = await knex("events").where('eid' , eid).del();
return true;
}catch(e){
return false;
}
let nb_affected = await knex("events").where('eid', eid).del();
return nb_affected > 0;
}
}
......@@ -15,6 +15,8 @@ import { GroupCoauthorEvent } from '../object_resolvers/requests/groupCoauthorEv
import { User } from "../object_resolvers/users";
import { Group as LDAP_Group } from '../../ldap/export/group';
import knex from "../../../db/knex_router"
import { GroupCollection, GroupSet } from "../../utils/tools";
import { Cache } from "../../utils/cache";
......@@ -149,16 +151,24 @@ export class RequestModel {
/**
* @memberof GraphQL.RequestModel#
* @function userRequestJoinGroup
* @summary Fonction pour demander a devenir membre
* @summary Fonction pour demander a devenir membre. Les données doivent exister en SQL.
* @arg {string} gid - Identifiant du groupe.
* @arg {string} comment - Commentaire supplémentaire
* @return {Promise(UserJoinGroup)} Renvoie la requete créée.
* @async
* @rights viewer du groupe
* @rights viewer du groupe et connecté
*/
async userRequestJoinGroup(gid: string, comment: string): Promise<UserJoinGroup> {
let res = await knex("requests_user_join_group").insert({request_to : gid, request_from : this.contextUser, request_comment : comment}, ['rid']);
return this.getUserJoinGroupRequest(res[0]["rid"]);
let res = await knex("requests").insert({ type: "user_join_group" }, ["rid"]);
let rid = res[0].rid;
await knex("requests_user_join_group").insert({
rid: rid,
to : gid,
from : this.contextUser,
comment : comment
});
return this.getUserJoinGroupRequest(rid, true);
}
/**
......@@ -212,8 +222,12 @@ export class RequestModel {
* @rights admin du groupe destinataire
*/
async acceptUserJoinRequest(req: UserJoinGroup, comment: string): Promise<boolean> {
//"comment" a envoyer par mail automatique
throw "Not implemented";
// TODO : "comment" a envoyer par mail automatique
if(! await LDAP_Group.addMember(await req.getFrom(), await req.getTo()))
return false;
await knex('requests_user_join_group').where('rid', req.rid).del();
return true;
}
/**
......@@ -227,8 +241,9 @@ export class RequestModel {
* @rights admin du groupe destinataire
*/
async refuseUserJoinRequest(req: UserJoinGroup, comment: string): Promise<boolean> {
//"comment" a envoyer par mail automatique
throw "Not implemented";
// TODO : "comment" a envoyer par mail automatique
let nb_affected = await knex('requests_user_join_group').where('rid', req.rid).del();
return nb_affected > 0;
}
/**
......
......@@ -46,6 +46,19 @@ export class UserModel {
return this.cache.get(uid, (id) => User.tryCreate(id, load));
}
/**
* @summary Ensures the user exists in SQL database. Inserts if needed.
*/
async ensureExists(uid: string) {
let u = this.getUser(uid);
if(!u) return;
let users = await knex("users").select("uid").where("uid", uid);
if(users.length <= 0) {
await knex("users").insert({uid: uid});
}
}
/**
* @memberof GraphQL.UserModel#
* @function getMemberOf
......
......@@ -307,7 +307,7 @@ export class Event {
let authors = await context.models.message.getMessageAuthors(id);
let recipients = await context.models.message.getMessageRecipients(id);
if (authorUser == context.models.auth.getUid() || context.models.auth.isSpeakerOr(authors) || context.models.auth.isMemberOr(recipients)) {
if (authorUser == context.models.auth.getUid() || await context.models.auth.isSpeakerOr(authors) || await context.models.auth.isMemberOr(recipients)) {
res.push(post);
}
}
......
......@@ -130,7 +130,7 @@ export class PrivatePost extends Message {
let authors = await context.models.message.getMessageAuthors(parent_id);
let recipients = await context.models.message.getMessageRecipients(parent_id);
if(authorUser == context.models.auth.getUid() || context.models.auth.isMemberOr(recipients) || context.models.auth.isSpeakerOr(authors)) {
if(authorUser == context.models.auth.getUid() || await context.models.auth.isMemberOr(recipients) || await context.models.auth.isSpeakerOr(authors)) {
return post;
}
......@@ -162,7 +162,7 @@ export class PrivatePost extends Message {
let authors = await context.models.message.getMessageAuthors(id);
let recipients = await context.models.message.getMessageRecipients(id);
if (authorUser == context.models.auth.getUid() || context.models.auth.isMemberOr(recipients) || context.models.auth.isSpeakerOr(authors)) {
if (authorUser == context.models.auth.getUid() || await context.models.auth.isMemberOr(recipients) || await context.models.auth.isSpeakerOr(authors)) {
res.push(post);
}
}
......@@ -191,7 +191,7 @@ export class PrivatePost extends Message {
let authors = await context.models.message.getMessageAuthors(id);
let recipients = await context.models.message.getMessageRecipients(id);
if (authorUser == context.models.auth.getUid() || context.models.auth.isMemberOr(recipients) || context.models.auth.isSpeakerOr(authors)) {
if (authorUser == context.models.auth.getUid() || await context.models.auth.isMemberOr(recipients) || await context.models.auth.isSpeakerOr(authors)) {
res.push(post);
}
}
......@@ -214,7 +214,7 @@ export class PrivatePost extends Message {
let authors = await context.models.message.getEventAuthors(eid);
let recipients = await context.models.message.getEventRecipients(eid);
if (context.models.auth.isMemberOr(recipients) || context.models.auth.isSpeakerOr(authors)) {
if (await context.models.auth.isMemberOr(recipients) || await context.models.auth.isSpeakerOr(authors)) {
return context.models.message.getEvent(eid);
}
......
......@@ -127,7 +127,7 @@ export class PublicPost extends Message {
let authors = await context.models.message.getMessageAuthors(parent_id);
let recipients = await context.models.message.getMessageRecipients(parent_id);
if (authorUser == context.models.auth.getUid() || context.models.auth.isConnectedOrOnplatal() || context.models.auth.isSpeakerOr(authors)) {
if (authorUser == context.models.auth.getUid() || context.models.auth.isConnectedOrOnplatal() || await context.models.auth.isSpeakerOr(authors)) {
return post;
}
......@@ -159,7 +159,7 @@ export class PublicPost extends Message {
let authors = await context.models.message.getMessageAuthors(id);
let recipients = await context.models.message.getMessageRecipients(id);
if (authorUser == context.models.auth.getUid() || context.models.auth.isConnectedOrOnplatal() || context.models.auth.isSpeakerOr(authors)) {
if (authorUser == context.models.auth.getUid() || context.models.auth.isConnectedOrOnplatal() || await context.models.auth.isSpeakerOr(authors)) {
res.push(post);
}
}
......@@ -188,7 +188,7 @@ export class PublicPost extends Message {
let authors = await context.models.message.getMessageAuthors(id);
let recipients = await context.models.message.getMessageRecipients(id);
if (authorUser == context.models.auth.getUid() || context.models.auth.isConnectedOrOnplatal() || context.models.auth.isSpeakerOr(authors)) {
if (authorUser == context.models.auth.getUid() || context.models.auth.isConnectedOrOnplatal() || await context.models.auth.isSpeakerOr(authors)) {
res.push(post);
}
}
......
......@@ -133,7 +133,7 @@ export class GroupCoauthorEvent extends Request {
let authors = await context.models.message.getEventAuthors(eid);
let recipients = await context.models.message.getEventRecipients(eid);
if(context.models.auth.isSpeakerOr(authors) || context.models.auth.isMemberOr(recipients)) {
if(await context.models.auth.isSpeakerOr(authors) || await context.models.auth.isMemberOr(recipients)) {
return context.models.message.getEvent(eid, false);
}
throw new AuthenticationError("Not a speaker of author or member of recipient group");
......
......@@ -404,7 +404,7 @@ export class User {
let authors = await context.models.message.getMessageAuthors(p);
let recipients = await context.models.message.getMessageRecipients(p);
if (authorUser == context.models.auth.getUid() || context.models.auth.isConnectedOrOnplatal() || context.models.auth.isSpeakerOr(authors)) {
if (authorUser == context.models.auth.getUid() || context.models.auth.isConnectedOrOnplatal() || await context.models.auth.isSpeakerOr(authors)) {
res.push(await context.models.message.getPublicPost(p, false));
}
}
......
This diff is collapsed.
......@@ -199,6 +199,7 @@ type Mutation {
content: String
): PublicPost
createGroupPublicComment(
fromGroup: ID!,
parent: ID!,
title: String,
content: String
......
......@@ -26,5 +26,9 @@ export class Cache<A, K> {
return a;
}
}
removeKey(k: K) {
this.instances.delete(k);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment