MySQL Database table - mysql

I really need some help. I have this project and confused how to build its database
I have this general messaging.
students have year and section
I need to send a message in different types
Send to all students
Send to all students who wants to receive daily update
Send to students who are belong in specified years
Send to students who are belong in that year who wants to receive daily update
Send to students who's belong to sections
Send to students who's belong to sections and who wants to receive daily update
Send to students who's year is and section is
Send to specific students
some features
Resend notification to new students
Time of notification to end sending
now here is my structure of database
message_queue
id
type
message
isWantToReceive
date_added
type field value is json string
i save it something like this
sample value
id type Message isWantToReceive date_added
1 a:1:{s:3:"all";a:0:{}} Hi welcome! 0 2009-12-2
2 a:1:{s:6:"others";a:5:{s:7:"year";a:1:{i:0;s:11:"1";}s:10:"section";a:1:{i:0;s:7:"1";}}} Hi welcome! 0 2009-12-2
then i have a cron job sender that will query it and send message depending on the type.
My problem is when querying all the notification that been send like
get all notification that been send to year 2 or year 1 section 1
since my type field is a json. Can you help me restructure my database design on how my features work.

Well, in addition to your message_queue table you should have a table as follows:
student
id
year
section
wantsDailyUpdates
This table will allow you to keep track of all the students and which year and section they're in. As well as whether or not they want to receive daily updates.

Related

Which data can I unhesitatingly send over a GET request?

I create a VueJS application with express and sequelize to access a mysql database (currently running with XAMPP). I have a database which consist of 3 tables:
users: [id (primary key), name, email, family_id (foreign key)]
families: [id (primary key), name]
hobbies: [id (primary key), name, user_id (foreign key)]
All of these IDs are auto_increment so the first user registered gets the ID 1 and so on.
Every user within the same family (so with equal family_id) is allowed to see the hobbies of the other family members. I have a SQL query, which gives me all the family members. On my websity I have a simple drop down menu, where I can select the member. With a GET request I then want to retrieve all hobbies of the selected member.
Now I can basically decide if I use the id or the email for the request parameter e.g. /api/hobbies/:id or /api/hobbies/:email. Email reveals more private information while id reveals information about my internal strucutre like "At least (id) number of users exists.". I think it is better to use the id.
Maybe there is also the possibility to assign a random id (not auto increment) in the database? But I dont know how to to this.
Nothing you send as a parameter to a GET request is private. Those parameters are part of the URL you GET, and those URLs can be logged in various proxy servers, etc, all over the internet without your consent or your users' consent.
It seem to me that family members' hobbies can be sensitive data. What if the whole family likes, say, golf? A cybercreep could easily figure out that a good time for burglary would be Saturday afternoons.
And if your app does GET operations with autoincrementing id values, it's child's play for a cybercreep to examine any record they want. Check out the Panera Bread data breach for example. https://krebsonsecurity.com/2018/04/panerabread-com-leaks-millions-of-customer-records/
At a minimum use POST for that kind of data.
Better yet, use a good authentication / session token system on your app, and conceal data from users if they're not members of that family.
And, if you want to use REST style GET parameters, you need to do these things to be safe:
Use randomized id values. It must be very difficult for a cybercreep to guess a second value from knowing a first value. Serial numbers won't do. Neither will email addresses.
Make sure unauthenticated users can see no data.
Make sure authenticated users can only see the subset of data for which they're authorized.
My suggestion to avoid REST-style GET parameters comes from multiple security auditors saying, you must change that.

MySQL Database Schema for role based system

We are developing a platform for NGOs (N) to get their work done via Individual Volunteers (V) or Volunteers via a Company (C)
NGO
An NGO can come signup for an account and create a profile.
It creates Activities (jobs it needs help from volunteers) to which Individual Volunteers or a Company (Sub set of their Employees who are registered as Volunteers in the system) can apply.
An NGO can check the Applicants Profile and previous Work History
and accept the application. On Acceptance they become members of an
Activity.
Here While they work after regular intervals say 2weeks they need to
enter the amount of hours they have contributed towards that
particular activity.
NGO has to validate this time so that it can reflect in a Volunteers profile as credit
Company
A Company signup for a profile.
It uploads the list of all its employees in a particular formatted CSV file to add Volunteers against itself or send an invite link to to ask their employees to signup. If an Employees already exists in the system we send an email asking him to validate the company's claims
Company can search for a particular Task and apply to it by selecting all its employes or a subset of it.
While Validating time for the work done it can be done it two ways. 1 Company can centrally say V1 V2 V3 have completed 2hrs 3hrs and 2hrs and submit for validation from the NGO or allow each of its Employees handle this manually and allow them to submit it.
Where i need help?
I have created the NGO and single Volunteer relationships. I am confused as to how use the same tables but allow a new entity like Company come in between the NGO and Volunteer and manage the time validation and activity management.
The Time Validated is very important as it will be used to be shown that in the Social Equity Balance of the NGO, Company as well as Volunteers (Individual Work and also Worked for a cause through a company)
I have created the ER diagram below for the NGO and Volunteer and need to create the Company part of it.
Link: http://i.stack.imgur.com/OMY21.png
I'm not sure you need to change your schema much, or even at all. Your schema requires an application to go with it to make it do anything - you can't implement all the logic here - some/most of it will be in your application.
As I understand it, your spec says that all actual volunteer work is performed by individuals, some of whom may be associated with a Company and some aren't. Your schema captures this already.
That's pretty much all you need, I think. When you say:
While Validating time for the work done it can be done it two ways. 1 Company can centrally say V1 V2 V3 have completed 2hrs 3hrs and 2hrs and submit for validation from the NGO or allow each of its Employees handle this manually and allow them to submit it.
This is already covered - either each individual inputs their own work records or the application allows the company to do it for them - and then the NGO validates these records in the same way, regardless of who entered them.
I have created the NGO and single Volunteer relationships. I am confused as to how use the same tables but allow a new entity like Company come in between the NGO and Volunteer and manage the time validation and activity management.
Lets go through a worked example to illustrate both use cases, to make sure we've got everything covered:
Worked Examples
Individual, no company
An individual signs up, creating a row in the volunteers table. They sign-up for an activity, creating a row in the ngo_activity_applications table.
The NGO approves them, creating a row in the ngo_activity_members table - and either removing the row in the ngo_activity_applications table, or changing it's status - the spec. is unclear.
The individual does some work and logs the time in the app, creating rows in the ngo_activity_time_validations table.
The NGO validates the work done somehow, then tells the app this. This presumably changes the status of the rows in the ngo_activity_time_validations table and creates either one summary row or matching rows in the volunteer_validated_times table. Spec unclear where cost_per_hour comes from?
Company
A company signs up and uploads a CSV file with 3 volunteers in. This creates a row in the companies table, plus three rows in the volunteers table, and 3 rows in the company_volunteers linking table.
Company Volunteer 1 signs up to an activity individually and everything proceeds as above.
The Company signs up for a different activity and volunteers all 3 of it's people to work on it. This creates 3 rows in the ngo_activity_applications table.
The NGO approves all three, creating three new rows in the ngo_activity_members table - and either removing the rows in the ngo_activity_applications table, or changing their status - the spec. is unclear.
The volunteers do some work and the company logs time in the app on behalf of Company Volunteers 1 and 2 - and Company Volunteer 3 logs her own time:
Company Volunteers 1 and 2
The company uses the application to log the time on their behalf - creating 2 rows in the ngo_activity_time_validations table.
Company Volunteer 3
Company Volunteer 3 uses the application to log their own time - creating a row in the ngo_activity_time_validations table.
The NGO validates the work done somehow, then tells the app this. This presumably changes the status of the rows in the ngo_activity_time_validations table and creates either one summary row or matching rows in the volunteer_validated_times table. Spec unclear where cost_per_hour comes from?
Summary
You can see how much validated time any individual has logged by querying the volunteer_validated_times table JOINed to the volunteers table. You can also see how much validated time any Company has logged, by doing the same query but also joining on the company_volunteers table.
Possible changes & Questions:
You might want to add a company_entered flag to the ngp_activity_time_validations table, so that you can distinguish between records entered by individuals and ones entered by the company on an individuals behalf. You might also want to add the ID of the person who makes the entry in this table, if logging that is relevant to your application.
Might want to add an hourly_rate column to the volunteers table, to use as a default cost_per_hour when creating rows in the volunteer_validated_times table.

data type for emails

I have a program where the user can enter multiple email addresses to get notification. I'm creating a field in the database to keep track of this and I'm not sure what would be the best data type to choose for all the email addresses. At this point I believe we will limit it to 4 email addresses.
What data type would be appropriate here for mysql?
Not sure this is relevant but I plan to serialize the data (with php function) When processing the email addresses. Interested in any feedback on my plans and if there is a better way to do this.
This indicates that you have 1:many relation of user:email addresses. Create another table with user_id and email columns and link it up to your users table via user_id.
Never serialize data and stick it in a column, you'll regret it later.

Basic Normalization Question

This might not exactly be a "normalization" question, it's more the type of data which I am saving.
I've just done a specification for a messaging and email system . The idea is that I need to save all of the messages which are internal to my web service, but also know if an email has been sent with that message.
Here is the specification.
Specification
Any messages are stored in one table.
Messages can be from unregistered users, or registered users.
An unregistered user message will just have a return email address
A registered user message will have the user id of the sender
Messages are either owned by a User (meaning that they are the sent to) or messages are shared by user roles.
When a message is owned by a user, we record some information about this message (same table as the message).
a) Has the user opened/read the message?
b) Was an _email sent_ to the owner of the message or is it just an internal message
c) Date the message was first read
d) Date the message was sent
When a message is sent to a group of users, meaning that they are sent to "All Users", or "All Owners" or "All SuperAdmin"...
a) The message is saved once in the messages table with a sent date
b) Each individual open is tracked in a seperate table
c) A field records if a direct _email has been sent_, or if it is just saved internally in the system. (seperate table)
Messages can be threaded, this means that if a message is responded to, that it is a child or the original message.
Messages have different "Types", meaning that a message can be "System Notice", "Enquiry", "Personal Message", "Private Message", "Transactional Information"
Messages which are linked to an enquiry for a product, will save the ID of the product they are enquiring for. (ie The relevant property).
End Specification
Now the actual question...
As you can see in bullet 1)(b) I am recording for a message which is sent to an indiviual user, if an email was also sent for that message.
However, when an email is sent to a group of users, I am then recording whether an email was sent in a completely different table.
Obviously because I can't save this information in the same table.
What are your opinions on this model. I'm not duplicating any data, but I'm seperating where the data is saved. Should I just have a email_sent table to record all of this information.
It is hard to say whether your current design is good or bad. On the surface, I think that it is a mistake to separate the same piece of information into two places. It may seem easier to have a note about an individual email sent in the table which is closer to the individual and notes about emails sent to groups closer to the groups. However, your code is going to have to go looking in two places to find information about any email or about all emails in general.
If the meaning of the flag email_sent is the same for an individual user as it is for a member of a group of users, then looking in two places all the time for what is essentially one kind of information will be tedious (which in code terms comes down to being potentially slow and hard to support).
On the other hand, it may be that email_sent is something that is not important to your transactional or reporting logic and is just a mildly interesting fact that is "coming along for the ride". In this case, trying to force two different email_sent flags into one place may require an inconvenient and inadvisable mash-up of two entities that ought to be distinct because of all of their other, more important attributes.
It is difficult to give a conclusive answer without having a better understanding of your business requirement, but this is the trade-off you have to consider.
Create 3 tables:
MSG with id (key auto), msgtext, type (value U or R), userId/roleId
ROLES with roleId, userId
ACCS with userId, MsgId, date opened, read, etc
MSG records the message, with a type to see if it's from a role or unregistered user
ROLES points one role to many users
ACCS records everything, for a user, registered or not.
To retrieve, join the MSG type U with ACCS
join MSG type R with ROLES and then with ACCS
To retrieve all, UNION them

Website Transactions in MySQL Database

Good Day,
I'm currently designing database structure for a website of mine. I need community assistance in one aspect only as I never did something similar.
Website will include three types of the payments:
Internal payments (Escrow kind payments). User can send payment to another user.
Deposits. Users add fund to their accounts.
Withdrawal. User can request a withdrawal. Money will be sent to their bank/PayPal account.
Basically, I need some tips to get the best design possible.
Here's what I'm thinking about:
deposits - this table will store info about deposits
deposits_data - this table will store info about deposit transaction (ex. data returned by PayPal IPN)
payments - table to store internal payments
withdrawals - table to store info about withdrawal request
transactions - table to store info about ALL transactions (with ENUM() field called type with following values possible: internal, deposit, withdrawal)
Please note that I have already a table logs to store every user action.
Unfortunately, I feel that my design approch is not the best possible in this aspect. Can you share some ideas/tips?
PS. Can I use a name "escrow" for internal payments or should I choose different name?
Edit
DEPOSITS, PAYMENTS and WITHDRAWALS tables store specific transaction details. TRANSACTIONS table stores only limited info - it's a kind of logs table - with a details field (which contains a text to display in user log section, ex: "User 1 sent you a payment for something")/
Of course I have users tables, etc.
Can I use a name "escrow" for internal
payments or should I choose different
name?
Escrow has a specfic financial/legal meaning, which is different from how you seem to mean it: "a written agreement (or property or money) delivered to a third party or put in trust by one party to a contract to be returned after fulfillment of some condition" (source)
So choosing a different name seems like a good idea.
As for design, what data will DEPOSITS, PAYMENTS and WITHDRAWALS store which TRANSACTIONS won't? Also, you need an ACCOUNTS table. Or are you planning to just use your existing USERS table (I presume you have such a thing)? You probably ought to have something for external parties, even if you only intend to support PayPal for the time being.