Example #1
0
File: forms.py Project: DaC24/taskr
    def get(self, task_id, comment_id):

        # reconstruct comment key and pull entity from datastore
        comment_key = ndb.Key(urlsafe=comment_id)
        comment = comment_key.get()
        # pull task from datastore
        task = comment.task.get()

        if not comment.task.urlsafe() == task_id:
            return self.abort(400, detail='Task/Comment mismatch')

        # users can only delete their own comments
        if not self.user_entity.key == comment.user and not is_admin(self.user_entity):
            return self.abort(403, detail="Users can only delete their own comments")

        # delete comment entity
        comment_key.delete()
        # re-save task so as to recalculate all computed
        # fields right the way up to project level
        task.put()

        # add flash msg to indicate success
        self.session.add_flash('Comment successfully deleted')

        # redirect to task view page
        redirect_url = self.uri_for('task-view', task_id=task.key.urlsafe())
        return self.redirect(redirect_url)
Example #2
0
File: forms.py Project: DaC24/taskr
    def handle(self):

        # check if user has admin permissions
        if not is_admin(self.user_entity):
            return self.abort(401, detail="Admin permissions required")

        # populate form with POST data (if available)
        form = TaskForm(self.request.POST)

        # check if form was POSTed and that user input validates
        if self.request.method == 'POST' and form.validate():

            # create new project
            task = Task()

            # populate task from form
            form.populate_obj(task)
            # add user to project's user list and assign to self
            task.users.append(self.user_entity.key)
            task.assigned_to = self.user_entity.key
            # store task in datastore
            task.put()

            # record history item
            history_text = 'Project added'
            add_to_history(task, self.user_entity, history_text)
            self.session.add_flash(history_text)

            # redirect to task view on succesful save
            redirect_url = self.uri_for('task-view', task_id=task.key.urlsafe())
            return self.redirect(redirect_url)

        # render form and display
        context = {'form': form, 'task_or_project': 'project', 'add_or_edit': 'Add new'}
        return self.render_response('task_form.html', context)
Example #3
0
File: forms.py Project: DaC24/taskr
    def get(self, task_id, user_id):

        # reconstruct user key from url
        user_key = ndb.Key(urlsafe=user_id)
        # pull task from datastore
        task_key = ndb.Key(urlsafe=task_id)
        task = task_key.get()

        if not task.is_top_level:
            return self.abort(403, detail="Can only remove users from projects")

        if not user_key in task.users:
            return self.abort(404, detail='User not assigned to project')

        # only admin users can modify user lists
        if not is_admin(self.user_entity):
            return self.abort(403, detail="Need admin permissions")

        # delete comment entity
        task.users.remove(user_key)
        # re-save task so as to recalculate all computed
        # fields right the way up to project level
        task.put()

        # add flash msg to indicate success
        self.session.add_flash('User successfully removed from task')

        # redirect to task view page
        redirect_url = self.uri_for('task-view', task_id=task.key.urlsafe())
        return self.redirect(redirect_url)
Example #4
0
def toggle_admin():
    if is_admin():
        u_id = int(request.args.get('u_id'))
        db.set_user_admin(u_id, True if db.get_user_admin(u_id) == 0 else False)
        flash('Administrative privileges toggled.')
    else:
        flash('You must be an admin to perform this action.')
        return redirect(url_for('index'))
    return redirect(url_for('admin'))
Example #5
0
def remove_picture():
    if is_admin():
        p_id = request.args.get('p_id')
        db.remove_picture(int(p_id))
        flash('Picture removed.')
    else:
        flash('You must be an admin to perform this action.')
        return redirect(url_for('index'))
    return redirect(url_for('admin'))
Example #6
0
def remove_item():
    if is_admin():
        i_id = request.args.get('i_id')
        db.remove_item(int(i_id))
        flash('Item removed.')
    else:
        flash('You must be an admin to perform this action.')
        return redirect(url_for('index'))
    return redirect(url_for('admin'))
Example #7
0
def admin():
    if is_admin():
        me = session['u_id']
        users = db.get_users()
        items = db.get_all_items()
        pictures = db.get_all_pictures()
        return render_template('admin.html', me = me, users = users, items = items, pictures = pictures)
    else:
        flash('You must be an admin to view this page.')
        return redirect(url_for('index'))
def members():
    if is_admin():
        member_list = create_members_dictionary(client)
        length = len(member_list)
        if member_list is None:
            flash("Failed to extract member information from Firebase!")
            return redirect(url_for('error_api.error'))
        if request.method == "POST":
            stdid = request.form['reset']
            stdname = get_attribute_from_member(client, stdid, 'name')
            if stdname == -1:
                flash(
                    "Unable to get member's name. Check log for more details. Source: get_attribute_from_member"
                )
                return redirect(url_for('error_api.error'))
            change_attribute_of_member(client, stdid, "limit", 5)
            loaned_items = get_attributes_from_sub_coll(client, stdid, "id")
            x = delete_sub_coll_x(client, stdid)
            if x == -1:
                flash("Unable to delete sub collection from user {}".format(
                    stdid))
                return redirect(url_for('error_api.error'))
            if not loaned_items == -1:
                for item_id in loaned_items:
                    y = delete_sub_doc(item_id, stdid)
                    if y == -1:
                        flash("Unable to delete {}'s record in item {}".format(
                            stdid, item_id))
                        return redirect(url_for('error_api.error'))
            flash(
                "Member {} {}'s limit has been reset!".format(stdid, stdname),
                'success')
            member_list = create_members_dictionary(client)
            length = len(member_list)
            return render_template('members.html',
                                   members=member_list,
                                   length=length)
        else:
            return render_template('members.html',
                                   members=member_list,
                                   length=length)
    else:
        flash("You are unauthorized!")
        return redirect(url_for('login_api.login'))
Example #9
0
File: forms.py Project: DaC24/taskr
    def post(self, task_id):

        # check if user has admin permissions
        if not is_admin(self.user_entity):
            return self.abort(401, detail="Admin permissions required")

        # get task from datastore
        task_key = ndb.Key(urlsafe=task_id)
        task = task_key.get()

        # if this isn't a project then we can't add users to it
        if not task.is_top_level:
            return self.abort(403, detail="Cannot add a user to a subtask")

        # build form with POST data
        form = add_user_to_task_form(task, self.request.POST)

        # check if form validates
        if form.validate() and form.user.data is not None:

            # coerce form data into valid datastore data
            data = ndb.Key(urlsafe=form.user.data)
            # reassign task
            task.users.append(data)
            # store task
            task.put()

            # record history item
            history_text = 'Added user:%s to project' % data.get().given_name
            add_to_history(task, self.user_entity, history_text)
            self.session.add_flash(history_text)

        else:

            # if form doesn't validate then add a flash message before redirecting
            flash_msg = form.errors
            self.session.add_flash(flash_msg)

        # build url of task and redirect to it
        redirect_url = self.uri_for('task-view', task_id=task.key.urlsafe())
        return self.redirect(redirect_url)
Example #10
0
File: task.py Project: DaC24/taskr
    def get(self):

        @ndb.tasklet
        def get_projects_for_user_async(user_key, admin_permissions):
            # base projects query
            projects = Task.query().filter(Task.is_top_level == True)
            # filter projects if user is not an admin
            if not admin_permissions:
                projects = projects.filter(Task.users == user_key)
            # sort projects by creation date
            projects = projects.order(Task.creation_time)
            project_list = yield projects.map_async(lambda x: x.key)
            raise ndb.Return(project_list)

        # run async query to get projects
        admin_permissions = is_admin(self.user_entity)
        user_key = self.user_entity.key
        projects = get_projects_for_user_async(user_key, admin_permissions)
        # add projects to the template context
        context = {'projects': ndb.get_multi_async(projects.get_result())}
        # render and return login page
        return self.render_response('projects.html', context)
Example #11
0
File: forms.py Project: DaC24/taskr
    def handle(self, task_id):

        # pull project from datastore or issue 404
        task = ndb.Key(urlsafe=task_id).get()
        if task is None:
            return self.abort(404, 'Project not found')

        # check if user has admin permissions
        if task.is_top_level:
            if not is_admin(self.user_entity):
                return self.abort(401, detail="Admin permissions required")
            task_or_project = 'project'
        else:
            task_or_project = 'task'

        # populate form with POST data (if available)
        form = TaskForm(self.request.POST, task)

        # check if form was POSTed and that user input validates
        if self.request.method == 'POST' and form.validate():

            # populate task from form
            form.populate_obj(task)
            # store task in datastore
            task.put()

            # record history item
            history_text = '%s edited' % task_or_project.capitalize()
            add_to_history(task, self.user_entity, history_text)
            self.session.add_flash(history_text)

            # redirect to task view on succesful save
            redirect_url = self.uri_for('task-view', task_id=task.key.urlsafe())
            return self.redirect(redirect_url)

        # render form and display
        context = {'form': form, 'task_or_project': task_or_project, 'add_or_edit': 'Editing'}
        return self.render_response('task_form.html', context)
def member_info(student_id):
    if is_admin():
        info = get_loaning_status(client, student_id)
        name = get_attribute_from_member(client, student_id, 'name')

        has_expired = False
        expiry_dates = get_attributes_from_sub_coll(client, student_id,
                                                    "expiry")
        now = datetime.datetime.now()

        for date in expiry_dates:
            if datetime.datetime.timestamp(now) > datetime.datetime.timestamp(
                    date):
                has_expired = True
                break

        if request.method == "POST":

            try:
                remind_btn = request.form['remind']
            except:
                remind_btn = None

            try:
                return_one = request.form['return_one']
            except:
                return_one = None

            try:
                return_all = request.form['return_all']
            except:
                return_all = None

            if remind_btn is not None:

                expired_items_str = ""
                student_email = get_attribute_from_member(
                    client, student_id, "email")
                loaned_items = get_loaning_status(client, student_id)
                now = datetime.datetime.now()
                for item in loaned_items:
                    expiry = item['expiry']
                    if datetime.datetime.timestamp(
                            now) > datetime.datetime.timestamp(expiry):
                        expired_items_str += "Item: {} , Item ID: {} , Expiry Date: {}\n".format(
                            item['name'], item['id'], expiry)

                reminder_email = '''
                Dear {},
                
                You have expired item(s) that have yet to be returned!
                Please return them ASAP otherwise you will not be able to loan any more item.
                
                Your expire item is/are:
                
                {}
                
                Please make an arrangement with any of the exco members via Telegram or Email to return your item.
                
                Thank you for your understanding!
                
                IEEE SUTD Student Branch
                IEEE Web Development Team
                
                [This is an auto-generated email. Please do not reply.]
                '''.format(name, expired_items_str)
                send_email(reminder_email.encode('utf-8'), student_email)
                flash(
                    "Reminder email has been successfully sent to {}".format(
                        name), 'success')
                return render_template('member_info.html',
                                       info=info,
                                       name=name,
                                       expired=has_expired)

            elif return_one is not None:
                item_id = return_one
                old_quantity = get_attr_from_sub_doc_x(client, student_id,
                                                       item_id, "quantity")
                new_quantity = old_quantity - 1
                old_limit = get_attribute_from_member(client, student_id,
                                                      "limit")
                if new_quantity == 0:
                    a = delete_sub_doc(item_id, student_id)
                    b = delete_sub_coll_doc(client, student_id, item_id)
                    if a == -1 or b == -1:
                        flash(
                            "Unable to update sub collection loaned item quantity!"
                        )
                        return redirect(url_for('error_api.error'))
                else:
                    old_quantity_from_inventory = get_sub_attr_from_member(
                        item_id, student_id, "quantity")
                    new_quantity_from_inventory = old_quantity_from_inventory - 1
                    status = update_sub_coll_attribute(client, student_id,
                                                       item_id, "quantity",
                                                       new_quantity)
                    status_inventory = update_attr_sub_coll(
                        item_id, student_id, "quantity",
                        new_quantity_from_inventory)
                    if status == -1 or status_inventory == -1:
                        flash(
                            "Unable to update sub collection loaned item quantity!"
                        )
                        return redirect(url_for('error_api.error'))
                new_limit = old_limit + 1
                limit_update = change_attribute_of_member(
                    client, student_id, "limit", new_limit)
                if limit_update == -1:
                    flash("Failed to update member's limit.")
                    return redirect(url_for('error_api.error'))
                old_quantity_inventory = get_attribute_value(
                    item_id, "quantity")
                new_quantity_inventory = old_quantity_inventory + 1
                status_update = update_attribute_value(item_id, "quantity",
                                                       new_quantity_inventory)
                if status_update == -1:
                    flash(
                        "Failed to update quantity in the main inventory system."
                    )
                    return redirect(url_for('error_api.error'))
                info = get_loaning_status(client, student_id)
                return render_template('member_info.html',
                                       info=info,
                                       name=name,
                                       expired=has_expired)

            elif return_all is not None:
                item_id = return_all
                old_limit = get_attribute_from_member(client, student_id,
                                                      "limit")
                old_loaned_quantity = get_attr_from_sub_doc_x(
                    client, student_id, item_id, "quantity")
                old_quantity_inventory = get_attribute_value(
                    item_id, "quantity")
                new_quantity_inventory = old_quantity_inventory + old_loaned_quantity
                new_limit = old_limit + old_loaned_quantity
                limit_update = change_attribute_of_member(
                    client, student_id, "limit", new_limit)
                if limit_update == -1:
                    flash("Failed to update member's limit.")
                    return redirect(url_for('error_api.error'))
                status_update = update_attribute_value(item_id, "quantity",
                                                       new_quantity_inventory)
                status_delete = delete_sub_coll_doc(client, student_id,
                                                    item_id)
                status_delete_inventory = delete_sub_doc(item_id, student_id)
                if status_update == -1 or status_delete == -1 or status_delete_inventory == -1:
                    flash(
                        "Failed to update quantity in the main inventory system."
                    )
                    return redirect(url_for('error_api.error'))
                info = get_loaning_status(client, student_id)
                return render_template('member_info.html',
                                       info=info,
                                       name=name,
                                       expired=has_expired)
        else:
            return render_template('member_info.html',
                                   info=info,
                                   name=name,
                                   expired=has_expired)

    else:
        flash("You are unauthorized!")
        return redirect(url_for('login_api.login'))
def inventory():
    inventory = create_inventory_dictionary()
    if is_admin():
        if request.method == 'POST':
            try:
                selection = request.form['inventory-option']
            except:
                selection = None

            if selection == 'add':
                try:
                    name = request.form['inventory-name']
                except:
                    flash("Fields empty! Unable to add new entry.", 'warn')
                    return render_template('inventory.html',
                                           inventory=inventory)
                try:
                    quantity = request.form['inventory-quantity']
                    if isinstance(quantity, float):
                        flash("Quantity must be an integer!", 'warn')
                        return render_template('inventory.html',
                                               inventory=inventory)
                    if quantity == "":
                        flash("Fields empty! Unable to add new entry.", 'warn')
                        return render_template('inventory.html',
                                               inventory=inventory)
                except:
                    flash("Fields empty! Unable to add new entry.", 'warn')
                    return render_template('inventory.html',
                                           inventory=inventory)
                try:
                    type = request.form['inventory-type']
                    if type == "":
                        flash("Fields empty! Unable to add new entry.", 'warn')
                        return render_template('inventory.html',
                                               inventory=inventory)
                except:
                    flash("Fields empty! Unable to add new entry.", 'warn')
                    return render_template('inventory.html',
                                           inventory=inventory)

                try:
                    info = request.form['info']
                except:
                    info = ""

                try:
                    loanable = request.form['inventory-loanable']
                    loanable = True if loanable == "on" else False
                except:
                    loanable = False

                last_id = decode_id(inventory_attr_to_list("id")[-1])
                next_id = generate_id(last_id + 1)

                new_entry = {
                    'id': next_id,
                    'name': name,
                    'type': type,
                    'quantity': quantity,
                    'info': info,
                    'is_allow': loanable
                }

                try:
                    create_new_entry(next_id, new_entry)
                except Exception as e:
                    flash("Failed to create new entry! {}".format(e))
                    return redirect(url_for('error_api.error'))

                flash("New entry successfully created. ID: {}".format(next_id),
                      'success')
                inventory = create_inventory_dictionary()
                return render_template('inventory.html', inventory=inventory)

            elif selection == 'update':
                try:
                    _id = request.form['update-selection']
                    if _id == "":
                        flash("Fields empty! Unable to add new entry.", 'warn')
                        return render_template('inventory.html',
                                               inventory=inventory)
                except:
                    flash("Please select an item first in order to update! ",
                          'warn')
                    return render_template('inventory.html',
                                           inventory=inventory)
                try:
                    quantity = request.form['update-quantity']
                    if isinstance(quantity, float):
                        flash("Quantity must be an integer!", 'warn')
                        return render_template('inventory.html',
                                               inventory=inventory)
                    if quantity == "":
                        quantity = "unchanged"
                except:
                    quantity = "unchanged"
                try:
                    info = request.form['info2']
                    if info == "":
                        info = "unchanged"
                except:
                    info = "unchanged"
                try:
                    loanable = request.form['update-loanable']
                    loanable = True if loanable == "on" else False
                except:
                    loanable = False

                if info != "unchanged":
                    status = update_attribute_value(_id, 'info', info)
                    if status == -1:
                        return render_template('inventory.html',
                                               inventory=inventory)

                if quantity != 'unchanged':
                    status = update_attribute_value(_id, 'quantity',
                                                    int(quantity))
                    if status == -1:
                        return render_template('inventory.html',
                                               inventory=inventory)
                if loanable != 'unchanged':
                    status = update_attribute_value(_id, 'is_allow', loanable)
                    if status == -1:
                        return render_template('inventory.html',
                                               inventory=inventory)

                flash("Item successfully updated. ID: {}".format(_id),
                      'success')
                inventory = create_inventory_dictionary()
                return render_template('inventory.html', inventory=inventory)

            elif selection == "view":
                try:
                    _id = request.form['view-inventory']
                    if _id == "":
                        flash("Fields empty! Unable to add new entry.", 'warn')
                        return render_template('inventory.html',
                                               inventory=inventory)
                except:
                    flash("Please select an item first in order to update! ",
                          'warn')
                    return render_template('inventory.html',
                                           inventory=inventory)

                return redirect(
                    url_for('admin_api.inventory_info', item_id=_id))

            else:
                flash("Invalid selection!", 'warn')
                return render_template('inventory.html', inventory=inventory)
        else:
            return render_template('inventory.html', inventory=inventory)
    else:
        flash("You are unauthorized!")
        return redirect(url_for('login_api.login'))
def index():
    if is_admin():
        return render_template('index.html')
    else:
        flash("You are unauthorized!")
        return redirect(url_for('login_api.login'))
Example #15
0
def loan():
    logged_in = is_login()
    admin = is_admin()
    if logged_in:
        inventory = create_inventory_dictionary()
        session_name = session['name']
        student_id = session['id']

        if request.method == "POST":
            try:
                picked_id = request.form['select']
            except Exception as e:
                print("No selection is done!", e)
                flash("You have yet to select anything!")
                return render_template('loan.html',
                                       name=session_name,
                                       inventory=inventory,
                                       id=student_id,
                                       admin=admin)

            quantity = get_attribute_value(picked_id, "quantity")
            item_name = get_attribute_value(picked_id, "name")
            limits = get_attribute_from_member(client, student_id, "limit")
            expiry_dates = get_attributes_from_sub_coll(
                client, student_id, "expiry")
            now = datetime.datetime.now()

            for date in expiry_dates:
                if datetime.datetime.timestamp(
                        now) > datetime.datetime.timestamp(date):
                    flash(
                        "You have expired item(s). Please check your loan record and return the expired item before making a new loan!"
                    )
                    return redirect(url_for('confirm_api.confirm'))

            if limits == 0:
                flash(
                    "You have already loaned 5 items! You can't loan until you return them."
                )
                return redirect(url_for('confirm_api.confirm'))

            if quantity == 0:
                flash(
                    "You selected an item which is run out. Please select other items we have."
                )
                return redirect(url_for('confirm_api.confirm'))

            update_attribute_value(picked_id, "quantity", quantity - 1)
            change_attribute_of_member(client, student_id, "limit", limits - 1)

            # for inventory side
            is_exist = check_sub_doc_exist(picked_id, student_id)
            if is_exist:
                number = get_sub_attr_from_member(picked_id, student_id,
                                                  "quantity")
                if number == -1:
                    number = 0
            else:
                number = 0

            # for member side
            x_is_exist = check_sub_doc_exist_x(client, student_id, picked_id)
            if x_is_exist:
                x_number = get_attr_from_sub_doc_x(client, student_id,
                                                   picked_id, "quantity")
                if x_number == -1:
                    x_number = 0
            else:
                x_number = 0

            expiry = now + datetime.timedelta(days=30)

            student_email = get_attribute_from_member(client, student_id,
                                                      "email")
            std_name = get_attribute_from_member(client, student_id, "name")

            sub_object = {
                "student": student_id,
                "name": std_name,
                "email": student_email,
                "quantity": number + 1,
                "expiry": expiry
            }
            sub_object_2 = {
                "id": picked_id,
                "name": item_name,
                "quantity": x_number + 1,
                "expiry": expiry
            }
            inventory_updated = create_sub_collection(picked_id, "loaners",
                                                      student_id, sub_object)
            member_updated = create_sub_collection_member(
                client, student_id, "loaned_items", picked_id, sub_object_2)

            if inventory_updated == -1 or member_updated == -1:
                flash("Can't create sub collection!")
                return redirect(url_for('error_api.error'))

            new_quantity = get_attribute_value(picked_id, "quantity")
            new_limit = get_attribute_from_member(client, student_id, "limit")

            student_name = get_attribute_from_member(client, student_id,
                                                     "name")
            student_email = get_attribute_from_member(client, student_id,
                                                      "email")

            master_email = '''
            [Inventory System Update]
            --Item: {}
            --Item ID: {}
            --Quantity left: {}
            
            was loaned out successfully
            by
            
            --Student ID: {}
            --Studnet name: {}
            --Remaining loans: {}
            
            Item expiry date is set to be:
            {}
            '''.format(item_name, picked_id, new_quantity, student_id,
                       student_name, new_limit,
                       datetime.datetime.strftime(now, "%Y-%m-%d %H:%M:%S"))

            loaner_email = '''
            Thank you for using IEEE SUTD Student Branch online inventory loaning system.
            Here is a summary for your loaning status.
            
            --Loaned Item: {}
            --Item ID: {}
            --Expiry date: {}
            
            Please make an arrangement with any of the exco members via Telegram or Email to collect your item.
            
            For further query, please contact us at [email protected]
            Please remember to return your item before the expiry date.
            Thank you for your understanding!
            
            IEEE SUTD Student Branch
            IEEE Web Development Team
            
            [This is an auto-generated email. Please do not reply.]
            '''.format(item_name, picked_id,
                       datetime.datetime.strftime(now, "%Y-%m-%d %H:%M:%S"))

            send_email(master_email.encode('utf-8'), "*****@*****.**")
            sleep(1)
            send_email(loaner_email.encode('utf-8'), student_email)

            flash_message = "You picked {}. " \
                            "Now left {}. " \
                            "Remaining number of items you can loan: {}. " \
                            "Check your loaned item here".format(item_name, new_quantity, new_limit)
            flash(flash_message)
            return redirect(url_for('confirm_api.confirm'))
        else:
            return render_template('loan.html',
                                   name=session_name,
                                   inventory=inventory,
                                   id=student_id,
                                   admin=admin)
    else:
        flash("Please login first!")
        return redirect(url_for('login_api.login'))